@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,232 @@
|
|
|
1
|
+
import { useId, useLayoutEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export type OverlayStackMode = 'replace' | 'overlay';
|
|
4
|
+
|
|
5
|
+
interface Entry {
|
|
6
|
+
id: string;
|
|
7
|
+
mode: OverlayStackMode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Internal ordered list of open overlay entries, most-recently-registered last.
|
|
11
|
+
const stack: Entry[] = [];
|
|
12
|
+
const listeners = new Set<() => void>();
|
|
13
|
+
const floating = new Set<string>();
|
|
14
|
+
// Escape events already handled (surface closed on them). Order-independent
|
|
15
|
+
// complement to the registry: a re-render can re-register a surface's
|
|
16
|
+
// document-capture listener AHEAD of its host's (effects re-fire child-
|
|
17
|
+
// first), so the surface may close + unregister within the same press —
|
|
18
|
+
// the host must still yield to a consumed event. WeakSet: no leaks.
|
|
19
|
+
const consumedEscapes = new WeakSet<Event>();
|
|
20
|
+
|
|
21
|
+
// Open floating surfaces (Select listbox, Popover, DropdownMenu levels,
|
|
22
|
+
// date/time popovers, Rail flyout). Hosts' Escape handlers yield while any
|
|
23
|
+
// is open so a single press closes the innermost surface, not the host too
|
|
24
|
+
// (#274). A Set of ids — hosts only need "is anything open". Surface-vs-
|
|
25
|
+
// surface ordering is NOT guaranteed here (a Select inside a Popover still
|
|
26
|
+
// closes with it on one press); only two hardcoded pairs defer today:
|
|
27
|
+
// DropdownMenu sub->parent and TimeField clock->calendar. See #280. The
|
|
28
|
+
// registry is also global, not host-scoped: any host yields to any open
|
|
29
|
+
// surface, even one belonging to a lower overlay — rare but reachable (e.g.
|
|
30
|
+
// a modal opened from a control inside a Popover: the popover dismisses only
|
|
31
|
+
// on outside pointerdown, so it stays open and registered underneath, and
|
|
32
|
+
// the modal's first Escape press yields to it).
|
|
33
|
+
|
|
34
|
+
function notify() {
|
|
35
|
+
for (const fn of listeners) fn();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function indexOf(id: string): number {
|
|
39
|
+
return stack.findIndex((e) => e.id === id);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function depthOf(id: string): number {
|
|
43
|
+
return indexOf(id);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function topEntry(): Entry | null {
|
|
47
|
+
return stack.length === 0 ? null : stack[stack.length - 1]!;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Module-level singleton tracking open overlay ids in registration order.
|
|
52
|
+
* Each overlay (Modal, Drawer) calls `register` on open and `unregister` on close. Depth is
|
|
53
|
+
* the overlay's index in the open-stack (0 = bottom, length-1 = top).
|
|
54
|
+
* Subscribers are notified after every register/unregister so consumers
|
|
55
|
+
* can re-derive `isTop` / `depth` / `topMode`.
|
|
56
|
+
*/
|
|
57
|
+
export const overlayStack = {
|
|
58
|
+
/**
|
|
59
|
+
* Register this overlay. If already present, update its mode in place
|
|
60
|
+
* (handles a parent re-render where stackMode prop changed).
|
|
61
|
+
*/
|
|
62
|
+
register(id: string, mode: OverlayStackMode): number {
|
|
63
|
+
const idx = indexOf(id);
|
|
64
|
+
if (idx === -1) {
|
|
65
|
+
stack.push({ id, mode });
|
|
66
|
+
} else {
|
|
67
|
+
stack[idx]!.mode = mode;
|
|
68
|
+
}
|
|
69
|
+
notify();
|
|
70
|
+
return depthOf(id);
|
|
71
|
+
},
|
|
72
|
+
unregister(id: string): void {
|
|
73
|
+
const idx = indexOf(id);
|
|
74
|
+
if (idx >= 0) {
|
|
75
|
+
stack.splice(idx, 1);
|
|
76
|
+
notify();
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
isTop(id: string): boolean {
|
|
80
|
+
return topEntry()?.id === id;
|
|
81
|
+
},
|
|
82
|
+
topDepth(): number {
|
|
83
|
+
return stack.length;
|
|
84
|
+
},
|
|
85
|
+
topMode(): OverlayStackMode | null {
|
|
86
|
+
return topEntry()?.mode ?? null;
|
|
87
|
+
},
|
|
88
|
+
depthOf,
|
|
89
|
+
/** Register an open floating surface (Escape-yield participant, #274). */
|
|
90
|
+
registerFloating(id: string): void {
|
|
91
|
+
floating.add(id);
|
|
92
|
+
},
|
|
93
|
+
unregisterFloating(id: string): void {
|
|
94
|
+
floating.delete(id);
|
|
95
|
+
},
|
|
96
|
+
/** True while any floating surface is open — hosts yield Escape to it. */
|
|
97
|
+
hasOpenFloating(): boolean {
|
|
98
|
+
return floating.size > 0;
|
|
99
|
+
},
|
|
100
|
+
/** A closing surface marks its Escape so hosts yield even when the
|
|
101
|
+
* surface's listener ran first (registration order is not stable). */
|
|
102
|
+
consumeEscape(e: Event): void {
|
|
103
|
+
consumedEscapes.add(e);
|
|
104
|
+
},
|
|
105
|
+
wasEscapeConsumed(e: Event): boolean {
|
|
106
|
+
return consumedEscapes.has(e);
|
|
107
|
+
},
|
|
108
|
+
/**
|
|
109
|
+
* True iff `id` is the INNERMOST open floating surface — the last one
|
|
110
|
+
* registered (surfaces register on open, outer-first, so the most-recently-
|
|
111
|
+
* opened is innermost). On Escape every surface defers unless it's innermost,
|
|
112
|
+
* so one press closes exactly the deepest surface (#280). Order-independent of
|
|
113
|
+
* listener firing: it reads the registry, not the event. Returns false if `id`
|
|
114
|
+
* isn't registered (e.g. already closing).
|
|
115
|
+
*
|
|
116
|
+
* Only CONTAINER surfaces that can host a deeper one (Popover, Select,
|
|
117
|
+
* DropdownMenu) gate their Escape on this. Leaf surfaces (date-time grids, the
|
|
118
|
+
* Rail flyout, RTE menus) are always innermost when nested and intentionally
|
|
119
|
+
* omit the guard — add it if a leaf ever hosts a Select/Popover/menu, or one
|
|
120
|
+
* Escape will wrongly close both.
|
|
121
|
+
*/
|
|
122
|
+
isTopFloating(id: string): boolean {
|
|
123
|
+
let last: string | undefined;
|
|
124
|
+
for (const x of floating) last = x; // Set preserves insertion (open) order
|
|
125
|
+
return last === id;
|
|
126
|
+
},
|
|
127
|
+
/** Subscribe to register/unregister notifications. Returns unsubscribe. */
|
|
128
|
+
_subscribe(fn: () => void): () => void {
|
|
129
|
+
listeners.add(fn);
|
|
130
|
+
return () => {
|
|
131
|
+
listeners.delete(fn);
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
/** Test-only escape hatch. */
|
|
135
|
+
_reset(): void {
|
|
136
|
+
stack.length = 0;
|
|
137
|
+
listeners.clear();
|
|
138
|
+
floating.clear();
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export interface OverlayStackState {
|
|
143
|
+
/** Current depth in the stack, or null if not registered. */
|
|
144
|
+
depth: number | null;
|
|
145
|
+
/** True iff this overlay is the topmost open overlay. */
|
|
146
|
+
isTop: boolean;
|
|
147
|
+
/** Mode of the current top overlay (null if stack is empty). */
|
|
148
|
+
topMode: OverlayStackMode | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Register/unregister this overlay in the singleton stack while `active` is
|
|
153
|
+
* true. Returns the current depth, whether this overlay is on top, and the
|
|
154
|
+
* top overlay's stackMode. Subscribes to stack mutations so state stays
|
|
155
|
+
* accurate when sibling overlays open/close.
|
|
156
|
+
*/
|
|
157
|
+
export function useOverlayStack(
|
|
158
|
+
id: string,
|
|
159
|
+
active: boolean,
|
|
160
|
+
mode: OverlayStackMode,
|
|
161
|
+
): OverlayStackState {
|
|
162
|
+
// Lazy initializer pre-computes the post-registration state so the FIRST
|
|
163
|
+
// render of an opened overlay already has correct `topMode` / `isTop` /
|
|
164
|
+
// `depth`. Without this, paint and stack-position attributes would be
|
|
165
|
+
// wrong on the first paint (transparent overlay flash, etc.). The actual
|
|
166
|
+
// register() still happens in useLayoutEffect; this is read-only.
|
|
167
|
+
const [state, setState] = useState<OverlayStackState>(() => {
|
|
168
|
+
if (!active) return { depth: null, isTop: false, topMode: null };
|
|
169
|
+
return {
|
|
170
|
+
depth: overlayStack.topDepth(),
|
|
171
|
+
isTop: true,
|
|
172
|
+
topMode: mode,
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// useLayoutEffect (not useEffect) so registration + state sync happen
|
|
177
|
+
// synchronously after commit, before the browser paints. Prevents a
|
|
178
|
+
// one-frame flash of the wrong overlay attributes.
|
|
179
|
+
useLayoutEffect(() => {
|
|
180
|
+
if (!active) {
|
|
181
|
+
setState({ depth: null, isTop: false, topMode: null });
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
overlayStack.register(id, mode);
|
|
185
|
+
const sync = () => {
|
|
186
|
+
setState({
|
|
187
|
+
depth: overlayStack.depthOf(id),
|
|
188
|
+
isTop: overlayStack.isTop(id),
|
|
189
|
+
topMode: overlayStack.topMode(),
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
sync();
|
|
193
|
+
const unsubscribe = overlayStack._subscribe(sync);
|
|
194
|
+
return () => {
|
|
195
|
+
unsubscribe();
|
|
196
|
+
overlayStack.unregister(id);
|
|
197
|
+
};
|
|
198
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- mode handled by separate effect below to avoid tear-down on mode change
|
|
199
|
+
}, [id, active]);
|
|
200
|
+
|
|
201
|
+
// Update mode in place without tearing down the entry. overlayStack.register
|
|
202
|
+
// handles existing entries by updating their mode and re-notifying.
|
|
203
|
+
useLayoutEffect(() => {
|
|
204
|
+
if (!active) return;
|
|
205
|
+
overlayStack.register(id, mode);
|
|
206
|
+
}, [id, active, mode]);
|
|
207
|
+
|
|
208
|
+
return state;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Register this floating surface in the Escape-yield registry while `open`
|
|
213
|
+
* (#274). Hosts (Modal/Drawer/Lightbox) skip their Escape-close while any
|
|
214
|
+
* surface is registered, so the surface's own Escape handling — a document-
|
|
215
|
+
* capture listener for most surfaces, an element-scoped handler for the
|
|
216
|
+
* editor-owned menus (Liquid autocomplete, RTE mentions) — closes it instead;
|
|
217
|
+
* the next press reaches the host. Layout effect: the registration must be
|
|
218
|
+
* observable before the browser can deliver the next keydown.
|
|
219
|
+
*/
|
|
220
|
+
export function useFloatingSurface(open: boolean): string {
|
|
221
|
+
const id = useId();
|
|
222
|
+
useLayoutEffect(() => {
|
|
223
|
+
if (!open) return;
|
|
224
|
+
overlayStack.registerFloating(id);
|
|
225
|
+
return () => {
|
|
226
|
+
overlayStack.unregisterFloating(id);
|
|
227
|
+
};
|
|
228
|
+
}, [id, open]);
|
|
229
|
+
// Returned so a surface can gate its Escape handler on `isTopFloating(id)` and
|
|
230
|
+
// defer to a deeper surface (#280). Stable across renders (useId).
|
|
231
|
+
return id;
|
|
232
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { useLayoutEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
// Module-level state shared across all useScrollLock callers.
|
|
4
|
+
let count = 0;
|
|
5
|
+
let originalPosition: string | null = null;
|
|
6
|
+
let originalTop: string | null = null;
|
|
7
|
+
let originalLeft: string | null = null;
|
|
8
|
+
let originalWidth: string | null = null;
|
|
9
|
+
let originalPaddingRight: string | null = null;
|
|
10
|
+
let rAFHandle: number | null = null;
|
|
11
|
+
|
|
12
|
+
function lock() {
|
|
13
|
+
// Cancel any pending unlock rAF — if a new modal opens before the
|
|
14
|
+
// previous unlock's rAF fired, we don't want the deferred scrollTo
|
|
15
|
+
// to fire after the new lock has set body.style.top.
|
|
16
|
+
if (rAFHandle !== null) {
|
|
17
|
+
cancelAnimationFrame(rAFHandle);
|
|
18
|
+
rAFHandle = null;
|
|
19
|
+
}
|
|
20
|
+
if (count === 0) {
|
|
21
|
+
const scrollY = window.scrollY;
|
|
22
|
+
const scrollX = window.scrollX;
|
|
23
|
+
|
|
24
|
+
originalPosition = document.body.style.position;
|
|
25
|
+
originalTop = document.body.style.top;
|
|
26
|
+
originalLeft = document.body.style.left;
|
|
27
|
+
originalWidth = document.body.style.width;
|
|
28
|
+
originalPaddingRight = document.body.style.paddingRight;
|
|
29
|
+
|
|
30
|
+
// Scrollbar-width compensation: body becomes position:fixed, the html
|
|
31
|
+
// scrollbar disappears, and content would otherwise reflow horizontally
|
|
32
|
+
// into the freed space. Padding on body absorbs that shift.
|
|
33
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
34
|
+
if (scrollbarWidth > 0) {
|
|
35
|
+
document.body.style.paddingRight = `${scrollbarWidth}px`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Fix the body in place at the user's current visual scroll position.
|
|
39
|
+
// top: -<scrollY>px keeps the content visually where it was; the body
|
|
40
|
+
// is now out of flow so no scrolling is possible. This avoids the
|
|
41
|
+
// scroll-to-top jump that `overflow: hidden` causes on the html element
|
|
42
|
+
// (overflow:hidden clamps scrollTop to 0).
|
|
43
|
+
document.body.style.position = 'fixed';
|
|
44
|
+
document.body.style.top = `-${scrollY}px`;
|
|
45
|
+
document.body.style.left = `-${scrollX}px`;
|
|
46
|
+
document.body.style.width = '100%';
|
|
47
|
+
}
|
|
48
|
+
count += 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function unlock() {
|
|
52
|
+
count = Math.max(0, count - 1);
|
|
53
|
+
if (count === 0) {
|
|
54
|
+
// Read saved scroll position from the body's top/left offset BEFORE
|
|
55
|
+
// restoring, so we can scroll back to exactly where we were.
|
|
56
|
+
const savedY = -parseFloat(document.body.style.top || '0');
|
|
57
|
+
const savedX = -parseFloat(document.body.style.left || '0');
|
|
58
|
+
|
|
59
|
+
document.body.style.position = originalPosition ?? '';
|
|
60
|
+
document.body.style.top = originalTop ?? '';
|
|
61
|
+
document.body.style.left = originalLeft ?? '';
|
|
62
|
+
document.body.style.width = originalWidth ?? '';
|
|
63
|
+
document.body.style.paddingRight = originalPaddingRight ?? '';
|
|
64
|
+
|
|
65
|
+
originalPosition = null;
|
|
66
|
+
originalTop = null;
|
|
67
|
+
originalLeft = null;
|
|
68
|
+
originalWidth = null;
|
|
69
|
+
originalPaddingRight = null;
|
|
70
|
+
|
|
71
|
+
// Force a synchronous reflow so the document's scrollable height is
|
|
72
|
+
// recalculated from the now-restored body BEFORE we scrollTo. Without
|
|
73
|
+
// this, the browser can clamp scrollTo to maxScrollY = 0 (the height
|
|
74
|
+
// while body was still fixed) and the page jumps to the top.
|
|
75
|
+
void document.body.offsetHeight;
|
|
76
|
+
|
|
77
|
+
// `behavior: 'instant'` bypasses any smooth-scroll preference and forces
|
|
78
|
+
// a single-frame jump. Without it, an animated scroll could be
|
|
79
|
+
// interrupted by post-unlock reflow (focus restoration) and land at an
|
|
80
|
+
// intermediate position.
|
|
81
|
+
window.scrollTo({ left: savedX, top: savedY, behavior: 'instant' });
|
|
82
|
+
|
|
83
|
+
// Belt-and-braces: re-issue on the next frame in case the synchronous
|
|
84
|
+
// call was clamped because the layout pipeline hadn't yet committed.
|
|
85
|
+
// No-op when the first call already succeeded. The handle is tracked so
|
|
86
|
+
// lock() can cancel this if a new modal opens before the frame fires.
|
|
87
|
+
rAFHandle = requestAnimationFrame(() => {
|
|
88
|
+
rAFHandle = null;
|
|
89
|
+
window.scrollTo({ left: savedX, top: savedY, behavior: 'instant' });
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Body scroll lock. Ref-counted across all callers so nested modals share
|
|
96
|
+
* the same lock — the first acquire suppresses scrolling, the last release
|
|
97
|
+
* restores it.
|
|
98
|
+
*
|
|
99
|
+
* Pins `body` to `position: fixed` with `top: -<scrollY>px` and
|
|
100
|
+
* `left: -<scrollX>px` so the user's visual scroll position is preserved
|
|
101
|
+
* while the body is locked. On unlock, the saved offsets are read back from
|
|
102
|
+
* body's inline styles and `scrollTo` returns the page to where the user
|
|
103
|
+
* left it. `overflow: hidden` on html is intentionally NOT used here
|
|
104
|
+
* because it clamps `scrollTop` to 0 and jumps the page to the top.
|
|
105
|
+
*/
|
|
106
|
+
export function useScrollLock(active: boolean): void {
|
|
107
|
+
useLayoutEffect(() => {
|
|
108
|
+
if (!active) return;
|
|
109
|
+
lock();
|
|
110
|
+
return unlock;
|
|
111
|
+
}, [active]);
|
|
112
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Ref } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Merge multiple refs into one. Each provided ref (callback or object) is set
|
|
5
|
+
* to the same value. Used by components that clone a child element and want
|
|
6
|
+
* to attach an internal ref alongside the consumer's own ref.
|
|
7
|
+
*/
|
|
8
|
+
export function mergeRefs<T>(...refs: Array<Ref<T> | undefined | null>): Ref<T> {
|
|
9
|
+
return (value: T | null) => {
|
|
10
|
+
for (const ref of refs) {
|
|
11
|
+
if (!ref) continue;
|
|
12
|
+
if (typeof ref === 'function') ref(value);
|
|
13
|
+
else (ref as React.MutableRefObject<T | null>).current = value;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Chain event handlers. Each provided handler runs in order with the same
|
|
20
|
+
* event. Used when a cloned element already has an `onX` and the wrapping
|
|
21
|
+
* component needs to add its own without overwriting.
|
|
22
|
+
*/
|
|
23
|
+
export function chain<E>(...fns: Array<((event: E) => void) | undefined>): (event: E) => void {
|
|
24
|
+
return (event: E) => {
|
|
25
|
+
for (const fn of fns) fn?.(event);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Convert React's `useId()` output into a value safe to interpolate into a
|
|
31
|
+
* CSS-style id or class. Replaces every char that isn't `[A-Za-z0-9_-]` with
|
|
32
|
+
* an underscore.
|
|
33
|
+
*/
|
|
34
|
+
export function sanitizeId(raw: string): string {
|
|
35
|
+
return raw.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Merge a consumer-supplied `aria-describedby` with an additional id, keeping
|
|
40
|
+
* the consumer's value first and de-duplicating. Returns the additional id
|
|
41
|
+
* alone when the consumer didn't provide one.
|
|
42
|
+
*/
|
|
43
|
+
export function mergeAriaDescribedby(consumer: string | undefined, extra: string): string {
|
|
44
|
+
if (!consumer) return extra;
|
|
45
|
+
const tokens = consumer.split(/\s+/).filter(Boolean);
|
|
46
|
+
if (tokens.includes(extra)) return consumer;
|
|
47
|
+
return [...tokens, extra].join(' ');
|
|
48
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type PaletteColor } from '../../palette';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Workflow status category — maps to a default palette color. Shared by
|
|
5
|
+
* `PillMenu` and `EntityChip` so both resolve the same category → color
|
|
6
|
+
* mapping.
|
|
7
|
+
*/
|
|
8
|
+
export type StatusCategory = 'to_do' | 'in_progress' | 'open' | 'done' | 'won' | 'lost';
|
|
9
|
+
|
|
10
|
+
/** Category → default palette color: to_do slate / in_progress blue / open violet / done green / won green / lost red. */
|
|
11
|
+
export const STATUS_CATEGORY_COLOR: Record<StatusCategory, PaletteColor> = {
|
|
12
|
+
to_do: 'slate',
|
|
13
|
+
in_progress: 'blue',
|
|
14
|
+
open: 'violet',
|
|
15
|
+
done: 'green',
|
|
16
|
+
won: 'green',
|
|
17
|
+
lost: 'red',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** `color` wins; otherwise fall back to the category's default; otherwise slate. */
|
|
21
|
+
export function resolveStatusColor(status: {
|
|
22
|
+
category?: StatusCategory;
|
|
23
|
+
color?: PaletteColor;
|
|
24
|
+
}): PaletteColor {
|
|
25
|
+
return status.color ?? (status.category && STATUS_CATEGORY_COLOR[status.category]) ?? 'slate';
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export shim for the time-of-day utilities that live in
|
|
3
|
+
* `components/DatePicker/utils.ts`. `<TimeField>` lives at
|
|
4
|
+
* `components/TimeField/` and needs these helpers, but importing them
|
|
5
|
+
* via `'../DatePicker/utils'` would trick `scripts/generate-manifest.mjs`
|
|
6
|
+
* into recording a `TimeField → DatePicker` edge in the manifest's
|
|
7
|
+
* dependency graph — which is wrong (TimeField does not consume the
|
|
8
|
+
* DatePicker component, only its sibling utility module) and would
|
|
9
|
+
* introduce a cycle (DatePicker → TimeField → DatePicker).
|
|
10
|
+
*
|
|
11
|
+
* The manifest generator's parent-path regex captures only directory
|
|
12
|
+
* names that start with an uppercase letter, so this `_internal`
|
|
13
|
+
* detour is invisible to it. Update both modules if the utility
|
|
14
|
+
* surface changes.
|
|
15
|
+
*/
|
|
16
|
+
export {
|
|
17
|
+
formatTime,
|
|
18
|
+
parseTime,
|
|
19
|
+
resolveHourCycle,
|
|
20
|
+
roundTimeToStep,
|
|
21
|
+
type HourCycle,
|
|
22
|
+
type TimeValue,
|
|
23
|
+
} from '../DatePicker/utils';
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Args accepted by `useAsyncOptions`.
|
|
5
|
+
*
|
|
6
|
+
* `loadOptions` is the consumer-supplied fetcher; the hook is a no-op when
|
|
7
|
+
* it's `undefined`. `query` and `enabled` drive when fetches happen:
|
|
8
|
+
* `enabled` gates the very first request (the `loadOnOpen` semantic — wait
|
|
9
|
+
* until the popover opens), `query` is what gets debounced and passed to
|
|
10
|
+
* each call. `debounceMs` is the delay between the last `query` change and
|
|
11
|
+
* the actual `loadOptions` invocation.
|
|
12
|
+
*/
|
|
13
|
+
export interface UseAsyncOptionsArgs<R extends readonly unknown[]> {
|
|
14
|
+
/** Async fetcher. Receives the current query and an `AbortSignal`. */
|
|
15
|
+
loadOptions?: (query: string, signal: AbortSignal) => Promise<R>;
|
|
16
|
+
/** Current search query string. Empty string is a valid fetch trigger. */
|
|
17
|
+
query: string;
|
|
18
|
+
/**
|
|
19
|
+
* When `false`, no fetches happen (going `false` aborts the in-flight one).
|
|
20
|
+
* Select wires it to "has the popover ever opened"; OptionsPicker to "is
|
|
21
|
+
* the panel open now" (a fresh fetch per open).
|
|
22
|
+
*/
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
/** Debounce window before firing `loadOptions` after a query change. */
|
|
25
|
+
debounceMs: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Return value of `useAsyncOptions`.
|
|
30
|
+
*
|
|
31
|
+
* `options` is `[]` until the first successful fetch resolves. `loading` is
|
|
32
|
+
* `true` while a request is in flight (but flips back to `false` on abort
|
|
33
|
+
* too — the next request's `loading=true` takes over immediately). `error`
|
|
34
|
+
* is set on non-abort rejections and cleared at the start of each new
|
|
35
|
+
* fetch. `retry()` re-runs the current query (no debounce).
|
|
36
|
+
*/
|
|
37
|
+
export interface UseAsyncOptionsReturn<R extends readonly unknown[]> {
|
|
38
|
+
options: R;
|
|
39
|
+
loading: boolean;
|
|
40
|
+
error: Error | null;
|
|
41
|
+
/** The query `options` belongs to; `null` until the first request settles. */
|
|
42
|
+
loadedQuery: string | null;
|
|
43
|
+
retry: () => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Hook that wraps an async `loadOptions(query, signal)` into a state-row
|
|
48
|
+
* friendly shape (options/loading/error + retry). Handles three concerns
|
|
49
|
+
* the Select would otherwise reinvent:
|
|
50
|
+
*
|
|
51
|
+
* 1. Debouncing — collapses keystroke bursts into one request.
|
|
52
|
+
* 2. Cancellation — aborts the in-flight request when a new one starts, so
|
|
53
|
+
* a slow response from query "ab" can't overwrite a fresh result for
|
|
54
|
+
* "abc".
|
|
55
|
+
* 3. Lifecycle — aborts on unmount.
|
|
56
|
+
*
|
|
57
|
+
* The hook is gated by `enabled`: while it is false no fetches fire. Select
|
|
58
|
+
* passes "has opened at least once" (its `loadOnOpen` semantic); OptionsPicker
|
|
59
|
+
* passes "is open now", so every open refetches. Shared by both — not
|
|
60
|
+
* exported from the package root.
|
|
61
|
+
*/
|
|
62
|
+
export function useAsyncOptions<R extends readonly unknown[]>(
|
|
63
|
+
args: UseAsyncOptionsArgs<R>,
|
|
64
|
+
): UseAsyncOptionsReturn<R> {
|
|
65
|
+
const { loadOptions, query, enabled, debounceMs } = args;
|
|
66
|
+
|
|
67
|
+
const [options, setOptions] = useState<R>([] as unknown as R);
|
|
68
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
69
|
+
// The query `options` actually belongs to, or null before the first settle.
|
|
70
|
+
// Callers cannot infer this from `loading`: it is false for the whole
|
|
71
|
+
// debounce window, during which `options` is still the PREVIOUS query's.
|
|
72
|
+
const [loadedQuery, setLoadedQuery] = useState<string | null>(null);
|
|
73
|
+
const [error, setError] = useState<Error | null>(null);
|
|
74
|
+
const [retryToken, setRetryToken] = useState<number>(0);
|
|
75
|
+
|
|
76
|
+
const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
77
|
+
const abortRef = useRef<AbortController | null>(null);
|
|
78
|
+
|
|
79
|
+
// `runFetch` aborts any in-flight request before starting a new one, so a
|
|
80
|
+
// slow response can never overwrite a fresher one. `signal.aborted` is
|
|
81
|
+
// checked again on both resolution paths to handle the race where the
|
|
82
|
+
// abort fires AFTER the network call resolved but BEFORE React processes
|
|
83
|
+
// the `.then`.
|
|
84
|
+
const runFetch = useCallback(
|
|
85
|
+
(q: string) => {
|
|
86
|
+
if (!loadOptions) return;
|
|
87
|
+
if (abortRef.current) abortRef.current.abort();
|
|
88
|
+
const ac = new AbortController();
|
|
89
|
+
abortRef.current = ac;
|
|
90
|
+
setLoading(true);
|
|
91
|
+
setError(null);
|
|
92
|
+
loadOptions(q, ac.signal)
|
|
93
|
+
.then((next) => {
|
|
94
|
+
if (ac.signal.aborted) return;
|
|
95
|
+
setOptions(next);
|
|
96
|
+
setLoadedQuery(q);
|
|
97
|
+
setLoading(false);
|
|
98
|
+
})
|
|
99
|
+
.catch((err) => {
|
|
100
|
+
if (ac.signal.aborted) return;
|
|
101
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
102
|
+
setLoadedQuery(q);
|
|
103
|
+
setLoading(false);
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
[loadOptions],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Debounced trigger: any time `query`, `enabled`, or the retry token
|
|
110
|
+
// changes, queue a fetch `debounceMs` later. The cleanup clears the
|
|
111
|
+
// pending timer so rapid changes collapse to a single fetch.
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
if (!enabled || !loadOptions) return;
|
|
114
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
115
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
116
|
+
runFetch(query);
|
|
117
|
+
}, debounceMs);
|
|
118
|
+
return () => {
|
|
119
|
+
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
120
|
+
};
|
|
121
|
+
}, [query, enabled, debounceMs, retryToken, runFetch, loadOptions]);
|
|
122
|
+
|
|
123
|
+
// Disabled (OptionsPicker closing) aborts the in-flight request: its answer
|
|
124
|
+
// has no reader. Select's gate never returns to false.
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
if (enabled) return;
|
|
127
|
+
abortRef.current?.abort();
|
|
128
|
+
abortRef.current = null;
|
|
129
|
+
setLoading(false);
|
|
130
|
+
}, [enabled]);
|
|
131
|
+
|
|
132
|
+
// Abort on unmount so a still-in-flight request can't write into a
|
|
133
|
+
// dead component.
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
return () => {
|
|
136
|
+
if (abortRef.current) abortRef.current.abort();
|
|
137
|
+
};
|
|
138
|
+
}, []);
|
|
139
|
+
|
|
140
|
+
const retry = useCallback(() => {
|
|
141
|
+
setRetryToken((n) => n + 1);
|
|
142
|
+
}, []);
|
|
143
|
+
|
|
144
|
+
return { options, loading, error, retry, loadedQuery };
|
|
145
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useRef, useState, type ReactNode, type RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ClippedTooltip<T extends HTMLElement> {
|
|
4
|
+
/** Attach to the element whose text may be clipped by an ellipsis. */
|
|
5
|
+
ref: RefObject<T | null>;
|
|
6
|
+
/** Pass to `<Tooltip open>`. */
|
|
7
|
+
open: boolean;
|
|
8
|
+
/** Pass to `<Tooltip onOpenChange>`; refuses to open unless the label overflows. */
|
|
9
|
+
onOpenChange: (next: boolean) => void;
|
|
10
|
+
/** Pass to `<Tooltip content>`. */
|
|
11
|
+
content: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* State for a controlled `Tooltip` that shows a label's full text only when the
|
|
16
|
+
* label is actually clipped. A fully visible label gets no tooltip and no
|
|
17
|
+
* `aria-describedby`, so it is not announced twice.
|
|
18
|
+
*
|
|
19
|
+
* `content`: a STRING `label` is used directly, so it is always fresh off the
|
|
20
|
+
* prop, even if it changes while the tooltip is open. Any other `label` (styled
|
|
21
|
+
* node, icon, …) falls back to plain text captured from the element's
|
|
22
|
+
* `textContent` when the tooltip opens, so a styled label's colour and weight
|
|
23
|
+
* don't leak onto the dark tooltip background.
|
|
24
|
+
*
|
|
25
|
+
* The captured text falls back to `label` with `||`, not `??`: Tooltip treats
|
|
26
|
+
* `null`/`undefined`/`''` content as "disabled" (no listeners at all), so an
|
|
27
|
+
* EMPTY capture (a label that renders no text, e.g. an icon) is stored as
|
|
28
|
+
* `null` and must resolve back to the current `label`. Otherwise the tooltip
|
|
29
|
+
* would stay disabled even after `label` becomes a long, clipped string (#592).
|
|
30
|
+
*
|
|
31
|
+
* `enabled`: pass `false` while the caller renders no Tooltip (e.g. a loading
|
|
32
|
+
* state). An open tooltip that unmounts has nothing left to close it, so the
|
|
33
|
+
* state resets during render and cannot remount already open.
|
|
34
|
+
*/
|
|
35
|
+
export function useClippedTooltip<T extends HTMLElement>(
|
|
36
|
+
label: ReactNode,
|
|
37
|
+
enabled = true,
|
|
38
|
+
): ClippedTooltip<T> {
|
|
39
|
+
const ref = useRef<T>(null);
|
|
40
|
+
const [open, setOpen] = useState(false);
|
|
41
|
+
const [text, setText] = useState<string | null>(null);
|
|
42
|
+
if (!enabled && open) setOpen(false);
|
|
43
|
+
const onOpenChange = (next: boolean) => {
|
|
44
|
+
const el = ref.current;
|
|
45
|
+
if (next && el != null) setText(el.textContent || null);
|
|
46
|
+
setOpen(next && el != null && el.scrollWidth > el.clientWidth);
|
|
47
|
+
};
|
|
48
|
+
const content = typeof label === 'string' ? label : text || label;
|
|
49
|
+
return { ref, open, onOpenChange, content };
|
|
50
|
+
}
|