@miethe/ui 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/README.md +1536 -0
- package/dist/bulk-actions/Button.d.ts +28 -0
- package/dist/bulk-actions/Button.d.ts.map +1 -0
- package/dist/bulk-actions/Button.js +45 -0
- package/dist/bulk-actions/Button.js.map +1 -0
- package/dist/bulk-actions/bulk-action-bar.d.ts +91 -0
- package/dist/bulk-actions/bulk-action-bar.d.ts.map +1 -0
- package/dist/bulk-actions/bulk-action-bar.js +94 -0
- package/dist/bulk-actions/bulk-action-bar.js.map +1 -0
- package/dist/bulk-actions/index.d.ts +5 -0
- package/dist/bulk-actions/index.d.ts.map +1 -0
- package/dist/bulk-actions/index.js +7 -0
- package/dist/bulk-actions/index.js.map +1 -0
- package/dist/bulk-actions/utils.d.ts +6 -0
- package/dist/bulk-actions/utils.d.ts.map +1 -0
- package/dist/bulk-actions/utils.js +9 -0
- package/dist/bulk-actions/utils.js.map +1 -0
- package/dist/components/ui/alert.d.ts +9 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/alert.js +23 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/button.d.ts +12 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +34 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +7 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +4 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +7 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/content-viewer/ContentPane.d.ts +107 -0
- package/dist/content-viewer/ContentPane.d.ts.map +1 -0
- package/dist/content-viewer/ContentPane.js +247 -0
- package/dist/content-viewer/ContentPane.js.map +1 -0
- package/dist/content-viewer/ContentViewerProvider.d.ts +83 -0
- package/dist/content-viewer/ContentViewerProvider.d.ts.map +1 -0
- package/dist/content-viewer/ContentViewerProvider.js +92 -0
- package/dist/content-viewer/ContentViewerProvider.js.map +1 -0
- package/dist/content-viewer/FileTree.d.ts +71 -0
- package/dist/content-viewer/FileTree.d.ts.map +1 -0
- package/dist/content-viewer/FileTree.js +294 -0
- package/dist/content-viewer/FileTree.js.map +1 -0
- package/dist/content-viewer/adapters.d.ts +101 -0
- package/dist/content-viewer/adapters.d.ts.map +1 -0
- package/dist/content-viewer/adapters.js +32 -0
- package/dist/content-viewer/adapters.js.map +1 -0
- package/dist/content-viewer/index.d.ts +8 -0
- package/dist/content-viewer/index.d.ts.map +1 -0
- package/dist/content-viewer/index.js +5 -0
- package/dist/content-viewer/index.js.map +1 -0
- package/dist/diff/DiffViewer.d.ts +112 -0
- package/dist/diff/DiffViewer.d.ts.map +1 -0
- package/dist/diff/DiffViewer.js +414 -0
- package/dist/diff/DiffViewer.js.map +1 -0
- package/dist/diff/diff.d.ts +32 -0
- package/dist/diff/diff.d.ts.map +1 -0
- package/dist/diff/diff.js +8 -0
- package/dist/diff/diff.js.map +1 -0
- package/dist/diff/index.d.ts +4 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +3 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/display/FilePreviewPane.d.ts +31 -0
- package/dist/display/FilePreviewPane.d.ts.map +1 -0
- package/dist/display/FilePreviewPane.js +144 -0
- package/dist/display/FilePreviewPane.js.map +1 -0
- package/dist/display/FrontmatterDisplay.d.ts +33 -0
- package/dist/display/FrontmatterDisplay.d.ts.map +1 -0
- package/dist/display/FrontmatterDisplay.js +79 -0
- package/dist/display/FrontmatterDisplay.js.map +1 -0
- package/dist/display/index.d.ts +5 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +4 -0
- package/dist/display/index.js.map +1 -0
- package/dist/editor/MarkdownEditor.d.ts +28 -0
- package/dist/editor/MarkdownEditor.d.ts.map +1 -0
- package/dist/editor/MarkdownEditor.js +160 -0
- package/dist/editor/MarkdownEditor.js.map +1 -0
- package/dist/editor/SplitPreview.d.ts +28 -0
- package/dist/editor/SplitPreview.d.ts.map +1 -0
- package/dist/editor/SplitPreview.js +34 -0
- package/dist/editor/SplitPreview.js.map +1 -0
- package/dist/editor/index.d.ts +5 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +4 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/filters/filters-dropdown.d.ts +24 -0
- package/dist/filters/filters-dropdown.d.ts.map +1 -0
- package/dist/filters/filters-dropdown.js +36 -0
- package/dist/filters/filters-dropdown.js.map +1 -0
- package/dist/filters/index.d.ts +9 -0
- package/dist/filters/index.d.ts.map +1 -0
- package/dist/filters/index.js +5 -0
- package/dist/filters/index.js.map +1 -0
- package/dist/filters/sort-dropdown.d.ts +13 -0
- package/dist/filters/sort-dropdown.d.ts.map +1 -0
- package/dist/filters/sort-dropdown.js +20 -0
- package/dist/filters/sort-dropdown.js.map +1 -0
- package/dist/filters/tag-filter-popover.d.ts +39 -0
- package/dist/filters/tag-filter-popover.d.ts.map +1 -0
- package/dist/filters/tag-filter-popover.js +72 -0
- package/dist/filters/tag-filter-popover.js.map +1 -0
- package/dist/filters/tool-filter-popover.d.ts +42 -0
- package/dist/filters/tool-filter-popover.d.ts.map +1 -0
- package/dist/filters/tool-filter-popover.js +67 -0
- package/dist/filters/tool-filter-popover.js.map +1 -0
- package/dist/hooks/use-debounce.d.ts +9 -0
- package/dist/hooks/use-debounce.d.ts.map +1 -0
- package/dist/hooks/use-debounce.js +21 -0
- package/dist/hooks/use-debounce.js.map +1 -0
- package/dist/hooks/use-intersection-observer.d.ts +11 -0
- package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
- package/dist/hooks/use-intersection-observer.js +25 -0
- package/dist/hooks/use-intersection-observer.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pickers/EntityPickerDialog.d.ts +233 -0
- package/dist/pickers/EntityPickerDialog.d.ts.map +1 -0
- package/dist/pickers/EntityPickerDialog.js +355 -0
- package/dist/pickers/EntityPickerDialog.js.map +1 -0
- package/dist/pickers/EntityPickerViewToggle.d.ts +8 -0
- package/dist/pickers/EntityPickerViewToggle.d.ts.map +1 -0
- package/dist/pickers/EntityPickerViewToggle.js +17 -0
- package/dist/pickers/EntityPickerViewToggle.js.map +1 -0
- package/dist/pickers/index.d.ts +5 -0
- package/dist/pickers/index.d.ts.map +1 -0
- package/dist/pickers/index.js +3 -0
- package/dist/pickers/index.js.map +1 -0
- package/dist/primitives/Badge.d.ts +16 -0
- package/dist/primitives/Badge.d.ts.map +1 -0
- package/dist/primitives/Badge.js +43 -0
- package/dist/primitives/Badge.js.map +1 -0
- package/dist/primitives/BaseArtifactModal.d.ts +114 -0
- package/dist/primitives/BaseArtifactModal.d.ts.map +1 -0
- package/dist/primitives/BaseArtifactModal.js +76 -0
- package/dist/primitives/BaseArtifactModal.js.map +1 -0
- package/dist/primitives/Dialog.d.ts +20 -0
- package/dist/primitives/Dialog.d.ts.map +1 -0
- package/dist/primitives/Dialog.js +24 -0
- package/dist/primitives/Dialog.js.map +1 -0
- package/dist/primitives/DropdownMenu.d.ts +28 -0
- package/dist/primitives/DropdownMenu.d.ts.map +1 -0
- package/dist/primitives/DropdownMenu.js +34 -0
- package/dist/primitives/DropdownMenu.js.map +1 -0
- package/dist/primitives/EnterpriseOwnerBadge.d.ts +9 -0
- package/dist/primitives/EnterpriseOwnerBadge.d.ts.map +1 -0
- package/dist/primitives/EnterpriseOwnerBadge.js +12 -0
- package/dist/primitives/EnterpriseOwnerBadge.js.map +1 -0
- package/dist/primitives/GroupedSelect.d.ts +30 -0
- package/dist/primitives/GroupedSelect.d.ts.map +1 -0
- package/dist/primitives/GroupedSelect.js +47 -0
- package/dist/primitives/GroupedSelect.js.map +1 -0
- package/dist/primitives/Input.d.ts +6 -0
- package/dist/primitives/Input.d.ts.map +1 -0
- package/dist/primitives/Input.js +9 -0
- package/dist/primitives/Input.js.map +1 -0
- package/dist/primitives/LockIcon.d.ts +11 -0
- package/dist/primitives/LockIcon.d.ts.map +1 -0
- package/dist/primitives/LockIcon.js +15 -0
- package/dist/primitives/LockIcon.js.map +1 -0
- package/dist/primitives/MaskedSecretInput.d.ts +16 -0
- package/dist/primitives/MaskedSecretInput.d.ts.map +1 -0
- package/dist/primitives/MaskedSecretInput.js +42 -0
- package/dist/primitives/MaskedSecretInput.js.map +1 -0
- package/dist/primitives/ModalHeader.d.ts +66 -0
- package/dist/primitives/ModalHeader.d.ts.map +1 -0
- package/dist/primitives/ModalHeader.js +58 -0
- package/dist/primitives/ModalHeader.js.map +1 -0
- package/dist/primitives/Popover.d.ts +9 -0
- package/dist/primitives/Popover.d.ts.map +1 -0
- package/dist/primitives/Popover.js +13 -0
- package/dist/primitives/Popover.js.map +1 -0
- package/dist/primitives/ScrollArea.d.ts +6 -0
- package/dist/primitives/ScrollArea.d.ts.map +1 -0
- package/dist/primitives/ScrollArea.js +11 -0
- package/dist/primitives/ScrollArea.js.map +1 -0
- package/dist/primitives/SearchableCombobox.d.ts +30 -0
- package/dist/primitives/SearchableCombobox.d.ts.map +1 -0
- package/dist/primitives/SearchableCombobox.js +124 -0
- package/dist/primitives/SearchableCombobox.js.map +1 -0
- package/dist/primitives/SearchablePickerDialog.d.ts +20 -0
- package/dist/primitives/SearchablePickerDialog.d.ts.map +1 -0
- package/dist/primitives/SearchablePickerDialog.js +78 -0
- package/dist/primitives/SearchablePickerDialog.js.map +1 -0
- package/dist/primitives/StatusBadge.d.ts +21 -0
- package/dist/primitives/StatusBadge.d.ts.map +1 -0
- package/dist/primitives/StatusBadge.js +25 -0
- package/dist/primitives/StatusBadge.js.map +1 -0
- package/dist/primitives/TabNavigation.d.ts +68 -0
- package/dist/primitives/TabNavigation.d.ts.map +1 -0
- package/dist/primitives/TabNavigation.js +74 -0
- package/dist/primitives/TabNavigation.js.map +1 -0
- package/dist/primitives/Tabs.d.ts +8 -0
- package/dist/primitives/Tabs.d.ts.map +1 -0
- package/dist/primitives/Tabs.js +14 -0
- package/dist/primitives/Tabs.js.map +1 -0
- package/dist/primitives/Tooltip.d.ts +8 -0
- package/dist/primitives/Tooltip.d.ts.map +1 -0
- package/dist/primitives/Tooltip.js +12 -0
- package/dist/primitives/Tooltip.js.map +1 -0
- package/dist/primitives/VerticalTabNavigation.d.ts +75 -0
- package/dist/primitives/VerticalTabNavigation.d.ts.map +1 -0
- package/dist/primitives/VerticalTabNavigation.js +166 -0
- package/dist/primitives/VerticalTabNavigation.js.map +1 -0
- package/dist/primitives/ViewModeToggle.d.ts +12 -0
- package/dist/primitives/ViewModeToggle.d.ts.map +1 -0
- package/dist/primitives/ViewModeToggle.js +56 -0
- package/dist/primitives/ViewModeToggle.js.map +1 -0
- package/dist/primitives/WizardShell.d.ts +81 -0
- package/dist/primitives/WizardShell.d.ts.map +1 -0
- package/dist/primitives/WizardShell.js +73 -0
- package/dist/primitives/WizardShell.js.map +1 -0
- package/dist/primitives/index.d.ts +38 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +24 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/utils.d.ts +6 -0
- package/dist/primitives/utils.d.ts.map +1 -0
- package/dist/primitives/utils.js +9 -0
- package/dist/primitives/utils.js.map +1 -0
- package/dist/types/index.d.ts +63 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +63 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +345 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/perf-marks.d.ts +28 -0
- package/dist/utils/perf-marks.d.ts.map +1 -0
- package/dist/utils/perf-marks.js +45 -0
- package/dist/utils/perf-marks.js.map +1 -0
- package/dist/utils/readme-utils.d.ts +67 -0
- package/dist/utils/readme-utils.d.ts.map +1 -0
- package/dist/utils/readme-utils.js +164 -0
- package/dist/utils/readme-utils.js.map +1 -0
- package/dist/utils/type-colors.d.ts +70 -0
- package/dist/utils/type-colors.d.ts.map +1 -0
- package/dist/utils/type-colors.js +118 -0
- package/dist/utils/type-colors.js.map +1 -0
- package/package.json +131 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Normalized result shape returned by each tab's `useData` hook.
|
|
4
|
+
* Callers wrap their query hooks to conform to this interface.
|
|
5
|
+
*/
|
|
6
|
+
export interface InfiniteDataResult<T> {
|
|
7
|
+
/** Flat list of items loaded so far across all pages */
|
|
8
|
+
items: T[];
|
|
9
|
+
/** True while the first page is loading */
|
|
10
|
+
isLoading: boolean;
|
|
11
|
+
/** True when more pages are available */
|
|
12
|
+
hasNextPage: boolean;
|
|
13
|
+
/** Trigger loading the next page */
|
|
14
|
+
fetchNextPage: () => void;
|
|
15
|
+
/** True while a subsequent page is loading */
|
|
16
|
+
isFetchingNextPage: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Definition for a single tab inside EntityPickerDialog.
|
|
20
|
+
*
|
|
21
|
+
* @template T - The entity type rendered within this tab
|
|
22
|
+
*/
|
|
23
|
+
export interface EntityPickerTab<T> {
|
|
24
|
+
/** Unique stable identifier for this tab */
|
|
25
|
+
id: string;
|
|
26
|
+
/** Human-readable label rendered in the tab strip */
|
|
27
|
+
label: string;
|
|
28
|
+
/** Lucide-compatible icon component shown beside the label */
|
|
29
|
+
icon: React.ComponentType<{
|
|
30
|
+
className?: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* React hook that returns paginated data for this tab.
|
|
34
|
+
*
|
|
35
|
+
* **Important**: This is called as a hook by TabContent — it MUST follow
|
|
36
|
+
* the Rules of Hooks (called unconditionally at the top of a render function).
|
|
37
|
+
* Do not call this inside conditionals, loops, or callbacks.
|
|
38
|
+
*
|
|
39
|
+
* ESLint cannot detect this as a hook via static analysis because it is stored
|
|
40
|
+
* as an interface field. Callers and implementors are responsible for ensuring
|
|
41
|
+
* compliance with the Rules of Hooks.
|
|
42
|
+
*/
|
|
43
|
+
useData: (params: {
|
|
44
|
+
search: string;
|
|
45
|
+
typeFilter?: string[];
|
|
46
|
+
}) => InfiniteDataResult<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Renders a single list card.
|
|
49
|
+
* @param item - The entity to render
|
|
50
|
+
* @param isSelected - Whether this entity is in the current selection
|
|
51
|
+
*/
|
|
52
|
+
renderCard: (item: T, isSelected: boolean) => React.ReactNode;
|
|
53
|
+
/** Extracts the stable entity identifier used for selection tracking */
|
|
54
|
+
getId: (item: T) => string;
|
|
55
|
+
/** Optional type filter pill definitions shown below the search bar */
|
|
56
|
+
typeFilters?: {
|
|
57
|
+
value: string;
|
|
58
|
+
label: string;
|
|
59
|
+
icon?: React.ComponentType<{
|
|
60
|
+
className?: string;
|
|
61
|
+
}>;
|
|
62
|
+
}[];
|
|
63
|
+
/**
|
|
64
|
+
* Optional base type constraint always applied before user pill selections.
|
|
65
|
+
*
|
|
66
|
+
* When set, the effective filter passed to `useData` is:
|
|
67
|
+
* - The active pill selection when the user toggles pills (caller must ensure
|
|
68
|
+
* `typeFilters` values are a subset of `allowedTypes`).
|
|
69
|
+
* - `allowedTypes` itself when no pills are active (i.e. show all allowed types).
|
|
70
|
+
* - `undefined` when both `allowedTypes` is absent and no pills are active.
|
|
71
|
+
*
|
|
72
|
+
* This removes the need for each `useData` implementation to manually merge a
|
|
73
|
+
* base type constraint with the user's pill selection.
|
|
74
|
+
*/
|
|
75
|
+
allowedTypes?: string[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Props for EntityPickerDialog.
|
|
79
|
+
*
|
|
80
|
+
* @template T - The entity type handled by the active tab
|
|
81
|
+
*/
|
|
82
|
+
export interface EntityPickerDialogProps<T = unknown> {
|
|
83
|
+
/** Controls dialog visibility */
|
|
84
|
+
open: boolean;
|
|
85
|
+
/** Called when the dialog requests open state change */
|
|
86
|
+
onOpenChange: (open: boolean) => void;
|
|
87
|
+
/** One or more tabs defining entity types the user can pick from */
|
|
88
|
+
tabs: EntityPickerTab<T>[];
|
|
89
|
+
/** Single-select closes on first pick; multi-select accumulates until "Done" */
|
|
90
|
+
mode: 'single' | 'multi';
|
|
91
|
+
/**
|
|
92
|
+
* Controlled selection value.
|
|
93
|
+
* - `'single'` mode: a single entity ID string (or empty string for none)
|
|
94
|
+
* - `'multi'` mode: an array of entity ID strings
|
|
95
|
+
*/
|
|
96
|
+
value: string | string[];
|
|
97
|
+
/**
|
|
98
|
+
* Called when the selection commits.
|
|
99
|
+
* Receives the same shape as `value`.
|
|
100
|
+
*/
|
|
101
|
+
onChange: (value: string | string[]) => void;
|
|
102
|
+
/** Dialog title shown in the header */
|
|
103
|
+
title?: string;
|
|
104
|
+
/** Supplementary description shown below the title */
|
|
105
|
+
description?: string;
|
|
106
|
+
/**
|
|
107
|
+
* IDs of entities that already exist in the target context (e.g. already
|
|
108
|
+
* members of a group or set). Items whose ID appears here are rendered with a
|
|
109
|
+
* green checkmark badge, dimmed, and made non-clickable. They are never added
|
|
110
|
+
* to the pending selection. Defaults to empty (no items blocked).
|
|
111
|
+
*
|
|
112
|
+
* Contrast with `excludeIds`: `existingIds` keeps items visible (with a
|
|
113
|
+
* disabled overlay) so the user can see what is already selected; `excludeIds`
|
|
114
|
+
* removes items from the list entirely.
|
|
115
|
+
*/
|
|
116
|
+
existingIds?: string[];
|
|
117
|
+
/**
|
|
118
|
+
* IDs of entities that must be hidden entirely from every tab (e.g. the
|
|
119
|
+
* entity being edited, to prevent circular self-references). Items whose ID
|
|
120
|
+
* appears here are filtered out at the display layer — they are never shown
|
|
121
|
+
* to the user regardless of which tab is active. Defaults to empty.
|
|
122
|
+
*
|
|
123
|
+
* Contrast with `existingIds`: `existingIds` keeps items visible with a
|
|
124
|
+
* disabled green overlay; `excludeIds` removes them from the list completely.
|
|
125
|
+
*/
|
|
126
|
+
excludeIds?: string[];
|
|
127
|
+
/**
|
|
128
|
+
* Optional single-click-to-add callback.
|
|
129
|
+
*
|
|
130
|
+
* When provided, the dialog operates in instant-add mode: clicking a
|
|
131
|
+
* non-existing item fires this callback immediately with the full item object,
|
|
132
|
+
* shows a brief green success flash (~200ms), and keeps the dialog open.
|
|
133
|
+
* The multi-select accumulator and footer are suppressed in this mode.
|
|
134
|
+
*
|
|
135
|
+
* Items in existingIds are always disabled and never trigger this callback.
|
|
136
|
+
* When absent, the existing multi-select + Done button pattern is unchanged.
|
|
137
|
+
* The two modes are mutually exclusive.
|
|
138
|
+
*/
|
|
139
|
+
onItemSelect?: (item: T) => void;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Props for EntityPickerTrigger.
|
|
143
|
+
*/
|
|
144
|
+
export interface EntityPickerTriggerProps {
|
|
145
|
+
/** Accessible label and button text used as the field caption */
|
|
146
|
+
label: string;
|
|
147
|
+
/** Current selection value (mirrors EntityPickerDialogProps.value) */
|
|
148
|
+
value: string | string[];
|
|
149
|
+
/** Named items for selected IDs — used to render display names and remove badges */
|
|
150
|
+
items?: {
|
|
151
|
+
id: string;
|
|
152
|
+
name: string;
|
|
153
|
+
}[];
|
|
154
|
+
/** Must match the mode of the companion EntityPickerDialog */
|
|
155
|
+
mode: 'single' | 'multi';
|
|
156
|
+
/** Called when the user clicks the trigger to open the picker dialog */
|
|
157
|
+
onClick: () => void;
|
|
158
|
+
/**
|
|
159
|
+
* Multi-mode only: called when the user removes an individual item badge.
|
|
160
|
+
* @param id - The entity ID to remove
|
|
161
|
+
*/
|
|
162
|
+
onRemove?: (id: string) => void;
|
|
163
|
+
/** Placeholder text shown when nothing is selected */
|
|
164
|
+
placeholder?: string;
|
|
165
|
+
/** Disables all interactions */
|
|
166
|
+
disabled?: boolean;
|
|
167
|
+
/** Additional CSS classes for the outermost wrapper */
|
|
168
|
+
className?: string;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* EntityPickerDialog — Generic tabbed entity picker dialog.
|
|
172
|
+
*
|
|
173
|
+
* Supports an arbitrary number of tabs, each backed by its own data hook.
|
|
174
|
+
* In `single` mode, selecting an entity immediately commits the change and
|
|
175
|
+
* closes the dialog. In `multi` mode, selections accumulate and are committed
|
|
176
|
+
* when the user clicks "Done".
|
|
177
|
+
*
|
|
178
|
+
* Features:
|
|
179
|
+
* - Tabbed navigation with icons
|
|
180
|
+
* - Per-tab search with 300ms debounce
|
|
181
|
+
* - Optional type filter pills per tab
|
|
182
|
+
* - Infinite scroll via `useIntersectionObserver`
|
|
183
|
+
* - Skeleton loading + empty state
|
|
184
|
+
* - Selection ring overlay on picked cards
|
|
185
|
+
* - WCAG 2.1 AA: keyboard navigation, ARIA labels, focus management
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```tsx
|
|
189
|
+
* <EntityPickerDialog
|
|
190
|
+
* open={open}
|
|
191
|
+
* onOpenChange={setOpen}
|
|
192
|
+
* tabs={[artifactTab]}
|
|
193
|
+
* mode="multi"
|
|
194
|
+
* value={selectedIds}
|
|
195
|
+
* onChange={setSelectedIds}
|
|
196
|
+
* title="Select Artifacts"
|
|
197
|
+
* />
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
export declare function EntityPickerDialog<T = unknown>({ open, onOpenChange, tabs, mode, value, onChange, title, description, existingIds, excludeIds, onItemSelect, }: EntityPickerDialogProps<T>): import("react/jsx-runtime").JSX.Element | null;
|
|
201
|
+
/**
|
|
202
|
+
* EntityPickerTrigger — Button/field trigger that opens an EntityPickerDialog.
|
|
203
|
+
*
|
|
204
|
+
* Renders a form-field-height button showing the current selection. In
|
|
205
|
+
* `single` mode it shows the selected item name (or placeholder). In `multi`
|
|
206
|
+
* mode it shows removable badge chips and a count summary.
|
|
207
|
+
*
|
|
208
|
+
* @example Single mode
|
|
209
|
+
* ```tsx
|
|
210
|
+
* <EntityPickerTrigger
|
|
211
|
+
* label="Primary Agent"
|
|
212
|
+
* value={selectedId}
|
|
213
|
+
* items={[{ id: selectedId, name: 'My Agent' }]}
|
|
214
|
+
* mode="single"
|
|
215
|
+
* onClick={() => setPickerOpen(true)}
|
|
216
|
+
* placeholder="Select an agent..."
|
|
217
|
+
* />
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* @example Multi mode
|
|
221
|
+
* ```tsx
|
|
222
|
+
* <EntityPickerTrigger
|
|
223
|
+
* label="Supporting Skills"
|
|
224
|
+
* value={selectedIds}
|
|
225
|
+
* items={resolvedItems}
|
|
226
|
+
* mode="multi"
|
|
227
|
+
* onClick={() => setPickerOpen(true)}
|
|
228
|
+
* onRemove={(id) => setSelectedIds((prev) => prev.filter((x) => x !== id))}
|
|
229
|
+
* />
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
export declare function EntityPickerTrigger({ label, value, items, mode, onClick, onRemove, placeholder, disabled, className, }: EntityPickerTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
233
|
+
//# sourceMappingURL=EntityPickerDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityPickerDialog.d.ts","sourceRoot":"","sources":["../../src/pickers/EntityPickerDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { ChevronDown, CheckCircle2, Package, Search, X, Check } from 'lucide-react';
|
|
5
|
+
import { Button } from '../components/ui/button';
|
|
6
|
+
import { Badge } from '../primitives/Badge';
|
|
7
|
+
import { Input } from '../primitives/Input';
|
|
8
|
+
import { ScrollArea } from '../primitives/ScrollArea';
|
|
9
|
+
import { Skeleton } from '../components/ui/skeleton';
|
|
10
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../primitives/Tabs';
|
|
11
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '../primitives/Dialog';
|
|
12
|
+
import { useDebounce } from '../hooks/use-debounce';
|
|
13
|
+
import { useIntersectionObserver } from '../hooks/use-intersection-observer';
|
|
14
|
+
import { cn } from '../primitives/utils';
|
|
15
|
+
import { EntityPickerViewToggle } from './EntityPickerViewToggle';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Internal sub-components
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/** Grid or list of skeleton cards shown during initial data load */
|
|
20
|
+
function GridSkeleton({ count = 6, viewMode = 'grid' }) {
|
|
21
|
+
if (viewMode === 'list') {
|
|
22
|
+
return (_jsx("div", { className: "flex flex-col gap-1.5", "aria-label": "Loading items", "aria-busy": "true", children: Array.from({ length: count }).map((_, i) => (_jsxs("div", { className: "flex items-center gap-3 rounded-lg border p-2.5", children: [_jsx(Skeleton, { className: "h-5 w-5 shrink-0 rounded" }), _jsx(Skeleton, { className: "h-4 flex-1 rounded" }), _jsx(Skeleton, { className: "h-4 w-16 rounded" })] }, i))) }));
|
|
23
|
+
}
|
|
24
|
+
return (_jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-3", "aria-label": "Loading items", "aria-busy": "true", children: Array.from({ length: count }).map((_, i) => (_jsxs("div", { className: "flex min-w-[140px] flex-col gap-2 rounded-lg border border-l-[3px] border-l-muted p-3", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Skeleton, { className: "h-4 w-4 rounded" }), _jsx(Skeleton, { className: "h-4 flex-1 rounded" })] }), _jsx(Skeleton, { className: "h-3 w-full rounded" }), _jsx(Skeleton, { className: "h-3 w-2/3 rounded" }), _jsx("div", { className: "mt-auto pt-1", children: _jsx(Skeleton, { className: "h-4 w-1/2 rounded" }) })] }, i))) }));
|
|
25
|
+
}
|
|
26
|
+
/** Empty state shown when item list is empty after loading */
|
|
27
|
+
function EmptyState({ message }) {
|
|
28
|
+
return (_jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [_jsx(Package, { className: "h-9 w-9 text-muted-foreground/30", "aria-hidden": "true" }), _jsx("p", { className: "mt-3 text-sm text-muted-foreground", children: message })] }));
|
|
29
|
+
}
|
|
30
|
+
function SearchInput({ value, onChange, placeholder = 'Search\u2026' }) {
|
|
31
|
+
const inputRef = useRef(null);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
// Auto-focus on mount (dialog already traps focus; this targets the input specifically)
|
|
34
|
+
const timer = setTimeout(() => inputRef.current?.focus(), 0);
|
|
35
|
+
return () => clearTimeout(timer);
|
|
36
|
+
}, []);
|
|
37
|
+
return (_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground", "aria-hidden": "true" }), _jsx(Input, { ref: inputRef, value: value, onChange: (e) => onChange(e.target.value), placeholder: placeholder, className: "pl-9 pr-9", "aria-label": placeholder, autoComplete: "off", spellCheck: false }), value && (_jsx("button", { type: "button", onClick: () => onChange(''), "aria-label": "Clear search", className: cn('absolute right-3 top-1/2 -translate-y-1/2 rounded-sm', 'text-muted-foreground hover:text-foreground', 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'), children: _jsx(X, { className: "h-4 w-4", "aria-hidden": "true" }) }))] }));
|
|
38
|
+
}
|
|
39
|
+
function TypeFilterPills({ filters, active, onToggle }) {
|
|
40
|
+
return (_jsx("div", { className: "flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by type", children: filters.map(({ value, label, icon: Icon }) => {
|
|
41
|
+
const isActive = active.has(value);
|
|
42
|
+
return (_jsxs("button", { type: "button", onClick: () => onToggle(value), "aria-pressed": isActive, className: cn('inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium transition-colors', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', isActive
|
|
43
|
+
? 'border-primary bg-primary text-primary-foreground'
|
|
44
|
+
: 'border-border bg-transparent text-muted-foreground hover:border-foreground/40 hover:text-foreground'), children: [Icon && _jsx(Icon, { className: "h-3 w-3", "aria-hidden": "true" }), label] }, value));
|
|
45
|
+
}) }));
|
|
46
|
+
}
|
|
47
|
+
function TabContent({ tab, selectedIds, onSelect, liveAnnouncement, onAnnounce, existingIds, excludeIds, viewMode, onItemSelect }) {
|
|
48
|
+
const [search, setSearch] = useState('');
|
|
49
|
+
const [activeTypeFilters, setActiveTypeFilters] = useState(new Set());
|
|
50
|
+
// Tracks which card ID was most recently selected, for selection animation
|
|
51
|
+
const [recentlySelected, setRecentlySelected] = useState(null);
|
|
52
|
+
// Grid container ref for arrow-key navigation
|
|
53
|
+
const gridRef = useRef(null);
|
|
54
|
+
const debouncedSearch = useDebounce(search, 300);
|
|
55
|
+
const toggleTypeFilter = useCallback((value) => {
|
|
56
|
+
setActiveTypeFilters((prev) => {
|
|
57
|
+
const next = new Set(prev);
|
|
58
|
+
if (next.has(value)) {
|
|
59
|
+
next.delete(value);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
next.add(value);
|
|
63
|
+
}
|
|
64
|
+
return next;
|
|
65
|
+
});
|
|
66
|
+
}, []);
|
|
67
|
+
const effectiveTypeFilter = activeTypeFilters.size > 0
|
|
68
|
+
? Array.from(activeTypeFilters)
|
|
69
|
+
: (tab.allowedTypes?.length ? tab.allowedTypes : undefined);
|
|
70
|
+
const { items: rawItems, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } = tab.useData({
|
|
71
|
+
search: debouncedSearch,
|
|
72
|
+
typeFilter: effectiveTypeFilter,
|
|
73
|
+
});
|
|
74
|
+
// Display-layer filter: hide items whose ID is in excludeIds entirely.
|
|
75
|
+
// This does not affect the underlying query — pagination and fetching are unchanged.
|
|
76
|
+
const items = React.useMemo(() => excludeIds.size > 0 ? rawItems.filter((item) => !excludeIds.has(tab.getId(item))) : rawItems,
|
|
77
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
|
+
[rawItems, excludeIds, tab.getId]);
|
|
79
|
+
// Infinite scroll sentinel
|
|
80
|
+
const { targetRef, isIntersecting } = useIntersectionObserver({
|
|
81
|
+
rootMargin: '100px',
|
|
82
|
+
enabled: !!hasNextPage && !isFetchingNextPage,
|
|
83
|
+
});
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (isIntersecting) {
|
|
86
|
+
fetchNextPage();
|
|
87
|
+
}
|
|
88
|
+
}, [isIntersecting, fetchNextPage]);
|
|
89
|
+
// Clear selection animation after 200ms
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (recentlySelected) {
|
|
92
|
+
const timer = setTimeout(() => setRecentlySelected(null), 200);
|
|
93
|
+
return () => clearTimeout(timer);
|
|
94
|
+
}
|
|
95
|
+
}, [recentlySelected]);
|
|
96
|
+
// Tracks which card just had an instant-add success flash
|
|
97
|
+
const [recentlyAdded, setRecentlyAdded] = useState(null);
|
|
98
|
+
// Clear instant-add success flash after 200ms
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (recentlyAdded) {
|
|
101
|
+
const timer = setTimeout(() => setRecentlyAdded(null), 200);
|
|
102
|
+
return () => clearTimeout(timer);
|
|
103
|
+
}
|
|
104
|
+
}, [recentlyAdded]);
|
|
105
|
+
const handleSelect = useCallback((id, name) => {
|
|
106
|
+
setRecentlySelected(id);
|
|
107
|
+
onSelect(id);
|
|
108
|
+
const willBeSelected = !selectedIds.has(id);
|
|
109
|
+
onAnnounce(willBeSelected ? `${name} selected` : `${name} deselected`);
|
|
110
|
+
}, [onSelect, onAnnounce, selectedIds]);
|
|
111
|
+
// O(1) lookup map: id -> item — used by handleInstantAdd to retrieve the full object
|
|
112
|
+
const itemById = React.useMemo(() => {
|
|
113
|
+
const map = new Map();
|
|
114
|
+
for (const item of items) {
|
|
115
|
+
map.set(tab.getId(item), item);
|
|
116
|
+
}
|
|
117
|
+
return map;
|
|
118
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
119
|
+
}, [items, tab.getId]);
|
|
120
|
+
const handleInstantAdd = useCallback((id, name) => {
|
|
121
|
+
const item = itemById.get(id);
|
|
122
|
+
if (!item || !onItemSelect)
|
|
123
|
+
return;
|
|
124
|
+
setRecentlyAdded(id);
|
|
125
|
+
onItemSelect(item);
|
|
126
|
+
onAnnounce(`${name} added`);
|
|
127
|
+
}, [itemById, onItemSelect, onAnnounce]);
|
|
128
|
+
const isInstantAddMode = !!onItemSelect;
|
|
129
|
+
/** Arrow-key navigation: move focus between grid card elements */
|
|
130
|
+
const handleGridKeyDown = useCallback((e) => {
|
|
131
|
+
if (!gridRef.current)
|
|
132
|
+
return;
|
|
133
|
+
if (!['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key))
|
|
134
|
+
return;
|
|
135
|
+
const cards = Array.from(gridRef.current.querySelectorAll('[data-picker-card]'));
|
|
136
|
+
const focused = document.activeElement;
|
|
137
|
+
const currentIndex = cards.indexOf(focused);
|
|
138
|
+
if (currentIndex === -1)
|
|
139
|
+
return;
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
// Determine columns count from computed style
|
|
142
|
+
const gridStyle = window.getComputedStyle(gridRef.current);
|
|
143
|
+
const colCount = gridStyle.gridTemplateColumns.split(' ').length || 2;
|
|
144
|
+
let nextIndex = currentIndex;
|
|
145
|
+
if (e.key === 'ArrowRight')
|
|
146
|
+
nextIndex = currentIndex + 1;
|
|
147
|
+
else if (e.key === 'ArrowLeft')
|
|
148
|
+
nextIndex = currentIndex - 1;
|
|
149
|
+
else if (e.key === 'ArrowDown')
|
|
150
|
+
nextIndex = currentIndex + colCount;
|
|
151
|
+
else if (e.key === 'ArrowUp')
|
|
152
|
+
nextIndex = currentIndex - colCount;
|
|
153
|
+
const target = nextIndex >= 0 && nextIndex < cards.length ? cards[nextIndex] : undefined;
|
|
154
|
+
target?.focus();
|
|
155
|
+
}, []);
|
|
156
|
+
const isEmpty = !isLoading && items.length === 0;
|
|
157
|
+
const hasTypeFilters = !!tab.typeFilters && tab.typeFilters.length > 0;
|
|
158
|
+
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsx("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: liveAnnouncement }), _jsx(SearchInput, { value: search, onChange: setSearch, placeholder: `Search ${tab.label.toLowerCase()}\u2026` }), hasTypeFilters && tab.typeFilters && (_jsx(TypeFilterPills, { filters: tab.typeFilters, active: activeTypeFilters, onToggle: toggleTypeFilter })), _jsx(ScrollArea, { className: "h-[min(400px,50vh)]", children: isLoading ? (_jsx(GridSkeleton, { count: 8, viewMode: viewMode })) : isEmpty ? (_jsx(EmptyState, { message: debouncedSearch || activeTypeFilters.size > 0
|
|
159
|
+
? 'No results match your filters'
|
|
160
|
+
: `No ${tab.label.toLowerCase()} found` })) : (_jsxs(_Fragment, { children: [_jsx("div", { ref: gridRef, className: cn(viewMode === 'grid'
|
|
161
|
+
? 'grid grid-cols-2 gap-3 sm:grid-cols-3'
|
|
162
|
+
: 'flex flex-col gap-1.5'), role: "listbox", "aria-label": tab.label, "aria-multiselectable": "true", onKeyDown: handleGridKeyDown, children: items.map((item) => {
|
|
163
|
+
const id = tab.getId(item);
|
|
164
|
+
const isSelected = selectedIds.has(id);
|
|
165
|
+
const isAnimating = recentlySelected === id;
|
|
166
|
+
const isExisting = existingIds.has(id);
|
|
167
|
+
return (_jsxs("div", { "data-picker-card": true, role: "option", "aria-selected": isSelected, "aria-disabled": isExisting ? true : undefined, "aria-description": isExisting ? 'Already added' : undefined, className: cn('relative rounded-lg', viewMode === 'grid' && 'min-w-[180px]', isExisting
|
|
168
|
+
? 'cursor-default opacity-60'
|
|
169
|
+
: 'cursor-pointer',
|
|
170
|
+
// Focus ring: apply to all focusable items; existing items still
|
|
171
|
+
// receive focus so keyboard users can discover what is already added.
|
|
172
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
|
|
173
|
+
// Selection flash animation on pick
|
|
174
|
+
!isExisting && isAnimating && 'animate-picker-flash'), onClick: isExisting ? undefined : () => {
|
|
175
|
+
// Derive display name: prefer aria-label on the card element, then
|
|
176
|
+
// first visible text content, then fall back to the raw id.
|
|
177
|
+
const el = gridRef.current?.querySelector(`[data-picker-card-id="${id}"]`);
|
|
178
|
+
const name = el?.getAttribute('aria-label') ?? el?.textContent?.trim().split('\n')[0] ?? id;
|
|
179
|
+
if (isInstantAddMode) {
|
|
180
|
+
handleInstantAdd(id, name);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
handleSelect(id, name);
|
|
184
|
+
}
|
|
185
|
+
}, onKeyDown: isExisting ? undefined : (e) => {
|
|
186
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
const el = gridRef.current?.querySelector(`[data-picker-card-id="${id}"]`);
|
|
189
|
+
const name = el?.getAttribute('aria-label') ?? el?.textContent?.trim().split('\n')[0] ?? id;
|
|
190
|
+
if (isInstantAddMode) {
|
|
191
|
+
handleInstantAdd(id, name);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
handleSelect(id, name);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}, tabIndex: 0, "data-picker-card-id": id, children: [tab.renderCard(item, isSelected), isExisting && (_jsx("div", { className: "pointer-events-none absolute inset-0 flex items-start justify-end rounded-lg p-1.5", "aria-hidden": "true", children: _jsx("span", { className: cn('flex h-5 w-5 items-center justify-center rounded-full', 'bg-emerald-500 text-white shadow-sm'), children: _jsx(CheckCircle2, { className: "h-3.5 w-3.5" }) }) })), !isExisting && isInstantAddMode && recentlyAdded === id && (_jsxs(_Fragment, { children: [_jsx("div", { className: "pointer-events-none absolute inset-0 rounded-lg bg-emerald-500/15 transition-opacity duration-200", "aria-hidden": "true" }), _jsx("span", { className: cn('pointer-events-none absolute right-2 top-2 z-10', 'flex h-5 w-5 items-center justify-center rounded-full', 'bg-emerald-500 text-white shadow-sm', 'transition-opacity duration-200'), "aria-hidden": "true", children: _jsx(Check, { className: "h-3 w-3", strokeWidth: 3 }) }), _jsx("div", { className: "pointer-events-none absolute inset-0 rounded-lg ring-2 ring-emerald-500 ring-offset-1 transition-opacity duration-200", "aria-hidden": "true" })] })), !isExisting && !isInstantAddMode && isSelected && (_jsx("span", { className: cn('pointer-events-none absolute right-2 top-2 z-10', 'flex h-5 w-5 items-center justify-center rounded-full', 'bg-primary text-primary-foreground shadow-sm'), "aria-hidden": "true", children: _jsx(Check, { className: "h-3 w-3", strokeWidth: 3 }) })), !isExisting && !isInstantAddMode && isSelected && (_jsx("div", { className: "pointer-events-none absolute inset-0 rounded-lg ring-2 ring-primary ring-offset-1", "aria-hidden": "true" }))] }, id));
|
|
198
|
+
}) }), isFetchingNextPage && (_jsx("div", { className: "mt-2", children: _jsx(GridSkeleton, { count: 4, viewMode: viewMode }) })), hasNextPage && !isFetchingNextPage && (_jsx("div", { ref: targetRef, className: "h-4", "aria-hidden": "true" }))] })) })] }));
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// EntityPickerDialog
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
/**
|
|
204
|
+
* EntityPickerDialog — Generic tabbed entity picker dialog.
|
|
205
|
+
*
|
|
206
|
+
* Supports an arbitrary number of tabs, each backed by its own data hook.
|
|
207
|
+
* In `single` mode, selecting an entity immediately commits the change and
|
|
208
|
+
* closes the dialog. In `multi` mode, selections accumulate and are committed
|
|
209
|
+
* when the user clicks "Done".
|
|
210
|
+
*
|
|
211
|
+
* Features:
|
|
212
|
+
* - Tabbed navigation with icons
|
|
213
|
+
* - Per-tab search with 300ms debounce
|
|
214
|
+
* - Optional type filter pills per tab
|
|
215
|
+
* - Infinite scroll via `useIntersectionObserver`
|
|
216
|
+
* - Skeleton loading + empty state
|
|
217
|
+
* - Selection ring overlay on picked cards
|
|
218
|
+
* - WCAG 2.1 AA: keyboard navigation, ARIA labels, focus management
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```tsx
|
|
222
|
+
* <EntityPickerDialog
|
|
223
|
+
* open={open}
|
|
224
|
+
* onOpenChange={setOpen}
|
|
225
|
+
* tabs={[artifactTab]}
|
|
226
|
+
* mode="multi"
|
|
227
|
+
* value={selectedIds}
|
|
228
|
+
* onChange={setSelectedIds}
|
|
229
|
+
* title="Select Artifacts"
|
|
230
|
+
* />
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
export function EntityPickerDialog({ open, onOpenChange, tabs, mode, value, onChange, title = 'Select', description, existingIds, excludeIds, onItemSelect, }) {
|
|
234
|
+
const existingIdsSet = React.useMemo(() => new Set(existingIds ?? []),
|
|
235
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
236
|
+
[existingIds?.join(',')]);
|
|
237
|
+
const excludeIdsSet = React.useMemo(() => new Set(excludeIds ?? []),
|
|
238
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
239
|
+
[excludeIds?.join(',')]);
|
|
240
|
+
const [activeTabId, setActiveTabId] = useState(() => tabs[0]?.id ?? '');
|
|
241
|
+
const [viewMode, setViewMode] = useState('grid');
|
|
242
|
+
// Internal multi-select accumulator; for single mode we bypass this
|
|
243
|
+
const [pendingSelection, setPendingSelection] = useState(new Set());
|
|
244
|
+
// Screen-reader live announcement (selection changes)
|
|
245
|
+
const [liveAnnouncement, setLiveAnnouncement] = useState('');
|
|
246
|
+
// Sync pendingSelection from external value when dialog opens
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
if (open) {
|
|
249
|
+
const ids = Array.isArray(value) ? value : value ? [value] : [];
|
|
250
|
+
setPendingSelection(new Set(ids));
|
|
251
|
+
setActiveTabId(tabs[0]?.id ?? '');
|
|
252
|
+
setLiveAnnouncement('');
|
|
253
|
+
}
|
|
254
|
+
}, [open]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
255
|
+
const handleSelect = useCallback((id) => {
|
|
256
|
+
if (mode === 'single') {
|
|
257
|
+
onChange(id);
|
|
258
|
+
onOpenChange(false);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
setPendingSelection((prev) => {
|
|
262
|
+
const next = new Set(prev);
|
|
263
|
+
if (next.has(id)) {
|
|
264
|
+
next.delete(id);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
next.add(id);
|
|
268
|
+
}
|
|
269
|
+
return next;
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}, [mode, onChange, onOpenChange]);
|
|
273
|
+
const handleDone = useCallback(() => {
|
|
274
|
+
if (mode === 'multi') {
|
|
275
|
+
onChange(Array.from(pendingSelection));
|
|
276
|
+
}
|
|
277
|
+
onOpenChange(false);
|
|
278
|
+
}, [mode, onChange, onOpenChange, pendingSelection]);
|
|
279
|
+
const handleClose = useCallback(() => {
|
|
280
|
+
onOpenChange(false);
|
|
281
|
+
}, [onOpenChange]);
|
|
282
|
+
// In instant-add mode the footer (selection count, Cancel, Done) is hidden
|
|
283
|
+
const isInstantAddMode = !!onItemSelect;
|
|
284
|
+
if (tabs.length === 0)
|
|
285
|
+
return null;
|
|
286
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-5xl max-h-[85vh] !grid-rows-[auto_1fr] overflow-hidden", children: [_jsxs(DialogHeader, { children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(DialogTitle, { className: "flex-1", children: title }), _jsx(EntityPickerViewToggle, { value: viewMode, onChange: setViewMode })] }), description && _jsx(DialogDescription, { children: description })] }), _jsxs(Tabs, { value: activeTabId, onValueChange: setActiveTabId, className: "mt-1 min-h-0 overflow-hidden flex flex-col", children: [_jsx(TabsList, { className: cn('grid w-full', `grid-cols-${tabs.length}`), "aria-label": "Entity type", children: tabs.map((tab) => {
|
|
287
|
+
const Icon = tab.icon;
|
|
288
|
+
return (_jsxs(TabsTrigger, { value: tab.id, className: "gap-1.5", children: [_jsx(Icon, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), tab.label] }, tab.id));
|
|
289
|
+
}) }), tabs.map((tab) => (_jsx(TabsContent, { value: tab.id, className: "mt-3 focus-visible:outline-none flex flex-col min-h-0", children: _jsx(TabContent, { tab: tab, selectedIds: pendingSelection, onSelect: handleSelect, liveAnnouncement: liveAnnouncement, onAnnounce: setLiveAnnouncement, existingIds: existingIdsSet, excludeIds: excludeIdsSet, viewMode: viewMode, onItemSelect: onItemSelect }) }, tab.id)))] }), !isInstantAddMode && _jsxs("div", { className: "flex items-center justify-between pt-1", children: [mode === 'multi' && (_jsx("span", { className: "text-sm text-muted-foreground", children: pendingSelection.size > 0
|
|
290
|
+
? `${pendingSelection.size} selected`
|
|
291
|
+
: 'Nothing selected' })), _jsxs("div", { className: cn('flex gap-2', mode === 'single' && 'ml-auto'), children: [mode === 'multi' && (_jsx(Button, { variant: "ghost", onClick: handleClose, children: "Cancel" })), _jsx(Button, { variant: "outline", onClick: handleDone, children: "Done" })] })] })] }) }));
|
|
292
|
+
}
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// EntityPickerTrigger
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
/**
|
|
297
|
+
* EntityPickerTrigger — Button/field trigger that opens an EntityPickerDialog.
|
|
298
|
+
*
|
|
299
|
+
* Renders a form-field-height button showing the current selection. In
|
|
300
|
+
* `single` mode it shows the selected item name (or placeholder). In `multi`
|
|
301
|
+
* mode it shows removable badge chips and a count summary.
|
|
302
|
+
*
|
|
303
|
+
* @example Single mode
|
|
304
|
+
* ```tsx
|
|
305
|
+
* <EntityPickerTrigger
|
|
306
|
+
* label="Primary Agent"
|
|
307
|
+
* value={selectedId}
|
|
308
|
+
* items={[{ id: selectedId, name: 'My Agent' }]}
|
|
309
|
+
* mode="single"
|
|
310
|
+
* onClick={() => setPickerOpen(true)}
|
|
311
|
+
* placeholder="Select an agent..."
|
|
312
|
+
* />
|
|
313
|
+
* ```
|
|
314
|
+
*
|
|
315
|
+
* @example Multi mode
|
|
316
|
+
* ```tsx
|
|
317
|
+
* <EntityPickerTrigger
|
|
318
|
+
* label="Supporting Skills"
|
|
319
|
+
* value={selectedIds}
|
|
320
|
+
* items={resolvedItems}
|
|
321
|
+
* mode="multi"
|
|
322
|
+
* onClick={() => setPickerOpen(true)}
|
|
323
|
+
* onRemove={(id) => setSelectedIds((prev) => prev.filter((x) => x !== id))}
|
|
324
|
+
* />
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
export function EntityPickerTrigger({ label, value, items = [], mode, onClick, onRemove, placeholder = 'Select\u2026', disabled = false, className, }) {
|
|
328
|
+
// Normalize value to array for internal logic
|
|
329
|
+
const selectedIds = Array.isArray(value)
|
|
330
|
+
? value
|
|
331
|
+
: value
|
|
332
|
+
? [value]
|
|
333
|
+
: [];
|
|
334
|
+
const itemMap = new Map(items.map((i) => [i.id, i.name]));
|
|
335
|
+
// Single-mode display
|
|
336
|
+
if (mode === 'single') {
|
|
337
|
+
const selectedId = selectedIds[0];
|
|
338
|
+
const selectedName = selectedId ? (itemMap.get(selectedId) ?? selectedId.slice(0, 8)) : null;
|
|
339
|
+
return (_jsxs("div", { className: cn('flex flex-col gap-1.5', className), children: [label && (_jsx("span", { className: "text-sm font-medium leading-none", children: label })), _jsxs(Button, { type: "button", variant: "outline", onClick: onClick, disabled: disabled, "aria-label": label
|
|
340
|
+
? selectedName
|
|
341
|
+
? `${label}: ${selectedName}`
|
|
342
|
+
: `${label}: ${placeholder}`
|
|
343
|
+
: (selectedName ?? placeholder), className: cn('flex h-9 w-full items-center justify-between gap-2 px-3 font-normal', !selectedName && 'text-muted-foreground'), children: [_jsx("span", { className: "flex-1 truncate text-left text-sm", "aria-hidden": "true", children: selectedName ?? placeholder }), _jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" })] })] }));
|
|
344
|
+
}
|
|
345
|
+
// Multi-mode display
|
|
346
|
+
const count = selectedIds.length;
|
|
347
|
+
return (_jsxs("div", { className: cn('flex flex-col gap-1.5', className), children: [label && (_jsx("span", { className: "text-sm font-medium leading-none", children: label })), _jsxs(Button, { type: "button", variant: "outline", onClick: onClick, disabled: disabled, "aria-label": `${label ?? 'Picker'}: ${count > 0 ? `${count} selected` : placeholder}`, className: cn('flex h-9 w-full items-center justify-between gap-2 px-3 font-normal', count === 0 && 'text-muted-foreground'), children: [_jsx("span", { className: "flex items-center gap-1.5 text-sm", children: count > 0 ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "inline-flex h-5 min-w-[20px] items-center justify-center rounded-full bg-primary px-1.5 text-xs font-semibold text-primary-foreground", "aria-label": `${count} selected`, children: count }), _jsx("span", { children: "selected" })] })) : (placeholder) }), _jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" })] }), count > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5", role: "list", "aria-label": `${label ?? 'Selected'} items`, children: selectedIds.map((id) => {
|
|
348
|
+
const name = itemMap.get(id) ?? id.slice(0, 8);
|
|
349
|
+
return (_jsxs(Badge, { variant: "secondary", className: "flex items-center gap-1 pr-1 text-xs", role: "listitem", children: [_jsx("span", { className: "max-w-[140px] truncate", children: name }), onRemove && (_jsx("button", { type: "button", onClick: (e) => {
|
|
350
|
+
e.stopPropagation();
|
|
351
|
+
onRemove(id);
|
|
352
|
+
}, disabled: disabled, "aria-label": `Remove ${name}`, className: cn('ml-0.5 flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-full', 'text-muted-foreground transition-colors', 'hover:bg-foreground/10 hover:text-foreground', 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', disabled && 'cursor-not-allowed opacity-50'), children: _jsx(X, { className: "h-2.5 w-2.5", "aria-hidden": "true" }) }))] }, id));
|
|
353
|
+
}) }))] }));
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=EntityPickerDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityPickerDialog.js","sourceRoot":"","sources":["../../src/pickers/EntityPickerDialog.tsx"],"names":[],"mappings":"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"}
|