@eocrm/design-system 0.0.0-stage → 0.6.17
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/README.md +262 -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 +82 -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,624 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useId,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type CSSProperties,
|
|
9
|
+
type HTMLAttributes,
|
|
10
|
+
type KeyboardEvent,
|
|
11
|
+
type PointerEvent,
|
|
12
|
+
type ReactNode,
|
|
13
|
+
} from 'react';
|
|
14
|
+
import clsx from 'clsx';
|
|
15
|
+
import { useTranslation } from '../../i18n/useTranslation';
|
|
16
|
+
import styles from './Slider.module.scss';
|
|
17
|
+
|
|
18
|
+
/** Track height + thumb size. */
|
|
19
|
+
export type SliderSize = 'sm' | 'md' | 'lg';
|
|
20
|
+
|
|
21
|
+
/** Fill color tone (track between min and value). */
|
|
22
|
+
export type SliderTone = 'default' | 'success' | 'warning' | 'danger';
|
|
23
|
+
|
|
24
|
+
/** Layout direction. */
|
|
25
|
+
export type SliderOrientation = 'horizontal' | 'vertical';
|
|
26
|
+
|
|
27
|
+
/** Either a single number (single-thumb) or a [min, max] tuple (range mode). */
|
|
28
|
+
export type SliderValue = number | [number, number];
|
|
29
|
+
|
|
30
|
+
/** Tick-mark configuration. */
|
|
31
|
+
export interface SliderMark {
|
|
32
|
+
/** Numeric position of the tick along the track (in min..max units). */
|
|
33
|
+
value: number;
|
|
34
|
+
/**
|
|
35
|
+
* Optional label rendered below (horizontal) or to the right (vertical)
|
|
36
|
+
* of the tick. When omitted, only the tick line renders — no text.
|
|
37
|
+
* When `marks` is passed as `number[]`, the label is auto-set to the
|
|
38
|
+
* value so consumers don't have to wrap each tick in an object.
|
|
39
|
+
*/
|
|
40
|
+
label?: ReactNode;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface SliderProps extends Omit<
|
|
44
|
+
HTMLAttributes<HTMLDivElement>,
|
|
45
|
+
'onChange' | 'defaultValue' | 'role'
|
|
46
|
+
> {
|
|
47
|
+
/** Marks each thumb `aria-invalid` for Field / SettingRow composition. @default false */
|
|
48
|
+
invalid?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Consumed for Field / SettingRow composition (they render the visible
|
|
51
|
+
* required marker). `role="slider"` does not support `aria-required` and a
|
|
52
|
+
* slider always has a value, so nothing is forwarded (#568).
|
|
53
|
+
*/
|
|
54
|
+
required?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Current value. A single `number` for one-thumb mode; a `[min, max]` tuple
|
|
57
|
+
* for two-thumb (range) mode. The component type-discriminates internally.
|
|
58
|
+
* Required — Slider is controlled-only.
|
|
59
|
+
*/
|
|
60
|
+
value: SliderValue;
|
|
61
|
+
/**
|
|
62
|
+
* Called on every thumb-drag tick (high frequency). For server-side or
|
|
63
|
+
* expensive update logic, prefer `onChangeEnd` or debounce in the consumer.
|
|
64
|
+
* The argument has the same shape as `value`: `number` for single,
|
|
65
|
+
* `[number, number]` for range.
|
|
66
|
+
*/
|
|
67
|
+
onChange: (value: SliderValue) => void;
|
|
68
|
+
/**
|
|
69
|
+
* Called once when the user "commits" a value change — at pointerup
|
|
70
|
+
* after a drag, or at blur after keyboard-nav that actually changed
|
|
71
|
+
* the value. Does NOT fire on Tab-in / Tab-out without any value
|
|
72
|
+
* change. Use for committing the value to a server or running an
|
|
73
|
+
* expensive recalculation. Receives the final value with the same
|
|
74
|
+
* shape as `value`.
|
|
75
|
+
*/
|
|
76
|
+
onChangeEnd?: (value: SliderValue) => void;
|
|
77
|
+
/** Minimum allowed value (inclusive). Default `0`. */
|
|
78
|
+
min?: number;
|
|
79
|
+
/** Maximum allowed value (inclusive). Default `100`. */
|
|
80
|
+
max?: number;
|
|
81
|
+
/**
|
|
82
|
+
* Step granularity. Default `1`. Use fractional steps (e.g. `0.1`) for
|
|
83
|
+
* zoom / opacity-style controls. Values are snapped to `min + (n * step)`.
|
|
84
|
+
*/
|
|
85
|
+
step?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Tick marks. Pass `number[]` for auto-labeled ticks (label = value) or
|
|
88
|
+
* `SliderMark[]` for custom labels (label = ReactNode). Marks render under
|
|
89
|
+
* the track (horizontal) or to the right (vertical).
|
|
90
|
+
*/
|
|
91
|
+
marks?: number[] | SliderMark[];
|
|
92
|
+
/**
|
|
93
|
+
* Value bubble on the thumb.
|
|
94
|
+
* - `false` (default) — no bubble.
|
|
95
|
+
* - `true` — show the current value (formatted via `toString()`) on hover /
|
|
96
|
+
* focus / drag. Auto-hides otherwise.
|
|
97
|
+
* - `(value: number) => ReactNode` — custom formatter. For range mode, the
|
|
98
|
+
* formatter is called once per thumb.
|
|
99
|
+
*/
|
|
100
|
+
label?: boolean | ((value: number) => ReactNode);
|
|
101
|
+
/**
|
|
102
|
+
* Explicit accessible names for the minimum and maximum thumbs in range
|
|
103
|
+
* mode. These win over a root `aria-label` or `aria-labelledby`; use them
|
|
104
|
+
* when the thumbs need domain-specific names such as `['Start date', 'End
|
|
105
|
+
* date']`. When an entry is omitted OR empty — an empty string is not an
|
|
106
|
+
* explicit name — that thumb falls back to a root label suffixed with the
|
|
107
|
+
* localized “minimum” or “maximum” name. The two entries are resolved
|
|
108
|
+
* independently, so `['', 'End date']` names only the maximum thumb.
|
|
109
|
+
*/
|
|
110
|
+
thumbLabels?: readonly [string, string];
|
|
111
|
+
/**
|
|
112
|
+
* Track + thumb sizing. Defaults to `'md'`.
|
|
113
|
+
* - `sm` — 4px track, 14px thumb.
|
|
114
|
+
* - `md` — 6px track, 18px thumb (default).
|
|
115
|
+
* - `lg` — 8px track, 22px thumb.
|
|
116
|
+
*/
|
|
117
|
+
size?: SliderSize;
|
|
118
|
+
/**
|
|
119
|
+
* Fill color tone (the track segment between min and value). Defaults to
|
|
120
|
+
* `'default'` (accent). State-coded `success` / `warning` / `danger` for
|
|
121
|
+
* threshold-style sliders (e.g. disk usage approaching capacity).
|
|
122
|
+
*/
|
|
123
|
+
tone?: SliderTone;
|
|
124
|
+
/** Orientation. Defaults to `'horizontal'`. Vertical defaults to 200px tall; override via `style={{ height }}`. */
|
|
125
|
+
orientation?: SliderOrientation;
|
|
126
|
+
/**
|
|
127
|
+
* Disabled state. Defaults to `false`. Thumbs become non-interactive
|
|
128
|
+
* (`tabIndex=-1`, `aria-disabled`, `pointer-events: none`, `cursor: not-allowed`).
|
|
129
|
+
*/
|
|
130
|
+
disabled?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Native form-input name. When set, a hidden `<input>` (or two for range,
|
|
133
|
+
* with `-min`/`-max` suffixes) is rendered with the current value(s) so
|
|
134
|
+
* the slider works inside uncontrolled HTML forms without consumer JS
|
|
135
|
+
* serialization. When the slider is `disabled`, the hidden input(s) are
|
|
136
|
+
* NOT rendered so the form does not submit a stale disabled value.
|
|
137
|
+
*/
|
|
138
|
+
name?: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// CSS-Modules naming note:
|
|
142
|
+
// SCSS class names here are kebab-case (`.orientation-horizontal`, `.size-sm`,
|
|
143
|
+
// `.tone-danger`) so the TSX can use bracket notation
|
|
144
|
+
// `styles[`orientation-${o}`]` for clean orientation × size × tone × state
|
|
145
|
+
// dispatch. Two-word non-prop classes (`.markFilled`, `.thumbDragging`) stay
|
|
146
|
+
// camelCase. Deviates from the Progress/Title pure-camelCase + record-of-strings
|
|
147
|
+
// pattern; the bigger matrix here makes bracket-access more legible.
|
|
148
|
+
|
|
149
|
+
function normalizeMarks(marks: number[] | SliderMark[] | undefined): SliderMark[] {
|
|
150
|
+
if (!marks || marks.length === 0) return [];
|
|
151
|
+
// For number[] input, auto-label with the value itself. For SliderMark[]
|
|
152
|
+
// input, keep `label` as-passed (may be undefined → no label rendered).
|
|
153
|
+
return marks.map((m) => (typeof m === 'number' ? { value: m, label: m } : m));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function clamp(n: number, lo: number, hi: number): number {
|
|
157
|
+
return Math.max(lo, Math.min(hi, n));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function snapToStep(raw: number, min: number, step: number): number {
|
|
161
|
+
if (step <= 0) return raw;
|
|
162
|
+
const stepped = Math.round((raw - min) / step) * step + min;
|
|
163
|
+
// Floating-point: align to step's decimal precision so 0.30000000000000004 → 0.3.
|
|
164
|
+
const decimals = (step.toString().split('.')[1] ?? '').length;
|
|
165
|
+
return decimals > 0 ? Number(stepped.toFixed(decimals)) : stepped;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Controlled slider supporting single and range modes, horizontal and vertical orientations, fractional steps, tick marks and value bubbles.
|
|
170
|
+
* @see docs/components/Slider.md
|
|
171
|
+
*/
|
|
172
|
+
export const Slider = forwardRef<HTMLDivElement, SliderProps>(function Slider(
|
|
173
|
+
{
|
|
174
|
+
value,
|
|
175
|
+
onChange,
|
|
176
|
+
onChangeEnd,
|
|
177
|
+
min = 0,
|
|
178
|
+
max = 100,
|
|
179
|
+
step = 1,
|
|
180
|
+
marks,
|
|
181
|
+
label = false,
|
|
182
|
+
thumbLabels,
|
|
183
|
+
size = 'md',
|
|
184
|
+
tone = 'default',
|
|
185
|
+
orientation = 'horizontal',
|
|
186
|
+
disabled = false,
|
|
187
|
+
name,
|
|
188
|
+
className,
|
|
189
|
+
'aria-label': ariaLabel,
|
|
190
|
+
'aria-labelledby': ariaLabelledBy,
|
|
191
|
+
'aria-describedby': ariaDescribedBy,
|
|
192
|
+
invalid = false,
|
|
193
|
+
// Consumed so it never lands on the root div (#568); see the prop's JSDoc.
|
|
194
|
+
required: _required = false,
|
|
195
|
+
...rest
|
|
196
|
+
},
|
|
197
|
+
ref,
|
|
198
|
+
) {
|
|
199
|
+
const t = useTranslation();
|
|
200
|
+
const reactId = useId();
|
|
201
|
+
const trackRef = useRef<HTMLDivElement>(null);
|
|
202
|
+
const isRange = Array.isArray(value);
|
|
203
|
+
const thumbValues: number[] = useMemo(() => (Array.isArray(value) ? value : [value]), [value]);
|
|
204
|
+
const thumbCount = thumbValues.length;
|
|
205
|
+
const marksArr = useMemo(() => normalizeMarks(marks), [marks]);
|
|
206
|
+
const range = max - min;
|
|
207
|
+
const thumbSuffixes = [t('slider.minimum'), t('slider.maximum')] as const;
|
|
208
|
+
const thumbSuffixIds = [`${reactId}-minimum`, `${reactId}-maximum`] as const;
|
|
209
|
+
// Per INDEX, not per array. `thumbLabels={[min ?? '', max ?? '']}` is ordinary
|
|
210
|
+
// consumer code, and an empty entry names that thumb no better than a missing
|
|
211
|
+
// tuple does — so it has to fall back down the SAME two paths a missing tuple
|
|
212
|
+
// takes, aria-labelledby included. Gating on `thumbLabels`'s mere existence
|
|
213
|
+
// left a <Field>-wrapped range thumb with neither attribute set.
|
|
214
|
+
const ownThumbLabel = (index: number) => thumbLabels?.[index] || undefined;
|
|
215
|
+
const thumbUsesRootLabelledBy = (index: number) =>
|
|
216
|
+
isRange && !ownThumbLabel(index) && Boolean(ariaLabelledBy);
|
|
217
|
+
// The hidden suffix nodes are shared, so render them if ANY thumb points at one.
|
|
218
|
+
const rangeUsesRootLabelledBy = thumbValues.some((_unused, index) =>
|
|
219
|
+
thumbUsesRootLabelledBy(index),
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
// Latest value ref — updated on every render. Read synchronously inside
|
|
223
|
+
// event handlers (e.g. onChangeEnd at pointerup) so they see the post-drag
|
|
224
|
+
// value, not the render-time closure capture. Critical for fast drags where
|
|
225
|
+
// pointermove fires multiple updates between renders.
|
|
226
|
+
const latestValueRef = useRef(value);
|
|
227
|
+
latestValueRef.current = value;
|
|
228
|
+
|
|
229
|
+
// isDraggingRef: read synchronously inside event handlers (no state batching
|
|
230
|
+
// race between pointerdown setting and pointermove reading).
|
|
231
|
+
// isDragging (state): drives the .thumbDragging className re-render. Both are
|
|
232
|
+
// updated together in setDragging().
|
|
233
|
+
const isDraggingRef = useRef<boolean[]>(new Array(thumbCount).fill(false));
|
|
234
|
+
const [isDragging, setIsDragging] = useState<boolean[]>(() => new Array(thumbCount).fill(false));
|
|
235
|
+
const [isFocused, setIsFocused] = useState<boolean[]>(() => new Array(thumbCount).fill(false));
|
|
236
|
+
const [isHovered, setIsHovered] = useState<boolean[]>(() => new Array(thumbCount).fill(false));
|
|
237
|
+
|
|
238
|
+
// Whether the value changed during the current focus session (for any
|
|
239
|
+
// reason: drag OR keyboard nav). Reset to false on focus. Set true on every
|
|
240
|
+
// applyThumbValue call. Read by handleThumbBlur to decide whether to fire
|
|
241
|
+
// onChangeEnd — prevents the "Tab in / Tab out without nav" no-op fire AND
|
|
242
|
+
// the "drag + Tab" double fire.
|
|
243
|
+
const valueChangedThisFocusRef = useRef(false);
|
|
244
|
+
|
|
245
|
+
const setFlag = useCallback(
|
|
246
|
+
(setter: typeof setIsFocused, index: number, next: boolean) => {
|
|
247
|
+
setter((prev) => {
|
|
248
|
+
const out = [...prev];
|
|
249
|
+
// Ensure the array length matches thumbCount in case value shape changed.
|
|
250
|
+
while (out.length < thumbCount) out.push(false);
|
|
251
|
+
out[index] = next;
|
|
252
|
+
return out;
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
[thumbCount],
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const setDragging = useCallback(
|
|
259
|
+
(index: number, next: boolean) => {
|
|
260
|
+
// Pad the ref array if the value shape changed (range → single transitions).
|
|
261
|
+
while (isDraggingRef.current.length < thumbCount) isDraggingRef.current.push(false);
|
|
262
|
+
isDraggingRef.current[index] = next;
|
|
263
|
+
setIsDragging((prev) => {
|
|
264
|
+
const out = [...prev];
|
|
265
|
+
while (out.length < thumbCount) out.push(false);
|
|
266
|
+
out[index] = next;
|
|
267
|
+
return out;
|
|
268
|
+
});
|
|
269
|
+
},
|
|
270
|
+
[thumbCount],
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
// Convert a value (in min..max) to a percentage along the track (0..100).
|
|
274
|
+
const valueToPercent = useCallback(
|
|
275
|
+
(v: number): number => (range === 0 ? 0 : clamp(((v - min) / range) * 100, 0, 100)),
|
|
276
|
+
[min, range],
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
// Compute the next value for a given thumb when the user moves the pointer to
|
|
280
|
+
// `clientX` / `clientY`. Returns null if the track has no measured length yet.
|
|
281
|
+
const pointerToValue = useCallback(
|
|
282
|
+
(clientX: number, clientY: number, thumbIndex: number): number | null => {
|
|
283
|
+
const trackEl = trackRef.current;
|
|
284
|
+
if (!trackEl) return null;
|
|
285
|
+
const rect = trackEl.getBoundingClientRect();
|
|
286
|
+
const lengthPx = orientation === 'horizontal' ? rect.width : rect.height;
|
|
287
|
+
if (lengthPx === 0) return null;
|
|
288
|
+
const pointerPos = orientation === 'horizontal' ? clientX - rect.left : rect.bottom - clientY;
|
|
289
|
+
const pct = clamp(pointerPos / lengthPx, 0, 1);
|
|
290
|
+
const raw = min + pct * range;
|
|
291
|
+
const snapped = clamp(snapToStep(raw, min, step), min, max);
|
|
292
|
+
// Range clamp: thumb 0 can't exceed thumb 1; thumb 1 can't go below thumb 0.
|
|
293
|
+
if (isRange) {
|
|
294
|
+
const [v0, v1] = value as [number, number];
|
|
295
|
+
if (thumbIndex === 0) return Math.min(snapped, v1);
|
|
296
|
+
return Math.max(snapped, v0);
|
|
297
|
+
}
|
|
298
|
+
return snapped;
|
|
299
|
+
},
|
|
300
|
+
[isRange, max, min, orientation, range, step, value],
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
// Apply a new thumb value and fire onChange with the appropriate shape.
|
|
304
|
+
const applyThumbValue = useCallback(
|
|
305
|
+
(thumbIndex: number, newValue: number) => {
|
|
306
|
+
if (isRange) {
|
|
307
|
+
const tuple = [...(value as [number, number])] as [number, number];
|
|
308
|
+
tuple[thumbIndex] = newValue;
|
|
309
|
+
onChange(tuple);
|
|
310
|
+
} else {
|
|
311
|
+
onChange(newValue);
|
|
312
|
+
}
|
|
313
|
+
valueChangedThisFocusRef.current = true;
|
|
314
|
+
},
|
|
315
|
+
[isRange, onChange, value],
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
const handleThumbPointerDown = useCallback(
|
|
319
|
+
(e: PointerEvent<HTMLDivElement>, thumbIndex: number) => {
|
|
320
|
+
if (disabled) return;
|
|
321
|
+
e.preventDefault();
|
|
322
|
+
// setPointerCapture: future pointermove/up fire on this element even if
|
|
323
|
+
// the pointer leaves it. Wrapped in try/catch because jsdom may not
|
|
324
|
+
// implement setPointerCapture — we still get pointermove on the element
|
|
325
|
+
// in test environments.
|
|
326
|
+
try {
|
|
327
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
328
|
+
} catch {
|
|
329
|
+
// jsdom or pre-PointerEvents browsers — drag still works via pointermove.
|
|
330
|
+
}
|
|
331
|
+
setDragging(thumbIndex, true);
|
|
332
|
+
},
|
|
333
|
+
[disabled, setDragging],
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
const handleThumbPointerMove = useCallback(
|
|
337
|
+
(e: PointerEvent<HTMLDivElement>, thumbIndex: number) => {
|
|
338
|
+
if (disabled || !isDraggingRef.current[thumbIndex]) return;
|
|
339
|
+
const next = pointerToValue(e.clientX, e.clientY, thumbIndex);
|
|
340
|
+
if (next === null) return;
|
|
341
|
+
// Read the LATEST value from the ref (not the closure-captured one) so
|
|
342
|
+
// the duplicate-fire guard works correctly across batched renders.
|
|
343
|
+
const latest = latestValueRef.current;
|
|
344
|
+
const current = Array.isArray(latest) ? latest[thumbIndex] : latest;
|
|
345
|
+
if (next !== current) applyThumbValue(thumbIndex, next);
|
|
346
|
+
},
|
|
347
|
+
[applyThumbValue, disabled, pointerToValue],
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
const handleThumbPointerUp = useCallback(
|
|
351
|
+
(e: PointerEvent<HTMLDivElement>, thumbIndex: number) => {
|
|
352
|
+
if (disabled || !isDraggingRef.current[thumbIndex]) return;
|
|
353
|
+
try {
|
|
354
|
+
e.currentTarget.releasePointerCapture(e.pointerId);
|
|
355
|
+
} catch {
|
|
356
|
+
// ignore — same rationale as pointerdown.
|
|
357
|
+
}
|
|
358
|
+
setDragging(thumbIndex, false);
|
|
359
|
+
// Fire onChangeEnd only if the value actually changed during the drag —
|
|
360
|
+
// a click-without-movement (pointerdown → pointerup, no pointermove)
|
|
361
|
+
// shouldn't be a "commit" event.
|
|
362
|
+
if (valueChangedThisFocusRef.current) {
|
|
363
|
+
onChangeEnd?.(latestValueRef.current);
|
|
364
|
+
valueChangedThisFocusRef.current = false;
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
[disabled, onChangeEnd, setDragging],
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const handleThumbKeyDown = useCallback(
|
|
371
|
+
(e: KeyboardEvent<HTMLDivElement>, thumbIndex: number) => {
|
|
372
|
+
if (disabled) return;
|
|
373
|
+
let delta = 0;
|
|
374
|
+
let absolute: number | null = null;
|
|
375
|
+
switch (e.key) {
|
|
376
|
+
case 'ArrowLeft':
|
|
377
|
+
case 'ArrowDown':
|
|
378
|
+
delta = -step;
|
|
379
|
+
break;
|
|
380
|
+
case 'ArrowRight':
|
|
381
|
+
case 'ArrowUp':
|
|
382
|
+
delta = step;
|
|
383
|
+
break;
|
|
384
|
+
case 'PageDown':
|
|
385
|
+
delta = -step * 10;
|
|
386
|
+
break;
|
|
387
|
+
case 'PageUp':
|
|
388
|
+
delta = step * 10;
|
|
389
|
+
break;
|
|
390
|
+
case 'Home':
|
|
391
|
+
absolute = min;
|
|
392
|
+
break;
|
|
393
|
+
case 'End':
|
|
394
|
+
absolute = max;
|
|
395
|
+
break;
|
|
396
|
+
default:
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
e.preventDefault();
|
|
400
|
+
const current = thumbValues[thumbIndex];
|
|
401
|
+
let next = absolute !== null ? absolute : current + delta;
|
|
402
|
+
next = clamp(snapToStep(next, min, step), min, max);
|
|
403
|
+
if (isRange) {
|
|
404
|
+
const [v0, v1] = value as [number, number];
|
|
405
|
+
if (thumbIndex === 0) next = Math.min(next, v1);
|
|
406
|
+
else next = Math.max(next, v0);
|
|
407
|
+
}
|
|
408
|
+
if (next !== current) applyThumbValue(thumbIndex, next);
|
|
409
|
+
},
|
|
410
|
+
[applyThumbValue, disabled, isRange, max, min, step, thumbValues, value],
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
const handleThumbBlur = useCallback(
|
|
414
|
+
(thumbIndex: number) => {
|
|
415
|
+
setFlag(setIsFocused, thumbIndex, false);
|
|
416
|
+
// Only fire onChangeEnd if the value actually changed during this focus
|
|
417
|
+
// session. Pointerup already fires onChangeEnd directly; blur covers the
|
|
418
|
+
// keyboard-nav case (Tab out after Arrow nav). Tab-in / Tab-out without
|
|
419
|
+
// any nav does NOT fire (no change, no fire).
|
|
420
|
+
if (valueChangedThisFocusRef.current) {
|
|
421
|
+
onChangeEnd?.(latestValueRef.current);
|
|
422
|
+
valueChangedThisFocusRef.current = false;
|
|
423
|
+
}
|
|
424
|
+
},
|
|
425
|
+
[onChangeEnd, setFlag],
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
// Track click: pick the nearest thumb (by current value distance to the
|
|
429
|
+
// click's projected value) and snap it. Range mode picks by distance; single
|
|
430
|
+
// mode always snaps the one thumb. Click on a thumb itself (descendant) is
|
|
431
|
+
// ignored — the thumb's pointerdown handles its own state.
|
|
432
|
+
const handleTrackPointerDown = useCallback(
|
|
433
|
+
(e: PointerEvent<HTMLDivElement>) => {
|
|
434
|
+
if (disabled) return;
|
|
435
|
+
// Don't override a thumb's own pointerdown (which bubbles up here).
|
|
436
|
+
if ((e.target as HTMLElement).closest(`.${styles.thumb}`)) return;
|
|
437
|
+
const target = pointerToValue(e.clientX, e.clientY, 0);
|
|
438
|
+
if (target === null) return;
|
|
439
|
+
let nearestIndex = 0;
|
|
440
|
+
if (isRange) {
|
|
441
|
+
const d0 = Math.abs((value as [number, number])[0] - target);
|
|
442
|
+
const d1 = Math.abs((value as [number, number])[1] - target);
|
|
443
|
+
nearestIndex = d1 < d0 ? 1 : 0;
|
|
444
|
+
}
|
|
445
|
+
// Recompute the snap WITH the chosen thumb index so the range-clamp uses
|
|
446
|
+
// the right "other thumb" reference.
|
|
447
|
+
const next = pointerToValue(e.clientX, e.clientY, nearestIndex);
|
|
448
|
+
if (next === null) return;
|
|
449
|
+
applyThumbValue(nearestIndex, next);
|
|
450
|
+
// Optionally: focus the moved thumb so the user can keyboard-nudge from
|
|
451
|
+
// the new position. Querying by selector since we don't keep a thumb ref.
|
|
452
|
+
const thumbEl = e.currentTarget
|
|
453
|
+
.closest(`.${styles.root}`)
|
|
454
|
+
?.querySelectorAll<HTMLDivElement>(`.${styles.thumb}`)[nearestIndex];
|
|
455
|
+
thumbEl?.focus();
|
|
456
|
+
},
|
|
457
|
+
[applyThumbValue, disabled, isRange, pointerToValue, value],
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
// Style helpers — positions in percent of the track length.
|
|
461
|
+
const fillStyle: CSSProperties = useMemo(() => {
|
|
462
|
+
if (isRange) {
|
|
463
|
+
const [v0, v1] = value as [number, number];
|
|
464
|
+
const startPct = valueToPercent(v0);
|
|
465
|
+
const endPct = valueToPercent(v1);
|
|
466
|
+
return orientation === 'horizontal'
|
|
467
|
+
? { left: `${startPct}%`, width: `${endPct - startPct}%` }
|
|
468
|
+
: { bottom: `${startPct}%`, height: `${endPct - startPct}%` };
|
|
469
|
+
}
|
|
470
|
+
const endPct = valueToPercent(value as number);
|
|
471
|
+
return orientation === 'horizontal'
|
|
472
|
+
? { left: '0%', width: `${endPct}%` }
|
|
473
|
+
: { bottom: '0%', height: `${endPct}%` };
|
|
474
|
+
}, [isRange, orientation, value, valueToPercent]);
|
|
475
|
+
|
|
476
|
+
const thumbStyle = useCallback(
|
|
477
|
+
(v: number): CSSProperties => {
|
|
478
|
+
const pct = valueToPercent(v);
|
|
479
|
+
return orientation === 'horizontal' ? { left: `${pct}%` } : { bottom: `${pct}%` };
|
|
480
|
+
},
|
|
481
|
+
[orientation, valueToPercent],
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
const markStyle = useCallback(
|
|
485
|
+
(m: SliderMark): CSSProperties => {
|
|
486
|
+
const pct = valueToPercent(m.value);
|
|
487
|
+
return orientation === 'horizontal' ? { left: `${pct}%` } : { bottom: `${pct}%` };
|
|
488
|
+
},
|
|
489
|
+
[orientation, valueToPercent],
|
|
490
|
+
);
|
|
491
|
+
|
|
492
|
+
const isMarkInFill = useCallback(
|
|
493
|
+
(m: SliderMark): boolean => {
|
|
494
|
+
if (isRange) {
|
|
495
|
+
const [v0, v1] = value as [number, number];
|
|
496
|
+
return m.value >= v0 && m.value <= v1;
|
|
497
|
+
}
|
|
498
|
+
return m.value <= (value as number);
|
|
499
|
+
},
|
|
500
|
+
[isRange, value],
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
const formatLabel = useCallback(
|
|
504
|
+
(v: number): ReactNode => {
|
|
505
|
+
if (label === true) return String(v);
|
|
506
|
+
if (typeof label === 'function') return label(v);
|
|
507
|
+
return null;
|
|
508
|
+
},
|
|
509
|
+
[label],
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
const showLabelFor = useCallback(
|
|
513
|
+
(index: number): boolean => {
|
|
514
|
+
if (label === false) return false;
|
|
515
|
+
return Boolean(isDragging[index] || isFocused[index] || isHovered[index]);
|
|
516
|
+
},
|
|
517
|
+
[isDragging, isFocused, isHovered, label],
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
// {...rest} last so consumer overrides win (Pattern A). `role` is Omit'd
|
|
521
|
+
// from rest at the type level so consumers can't override the slider thumb
|
|
522
|
+
// role contract.
|
|
523
|
+
return (
|
|
524
|
+
<div
|
|
525
|
+
ref={ref}
|
|
526
|
+
className={clsx(
|
|
527
|
+
styles.root,
|
|
528
|
+
styles[`orientation-${orientation}`],
|
|
529
|
+
styles[`size-${size}`],
|
|
530
|
+
styles[`tone-${tone}`],
|
|
531
|
+
disabled && styles.disabled,
|
|
532
|
+
className,
|
|
533
|
+
)}
|
|
534
|
+
{...rest}
|
|
535
|
+
>
|
|
536
|
+
<div ref={trackRef} className={styles.track} onPointerDown={handleTrackPointerDown}>
|
|
537
|
+
<div className={styles.fill} style={fillStyle} />
|
|
538
|
+
{marksArr.map((mark) => (
|
|
539
|
+
<span
|
|
540
|
+
key={mark.value}
|
|
541
|
+
className={clsx(styles.mark, isMarkInFill(mark) && styles.markFilled)}
|
|
542
|
+
style={markStyle(mark)}
|
|
543
|
+
>
|
|
544
|
+
{mark.label !== undefined && <span className={styles.markLabel}>{mark.label}</span>}
|
|
545
|
+
</span>
|
|
546
|
+
))}
|
|
547
|
+
</div>
|
|
548
|
+
{thumbValues.map((thumbValue, index) => (
|
|
549
|
+
<div
|
|
550
|
+
key={index}
|
|
551
|
+
role="slider"
|
|
552
|
+
tabIndex={disabled ? -1 : 0}
|
|
553
|
+
aria-valuemin={min}
|
|
554
|
+
aria-valuemax={max}
|
|
555
|
+
aria-valuenow={thumbValue}
|
|
556
|
+
aria-valuetext={typeof label === 'function' ? String(label(thumbValue)) : undefined}
|
|
557
|
+
aria-orientation={orientation}
|
|
558
|
+
aria-disabled={disabled || undefined}
|
|
559
|
+
aria-invalid={invalid || undefined}
|
|
560
|
+
aria-label={
|
|
561
|
+
// Each range thumb needs a distinct accessible name. Explicit
|
|
562
|
+
// tuple labels take precedence; otherwise derive from the root's
|
|
563
|
+
// aria-label + localized minimum/maximum suffix.
|
|
564
|
+
isRange
|
|
565
|
+
? ownThumbLabel(index) ||
|
|
566
|
+
(thumbUsesRootLabelledBy(index) || !ariaLabel
|
|
567
|
+
? undefined
|
|
568
|
+
: `${ariaLabel}, ${thumbSuffixes[index]}`)
|
|
569
|
+
: ariaLabel
|
|
570
|
+
}
|
|
571
|
+
aria-labelledby={
|
|
572
|
+
isRange
|
|
573
|
+
? thumbUsesRootLabelledBy(index)
|
|
574
|
+
? `${ariaLabelledBy} ${thumbSuffixIds[index]}`
|
|
575
|
+
: undefined
|
|
576
|
+
: ariaLabelledBy
|
|
577
|
+
}
|
|
578
|
+
aria-describedby={
|
|
579
|
+
// Forward the root's aria-describedby to each focusable thumb so a
|
|
580
|
+
// <Field error/description> wrapping a Slider is announced when a
|
|
581
|
+
// thumb has focus. The role-less root intentionally stays unnamed.
|
|
582
|
+
ariaDescribedBy
|
|
583
|
+
}
|
|
584
|
+
className={clsx(styles.thumb, isDragging[index] && styles.thumbDragging)}
|
|
585
|
+
style={thumbStyle(thumbValue)}
|
|
586
|
+
onPointerDown={(e) => handleThumbPointerDown(e, index)}
|
|
587
|
+
onPointerMove={(e) => handleThumbPointerMove(e, index)}
|
|
588
|
+
onPointerUp={(e) => handleThumbPointerUp(e, index)}
|
|
589
|
+
onPointerEnter={() => setFlag(setIsHovered, index, true)}
|
|
590
|
+
onPointerLeave={() => setFlag(setIsHovered, index, false)}
|
|
591
|
+
onFocus={() => {
|
|
592
|
+
setFlag(setIsFocused, index, true);
|
|
593
|
+
valueChangedThisFocusRef.current = false;
|
|
594
|
+
}}
|
|
595
|
+
onBlur={() => handleThumbBlur(index)}
|
|
596
|
+
onKeyDown={(e) => handleThumbKeyDown(e, index)}
|
|
597
|
+
>
|
|
598
|
+
{showLabelFor(index) && <span className={styles.label}>{formatLabel(thumbValue)}</span>}
|
|
599
|
+
</div>
|
|
600
|
+
))}
|
|
601
|
+
{rangeUsesRootLabelledBy && (
|
|
602
|
+
<>
|
|
603
|
+
{/* Referenced hidden nodes add localized context without rendering text. */}
|
|
604
|
+
<span id={thumbSuffixIds[0]} hidden>
|
|
605
|
+
{thumbSuffixes[0]}
|
|
606
|
+
</span>
|
|
607
|
+
<span id={thumbSuffixIds[1]} hidden>
|
|
608
|
+
{thumbSuffixes[1]}
|
|
609
|
+
</span>
|
|
610
|
+
</>
|
|
611
|
+
)}
|
|
612
|
+
{name &&
|
|
613
|
+
!disabled &&
|
|
614
|
+
(isRange ? (
|
|
615
|
+
<>
|
|
616
|
+
<input type="hidden" name={`${name}-min`} value={(value as [number, number])[0]} />
|
|
617
|
+
<input type="hidden" name={`${name}-max`} value={(value as [number, number])[1]} />
|
|
618
|
+
</>
|
|
619
|
+
) : (
|
|
620
|
+
<input type="hidden" name={name} value={value as number} />
|
|
621
|
+
))}
|
|
622
|
+
</div>
|
|
623
|
+
);
|
|
624
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
@use './SlotGrid.tokens';
|
|
2
|
+
@use '../_internal/choiceTile' as tile;
|
|
3
|
+
|
|
4
|
+
.root {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: var(--slot-grid-group-gap);
|
|
8
|
+
container-type: inline-size;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.group {
|
|
12
|
+
// UA fieldset reset (precedent: Radio/RadioGroup.module.scss).
|
|
13
|
+
// stylelint-disable-next-line property-disallowed-list -- UA fieldset reset, not layout
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
border: 0;
|
|
17
|
+
min-width: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.legend {
|
|
21
|
+
// stylelint-disable-next-line property-disallowed-list -- UA legend reset + internal spacing to the tiles
|
|
22
|
+
margin: 0 0 var(--slot-grid-legend-gap);
|
|
23
|
+
padding: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.tiles {
|
|
27
|
+
display: grid;
|
|
28
|
+
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
29
|
+
gap: var(--slot-grid-gap);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@container (max-width: 48rem) {
|
|
33
|
+
.tiles {
|
|
34
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.tile {
|
|
39
|
+
@include tile.choice-tile(
|
|
40
|
+
$input: '.input',
|
|
41
|
+
$bg: var(--slot-grid-tile-bg),
|
|
42
|
+
$bg-hover: var(--slot-grid-tile-bg-hover),
|
|
43
|
+
$fg: var(--slot-grid-tile-fg),
|
|
44
|
+
$border: var(--slot-grid-tile-border),
|
|
45
|
+
$bg-checked: var(--slot-grid-tile-bg-checked),
|
|
46
|
+
$bg-checked-hover: var(--slot-grid-tile-bg-checked-hover),
|
|
47
|
+
$fg-checked: var(--slot-grid-tile-fg-checked),
|
|
48
|
+
$radius: var(--slot-grid-tile-radius),
|
|
49
|
+
$ring: var(--slot-grid-tile-ring),
|
|
50
|
+
$opacity-disabled: var(--slot-grid-tile-opacity-disabled)
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
height: var(--slot-grid-tile-height);
|
|
54
|
+
font-size: var(--slot-grid-tile-font-size);
|
|
55
|
+
font-weight: var(--slot-grid-tile-font-weight);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Needs a real declaration so CSS Modules emits the class the mixin targets.
|
|
59
|
+
.input {
|
|
60
|
+
opacity: var(--opacity-hidden);
|
|
61
|
+
}
|