flikkui 0.2.0-beta.2 → 0.2.0-beta.5
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/README.md +92 -0
- package/dist/components/ai/PromptInput/PromptInput.js +23 -15
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.d.ts +27 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.js +62 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.d.ts +10 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +12 -0
- package/dist/components/ai/PromptSuggestions/PromptSuggestion.types.d.ts +53 -0
- package/dist/components/ai/PromptSuggestions/index.d.ts +4 -2
- package/dist/components/ai/index.d.ts +2 -12
- package/dist/components/charts/ActivityRings/ActivityRings.js +70 -58
- package/dist/components/charts/ActivityRings/ActivityRings.theme.js +0 -1
- package/dist/components/charts/ActivityRings/ActivityRings.types.d.ts +17 -0
- package/dist/components/charts/BarChart/BarChart.js +8 -4
- package/dist/components/charts/BarChart/BarChart.types.d.ts +14 -0
- package/dist/components/charts/DonutChart/DonutChart.js +11 -8
- package/dist/components/charts/DonutChart/DonutChart.theme.d.ts +3 -0
- package/dist/components/charts/DonutChart/DonutChart.theme.js +5 -4
- package/dist/components/charts/DonutChart/donut-utils.d.ts +5 -0
- package/dist/components/charts/DonutChart/donut-utils.js +26 -1
- package/dist/components/charts/Heatmap/Heatmap.theme.js +2 -2
- package/dist/components/charts/shared/ChartAxis/XAxis.d.ts +2 -2
- package/dist/components/charts/shared/ChartAxis/XAxis.js +4 -4
- package/dist/components/charts/shared/ChartAxis/YAxis.d.ts +2 -2
- package/dist/components/charts/shared/ChartAxis/YAxis.js +8 -7
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +1 -1
- package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +2 -2
- package/dist/components/charts/theme/chart.theme.d.ts +1 -1
- package/dist/components/charts/theme/chart.theme.js +39 -39
- package/dist/components/core/Accordion/Accordion.d.ts +1 -1
- package/dist/components/core/Accordion/Accordion.js +2 -2
- package/dist/components/core/Accordion/Accordion.types.d.ts +8 -0
- package/dist/components/core/Badge/Badge.js +11 -15
- package/dist/components/core/Badge/Badge.theme.js +7 -21
- package/dist/components/core/Badge/Badge.types.d.ts +9 -1
- package/dist/components/core/Button/Button.js +2 -2
- package/dist/components/core/Button/Button.theme.js +1 -1
- package/dist/components/core/Button/Button.types.d.ts +8 -0
- package/dist/components/core/Card/Card.js +8 -2
- package/dist/components/core/Card/Card.theme.js +1 -1
- package/dist/components/core/Card/Card.types.d.ts +24 -1
- package/dist/components/core/Drawer/Drawer.d.ts +1 -1
- package/dist/components/core/Drawer/Drawer.js +10 -40
- package/dist/components/core/Drawer/Drawer.theme.js +2 -1
- package/dist/components/core/Drawer/Drawer.types.d.ts +8 -0
- package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/core/Dropdown/Dropdown.js +2 -2
- package/dist/components/core/Dropdown/Dropdown.types.d.ts +8 -0
- package/dist/components/core/Metric/Metric.d.ts +1 -1
- package/dist/components/core/Metric/Metric.js +9 -5
- package/dist/components/core/Metric/Metric.theme.d.ts +1 -1
- package/dist/components/core/Metric/Metric.theme.js +38 -28
- package/dist/components/core/Metric/Metric.types.d.ts +27 -8
- package/dist/components/core/Modal/Modal.d.ts +1 -1
- package/dist/components/core/Modal/Modal.js +17 -40
- package/dist/components/core/Modal/Modal.theme.js +8 -3
- package/dist/components/core/Modal/Modal.types.d.ts +18 -0
- package/dist/components/core/Modal/index.d.ts +1 -1
- package/dist/components/core/Notification/Notification.js +2 -0
- package/dist/components/core/Pill/Pill.d.ts +6 -11
- package/dist/components/core/Pill/Pill.theme.d.ts +2 -2
- package/dist/components/core/Pill/Pill.types.d.ts +9 -22
- package/dist/components/core/Pill/index.d.ts +1 -1
- package/dist/components/core/Popover/Popover.d.ts +1 -1
- package/dist/components/core/Popover/Popover.js +2 -2
- package/dist/components/core/Popover/Popover.types.d.ts +8 -0
- package/dist/components/core/Progress/Progress.d.ts +28 -0
- package/dist/components/core/Progress/Progress.js +114 -0
- package/dist/components/core/Progress/Progress.theme.d.ts +5 -0
- package/dist/components/core/Progress/Progress.theme.js +33 -0
- package/dist/components/core/Progress/Progress.types.d.ts +92 -0
- package/dist/components/core/Progress/index.d.ts +2 -0
- package/dist/components/core/Table/Table.animations.d.ts +5 -16
- package/dist/components/core/Table/Table.animations.js +46 -0
- package/dist/components/core/Table/Table.d.ts +0 -27
- package/dist/components/core/Table/Table.js +58 -156
- package/dist/components/core/Table/Table.theme.js +28 -19
- package/dist/components/core/Table/Table.types.d.ts +95 -8
- package/dist/components/core/Table/Table.utils.d.ts +7 -0
- package/dist/components/core/Table/Table.utils.js +11 -1
- package/dist/components/core/Table/{components/TableActions/TableActions.d.ts → TableActions.d.ts} +3 -3
- package/dist/components/core/Table/{components/TableActions/TableActions.js → TableActions.js} +14 -24
- package/dist/components/core/Table/{components/TableActions/TableActionsMenu.d.ts → TableActionsMenu.d.ts} +1 -1
- package/dist/components/core/Table/{components/TableActions/TableActionsMenu.js → TableActionsMenu.js} +4 -4
- package/dist/components/core/Table/{components/core/TableBody.d.ts → TableBody.d.ts} +1 -1
- package/dist/components/core/Table/{components/core/TableBody.js → TableBody.js} +14 -20
- package/dist/components/core/Table/{components/core/TableCell.d.ts → TableCell.d.ts} +1 -9
- package/dist/components/core/Table/{components/core/TableCell.js → TableCell.js} +5 -13
- package/dist/components/core/Table/TableColumnManager.d.ts +3 -0
- package/dist/components/core/Table/TableColumnManager.js +34 -0
- package/dist/components/core/Table/{components/DeclarativeComponents.d.ts → TableDeclarative.d.ts} +1 -1
- package/dist/components/core/Table/{components/DeclarativeComponents.js → TableDeclarative.js} +6 -56
- package/dist/components/core/Table/TableFilter.d.ts +3 -0
- package/dist/components/core/Table/TableFilter.js +122 -0
- package/dist/components/core/Table/{components/core/TableHeader.d.ts → TableHeader.d.ts} +1 -1
- package/dist/components/core/Table/{components/core/TableHeader.js → TableHeader.js} +15 -29
- package/dist/components/core/Table/TablePagination.d.ts +7 -0
- package/dist/components/core/Table/{components/TablePagination/TablePagination.js → TablePagination.js} +5 -16
- package/dist/components/core/Table/TableRow.d.ts +8 -0
- package/dist/components/core/Table/TableRow.js +45 -0
- package/dist/components/core/Table/TableSelectionHeader.d.ts +7 -0
- package/dist/components/core/Table/{components/TableSelectionHeader/TableSelectionHeader.js → TableSelectionHeader.js} +4 -5
- package/dist/components/core/Table/hooks/index.d.ts +10 -0
- package/dist/components/core/Table/hooks/useTableColumns.d.ts +16 -0
- package/dist/components/core/Table/hooks/useTableColumns.js +67 -0
- package/dist/components/core/Table/hooks/useTableExpansion.d.ts +8 -0
- package/dist/components/core/Table/hooks/useTableExpansion.js +15 -0
- package/dist/components/core/Table/hooks/useTableFilter.d.ts +12 -0
- package/dist/components/core/Table/hooks/useTableFilter.js +37 -0
- package/dist/components/core/Table/hooks/useTablePagination.d.ts +12 -0
- package/dist/components/core/Table/hooks/useTablePagination.js +13 -0
- package/dist/components/core/Table/hooks/useTableSelection.d.ts +17 -0
- package/dist/components/core/Table/hooks/useTableSelection.js +40 -0
- package/dist/components/core/Table/index.d.ts +9 -8
- package/dist/components/core/Table/index.js +7 -5
- package/dist/components/core/Tabs/Tabs.js +2 -2
- package/dist/components/core/Tabs/Tabs.types.d.ts +8 -0
- package/dist/components/core/Tag/Tag.animations.d.ts +3 -0
- package/dist/components/core/Tag/Tag.animations.js +31 -0
- package/dist/components/core/Tag/Tag.d.ts +14 -0
- package/dist/components/core/Tag/Tag.js +45 -0
- package/dist/components/core/Tag/Tag.theme.d.ts +2 -0
- package/dist/components/core/Tag/Tag.theme.js +21 -0
- package/dist/components/core/Tag/Tag.types.d.ts +40 -0
- package/dist/components/core/Tag/index.d.ts +3 -0
- package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
- package/dist/components/core/Tooltip/Tooltip.js +3 -3
- package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
- package/dist/components/core/Tooltip/Tooltip.types.d.ts +17 -0
- package/dist/components/core/index.d.ts +2 -1
- package/dist/components/core/index.js +12 -5
- package/dist/components/effects/CustomCursor/CustomCursor.d.ts +0 -13
- package/dist/components/effects/CustomCursor/CustomCursor.js +26 -2
- package/dist/components/effects/CustomCursor/CustomCursor.theme.js +12 -1
- package/dist/components/effects/CustomCursor/CustomCursor.types.d.ts +14 -1
- package/dist/components/forms/Combobox/Combobox.d.ts +25 -0
- package/dist/components/forms/Combobox/Combobox.js +412 -0
- package/dist/components/forms/Combobox/Combobox.theme.d.ts +6 -0
- package/dist/components/forms/Combobox/Combobox.theme.js +60 -0
- package/dist/components/forms/Combobox/Combobox.types.d.ts +111 -0
- package/dist/components/forms/Combobox/index.d.ts +3 -0
- package/dist/components/forms/FileUpload/FileUpload.js +2 -0
- package/dist/components/forms/Input/Input.js +25 -28
- package/dist/components/forms/Input/inputMasks.d.ts +15 -0
- package/dist/components/forms/Input/inputMasks.js +72 -1
- package/dist/components/forms/InputTag/InputTag.d.ts +40 -0
- package/dist/components/forms/InputTag/InputTag.js +491 -0
- package/dist/components/forms/InputTag/InputTag.theme.d.ts +2 -0
- package/dist/components/forms/InputTag/InputTag.theme.js +16 -0
- package/dist/components/forms/InputTag/InputTag.types.d.ts +107 -0
- package/dist/components/forms/InputTag/index.d.ts +3 -0
- package/dist/components/forms/Select/Select.d.ts +101 -2
- package/dist/components/forms/Select/Select.js +128 -132
- package/dist/components/forms/Select/Select.theme.js +10 -14
- package/dist/components/forms/Select/Select.types.d.ts +6 -2
- package/dist/components/forms/Select/index.d.ts +7 -4
- package/dist/components/forms/Select/useSelectState.d.ts +66 -0
- package/dist/components/forms/Select/useSelectState.js +134 -0
- package/dist/components/forms/SelectExpand/SelectExpand.animations.d.ts +20 -0
- package/dist/components/forms/SelectExpand/SelectExpand.animations.js +74 -0
- package/dist/components/forms/SelectExpand/SelectExpand.d.ts +9 -0
- package/dist/components/forms/SelectExpand/SelectExpand.js +223 -0
- package/dist/components/forms/SelectExpand/SelectExpand.theme.d.ts +5 -0
- package/dist/components/forms/SelectExpand/SelectExpand.theme.js +74 -0
- package/dist/components/forms/SelectExpand/SelectExpand.types.d.ts +126 -0
- package/dist/components/forms/SelectExpand/index.d.ts +4 -0
- package/dist/components/forms/Switch/Switch.js +3 -3
- package/dist/components/forms/Switch/Switch.theme.d.ts +1 -1
- package/dist/components/forms/Switch/Switch.theme.js +2 -2
- package/dist/components/forms/TimePicker/TimePicker.animations.d.ts +0 -46
- package/dist/components/forms/TimePicker/TimePicker.d.ts +15 -6
- package/dist/components/forms/TimePicker/TimePicker.js +285 -124
- package/dist/components/forms/TimePicker/TimePicker.theme.d.ts +1 -1
- package/dist/components/forms/TimePicker/TimePicker.theme.js +39 -22
- package/dist/components/forms/TimePicker/TimePicker.types.d.ts +88 -34
- package/dist/components/forms/TimePicker/TimePickerContent.d.ts +7 -10
- package/dist/components/forms/TimePicker/TimePickerContent.js +149 -16
- package/dist/components/forms/TimePicker/TimePickerTrigger.d.ts +3 -3
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +22 -19
- package/dist/components/forms/TimePicker/WheelColumn.d.ts +14 -0
- package/dist/components/forms/TimePicker/WheelColumn.js +90 -0
- package/dist/components/forms/TimePicker/index.d.ts +4 -1
- package/dist/components/forms/TimePicker/useWheelPicker.d.ts +37 -0
- package/dist/components/forms/TimePicker/useWheelPicker.js +138 -0
- package/dist/components/forms/forms.theme.d.ts +14 -0
- package/dist/components/forms/forms.theme.js +31 -0
- package/dist/components/forms/index.d.ts +9 -3
- package/dist/components/forms/index.js +73 -2
- package/dist/hooks/index.d.ts +0 -4
- package/dist/icons/Icon.d.ts +7 -0
- package/dist/icons/Icon.js +6 -2
- package/dist/index.js +21 -19
- package/dist/styles.css +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/optimisticErrors.js +1 -70
- package/package.json +1 -1
- package/dist/components/ai/EditingIndicator/EditingIndicator.animations.d.ts +0 -31
- package/dist/components/ai/EditingIndicator/EditingIndicator.animations.js +0 -115
- package/dist/components/ai/EditingIndicator/EditingIndicator.d.ts +0 -35
- package/dist/components/ai/EditingIndicator/EditingIndicator.js +0 -94
- package/dist/components/ai/EditingIndicator/EditingIndicator.theme.d.ts +0 -2
- package/dist/components/ai/EditingIndicator/EditingIndicator.theme.js +0 -13
- package/dist/components/ai/EditingIndicator/EditingIndicator.types.d.ts +0 -54
- package/dist/components/ai/EditingIndicator/index.d.ts +0 -9
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.d.ts +0 -3
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.js +0 -126
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.d.ts +0 -2
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.js +0 -8
- package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.types.d.ts +0 -45
- package/dist/components/ai/GenerativeRenderer/index.d.ts +0 -3
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.d.ts +0 -17
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.js +0 -56
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.d.ts +0 -38
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.js +0 -110
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.d.ts +0 -2
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.js +0 -13
- package/dist/components/ai/PresenceIndicator/PresenceIndicator.types.d.ts +0 -53
- package/dist/components/ai/PresenceIndicator/index.d.ts +0 -8
- package/dist/components/ai/PresenceProvider/PresenceContext.d.ts +0 -24
- package/dist/components/ai/PresenceProvider/PresenceContext.js +0 -34
- package/dist/components/ai/PresenceProvider/PresenceProvider.d.ts +0 -32
- package/dist/components/ai/PresenceProvider/PresenceProvider.js +0 -321
- package/dist/components/ai/PresenceProvider/PresenceProvider.types.d.ts +0 -140
- package/dist/components/ai/PresenceProvider/adapters/MockAdapter.d.ts +0 -102
- package/dist/components/ai/PresenceProvider/adapters/MockAdapter.js +0 -331
- package/dist/components/ai/PresenceProvider/adapters/PresenceAdapter.d.ts +0 -93
- package/dist/components/ai/PresenceProvider/adapters/SupabaseAdapter.d.ts +0 -134
- package/dist/components/ai/PresenceProvider/adapters/WebSocketAdapter.d.ts +0 -149
- package/dist/components/ai/PresenceProvider/adapters/index.d.ts +0 -11
- package/dist/components/ai/PresenceProvider/index.d.ts +0 -10
- package/dist/components/ai/PromptSuggestions/PromptSuggestions.d.ts +0 -27
- package/dist/components/ai/PromptSuggestions/PromptSuggestions.js +0 -61
- package/dist/components/ai/PromptSuggestions/PromptSuggestions.types.d.ts +0 -65
- package/dist/components/ai/VersionSlider/VersionSlider.d.ts +0 -3
- package/dist/components/ai/VersionSlider/VersionSlider.js +0 -97
- package/dist/components/ai/VersionSlider/VersionSlider.theme.d.ts +0 -2
- package/dist/components/ai/VersionSlider/VersionSlider.theme.js +0 -18
- package/dist/components/ai/VersionSlider/VersionSlider.types.d.ts +0 -77
- package/dist/components/ai/VersionSlider/index.d.ts +0 -3
- package/dist/components/core/Pill/Pill.animations.js +0 -25
- package/dist/components/core/Pill/Pill.js +0 -145
- package/dist/components/core/Pill/Pill.theme.js +0 -65
- package/dist/components/core/RetryBoundary/RetryBoundary.d.ts +0 -35
- package/dist/components/core/RetryBoundary/RetryBoundary.js +0 -154
- package/dist/components/core/RetryBoundary/RetryBoundary.theme.d.ts +0 -2
- package/dist/components/core/RetryBoundary/RetryBoundary.theme.js +0 -7
- package/dist/components/core/RetryBoundary/RetryBoundary.types.d.ts +0 -51
- package/dist/components/core/RetryBoundary/index.d.ts +0 -3
- package/dist/components/core/Table/components/TableActions/TableActions.types.d.ts +0 -40
- package/dist/components/core/Table/components/TableActions/index.d.ts +0 -3
- package/dist/components/core/Table/components/TableActionsMenu.d.ts +0 -6
- package/dist/components/core/Table/components/TablePagination/TablePagination.d.ts +0 -17
- package/dist/components/core/Table/components/TablePagination/TablePagination.types.d.ts +0 -21
- package/dist/components/core/Table/components/TablePagination/index.d.ts +0 -2
- package/dist/components/core/Table/components/TableSelectionHeader/TableSelectionHeader.d.ts +0 -15
- package/dist/components/core/Table/components/TableSelectionHeader/index.d.ts +0 -3
- package/dist/components/core/Table/components/core/TableRow.d.ts +0 -3
- package/dist/components/core/Table/components/core/TableRow.js +0 -44
- package/dist/components/core/Table/components/core/index.d.ts +0 -4
- package/dist/components/forms/OptimisticForm/OptimisticForm.d.ts +0 -33
- package/dist/components/forms/OptimisticForm/OptimisticForm.js +0 -87
- package/dist/components/forms/OptimisticForm/OptimisticForm.theme.d.ts +0 -2
- package/dist/components/forms/OptimisticForm/OptimisticForm.theme.js +0 -8
- package/dist/components/forms/OptimisticForm/OptimisticForm.types.d.ts +0 -74
- package/dist/components/forms/OptimisticForm/index.d.ts +0 -3
- package/dist/hooks/useOptimisticMutation.d.ts +0 -109
- package/dist/hooks/useOptimisticMutation.js +0 -171
- package/dist/hooks/usePresence.d.ts +0 -88
- package/dist/utils/presenceUtils.d.ts +0 -66
- package/dist/utils/presenceUtils.js +0 -107
|
@@ -21,6 +21,7 @@ export * from "./Metric";
|
|
|
21
21
|
export * from "./Modal";
|
|
22
22
|
export * from "./Pagination";
|
|
23
23
|
export * from "./Popover";
|
|
24
|
+
export * from "./Progress";
|
|
24
25
|
export * from "./ProgressiveBlur";
|
|
25
26
|
export * from "./Segmented";
|
|
26
27
|
export * from "./Skeleton";
|
|
@@ -29,6 +30,7 @@ export * from "./Stepper";
|
|
|
29
30
|
export * from "./Tabs";
|
|
30
31
|
export * from "./Tooltip";
|
|
31
32
|
export * from "./Tree";
|
|
33
|
+
export * from "./Tag";
|
|
32
34
|
export * from "./Alert";
|
|
33
35
|
export * from "./Toast";
|
|
34
36
|
export * from "./Notification";
|
|
@@ -41,5 +43,4 @@ export * from "./DragDrop";
|
|
|
41
43
|
export * from "./Sortable";
|
|
42
44
|
export * from "./NavItem";
|
|
43
45
|
export * from "./Sidebar";
|
|
44
|
-
export * from "./RetryBoundary";
|
|
45
46
|
export * from "./OfflineIndicator";
|
|
@@ -36,6 +36,7 @@ export { Modal } from './Modal/Modal.js';
|
|
|
36
36
|
export { Pagination } from './Pagination/Pagination.js';
|
|
37
37
|
export { Popover } from './Popover/Popover.js';
|
|
38
38
|
export { PopoverContext, usePopoverContext } from './Popover/PopoverContext.js';
|
|
39
|
+
export { Progress } from './Progress/Progress.js';
|
|
39
40
|
export { default as ProgressiveBlur } from './ProgressiveBlur/ProgressiveBlur.js';
|
|
40
41
|
export { Segmented } from './Segmented/Segmented.js';
|
|
41
42
|
export { Skeleton } from './Skeleton/Skeleton.js';
|
|
@@ -50,6 +51,8 @@ export { Tooltip } from './Tooltip/Tooltip.js';
|
|
|
50
51
|
export { baseTooltipVariants, getTooltipVariants, tooltipSpringConfig } from './Tooltip/Tooltip.animations.js';
|
|
51
52
|
export { Tree } from './Tree/Tree.js';
|
|
52
53
|
export { treeTheme } from './Tree/Tree.theme.js';
|
|
54
|
+
export { Tag } from './Tag/Tag.js';
|
|
55
|
+
export { tagTheme } from './Tag/Tag.theme.js';
|
|
53
56
|
export { Alert } from './Alert/Alert.js';
|
|
54
57
|
export { alertTheme } from './Alert/Alert.theme.js';
|
|
55
58
|
export { Toast } from './Toast/Toast.js';
|
|
@@ -79,8 +82,6 @@ export { SidebarNavGroup } from './Sidebar/SidebarNavGroup.js';
|
|
|
79
82
|
export { SidebarSubmenu } from './Sidebar/SidebarSubmenu.js';
|
|
80
83
|
export { SidebarToggle } from './Sidebar/SidebarToggle.js';
|
|
81
84
|
export { useSidebarContext } from './Sidebar/SidebarContext.js';
|
|
82
|
-
export { RetryBoundary } from './RetryBoundary/RetryBoundary.js';
|
|
83
|
-
export { retryBoundaryTheme } from './RetryBoundary/RetryBoundary.theme.js';
|
|
84
85
|
export { OfflineIndicator } from './OfflineIndicator/OfflineIndicator.js';
|
|
85
86
|
export { offlineIndicatorTheme } from './OfflineIndicator/OfflineIndicator.theme.js';
|
|
86
87
|
export { CardHeader } from './Card/CardHeader.js';
|
|
@@ -88,7 +89,13 @@ export { CardTitle } from './Card/CardTitle.js';
|
|
|
88
89
|
export { CardDescription } from './Card/CardDescription.js';
|
|
89
90
|
export { CardContent } from './Card/CardContent.js';
|
|
90
91
|
export { CardFooter } from './Card/CardFooter.js';
|
|
91
|
-
export {
|
|
92
|
-
export {
|
|
93
|
-
export {
|
|
92
|
+
export { useTableColumns } from './Table/hooks/useTableColumns.js';
|
|
93
|
+
export { useTableSelection } from './Table/hooks/useTableSelection.js';
|
|
94
|
+
export { useTableExpansion } from './Table/hooks/useTableExpansion.js';
|
|
95
|
+
export { useTablePagination } from './Table/hooks/useTablePagination.js';
|
|
96
|
+
export { useTableFilter } from './Table/hooks/useTableFilter.js';
|
|
97
|
+
export { TableActions } from './Table/TableActions.js';
|
|
98
|
+
export { TableActionsMenu } from './Table/TableActionsMenu.js';
|
|
99
|
+
export { TablePagination } from './Table/TablePagination.js';
|
|
100
|
+
export { TableFilter } from './Table/TableFilter.js';
|
|
94
101
|
export { AnimatePresence } from 'motion/react';
|
|
@@ -32,17 +32,4 @@ export declare const CustomCursorProvider: React.ForwardRefExoticComponent<Omit<
|
|
|
32
32
|
* ```
|
|
33
33
|
*/
|
|
34
34
|
export declare const CustomCursor: React.ForwardRefExoticComponent<Omit<CustomCursorProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
35
|
-
/**
|
|
36
|
-
* CustomCursorFollow - Smooth following cursor element
|
|
37
|
-
* Follows the main cursor with spring physics for smooth, laggy movement
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```tsx
|
|
41
|
-
* <CustomCursorFollow align="bottom-right" sideOffset={20}>
|
|
42
|
-
* <div className="bg-white rounded-lg shadow-lg p-2">
|
|
43
|
-
* Tooltip content
|
|
44
|
-
* </div>
|
|
45
|
-
* </CustomCursorFollow>
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
35
|
export declare const CustomCursorFollow: React.ForwardRefExoticComponent<Omit<CustomCursorFollowProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { useMotionValue, AnimatePresence, motion, useReducedMotion, useSpring } from 'motion/react';
|
|
3
3
|
import { PaperAirplaneIcon } from '@heroicons/react/20/solid';
|
|
4
4
|
import { cn } from '../../../utils/cn.js';
|
|
5
|
+
import { Avatar } from '../../core/Avatar/Avatar.js';
|
|
5
6
|
import { customCursorVariants, reducedMotionSpringConfig, defaultSpringConfig } from './CustomCursor.animations.js';
|
|
6
7
|
import { customCursorTheme } from './CustomCursor.theme.js';
|
|
7
8
|
|
|
@@ -189,10 +190,24 @@ const calculateOffset = (align, sideOffset, width, height) => {
|
|
|
189
190
|
* </CustomCursorFollow>
|
|
190
191
|
* ```
|
|
191
192
|
*/
|
|
192
|
-
|
|
193
|
+
/** Available colors for random selection in user variant */
|
|
194
|
+
const userVariantColors = [
|
|
195
|
+
'primary',
|
|
196
|
+
'success',
|
|
197
|
+
'warning',
|
|
198
|
+
'danger',
|
|
199
|
+
];
|
|
200
|
+
const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align = 'bottom-right', transition, variant = 'default', avatar, name, color, className, style, ...props }, ref) => {
|
|
193
201
|
const { cursorPos, isActive, cursorRef } = useCustomCursor();
|
|
194
202
|
const cursorFollowRef = React.useRef(null);
|
|
195
203
|
const shouldReduceMotion = useReducedMotion();
|
|
204
|
+
// Select random color for user variant if not provided (stable across renders)
|
|
205
|
+
const resolvedColor = React.useMemo(() => {
|
|
206
|
+
if (color)
|
|
207
|
+
return color;
|
|
208
|
+
const randomIndex = Math.floor(Math.random() * userVariantColors.length);
|
|
209
|
+
return userVariantColors[randomIndex];
|
|
210
|
+
}, [color]);
|
|
196
211
|
React.useImperativeHandle(ref, () => cursorFollowRef.current);
|
|
197
212
|
const x = useMotionValue(0);
|
|
198
213
|
const y = useMotionValue(0);
|
|
@@ -293,7 +308,16 @@ const CustomCursorFollow = React.forwardRef(({ children, sideOffset = 15, align
|
|
|
293
308
|
x,
|
|
294
309
|
y,
|
|
295
310
|
]);
|
|
296
|
-
|
|
311
|
+
// Determine content based on variant
|
|
312
|
+
const renderContent = () => {
|
|
313
|
+
if (variant === 'user') {
|
|
314
|
+
return (React.createElement(React.Fragment, null,
|
|
315
|
+
avatar && React.createElement(Avatar, { src: avatar, alt: name || 'User', size: "xs" }),
|
|
316
|
+
name && (React.createElement("span", { className: "text-white text-xs font-medium whitespace-nowrap" }, name))));
|
|
317
|
+
}
|
|
318
|
+
return children;
|
|
319
|
+
};
|
|
320
|
+
return (React.createElement(AnimatePresence, null, isActive && (React.createElement(motion.div, { ref: cursorFollowRef, "data-slot": "custom-cursor-follow", className: cn(customCursorTheme.baseStyle, customCursorTheme.cursorFollowVariants[variant], variant === 'user' && customCursorTheme.cursorFollowColors[resolvedColor], className), style: { top: springY, left: springX, ...style }, variants: customCursorVariants, initial: "initial", animate: "animate", exit: "exit", role: "presentation", "aria-hidden": "true", ...props }, renderContent()))));
|
|
297
321
|
});
|
|
298
322
|
CustomCursorFollow.displayName = 'CustomCursorFollow';
|
|
299
323
|
|
|
@@ -5,7 +5,18 @@
|
|
|
5
5
|
const customCursorTheme = {
|
|
6
6
|
baseStyle: 'pointer-events-none z-[9999] absolute transform-[translate(-50%,-50%)]',
|
|
7
7
|
cursorStyle: 'transition-transform duration-150',
|
|
8
|
-
|
|
8
|
+
cursorFollowVariants: {
|
|
9
|
+
default: 'rounded-lg bg-white shadow-lg border border-[var(--color-border)] px-3 py-2 text-sm text-[var(--color-text-primary)]',
|
|
10
|
+
user: 'flex items-center gap-2 rounded-full pl-1 pr-3 py-1 shadow-xl',
|
|
11
|
+
},
|
|
12
|
+
cursorFollowColors: {
|
|
13
|
+
neutral: 'bg-[var(--color-background-quaternary)]',
|
|
14
|
+
dark: 'bg-[var(--color-text-primary)]',
|
|
15
|
+
primary: 'bg-[var(--color-primary)]',
|
|
16
|
+
success: 'bg-[var(--color-success)]',
|
|
17
|
+
warning: 'bg-[var(--color-warning)]',
|
|
18
|
+
danger: 'bg-[var(--color-danger)]',
|
|
19
|
+
},
|
|
9
20
|
sizes: {
|
|
10
21
|
sm: 'w-5 h-5',
|
|
11
22
|
md: 'w-7 h-7',
|
|
@@ -20,6 +20,10 @@ export type CustomCursorVariant = 'default' | 'glass';
|
|
|
20
20
|
* Shape variants for the custom cursor
|
|
21
21
|
*/
|
|
22
22
|
export type CustomCursorShape = 'circle' | 'arrow';
|
|
23
|
+
/**
|
|
24
|
+
* Variant for CustomCursorFollow component
|
|
25
|
+
*/
|
|
26
|
+
export type CustomCursorFollowVariant = 'default' | 'user';
|
|
23
27
|
/**
|
|
24
28
|
* Context type for CustomCursor state management
|
|
25
29
|
*/
|
|
@@ -56,11 +60,18 @@ export interface CustomCursorProps extends HTMLMotionProps<'div'> {
|
|
|
56
60
|
* Props for CustomCursorFollow component
|
|
57
61
|
*/
|
|
58
62
|
export interface CustomCursorFollowProps extends HTMLMotionProps<'div'> {
|
|
59
|
-
children
|
|
63
|
+
children?: React.ReactNode;
|
|
60
64
|
sideOffset?: number;
|
|
61
65
|
align?: AlignType;
|
|
62
66
|
transition?: SpringOptions;
|
|
67
|
+
variant?: CustomCursorFollowVariant;
|
|
63
68
|
className?: string;
|
|
69
|
+
/** Avatar image URL (used with variant="user") */
|
|
70
|
+
avatar?: string;
|
|
71
|
+
/** User name to display (used with variant="user") */
|
|
72
|
+
name?: string;
|
|
73
|
+
/** Color for the user pill (used with variant="user"). If not provided, a random color is selected. */
|
|
74
|
+
color?: CustomCursorColor;
|
|
64
75
|
}
|
|
65
76
|
/**
|
|
66
77
|
* Theme configuration for CustomCursor
|
|
@@ -69,6 +80,8 @@ export interface CustomCursorTheme {
|
|
|
69
80
|
baseStyle: string;
|
|
70
81
|
cursorStyle: string;
|
|
71
82
|
cursorFollowStyle: string;
|
|
83
|
+
cursorFollowVariants: Record<CustomCursorFollowVariant, string>;
|
|
84
|
+
cursorFollowColors: Record<CustomCursorColor, string>;
|
|
72
85
|
sizes: Record<CustomCursorSize, string>;
|
|
73
86
|
colors: Record<CustomCursorColor, string>;
|
|
74
87
|
variants: Record<CustomCursorVariant, string>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ComboboxProps } from "./Combobox.types";
|
|
3
|
+
/**
|
|
4
|
+
* Combobox Component
|
|
5
|
+
*
|
|
6
|
+
* An autocomplete input where the input IS the trigger.
|
|
7
|
+
* Type directly to filter options. Built on Select primitives.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <Combobox
|
|
12
|
+
* options={[
|
|
13
|
+
* { id: "1", label: "Apple", value: "apple" },
|
|
14
|
+
* { id: "2", label: "Banana", value: "banana" },
|
|
15
|
+
* ]}
|
|
16
|
+
* value={selected}
|
|
17
|
+
* onChange={setSelected}
|
|
18
|
+
* placeholder="Search fruits..."
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const Combobox: {
|
|
23
|
+
<T extends string | number = string>({ options, value, onChange, placeholder, label, helperText, size, state, clearable, iconStart, openOnFocus, filterFn, emptyMessage, creatable, onCreateOption, createLabel, required, name, className, wrapperClassName, inputClassName, dropdownClassName, theme: themeOverrides, portal, placement, offset, id, ...props }: ComboboxProps<T>): React.JSX.Element;
|
|
24
|
+
displayName: string;
|
|
25
|
+
};
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import React__default, { useId, useRef, useEffect, useCallback } from 'react';
|
|
2
|
+
import { AnimatePresence, motion } from 'motion/react';
|
|
3
|
+
import { createPortal } from 'react-dom';
|
|
4
|
+
import { XMarkIcon, PlusIcon } from '@heroicons/react/24/outline';
|
|
5
|
+
import { comboboxTheme } from './Combobox.theme.js';
|
|
6
|
+
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
7
|
+
import { createDropdownAnimations } from '../Select/Select.animations.js';
|
|
8
|
+
import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
|
|
9
|
+
import { cn } from '../../../utils/cn.js';
|
|
10
|
+
import { SelectProvider, useSelectContext } from '../Select/Select.js';
|
|
11
|
+
import '../Select/Select.theme.js';
|
|
12
|
+
import { useSelectState } from '../Select/useSelectState.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Hook to detect dark mode state from document
|
|
16
|
+
*/
|
|
17
|
+
const useDarkMode = () => {
|
|
18
|
+
const [isDark, setIsDark] = React__default.useState(false);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (typeof document === "undefined")
|
|
21
|
+
return;
|
|
22
|
+
const checkDarkMode = () => {
|
|
23
|
+
const hasDarkClass = document.documentElement.classList.contains("dark") ||
|
|
24
|
+
document.body.classList.contains("dark") ||
|
|
25
|
+
document.querySelector(".dark") !== null;
|
|
26
|
+
setIsDark(hasDarkClass);
|
|
27
|
+
};
|
|
28
|
+
checkDarkMode();
|
|
29
|
+
const observer = new MutationObserver(checkDarkMode);
|
|
30
|
+
observer.observe(document.documentElement, {
|
|
31
|
+
attributes: true,
|
|
32
|
+
attributeFilter: ["class"],
|
|
33
|
+
});
|
|
34
|
+
observer.observe(document.body, {
|
|
35
|
+
attributes: true,
|
|
36
|
+
attributeFilter: ["class"],
|
|
37
|
+
});
|
|
38
|
+
return () => observer.disconnect();
|
|
39
|
+
}, []);
|
|
40
|
+
return isDark;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Default filter function for options
|
|
44
|
+
*/
|
|
45
|
+
const defaultFilterFn = (option, inputValue) => {
|
|
46
|
+
return option.label.toLowerCase().includes(inputValue.toLowerCase());
|
|
47
|
+
};
|
|
48
|
+
const ComboboxOptions = ({ isOpen, onClose, triggerRef, portal, placement, offset, emptyMessage, className, }) => {
|
|
49
|
+
var _a;
|
|
50
|
+
const { filteredOptions, highlightedIndex, setHighlightedIndex, selectedValue, selectOption, optionsRef, theme, } = useSelectContext();
|
|
51
|
+
const isDarkMode = useDarkMode();
|
|
52
|
+
// Use enhanced dropdown positioning hook
|
|
53
|
+
const triggerWidth = ((_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width) || 0;
|
|
54
|
+
const { position, cssVariables, contentRef, isFlipped } = useSelectPortal({
|
|
55
|
+
triggerRef,
|
|
56
|
+
isOpen,
|
|
57
|
+
placement,
|
|
58
|
+
offset,
|
|
59
|
+
estimatedWidth: triggerWidth,
|
|
60
|
+
});
|
|
61
|
+
const animations = createDropdownAnimations(isFlipped);
|
|
62
|
+
// Combine refs
|
|
63
|
+
const combinedRef = useCallback((el) => {
|
|
64
|
+
if (optionsRef &&
|
|
65
|
+
typeof optionsRef === "object" &&
|
|
66
|
+
"current" in optionsRef) {
|
|
67
|
+
optionsRef.current =
|
|
68
|
+
el;
|
|
69
|
+
}
|
|
70
|
+
if (contentRef &&
|
|
71
|
+
typeof contentRef === "object" &&
|
|
72
|
+
"current" in contentRef) {
|
|
73
|
+
contentRef.current = el;
|
|
74
|
+
}
|
|
75
|
+
}, [optionsRef, contentRef]);
|
|
76
|
+
// Handle click outside
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (!isOpen)
|
|
79
|
+
return;
|
|
80
|
+
const handleClickOutside = (event) => {
|
|
81
|
+
const currentContentRef = portal
|
|
82
|
+
? contentRef.current
|
|
83
|
+
: optionsRef.current;
|
|
84
|
+
if (currentContentRef &&
|
|
85
|
+
!currentContentRef.contains(event.target) &&
|
|
86
|
+
triggerRef.current &&
|
|
87
|
+
!triggerRef.current.contains(event.target)) {
|
|
88
|
+
onClose();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
92
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
93
|
+
}, [isOpen, onClose, portal, contentRef, optionsRef, triggerRef]);
|
|
94
|
+
// Theme can come from Select's theme (optionsContainerStyle) or Combobox's theme (dropdownStyle)
|
|
95
|
+
const dropdownStyle = theme.dropdownStyle ||
|
|
96
|
+
theme.optionsContainerStyle ||
|
|
97
|
+
comboboxTheme.dropdownStyle;
|
|
98
|
+
const optionStyle = theme.optionStyle || comboboxTheme.optionStyle;
|
|
99
|
+
const selectedOptionStyle = theme.selectedOptionStyle || comboboxTheme.selectedOptionStyle;
|
|
100
|
+
const highlightedOptionStyle = theme.highlightedOptionStyle || comboboxTheme.highlightedOptionStyle;
|
|
101
|
+
const disabledOptionStyle = theme.disabledOptionStyle || comboboxTheme.disabledOptionStyle;
|
|
102
|
+
const createOptionStyleTheme = theme.createOptionStyle || comboboxTheme.createOptionStyle;
|
|
103
|
+
const emptyMessageStyle = comboboxTheme.emptyMessageStyle;
|
|
104
|
+
const optionsContent = (React__default.createElement(AnimatePresence, { mode: "wait" }, isOpen && (React__default.createElement(motion.div, { ref: combinedRef, role: "listbox", className: cn(dropdownStyle, className), style: {
|
|
105
|
+
...cssVariables,
|
|
106
|
+
overscrollBehavior: "contain",
|
|
107
|
+
...(portal
|
|
108
|
+
? {
|
|
109
|
+
top: `${position.top}px`,
|
|
110
|
+
left: `${position.left}px`,
|
|
111
|
+
width: `${position.width}px`,
|
|
112
|
+
}
|
|
113
|
+
: {}),
|
|
114
|
+
}, tabIndex: -1, variants: animations, initial: "initial", animate: "visible", exit: "exit" }, filteredOptions.length === 0 ? (React__default.createElement("div", { className: emptyMessageStyle }, emptyMessage)) : (filteredOptions.map((option, index) => {
|
|
115
|
+
const isSelected = option.value === selectedValue;
|
|
116
|
+
const isHighlighted = index === highlightedIndex;
|
|
117
|
+
const isCreateOption = option.id === "__create__";
|
|
118
|
+
return (React__default.createElement("div", { key: option.id, role: "option", "aria-selected": isSelected, "aria-disabled": option.disabled, "data-option-index": index, className: cn(optionStyle, isSelected && selectedOptionStyle, isHighlighted && highlightedOptionStyle, option.disabled && disabledOptionStyle, isCreateOption && createOptionStyleTheme), onMouseEnter: () => !option.disabled && setHighlightedIndex(index), onClick: () => {
|
|
119
|
+
if (!option.disabled) {
|
|
120
|
+
selectOption(option.value, isCreateOption);
|
|
121
|
+
onClose();
|
|
122
|
+
}
|
|
123
|
+
} }, isCreateOption ? (React__default.createElement("span", { className: "flex items-center gap-1" },
|
|
124
|
+
React__default.createElement(PlusIcon, { className: "size-4 shrink-0", strokeWidth: 2 }),
|
|
125
|
+
React__default.createElement("span", { className: "block truncate" }, option.label))) : (React__default.createElement("span", { className: "block truncate" }, option.label))));
|
|
126
|
+
}))))));
|
|
127
|
+
if (portal && typeof document !== "undefined") {
|
|
128
|
+
return createPortal(React__default.createElement("div", { className: isDarkMode ? "dark" : undefined }, optionsContent), document.body);
|
|
129
|
+
}
|
|
130
|
+
return optionsContent;
|
|
131
|
+
};
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Main Combobox Component
|
|
134
|
+
// ============================================================================
|
|
135
|
+
/**
|
|
136
|
+
* Combobox Component
|
|
137
|
+
*
|
|
138
|
+
* An autocomplete input where the input IS the trigger.
|
|
139
|
+
* Type directly to filter options. Built on Select primitives.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* <Combobox
|
|
144
|
+
* options={[
|
|
145
|
+
* { id: "1", label: "Apple", value: "apple" },
|
|
146
|
+
* { id: "2", label: "Banana", value: "banana" },
|
|
147
|
+
* ]}
|
|
148
|
+
* value={selected}
|
|
149
|
+
* onChange={setSelected}
|
|
150
|
+
* placeholder="Search fruits..."
|
|
151
|
+
* />
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
const Combobox = ({ options, value, onChange, placeholder = "Search...", label, helperText, size = "md", state = "default", clearable = true, iconStart, openOnFocus = true, filterFn = defaultFilterFn, emptyMessage = "No results found", creatable = false, onCreateOption, createLabel, required = false, name, className, wrapperClassName, inputClassName, dropdownClassName, theme: themeOverrides, portal = true, placement = "bottom-start", offset = 8, id, ...props }) => {
|
|
155
|
+
var _a;
|
|
156
|
+
// Merge theme
|
|
157
|
+
const theme = { ...comboboxTheme, ...(themeOverrides || {}) };
|
|
158
|
+
// Generate unique ID
|
|
159
|
+
const generatedId = useId();
|
|
160
|
+
const comboboxId = id || `combobox-${generatedId}`;
|
|
161
|
+
const listboxId = `${comboboxId}-listbox`;
|
|
162
|
+
// Refs
|
|
163
|
+
const inputRef = useRef(null);
|
|
164
|
+
const wrapperRef = useRef(null);
|
|
165
|
+
const justSelectedRef = useRef(false);
|
|
166
|
+
// Convert ComboboxOption to SelectOption format
|
|
167
|
+
const selectOptions = options.map((opt) => ({
|
|
168
|
+
id: opt.id,
|
|
169
|
+
label: opt.label,
|
|
170
|
+
value: opt.value,
|
|
171
|
+
disabled: opt.disabled,
|
|
172
|
+
}));
|
|
173
|
+
// Custom filter wrapper - filter options before passing to useSelectState
|
|
174
|
+
// This allows us to use the custom filterFn prop
|
|
175
|
+
selectOptions.filter((opt) => {
|
|
176
|
+
// If there's no search value in the internal state yet, return all
|
|
177
|
+
// We'll handle filtering via searchValue from selectState
|
|
178
|
+
return true; // Let useSelectState handle filtering
|
|
179
|
+
});
|
|
180
|
+
// Use the shared select state hook
|
|
181
|
+
const selectState = useSelectState({
|
|
182
|
+
options: selectOptions,
|
|
183
|
+
value,
|
|
184
|
+
onChange: (newValue) => {
|
|
185
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
186
|
+
},
|
|
187
|
+
searchable: true, // Combobox is always searchable
|
|
188
|
+
creatable,
|
|
189
|
+
onCreateOption,
|
|
190
|
+
createLabel,
|
|
191
|
+
});
|
|
192
|
+
const { isOpen, setIsOpen, searchValue, setSearchValue, highlightedIndex, setHighlightedIndex, filteredOptions: baseFilteredOptions, selectedOption, selectOption, } = selectState;
|
|
193
|
+
// Apply custom filter function if provided (override the default filtering)
|
|
194
|
+
const customFilteredOptions = React__default.useMemo(() => {
|
|
195
|
+
if (!searchValue)
|
|
196
|
+
return baseFilteredOptions;
|
|
197
|
+
// Re-filter using custom filterFn
|
|
198
|
+
const refiltered = selectOptions.filter((option) => filterFn(option, searchValue));
|
|
199
|
+
// Check if we should show create option
|
|
200
|
+
const shouldShowCreate = creatable &&
|
|
201
|
+
searchValue.trim() !== "" &&
|
|
202
|
+
!refiltered.some((option) => option.label.toLowerCase() === searchValue.toLowerCase());
|
|
203
|
+
if (shouldShowCreate) {
|
|
204
|
+
const createOptionLabel = typeof createLabel === "function"
|
|
205
|
+
? createLabel(searchValue)
|
|
206
|
+
: createLabel || `Create "${searchValue}"`;
|
|
207
|
+
return [
|
|
208
|
+
{
|
|
209
|
+
id: "__create__",
|
|
210
|
+
label: createOptionLabel,
|
|
211
|
+
value: searchValue,
|
|
212
|
+
},
|
|
213
|
+
...refiltered,
|
|
214
|
+
];
|
|
215
|
+
}
|
|
216
|
+
return refiltered;
|
|
217
|
+
}, [
|
|
218
|
+
searchValue,
|
|
219
|
+
selectOptions,
|
|
220
|
+
filterFn,
|
|
221
|
+
creatable,
|
|
222
|
+
createLabel,
|
|
223
|
+
baseFilteredOptions,
|
|
224
|
+
]);
|
|
225
|
+
// Derived state
|
|
226
|
+
const isDisabled = state === "disabled";
|
|
227
|
+
const isInvalid = state === "invalid";
|
|
228
|
+
// Sync input value with selected value when closed
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
if (!isOpen && selectedOption) {
|
|
231
|
+
setSearchValue(selectedOption.label);
|
|
232
|
+
}
|
|
233
|
+
else if (!isOpen && !value) {
|
|
234
|
+
setSearchValue("");
|
|
235
|
+
}
|
|
236
|
+
}, [isOpen, selectedOption, value, setSearchValue]);
|
|
237
|
+
// Reset highlighted index when options change
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
setHighlightedIndex(-1);
|
|
240
|
+
}, [customFilteredOptions.length, searchValue, setHighlightedIndex]);
|
|
241
|
+
// Handle clear
|
|
242
|
+
const handleClear = useCallback((e) => {
|
|
243
|
+
var _a;
|
|
244
|
+
e.stopPropagation();
|
|
245
|
+
e.preventDefault();
|
|
246
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
|
|
247
|
+
setSearchValue("");
|
|
248
|
+
setIsOpen(false);
|
|
249
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
250
|
+
}, [onChange, setSearchValue, setIsOpen]);
|
|
251
|
+
// Handle input change
|
|
252
|
+
const handleInputChange = (e) => {
|
|
253
|
+
const newValue = e.target.value;
|
|
254
|
+
setSearchValue(newValue);
|
|
255
|
+
// Open dropdown when typing
|
|
256
|
+
if (!isOpen && newValue) {
|
|
257
|
+
setIsOpen(true);
|
|
258
|
+
}
|
|
259
|
+
// If input is cleared, clear the value
|
|
260
|
+
if (!newValue && value !== undefined) {
|
|
261
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
// Handle input focus
|
|
265
|
+
const handleInputFocus = () => {
|
|
266
|
+
// Skip reopening if we just selected an option
|
|
267
|
+
if (justSelectedRef.current) {
|
|
268
|
+
justSelectedRef.current = false;
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (openOnFocus && !isDisabled) {
|
|
272
|
+
setIsOpen(true);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
// Handle option selection
|
|
276
|
+
const handleSelectOption = useCallback((optionValue, isCreateAction = false) => {
|
|
277
|
+
var _a;
|
|
278
|
+
selectOption(optionValue, isCreateAction);
|
|
279
|
+
// Find the selected option to get its label
|
|
280
|
+
const selected = customFilteredOptions.find((opt) => opt.value === optionValue);
|
|
281
|
+
if (selected) {
|
|
282
|
+
setSearchValue(selected.label);
|
|
283
|
+
}
|
|
284
|
+
setIsOpen(false);
|
|
285
|
+
setHighlightedIndex(-1);
|
|
286
|
+
// Prevent reopening on focus after selection
|
|
287
|
+
justSelectedRef.current = true;
|
|
288
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
289
|
+
}, [
|
|
290
|
+
selectOption,
|
|
291
|
+
customFilteredOptions,
|
|
292
|
+
setSearchValue,
|
|
293
|
+
setIsOpen,
|
|
294
|
+
setHighlightedIndex,
|
|
295
|
+
]);
|
|
296
|
+
// Handle keyboard navigation
|
|
297
|
+
const handleKeyDown = (event) => {
|
|
298
|
+
if (isDisabled)
|
|
299
|
+
return;
|
|
300
|
+
switch (event.key) {
|
|
301
|
+
case "ArrowDown":
|
|
302
|
+
event.preventDefault();
|
|
303
|
+
if (!isOpen) {
|
|
304
|
+
setIsOpen(true);
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
setHighlightedIndex((prev) => prev >= customFilteredOptions.length - 1 ? 0 : prev + 1);
|
|
308
|
+
}
|
|
309
|
+
break;
|
|
310
|
+
case "ArrowUp":
|
|
311
|
+
event.preventDefault();
|
|
312
|
+
if (!isOpen) {
|
|
313
|
+
setIsOpen(true);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
setHighlightedIndex((prev) => prev <= 0 ? customFilteredOptions.length - 1 : prev - 1);
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
case "Enter":
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
if (isOpen &&
|
|
322
|
+
highlightedIndex >= 0 &&
|
|
323
|
+
highlightedIndex < customFilteredOptions.length) {
|
|
324
|
+
const highlightedOption = customFilteredOptions[highlightedIndex];
|
|
325
|
+
const isCreateOption = highlightedOption.id === "__create__";
|
|
326
|
+
handleSelectOption(highlightedOption.value, isCreateOption);
|
|
327
|
+
}
|
|
328
|
+
else if (!isOpen) {
|
|
329
|
+
setIsOpen(true);
|
|
330
|
+
}
|
|
331
|
+
break;
|
|
332
|
+
case "Escape":
|
|
333
|
+
event.preventDefault();
|
|
334
|
+
if (isOpen) {
|
|
335
|
+
setIsOpen(false);
|
|
336
|
+
// Restore selected value
|
|
337
|
+
if (selectedOption) {
|
|
338
|
+
setSearchValue(selectedOption.label);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
setSearchValue("");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
break;
|
|
345
|
+
case "Tab":
|
|
346
|
+
if (isOpen) {
|
|
347
|
+
setIsOpen(false);
|
|
348
|
+
// Restore selected value
|
|
349
|
+
if (selectedOption) {
|
|
350
|
+
setSearchValue(selectedOption.label);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
setSearchValue("");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
// Scroll highlighted option into view
|
|
360
|
+
useEffect(() => {
|
|
361
|
+
if (highlightedIndex >= 0 && isOpen) {
|
|
362
|
+
const optionElement = document.querySelector(`[data-option-index="${highlightedIndex}"]`);
|
|
363
|
+
if (optionElement) {
|
|
364
|
+
optionElement.scrollIntoView({ block: "nearest" });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}, [highlightedIndex, isOpen]);
|
|
368
|
+
// Theme classes
|
|
369
|
+
const containerClasses = theme.containerStyle;
|
|
370
|
+
const inputGroupClasses = theme.inputGroupStyle;
|
|
371
|
+
const inputClasses = theme.inputStyle;
|
|
372
|
+
const sizeClasses = theme.sizes[size];
|
|
373
|
+
const stateClasses = theme.states[state];
|
|
374
|
+
const helperTextClasses = theme.helperTextStyle;
|
|
375
|
+
const helperTextStateClasses = ((_a = theme.helperTextStates) === null || _a === void 0 ? void 0 : _a[state]) || "";
|
|
376
|
+
// State class for CSS selectors
|
|
377
|
+
const stateClass = isInvalid
|
|
378
|
+
? "state-invalid"
|
|
379
|
+
: isDisabled
|
|
380
|
+
? "state-disabled"
|
|
381
|
+
: "state-default";
|
|
382
|
+
// Show clear button
|
|
383
|
+
const showClearButton = clearable && value !== undefined && !isDisabled;
|
|
384
|
+
// Icon padding
|
|
385
|
+
const hasLeftIcon = Boolean(iconStart);
|
|
386
|
+
const iconStartPadding = hasLeftIcon ? theme.iconPadding.left : "";
|
|
387
|
+
// Create a modified selectState for the provider with our custom filtered options
|
|
388
|
+
const modifiedSelectState = {
|
|
389
|
+
...selectState,
|
|
390
|
+
filteredOptions: customFilteredOptions,
|
|
391
|
+
selectOption: handleSelectOption,
|
|
392
|
+
};
|
|
393
|
+
return (React__default.createElement(SelectProvider, { selectState: modifiedSelectState, size: size, componentState: state, theme: theme, searchable: true, enableTypeahead: false },
|
|
394
|
+
React__default.createElement("div", { className: cn("relative", containerClasses, stateClass, wrapperClassName), ...props },
|
|
395
|
+
label && (React__default.createElement(FormLabel, { htmlFor: comboboxId, required: required }, label)),
|
|
396
|
+
React__default.createElement("div", { ref: wrapperRef, className: theme.wrapperStyle },
|
|
397
|
+
React__default.createElement("div", { className: cn(inputGroupClasses, stateClasses, className) },
|
|
398
|
+
React__default.createElement("div", { className: "relative flex-1" },
|
|
399
|
+
React__default.createElement("input", { ref: inputRef, id: comboboxId, type: "text", role: "combobox", "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 &&
|
|
400
|
+
customFilteredOptions[highlightedIndex]
|
|
401
|
+
? `${comboboxId}-option-${customFilteredOptions[highlightedIndex].id}`
|
|
402
|
+
: undefined, "aria-autocomplete": "list", "aria-invalid": isInvalid, autoComplete: "off", className: cn(inputClasses, sizeClasses, iconStartPadding, showClearButton && "pr-8", inputClassName), value: searchValue, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: isDisabled, required: required }),
|
|
403
|
+
hasLeftIcon && (React__default.createElement("div", { className: theme.iconStartStyle }, iconStart)),
|
|
404
|
+
showClearButton && (React__default.createElement("button", { type: "button", className: theme.clearButtonStyle, onClick: handleClear, "aria-label": "Clear selection", tabIndex: -1 },
|
|
405
|
+
React__default.createElement(XMarkIcon, { className: theme.clearIconStyle }))))),
|
|
406
|
+
React__default.createElement(ComboboxOptions, { isOpen: isOpen, onClose: () => setIsOpen(false), triggerRef: wrapperRef, portal: portal, placement: placement, offset: offset, emptyMessage: emptyMessage, className: dropdownClassName })),
|
|
407
|
+
helperText && (React__default.createElement("p", { className: cn(helperTextClasses, helperTextStateClasses) }, helperText)),
|
|
408
|
+
name && (React__default.createElement("input", { type: "hidden", name: name, value: value !== undefined ? String(value) : "" })))));
|
|
409
|
+
};
|
|
410
|
+
Combobox.displayName = "Combobox";
|
|
411
|
+
|
|
412
|
+
export { Combobox };
|