@eocrm/design-system 0.0.0-stage → 0.6.18
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/AI-PRIMER.md +341 -0
- package/LICENSE +202 -0
- package/README.md +266 -2
- package/docs/components/Accordion.md +114 -0
- package/docs/components/AgentAvatar.md +58 -0
- package/docs/components/Alert.md +81 -0
- package/docs/components/AppLayout.md +70 -0
- package/docs/components/Avatar.md +49 -0
- package/docs/components/AvatarGroup.md +47 -0
- package/docs/components/Badge.md +60 -0
- package/docs/components/Banner.md +89 -0
- package/docs/components/BrandIcon.md +32 -0
- package/docs/components/Breadcrumb.md +72 -0
- package/docs/components/Button.md +107 -0
- package/docs/components/ButtonGroup.md +78 -0
- package/docs/components/Calendar.md +158 -0
- package/docs/components/Card.md +165 -0
- package/docs/components/CatalogPicker.md +83 -0
- package/docs/components/Chart.md +114 -0
- package/docs/components/ChatBubble.md +55 -0
- package/docs/components/ChatLauncher.md +97 -0
- package/docs/components/Checkbox.md +55 -0
- package/docs/components/CircularProgress.md +53 -0
- package/docs/components/Cluster.md +96 -0
- package/docs/components/Code.md +35 -0
- package/docs/components/CodeBlock.md +67 -0
- package/docs/components/ColorPicker.md +115 -0
- package/docs/components/ConfirmationPopover.md +70 -0
- package/docs/components/Constrain.md +39 -0
- package/docs/components/CurrencySelect.md +57 -0
- package/docs/components/CursorPagination.md +43 -0
- package/docs/components/DashboardCanvas.md +79 -0
- package/docs/components/DashboardWidget.md +131 -0
- package/docs/components/DataTable.md +88 -0
- package/docs/components/DatePicker.md +68 -0
- package/docs/components/DateRangePicker.md +71 -0
- package/docs/components/DateStrip.md +56 -0
- package/docs/components/DefinitionList.md +82 -0
- package/docs/components/Divider.md +57 -0
- package/docs/components/Dot.md +26 -0
- package/docs/components/Drawer.md +94 -0
- package/docs/components/DropdownMenu.md +299 -0
- package/docs/components/EmojiPicker.md +84 -0
- package/docs/components/EmptyState.md +55 -0
- package/docs/components/EntityChip.md +102 -0
- package/docs/components/ErrorState.md +72 -0
- package/docs/components/Field.md +91 -0
- package/docs/components/FileUpload.md +109 -0
- package/docs/components/FilterChip.md +88 -0
- package/docs/components/FlowCanvas.md +108 -0
- package/docs/components/FormRow.md +31 -0
- package/docs/components/FormSection.md +37 -0
- package/docs/components/Grid.md +103 -0
- package/docs/components/Highlight.md +75 -0
- package/docs/components/HighlightedText.md +50 -0
- package/docs/components/IconPicker.md +134 -0
- package/docs/components/IconTile.md +30 -0
- package/docs/components/Image.md +84 -0
- package/docs/components/ImageCrop.md +163 -0
- package/docs/components/Indent.md +31 -0
- package/docs/components/InlineDatePicker.md +58 -0
- package/docs/components/InlineDateRangePicker.md +57 -0
- package/docs/components/Input.md +54 -0
- package/docs/components/Kanban.md +122 -0
- package/docs/components/Kbd.md +41 -0
- package/docs/components/Lightbox.md +105 -0
- package/docs/components/Link.md +65 -0
- package/docs/components/LinkCard.md +41 -0
- package/docs/components/LiquidEditor.md +84 -0
- package/docs/components/List.md +68 -0
- package/docs/components/LiveRegion.md +29 -0
- package/docs/components/LocaleProvider.md +25 -0
- package/docs/components/Logo.md +41 -0
- package/docs/components/Masonry.md +48 -0
- package/docs/components/MediaTile.md +95 -0
- package/docs/components/Modal.md +107 -0
- package/docs/components/MoneyInput.md +62 -0
- package/docs/components/OptionsPicker.md +123 -0
- package/docs/components/OtpInput.md +65 -0
- package/docs/components/Page.md +35 -0
- package/docs/components/PageHeader.md +133 -0
- package/docs/components/Pagination.md +44 -0
- package/docs/components/Palette.md +32 -0
- package/docs/components/PasswordInput.md +45 -0
- package/docs/components/PasswordStrengthMeter.md +27 -0
- package/docs/components/PersonDisplay.md +153 -0
- package/docs/components/PhoneInput.md +54 -0
- package/docs/components/PillMenu.md +91 -0
- package/docs/components/Popover.md +127 -0
- package/docs/components/Progress.md +56 -0
- package/docs/components/QrCode.md +34 -0
- package/docs/components/Radio.md +37 -0
- package/docs/components/RadioGroup.md +56 -0
- package/docs/components/Rail.md +191 -0
- package/docs/components/RelativeDateInput.md +114 -0
- package/docs/components/RichText.md +44 -0
- package/docs/components/RichTextEditor.md +112 -0
- package/docs/components/Screen.md +37 -0
- package/docs/components/ScrollArea.md +39 -0
- package/docs/components/Select.md +131 -0
- package/docs/components/SettingRow.md +98 -0
- package/docs/components/Skeleton.md +68 -0
- package/docs/components/Slider.md +92 -0
- package/docs/components/SlotGrid.md +55 -0
- package/docs/components/SocialButton.md +31 -0
- package/docs/components/Sortable.md +127 -0
- package/docs/components/SortableGroup.md +52 -0
- package/docs/components/Sparkline.md +51 -0
- package/docs/components/Split.md +76 -0
- package/docs/components/Stack.md +59 -0
- package/docs/components/StagePath.md +66 -0
- package/docs/components/StatGroup.md +61 -0
- package/docs/components/StatTile.md +58 -0
- package/docs/components/Sticky.md +69 -0
- package/docs/components/Switch.md +89 -0
- package/docs/components/Table.md +184 -0
- package/docs/components/TableOfContents.md +76 -0
- package/docs/components/Tabs.md +94 -0
- package/docs/components/Text.md +63 -0
- package/docs/components/Textarea.md +59 -0
- package/docs/components/Thread.md +52 -0
- package/docs/components/TimeField.md +70 -0
- package/docs/components/Timeline.md +57 -0
- package/docs/components/Title.md +54 -0
- package/docs/components/ToastViewport.md +61 -0
- package/docs/components/Tooltip.md +63 -0
- package/docs/components/TopBar.md +214 -0
- package/docs/components/Tour.md +85 -0
- package/docs/components/TreeView.md +113 -0
- package/docs/components/VisuallyHidden.md +43 -0
- package/docs/components/WidgetPreview.md +54 -0
- package/docs/components/useBelowBreakpoint.md +11 -0
- package/docs/components/useMonth.md +18 -0
- package/docs/setup.md +51 -0
- package/docs/theming.md +95 -0
- package/docs/tokens.md +123 -0
- package/docs/transient-state.md +56 -0
- package/package.json +86 -4
- package/src/_meta/manifest.ts +293 -0
- package/src/app/AppProvider.tsx +78 -0
- package/src/app/index.ts +3 -0
- package/src/app/themeTokens.ts +95 -0
- package/src/calendar/dateMath.ts +114 -0
- package/src/calendar/formatters.ts +75 -0
- package/src/calendar/index.ts +39 -0
- package/src/calendar/types.ts +36 -0
- package/src/calendar/useAgenda.ts +70 -0
- package/src/calendar/useDay.ts +51 -0
- package/src/calendar/useMonth.ts +82 -0
- package/src/calendar/useWeek.ts +62 -0
- package/src/calendar/weekInfo.ts +83 -0
- package/src/components/Accordion/Accordion.module.scss +304 -0
- package/src/components/Accordion/Accordion.tokens.scss +64 -0
- package/src/components/Accordion/Accordion.tsx +272 -0
- package/src/components/Accordion/AccordionContent.tsx +36 -0
- package/src/components/Accordion/AccordionItem.tsx +66 -0
- package/src/components/Accordion/AccordionTrigger.tsx +121 -0
- package/src/components/Accordion/context.ts +47 -0
- package/src/components/Accordion/index.ts +14 -0
- package/src/components/Alert/Alert.module.scss +92 -0
- package/src/components/Alert/Alert.tokens.scss +60 -0
- package/src/components/Alert/Alert.tsx +136 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/AppLayout/AppLayout.module.scss +130 -0
- package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
- package/src/components/AppLayout/AppLayout.tsx +211 -0
- package/src/components/AppLayout/index.ts +2 -0
- package/src/components/Avatar/AgentAvatar.module.scss +117 -0
- package/src/components/Avatar/AgentAvatar.tsx +122 -0
- package/src/components/Avatar/Avatar.module.scss +181 -0
- package/src/components/Avatar/Avatar.tokens.scss +107 -0
- package/src/components/Avatar/Avatar.tsx +210 -0
- package/src/components/Avatar/AvatarGroup.module.scss +128 -0
- package/src/components/Avatar/AvatarGroup.tsx +119 -0
- package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
- package/src/components/Avatar/index.ts +6 -0
- package/src/components/Badge/Badge.module.scss +124 -0
- package/src/components/Badge/Badge.tokens.scss +74 -0
- package/src/components/Badge/Badge.tsx +164 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Banner/Banner.module.scss +73 -0
- package/src/components/Banner/Banner.tokens.scss +51 -0
- package/src/components/Banner/Banner.tsx +138 -0
- package/src/components/Banner/index.ts +2 -0
- package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
- package/src/components/BrandIcon/BrandIcon.tsx +99 -0
- package/src/components/BrandIcon/index.ts +2 -0
- package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
- package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
- package/src/components/Breadcrumb/index.ts +2 -0
- package/src/components/Button/Button.module.scss +167 -0
- package/src/components/Button/Button.tokens.scss +90 -0
- package/src/components/Button/Button.tsx +205 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
- package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
- package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
- package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
- package/src/components/ButtonGroup/context.ts +45 -0
- package/src/components/ButtonGroup/index.ts +2 -0
- package/src/components/Calendar/AgendaView.module.scss +231 -0
- package/src/components/Calendar/AgendaView.tsx +214 -0
- package/src/components/Calendar/AllDayBand.module.scss +18 -0
- package/src/components/Calendar/AllDayBand.tsx +75 -0
- package/src/components/Calendar/Calendar.module.scss +23 -0
- package/src/components/Calendar/Calendar.tokens.scss +262 -0
- package/src/components/Calendar/Calendar.tsx +370 -0
- package/src/components/Calendar/DayCell.module.scss +30 -0
- package/src/components/Calendar/DayCell.tsx +50 -0
- package/src/components/Calendar/DayView.module.scss +10 -0
- package/src/components/Calendar/DayView.tsx +163 -0
- package/src/components/Calendar/EventChip.module.scss +171 -0
- package/src/components/Calendar/EventChip.tsx +115 -0
- package/src/components/Calendar/HourGrid.module.scss +123 -0
- package/src/components/Calendar/HourGrid.tsx +381 -0
- package/src/components/Calendar/MonthView.module.scss +99 -0
- package/src/components/Calendar/MonthView.tsx +296 -0
- package/src/components/Calendar/TimedEvent.module.scss +205 -0
- package/src/components/Calendar/TimedEvent.tsx +247 -0
- package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
- package/src/components/Calendar/ViewSwitcher.tsx +47 -0
- package/src/components/Calendar/WeekView.module.scss +10 -0
- package/src/components/Calendar/WeekView.tsx +137 -0
- package/src/components/Calendar/eventColor.ts +60 -0
- package/src/components/Calendar/index.ts +18 -0
- package/src/components/Calendar/types.ts +451 -0
- package/src/components/Calendar/useEventDrag.ts +783 -0
- package/src/components/Calendar/utils.ts +622 -0
- package/src/components/Card/Card.module.scss +264 -0
- package/src/components/Card/Card.tokens.scss +55 -0
- package/src/components/Card/Card.tsx +170 -0
- package/src/components/Card/CardBody.tsx +45 -0
- package/src/components/Card/CardHeader.tsx +113 -0
- package/src/components/Card/CardList.tsx +24 -0
- package/src/components/Card/CardListRow.tsx +24 -0
- package/src/components/Card/index.ts +7 -0
- package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
- package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
- package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
- package/src/components/CatalogPicker/index.ts +2 -0
- package/src/components/Chart/Chart.module.scss +287 -0
- package/src/components/Chart/Chart.tokens.scss +63 -0
- package/src/components/Chart/Chart.tsx +607 -0
- package/src/components/Chart/ChartLegend.tsx +99 -0
- package/src/components/Chart/ChartTable.tsx +62 -0
- package/src/components/Chart/ChartTooltip.tsx +91 -0
- package/src/components/Chart/chartModel.ts +689 -0
- package/src/components/Chart/index.ts +2 -0
- package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
- package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
- package/src/components/ChatBubble/ChatBubble.tsx +61 -0
- package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
- package/src/components/ChatBubble/index.ts +3 -0
- package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
- package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
- package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
- package/src/components/ChatLauncher/index.ts +2 -0
- package/src/components/ChatLauncher/isAtBottom.ts +12 -0
- package/src/components/Checkbox/Checkbox.module.scss +147 -0
- package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
- package/src/components/Checkbox/Checkbox.tsx +188 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
- package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
- package/src/components/CircularProgress/CircularProgress.tsx +139 -0
- package/src/components/CircularProgress/index.ts +7 -0
- package/src/components/Cluster/Cluster.module.scss +145 -0
- package/src/components/Cluster/Cluster.tokens.scss +11 -0
- package/src/components/Cluster/Cluster.tsx +215 -0
- package/src/components/Cluster/index.ts +2 -0
- package/src/components/Code/Code.module.scss +28 -0
- package/src/components/Code/Code.tokens.scss +15 -0
- package/src/components/Code/Code.tsx +44 -0
- package/src/components/Code/index.ts +2 -0
- package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
- package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
- package/src/components/CodeBlock/CodeBlock.tsx +274 -0
- package/src/components/CodeBlock/highlight.ts +179 -0
- package/src/components/CodeBlock/index.ts +8 -0
- package/src/components/CodeBlock/sampleSync.ts +42 -0
- package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
- package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
- package/src/components/ColorPicker/ColorPicker.tsx +367 -0
- package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
- package/src/components/ColorPicker/SVSquare.tsx +189 -0
- package/src/components/ColorPicker/colorMath.ts +141 -0
- package/src/components/ColorPicker/index.ts +6 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
- package/src/components/ConfirmationPopover/index.ts +2 -0
- package/src/components/Constrain/Constrain.module.scss +99 -0
- package/src/components/Constrain/Constrain.tsx +79 -0
- package/src/components/Constrain/index.ts +2 -0
- package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
- package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
- package/src/components/CurrencySelect/index.ts +3 -0
- package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
- package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
- package/src/components/CursorPagination/CursorPagination.tsx +121 -0
- package/src/components/CursorPagination/index.ts +2 -0
- package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
- package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
- package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
- package/src/components/DashboardCanvas/engine.ts +363 -0
- package/src/components/DashboardCanvas/index.ts +9 -0
- package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
- package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
- package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
- package/src/components/DashboardWidget/index.ts +7 -0
- package/src/components/DataTable/BodyRow.tsx +197 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
- package/src/components/DataTable/DataTable.module.scss +511 -0
- package/src/components/DataTable/DataTable.tokens.scss +80 -0
- package/src/components/DataTable/DataTable.tsx +734 -0
- package/src/components/DataTable/HeaderCell.module.scss +215 -0
- package/src/components/DataTable/HeaderCell.tsx +440 -0
- package/src/components/DataTable/columnShift.ts +117 -0
- package/src/components/DataTable/index.ts +23 -0
- package/src/components/DataTable/pinStyle.ts +47 -0
- package/src/components/DataTable/reorderColumns.ts +66 -0
- package/src/components/DataTable/types.ts +289 -0
- package/src/components/DataTable/useColumnDragShift.ts +216 -0
- package/src/components/DataTable/useDataTable.ts +372 -0
- package/src/components/DataTable/useResizeHandle.ts +97 -0
- package/src/components/DatePicker/DatePicker.module.scss +180 -0
- package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
- package/src/components/DatePicker/DatePicker.tsx +664 -0
- package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
- package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
- package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
- package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
- package/src/components/DatePicker/index.ts +4 -0
- package/src/components/DatePicker/utils.ts +364 -0
- package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
- package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
- package/src/components/DateRangePicker/index.ts +5 -0
- package/src/components/DateRangePicker/utils.ts +151 -0
- package/src/components/DateStrip/DateStrip.module.scss +78 -0
- package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
- package/src/components/DateStrip/DateStrip.tsx +205 -0
- package/src/components/DateStrip/index.ts +2 -0
- package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
- package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
- package/src/components/DefinitionList/DefinitionList.tsx +198 -0
- package/src/components/DefinitionList/index.ts +9 -0
- package/src/components/Divider/Divider.module.scss +144 -0
- package/src/components/Divider/Divider.tokens.scss +21 -0
- package/src/components/Divider/Divider.tsx +103 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Dot/Dot.module.scss +40 -0
- package/src/components/Dot/Dot.tokens.scss +4 -0
- package/src/components/Dot/Dot.tsx +45 -0
- package/src/components/Dot/index.ts +2 -0
- package/src/components/Drawer/Body.tsx +23 -0
- package/src/components/Drawer/Close.tsx +35 -0
- package/src/components/Drawer/Content.tsx +93 -0
- package/src/components/Drawer/Drawer.module.scss +232 -0
- package/src/components/Drawer/Drawer.tokens.scss +38 -0
- package/src/components/Drawer/Drawer.tsx +23 -0
- package/src/components/Drawer/DrawerRoot.tsx +190 -0
- package/src/components/Drawer/Footer.tsx +24 -0
- package/src/components/Drawer/Header.tsx +64 -0
- package/src/components/Drawer/Overlay.tsx +82 -0
- package/src/components/Drawer/context.ts +44 -0
- package/src/components/Drawer/index.ts +12 -0
- package/src/components/Drawer/useDragToClose.ts +149 -0
- package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
- package/src/components/DropdownMenu/Content.tsx +419 -0
- package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
- package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
- package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
- package/src/components/DropdownMenu/Group.tsx +76 -0
- package/src/components/DropdownMenu/Item.tsx +148 -0
- package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
- package/src/components/DropdownMenu/Radio.tsx +178 -0
- package/src/components/DropdownMenu/Root.tsx +100 -0
- package/src/components/DropdownMenu/Sub.tsx +332 -0
- package/src/components/DropdownMenu/Trigger.tsx +76 -0
- package/src/components/DropdownMenu/context.ts +65 -0
- package/src/components/DropdownMenu/index.ts +20 -0
- package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
- package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
- package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
- package/src/components/EmojiPicker/emojiData.ts +245 -0
- package/src/components/EmojiPicker/index.ts +3 -0
- package/src/components/EmptyState/EmptyState.module.scss +102 -0
- package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
- package/src/components/EmptyState/EmptyState.tsx +112 -0
- package/src/components/EmptyState/index.ts +7 -0
- package/src/components/EntityChip/EntityChip.module.scss +275 -0
- package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
- package/src/components/EntityChip/EntityChip.tsx +649 -0
- package/src/components/EntityChip/index.ts +10 -0
- package/src/components/ErrorState/ErrorState.module.scss +105 -0
- package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
- package/src/components/ErrorState/ErrorState.tsx +125 -0
- package/src/components/ErrorState/index.ts +8 -0
- package/src/components/Field/Field.module.scss +46 -0
- package/src/components/Field/Field.tsx +185 -0
- package/src/components/Field/index.ts +2 -0
- package/src/components/FileUpload/FileUpload.module.scss +187 -0
- package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
- package/src/components/FileUpload/FileUpload.tsx +569 -0
- package/src/components/FileUpload/formatBytes.ts +34 -0
- package/src/components/FileUpload/iconForFile.ts +40 -0
- package/src/components/FileUpload/index.ts +2 -0
- package/src/components/FilterChip/FilterChip.module.scss +61 -0
- package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
- package/src/components/FilterChip/FilterChip.tsx +208 -0
- package/src/components/FilterChip/index.ts +5 -0
- package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
- package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
- package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
- package/src/components/FlowCanvas/FlowControls.tsx +46 -0
- package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
- package/src/components/FlowCanvas/FlowNode.tsx +76 -0
- package/src/components/FlowCanvas/edgePath.ts +85 -0
- package/src/components/FlowCanvas/index.ts +4 -0
- package/src/components/FlowCanvas/layout.ts +148 -0
- package/src/components/FlowCanvas/spatialNav.ts +76 -0
- package/src/components/FlowCanvas/types.ts +59 -0
- package/src/components/FlowCanvas/useViewport.ts +122 -0
- package/src/components/FormRow/FormRow.module.scss +2 -0
- package/src/components/FormRow/FormRow.tsx +37 -0
- package/src/components/FormRow/index.ts +2 -0
- package/src/components/FormSection/FormSection.module.scss +24 -0
- package/src/components/FormSection/FormSection.tsx +46 -0
- package/src/components/FormSection/index.ts +2 -0
- package/src/components/Grid/Grid.module.scss +162 -0
- package/src/components/Grid/Grid.tokens.scss +13 -0
- package/src/components/Grid/Grid.tsx +226 -0
- package/src/components/Grid/GridItem.tsx +77 -0
- package/src/components/Grid/index.ts +11 -0
- package/src/components/Highlight/Highlight.module.scss +43 -0
- package/src/components/Highlight/Highlight.tokens.scss +35 -0
- package/src/components/Highlight/Highlight.tsx +164 -0
- package/src/components/Highlight/HighlightOverlay.tsx +100 -0
- package/src/components/Highlight/index.ts +2 -0
- package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
- package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
- package/src/components/HighlightedText/HighlightedText.tsx +50 -0
- package/src/components/HighlightedText/highlightRanges.ts +44 -0
- package/src/components/HighlightedText/index.ts +2 -0
- package/src/components/IconPicker/IconPicker.module.scss +175 -0
- package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
- package/src/components/IconPicker/IconPicker.tsx +629 -0
- package/src/components/IconPicker/index.ts +9 -0
- package/src/components/IconTile/IconTile.module.scss +57 -0
- package/src/components/IconTile/IconTile.tokens.scss +16 -0
- package/src/components/IconTile/IconTile.tsx +91 -0
- package/src/components/IconTile/index.ts +2 -0
- package/src/components/Image/Image.module.scss +266 -0
- package/src/components/Image/Image.tokens.scss +55 -0
- package/src/components/Image/Image.tsx +342 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
- package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
- package/src/components/ImageCrop/ImageCrop.tsx +542 -0
- package/src/components/ImageCrop/cropGeometry.ts +120 -0
- package/src/components/ImageCrop/extractCropBlob.ts +140 -0
- package/src/components/ImageCrop/index.ts +11 -0
- package/src/components/ImageCrop/useCropPreview.ts +161 -0
- package/src/components/Indent/Indent.module.scss +33 -0
- package/src/components/Indent/Indent.tokens.scss +10 -0
- package/src/components/Indent/Indent.tsx +46 -0
- package/src/components/Indent/index.ts +2 -0
- package/src/components/Input/Input.module.scss +99 -0
- package/src/components/Input/Input.tokens.scss +54 -0
- package/src/components/Input/Input.tsx +105 -0
- package/src/components/Input/Suggestions.tsx +260 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Kanban/Kanban.module.scss +39 -0
- package/src/components/Kanban/Kanban.tokens.scss +15 -0
- package/src/components/Kanban/Kanban.tsx +951 -0
- package/src/components/Kanban/index.ts +7 -0
- package/src/components/Kbd/Kbd.module.scss +47 -0
- package/src/components/Kbd/Kbd.tokens.scss +26 -0
- package/src/components/Kbd/Kbd.tsx +73 -0
- package/src/components/Kbd/index.ts +2 -0
- package/src/components/Lightbox/Lightbox.module.scss +283 -0
- package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
- package/src/components/Lightbox/Lightbox.tsx +506 -0
- package/src/components/Lightbox/index.ts +2 -0
- package/src/components/Link/Link.module.scss +78 -0
- package/src/components/Link/Link.tokens.scss +28 -0
- package/src/components/Link/Link.tsx +114 -0
- package/src/components/Link/index.ts +2 -0
- package/src/components/LinkCard/LinkCard.module.scss +92 -0
- package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
- package/src/components/LinkCard/LinkCard.tsx +72 -0
- package/src/components/LinkCard/index.ts +2 -0
- package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
- package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
- package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
- package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
- package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
- package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
- package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
- package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
- package/src/components/LiquidEditor/index.ts +7 -0
- package/src/components/LiquidEditor/liquidFilters.ts +23 -0
- package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
- package/src/components/LiquidEditor/types.ts +101 -0
- package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
- package/src/components/List/List.module.scss +105 -0
- package/src/components/List/List.tokens.scss +42 -0
- package/src/components/List/List.tsx +124 -0
- package/src/components/List/index.ts +9 -0
- package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
- package/src/components/LiveRegion/LiveRegion.tsx +116 -0
- package/src/components/LiveRegion/index.ts +2 -0
- package/src/components/Logo/Logo.module.scss +139 -0
- package/src/components/Logo/Logo.tokens.scss +14 -0
- package/src/components/Logo/Logo.tsx +126 -0
- package/src/components/Logo/index.ts +2 -0
- package/src/components/Masonry/Masonry.module.scss +42 -0
- package/src/components/Masonry/Masonry.tokens.scss +8 -0
- package/src/components/Masonry/Masonry.tsx +136 -0
- package/src/components/Masonry/index.ts +2 -0
- package/src/components/Masonry/masonryUtils.ts +42 -0
- package/src/components/MediaTile/MediaTile.module.scss +183 -0
- package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
- package/src/components/MediaTile/MediaTile.tsx +208 -0
- package/src/components/MediaTile/index.ts +8 -0
- package/src/components/Modal/Body.tsx +27 -0
- package/src/components/Modal/Close.tsx +45 -0
- package/src/components/Modal/Content.tsx +98 -0
- package/src/components/Modal/Footer.tsx +28 -0
- package/src/components/Modal/Header.tsx +51 -0
- package/src/components/Modal/Modal.module.scss +262 -0
- package/src/components/Modal/Modal.tokens.scss +50 -0
- package/src/components/Modal/Modal.tsx +23 -0
- package/src/components/Modal/ModalRoot.tsx +299 -0
- package/src/components/Modal/Overlay.tsx +101 -0
- package/src/components/Modal/context.ts +60 -0
- package/src/components/Modal/index.ts +11 -0
- package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
- package/src/components/MoneyInput/MoneyInput.tsx +433 -0
- package/src/components/MoneyInput/index.ts +2 -0
- package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
- package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
- package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
- package/src/components/OptionsPicker/index.ts +9 -0
- package/src/components/OtpInput/OtpInput.module.scss +69 -0
- package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
- package/src/components/OtpInput/OtpInput.tsx +368 -0
- package/src/components/OtpInput/index.ts +2 -0
- package/src/components/Page/Page.module.scss +30 -0
- package/src/components/Page/Page.tokens.scss +11 -0
- package/src/components/Page/Page.tsx +53 -0
- package/src/components/Page/index.ts +2 -0
- package/src/components/PageHeader/PageHeader.module.scss +197 -0
- package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
- package/src/components/PageHeader/PageHeader.tsx +310 -0
- package/src/components/PageHeader/index.ts +20 -0
- package/src/components/Pagination/Pagination.module.scss +117 -0
- package/src/components/Pagination/Pagination.tokens.scss +54 -0
- package/src/components/Pagination/Pagination.tsx +165 -0
- package/src/components/Pagination/index.ts +4 -0
- package/src/components/Pagination/paginationRange.ts +72 -0
- package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
- package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
- package/src/components/PasswordInput/PasswordInput.tsx +210 -0
- package/src/components/PasswordInput/index.ts +2 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
- package/src/components/PasswordStrengthMeter/index.ts +2 -0
- package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
- package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
- package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
- package/src/components/PersonDisplay/index.ts +10 -0
- package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
- package/src/components/PhoneInput/PhoneInput.tsx +271 -0
- package/src/components/PhoneInput/index.ts +4 -0
- package/src/components/PhoneInput/phone.ts +128 -0
- package/src/components/PillMenu/PillMenu.module.scss +117 -0
- package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
- package/src/components/PillMenu/PillMenu.tsx +324 -0
- package/src/components/PillMenu/index.ts +2 -0
- package/src/components/Popover/Anchor.tsx +37 -0
- package/src/components/Popover/Close.tsx +45 -0
- package/src/components/Popover/Content.tsx +213 -0
- package/src/components/Popover/Heading.tsx +33 -0
- package/src/components/Popover/Popover.module.scss +177 -0
- package/src/components/Popover/Popover.tokens.scss +22 -0
- package/src/components/Popover/Popover.tsx +23 -0
- package/src/components/Popover/PopoverRoot.tsx +75 -0
- package/src/components/Popover/Trigger.tsx +86 -0
- package/src/components/Popover/context.ts +22 -0
- package/src/components/Popover/index.ts +7 -0
- package/src/components/Progress/Progress.module.scss +110 -0
- package/src/components/Progress/Progress.tokens.scss +44 -0
- package/src/components/Progress/Progress.tsx +129 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/QrCode/QrCode.module.scss +97 -0
- package/src/components/QrCode/QrCode.tokens.scss +17 -0
- package/src/components/QrCode/QrCode.tsx +233 -0
- package/src/components/QrCode/index.ts +2 -0
- package/src/components/QrCode/qr.ts +161 -0
- package/src/components/Radio/Radio.module.scss +175 -0
- package/src/components/Radio/Radio.tokens.scss +59 -0
- package/src/components/Radio/Radio.tsx +127 -0
- package/src/components/Radio/RadioGroup.module.scss +42 -0
- package/src/components/Radio/RadioGroup.tsx +120 -0
- package/src/components/Radio/RadioGroupContext.tsx +30 -0
- package/src/components/Radio/index.ts +4 -0
- package/src/components/Rail/Rail.module.scss +510 -0
- package/src/components/Rail/Rail.tokens.scss +92 -0
- package/src/components/Rail/Rail.tsx +287 -0
- package/src/components/Rail/RailCollapseToggle.tsx +57 -0
- package/src/components/Rail/RailFooter.tsx +17 -0
- package/src/components/Rail/RailGroup.tsx +728 -0
- package/src/components/Rail/RailGroupContext.ts +9 -0
- package/src/components/Rail/RailHeader.tsx +23 -0
- package/src/components/Rail/RailItem.tsx +119 -0
- package/src/components/Rail/RailSection.tsx +39 -0
- package/src/components/Rail/RailSpacer.tsx +19 -0
- package/src/components/Rail/index.ts +9 -0
- package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
- package/src/components/RelativeDateInput/index.ts +10 -0
- package/src/components/RelativeDateInput/relativeDate.ts +127 -0
- package/src/components/RichText/RichText.module.scss +5 -0
- package/src/components/RichText/RichText.tsx +70 -0
- package/src/components/RichText/RichTextAttachment.module.scss +82 -0
- package/src/components/RichText/RichTextAttachment.tsx +122 -0
- package/src/components/RichText/_prose.scss +79 -0
- package/src/components/RichText/attachmentIcon.tsx +24 -0
- package/src/components/RichText/engine/attachment.ts +154 -0
- package/src/components/RichText/engine/autolink.ts +64 -0
- package/src/components/RichText/engine/blockUnit.ts +174 -0
- package/src/components/RichText/engine/colorMarks.ts +85 -0
- package/src/components/RichText/engine/escape.ts +11 -0
- package/src/components/RichText/engine/fromHtml.ts +353 -0
- package/src/components/RichText/engine/fromMarkdown.ts +20 -0
- package/src/components/RichText/engine/inlines.ts +82 -0
- package/src/components/RichText/engine/listDepths.ts +32 -0
- package/src/components/RichText/engine/marks.ts +80 -0
- package/src/components/RichText/engine/mdToHtml.ts +178 -0
- package/src/components/RichText/engine/model.ts +157 -0
- package/src/components/RichText/engine/position.ts +118 -0
- package/src/components/RichText/engine/renderDoc.tsx +395 -0
- package/src/components/RichText/engine/renderLink.ts +15 -0
- package/src/components/RichText/engine/renderMention.ts +16 -0
- package/src/components/RichText/engine/safeHref.ts +22 -0
- package/src/components/RichText/engine/toHtml.ts +154 -0
- package/src/components/RichText/engine/toMarkdown.ts +97 -0
- package/src/components/RichText/engine/transforms.ts +434 -0
- package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
- package/src/components/RichText/index.ts +31 -0
- package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
- package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
- package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
- package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
- package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
- package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
- package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
- package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
- package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
- package/src/components/RichTextEditor/autolinkInput.ts +65 -0
- package/src/components/RichTextEditor/blockDrop.ts +9 -0
- package/src/components/RichTextEditor/blockReflow.ts +62 -0
- package/src/components/RichTextEditor/commands.ts +300 -0
- package/src/components/RichTextEditor/history.ts +93 -0
- package/src/components/RichTextEditor/icons.tsx +152 -0
- package/src/components/RichTextEditor/imageSize.ts +70 -0
- package/src/components/RichTextEditor/index.ts +5 -0
- package/src/components/RichTextEditor/input.ts +209 -0
- package/src/components/RichTextEditor/inputRules.ts +71 -0
- package/src/components/RichTextEditor/links.ts +103 -0
- package/src/components/RichTextEditor/mentionContext.ts +37 -0
- package/src/components/RichTextEditor/mentions.ts +28 -0
- package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
- package/src/components/RichTextEditor/selection.ts +415 -0
- package/src/components/RichTextEditor/shortcuts.ts +44 -0
- package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
- package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
- package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
- package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
- package/src/components/RichTextEditor/useMention.ts +226 -0
- package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
- package/src/components/RichTextEditor/useUpload.ts +246 -0
- package/src/components/Screen/Screen.module.scss +46 -0
- package/src/components/Screen/Screen.tokens.scss +20 -0
- package/src/components/Screen/Screen.tsx +97 -0
- package/src/components/Screen/index.ts +2 -0
- package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
- package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
- package/src/components/ScrollArea/ScrollArea.tsx +154 -0
- package/src/components/ScrollArea/index.ts +2 -0
- package/src/components/Select/Chip.tsx +45 -0
- package/src/components/Select/Empty.tsx +39 -0
- package/src/components/Select/Error.tsx +51 -0
- package/src/components/Select/HiddenInputs.tsx +44 -0
- package/src/components/Select/Listbox.tsx +557 -0
- package/src/components/Select/Loading.tsx +30 -0
- package/src/components/Select/Select.module.scss +512 -0
- package/src/components/Select/Select.tokens.scss +140 -0
- package/src/components/Select/Select.tsx +685 -0
- package/src/components/Select/Trigger.tsx +952 -0
- package/src/components/Select/context.ts +101 -0
- package/src/components/Select/emptyStateText.ts +19 -0
- package/src/components/Select/index.ts +9 -0
- package/src/components/Select/useSelectState.ts +157 -0
- package/src/components/Select/utils-types.ts +7 -0
- package/src/components/Select/utils.ts +122 -0
- package/src/components/SettingRow/SettingRow.module.scss +166 -0
- package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
- package/src/components/SettingRow/SettingRow.tsx +242 -0
- package/src/components/SettingRow/index.ts +7 -0
- package/src/components/Skeleton/Skeleton.module.scss +55 -0
- package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
- package/src/components/Skeleton/Skeleton.tsx +131 -0
- package/src/components/Skeleton/index.ts +4 -0
- package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
- package/src/components/Slider/Slider.module.scss +293 -0
- package/src/components/Slider/Slider.tokens.scss +98 -0
- package/src/components/Slider/Slider.tsx +624 -0
- package/src/components/Slider/index.ts +9 -0
- package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
- package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
- package/src/components/SlotGrid/SlotGrid.tsx +111 -0
- package/src/components/SlotGrid/index.ts +2 -0
- package/src/components/SocialButton/SocialButton.module.scss +4 -0
- package/src/components/SocialButton/SocialButton.tsx +40 -0
- package/src/components/SocialButton/index.ts +2 -0
- package/src/components/Sortable/Sortable.module.scss +177 -0
- package/src/components/Sortable/Sortable.tokens.scss +27 -0
- package/src/components/Sortable/Sortable.tsx +572 -0
- package/src/components/Sortable/containerAwareCollision.ts +125 -0
- package/src/components/Sortable/index.ts +13 -0
- package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
- package/src/components/SortableGroup/SortableGroup.tsx +315 -0
- package/src/components/SortableGroup/index.ts +4 -0
- package/src/components/SortableGroup/moveSortableItem.ts +39 -0
- package/src/components/Sparkline/Sparkline.module.scss +28 -0
- package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
- package/src/components/Sparkline/Sparkline.tsx +133 -0
- package/src/components/Sparkline/index.ts +2 -0
- package/src/components/Sparkline/sparklineModel.ts +119 -0
- package/src/components/Split/Split.module.scss +158 -0
- package/src/components/Split/Split.tokens.scss +10 -0
- package/src/components/Split/Split.tsx +231 -0
- package/src/components/Split/index.ts +2 -0
- package/src/components/Stack/Stack.module.scss +67 -0
- package/src/components/Stack/Stack.tokens.scss +11 -0
- package/src/components/Stack/Stack.tsx +100 -0
- package/src/components/Stack/index.ts +2 -0
- package/src/components/StagePath/StagePath.module.scss +255 -0
- package/src/components/StagePath/StagePath.tokens.scss +43 -0
- package/src/components/StagePath/StagePath.tsx +176 -0
- package/src/components/StagePath/index.ts +2 -0
- package/src/components/StatGroup/StatGroup.module.scss +6 -0
- package/src/components/StatGroup/StatGroup.tsx +70 -0
- package/src/components/StatGroup/StatGroupContext.ts +10 -0
- package/src/components/StatGroup/StatTile.module.scss +99 -0
- package/src/components/StatGroup/StatTile.tokens.scss +35 -0
- package/src/components/StatGroup/StatTile.tsx +143 -0
- package/src/components/StatGroup/index.ts +4 -0
- package/src/components/Sticky/Sticky.module.scss +98 -0
- package/src/components/Sticky/Sticky.tokens.scss +17 -0
- package/src/components/Sticky/Sticky.tsx +103 -0
- package/src/components/Sticky/index.ts +2 -0
- package/src/components/Switch/Switch.module.scss +182 -0
- package/src/components/Switch/Switch.tokens.scss +59 -0
- package/src/components/Switch/Switch.tsx +214 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/Table.module.scss +308 -0
- package/src/components/Table/Table.tokens.scss +79 -0
- package/src/components/Table/Table.tsx +381 -0
- package/src/components/Table/index.ts +15 -0
- package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
- package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
- package/src/components/TableOfContents/TableOfContents.tsx +192 -0
- package/src/components/TableOfContents/activeSection.ts +18 -0
- package/src/components/TableOfContents/index.ts +2 -0
- package/src/components/Tabs/Tabs.module.scss +359 -0
- package/src/components/Tabs/Tabs.tokens.scss +50 -0
- package/src/components/Tabs/Tabs.tsx +538 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Text/Text.module.scss +115 -0
- package/src/components/Text/Text.tokens.scss +55 -0
- package/src/components/Text/Text.tsx +197 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Textarea/Textarea.module.scss +94 -0
- package/src/components/Textarea/Textarea.tokens.scss +48 -0
- package/src/components/Textarea/Textarea.tsx +246 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Thread/Thread.module.scss +161 -0
- package/src/components/Thread/Thread.tokens.scss +32 -0
- package/src/components/Thread/Thread.tsx +176 -0
- package/src/components/Thread/index.ts +2 -0
- package/src/components/TimeField/TimeField.module.scss +232 -0
- package/src/components/TimeField/TimeField.tsx +793 -0
- package/src/components/TimeField/index.ts +2 -0
- package/src/components/Timeline/Timeline.module.scss +58 -0
- package/src/components/Timeline/Timeline.tokens.scss +13 -0
- package/src/components/Timeline/Timeline.tsx +53 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Title/Title.module.scss +84 -0
- package/src/components/Title/Title.tokens.scss +37 -0
- package/src/components/Title/Title.tsx +150 -0
- package/src/components/Title/index.ts +2 -0
- package/src/components/Toast/Toast.module.scss +299 -0
- package/src/components/Toast/Toast.tokens.scss +65 -0
- package/src/components/Toast/Toast.tsx +122 -0
- package/src/components/Toast/ToastViewport.tsx +166 -0
- package/src/components/Toast/api.ts +175 -0
- package/src/components/Toast/index.ts +5 -0
- package/src/components/Toast/store.ts +133 -0
- package/src/components/Toast/useToastTimer.ts +94 -0
- package/src/components/Tooltip/Tooltip.module.scss +99 -0
- package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
- package/src/components/Tooltip/Tooltip.tsx +341 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/TopBar/TopBar.module.scss +235 -0
- package/src/components/TopBar/TopBar.tokens.scss +79 -0
- package/src/components/TopBar/TopBar.tsx +87 -0
- package/src/components/TopBar/TopBarEnd.tsx +20 -0
- package/src/components/TopBar/TopBarIconButton.tsx +86 -0
- package/src/components/TopBar/TopBarSearch.tsx +319 -0
- package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
- package/src/components/TopBar/TopBarStart.tsx +20 -0
- package/src/components/TopBar/index.ts +11 -0
- package/src/components/Tour/Spotlight.tsx +121 -0
- package/src/components/Tour/Tour.module.scss +210 -0
- package/src/components/Tour/Tour.tokens.scss +58 -0
- package/src/components/Tour/Tour.tsx +617 -0
- package/src/components/Tour/index.ts +2 -0
- package/src/components/Tour/useTourTarget.ts +115 -0
- package/src/components/TreeView/TreeView.module.scss +268 -0
- package/src/components/TreeView/TreeView.tokens.scss +36 -0
- package/src/components/TreeView/TreeView.tsx +536 -0
- package/src/components/TreeView/index.ts +3 -0
- package/src/components/TreeView/treeModel.ts +224 -0
- package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
- package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
- package/src/components/VisuallyHidden/index.ts +2 -0
- package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
- package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
- package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
- package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
- package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
- package/src/components/WidgetPreview/index.ts +2 -0
- package/src/components/_internal/Trend.tsx +27 -0
- package/src/components/_internal/choiceTile.scss +74 -0
- package/src/components/_internal/collapse.scss +10 -0
- package/src/components/_internal/collapse.ts +58 -0
- package/src/components/_internal/currency.ts +257 -0
- package/src/components/_internal/dragAnnouncements.ts +200 -0
- package/src/components/_internal/fieldWiring.ts +225 -0
- package/src/components/_internal/gridSpan.ts +54 -0
- package/src/components/_internal/isoDay.ts +35 -0
- package/src/components/_internal/letterKey.ts +26 -0
- package/src/components/_internal/overlay/focusRestore.ts +21 -0
- package/src/components/_internal/overlay/index.ts +12 -0
- package/src/components/_internal/overlay/tourHold.ts +23 -0
- package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
- package/src/components/_internal/overlay/useInOverlay.ts +81 -0
- package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
- package/src/components/_internal/overlay/useScrollLock.ts +112 -0
- package/src/components/_internal/refs.ts +48 -0
- package/src/components/_internal/statusColor.ts +26 -0
- package/src/components/_internal/timeUtils.ts +23 -0
- package/src/components/_internal/useAsyncOptions.ts +145 -0
- package/src/components/_internal/useClippedTooltip.ts +50 -0
- package/src/components/_internal/useControllableState.ts +50 -0
- package/src/components.manifest.json +1141 -0
- package/src/hooks/useBelowBreakpoint.ts +58 -0
- package/src/i18n/I18nProvider.tsx +52 -0
- package/src/i18n/LocaleProvider.tsx +17 -0
- package/src/i18n/en.ts +648 -0
- package/src/i18n/format.ts +71 -0
- package/src/i18n/index.ts +13 -0
- package/src/i18n/messages.ts +1275 -0
- package/src/i18n/ru.ts +677 -0
- package/src/i18n/useLocale.ts +19 -0
- package/src/i18n/useTranslation.ts +58 -0
- package/src/index.ts +913 -0
- package/src/palette/index.ts +2 -0
- package/src/palette/palette.ts +108 -0
- package/src/styles/dark.scss +4 -0
- package/src/styles/global.scss +7 -0
- package/src/styles/mixins.scss +143 -0
- package/src/styles/reset.scss +78 -0
- package/src/styles/tokens.scss +18 -0
- package/src/styles/typography.scss +44 -0
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useId,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
type HTMLAttributes,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
type Ref,
|
|
12
|
+
} from 'react';
|
|
13
|
+
import clsx from 'clsx';
|
|
14
|
+
import styles from './Select.module.scss';
|
|
15
|
+
import { SelectContext, type SelectContextValue } from './context';
|
|
16
|
+
import { sanitizeId } from '../_internal/refs';
|
|
17
|
+
import { useSelectState } from './useSelectState';
|
|
18
|
+
import { useAsyncOptions } from '../_internal/useAsyncOptions';
|
|
19
|
+
import { flattenOptions, findOption, findOptions, hasExactLabelMatch } from './utils';
|
|
20
|
+
import type { FlatRow } from './utils';
|
|
21
|
+
import { Trigger } from './Trigger';
|
|
22
|
+
import { Listbox } from './Listbox';
|
|
23
|
+
import { HiddenInputs } from './HiddenInputs';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Visual size of the trigger. Mirrors `<Input>` and `<Button>` sizes.
|
|
27
|
+
* - `'sm'` — 24px tall; dense toolbars and tables.
|
|
28
|
+
* - `'md'` — 32px tall (default).
|
|
29
|
+
* - `'lg'` — 40px tall; hero-form prominence.
|
|
30
|
+
*/
|
|
31
|
+
export type SelectSize = 'sm' | 'md' | 'lg';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* How a multi-select renders its selections inside the trigger.
|
|
35
|
+
* - `'chips'` — inline removable chips; wraps vertically as needed (default).
|
|
36
|
+
* - `'summary'` — comma-joined labels with ellipsis on overflow; reads as a single line.
|
|
37
|
+
*/
|
|
38
|
+
export type SelectTriggerDisplay = 'chips' | 'summary';
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* One row of selectable data.
|
|
42
|
+
*
|
|
43
|
+
* `value` is the identity that `onChange` emits and that `value` /
|
|
44
|
+
* `defaultValue` reference. `label` is what the user sees and what
|
|
45
|
+
* the substring filter searches against. `data` is an opaque payload
|
|
46
|
+
* that flows through to `renderOption`, `renderValue`, and `renderTag`.
|
|
47
|
+
*/
|
|
48
|
+
export interface SelectOption<T = unknown> {
|
|
49
|
+
/** Unique key. What `onChange` emits. */
|
|
50
|
+
value: string;
|
|
51
|
+
/** Displayed text. Used for substring search when `searchable` is on. */
|
|
52
|
+
label: string;
|
|
53
|
+
/** Optional secondary line shown under the label in default render. */
|
|
54
|
+
description?: string;
|
|
55
|
+
/** When true, the option is dimmed, `aria-disabled`, and skipped in keyboard nav. */
|
|
56
|
+
disabled?: boolean;
|
|
57
|
+
/** Arbitrary payload — surfaces in `renderOption`, `renderValue`, `renderTag`. */
|
|
58
|
+
data?: T;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A labelled bucket of options. Use grouped input when you want a header
|
|
63
|
+
* row to appear above a chunk of options. Mixing flat options and groups
|
|
64
|
+
* at the same level is not supported — the input must be all-flat or
|
|
65
|
+
* all-grouped.
|
|
66
|
+
*/
|
|
67
|
+
export interface SelectGroup<T = unknown> {
|
|
68
|
+
/** Header text shown above the group's options. */
|
|
69
|
+
label: string;
|
|
70
|
+
/** Members of the group. */
|
|
71
|
+
options: SelectOption<T>[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Either a flat list of options or a list of groups, discriminated at
|
|
76
|
+
* runtime by inspecting whether the first element has an `options` field.
|
|
77
|
+
*/
|
|
78
|
+
export type SelectOptions<T = unknown> = SelectOption<T>[] | SelectGroup<T>[];
|
|
79
|
+
|
|
80
|
+
export interface SelectProps<T = unknown> extends Omit<
|
|
81
|
+
HTMLAttributes<HTMLDivElement>,
|
|
82
|
+
'onChange' | 'defaultValue'
|
|
83
|
+
> {
|
|
84
|
+
/**
|
|
85
|
+
* Placed on the combobox trigger (the `<button>` / `<input>`), not the
|
|
86
|
+
* wrapper div, so a `<label for>` — Field / SettingRow wire one — focuses
|
|
87
|
+
* the control when clicked (#568). Default: a generated id. Target the
|
|
88
|
+
* wrapper by `className` or a `data-*` attribute, not `#id`.
|
|
89
|
+
*/
|
|
90
|
+
id?: string;
|
|
91
|
+
// ─── data ─────────────────────────────────────────────────────────────────
|
|
92
|
+
/**
|
|
93
|
+
* Sync options — flat list or list of groups. Ignored when `loadOptions`
|
|
94
|
+
* is provided (dev warning fires if both are non-empty). For grouped
|
|
95
|
+
* input, every element must carry an `options` field; mixing flat options
|
|
96
|
+
* with groups at the same level is not supported.
|
|
97
|
+
*/
|
|
98
|
+
options?: SelectOptions<T>;
|
|
99
|
+
|
|
100
|
+
// ─── async data ───────────────────────────────────────────────────────────
|
|
101
|
+
/**
|
|
102
|
+
* Async fetcher that returns the options for a given query. When set, the
|
|
103
|
+
* Select switches to async mode: the local substring filter is bypassed
|
|
104
|
+
* (the server filters), loading/error/empty rows replace the listbox
|
|
105
|
+
* body, and `options` is ignored (with a dev warning). The `signal`
|
|
106
|
+
* argument is aborted whenever a newer query supersedes this one — wire
|
|
107
|
+
* it through to `fetch` to cancel in-flight requests.
|
|
108
|
+
*/
|
|
109
|
+
loadOptions?: (query: string, signal: AbortSignal) => Promise<SelectOptions<T>>;
|
|
110
|
+
/**
|
|
111
|
+
* When `true` (default), defers the first `loadOptions` call until the
|
|
112
|
+
* user opens the listbox. Set to `false` to fetch eagerly on mount.
|
|
113
|
+
*/
|
|
114
|
+
loadOnOpen?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Debounce window (ms) between the last query keystroke and the next
|
|
117
|
+
* `loadOptions` call. Default `250`.
|
|
118
|
+
*/
|
|
119
|
+
searchDebounceMs?: number;
|
|
120
|
+
|
|
121
|
+
// ─── mode ─────────────────────────────────────────────────────────────────
|
|
122
|
+
/**
|
|
123
|
+
* Enables multi-select. `value` / `defaultValue` become `string[]` and
|
|
124
|
+
* `onChange` emits arrays. Picking a row toggles it in/out of the
|
|
125
|
+
* selection instead of replacing-and-closing.
|
|
126
|
+
*/
|
|
127
|
+
multiple?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* How the trigger renders the selected value(s) in multi mode. Ignored
|
|
130
|
+
* in single mode. See `SelectTriggerDisplay`. Defaults to `'chips'`. Use
|
|
131
|
+
* `'summary'` for table-filter UIs where chips would crowd the toolbar.
|
|
132
|
+
*/
|
|
133
|
+
triggerDisplay?: SelectTriggerDisplay;
|
|
134
|
+
/**
|
|
135
|
+
* Renders the trigger as a combobox text input with substring filtering
|
|
136
|
+
* over the (sync) options. In async mode the filter is delegated to the
|
|
137
|
+
* server. Required by `creatable`.
|
|
138
|
+
*/
|
|
139
|
+
searchable?: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* When the searchable combobox opens, select the current text so the user
|
|
142
|
+
* can immediately type to replace it (type-to-search). Default `false`.
|
|
143
|
+
* Only affects the single searchable trigger.
|
|
144
|
+
*/
|
|
145
|
+
selectOnOpen?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Adds a "+ Create <query>" row when the trimmed query has no exact
|
|
148
|
+
* label match. Activating it fires `onCreate(label)` and folds the new
|
|
149
|
+
* value into the selection. Requires `searchable` (throws in dev otherwise).
|
|
150
|
+
*/
|
|
151
|
+
creatable?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Fires when the user activates the "+ Create" row (creatable mode).
|
|
154
|
+
* The trimmed query string is passed as `label`. After this fires,
|
|
155
|
+
* the Select also calls `onChange` with the new value: in single mode
|
|
156
|
+
* the value replaces the current selection and the listbox closes; in
|
|
157
|
+
* multi mode the value is appended to the current selection and the
|
|
158
|
+
* query is cleared.
|
|
159
|
+
*
|
|
160
|
+
* Consumers typically use this hook to persist the new option upstream
|
|
161
|
+
* (e.g. POST to a backend) and reconcile their `options` array.
|
|
162
|
+
*/
|
|
163
|
+
onCreate?: (label: string) => void;
|
|
164
|
+
|
|
165
|
+
// ─── value ────────────────────────────────────────────────────────────────
|
|
166
|
+
/**
|
|
167
|
+
* Controlled selection. `string` in single mode, `string[]` in multi.
|
|
168
|
+
* Provide alongside `onChange` to drive the value externally.
|
|
169
|
+
*
|
|
170
|
+
* `''` is NOT reserved for "nothing selected". If your `options` contain
|
|
171
|
+
* an option whose `value` is `''` — the common "one sentinel row plus N
|
|
172
|
+
* catalog ids" shape — that option renders and selects like any other, and
|
|
173
|
+
* the trigger shows its label. "Nothing selected" means simply "the value
|
|
174
|
+
* matches no option", which is what an untouched Select resolves to when
|
|
175
|
+
* the list has no `''` row.
|
|
176
|
+
*/
|
|
177
|
+
value?: string | string[];
|
|
178
|
+
/**
|
|
179
|
+
* Initial selection for uncontrolled usage. `string` in single mode,
|
|
180
|
+
* `string[]` in multi. Ignored when `value` is provided.
|
|
181
|
+
*/
|
|
182
|
+
defaultValue?: string | string[];
|
|
183
|
+
/**
|
|
184
|
+
* Fires when the selection changes. The first argument is the next
|
|
185
|
+
* value (`string` in single mode, `string[]` in multi). The second
|
|
186
|
+
* argument is the matched `SelectOption` (single), the matched array
|
|
187
|
+
* (multi), or `null` when the selection clears in single mode. For
|
|
188
|
+
* creatable rows not present in `options`, a synthetic
|
|
189
|
+
* `{ value, label: value }` is supplied.
|
|
190
|
+
*
|
|
191
|
+
* The match is a lookup, not an emptiness test: an emitted `''` yields the
|
|
192
|
+
* matching `SelectOption` when your `options` contain a `value: ''` row,
|
|
193
|
+
* and `null` only when they don't (a genuine clear).
|
|
194
|
+
*/
|
|
195
|
+
onChange?: (value: string | string[], option: SelectOption<T> | SelectOption<T>[] | null) => void;
|
|
196
|
+
|
|
197
|
+
// ─── open state (controlled, rare) ────────────────────────────────────────
|
|
198
|
+
/**
|
|
199
|
+
* Controlled open state. Pair with `onOpenChange`. Omit both to let
|
|
200
|
+
* Select own its open state (the common case).
|
|
201
|
+
*/
|
|
202
|
+
open?: boolean;
|
|
203
|
+
/** Initial open state for uncontrolled usage. Defaults to `false`. */
|
|
204
|
+
defaultOpen?: boolean;
|
|
205
|
+
/** Fires whenever Select wants to change open state. */
|
|
206
|
+
onOpenChange?: (open: boolean) => void;
|
|
207
|
+
|
|
208
|
+
// ─── visuals ──────────────────────────────────────────────────────────────
|
|
209
|
+
/** Trigger height + type scale. See `SelectSize`. Defaults to `'md'`. */
|
|
210
|
+
size?: SelectSize;
|
|
211
|
+
/**
|
|
212
|
+
* Marks the trigger as invalid — applies the error border + sets
|
|
213
|
+
* `aria-invalid="true"`. Pair with an external error message linked via
|
|
214
|
+
* `aria-describedby`.
|
|
215
|
+
*/
|
|
216
|
+
invalid?: boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Placeholder shown when nothing is selected. In searchable mode, also
|
|
219
|
+
* the input's `placeholder` until the user types.
|
|
220
|
+
*/
|
|
221
|
+
placeholder?: string;
|
|
222
|
+
/**
|
|
223
|
+
* Shows a `✕` button in the trigger that clears the selection. Opt-in:
|
|
224
|
+
* defaults to `false`. Always forced `false` when `disabled` or `readOnly`.
|
|
225
|
+
*
|
|
226
|
+
* "Clear" means "reset to the empty value" (`''` / `[]`), so the button
|
|
227
|
+
* only appears when the current value differs from that. A Select whose
|
|
228
|
+
* selected option IS `value: ''` is already at the cleared value and shows
|
|
229
|
+
* no ✕; a value matching no option (a stale id) does show one.
|
|
230
|
+
*/
|
|
231
|
+
clearable?: boolean;
|
|
232
|
+
|
|
233
|
+
// ─── states ───────────────────────────────────────────────────────────────
|
|
234
|
+
/**
|
|
235
|
+
* Disables the trigger entirely — non-interactive, dimmed, focusable
|
|
236
|
+
* only via assistive tech. Hidden form inputs are also disabled.
|
|
237
|
+
*/
|
|
238
|
+
disabled?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* Read-only — trigger is focusable but cannot open or change the
|
|
241
|
+
* selection. Useful for displaying a value inside a form that's not yet
|
|
242
|
+
* editable.
|
|
243
|
+
*/
|
|
244
|
+
readOnly?: boolean;
|
|
245
|
+
|
|
246
|
+
// ─── form integration ─────────────────────────────────────────────────────
|
|
247
|
+
/**
|
|
248
|
+
* Name attribute for native form submission. In multi mode, one hidden
|
|
249
|
+
* `<input>` per selected value is emitted (so `FormData.getAll(name)`
|
|
250
|
+
* returns the array).
|
|
251
|
+
*/
|
|
252
|
+
name?: string;
|
|
253
|
+
/**
|
|
254
|
+
* Marks the field as required. The trigger exposes `aria-required="true"` to
|
|
255
|
+
* assistive technology. Hidden inputs still serialize named values, but they do
|
|
256
|
+
* not participate in native constraint validation; validate the selection in
|
|
257
|
+
* your form layer.
|
|
258
|
+
*/
|
|
259
|
+
required?: boolean;
|
|
260
|
+
/** `form` attribute forwarded to the hidden `<input>` elements. */
|
|
261
|
+
form?: string;
|
|
262
|
+
|
|
263
|
+
// ─── render escape hatches ────────────────────────────────────────────────
|
|
264
|
+
/**
|
|
265
|
+
* Custom renderer for a row inside the listbox. Receives the option and
|
|
266
|
+
* its current `{ active, selected }` state (active = keyboard-focused
|
|
267
|
+
* row, selected = part of the current value). The returned node
|
|
268
|
+
* replaces the default label / description layout — chrome (padding,
|
|
269
|
+
* background, `aria-*`) stays.
|
|
270
|
+
*/
|
|
271
|
+
renderOption?: (opt: SelectOption<T>, state: { active: boolean; selected: boolean }) => ReactNode;
|
|
272
|
+
/**
|
|
273
|
+
* Custom renderer for the selected value inside the single-mode trigger.
|
|
274
|
+
* Ignored in multi mode (see `renderTag`).
|
|
275
|
+
*/
|
|
276
|
+
renderValue?: (opt: SelectOption<T>) => ReactNode;
|
|
277
|
+
/**
|
|
278
|
+
* Custom renderer for a chip inside the multi-mode `chips` trigger.
|
|
279
|
+
* Receives the option and a `remove` callback that deselects it. Ignored
|
|
280
|
+
* in single mode and in `triggerDisplay='summary'`.
|
|
281
|
+
*/
|
|
282
|
+
renderTag?: (opt: SelectOption<T>, remove: () => void) => ReactNode;
|
|
283
|
+
/**
|
|
284
|
+
* Custom empty-state renderer. Fires when the filtered listbox has no
|
|
285
|
+
* rows. Receives the current trimmed query for use in messages like
|
|
286
|
+
* "No matches for 'foo'".
|
|
287
|
+
*/
|
|
288
|
+
renderEmpty?: (query: string) => ReactNode;
|
|
289
|
+
/** Custom loading-state renderer for async mode. */
|
|
290
|
+
renderLoading?: () => ReactNode;
|
|
291
|
+
/**
|
|
292
|
+
* Custom error-state renderer for async mode. Receives the thrown
|
|
293
|
+
* `Error` and a `retry` callback that re-invokes `loadOptions` with the
|
|
294
|
+
* current query.
|
|
295
|
+
*/
|
|
296
|
+
renderError?: (err: Error, retry: () => void) => ReactNode;
|
|
297
|
+
|
|
298
|
+
// ─── ARIA ─────────────────────────────────────────────────────────────────
|
|
299
|
+
/**
|
|
300
|
+
* Accessible name for the trigger. Use this when a visible `<label>` is
|
|
301
|
+
* not present. Mutually exclusive with `aria-labelledby`.
|
|
302
|
+
*/
|
|
303
|
+
'aria-label'?: string;
|
|
304
|
+
/**
|
|
305
|
+
* ID of an element that labels the trigger. Use when the label is a
|
|
306
|
+
* sibling node (e.g. a `<Field>` label).
|
|
307
|
+
*/
|
|
308
|
+
'aria-labelledby'?: string;
|
|
309
|
+
/**
|
|
310
|
+
* ID of an element that describes the trigger — e.g. an error message
|
|
311
|
+
* or helper hint paired with `invalid`.
|
|
312
|
+
*/
|
|
313
|
+
'aria-describedby'?: string;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const SelectImpl = forwardRef<HTMLDivElement, SelectProps>(function Select(
|
|
317
|
+
props: SelectProps,
|
|
318
|
+
ref: Ref<HTMLDivElement>,
|
|
319
|
+
) {
|
|
320
|
+
const {
|
|
321
|
+
options = [],
|
|
322
|
+
loadOptions,
|
|
323
|
+
loadOnOpen = true,
|
|
324
|
+
searchDebounceMs = 250,
|
|
325
|
+
multiple = false,
|
|
326
|
+
triggerDisplay = 'chips',
|
|
327
|
+
searchable = false,
|
|
328
|
+
creatable = false,
|
|
329
|
+
onCreate,
|
|
330
|
+
value: controlledValue,
|
|
331
|
+
defaultValue,
|
|
332
|
+
onChange,
|
|
333
|
+
open: controlledOpen,
|
|
334
|
+
defaultOpen,
|
|
335
|
+
onOpenChange,
|
|
336
|
+
size = 'md',
|
|
337
|
+
invalid = false,
|
|
338
|
+
placeholder,
|
|
339
|
+
clearable,
|
|
340
|
+
selectOnOpen = false,
|
|
341
|
+
disabled = false,
|
|
342
|
+
readOnly = false,
|
|
343
|
+
name,
|
|
344
|
+
required,
|
|
345
|
+
form,
|
|
346
|
+
'aria-label': ariaLabel,
|
|
347
|
+
'aria-labelledby': ariaLabelledby,
|
|
348
|
+
'aria-describedby': ariaDescribedby,
|
|
349
|
+
'aria-required': ariaRequired,
|
|
350
|
+
renderOption,
|
|
351
|
+
renderValue,
|
|
352
|
+
renderTag,
|
|
353
|
+
renderEmpty,
|
|
354
|
+
renderLoading,
|
|
355
|
+
renderError,
|
|
356
|
+
className,
|
|
357
|
+
id,
|
|
358
|
+
...rest
|
|
359
|
+
} = props;
|
|
360
|
+
|
|
361
|
+
// Dev-only invariant: a creatable picker without a search input has no
|
|
362
|
+
// way to capture the new label. Throw early so the misconfiguration is
|
|
363
|
+
// obvious during development; stripped in prod builds.
|
|
364
|
+
if (process.env.NODE_ENV !== 'production' && creatable && !searchable) {
|
|
365
|
+
throw new Error(
|
|
366
|
+
'<Select>: `creatable` requires `searchable`. A creatable picker without a search input has no way to capture the new label.',
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const reactId = useId();
|
|
371
|
+
const idBase = sanitizeId(reactId);
|
|
372
|
+
const listboxId = `select-listbox-${idBase}`;
|
|
373
|
+
// A consumer / Field-wired `id` goes on the combobox itself, not the wrapper
|
|
374
|
+
// div — it is the labelable element, so `<label for>` focuses it (#568).
|
|
375
|
+
const triggerId = id ?? `select-trigger-${idBase}`;
|
|
376
|
+
const getOptionId = useCallback((v: string) => `select-opt-${idBase}-${sanitizeId(v)}`, [idBase]);
|
|
377
|
+
const getGroupHeaderId = useCallback(
|
|
378
|
+
(label: string) => `select-grp-${idBase}-${sanitizeId(label)}`,
|
|
379
|
+
[idBase],
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
// The option set the `onChange` wrapper resolves against. It has to be
|
|
383
|
+
// `effectiveOptions` (below) rather than the `options` prop: in async mode
|
|
384
|
+
// the backend's response replaces `options` entirely, so resolving against
|
|
385
|
+
// the prop would hand every async selection a synthetic
|
|
386
|
+
// `{ value, label: value }` — and would report a server-supplied
|
|
387
|
+
// `value: ''` row as `null`, reintroducing exactly the bug #470 fixes.
|
|
388
|
+
// A ref because `effectiveOptions` is derived after this hook runs.
|
|
389
|
+
const lookupOptionsRef = useRef<SelectOptions>(options);
|
|
390
|
+
|
|
391
|
+
// `onChange` is wrapped to look up the SelectOption(s) and pass them as
|
|
392
|
+
// the second arg. `findOption` / `findOptions` are O(n); for the option
|
|
393
|
+
// counts a Select handles in practice this is fine and keeps the public
|
|
394
|
+
// API ergonomic (consumers get the matched payload, not just the id).
|
|
395
|
+
//
|
|
396
|
+
// Creatable: when the user accepts the "+ Create" row, the new value is
|
|
397
|
+
// not in `options`. Back-fill a synthetic `{ value: v, label: v }` so
|
|
398
|
+
// consumers still receive a stable option payload for the new row —
|
|
399
|
+
// mirrors the shape the create-row carries internally.
|
|
400
|
+
const state = useSelectState({
|
|
401
|
+
multiple,
|
|
402
|
+
value: controlledValue,
|
|
403
|
+
defaultValue,
|
|
404
|
+
onChange: (v) => {
|
|
405
|
+
if (multiple) {
|
|
406
|
+
const values = Array.isArray(v) ? v : [];
|
|
407
|
+
const found = findOptions(lookupOptionsRef.current, values);
|
|
408
|
+
const byValue = new Map(found.map((o) => [o.value, o]));
|
|
409
|
+
const opts = values.map((val) => byValue.get(val) ?? { value: val, label: val });
|
|
410
|
+
onChange?.(v, opts);
|
|
411
|
+
} else if (typeof v === 'string') {
|
|
412
|
+
// Look the value up rather than special-casing `''` (issue #470):
|
|
413
|
+
// `''` is a legitimate option value, and when the consumer supplied
|
|
414
|
+
// such an option its `SelectOption` is the correct payload.
|
|
415
|
+
const opt = findOption(lookupOptionsRef.current, v);
|
|
416
|
+
if (opt) {
|
|
417
|
+
onChange?.(v, opt);
|
|
418
|
+
} else if (v === '') {
|
|
419
|
+
// Empty and NOT an option → the selection was cleared.
|
|
420
|
+
onChange?.(v, null);
|
|
421
|
+
} else {
|
|
422
|
+
// Creatable: a freshly created value isn't in `options` yet (nor is
|
|
423
|
+
// an async-loaded one before its page arrives). Back-fill a
|
|
424
|
+
// synthetic option so consumers still get a stable payload.
|
|
425
|
+
onChange?.(v, { value: v, label: v });
|
|
426
|
+
}
|
|
427
|
+
} else {
|
|
428
|
+
onChange?.(v, null);
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
open: controlledOpen,
|
|
432
|
+
defaultOpen,
|
|
433
|
+
onOpenChange,
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Dev-only sanity check: a Select can't sensibly take both `options` and
|
|
437
|
+
// `loadOptions`. We pick `loadOptions` (the more specific API) and warn
|
|
438
|
+
// so the consumer notices their config conflict during dev. Stripped in
|
|
439
|
+
// prod builds by the bundler dead-code path.
|
|
440
|
+
if (
|
|
441
|
+
process.env.NODE_ENV !== 'production' &&
|
|
442
|
+
loadOptions &&
|
|
443
|
+
Array.isArray(options) &&
|
|
444
|
+
options.length > 0
|
|
445
|
+
) {
|
|
446
|
+
console.warn(
|
|
447
|
+
'<Select> received both `options` and `loadOptions`. `loadOptions` wins; `options` is ignored.',
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const [activeIndex, setActiveIndex] = useState<number>(-1);
|
|
452
|
+
const [query, setQuery] = useState<string>('');
|
|
453
|
+
|
|
454
|
+
// `hasOpenedOnce` gates the first async fetch. The `loadOnOpen` semantic
|
|
455
|
+
// is: don't fetch anything until the user opens the popover at least
|
|
456
|
+
// once. `loadOnOpen=false` flips the gate immediately on mount.
|
|
457
|
+
const [hasOpenedOnce, setHasOpenedOnce] = useState<boolean>(!loadOnOpen);
|
|
458
|
+
useEffect(() => {
|
|
459
|
+
if (state.open && !hasOpenedOnce) setHasOpenedOnce(true);
|
|
460
|
+
}, [state.open, hasOpenedOnce]);
|
|
461
|
+
|
|
462
|
+
const asyncEnabled = !!loadOptions && hasOpenedOnce;
|
|
463
|
+
const asyncResult = useAsyncOptions({
|
|
464
|
+
loadOptions,
|
|
465
|
+
query,
|
|
466
|
+
enabled: asyncEnabled,
|
|
467
|
+
debounceMs: searchDebounceMs,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// In async mode, the backend's response replaces the local `options`
|
|
471
|
+
// entirely. The label cache for already-selected values is a Phase 8+
|
|
472
|
+
// concern — chips may temporarily render `<unknown>` while the latest
|
|
473
|
+
// server response filters their option out.
|
|
474
|
+
const effectiveOptions = loadOptions ? asyncResult.options : options;
|
|
475
|
+
lookupOptionsRef.current = effectiveOptions;
|
|
476
|
+
const allRows = useMemo(() => flattenOptions(effectiveOptions), [effectiveOptions]);
|
|
477
|
+
|
|
478
|
+
// When `searchable`, filter `allRows` by the query (case-insensitive
|
|
479
|
+
// substring on label OR description). Group headers are retained only
|
|
480
|
+
// when at least one option underneath them matches — a header sitting
|
|
481
|
+
// alone in the listbox is noise.
|
|
482
|
+
//
|
|
483
|
+
// Empty query short-circuits to the unfiltered list so the open-effect
|
|
484
|
+
// in Listbox lands on the user's selected row, and so the first
|
|
485
|
+
// ArrowDown after open lands on row 0 instead of row 0-of-filtered.
|
|
486
|
+
const rows = useMemo(() => {
|
|
487
|
+
// Async mode: the backend already filtered to the current query, so
|
|
488
|
+
// local re-filtering would double-filter (e.g. backend matches by
|
|
489
|
+
// word-prefix, we'd then drop rows whose label doesn't contain the
|
|
490
|
+
// exact substring).
|
|
491
|
+
if (loadOptions) return allRows;
|
|
492
|
+
if (!searchable || query.trim() === '') return allRows;
|
|
493
|
+
const q = query.toLowerCase();
|
|
494
|
+
const out: typeof allRows = [];
|
|
495
|
+
let pendingHeader: (typeof allRows)[number] | null = null;
|
|
496
|
+
for (const row of allRows) {
|
|
497
|
+
if (row.kind === 'header') {
|
|
498
|
+
pendingHeader = row;
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
const matches =
|
|
502
|
+
row.option.label.toLowerCase().includes(q) ||
|
|
503
|
+
(row.option.description?.toLowerCase().includes(q) ?? false);
|
|
504
|
+
if (matches) {
|
|
505
|
+
if (pendingHeader) {
|
|
506
|
+
out.push(pendingHeader);
|
|
507
|
+
pendingHeader = null;
|
|
508
|
+
}
|
|
509
|
+
out.push(row);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return out;
|
|
513
|
+
}, [allRows, searchable, query, loadOptions]);
|
|
514
|
+
|
|
515
|
+
// Creatable: compute an extra "+ Create <query>" row when the trimmed
|
|
516
|
+
// query has no exact label match in the available options AND, in multi
|
|
517
|
+
// mode, isn't already in the current selection. The sentinel
|
|
518
|
+
// `{ __create: true }` on `data` is what `isCreateRow` matches, and what
|
|
519
|
+
// the listbox + keyboard handlers branch on to fire `onCreate` instead
|
|
520
|
+
// of the normal select/toggle flow.
|
|
521
|
+
const createRow: FlatRow | null = useMemo(() => {
|
|
522
|
+
const trimmed = query.trim();
|
|
523
|
+
if (!creatable || !searchable || trimmed === '') return null;
|
|
524
|
+
if (hasExactLabelMatch(effectiveOptions, trimmed)) return null;
|
|
525
|
+
if (multiple) {
|
|
526
|
+
const currentValues = Array.isArray(state.value) ? (state.value as string[]) : [];
|
|
527
|
+
if (currentValues.some((v) => v.toLowerCase() === trimmed.toLowerCase())) return null;
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
kind: 'option' as const,
|
|
531
|
+
option: {
|
|
532
|
+
value: trimmed,
|
|
533
|
+
label: trimmed,
|
|
534
|
+
data: { __create: true } as unknown,
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
}, [creatable, searchable, query, effectiveOptions, multiple, state.value]);
|
|
538
|
+
|
|
539
|
+
// Append the create row to the end of the filtered (or async) rows. The
|
|
540
|
+
// unfiltered `allRows` deliberately does NOT include the create row —
|
|
541
|
+
// chip / summary label lookups walk `allRows` and the create row has no
|
|
542
|
+
// selected counterpart there.
|
|
543
|
+
const rowsWithCreate = useMemo(() => {
|
|
544
|
+
return createRow ? [...rows, createRow] : rows;
|
|
545
|
+
}, [rows, createRow]);
|
|
546
|
+
|
|
547
|
+
// #309: filtering while open rebuilds `rows`, but `activeIndex` is a flat
|
|
548
|
+
// index — keeping it points the highlight at whatever row now occupies
|
|
549
|
+
// that slot (or past the end, hiding it). Re-seed to the first selectable
|
|
550
|
+
// row whenever the QUERY changes while open. The open transition is
|
|
551
|
+
// excluded (the Listbox open-seed effect highlights the current selection
|
|
552
|
+
// there); non-query row changes (multi toggle, async refresh with the
|
|
553
|
+
// same query) keep the cursor.
|
|
554
|
+
// ponytail: in async mode this fires against the pre-fetch rows (results
|
|
555
|
+
// land after the debounce); first-selectable is almost always index 0
|
|
556
|
+
// either way. Re-seed on async arrival too if a palette with leading
|
|
557
|
+
// disabled rows ever makes this visible.
|
|
558
|
+
const prevQueryRef = useRef(query);
|
|
559
|
+
useEffect(() => {
|
|
560
|
+
if (prevQueryRef.current === query) return;
|
|
561
|
+
prevQueryRef.current = query;
|
|
562
|
+
if (!state.open) return;
|
|
563
|
+
setActiveIndex(rowsWithCreate.findIndex((r) => r.kind === 'option' && !r.option.disabled));
|
|
564
|
+
// rowsWithCreate is read fresh (it recomputes in the same render as the
|
|
565
|
+
// query) but must not itself re-trigger the reseed — non-query row
|
|
566
|
+
// changes keep the cursor (see above).
|
|
567
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
568
|
+
}, [query, state.open]);
|
|
569
|
+
|
|
570
|
+
// Safety net for every OTHER row-shrink path (async results landing after
|
|
571
|
+
// arrow-key navigation, a mid-open `options` prop change): a cursor past
|
|
572
|
+
// the end of the rebuilt list is meaningless — re-seed it. Never fires for
|
|
573
|
+
// an in-bounds cursor, so it cannot steal a valid position.
|
|
574
|
+
useEffect(() => {
|
|
575
|
+
if (!state.open || activeIndex < rowsWithCreate.length) return;
|
|
576
|
+
setActiveIndex(rowsWithCreate.findIndex((r) => r.kind === 'option' && !r.option.disabled));
|
|
577
|
+
}, [state.open, activeIndex, rowsWithCreate]);
|
|
578
|
+
|
|
579
|
+
const triggerRef = useRef<HTMLElement | null>(null);
|
|
580
|
+
const triggerRootRef = useRef<HTMLElement | null>(null);
|
|
581
|
+
const listboxRef = useRef<HTMLDivElement | null>(null);
|
|
582
|
+
|
|
583
|
+
// `clearable` is opt-in: the ✕ clear button defaults OFF and only shows when a
|
|
584
|
+
// consumer explicitly sets `clearable`. `disabled` / `readOnly` always suppress it
|
|
585
|
+
// (the trigger is non-interactive in those states).
|
|
586
|
+
const effectiveClearable = (clearable ?? false) && !disabled && !readOnly;
|
|
587
|
+
|
|
588
|
+
// Defined inline rather than via useCallback because it captures the
|
|
589
|
+
// current `setOpen` and `triggerRef` — both stable identities — and is
|
|
590
|
+
// only consumed downstream via context, which already memoizes nothing.
|
|
591
|
+
const closeAndFocusTrigger = () => {
|
|
592
|
+
state.setOpen(false);
|
|
593
|
+
queueMicrotask(() => triggerRef.current?.focus({ preventScroll: true }));
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const ctxValue: SelectContextValue = {
|
|
597
|
+
multiple,
|
|
598
|
+
searchable,
|
|
599
|
+
creatable,
|
|
600
|
+
triggerDisplay,
|
|
601
|
+
rows: rowsWithCreate,
|
|
602
|
+
allRows,
|
|
603
|
+
loading: loadOptions ? asyncResult.loading : false,
|
|
604
|
+
error: loadOptions ? asyncResult.error : null,
|
|
605
|
+
loadedQuery: loadOptions ? asyncResult.loadedQuery : undefined,
|
|
606
|
+
value: state.value,
|
|
607
|
+
setValue: state.setValue,
|
|
608
|
+
toggleValue: state.toggleValue,
|
|
609
|
+
open: state.open,
|
|
610
|
+
setOpen: state.setOpen,
|
|
611
|
+
activeIndex,
|
|
612
|
+
setActiveIndex,
|
|
613
|
+
query,
|
|
614
|
+
setQuery,
|
|
615
|
+
listboxId,
|
|
616
|
+
triggerId,
|
|
617
|
+
getOptionId,
|
|
618
|
+
getGroupHeaderId,
|
|
619
|
+
triggerRef,
|
|
620
|
+
triggerRootRef,
|
|
621
|
+
listboxRef,
|
|
622
|
+
closeAndFocusTrigger,
|
|
623
|
+
retry: asyncResult.retry,
|
|
624
|
+
onCreate,
|
|
625
|
+
renderOption: renderOption as SelectContextValue['renderOption'],
|
|
626
|
+
renderValue: renderValue as SelectContextValue['renderValue'],
|
|
627
|
+
renderTag: renderTag as SelectContextValue['renderTag'],
|
|
628
|
+
renderEmpty,
|
|
629
|
+
renderLoading,
|
|
630
|
+
renderError,
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
return (
|
|
634
|
+
<SelectContext.Provider value={ctxValue}>
|
|
635
|
+
<div
|
|
636
|
+
ref={ref}
|
|
637
|
+
{...rest}
|
|
638
|
+
className={clsx(
|
|
639
|
+
styles.root,
|
|
640
|
+
styles[`size-${size}`],
|
|
641
|
+
invalid && styles.invalid,
|
|
642
|
+
disabled && styles.disabled,
|
|
643
|
+
readOnly && styles.readOnly,
|
|
644
|
+
className,
|
|
645
|
+
)}
|
|
646
|
+
>
|
|
647
|
+
<Trigger
|
|
648
|
+
placeholder={placeholder}
|
|
649
|
+
disabled={disabled}
|
|
650
|
+
readOnly={readOnly}
|
|
651
|
+
invalid={invalid}
|
|
652
|
+
clearable={effectiveClearable}
|
|
653
|
+
selectOnOpen={selectOnOpen}
|
|
654
|
+
aria-label={ariaLabel}
|
|
655
|
+
aria-labelledby={ariaLabelledby}
|
|
656
|
+
aria-describedby={ariaDescribedby}
|
|
657
|
+
aria-required={required ? true : ariaRequired}
|
|
658
|
+
/>
|
|
659
|
+
{state.open && <Listbox />}
|
|
660
|
+
<HiddenInputs
|
|
661
|
+
name={name}
|
|
662
|
+
value={state.value}
|
|
663
|
+
multiple={multiple}
|
|
664
|
+
required={required ?? false}
|
|
665
|
+
form={form}
|
|
666
|
+
disabled={disabled}
|
|
667
|
+
/>
|
|
668
|
+
</div>
|
|
669
|
+
</SelectContext.Provider>
|
|
670
|
+
);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Value picker covering single, multi (chips and summary), searchable, grouped, async-loaded and creatable patterns.
|
|
675
|
+
* @see docs/components/Select.md
|
|
676
|
+
*/
|
|
677
|
+
// `Select` is exposed via a cast so the public type is generic over `T`
|
|
678
|
+
// — `forwardRef` does not preserve the generic parameter through its own
|
|
679
|
+
// signature. Internally `SelectImpl` is the forwardRef component; the cast
|
|
680
|
+
// only rewrites its type surface. Do not "fix" this by dropping the cast —
|
|
681
|
+
// you'll lose the `T` inference that flows from `options` into `onChange`'s
|
|
682
|
+
// option payload.
|
|
683
|
+
export const Select = SelectImpl as <T = unknown>(
|
|
684
|
+
props: SelectProps<T> & { ref?: Ref<HTMLDivElement> },
|
|
685
|
+
) => React.ReactElement;
|