entangle-ui 0.8.2 → 0.9.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/dist/esm/assets/src/components/controls/Combobox/Combobox.css.ts.vanilla-B7B5ttkq.css +210 -0
- package/dist/esm/assets/src/components/controls/FileUploader/FileUploader.css.ts.vanilla-T4nRiI7s.css +194 -0
- package/dist/esm/assets/src/components/controls/MultiSelect/MultiSelect.css.ts.vanilla-CdYayqaF.css +311 -0
- package/dist/esm/assets/src/components/controls/TagInput/TagInput.css.ts.vanilla-hnkMOPp1.css +141 -0
- package/dist/esm/assets/src/components/data/DataTable/DataTable.css.ts.vanilla-CmRgtjIW.css +231 -0
- package/dist/esm/assets/src/components/feedback/Alert/{Alert.css.ts.vanilla-CRAI-xHx.css → Alert.css.ts.vanilla-CfCDsIEg.css} +2 -0
- package/dist/esm/assets/src/components/feedback/CommandPalette/CommandPalette.css.ts.vanilla-DGdrLKYZ.css +160 -0
- package/dist/esm/assets/src/components/feedback/Drawer/Drawer.css.ts.vanilla-CLPTOUrA.css +247 -0
- package/dist/esm/assets/src/components/feedback/Skeleton/SkeletonLayout.css.ts.vanilla-Db7bpqiI.css +75 -0
- package/dist/esm/assets/src/components/feedback/Stat/Stat.css.ts.vanilla-GBk3JAMB.css +69 -0
- package/dist/esm/assets/src/components/layout/Card/Card.css.ts.vanilla-Ducn1gUX.css +124 -0
- package/dist/esm/assets/src/components/navigation/Pagination/Pagination.css.ts.vanilla-CmlFyyjh.css +103 -0
- package/dist/esm/assets/src/components/primitives/HoverCard/HoverCard.css.ts.vanilla-BYT0qbLp.css +41 -0
- package/dist/esm/components/Icons/CloudUploadIcon.js +24 -0
- package/dist/esm/components/Icons/CloudUploadIcon.js.map +1 -0
- package/dist/esm/components/Icons/ExternalLinkIcon.js +26 -0
- package/dist/esm/components/Icons/ExternalLinkIcon.js.map +1 -0
- package/dist/esm/components/Icons/FirstIcon.js +23 -0
- package/dist/esm/components/Icons/FirstIcon.js.map +1 -0
- package/dist/esm/components/Icons/LastIcon.js +23 -0
- package/dist/esm/components/Icons/LastIcon.js.map +1 -0
- package/dist/esm/components/Icons/UnlinkIcon.js +26 -0
- package/dist/esm/components/Icons/UnlinkIcon.js.map +1 -0
- package/dist/esm/components/controls/Combobox/Combobox.css.js +20 -0
- package/dist/esm/components/controls/Combobox/Combobox.css.js.map +1 -0
- package/dist/esm/components/controls/Combobox/Combobox.js +354 -0
- package/dist/esm/components/controls/Combobox/Combobox.js.map +1 -0
- package/dist/esm/components/controls/FileUploader/FileUploader.css.js +20 -0
- package/dist/esm/components/controls/FileUploader/FileUploader.css.js.map +1 -0
- package/dist/esm/components/controls/FileUploader/FileUploader.js +264 -0
- package/dist/esm/components/controls/FileUploader/FileUploader.js.map +1 -0
- package/dist/esm/components/controls/MultiSelect/MultiSelect.css.js +23 -0
- package/dist/esm/components/controls/MultiSelect/MultiSelect.css.js.map +1 -0
- package/dist/esm/components/controls/MultiSelect/MultiSelect.js +269 -0
- package/dist/esm/components/controls/MultiSelect/MultiSelect.js.map +1 -0
- package/dist/esm/components/controls/Select/Select.js +5 -4
- package/dist/esm/components/controls/Select/Select.js.map +1 -1
- package/dist/esm/components/controls/TagInput/TagInput.css.js +12 -0
- package/dist/esm/components/controls/TagInput/TagInput.css.js.map +1 -0
- package/dist/esm/components/controls/TagInput/TagInput.js +189 -0
- package/dist/esm/components/controls/TagInput/TagInput.js.map +1 -0
- package/dist/esm/components/controls/TreeView/TreeNode.js +87 -1
- package/dist/esm/components/controls/TreeView/TreeNode.js.map +1 -1
- package/dist/esm/components/controls/VectorInput/VectorInput.js +87 -4
- package/dist/esm/components/controls/VectorInput/VectorInput.js.map +1 -1
- package/dist/esm/components/data/DataTable/DataTable.css.js +25 -0
- package/dist/esm/components/data/DataTable/DataTable.css.js.map +1 -0
- package/dist/esm/components/data/DataTable/DataTable.js +502 -0
- package/dist/esm/components/data/DataTable/DataTable.js.map +1 -0
- package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js +87 -5
- package/dist/esm/components/editor/ChatPanel/ChatCodeBlock.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatInput.js +87 -5
- package/dist/esm/components/editor/ChatPanel/ChatInput.js.map +1 -1
- package/dist/esm/components/editor/ChatPanel/ChatMessage.js +87 -2
- package/dist/esm/components/editor/ChatPanel/ChatMessage.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertyRow.js +87 -3
- package/dist/esm/components/editor/PropertyInspector/PropertyRow.js.map +1 -1
- package/dist/esm/components/editor/PropertyInspector/PropertySection.js +87 -3
- package/dist/esm/components/editor/PropertyInspector/PropertySection.js.map +1 -1
- package/dist/esm/components/feedback/Alert/Alert.css.js +1 -1
- package/dist/esm/components/feedback/Alert/Alert.js +3 -2
- package/dist/esm/components/feedback/Alert/Alert.js.map +1 -1
- package/dist/esm/components/feedback/CommandPalette/CommandPalette.css.js +20 -0
- package/dist/esm/components/feedback/CommandPalette/CommandPalette.css.js.map +1 -0
- package/dist/esm/components/feedback/CommandPalette/CommandPalette.js +261 -0
- package/dist/esm/components/feedback/CommandPalette/CommandPalette.js.map +1 -0
- package/dist/esm/components/feedback/CommandPalette/fuzzySearch.js +86 -0
- package/dist/esm/components/feedback/CommandPalette/fuzzySearch.js.map +1 -0
- package/dist/esm/components/feedback/CommandPalette/useRecentItems.js +63 -0
- package/dist/esm/components/feedback/CommandPalette/useRecentItems.js.map +1 -0
- package/dist/esm/components/feedback/Dialog/DialogHeader.js +2 -1
- package/dist/esm/components/feedback/Dialog/DialogHeader.js.map +1 -1
- package/dist/esm/components/feedback/Drawer/Drawer.css.js +17 -0
- package/dist/esm/components/feedback/Drawer/Drawer.css.js.map +1 -0
- package/dist/esm/components/feedback/Drawer/Drawer.js +120 -0
- package/dist/esm/components/feedback/Drawer/Drawer.js.map +1 -0
- package/dist/esm/components/feedback/Drawer/useDrawerAnimation.js +74 -0
- package/dist/esm/components/feedback/Drawer/useDrawerAnimation.js.map +1 -0
- package/dist/esm/components/feedback/Skeleton/SkeletonLayout.css.js +18 -0
- package/dist/esm/components/feedback/Skeleton/SkeletonLayout.css.js.map +1 -0
- package/dist/esm/components/feedback/Skeleton/SkeletonLayout.js +95 -0
- package/dist/esm/components/feedback/Skeleton/SkeletonLayout.js.map +1 -0
- package/dist/esm/components/feedback/Stat/Stat.css.js +15 -0
- package/dist/esm/components/feedback/Stat/Stat.css.js.map +1 -0
- package/dist/esm/components/feedback/Stat/Stat.js +55 -0
- package/dist/esm/components/feedback/Stat/Stat.js.map +1 -0
- package/dist/esm/components/feedback/Toast/ToastItem.js +12 -15
- package/dist/esm/components/feedback/Toast/ToastItem.js.map +1 -1
- package/dist/esm/components/layout/Accordion/Accordion.js +2 -1
- package/dist/esm/components/layout/Accordion/Accordion.js.map +1 -1
- package/dist/esm/components/layout/Accordion/AccordionTrigger.js +2 -3
- package/dist/esm/components/layout/Accordion/AccordionTrigger.js.map +1 -1
- package/dist/esm/components/layout/Card/Card.css.js +18 -0
- package/dist/esm/components/layout/Card/Card.css.js.map +1 -0
- package/dist/esm/components/layout/Card/Card.js +66 -0
- package/dist/esm/components/layout/Card/Card.js.map +1 -0
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbEllipsis.js +1 -0
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbEllipsis.js.map +1 -1
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbItem.js +1 -0
- package/dist/esm/components/navigation/Breadcrumbs/BreadcrumbItem.js.map +1 -1
- package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js +5 -0
- package/dist/esm/components/navigation/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/esm/components/navigation/Pagination/Pagination.css.js +12 -0
- package/dist/esm/components/navigation/Pagination/Pagination.css.js.map +1 -0
- package/dist/esm/components/navigation/Pagination/Pagination.js +107 -0
- package/dist/esm/components/navigation/Pagination/Pagination.js.map +1 -0
- package/dist/esm/components/navigation/Pagination/usePagination.js +143 -0
- package/dist/esm/components/navigation/Pagination/usePagination.js.map +1 -0
- package/dist/esm/components/primitives/Avatar/Avatar.js +87 -1
- package/dist/esm/components/primitives/Avatar/Avatar.js.map +1 -1
- package/dist/esm/components/primitives/Badge/Badge.js +87 -1
- package/dist/esm/components/primitives/Badge/Badge.js.map +1 -1
- package/dist/esm/components/primitives/Checkbox/Checkbox.js +5 -2
- package/dist/esm/components/primitives/Checkbox/Checkbox.js.map +1 -1
- package/dist/esm/components/primitives/Collapsible/Collapsible.js +2 -3
- package/dist/esm/components/primitives/Collapsible/Collapsible.js.map +1 -1
- package/dist/esm/components/primitives/HoverCard/HoverCard.css.js +7 -0
- package/dist/esm/components/primitives/HoverCard/HoverCard.css.js.map +1 -0
- package/dist/esm/components/primitives/HoverCard/HoverCard.js +169 -0
- package/dist/esm/components/primitives/HoverCard/HoverCard.js.map +1 -0
- package/dist/esm/components/primitives/Icon/Icon.js +16 -2
- package/dist/esm/components/primitives/Icon/Icon.js.map +1 -1
- package/dist/esm/components/primitives/Link/Link.js +3 -3
- package/dist/esm/components/primitives/Link/Link.js.map +1 -1
- package/dist/esm/components/primitives/Popover/PopoverClose.js +2 -3
- package/dist/esm/components/primitives/Popover/PopoverClose.js.map +1 -1
- package/dist/esm/components/primitives/Radio/Radio.js +1 -1
- package/dist/esm/hooks/useBreakpoint/useBreakpoint.js +44 -0
- package/dist/esm/hooks/useBreakpoint/useBreakpoint.js.map +1 -0
- package/dist/esm/hooks/useDebounced/useDebouncedCallback.js +97 -0
- package/dist/esm/hooks/useDebounced/useDebouncedCallback.js.map +1 -0
- package/dist/esm/hooks/useDebounced/useDebouncedValue.js +35 -0
- package/dist/esm/hooks/useDebounced/useDebouncedValue.js.map +1 -0
- package/dist/esm/hooks/useIntersectionObserver/useIntersectionObserver.js +73 -0
- package/dist/esm/hooks/useIntersectionObserver/useIntersectionObserver.js.map +1 -0
- package/dist/esm/hooks/useListboxNav/useListboxNav.js +181 -0
- package/dist/esm/hooks/useListboxNav/useListboxNav.js.map +1 -0
- package/dist/esm/hooks/useMediaQuery/useMediaQuery.js +54 -0
- package/dist/esm/hooks/useMediaQuery/useMediaQuery.js.map +1 -0
- package/dist/esm/hooks/useThrottledCallback/useThrottledCallback.js +78 -0
- package/dist/esm/hooks/useThrottledCallback/useThrottledCallback.js.map +1 -0
- package/dist/esm/index.js +25 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/theme/breakpoints.js +27 -0
- package/dist/esm/theme/breakpoints.js.map +1 -0
- package/dist/esm/theme/index.js +1 -0
- package/dist/esm/theme/index.js.map +1 -1
- package/dist/tokens/tokens.dark.css +1 -1
- package/dist/tokens/tokens.json +1 -1
- package/dist/tokens/tokens.light.css +1 -1
- package/dist/types/components/Icons/CloudUploadIcon.d.ts +27 -0
- package/dist/types/components/Icons/ExternalLinkIcon.d.ts +29 -0
- package/dist/types/components/Icons/FirstIcon.d.ts +26 -0
- package/dist/types/components/Icons/LastIcon.d.ts +26 -0
- package/dist/types/components/Icons/UnlinkIcon.d.ts +29 -0
- package/dist/types/components/controls/Combobox/Combobox.d.ts +29 -0
- package/dist/types/components/controls/Combobox/Combobox.types.d.ts +109 -0
- package/dist/types/components/controls/FileUploader/FileUploader.d.ts +34 -0
- package/dist/types/components/controls/FileUploader/FileUploader.types.d.ts +94 -0
- package/dist/types/components/controls/MultiSelect/MultiSelect.d.ts +31 -0
- package/dist/types/components/controls/MultiSelect/MultiSelect.types.d.ts +85 -0
- package/dist/types/components/controls/TagInput/TagInput.d.ts +24 -0
- package/dist/types/components/controls/TagInput/TagInput.types.d.ts +100 -0
- package/dist/types/components/data/DataTable/DataTable.d.ts +8 -0
- package/dist/types/components/data/DataTable/DataTable.types.d.ts +159 -0
- package/dist/types/components/feedback/Alert/Alert.d.ts +1 -0
- package/dist/types/components/feedback/Alert/Alert.types.d.ts +7 -0
- package/dist/types/components/feedback/CommandPalette/CommandPalette.d.ts +29 -0
- package/dist/types/components/feedback/CommandPalette/CommandPalette.types.d.ts +61 -0
- package/dist/types/components/feedback/CommandPalette/fuzzySearch.d.ts +6 -0
- package/dist/types/components/feedback/Drawer/Drawer.d.ts +12 -0
- package/dist/types/components/feedback/Drawer/Drawer.types.d.ts +70 -0
- package/dist/types/components/feedback/Skeleton/Skeleton.types.d.ts +44 -1
- package/dist/types/components/feedback/Skeleton/SkeletonLayout.d.ts +314 -0
- package/dist/types/components/feedback/Stat/Stat.d.ts +23 -0
- package/dist/types/components/feedback/Stat/Stat.types.d.ts +38 -0
- package/dist/types/components/layout/Accordion/Accordion.types.d.ts +7 -0
- package/dist/types/components/layout/Card/Card.d.ts +12 -0
- package/dist/types/components/layout/Card/Card.types.d.ts +54 -0
- package/dist/types/components/navigation/Pagination/Pagination.d.ts +22 -0
- package/dist/types/components/navigation/Pagination/Pagination.types.d.ts +49 -0
- package/dist/types/components/primitives/Button/Button.d.ts +1 -1
- package/dist/types/components/primitives/HoverCard/HoverCard.d.ts +10 -0
- package/dist/types/components/primitives/HoverCard/HoverCard.types.d.ts +64 -0
- package/dist/types/components/primitives/Icon/Icon.d.ts +14 -1
- package/dist/types/components/primitives/IconButton/IconButton.d.ts +1 -1
- package/dist/types/hooks/useBreakpoint/useBreakpoint.d.ts +19 -0
- package/dist/types/hooks/useBreakpoint/useBreakpoint.types.d.ts +20 -0
- package/dist/types/hooks/useDebounced/useDebounced.types.d.ts +15 -0
- package/dist/types/hooks/useDebounced/useDebouncedCallback.d.ts +22 -0
- package/dist/types/hooks/useDebounced/useDebouncedValue.d.ts +16 -0
- package/dist/types/hooks/useIntersectionObserver/useIntersectionObserver.d.ts +22 -0
- package/dist/types/hooks/useIntersectionObserver/useIntersectionObserver.types.d.ts +22 -0
- package/dist/types/hooks/useListboxNav/useListboxNav.d.ts +75 -0
- package/dist/types/hooks/useMediaQuery/useMediaQuery.d.ts +19 -0
- package/dist/types/hooks/useMediaQuery/useMediaQuery.types.d.ts +6 -0
- package/dist/types/hooks/useThrottledCallback/useThrottledCallback.d.ts +23 -0
- package/dist/types/hooks/useThrottledCallback/useThrottledCallback.types.d.ts +13 -0
- package/dist/types/index.d.ts +43 -1
- package/dist/types/theme/breakpoints.d.ts +22 -0
- package/dist/types/theme/index.d.ts +1 -0
- package/package.json +3 -1
package/dist/esm/assets/src/components/navigation/Pagination/Pagination.css.ts.vanilla-CmlFyyjh.css
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
.Pagination_paginationRootStyle__17bx4kb0 {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
}
|
|
5
|
+
.Pagination_paginationListRecipe__17bx4kb1 {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
list-style: none;
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
}
|
|
12
|
+
.Pagination_paginationListRecipe_size_sm__17bx4kb2 {
|
|
13
|
+
gap: var(--etui-spacing-xs);
|
|
14
|
+
}
|
|
15
|
+
.Pagination_paginationListRecipe_size_md__17bx4kb3 {
|
|
16
|
+
gap: var(--etui-spacing-xs);
|
|
17
|
+
}
|
|
18
|
+
.Pagination_paginationListRecipe_size_lg__17bx4kb4 {
|
|
19
|
+
gap: var(--etui-spacing-sm);
|
|
20
|
+
}
|
|
21
|
+
.Pagination_paginationItemStyle__17bx4kb5 {
|
|
22
|
+
display: inline-flex;
|
|
23
|
+
}
|
|
24
|
+
.Pagination_paginationButtonRecipe__17bx4kb6 {
|
|
25
|
+
display: inline-flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
padding: 0 var(--etui-spacing-xs);
|
|
30
|
+
font-family: var(--etui-font-family-sans);
|
|
31
|
+
font-weight: var(--etui-font-weight-medium);
|
|
32
|
+
line-height: 1;
|
|
33
|
+
color: var(--etui-color-text-primary);
|
|
34
|
+
background: transparent;
|
|
35
|
+
border: 1px solid transparent;
|
|
36
|
+
border-radius: var(--etui-radius-md);
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
user-select: none;
|
|
39
|
+
transition: background-color var(--etui-transition-fast), color var(--etui-transition-fast), border-color var(--etui-transition-fast);
|
|
40
|
+
}
|
|
41
|
+
.Pagination_paginationButtonRecipe__17bx4kb6:hover:not(:disabled) {
|
|
42
|
+
background: var(--etui-color-surface-hover);
|
|
43
|
+
}
|
|
44
|
+
.Pagination_paginationButtonRecipe__17bx4kb6:focus-visible {
|
|
45
|
+
outline: 2px solid var(--etui-color-border-focus);
|
|
46
|
+
outline-offset: 2px;
|
|
47
|
+
}
|
|
48
|
+
.Pagination_paginationButtonRecipe__17bx4kb6:disabled {
|
|
49
|
+
cursor: not-allowed;
|
|
50
|
+
opacity: 0.5;
|
|
51
|
+
}
|
|
52
|
+
.Pagination_paginationButtonRecipe_size_sm__17bx4kb7 {
|
|
53
|
+
min-width: 24px;
|
|
54
|
+
height: 24px;
|
|
55
|
+
font-size: var(--etui-font-size-xs);
|
|
56
|
+
}
|
|
57
|
+
.Pagination_paginationButtonRecipe_size_md__17bx4kb8 {
|
|
58
|
+
min-width: 32px;
|
|
59
|
+
height: 32px;
|
|
60
|
+
font-size: var(--etui-font-size-sm);
|
|
61
|
+
}
|
|
62
|
+
.Pagination_paginationButtonRecipe_size_lg__17bx4kb9 {
|
|
63
|
+
min-width: 40px;
|
|
64
|
+
height: 40px;
|
|
65
|
+
font-size: var(--etui-font-size-md);
|
|
66
|
+
}
|
|
67
|
+
.Pagination_paginationButtonRecipe_selected_true__17bx4kba {
|
|
68
|
+
background: var(--etui-color-accent-primary);
|
|
69
|
+
color: white;
|
|
70
|
+
border-color: var(--etui-color-accent-primary);
|
|
71
|
+
}
|
|
72
|
+
.Pagination_paginationButtonRecipe_selected_true__17bx4kba:hover:not(:disabled) {
|
|
73
|
+
background: var(--etui-color-accent-secondary);
|
|
74
|
+
border-color: var(--etui-color-accent-secondary);
|
|
75
|
+
}
|
|
76
|
+
.Pagination_paginationEllipsisRecipe__17bx4kbb {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
box-sizing: border-box;
|
|
81
|
+
color: var(--etui-color-text-secondary);
|
|
82
|
+
user-select: none;
|
|
83
|
+
}
|
|
84
|
+
.Pagination_paginationEllipsisRecipe_size_sm__17bx4kbc {
|
|
85
|
+
min-width: 24px;
|
|
86
|
+
height: 24px;
|
|
87
|
+
font-size: var(--etui-font-size-xs);
|
|
88
|
+
}
|
|
89
|
+
.Pagination_paginationEllipsisRecipe_size_md__17bx4kbd {
|
|
90
|
+
min-width: 32px;
|
|
91
|
+
height: 32px;
|
|
92
|
+
font-size: var(--etui-font-size-sm);
|
|
93
|
+
}
|
|
94
|
+
.Pagination_paginationEllipsisRecipe_size_lg__17bx4kbe {
|
|
95
|
+
min-width: 40px;
|
|
96
|
+
height: 40px;
|
|
97
|
+
font-size: var(--etui-font-size-md);
|
|
98
|
+
}
|
|
99
|
+
.Pagination_paginationIconStyle__17bx4kbf {
|
|
100
|
+
display: inline-flex;
|
|
101
|
+
width: 1em;
|
|
102
|
+
height: 1em;
|
|
103
|
+
}
|
package/dist/esm/assets/src/components/primitives/HoverCard/HoverCard.css.ts.vanilla-BYT0qbLp.css
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
.HoverCard_hoverCardContentRecipe__1aj59sj0 {
|
|
2
|
+
z-index: var(--etui-z-popover);
|
|
3
|
+
background: var(--etui-color-bg-elevated);
|
|
4
|
+
border: 1px solid var(--etui-color-border-default);
|
|
5
|
+
border-radius: var(--etui-radius-lg);
|
|
6
|
+
box-shadow: var(--etui-shadow-lg);
|
|
7
|
+
color: var(--etui-color-text-primary);
|
|
8
|
+
font-size: var(--etui-font-size-sm);
|
|
9
|
+
font-family: var(--etui-font-family-sans);
|
|
10
|
+
transition: opacity var(--etui-transition-fast), transform var(--etui-transition-fast);
|
|
11
|
+
}
|
|
12
|
+
.HoverCard_hoverCardContentRecipe__1aj59sj0:focus {
|
|
13
|
+
outline: none;
|
|
14
|
+
}
|
|
15
|
+
.HoverCard_hoverCardContentRecipe_padding_none__1aj59sj1 {
|
|
16
|
+
padding: 0;
|
|
17
|
+
}
|
|
18
|
+
.HoverCard_hoverCardContentRecipe_padding_sm__1aj59sj2 {
|
|
19
|
+
padding: var(--etui-spacing-sm);
|
|
20
|
+
}
|
|
21
|
+
.HoverCard_hoverCardContentRecipe_padding_md__1aj59sj3 {
|
|
22
|
+
padding: var(--etui-spacing-md);
|
|
23
|
+
}
|
|
24
|
+
.HoverCard_hoverCardContentRecipe_padding_lg__1aj59sj4 {
|
|
25
|
+
padding: var(--etui-spacing-lg);
|
|
26
|
+
}
|
|
27
|
+
.HoverCard_hoverCardContentRecipe_visible_true__1aj59sj5 {
|
|
28
|
+
opacity: 1;
|
|
29
|
+
transform: scale(1);
|
|
30
|
+
pointer-events: auto;
|
|
31
|
+
}
|
|
32
|
+
.HoverCard_hoverCardContentRecipe_visible_false__1aj59sj6 {
|
|
33
|
+
opacity: 0;
|
|
34
|
+
transform: scale(0.96);
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
|
37
|
+
@media (prefers-reduced-motion: reduce) {
|
|
38
|
+
.HoverCard_hoverCardContentRecipe__1aj59sj0 {
|
|
39
|
+
transition: none;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Icon } from '../primitives/Icon/Icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Cloud upload icon — a cloud silhouette with an upward arrow inside.
|
|
8
|
+
*
|
|
9
|
+
* Use for file-upload drop zones, "send to cloud" actions, and any other
|
|
10
|
+
* upload-to-remote affordance. For a generic up-arrow without the cloud,
|
|
11
|
+
* use `UploadIcon` instead.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <CloudUploadIcon size="lg" color="muted" />
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
const CloudUploadIcon = /*#__PURE__*/ React.memo(props => {
|
|
19
|
+
return (jsxs(Icon, { ...props, children: [jsx("path", { d: "M7 18a4 4 0 1 1 .5-7.97A6 6 0 0 1 18 11h.5a3.5 3.5 0 0 1 0 7H7z" }), jsx("path", { d: "M12 13v5m0-5l-2 2m2-2l2 2" })] }));
|
|
20
|
+
});
|
|
21
|
+
CloudUploadIcon.displayName = 'CloudUploadIcon';
|
|
22
|
+
|
|
23
|
+
export { CloudUploadIcon };
|
|
24
|
+
//# sourceMappingURL=CloudUploadIcon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CloudUploadIcon.js","sources":["../../../../../src/components/Icons/CloudUploadIcon.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAMA;;;;;;;;;;;AAWG;AACI;AAGL;AAMF;AAEA;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Icon } from '../primitives/Icon/Icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* External link icon — a box with an arrow exiting the top-right corner.
|
|
8
|
+
*
|
|
9
|
+
* Use for links that open in a new tab/window or otherwise navigate
|
|
10
|
+
* outside the current surface. For an in-app link (chain shape) use
|
|
11
|
+
* `LinkIcon` instead.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <Link href="https://example.com" target="_blank">
|
|
16
|
+
* Docs <ExternalLinkIcon size="sm" decorative />
|
|
17
|
+
* </Link>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
const ExternalLinkIcon = /*#__PURE__*/ React.memo(props => {
|
|
21
|
+
return (jsxs(Icon, { ...props, children: [jsx("path", { d: "M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" }), jsx("polyline", { points: "15 3 21 3 21 9" }), jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] }));
|
|
22
|
+
});
|
|
23
|
+
ExternalLinkIcon.displayName = 'ExternalLinkIcon';
|
|
24
|
+
|
|
25
|
+
export { ExternalLinkIcon };
|
|
26
|
+
//# sourceMappingURL=ExternalLinkIcon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExternalLinkIcon.js","sources":["../../../../../src/components/Icons/ExternalLinkIcon.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAMA;;;;;;;;;;;;;AAaG;AACI;AAGL;AAOF;AAEA;;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Icon } from '../primitives/Icon/Icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Skip to first icon — vertical bar plus a leftward chevron.
|
|
8
|
+
*
|
|
9
|
+
* Used by Pagination's "first page" button and similar
|
|
10
|
+
* jump-to-start controls.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <IconButton aria-label="First page"><FirstIcon /></IconButton>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
const FirstIcon = /*#__PURE__*/ React.memo(props => {
|
|
18
|
+
return (jsx(Icon, { ...props, children: jsx("path", { d: "M6 5v14M18 5l-7 7 7 7" }) }));
|
|
19
|
+
});
|
|
20
|
+
FirstIcon.displayName = 'FirstIcon';
|
|
21
|
+
|
|
22
|
+
export { FirstIcon };
|
|
23
|
+
//# sourceMappingURL=FirstIcon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FirstIcon.js","sources":["../../../../../src/components/Icons/FirstIcon.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAMA;;;;;;;;;;AAUG;AACI;AAEH;AAKF;AAGF;;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Icon } from '../primitives/Icon/Icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Skip to last icon — rightward chevron plus a vertical bar.
|
|
8
|
+
*
|
|
9
|
+
* Used by Pagination's "last page" button and similar
|
|
10
|
+
* jump-to-end controls.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <IconButton aria-label="Last page"><LastIcon /></IconButton>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
const LastIcon = /*#__PURE__*/ React.memo(props => {
|
|
18
|
+
return (jsx(Icon, { ...props, children: jsx("path", { d: "M18 5v14M6 5l7 7-7 7" }) }));
|
|
19
|
+
});
|
|
20
|
+
LastIcon.displayName = 'LastIcon';
|
|
21
|
+
|
|
22
|
+
export { LastIcon };
|
|
23
|
+
//# sourceMappingURL=LastIcon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LastIcon.js","sources":["../../../../../src/components/Icons/LastIcon.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAMA;;;;;;;;;;AAUG;AACI;AAEH;AAKF;AAGF;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Icon } from '../primitives/Icon/Icon.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Unlink icon — a broken chain.
|
|
8
|
+
*
|
|
9
|
+
* Indicates that two values are decoupled (no longer linked). Pair with
|
|
10
|
+
* `LinkIcon` to render a toggle: link → unlink. Common in coordinate
|
|
11
|
+
* inputs, transform locks, color-channel groups.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <IconButton aria-label="Unlink axes">
|
|
16
|
+
* <UnlinkIcon />
|
|
17
|
+
* </IconButton>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
const UnlinkIcon = /*#__PURE__*/ React.memo(props => {
|
|
21
|
+
return (jsxs(Icon, { ...props, children: [jsx("path", { d: "M9 17H7A5 5 0 0 1 7 7h2" }), jsx("path", { d: "M15 7h2a5 5 0 0 1 0 10h-2" }), jsx("line", { x1: "3", y1: "3", x2: "21", y2: "21" })] }));
|
|
22
|
+
});
|
|
23
|
+
UnlinkIcon.displayName = 'UnlinkIcon';
|
|
24
|
+
|
|
25
|
+
export { UnlinkIcon };
|
|
26
|
+
//# sourceMappingURL=UnlinkIcon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UnlinkIcon.js","sources":["../../../../../src/components/Icons/UnlinkIcon.tsx"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAMA;;;;;;;;;;;;;AAaG;AACI;AAEH;AAOF;AAGF;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import './../../../assets/src/components/controls/Combobox/Combobox.css.ts.vanilla-B7B5ttkq.css';
|
|
2
|
+
import { createRuntimeFn } from '@vanilla-extract/recipes/createRuntimeFn';
|
|
3
|
+
|
|
4
|
+
var checkmarkStyle = 'Combobox_checkmarkStyle__1pazsaxx';
|
|
5
|
+
var chevronButtonStyle = 'Combobox_chevronButtonStyle__1pazsaxg';
|
|
6
|
+
var chevronIconRecipe = createRuntimeFn({defaultClassName:'Combobox_chevronIconRecipe__1pazsaxh',variantClassNames:{open:{true:'Combobox_chevronIconRecipe_open_true__1pazsaxi',false:'Combobox_chevronIconRecipe_open_false__1pazsaxj'}},defaultVariants:{open:false},compoundVariants:[]});
|
|
7
|
+
var clearButtonStyle = 'Combobox_clearButtonStyle__1pazsaxf';
|
|
8
|
+
var containerStyle = 'Combobox_containerStyle__1pazsax0';
|
|
9
|
+
var createRowStyle = 'Combobox_createRowStyle__1pazsaxy';
|
|
10
|
+
var dropdownStyle = 'Combobox_dropdownStyle__1pazsaxl';
|
|
11
|
+
var emptyMessageStyle = 'Combobox_emptyMessageStyle__1pazsaxw';
|
|
12
|
+
var inputStyle = 'Combobox_inputStyle__1pazsaxe';
|
|
13
|
+
var inputWrapperRecipe = createRuntimeFn({defaultClassName:'Combobox_inputWrapperRecipe__1pazsax1',variantClassNames:{size:{sm:'Combobox_inputWrapperRecipe_size_sm__1pazsax2',md:'Combobox_inputWrapperRecipe_size_md__1pazsax3',lg:'Combobox_inputWrapperRecipe_size_lg__1pazsax4'},variant:{'default':'Combobox_inputWrapperRecipe_variant_default__1pazsax5',ghost:'Combobox_inputWrapperRecipe_variant_ghost__1pazsax6',filled:'Combobox_inputWrapperRecipe_variant_filled__1pazsax7'},focused:{true:'Combobox_inputWrapperRecipe_focused_true__1pazsax8',false:'Combobox_inputWrapperRecipe_focused_false__1pazsax9'},error:{true:'Combobox_inputWrapperRecipe_error_true__1pazsaxa',false:'Combobox_inputWrapperRecipe_error_false__1pazsaxb'},disabled:{true:'Combobox_inputWrapperRecipe_disabled_true__1pazsaxc',false:'Combobox_inputWrapperRecipe_disabled_false__1pazsaxd'}},defaultVariants:{size:'md',variant:'default',focused:false,error:false,disabled:false},compoundVariants:[]});
|
|
14
|
+
var optionDescriptionStyle = 'Combobox_optionDescriptionStyle__1pazsaxv';
|
|
15
|
+
var optionItemRecipe = createRuntimeFn({defaultClassName:'Combobox_optionItemRecipe__1pazsaxn',variantClassNames:{active:{true:'Combobox_optionItemRecipe_active_true__1pazsaxo',false:'Combobox_optionItemRecipe_active_false__1pazsaxp'},selected:{true:'Combobox_optionItemRecipe_selected_true__1pazsaxq',false:'Combobox_optionItemRecipe_selected_false__1pazsaxr'},disabled:{true:'Combobox_optionItemRecipe_disabled_true__1pazsaxs',false:'Combobox_optionItemRecipe_disabled_false__1pazsaxt'}},defaultVariants:{active:false,selected:false,disabled:false},compoundVariants:[]});
|
|
16
|
+
var optionLabelStyle = 'Combobox_optionLabelStyle__1pazsaxu';
|
|
17
|
+
var optionsListStyle = 'Combobox_optionsListStyle__1pazsaxm';
|
|
18
|
+
|
|
19
|
+
export { checkmarkStyle, chevronButtonStyle, chevronIconRecipe, clearButtonStyle, containerStyle, createRowStyle, dropdownStyle, emptyMessageStyle, inputStyle, inputWrapperRecipe, optionDescriptionStyle, optionItemRecipe, optionLabelStyle, optionsListStyle };
|
|
20
|
+
//# sourceMappingURL=Combobox.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Combobox.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { useId, useRef, useCallback, useState, useEffect, useMemo } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { CheckIcon } from '../../Icons/CheckIcon.js';
|
|
6
|
+
import { ChevronDownIcon } from '../../Icons/ChevronDownIcon.js';
|
|
7
|
+
import { CloseIcon } from '../../Icons/CloseIcon.js';
|
|
8
|
+
import { fuzzyScore } from '../../feedback/CommandPalette/fuzzySearch.js';
|
|
9
|
+
import { FormHelperText } from '../../form/FormHelperText.js';
|
|
10
|
+
import { FormLabel } from '../../form/FormLabel.js';
|
|
11
|
+
import { ScrollArea } from '../../layout/ScrollArea/ScrollArea.js';
|
|
12
|
+
import { Spinner } from '../../feedback/Spinner/Spinner.js';
|
|
13
|
+
import { useControlledState } from '../../../hooks/useControlledState/useControlledState.js';
|
|
14
|
+
import { useListboxNav } from '../../../hooks/useListboxNav/useListboxNav.js';
|
|
15
|
+
import { useMergedRef } from '../../../hooks/useMergedRef/useMergedRef.js';
|
|
16
|
+
import { cx } from '../../../utils/cx.js';
|
|
17
|
+
import { inputStyle, clearButtonStyle, chevronButtonStyle, chevronIconRecipe, inputWrapperRecipe, dropdownStyle, optionsListStyle, containerStyle, emptyMessageStyle, optionLabelStyle, optionDescriptionStyle, checkmarkStyle, createRowStyle, optionItemRecipe } from './Combobox.css.js';
|
|
18
|
+
|
|
19
|
+
const CHEVRON_SIZES = {
|
|
20
|
+
sm: 10,
|
|
21
|
+
md: 12,
|
|
22
|
+
lg: 14,
|
|
23
|
+
};
|
|
24
|
+
const CREATE_ROW_VALUE = '__combobox_create__';
|
|
25
|
+
function defaultFilter(option, query) {
|
|
26
|
+
const haystack = `${option.label ?? option.value} ${option.description ?? ''}`;
|
|
27
|
+
return fuzzyScore(query, haystack);
|
|
28
|
+
}
|
|
29
|
+
function applyFilter(options, query, custom) {
|
|
30
|
+
if (!query)
|
|
31
|
+
return options;
|
|
32
|
+
const scored = [];
|
|
33
|
+
for (const option of options) {
|
|
34
|
+
let score;
|
|
35
|
+
if (custom) {
|
|
36
|
+
const result = custom(option, query);
|
|
37
|
+
if (typeof result === 'boolean') {
|
|
38
|
+
score = result ? 1 : 0;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
score = result;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
score = defaultFilter(option, query);
|
|
46
|
+
}
|
|
47
|
+
if (score > 0)
|
|
48
|
+
scored.push({ option, score });
|
|
49
|
+
}
|
|
50
|
+
scored.sort((a, b) => b.score - a.score);
|
|
51
|
+
return scored.map(entry => entry.option);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Single-value select with an editable input. Filters the option list as the
|
|
55
|
+
* user types (built-in fuzzy matcher, configurable via `filterFn`), supports
|
|
56
|
+
* controlled and uncontrolled modes, optional `freeSolo` typing, optional
|
|
57
|
+
* `creatable` mode for adding new entries, and an `loading` state for async
|
|
58
|
+
* data sources.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <Combobox
|
|
63
|
+
* label="Framework"
|
|
64
|
+
* options={[
|
|
65
|
+
* { value: 'react', label: 'React' },
|
|
66
|
+
* { value: 'vue', label: 'Vue' },
|
|
67
|
+
* ]}
|
|
68
|
+
* value={framework}
|
|
69
|
+
* onChange={setFramework}
|
|
70
|
+
* />
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
function Combobox({ value, defaultValue, options, placeholder, filterFn, emptyMessage = 'No results found', loading = false, loadingMessage = 'Loading...', freeSolo = false, creatable = false, createLabel, openOnFocus = false, size = 'md', variant = 'default', label, helperText, error = false, errorMessage, disabled = false, required = false, readOnly = false, clearable = false, maxDropdownHeight = 240, minDropdownWidth, name, onChange, onInputChange, onCreate, onOpenChange, className, style, testId, ref, id: idProp, ...rest }) {
|
|
74
|
+
const autoId = useId();
|
|
75
|
+
const fieldId = idProp ?? autoId;
|
|
76
|
+
const labelId = `${fieldId}-label`;
|
|
77
|
+
const helperId = `${fieldId}-helper`;
|
|
78
|
+
const listboxId = `${fieldId}-listbox`;
|
|
79
|
+
const inputRef = useRef(null);
|
|
80
|
+
const wrapperRef = useRef(null);
|
|
81
|
+
const dropdownRef = useRef(null);
|
|
82
|
+
const setInputRef = useMergedRef(inputRef, ref);
|
|
83
|
+
const [selected, setSelected] = useControlledState({
|
|
84
|
+
value,
|
|
85
|
+
defaultValue,
|
|
86
|
+
onChange,
|
|
87
|
+
fallback: null,
|
|
88
|
+
});
|
|
89
|
+
const labelOf = useCallback((val) => {
|
|
90
|
+
if (val === null)
|
|
91
|
+
return '';
|
|
92
|
+
const found = options.find(o => o.value === val);
|
|
93
|
+
return found?.label ?? String(val);
|
|
94
|
+
}, [options]);
|
|
95
|
+
const [query, setQuery] = useState(() => labelOf(selected));
|
|
96
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
97
|
+
const [focused, setFocused] = useState(false);
|
|
98
|
+
const [dropdownPos, setDropdownPos] = useState({});
|
|
99
|
+
const isEditingRef = useRef(false);
|
|
100
|
+
// Sync the query with the selected label when it changes externally and the
|
|
101
|
+
// user is not actively typing.
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (!isEditingRef.current) {
|
|
104
|
+
setQuery(labelOf(selected));
|
|
105
|
+
}
|
|
106
|
+
}, [labelOf, selected]);
|
|
107
|
+
const effectiveCreatable = creatable;
|
|
108
|
+
const effectiveFreeSolo = freeSolo || creatable;
|
|
109
|
+
const filteredOptions = useMemo(() => applyFilter(options,
|
|
110
|
+
// When the user hasn't typed yet (query equals the selected label) we
|
|
111
|
+
// show the full list so the dropdown serves as a browseable menu.
|
|
112
|
+
isEditingRef.current ? query : '', filterFn), [filterFn, options, query]);
|
|
113
|
+
const hasExactMatch = useMemo(() => {
|
|
114
|
+
if (!query)
|
|
115
|
+
return false;
|
|
116
|
+
const q = query.toLowerCase();
|
|
117
|
+
return options.some(o => (o.label ?? o.value).toLowerCase() === q);
|
|
118
|
+
}, [options, query]);
|
|
119
|
+
const showCreateRow = effectiveCreatable && query.length > 0 && !hasExactMatch && !loading;
|
|
120
|
+
// The list passed to useListboxNav. The "create" row is appended at the
|
|
121
|
+
// end as a synthetic option so the same navigation works.
|
|
122
|
+
const navItems = useMemo(() => {
|
|
123
|
+
const list = [...filteredOptions];
|
|
124
|
+
if (showCreateRow) {
|
|
125
|
+
list.push({
|
|
126
|
+
value: CREATE_ROW_VALUE,
|
|
127
|
+
label: query,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return list;
|
|
131
|
+
}, [filteredOptions, query, showCreateRow]);
|
|
132
|
+
const open = useCallback(() => {
|
|
133
|
+
if (disabled || readOnly)
|
|
134
|
+
return;
|
|
135
|
+
if (isOpen)
|
|
136
|
+
return;
|
|
137
|
+
setIsOpen(true);
|
|
138
|
+
onOpenChange?.(true);
|
|
139
|
+
}, [disabled, readOnly, isOpen, onOpenChange]);
|
|
140
|
+
const close = useCallback(() => {
|
|
141
|
+
if (!isOpen)
|
|
142
|
+
return;
|
|
143
|
+
setIsOpen(false);
|
|
144
|
+
onOpenChange?.(false);
|
|
145
|
+
}, [isOpen, onOpenChange]);
|
|
146
|
+
const commitOption = useCallback((opt) => {
|
|
147
|
+
if (opt.disabled)
|
|
148
|
+
return;
|
|
149
|
+
if (opt.value === CREATE_ROW_VALUE) {
|
|
150
|
+
const created = query;
|
|
151
|
+
if (onCreate)
|
|
152
|
+
onCreate(created);
|
|
153
|
+
else
|
|
154
|
+
setSelected(created);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
setSelected(opt.value);
|
|
158
|
+
}
|
|
159
|
+
isEditingRef.current = false;
|
|
160
|
+
setQuery(opt.value === CREATE_ROW_VALUE
|
|
161
|
+
? query
|
|
162
|
+
: (opt.label ?? String(opt.value)));
|
|
163
|
+
close();
|
|
164
|
+
}, [close, onCreate, query, setSelected]);
|
|
165
|
+
const listbox = useListboxNav({
|
|
166
|
+
items: navItems,
|
|
167
|
+
isItemDisabled: opt => Boolean(opt.disabled),
|
|
168
|
+
onSelect: commitOption,
|
|
169
|
+
onEscape: close,
|
|
170
|
+
});
|
|
171
|
+
const updateDropdownPosition = useCallback(() => {
|
|
172
|
+
const wrapper = wrapperRef.current;
|
|
173
|
+
if (!wrapper)
|
|
174
|
+
return;
|
|
175
|
+
const rect = wrapper.getBoundingClientRect();
|
|
176
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
177
|
+
const openAbove = spaceBelow < maxDropdownHeight + 8 && rect.top > spaceBelow;
|
|
178
|
+
const dropdownW = minDropdownWidth !== undefined
|
|
179
|
+
? Math.max(rect.width, minDropdownWidth)
|
|
180
|
+
: rect.width;
|
|
181
|
+
setDropdownPos({
|
|
182
|
+
left: rect.left,
|
|
183
|
+
width: dropdownW,
|
|
184
|
+
...(openAbove
|
|
185
|
+
? {
|
|
186
|
+
bottom: window.innerHeight - rect.top + 4,
|
|
187
|
+
transformOrigin: 'bottom',
|
|
188
|
+
}
|
|
189
|
+
: { top: rect.bottom + 4, transformOrigin: 'top' }),
|
|
190
|
+
});
|
|
191
|
+
}, [maxDropdownHeight, minDropdownWidth]);
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
if (!isOpen)
|
|
194
|
+
return;
|
|
195
|
+
updateDropdownPosition();
|
|
196
|
+
}, [isOpen, updateDropdownPosition]);
|
|
197
|
+
// Outside click
|
|
198
|
+
useEffect(() => {
|
|
199
|
+
if (!isOpen)
|
|
200
|
+
return;
|
|
201
|
+
const handleClick = (e) => {
|
|
202
|
+
const target = e.target;
|
|
203
|
+
if (!wrapperRef.current?.contains(target) &&
|
|
204
|
+
!dropdownRef.current?.contains(target)) {
|
|
205
|
+
close();
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
document.addEventListener('mousedown', handleClick);
|
|
209
|
+
return () => {
|
|
210
|
+
document.removeEventListener('mousedown', handleClick);
|
|
211
|
+
};
|
|
212
|
+
}, [close, isOpen]);
|
|
213
|
+
const handleInputChange = useCallback((event) => {
|
|
214
|
+
const next = event.target.value;
|
|
215
|
+
isEditingRef.current = true;
|
|
216
|
+
setQuery(next);
|
|
217
|
+
onInputChange?.(next);
|
|
218
|
+
if (!isOpen)
|
|
219
|
+
open();
|
|
220
|
+
// Clearing the input clears the selection.
|
|
221
|
+
if (next === '' && selected !== null) {
|
|
222
|
+
setSelected(null);
|
|
223
|
+
}
|
|
224
|
+
}, [isOpen, onInputChange, open, selected, setSelected]);
|
|
225
|
+
const handleInputKeyDown = useCallback((event) => {
|
|
226
|
+
if (disabled || readOnly)
|
|
227
|
+
return;
|
|
228
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
229
|
+
if (!isOpen) {
|
|
230
|
+
event.preventDefault();
|
|
231
|
+
open();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (event.key === 'Enter') {
|
|
236
|
+
// freeSolo / creatable take precedence when no suggestion is active.
|
|
237
|
+
if (effectiveFreeSolo && listbox.activeIndex < 0 && query.length > 0) {
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
if (effectiveCreatable && !hasExactMatch) {
|
|
240
|
+
if (onCreate)
|
|
241
|
+
onCreate(query);
|
|
242
|
+
else
|
|
243
|
+
setSelected(query);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
setSelected(query);
|
|
247
|
+
}
|
|
248
|
+
isEditingRef.current = false;
|
|
249
|
+
close();
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (event.key === 'Tab' && isOpen) {
|
|
254
|
+
// Commit the active suggestion if any, otherwise close.
|
|
255
|
+
if (listbox.activeIndex >= 0) {
|
|
256
|
+
listbox.selectActive();
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
close();
|
|
260
|
+
}
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
listbox.handleKeyDown(event);
|
|
264
|
+
}, [
|
|
265
|
+
close,
|
|
266
|
+
disabled,
|
|
267
|
+
effectiveCreatable,
|
|
268
|
+
effectiveFreeSolo,
|
|
269
|
+
hasExactMatch,
|
|
270
|
+
isOpen,
|
|
271
|
+
listbox,
|
|
272
|
+
onCreate,
|
|
273
|
+
open,
|
|
274
|
+
query,
|
|
275
|
+
readOnly,
|
|
276
|
+
setSelected,
|
|
277
|
+
]);
|
|
278
|
+
const handleFocus = useCallback(() => {
|
|
279
|
+
setFocused(true);
|
|
280
|
+
if (openOnFocus)
|
|
281
|
+
open();
|
|
282
|
+
}, [open, openOnFocus]);
|
|
283
|
+
const handleBlur = useCallback(() => {
|
|
284
|
+
setFocused(false);
|
|
285
|
+
isEditingRef.current = false;
|
|
286
|
+
// Restore the last selected label unless freeSolo allowed the typed value.
|
|
287
|
+
if (!effectiveFreeSolo) {
|
|
288
|
+
setQuery(labelOf(selected));
|
|
289
|
+
}
|
|
290
|
+
}, [effectiveFreeSolo, labelOf, selected]);
|
|
291
|
+
const handleClear = useCallback((event) => {
|
|
292
|
+
event.preventDefault();
|
|
293
|
+
event.stopPropagation();
|
|
294
|
+
setSelected(null);
|
|
295
|
+
setQuery('');
|
|
296
|
+
isEditingRef.current = false;
|
|
297
|
+
inputRef.current?.focus();
|
|
298
|
+
}, [setSelected]);
|
|
299
|
+
const handleToggleClick = useCallback(() => {
|
|
300
|
+
if (disabled || readOnly)
|
|
301
|
+
return;
|
|
302
|
+
if (isOpen)
|
|
303
|
+
close();
|
|
304
|
+
else
|
|
305
|
+
open();
|
|
306
|
+
inputRef.current?.focus();
|
|
307
|
+
}, [close, disabled, isOpen, open, readOnly]);
|
|
308
|
+
const showHelperText = error && errorMessage ? errorMessage : helperText;
|
|
309
|
+
const chevronSize = CHEVRON_SIZES[size];
|
|
310
|
+
const renderOptions = () => {
|
|
311
|
+
if (loading) {
|
|
312
|
+
return (jsxs("div", { className: emptyMessageStyle, children: [jsx(Spinner, { size: "xs" }), " ", loadingMessage] }));
|
|
313
|
+
}
|
|
314
|
+
if (navItems.length === 0) {
|
|
315
|
+
return jsx("div", { className: emptyMessageStyle, children: emptyMessage });
|
|
316
|
+
}
|
|
317
|
+
return navItems.map((opt, idx) => {
|
|
318
|
+
const isCreate = opt.value === CREATE_ROW_VALUE;
|
|
319
|
+
const isSelected = !isCreate && opt.value === selected;
|
|
320
|
+
const isActive = idx === listbox.activeIndex;
|
|
321
|
+
const isDisabled = opt.disabled ?? false;
|
|
322
|
+
return (jsxs("div", { role: "option", "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, id: `${listboxId}-${String(idx)}`, className: cx(optionItemRecipe({
|
|
323
|
+
active: isActive,
|
|
324
|
+
selected: isSelected,
|
|
325
|
+
disabled: isDisabled,
|
|
326
|
+
}), isCreate && createRowStyle), onClick: () => {
|
|
327
|
+
commitOption(opt);
|
|
328
|
+
}, onMouseEnter: () => {
|
|
329
|
+
if (!isDisabled)
|
|
330
|
+
listbox.setActiveIndex(idx);
|
|
331
|
+
}, children: [opt.icon && jsx("span", { children: opt.icon }), jsx("span", { className: optionLabelStyle, children: isCreate
|
|
332
|
+
? (createLabel?.(query) ?? jsxs(Fragment, { children: ["Create \"", query, "\""] }))
|
|
333
|
+
: (opt.label ?? opt.value) }), opt.description && !isCreate && (jsx("span", { className: optionDescriptionStyle, children: opt.description })), isSelected && (jsx("span", { className: checkmarkStyle, children: jsx(CheckIcon, { size: 10, decorative: true }) }))] }, isCreate ? `create-${query}` : `${opt.value}-${String(idx)}`));
|
|
334
|
+
});
|
|
335
|
+
};
|
|
336
|
+
const formValue = selected ?? '';
|
|
337
|
+
const displayValue = focused || isOpen ? query : labelOf(selected);
|
|
338
|
+
return (jsxs("div", { className: cx(containerStyle, className), style: style, children: [label && (jsx(FormLabel, { id: labelId, htmlFor: fieldId, required: required, disabled: disabled, children: label })), jsxs("div", { ref: wrapperRef, className: inputWrapperRecipe({
|
|
339
|
+
size,
|
|
340
|
+
variant,
|
|
341
|
+
focused,
|
|
342
|
+
error,
|
|
343
|
+
disabled,
|
|
344
|
+
}), children: [jsx("input", { ref: setInputRef, id: fieldId, type: "text", role: "combobox", "aria-expanded": isOpen, "aria-controls": isOpen ? listboxId : undefined, "aria-autocomplete": "list", "aria-activedescendant": isOpen && listbox.activeIndex >= 0
|
|
345
|
+
? `${listboxId}-${String(listbox.activeIndex)}`
|
|
346
|
+
: undefined, "aria-labelledby": label ? labelId : undefined, "aria-required": required || undefined, "aria-invalid": error || undefined, "aria-describedby": showHelperText ? helperId : undefined, autoComplete: "off", spellCheck: false, disabled: disabled, readOnly: readOnly, required: required, placeholder: placeholder, value: displayValue, className: inputStyle, onChange: handleInputChange, onKeyDown: handleInputKeyDown, onFocus: handleFocus, onBlur: handleBlur, "data-testid": testId, ...rest }), clearable && selected !== null && !disabled && !readOnly && (jsx("button", { type: "button", tabIndex: -1, "aria-label": "Clear selection", className: clearButtonStyle, onMouseDown: handleClear, children: jsx(CloseIcon, { size: "sm", decorative: true }) })), jsx("button", { type: "button", tabIndex: -1, "aria-label": isOpen ? 'Close suggestions' : 'Open suggestions', className: chevronButtonStyle, onMouseDown: e => {
|
|
347
|
+
e.preventDefault();
|
|
348
|
+
}, onClick: handleToggleClick, disabled: disabled, children: jsx("span", { className: chevronIconRecipe({ open: isOpen }), children: jsx(ChevronDownIcon, { size: chevronSize, decorative: true }) }) })] }), name && jsx("input", { type: "hidden", name: name, value: formValue }), isOpen &&
|
|
349
|
+
createPortal(jsx("div", { ref: dropdownRef, role: "listbox", id: listboxId, "aria-labelledby": label ? labelId : undefined, className: dropdownStyle, style: dropdownPos, tabIndex: -1, children: jsx(ScrollArea, { className: optionsListStyle, maxHeight: maxDropdownHeight, scrollbarWidth: 4, scrollbarVisibility: "auto", hideDelay: 600, children: renderOptions() }) }), document.body), showHelperText && (jsx(FormHelperText, { id: helperId, error: error, children: showHelperText }))] }));
|
|
350
|
+
}
|
|
351
|
+
Combobox.displayName = 'Combobox';
|
|
352
|
+
|
|
353
|
+
export { Combobox };
|
|
354
|
+
//# sourceMappingURL=Combobox.js.map
|