@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,557 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useRef, useState, type ReactNode } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import {
|
|
4
|
+
autoUpdate,
|
|
5
|
+
flip,
|
|
6
|
+
offset,
|
|
7
|
+
shift,
|
|
8
|
+
size as floatingSize,
|
|
9
|
+
useFloating,
|
|
10
|
+
} from '@floating-ui/react-dom';
|
|
11
|
+
import clsx from 'clsx';
|
|
12
|
+
import { useTranslation } from '../../i18n/useTranslation';
|
|
13
|
+
import { emptyStateText } from './emptyStateText';
|
|
14
|
+
import { useSelectContext, type SelectContextValue } from './context';
|
|
15
|
+
import { mergeRefs } from '../_internal/refs';
|
|
16
|
+
import { isTourHeld, overlayStack, useFloatingSurface, useInOverlay } from '../_internal/overlay';
|
|
17
|
+
import type { SelectOption } from './utils-types';
|
|
18
|
+
import { isCreateRow } from './utils';
|
|
19
|
+
import { Empty } from './Empty';
|
|
20
|
+
import { Loading } from './Loading';
|
|
21
|
+
import { ErrorRow } from './Error';
|
|
22
|
+
import styles from './Select.module.scss';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Portaled listbox panel. Positioned by Floating UI relative to the
|
|
26
|
+
* trigger, dismissed on outside-click and Escape, restores active row
|
|
27
|
+
* to the current selection (or first selectable) on open.
|
|
28
|
+
*
|
|
29
|
+
* Only mounted when `ctx.open` is true — there is no exit animation
|
|
30
|
+
* because the node is unmounted. Click-to-select is wired here; the
|
|
31
|
+
* keyboard handlers live on the Trigger so the trigger keeps focus
|
|
32
|
+
* while the listbox is open (combobox / single-mode-button pattern).
|
|
33
|
+
*/
|
|
34
|
+
export function Listbox() {
|
|
35
|
+
const ctx = useSelectContext('Listbox');
|
|
36
|
+
const { setOpen, closeAndFocusTrigger } = ctx;
|
|
37
|
+
const t = useTranslation();
|
|
38
|
+
|
|
39
|
+
// Deferred by a tick so a listbox that OPENS already loading still
|
|
40
|
+
// announces — mounting region and text together announces nothing.
|
|
41
|
+
const [statusText, setStatusText] = useState('');
|
|
42
|
+
// Synchronous Select: emptiness is always a result. Async: only once the
|
|
43
|
+
// settled query matches the one on screen.
|
|
44
|
+
const emptyIsSettled = ctx.loadedQuery === undefined || ctx.loadedQuery === ctx.query;
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
// Error included. Dropping `role="alert"` from the error row removed the
|
|
47
|
+
// one Select announcement that actually worked — `alert` is specified to
|
|
48
|
+
// announce content inserted together with its node, so it was not one of
|
|
49
|
+
// the three broken mechanisms. Without this the region reset to '' on
|
|
50
|
+
// rejection and the failure was silent.
|
|
51
|
+
// Empty included, but only once the emptiness is a RESULT. For an async
|
|
52
|
+
// Select, `loading` is false for the entire debounce window while the rows
|
|
53
|
+
// are still the previous query's — so this announced "No options." on every
|
|
54
|
+
// open before the first fetch started, and "No results for X" about a
|
|
55
|
+
// search that had not run, re-firing per keystroke because the
|
|
56
|
+
// interpolated query made each string distinct. A synchronous Select has
|
|
57
|
+
// no such window and announces immediately.
|
|
58
|
+
//
|
|
59
|
+
// "Nothing matched" is the most useful thing a Select can say — a keyboard user typing into a combobox gets no other signal that
|
|
60
|
+
// the list went empty — and it was announced by nothing: the row carries
|
|
61
|
+
// no live region and this one did not cover the state. Hard rule 10 wants
|
|
62
|
+
// chosen silence written down, and this silence was not chosen.
|
|
63
|
+
setStatusText(
|
|
64
|
+
ctx.error
|
|
65
|
+
? t('select.loadFailed')
|
|
66
|
+
: ctx.loading && ctx.rows.length === 0
|
|
67
|
+
? t('select.statusLoading')
|
|
68
|
+
: ctx.rows.length === 0 && emptyIsSettled
|
|
69
|
+
? emptyStateText(t, ctx.query)
|
|
70
|
+
: '',
|
|
71
|
+
);
|
|
72
|
+
// `ctx.error` is in the deps deliberately. It happens to work without it
|
|
73
|
+
// — a rejection also flips `loading` — but that is a coincidence of the
|
|
74
|
+
// current hook, and there is no eslint in this repo to catch the day it
|
|
75
|
+
// stops being true.
|
|
76
|
+
}, [ctx.error, ctx.loading, ctx.rows.length, ctx.query, emptyIsSettled, t]);
|
|
77
|
+
const inOverlay = useInOverlay(ctx.triggerRootRef, ctx.open);
|
|
78
|
+
// #274: hosts yield Escape while we're open — our own capture/element
|
|
79
|
+
// handler closes us on the same press instead of the Modal/Drawer.
|
|
80
|
+
const floatingId = useFloatingSurface(ctx.open);
|
|
81
|
+
|
|
82
|
+
const widestRef = useRef(0);
|
|
83
|
+
const { refs, floatingStyles, isPositioned } = useFloating({
|
|
84
|
+
open: ctx.open,
|
|
85
|
+
placement: 'bottom-start',
|
|
86
|
+
// `transform: false` — emit `top` / `left` positioning instead of an
|
|
87
|
+
// inline `transform: translate(...)`. The open animation in
|
|
88
|
+
// Select.module.scss animates `transform: scale(...)` on the panel; if
|
|
89
|
+
// Floating UI also wrote `transform`, the keyframe would clobber the
|
|
90
|
+
// inline translate and the panel would visibly snap to the document
|
|
91
|
+
// origin before jumping to the trigger. Matches DropdownMenu and
|
|
92
|
+
// Popover Content.
|
|
93
|
+
transform: false,
|
|
94
|
+
middleware: [
|
|
95
|
+
offset(4),
|
|
96
|
+
flip(),
|
|
97
|
+
shift({ padding: 8 }),
|
|
98
|
+
// Publish a min width + viewport room as CSS vars; `.listbox` turns
|
|
99
|
+
// them into min/max width and max height. Width stays intrinsic so
|
|
100
|
+
// option labels only wrap when the panel would hit its cap or the
|
|
101
|
+
// viewport edge — not because the trigger is narrow. The min width
|
|
102
|
+
// ratchets to the widest the panel has been while open, so filtering
|
|
103
|
+
// or async rows don't make the right edge jump on every keystroke
|
|
104
|
+
// (the Listbox unmounts on close, which resets the ratchet).
|
|
105
|
+
floatingSize({
|
|
106
|
+
padding: 8,
|
|
107
|
+
apply({ rects, availableWidth, availableHeight, elements }) {
|
|
108
|
+
const s = elements.floating.style;
|
|
109
|
+
const minWidth = () => `${Math.max(rects.reference.width, widestRef.current)}px`;
|
|
110
|
+
s.setProperty('--select-listbox-min-width', minWidth());
|
|
111
|
+
s.setProperty('--select-listbox-available-width', `${Math.max(0, availableWidth)}px`);
|
|
112
|
+
s.setProperty('--select-listbox-available-height', `${Math.max(0, availableHeight)}px`);
|
|
113
|
+
// Written twice on purpose: the first write lets a grown trigger
|
|
114
|
+
// widen the panel before it is measured; the second locks the
|
|
115
|
+
// measured width in as the new floor.
|
|
116
|
+
widestRef.current = Math.max(widestRef.current, elements.floating.offsetWidth);
|
|
117
|
+
s.setProperty('--select-listbox-min-width', minWidth());
|
|
118
|
+
},
|
|
119
|
+
}),
|
|
120
|
+
],
|
|
121
|
+
whileElementsMounted: autoUpdate,
|
|
122
|
+
elements: { reference: ctx.triggerRootRef.current },
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Outside-click closes. Capture-phase pointerdown fires before any
|
|
126
|
+
// focused widget's handlers, matching the Popover / DropdownMenu
|
|
127
|
+
// patterns. Clicks on the trigger are excluded so its own toggle
|
|
128
|
+
// handler isn't double-fired; clicks on the panel are excluded so
|
|
129
|
+
// option clicks aren't swallowed (they also preventDefault on
|
|
130
|
+
// pointerdown — belt-and-suspenders).
|
|
131
|
+
useEffect(() => {
|
|
132
|
+
if (!ctx.open) return;
|
|
133
|
+
const onPointerDown = (e: PointerEvent) => {
|
|
134
|
+
const target = e.target as Node | null;
|
|
135
|
+
if (!target) return;
|
|
136
|
+
const panel = ctx.listboxRef.current;
|
|
137
|
+
const trigger = ctx.triggerRootRef.current;
|
|
138
|
+
if (panel && panel.contains(target)) return;
|
|
139
|
+
if (trigger && trigger.contains(target)) return;
|
|
140
|
+
// #684: a tour pointing into this listbox doesn't dismiss it.
|
|
141
|
+
if (isTourHeld(target, panel, trigger)) return;
|
|
142
|
+
setOpen(false);
|
|
143
|
+
};
|
|
144
|
+
document.addEventListener('pointerdown', onPointerDown, true);
|
|
145
|
+
return () => document.removeEventListener('pointerdown', onPointerDown, true);
|
|
146
|
+
}, [ctx.open, ctx.listboxRef, ctx.triggerRootRef, setOpen]);
|
|
147
|
+
|
|
148
|
+
// Escape closes and returns focus to the trigger. Capture-phase so a
|
|
149
|
+
// future in-panel input (Phase 5/6 search input) can't stop the event
|
|
150
|
+
// before we see it.
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (!ctx.open) return;
|
|
153
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
154
|
+
if (e.key === 'Escape') {
|
|
155
|
+
// #280: defer to a DEEPER floating surface — only the innermost closes.
|
|
156
|
+
// A Select listbox is normally innermost, so this is uniformity/safety
|
|
157
|
+
// net, not load-bearing; the real Select-in-Popover fix is the Popover
|
|
158
|
+
// deferring to us.
|
|
159
|
+
if (!overlayStack.isTopFloating(floatingId)) return;
|
|
160
|
+
e.preventDefault();
|
|
161
|
+
overlayStack.consumeEscape(e); // hosts yield even if we ran first (#274)
|
|
162
|
+
closeAndFocusTrigger();
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
document.addEventListener('keydown', onKeyDown, true);
|
|
166
|
+
return () => document.removeEventListener('keydown', onKeyDown, true);
|
|
167
|
+
}, [ctx.open, closeAndFocusTrigger, floatingId]);
|
|
168
|
+
|
|
169
|
+
// On open: pre-highlight the current selection (if any), else the
|
|
170
|
+
// first non-disabled option. Trigger's ArrowUp handler may override
|
|
171
|
+
// this via a queueMicrotask to "last selectable" — that's fine, this
|
|
172
|
+
// layout effect runs first and the microtask wins.
|
|
173
|
+
// Only fires on the `ctx.open` transition; row changes mid-open don't
|
|
174
|
+
// reset the cursor.
|
|
175
|
+
useLayoutEffect(() => {
|
|
176
|
+
if (!ctx.open) return;
|
|
177
|
+
const firstSelectedIdx = ctx.rows.findIndex(
|
|
178
|
+
(r) =>
|
|
179
|
+
r.kind === 'option' &&
|
|
180
|
+
!r.option.disabled &&
|
|
181
|
+
(ctx.multiple
|
|
182
|
+
? (ctx.value as string[]).includes(r.option.value)
|
|
183
|
+
: ctx.value === r.option.value),
|
|
184
|
+
);
|
|
185
|
+
if (firstSelectedIdx >= 0) {
|
|
186
|
+
ctx.setActiveIndex(firstSelectedIdx);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const firstSelectableIdx = ctx.rows.findIndex((r) => r.kind === 'option' && !r.option.disabled);
|
|
190
|
+
ctx.setActiveIndex(firstSelectableIdx >= 0 ? firstSelectableIdx : -1);
|
|
191
|
+
// Intentionally only depends on `ctx.open`: this effect seeds the active
|
|
192
|
+
// row on the open transition, and must NOT re-run when `ctx.rows` or
|
|
193
|
+
// `ctx.value` shift mid-open (that would yank the cursor out from under
|
|
194
|
+
// the user's keyboard / mouse navigation).
|
|
195
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
196
|
+
}, [ctx.open]);
|
|
197
|
+
|
|
198
|
+
// #305: keep the active option visible inside the height-clamped panel.
|
|
199
|
+
// aria-activedescendant means DOM focus never enters the listbox, so
|
|
200
|
+
// nothing scrolls it natively — with >~8 options the active row moves
|
|
201
|
+
// below the fold and the highlight disappears. One effect here covers
|
|
202
|
+
// every setActiveIndex source (trigger keyboard, typeahead, in-panel
|
|
203
|
+
// search, open seeding). Gated on isPositioned: before Floating UI
|
|
204
|
+
// places the portaled panel it sits at the document origin, where
|
|
205
|
+
// scrollIntoView would scroll the WINDOW to the top (see the identical
|
|
206
|
+
// fix in DropdownMenu/Content.tsx, #303) — and the size clamp hasn't
|
|
207
|
+
// been applied yet anyway. `block: 'nearest'` no-ops for
|
|
208
|
+
// already-visible rows, so mouse-hover activation causes no jumps.
|
|
209
|
+
// Guarded — jsdom has no scrollIntoView.
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
if (!ctx.open || !isPositioned || ctx.activeIndex < 0) return;
|
|
212
|
+
const row = ctx.rows[ctx.activeIndex];
|
|
213
|
+
if (!row || row.kind !== 'option') return;
|
|
214
|
+
document
|
|
215
|
+
.getElementById(ctx.getOptionId(row.option.value))
|
|
216
|
+
?.scrollIntoView?.({ block: 'nearest' });
|
|
217
|
+
// ctx.rows is read fresh but intentionally not a dep: a mid-open rows
|
|
218
|
+
// identity change (async load, filtering) must not re-scroll a row the
|
|
219
|
+
// user has already scrolled away from.
|
|
220
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
221
|
+
}, [ctx.open, isPositioned, ctx.activeIndex]);
|
|
222
|
+
|
|
223
|
+
return createPortal(
|
|
224
|
+
<div
|
|
225
|
+
ref={mergeRefs<HTMLDivElement>(ctx.listboxRef, refs.setFloating)}
|
|
226
|
+
data-in-overlay={inOverlay ? '' : undefined}
|
|
227
|
+
className={clsx(styles.listbox)}
|
|
228
|
+
style={floatingStyles}
|
|
229
|
+
>
|
|
230
|
+
{/* In-panel search for multi-summary-searchable mode. Single-mode
|
|
231
|
+
searchable Select keeps the search input AS the trigger
|
|
232
|
+
(ComboboxInputTrigger) since there's no second trigger to compete
|
|
233
|
+
with; multi-summary keeps a select-only combobox trigger that shows
|
|
234
|
+
the summary, so this filter is its sibling inside the panel. */}
|
|
235
|
+
{ctx.multiple && ctx.triggerDisplay === 'summary' && ctx.searchable && <InPanelSearchInput />}
|
|
236
|
+
{/* ONE live region for the whole listbox, outside the <ul>.
|
|
237
|
+
Each of the three state rows used to carry its own announcement, in
|
|
238
|
+
three different and partly invalid ways: `aria-live` on
|
|
239
|
+
`<li role="presentation">` (a global attribute, so the presentation
|
|
240
|
+
role was discarded and the row was exposed as a list item inside a
|
|
241
|
+
listbox), and `role="alert"` on another `<li>` — the same
|
|
242
|
+
required-children deviation. All three also mounted their region
|
|
243
|
+
together with its text, which most screen readers do not announce.
|
|
244
|
+
Rendered unconditionally here with the text deferred, per Hard rule
|
|
245
|
+
10. See #495. */}
|
|
246
|
+
<span role="status" aria-live="polite" className={styles.srOnly}>
|
|
247
|
+
{statusText}
|
|
248
|
+
</span>
|
|
249
|
+
<ul
|
|
250
|
+
id={ctx.listboxId}
|
|
251
|
+
role="listbox"
|
|
252
|
+
aria-multiselectable={ctx.multiple || undefined}
|
|
253
|
+
aria-labelledby={ctx.triggerId}
|
|
254
|
+
tabIndex={-1}
|
|
255
|
+
data-in-overlay={inOverlay ? '' : undefined}
|
|
256
|
+
className={styles.listboxBody}
|
|
257
|
+
>
|
|
258
|
+
{renderListboxBody(ctx, t)}
|
|
259
|
+
</ul>
|
|
260
|
+
</div>,
|
|
261
|
+
document.body,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Decide what goes in the listbox body. Three short-circuits ahead of the
|
|
267
|
+
* normal row walk:
|
|
268
|
+
*
|
|
269
|
+
* 1. Loading — async request is in flight AND we have nothing else to show.
|
|
270
|
+
* Once a previous result is in `rows`, we keep showing it instead of
|
|
271
|
+
* swapping to a spinner (UI doesn't flicker between every keystroke).
|
|
272
|
+
* 2. Error — the latest async request rejected. Surfaces a Retry button.
|
|
273
|
+
* 3. Empty — no rows after filtering and we're not loading or in error.
|
|
274
|
+
*
|
|
275
|
+
* Each branch consults the consumer's `renderLoading` / `renderError` /
|
|
276
|
+
* `renderEmpty` first, falling back to the bundled defaults.
|
|
277
|
+
*/
|
|
278
|
+
function renderListboxBody<T>(
|
|
279
|
+
ctx: SelectContextValue<T>,
|
|
280
|
+
t: ReturnType<typeof useTranslation>,
|
|
281
|
+
): ReactNode {
|
|
282
|
+
const showLoading = ctx.loading && ctx.rows.length === 0;
|
|
283
|
+
const showError = !!ctx.error && !ctx.loading;
|
|
284
|
+
const showEmpty = !ctx.loading && !ctx.error && ctx.rows.length === 0;
|
|
285
|
+
|
|
286
|
+
if (showLoading) {
|
|
287
|
+
return ctx.renderLoading ? (
|
|
288
|
+
<li className={styles.stateRow} role="presentation">
|
|
289
|
+
{ctx.renderLoading()}
|
|
290
|
+
</li>
|
|
291
|
+
) : (
|
|
292
|
+
<Loading />
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
if (showError) {
|
|
296
|
+
return ctx.renderError ? (
|
|
297
|
+
<li className={styles.stateRow} role="presentation">
|
|
298
|
+
{ctx.renderError(ctx.error as Error, ctx.retry)}
|
|
299
|
+
</li>
|
|
300
|
+
) : (
|
|
301
|
+
<ErrorRow error={ctx.error as Error} onRetry={ctx.retry} />
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
if (showEmpty) {
|
|
305
|
+
return ctx.renderEmpty ? (
|
|
306
|
+
<li className={styles.stateRow} role="presentation">
|
|
307
|
+
{ctx.renderEmpty(ctx.query)}
|
|
308
|
+
</li>
|
|
309
|
+
) : (
|
|
310
|
+
<Empty query={ctx.query} />
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Walk the flat rows array, wrapping each header + its following option
|
|
315
|
+
// rows in `<li role="group" aria-labelledby={headerId}>` so the listbox
|
|
316
|
+
// exposes proper grouping semantics. The flat index `i` is preserved
|
|
317
|
+
// across the wrapping — Trigger's keyboard logic computes
|
|
318
|
+
// `aria-activedescendant` from it, so option rows inside groups MUST
|
|
319
|
+
// keep the same index they would have had in the flat map.
|
|
320
|
+
const nodes: ReactNode[] = [];
|
|
321
|
+
let i = 0;
|
|
322
|
+
while (i < ctx.rows.length) {
|
|
323
|
+
const row = ctx.rows[i];
|
|
324
|
+
if (row.kind === 'header') {
|
|
325
|
+
const headerLabel = row.label;
|
|
326
|
+
const headerId = ctx.getGroupHeaderId(headerLabel);
|
|
327
|
+
const groupChildren: ReactNode[] = [];
|
|
328
|
+
// Non-focusable header row; `data-group-header` is the hook
|
|
329
|
+
// grouped-options tests query against (avoids relying on the hashed
|
|
330
|
+
// CSS-module class name).
|
|
331
|
+
groupChildren.push(
|
|
332
|
+
<li key={`h-${i}`} id={headerId} data-group-header="" className={styles.groupHeader}>
|
|
333
|
+
{headerLabel}
|
|
334
|
+
</li>,
|
|
335
|
+
);
|
|
336
|
+
let j = i + 1;
|
|
337
|
+
while (j < ctx.rows.length && ctx.rows[j].kind === 'option') {
|
|
338
|
+
const optRow = ctx.rows[j] as Extract<(typeof ctx.rows)[number], { kind: 'option' }>;
|
|
339
|
+
const selected = ctx.multiple
|
|
340
|
+
? (ctx.value as string[]).includes(optRow.option.value)
|
|
341
|
+
: ctx.value === optRow.option.value;
|
|
342
|
+
const active = ctx.activeIndex === j;
|
|
343
|
+
groupChildren.push(renderOptionRow(optRow.option, j, selected, active, ctx, t));
|
|
344
|
+
j++;
|
|
345
|
+
}
|
|
346
|
+
nodes.push(
|
|
347
|
+
<li role="group" key={`g-${i}`} aria-labelledby={headerId}>
|
|
348
|
+
<ul role="none" className={styles.groupList}>
|
|
349
|
+
{groupChildren}
|
|
350
|
+
</ul>
|
|
351
|
+
</li>,
|
|
352
|
+
);
|
|
353
|
+
i = j;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
// Ungrouped (flat) option row.
|
|
357
|
+
const optRow = row;
|
|
358
|
+
const selected = ctx.multiple
|
|
359
|
+
? (ctx.value as string[]).includes(optRow.option.value)
|
|
360
|
+
: ctx.value === optRow.option.value;
|
|
361
|
+
const active = ctx.activeIndex === i;
|
|
362
|
+
nodes.push(renderOptionRow(optRow.option, i, selected, active, ctx, t));
|
|
363
|
+
i++;
|
|
364
|
+
}
|
|
365
|
+
return nodes;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Render one `<li role="option">` row. Extracted as a module-local helper
|
|
370
|
+
* so the listbox loop can call it from two call sites — the in-group path
|
|
371
|
+
* and the flat-options path — without duplicating the JSX.
|
|
372
|
+
*
|
|
373
|
+
* `i` is the flat index into `ctx.rows`; it MUST match the index Trigger's
|
|
374
|
+
* keyboard handlers compute against, since `aria-activedescendant` and
|
|
375
|
+
* `ctx.setActiveIndex` both key off it.
|
|
376
|
+
*/
|
|
377
|
+
function renderOptionRow<T>(
|
|
378
|
+
opt: SelectOption<T>,
|
|
379
|
+
i: number,
|
|
380
|
+
selected: boolean,
|
|
381
|
+
active: boolean,
|
|
382
|
+
ctx: SelectContextValue<T>,
|
|
383
|
+
// Threaded rather than hooked: these are plain functions, not components.
|
|
384
|
+
t: ReturnType<typeof useTranslation>,
|
|
385
|
+
): ReactNode {
|
|
386
|
+
// Creatable "+ Create <query>" row. Rendered distinctly (italic + accent
|
|
387
|
+
// colour via `.optionCreate`) and dispatches `onCreate` plus the same
|
|
388
|
+
// single-vs-multi commit flow as a normal option click.
|
|
389
|
+
if (isCreateRow(opt)) {
|
|
390
|
+
return (
|
|
391
|
+
<li
|
|
392
|
+
key="__create__"
|
|
393
|
+
id={ctx.getOptionId(opt.value)}
|
|
394
|
+
role="option"
|
|
395
|
+
aria-selected={false}
|
|
396
|
+
className={clsx(styles.option, styles.optionCreate, active && styles.optionActive)}
|
|
397
|
+
onPointerDown={(e) => e.preventDefault()}
|
|
398
|
+
onClick={() => {
|
|
399
|
+
ctx.onCreate?.(opt.label);
|
|
400
|
+
if (ctx.multiple) {
|
|
401
|
+
const next = [...((ctx.value as string[]) ?? []), opt.value];
|
|
402
|
+
ctx.setValue(next);
|
|
403
|
+
if (ctx.searchable) ctx.setQuery('');
|
|
404
|
+
} else {
|
|
405
|
+
ctx.setValue(opt.value);
|
|
406
|
+
ctx.closeAndFocusTrigger();
|
|
407
|
+
}
|
|
408
|
+
}}
|
|
409
|
+
onMouseEnter={() => ctx.setActiveIndex(i)}
|
|
410
|
+
>
|
|
411
|
+
{t('select.createOption', { label: opt.label })}
|
|
412
|
+
</li>
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
// Consumer's `renderOption` wins over the default label rendering. The
|
|
416
|
+
// create-row branch above intentionally does NOT pass through here —
|
|
417
|
+
// "+ Create" is internal chrome the consumer doesn't know about.
|
|
418
|
+
// Default render with a description: label and description get their own
|
|
419
|
+
// ids so the option's name stays the label alone and the description is
|
|
420
|
+
// announced as its accessible description (not concatenated into the name).
|
|
421
|
+
const optionId = ctx.getOptionId(opt.value);
|
|
422
|
+
const describe = !ctx.renderOption && !!opt.description;
|
|
423
|
+
const body = ctx.renderOption ? (
|
|
424
|
+
ctx.renderOption(opt, { active, selected })
|
|
425
|
+
) : describe ? (
|
|
426
|
+
<>
|
|
427
|
+
<span id={`${optionId}-label`}>{opt.label}</span>
|
|
428
|
+
<span id={`${optionId}-desc`} className={styles.optionDescription}>
|
|
429
|
+
{opt.description}
|
|
430
|
+
</span>
|
|
431
|
+
</>
|
|
432
|
+
) : (
|
|
433
|
+
opt.label
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
return (
|
|
437
|
+
<li
|
|
438
|
+
key={opt.value}
|
|
439
|
+
id={optionId}
|
|
440
|
+
role="option"
|
|
441
|
+
aria-selected={selected}
|
|
442
|
+
aria-disabled={opt.disabled || undefined}
|
|
443
|
+
aria-labelledby={describe ? `${optionId}-label` : undefined}
|
|
444
|
+
aria-describedby={describe ? `${optionId}-desc` : undefined}
|
|
445
|
+
className={clsx(
|
|
446
|
+
styles.option,
|
|
447
|
+
active && styles.optionActive,
|
|
448
|
+
selected && styles.optionSelected,
|
|
449
|
+
opt.disabled && styles.optionDisabled,
|
|
450
|
+
)}
|
|
451
|
+
onPointerDown={(e) => {
|
|
452
|
+
// Stop the document-level outside-click pointerdown handler from
|
|
453
|
+
// closing the listbox before the click resolves. The click handler
|
|
454
|
+
// still fires and commits the selection.
|
|
455
|
+
e.preventDefault();
|
|
456
|
+
}}
|
|
457
|
+
onClick={() => {
|
|
458
|
+
if (opt.disabled) return;
|
|
459
|
+
if (ctx.multiple) {
|
|
460
|
+
ctx.toggleValue(opt.value);
|
|
461
|
+
// Multi + searchable mode (chips-input or in-panel search):
|
|
462
|
+
// clear the query so the user can immediately pick another
|
|
463
|
+
// option without manually erasing the previous filter.
|
|
464
|
+
if (ctx.searchable) ctx.setQuery('');
|
|
465
|
+
} else {
|
|
466
|
+
ctx.setValue(opt.value);
|
|
467
|
+
ctx.closeAndFocusTrigger();
|
|
468
|
+
}
|
|
469
|
+
}}
|
|
470
|
+
onMouseEnter={() => {
|
|
471
|
+
if (!opt.disabled) ctx.setActiveIndex(i);
|
|
472
|
+
}}
|
|
473
|
+
>
|
|
474
|
+
{body}
|
|
475
|
+
</li>
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Search input rendered beside the listbox inside the panel for the
|
|
481
|
+
* multi-summary-searchable variant. The trigger remains a select-only
|
|
482
|
+
* combobox that shows the comma-joined selection summary; this sibling
|
|
483
|
+
* searchbox filters without becoming an invalid child of the listbox.
|
|
484
|
+
*
|
|
485
|
+
* Owns its own keyboard handling: ArrowUp/Down cycle the active option,
|
|
486
|
+
* Enter toggles selection, Escape closes and returns focus to the trigger.
|
|
487
|
+
* This duplicates a small slice of `useTriggerKeyboard.moveActive` —
|
|
488
|
+
* deliberate, since the trigger hook is button-shaped and pulling the
|
|
489
|
+
* cycle logic into a shared hook would obscure both call sites at this
|
|
490
|
+
* scale. Revisit if Phase 6's chips trigger lands a third copy.
|
|
491
|
+
*/
|
|
492
|
+
function InPanelSearchInput() {
|
|
493
|
+
const ctx = useSelectContext('Listbox.SearchInput');
|
|
494
|
+
const t = useTranslation();
|
|
495
|
+
const ref = useRef<HTMLInputElement>(null);
|
|
496
|
+
|
|
497
|
+
// Auto-focus on mount so the user starts typing immediately after
|
|
498
|
+
// clicking the trigger. `preventScroll` avoids the portaled panel
|
|
499
|
+
// yanking the viewport on focus.
|
|
500
|
+
useLayoutEffect(() => {
|
|
501
|
+
ref.current?.focus({ preventScroll: true });
|
|
502
|
+
}, []);
|
|
503
|
+
|
|
504
|
+
const activeRow = ctx.activeIndex >= 0 ? ctx.rows[ctx.activeIndex] : undefined;
|
|
505
|
+
const activeOptionId =
|
|
506
|
+
activeRow && activeRow.kind === 'option' ? ctx.getOptionId(activeRow.option.value) : undefined;
|
|
507
|
+
|
|
508
|
+
return (
|
|
509
|
+
<input
|
|
510
|
+
ref={ref}
|
|
511
|
+
type="text"
|
|
512
|
+
role="searchbox"
|
|
513
|
+
aria-controls={ctx.listboxId}
|
|
514
|
+
aria-activedescendant={activeOptionId}
|
|
515
|
+
aria-autocomplete="list"
|
|
516
|
+
className={styles.popoverSearch}
|
|
517
|
+
placeholder={t('select.search')}
|
|
518
|
+
autoComplete="off"
|
|
519
|
+
spellCheck={false}
|
|
520
|
+
value={ctx.query}
|
|
521
|
+
onChange={(e) => ctx.setQuery(e.target.value)}
|
|
522
|
+
onKeyDown={(e) => {
|
|
523
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
524
|
+
e.preventDefault();
|
|
525
|
+
const delta = e.key === 'ArrowDown' ? +1 : -1;
|
|
526
|
+
const len = ctx.rows.length;
|
|
527
|
+
if (len === 0) return;
|
|
528
|
+
let i = ctx.activeIndex;
|
|
529
|
+
for (let s = 0; s < len; s++) {
|
|
530
|
+
i = (i + delta + len) % len;
|
|
531
|
+
const r = ctx.rows[i];
|
|
532
|
+
if (r.kind === 'option' && !r.option.disabled) {
|
|
533
|
+
ctx.setActiveIndex(i);
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
} else if (e.key === 'Enter') {
|
|
538
|
+
e.preventDefault();
|
|
539
|
+
const row = ctx.rows[ctx.activeIndex];
|
|
540
|
+
if (row && row.kind === 'option' && !row.option.disabled) {
|
|
541
|
+
if (isCreateRow(row.option)) {
|
|
542
|
+
ctx.onCreate?.(row.option.label);
|
|
543
|
+
const next = [...((ctx.value as string[]) ?? []), row.option.value];
|
|
544
|
+
ctx.setValue(next);
|
|
545
|
+
ctx.setQuery('');
|
|
546
|
+
} else {
|
|
547
|
+
ctx.toggleValue(row.option.value);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
} else if (e.key === 'Escape') {
|
|
551
|
+
e.preventDefault();
|
|
552
|
+
ctx.closeAndFocusTrigger();
|
|
553
|
+
}
|
|
554
|
+
}}
|
|
555
|
+
/>
|
|
556
|
+
);
|
|
557
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useTranslation } from '../../i18n/useTranslation';
|
|
2
|
+
import styles from './Select.module.scss';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Default loading-state row, rendered inside the listbox while an async
|
|
6
|
+
* `loadOptions` request is in flight and the previous result has not yet
|
|
7
|
+
* arrived (i.e. there are no rows to show alongside it).
|
|
8
|
+
*
|
|
9
|
+
* Non-interactive `<li role="presentation">`. Unlike its Empty and Error
|
|
10
|
+
* siblings its copy is NOT `aria-hidden`: those two render the same sentence
|
|
11
|
+
* the status region announces, so hiding the visible one stops a reader
|
|
12
|
+
* meeting it twice, whereas this row's "Loading..." differs from the region's
|
|
13
|
+
* "Loading options...". Browse mode therefore reads both — different strings,
|
|
14
|
+
* not a duplicate, but the three rows do not follow one pattern and that is
|
|
15
|
+
* worth knowing before copying any of them. The
|
|
16
|
+
* announcement comes from ONE live region the Select root owns; carrying
|
|
17
|
+
* `aria-live` here mounted the region together with its text, which most
|
|
18
|
+
* screen readers do not announce. See #495, and `messages.ts` for why the
|
|
19
|
+
* conflict-resolution half of the original explanation was dropped — it was
|
|
20
|
+
* spec-arguable but is not what Chromium does inside a `role="listbox"`.
|
|
21
|
+
*/
|
|
22
|
+
export function Loading() {
|
|
23
|
+
const t = useTranslation();
|
|
24
|
+
return (
|
|
25
|
+
<li className={styles.stateRow} role="presentation">
|
|
26
|
+
<span className={styles.spinner} aria-hidden="true" />
|
|
27
|
+
<span>{t('select.loading')}</span>
|
|
28
|
+
</li>
|
|
29
|
+
);
|
|
30
|
+
}
|