# Record Sharing URL: /docs/web/components/record-sharing Record Sharing component. **Demo:** ```tsx 'use client'; import { useCallback, useState } from 'react'; import { RecordSharingButton, type SharedEntity, type SharingSearchResult, SharingPermissionPreset } from '@docyrus/ui/components/record-sharing'; const MOCK_USERS: SharingSearchResult[] = [ { id: 'u1', name: 'Alice Johnson', description: 'alice@company.com', type: 'user', initials: 'AJ' }, { id: 'u2', name: 'Bob Smith', description: 'bob@company.com', type: 'user', initials: 'BS' }, { id: 'u3', name: 'Carol Williams', description: 'carol@company.com', type: 'user', initials: 'CW' }, { id: 't1', name: 'Engineering', description: '12 members', type: 'team', initials: 'EN' }, { id: 'r1', name: 'Admin', description: 'Full system access', type: 'role', initials: 'AD' } ]; const INITIAL_SHARED: SharedEntity[] = [ { id: 'u1', name: 'Alice Johnson', description: 'alice@company.com', type: 'user', initials: 'AJ', avatarUrl: null, permission: SharingPermissionPreset.FULL_ACCESS }, { id: 't1', name: 'Engineering', description: '12 members', type: 'team', initials: 'EN', permission: SharingPermissionPreset.CAN_VIEW } ]; export function RecordSharingDemo() { const [sharedEntities, setSharedEntities] = useState(INITIAL_SHARED); const onSearch = useCallback(async (query: string): Promise => { await new Promise(r => setTimeout(r, 300)); const q = query.toLowerCase(); return MOCK_USERS.filter(u => u.name.toLowerCase().includes(q)); }, []); const onAdd = useCallback((entities: Array<{ id: string; type: string; permission: number }>) => { setSharedEntities((prev) => { const newEntities = entities .filter(e => !prev.some(p => p.id === e.id)) .map((e) => { const found = MOCK_USERS.find(u => u.id === e.id); return { id: e.id, name: found?.name ?? 'Unknown', description: found?.description, type: e.type as SharedEntity['type'], initials: found?.initials, avatarUrl: null, permission: e.permission }; }); return [...prev, ...newEntities]; }); }, []); const onPermissionChange = useCallback((entityId: string, permission: number) => { setSharedEntities(prev => prev.map(e => (e.id === entityId ? { ...e, permission } : e))); }, []); const onRemove = useCallback((entityId: string) => { setSharedEntities(prev => prev.filter(e => e.id !== entityId)); }, []); return (
); } ``` ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/ui-record-sharing ``` **Dependencies:** - [lucide-react](https://www.npmjs.com/package/lucide-react) - [class-variance-authority](https://www.npmjs.com/package/class-variance-authority) ## Usage ```tsx import { RecordSharingButton } from "@docyrus/ui/components/record-sharing"; import type { RecordSharingButtonProps, RecordSharingPanelProps, RecordSharingItemProps, SharedEntity, SharingSearchResult, SharingResourceType, SharingPermissionValue, SharingPermissionPresetValue, PermissionPresetOption } from "@docyrus/ui/components/record-sharing"; ``` ## API Reference | Component | Prop | Type | Default | |-----------|------|------|---------| | `RecordSharing` | `className` | `string` | — | ## Components | Component | Description | |-----------|-------------| | `RecordSharingButton` | Public export | | `RecordSharingItem` | Internal — `record-sharing-item.tsx` | | `RecordSharingPanel` | Internal — `record-sharing-panel.tsx` | ## Type Exports | Type | Description | |------|-------------| | `RecordSharingButtonProps` | — | | `RecordSharingPanelProps` | — | | `RecordSharingItemProps` | — | | `SharedEntity` | — | | `SharingSearchResult` | — | | `SharingResourceType` | — | | `SharingPermissionValue` | — | | `SharingPermissionPresetValue` | — | | `PermissionPresetOption` | — | ## Type Reference ### RecordSharingButtonProps | Field | Type | Description | |-------|------|-------------| | `ref` | `Ref` | — | | `variant` | `'button' \| 'avatar-group'` | — | | `maxAvatars` | `number` | — | | `size` | `'sm' \| 'default' \| 'lg'` | — | | `align` | `'start' \| 'center' \| 'end'` | — | | `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | — | | `open` | `boolean` | — | | `onOpenChange` | `(open: boolean) => void` | — | | `disabled` | `boolean` | — | | `triggerClassName` | `string` | — | ### RecordSharingPanelProps | Field | Type | Description | |-------|------|-------------| | `sharedEntities` | `SharedEntity[]` | — | | `resources` | `SharingResourceType[]` | — | | `permissionPresets` | `PermissionPresetOption[]` | — | | `defaultPermission` | `number` | — | | `onSearch` | `(query: string) => Promise \| SharingSearchResult[]` | — | | `onAdd` | `(entities: Array<{ id: string; type: SharingResourceType; permission: number }>) => void \| Promise` | — | | `onPermissionChange` | `(entityId: string, permission: number) => void \| Promise` | — | | `onRemove` | `(entityId: string) => void \| Promise` | — | | `isLoading` | `boolean` | — | | `isSearching` | `boolean` | — | | `isAddPending` | `boolean` | — | | `pendingPermissionChanges` | `Record` | — | | `pendingRemovals` | `Record` | — | | `title` | `string` | — | | `maxHeight` | `number \| string` | — | | `className` | `string` | — | ### RecordSharingItemProps | Field | Type | Description | |-------|------|-------------| | `entity` | `SharedEntity` | — | | `permissionPresets` | `PermissionPresetOption[]` | — | | `onPermissionChange` | `(entityId: string, permission: number) => void \| Promise` | — | | `onRemove` | `(entityId: string) => void \| Promise` | — | | `isPermissionChangePending` | `boolean` | — | | `isRemovePending` | `boolean` | — | ### SharedEntity | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `name` | `string` | — | | `description` | `string` | — | | `type` | `SharingResourceType` | — | | `avatarUrl` | `string \| null` | — | | `initials` | `string` | — | | `permission` | `number` | — | ### SharingSearchResult | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `name` | `string` | — | | `description` | `string` | — | | `type` | `SharingResourceType` | — | | `avatarUrl` | `string \| null` | — | | `initials` | `string` | — | ### SharingResourceType `"user"` | `"team"` | `"role"` | `"tenant"` | `"public"` ### PermissionPresetOption | Field | Type | Description | |-------|------|-------------| | `label` | `string` | — | | `value` | `number` | — | | `description` | `string` | — |