@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,617 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useId,
|
|
6
|
+
useLayoutEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
type CSSProperties,
|
|
10
|
+
type HTMLAttributes,
|
|
11
|
+
type KeyboardEvent as ReactKeyboardEvent,
|
|
12
|
+
type ReactNode,
|
|
13
|
+
} from 'react';
|
|
14
|
+
import { createPortal } from 'react-dom';
|
|
15
|
+
import {
|
|
16
|
+
arrow,
|
|
17
|
+
autoUpdate,
|
|
18
|
+
flip,
|
|
19
|
+
offset,
|
|
20
|
+
shift,
|
|
21
|
+
useFloating,
|
|
22
|
+
type Placement,
|
|
23
|
+
} from '@floating-ui/react-dom';
|
|
24
|
+
import clsx from 'clsx';
|
|
25
|
+
import { Button } from '../Button';
|
|
26
|
+
import { Cluster } from '../Cluster';
|
|
27
|
+
import { CircularProgress } from '../CircularProgress';
|
|
28
|
+
import { Stack } from '../Stack';
|
|
29
|
+
import { useTranslation } from '../../i18n/useTranslation';
|
|
30
|
+
import {
|
|
31
|
+
TOUR_CURRENT_TARGET,
|
|
32
|
+
overlayStack,
|
|
33
|
+
useFloatingSurface,
|
|
34
|
+
useFocusTrap,
|
|
35
|
+
} from '../_internal/overlay';
|
|
36
|
+
import { mergeRefs, sanitizeId } from '../_internal/refs';
|
|
37
|
+
import { useControllableState } from '../_internal/useControllableState';
|
|
38
|
+
import { Spotlight } from './Spotlight';
|
|
39
|
+
import { useTourTarget } from './useTourTarget';
|
|
40
|
+
import styles from './Tour.module.scss';
|
|
41
|
+
|
|
42
|
+
/** Preferred side of the target for the card. Auto-flips on collision. */
|
|
43
|
+
export type TourSide = 'top' | 'right' | 'bottom' | 'left';
|
|
44
|
+
/** Which card edge aligns with the matching target edge. */
|
|
45
|
+
export type TourAlign = 'start' | 'center' | 'end';
|
|
46
|
+
/** Why a tour ended: `'completed'` = Done on the last step; `'skipped'` = Skip or Escape. */
|
|
47
|
+
export type TourFinishReason = 'completed' | 'skipped';
|
|
48
|
+
|
|
49
|
+
/** One step of a `<Tour>`. Plain data — keep tours in a config module. */
|
|
50
|
+
export interface TourStep {
|
|
51
|
+
/**
|
|
52
|
+
* `data-tour` value of the element to spotlight (`<Button data-tour="bulk-edit">`
|
|
53
|
+
* ↔ `target: 'bulk-edit'`). Omit for a centered step with no spotlight
|
|
54
|
+
* (welcome / finish). If the target isn't mounted yet the Tour waits for it
|
|
55
|
+
* — see `targetTimeout`.
|
|
56
|
+
*/
|
|
57
|
+
target?: string;
|
|
58
|
+
/** Card heading; also the dialog's accessible name. */
|
|
59
|
+
title: ReactNode;
|
|
60
|
+
/** Card text; also the dialog's accessible description. Links, `Kbd`, etc. are fine. */
|
|
61
|
+
body?: ReactNode;
|
|
62
|
+
/** Preferred side of the target. Default `'bottom'`. Auto-flips if it doesn't fit. */
|
|
63
|
+
side?: TourSide;
|
|
64
|
+
/** Edge alignment against the target. Default `'center'`. */
|
|
65
|
+
align?: TourAlign;
|
|
66
|
+
/** Px of spotlight around the target. Default `8`. */
|
|
67
|
+
spotlightPadding?: number;
|
|
68
|
+
/**
|
|
69
|
+
* Modal mode only. The target stays clickable through the spotlight and joins
|
|
70
|
+
* the focus trap — for "click X to continue" steps. Default `false`
|
|
71
|
+
* (look-only: the target is blocked like the rest of the page).
|
|
72
|
+
*/
|
|
73
|
+
interactive?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* `'click'` advances to the next step after the target's own click handler
|
|
76
|
+
* runs. Needs a clickable target: `interactive: true` in modal mode, or any
|
|
77
|
+
* step with `modal={false}`. Ignored (dev warning) otherwise.
|
|
78
|
+
*/
|
|
79
|
+
advanceOn?: 'click';
|
|
80
|
+
/**
|
|
81
|
+
* What the card's Next / Done / ArrowRight does on a click-to-continue step
|
|
82
|
+
* (`advanceOn: 'click'`). Ignored on any other step.
|
|
83
|
+
* - `'click'` (default) — activates the target (a full pointer sequence), so
|
|
84
|
+
* the step's own action runs, then the tour advances.
|
|
85
|
+
* - `'skip'` — advances without touching the target. Choose it when the
|
|
86
|
+
* target's action has side effects Next shouldn't trigger (a delete, a
|
|
87
|
+
* save, a navigation). The hint, the secondary Next and the waves stay;
|
|
88
|
+
* a real click on the target still advances.
|
|
89
|
+
*/
|
|
90
|
+
next?: 'click' | 'skip';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface TourProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'children'> {
|
|
94
|
+
/** The steps, in order. Must be non-empty. */
|
|
95
|
+
steps: TourStep[];
|
|
96
|
+
/**
|
|
97
|
+
* Controlled open state (required — like `Modal`, there is no uncontrolled
|
|
98
|
+
* mode: an uncontrolled tour could not be started or replayed).
|
|
99
|
+
*/
|
|
100
|
+
open: boolean;
|
|
101
|
+
/** Called with `false` on Skip, Escape and Done. */
|
|
102
|
+
onOpenChange: (open: boolean) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Fires once per Skip / Escape / Done. NOT called when the consumer closes
|
|
105
|
+
* the tour itself by setting `open={false}` — only the tour's own end
|
|
106
|
+
* gestures fire it. Use it to persist "seen" state.
|
|
107
|
+
*/
|
|
108
|
+
onFinish?: (reason: TourFinishReason) => void;
|
|
109
|
+
/**
|
|
110
|
+
* Controlled step index. Control it when a step change must do something
|
|
111
|
+
* first — navigate to another page, open an accordion, switch a tab — then
|
|
112
|
+
* the Tour waits for the next target to mount.
|
|
113
|
+
*/
|
|
114
|
+
step?: number;
|
|
115
|
+
/** Fires on every step change (Next, Back, arrow keys, `advanceOn`), controlled or not. */
|
|
116
|
+
onStepChange?: (index: number) => void;
|
|
117
|
+
/** Uncontrolled starting step. Default `0`. Every re-open starts here again. */
|
|
118
|
+
defaultStep?: number;
|
|
119
|
+
/**
|
|
120
|
+
* `true` (default): dims the page with a spotlight cutout, blocks clicks
|
|
121
|
+
* outside it and traps focus — onboarding. `false`: card only, page stays
|
|
122
|
+
* usable — feature announcements.
|
|
123
|
+
*/
|
|
124
|
+
modal?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Ms to wait for a step's target before falling back to a centered card.
|
|
127
|
+
* Default `5000` (room for a route change + data fetch). `Infinity` waits forever.
|
|
128
|
+
*/
|
|
129
|
+
targetTimeout?: number;
|
|
130
|
+
/** Called when a step's target didn't appear within `targetTimeout`. Log it. */
|
|
131
|
+
onTargetMissing?: (step: TourStep, index: number) => void;
|
|
132
|
+
/**
|
|
133
|
+
* Contextual label for the last step's button, e.g. `'Got it'` for a
|
|
134
|
+
* one-step announcement. Defaults to the i18n `tour.done` (`'Done'`). An
|
|
135
|
+
* empty string counts as unset.
|
|
136
|
+
*/
|
|
137
|
+
doneLabel?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Activates a click-to-continue target. DropdownMenu's trigger toggles on
|
|
142
|
+
* pointerdown, so a bare click() wouldn't activate it; replay the full
|
|
143
|
+
* primary-pointer sequence a real click produces.
|
|
144
|
+
*/
|
|
145
|
+
function activate(el: HTMLElement) {
|
|
146
|
+
const init = { bubbles: true, cancelable: true, button: 0 };
|
|
147
|
+
const Ptr = typeof window.PointerEvent === 'function' ? window.PointerEvent : MouseEvent;
|
|
148
|
+
const ptr = { ...init, isPrimary: true, pointerType: 'mouse' };
|
|
149
|
+
el.dispatchEvent(new Ptr('pointerdown', ptr));
|
|
150
|
+
el.dispatchEvent(new MouseEvent('mousedown', init));
|
|
151
|
+
el.dispatchEvent(new Ptr('pointerup', ptr));
|
|
152
|
+
el.dispatchEvent(new MouseEvent('mouseup', init));
|
|
153
|
+
el.dispatchEvent(new MouseEvent('click', init));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Unmount fallback when `transitionend` never fires (reduced motion, jsdom). */
|
|
157
|
+
export const EXIT_FALLBACK_MS = 300;
|
|
158
|
+
/** Gap in px between target and card (room for the arrow). */
|
|
159
|
+
const CARD_OFFSET = 12;
|
|
160
|
+
/** Viewport edge padding for shift(); mirrored by `--tour-card-viewport-gap` in Tour.tokens.scss. */
|
|
161
|
+
const CARD_VIEWPORT_PADDING = 8;
|
|
162
|
+
/** Arrow keys inside these keep their native meaning (caret, option list). */
|
|
163
|
+
const EDITABLE = 'input, textarea, select, [contenteditable]:not([contenteditable="false"])';
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Guided tour that spotlights each step's `data-tour` target and anchors a card with Skip / Back / Next to it.
|
|
167
|
+
* @see docs/components/Tour.md
|
|
168
|
+
*/
|
|
169
|
+
export const Tour = forwardRef<HTMLDivElement, TourProps>(function Tour(props, ref) {
|
|
170
|
+
const { open } = props;
|
|
171
|
+
const [present, setPresent] = useState(open);
|
|
172
|
+
const [session, setSession] = useState(0);
|
|
173
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
174
|
+
if (open !== prevOpen) {
|
|
175
|
+
setPrevOpen(open);
|
|
176
|
+
if (open) {
|
|
177
|
+
setPresent(true);
|
|
178
|
+
setSession((s) => s + 1);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const onExited = useCallback(() => setPresent(false), []);
|
|
182
|
+
if (!present) return null;
|
|
183
|
+
// A fresh session per open resets uncontrolled step state to defaultStep.
|
|
184
|
+
return <TourSession key={session} {...props} ref={ref} closing={!open} onExited={onExited} />;
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
interface TourSessionProps extends TourProps {
|
|
188
|
+
closing: boolean;
|
|
189
|
+
onExited: () => void;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const TourSession = forwardRef<HTMLDivElement, TourSessionProps>(function TourSession(
|
|
193
|
+
{
|
|
194
|
+
steps,
|
|
195
|
+
open: _open,
|
|
196
|
+
onOpenChange,
|
|
197
|
+
onFinish,
|
|
198
|
+
step: stepProp,
|
|
199
|
+
onStepChange,
|
|
200
|
+
defaultStep = 0,
|
|
201
|
+
modal = true,
|
|
202
|
+
targetTimeout = 5000,
|
|
203
|
+
onTargetMissing,
|
|
204
|
+
doneLabel,
|
|
205
|
+
closing,
|
|
206
|
+
onExited,
|
|
207
|
+
onKeyDown,
|
|
208
|
+
className,
|
|
209
|
+
style,
|
|
210
|
+
...rest
|
|
211
|
+
},
|
|
212
|
+
forwardedRef,
|
|
213
|
+
) {
|
|
214
|
+
const t = useTranslation();
|
|
215
|
+
const [index, setIndex] = useControllableState<number>({
|
|
216
|
+
value: stepProp,
|
|
217
|
+
defaultValue: defaultStep,
|
|
218
|
+
onChange: onStepChange,
|
|
219
|
+
});
|
|
220
|
+
const current = steps[index];
|
|
221
|
+
const total = steps.length;
|
|
222
|
+
const isLast = index === total - 1;
|
|
223
|
+
|
|
224
|
+
const uid = sanitizeId(useId());
|
|
225
|
+
const titleId = `tour-title-${uid}`;
|
|
226
|
+
const bodyId = `tour-body-${uid}`;
|
|
227
|
+
const hintId = `tour-hint-${uid}`;
|
|
228
|
+
const cardRef = useRef<HTMLDivElement | null>(null);
|
|
229
|
+
const arrowRef = useRef<HTMLSpanElement | null>(null);
|
|
230
|
+
|
|
231
|
+
const { element, status } = useTourTarget(current?.target, targetTimeout, () => {
|
|
232
|
+
if (!current) return;
|
|
233
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
234
|
+
console.warn(
|
|
235
|
+
`[Tour] target "${current.target}" not found after ${targetTimeout}ms; showing step ${index + 1} centered.`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
onTargetMissing?.(current, index);
|
|
239
|
+
});
|
|
240
|
+
const found = status === 'found' ? element : null;
|
|
241
|
+
const waiting = status === 'waiting';
|
|
242
|
+
const centered = !found;
|
|
243
|
+
|
|
244
|
+
// One tick behind on purpose — see Switch's busyText for why. Mounting the
|
|
245
|
+
// region and its text together on the first `waiting` render would be
|
|
246
|
+
// silent for most screen readers; deferring to an effect makes the word
|
|
247
|
+
// always arrive as a change (Hard rule 10).
|
|
248
|
+
const [waitingText, setWaitingText] = useState('');
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
setWaitingText(waiting && !closing ? t('tour.waiting') : '');
|
|
251
|
+
}, [waiting, closing, t]);
|
|
252
|
+
|
|
253
|
+
// Guards against a consumer whose onOpenChange ignores `false` (so `closing`
|
|
254
|
+
// never flips true) — Skip then Escape must still fire onFinish only once.
|
|
255
|
+
// Reset per session: finishedRef is fresh on every TourSession mount
|
|
256
|
+
// (key={session} in Tour).
|
|
257
|
+
const finishedRef = useRef(false);
|
|
258
|
+
const finish = (reason: TourFinishReason) => {
|
|
259
|
+
if (closing || finishedRef.current) return;
|
|
260
|
+
finishedRef.current = true;
|
|
261
|
+
onOpenChange(false);
|
|
262
|
+
onFinish?.(reason);
|
|
263
|
+
};
|
|
264
|
+
const goNext = () => (isLast ? finish('completed') : setIndex(index + 1));
|
|
265
|
+
const goBack = () => {
|
|
266
|
+
if (index > 0) setIndex(index - 1);
|
|
267
|
+
};
|
|
268
|
+
// Latest-callback ref for listeners registered in effects (advanceOn, keys).
|
|
269
|
+
const goNextRef = useRef(goNext);
|
|
270
|
+
goNextRef.current = goNext;
|
|
271
|
+
|
|
272
|
+
const finishRef = useRef(finish);
|
|
273
|
+
finishRef.current = finish;
|
|
274
|
+
|
|
275
|
+
// ---- Focus ----
|
|
276
|
+
// Captured before the card takes focus (effects run in declaration order).
|
|
277
|
+
const restoreRef = useRef<HTMLElement | null>(null);
|
|
278
|
+
useLayoutEffect(() => {
|
|
279
|
+
restoreRef.current = document.activeElement as HTMLElement | null;
|
|
280
|
+
}, []);
|
|
281
|
+
|
|
282
|
+
// Focus the card on open and on every step change so the new title is
|
|
283
|
+
// announced. preventScroll: the target scroll is ours to control.
|
|
284
|
+
useLayoutEffect(() => {
|
|
285
|
+
if (closing) return;
|
|
286
|
+
queueMicrotask(() => cardRef.current?.focus({ preventScroll: true }));
|
|
287
|
+
}, [index, closing]);
|
|
288
|
+
|
|
289
|
+
// Return focus on close — unless the user has already moved it elsewhere.
|
|
290
|
+
useEffect(() => {
|
|
291
|
+
if (!closing) return;
|
|
292
|
+
const active = document.activeElement;
|
|
293
|
+
if (active && active !== document.body && !cardRef.current?.contains(active)) return;
|
|
294
|
+
const el = restoreRef.current;
|
|
295
|
+
if (el?.isConnected) el.focus({ preventScroll: true });
|
|
296
|
+
}, [closing]);
|
|
297
|
+
|
|
298
|
+
useFocusTrap(cardRef, modal && !closing, modal && current?.interactive ? found : null);
|
|
299
|
+
|
|
300
|
+
// ---- Escape = skip ----
|
|
301
|
+
// Registered as a floating surface so a host Modal yields (#274), and gated
|
|
302
|
+
// on isTopFloating so a Select/Popover opened in the card closes first (#280).
|
|
303
|
+
// Gated on `current` too: an empty/out-of-range step renders nothing (see
|
|
304
|
+
// the early return below), so it must not register as a floating surface
|
|
305
|
+
// or handle Escape.
|
|
306
|
+
const floatingId = useFloatingSurface(!closing && !!current);
|
|
307
|
+
const hasCurrent = !!current;
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
if (closing || !hasCurrent) return;
|
|
310
|
+
const onDocKeyDown = (e: KeyboardEvent) => {
|
|
311
|
+
if (e.key !== 'Escape' || !overlayStack.isTopFloating(floatingId)) return;
|
|
312
|
+
// modal={false} leaves the rest of the page usable, so Escape typed
|
|
313
|
+
// into an unrelated page control (a filter input, a form field) must
|
|
314
|
+
// not skip the tour out from under the user — only Escape while focus
|
|
315
|
+
// is actually in the card counts. Modal mode is unaffected: the page
|
|
316
|
+
// is blocked behind the scrim, so Escape always means "skip".
|
|
317
|
+
if (!modal && !cardRef.current?.contains(document.activeElement)) return;
|
|
318
|
+
e.preventDefault();
|
|
319
|
+
overlayStack.consumeEscape(e);
|
|
320
|
+
finishRef.current('skipped');
|
|
321
|
+
};
|
|
322
|
+
document.addEventListener('keydown', onDocKeyDown, true);
|
|
323
|
+
return () => document.removeEventListener('keydown', onDocKeyDown, true);
|
|
324
|
+
}, [closing, floatingId, hasCurrent, modal]);
|
|
325
|
+
|
|
326
|
+
// ---- Positioning ----
|
|
327
|
+
const side = current?.side ?? 'bottom';
|
|
328
|
+
const align = current?.align ?? 'center';
|
|
329
|
+
const placement = (align === 'center' ? side : `${side}-${align}`) as Placement;
|
|
330
|
+
const {
|
|
331
|
+
refs,
|
|
332
|
+
floatingStyles,
|
|
333
|
+
placement: resolvedPlacement,
|
|
334
|
+
middlewareData,
|
|
335
|
+
isPositioned,
|
|
336
|
+
} = useFloating({
|
|
337
|
+
open: !!found,
|
|
338
|
+
placement,
|
|
339
|
+
strategy: 'fixed',
|
|
340
|
+
// CSS `transform` stays free for the entrance scale (as in Popover).
|
|
341
|
+
transform: false,
|
|
342
|
+
middleware: [
|
|
343
|
+
offset(CARD_OFFSET),
|
|
344
|
+
flip(),
|
|
345
|
+
shift({ padding: CARD_VIEWPORT_PADDING }),
|
|
346
|
+
arrow({ element: arrowRef }),
|
|
347
|
+
],
|
|
348
|
+
whileElementsMounted: autoUpdate,
|
|
349
|
+
elements: { reference: found },
|
|
350
|
+
});
|
|
351
|
+
const resolvedSide = resolvedPlacement.split('-')[0] as TourSide;
|
|
352
|
+
const staticSide = ({ top: 'bottom', bottom: 'top', left: 'right', right: 'left' } as const)[
|
|
353
|
+
resolvedSide
|
|
354
|
+
];
|
|
355
|
+
|
|
356
|
+
// Glide (top/left/translate + spotlight geometry) only after the first
|
|
357
|
+
// placement, so nothing sweeps in from the viewport origin on open.
|
|
358
|
+
const [glide, setGlide] = useState(false);
|
|
359
|
+
useEffect(() => {
|
|
360
|
+
if (glide || !(centered || isPositioned)) return;
|
|
361
|
+
const id = requestAnimationFrame(() => setGlide(true));
|
|
362
|
+
return () => cancelAnimationFrame(id);
|
|
363
|
+
}, [glide, centered, isPositioned]);
|
|
364
|
+
|
|
365
|
+
// ---- Scroll the target into view ----
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
if (!found) return;
|
|
368
|
+
const r = found.getBoundingClientRect();
|
|
369
|
+
const inView =
|
|
370
|
+
r.top >= 0 && r.left >= 0 && r.bottom <= window.innerHeight && r.right <= window.innerWidth;
|
|
371
|
+
if (inView) return;
|
|
372
|
+
const reduce = window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches;
|
|
373
|
+
found.scrollIntoView?.({
|
|
374
|
+
block: 'center',
|
|
375
|
+
inline: 'nearest',
|
|
376
|
+
behavior: reduce ? 'auto' : 'smooth',
|
|
377
|
+
});
|
|
378
|
+
}, [found]);
|
|
379
|
+
|
|
380
|
+
// ---- advanceOn: 'click' ----
|
|
381
|
+
// Deps are the two primitives this effect actually reads, not the whole
|
|
382
|
+
// `current` object — a consumer passing `steps` as an inline array literal
|
|
383
|
+
// gives `current` a new identity every render even when its content is
|
|
384
|
+
// unchanged, which would re-attach the click listener on every unrelated
|
|
385
|
+
// re-render.
|
|
386
|
+
const advanceOn = current?.advanceOn;
|
|
387
|
+
const interactive = current?.interactive;
|
|
388
|
+
// Same condition the effect below uses to actually listen for the click —
|
|
389
|
+
// including `found`: no target (waiting / centered fallback), no listener.
|
|
390
|
+
const clickToContinue = advanceOn === 'click' && (!modal || !!interactive) && !!found;
|
|
391
|
+
// A synthetic click on a disabled control never fires, so skip activating it.
|
|
392
|
+
const advance = () =>
|
|
393
|
+
clickToContinue && current?.next !== 'skip' && found && !found.matches(':disabled')
|
|
394
|
+
? activate(found)
|
|
395
|
+
: goNext();
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
if (advanceOn !== 'click') return;
|
|
398
|
+
if (modal && !interactive) {
|
|
399
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
400
|
+
console.warn('[Tour] advanceOn="click" needs interactive: true in modal mode — ignored.');
|
|
401
|
+
}
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (!found) return;
|
|
405
|
+
// setTimeout(0), not a microtask: React's root-delegated onClick runs
|
|
406
|
+
// after this native listener, and must finish first. The timer is NOT
|
|
407
|
+
// cleared on cleanup — the click itself commonly unmounts the target
|
|
408
|
+
// (navigation), which re-runs this effect before the timer fires.
|
|
409
|
+
const onClick = () => {
|
|
410
|
+
setTimeout(() => goNextRef.current(), 0);
|
|
411
|
+
};
|
|
412
|
+
found.addEventListener('click', onClick);
|
|
413
|
+
return () => found.removeEventListener('click', onClick);
|
|
414
|
+
}, [advanceOn, interactive, found, modal]);
|
|
415
|
+
|
|
416
|
+
// ---- Interactive-target elevation ----
|
|
417
|
+
// An interactive modal step's target stays clickable through the spotlight
|
|
418
|
+
// (see useFocusTrap above) — including opening its OWN floating surface
|
|
419
|
+
// (a DropdownMenu/Select/Popover trigger that is, or contains, the target).
|
|
420
|
+
// Mark it so useInOverlay's [data-tour-active-target] host elevates that
|
|
421
|
+
// surface above the tour instead of rendering it behind the card/scrim.
|
|
422
|
+
// Gated on !closing: once the tour starts closing the target is no longer
|
|
423
|
+
// being featured (mirrors the focus trap's own `!closing` gate).
|
|
424
|
+
useEffect(() => {
|
|
425
|
+
if (!(modal && interactive && found) || closing) return;
|
|
426
|
+
found.setAttribute('data-tour-active-target', '');
|
|
427
|
+
return () => found.removeAttribute('data-tour-active-target');
|
|
428
|
+
}, [modal, interactive, found, closing]);
|
|
429
|
+
|
|
430
|
+
// ---- Inert target (#697) ----
|
|
431
|
+
// A non-interactive modal step lights its target but must not let the
|
|
432
|
+
// pointer through to it (e.g. a lifted, open menu panel). Marker + global
|
|
433
|
+
// pointer-events rule instead of the `inert` attribute, which would also
|
|
434
|
+
// hide the panel from assistive tech. Keyboard is already contained: the
|
|
435
|
+
// focus trap only extends to the target on interactive steps.
|
|
436
|
+
useEffect(() => {
|
|
437
|
+
if (!(modal && !interactive && found) || closing) return;
|
|
438
|
+
found.setAttribute('data-tour-inert', '');
|
|
439
|
+
return () => found.removeAttribute('data-tour-inert');
|
|
440
|
+
}, [modal, interactive, found, closing]);
|
|
441
|
+
|
|
442
|
+
// ---- Current-target marker (#684) ----
|
|
443
|
+
// Every step's found target (modal or not, interactive or not) — floating
|
|
444
|
+
// surfaces read it via isTourHeld so the tour pointing into an open menu
|
|
445
|
+
// doesn't dismiss that menu when the user presses Next or the card takes
|
|
446
|
+
// focus. Separate from data-tour-active-target, which drives elevation.
|
|
447
|
+
useEffect(() => {
|
|
448
|
+
if (!found || closing) return;
|
|
449
|
+
found.setAttribute(TOUR_CURRENT_TARGET, '');
|
|
450
|
+
return () => found.removeAttribute(TOUR_CURRENT_TARGET);
|
|
451
|
+
}, [found, closing]);
|
|
452
|
+
|
|
453
|
+
// ---- Exit: unmount after the fade ----
|
|
454
|
+
useEffect(() => {
|
|
455
|
+
if (!closing) return;
|
|
456
|
+
const el = cardRef.current;
|
|
457
|
+
const onEnd = (e: TransitionEvent) => {
|
|
458
|
+
if (e.target === el) onExited();
|
|
459
|
+
};
|
|
460
|
+
el?.addEventListener('transitionend', onEnd);
|
|
461
|
+
const timer = setTimeout(onExited, EXIT_FALLBACK_MS);
|
|
462
|
+
return () => {
|
|
463
|
+
el?.removeEventListener('transitionend', onEnd);
|
|
464
|
+
clearTimeout(timer);
|
|
465
|
+
};
|
|
466
|
+
}, [closing, onExited]);
|
|
467
|
+
|
|
468
|
+
const onCardKeyDown = (e: ReactKeyboardEvent<HTMLDivElement>) => {
|
|
469
|
+
onKeyDown?.(e);
|
|
470
|
+
if (e.defaultPrevented) return;
|
|
471
|
+
if (e.key !== 'ArrowRight' && e.key !== 'ArrowLeft') return;
|
|
472
|
+
if ((e.target as HTMLElement).closest(EDITABLE)) return;
|
|
473
|
+
e.preventDefault();
|
|
474
|
+
if (e.key === 'ArrowLeft') goBack();
|
|
475
|
+
else if (!isLast) advance();
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// Dev-only: an empty `steps` array or an out-of-range `step`/`defaultStep`.
|
|
479
|
+
// In an effect (not inline during render) so it fires once per bad
|
|
480
|
+
// index/total pair, not on every re-render, and stays above the early
|
|
481
|
+
// return below so hook order is stable.
|
|
482
|
+
useEffect(() => {
|
|
483
|
+
if (current) return;
|
|
484
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
485
|
+
console.warn(`[Tour] no step at index ${index} (steps: ${total}).`);
|
|
486
|
+
}
|
|
487
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- keyed on index/total only, per design; `current` is derived from both
|
|
488
|
+
}, [index, total]);
|
|
489
|
+
|
|
490
|
+
if (!current) {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const state = closing ? 'closed' : 'open';
|
|
495
|
+
// No isPositioned-gated visibility hiding — same as Popover.Content, whose
|
|
496
|
+
// floatingStyles apply directly with no flash-prevention gate.
|
|
497
|
+
const cardStyle: CSSProperties = centered
|
|
498
|
+
? { position: 'fixed', top: '50%', left: '50%', translate: '-50% -50%' }
|
|
499
|
+
: { ...floatingStyles, translate: '0 0' };
|
|
500
|
+
const arrowXY = middlewareData.arrow;
|
|
501
|
+
|
|
502
|
+
return createPortal(
|
|
503
|
+
// Single body child for ALL of Tour's portaled layers (spotlight, 4
|
|
504
|
+
// blockers, card) — Modal/Drawer's Overlay inerts every body child
|
|
505
|
+
// except ones matching their PORTAL_EXEMPT_SELECTOR, and that selector
|
|
506
|
+
// exempts by matching a body-direct child, not by descendant search.
|
|
507
|
+
// Wrapping means one `[data-tour-portal-root]` entry there exempts the
|
|
508
|
+
// whole tour, instead of Modal/Drawer inerting the card that the tour
|
|
509
|
+
// is trying to keep interactive. No class/style: children are already
|
|
510
|
+
// `position: fixed` inline, and an unstyled div creates no containing
|
|
511
|
+
// block or stacking context of its own.
|
|
512
|
+
<div data-tour-portal-root="">
|
|
513
|
+
{modal && (
|
|
514
|
+
<Spotlight
|
|
515
|
+
target={found}
|
|
516
|
+
padding={current.spotlightPadding ?? 8}
|
|
517
|
+
interactive={!!current.interactive && !!found}
|
|
518
|
+
state={state}
|
|
519
|
+
glide={glide}
|
|
520
|
+
/>
|
|
521
|
+
)}
|
|
522
|
+
{/* {...rest} first so role / aria-* / tabIndex / data-state always win. */}
|
|
523
|
+
<div
|
|
524
|
+
{...rest}
|
|
525
|
+
ref={mergeRefs<HTMLDivElement>(cardRef, refs.setFloating, forwardedRef)}
|
|
526
|
+
role="dialog"
|
|
527
|
+
aria-modal={modal}
|
|
528
|
+
aria-labelledby={titleId}
|
|
529
|
+
aria-describedby={
|
|
530
|
+
[current.body != null && bodyId, clickToContinue && hintId].filter(Boolean).join(' ') ||
|
|
531
|
+
undefined
|
|
532
|
+
}
|
|
533
|
+
tabIndex={-1}
|
|
534
|
+
data-state={state}
|
|
535
|
+
data-side={centered ? undefined : resolvedSide}
|
|
536
|
+
data-centered={centered ? '' : undefined}
|
|
537
|
+
data-waiting={waiting ? '' : undefined}
|
|
538
|
+
data-glide={glide ? '' : undefined}
|
|
539
|
+
className={clsx(styles.card, className)}
|
|
540
|
+
style={{ ...style, ...cardStyle }}
|
|
541
|
+
onKeyDown={onCardKeyDown}
|
|
542
|
+
>
|
|
543
|
+
{!centered && (
|
|
544
|
+
<span
|
|
545
|
+
ref={arrowRef}
|
|
546
|
+
aria-hidden="true"
|
|
547
|
+
className={styles.arrow}
|
|
548
|
+
style={{
|
|
549
|
+
left: typeof arrowXY?.x === 'number' ? `${arrowXY.x}px` : undefined,
|
|
550
|
+
top: typeof arrowXY?.y === 'number' ? `${arrowXY.y}px` : undefined,
|
|
551
|
+
[staticSide]: 'calc(var(--tour-arrow-size) / -2)',
|
|
552
|
+
}}
|
|
553
|
+
/>
|
|
554
|
+
)}
|
|
555
|
+
<Stack gap="md">
|
|
556
|
+
<Stack key={index} gap="xs" className={styles.content}>
|
|
557
|
+
<span className={styles.progress}>
|
|
558
|
+
{t('tour.progress', { current: index + 1, total })}
|
|
559
|
+
</span>
|
|
560
|
+
<h2 id={titleId} className={styles.title}>
|
|
561
|
+
{current.title}
|
|
562
|
+
</h2>
|
|
563
|
+
{current.body != null && (
|
|
564
|
+
<div id={bodyId} className={styles.body}>
|
|
565
|
+
{current.body}
|
|
566
|
+
</div>
|
|
567
|
+
)}
|
|
568
|
+
</Stack>
|
|
569
|
+
{clickToContinue && (
|
|
570
|
+
<span id={hintId} className={styles.hint}>
|
|
571
|
+
{t('tour.clickHint')}
|
|
572
|
+
</span>
|
|
573
|
+
)}
|
|
574
|
+
{/* Visual only: the status region below is the single announcement. */}
|
|
575
|
+
{waiting && (
|
|
576
|
+
<Cluster gap="sm" align="center" aria-hidden="true">
|
|
577
|
+
<CircularProgress size="sm" />
|
|
578
|
+
<span className={styles.waiting}>{t('tour.waiting')}</span>
|
|
579
|
+
</Cluster>
|
|
580
|
+
)}
|
|
581
|
+
<Cluster justify={isLast ? 'end' : 'between'} gap="sm">
|
|
582
|
+
{!isLast && (
|
|
583
|
+
<Button variant="ghost" size="sm" onClick={() => finish('skipped')}>
|
|
584
|
+
{t('tour.skip')}
|
|
585
|
+
</Button>
|
|
586
|
+
)}
|
|
587
|
+
<Cluster gap="sm">
|
|
588
|
+
{index > 0 && (
|
|
589
|
+
<Button variant="secondary" size="sm" onClick={goBack}>
|
|
590
|
+
{t('tour.back')}
|
|
591
|
+
</Button>
|
|
592
|
+
)}
|
|
593
|
+
{/* Secondary on click-to-continue steps: the target is the primary action. */}
|
|
594
|
+
<Button
|
|
595
|
+
variant={clickToContinue ? 'secondary' : undefined}
|
|
596
|
+
size="sm"
|
|
597
|
+
// The advanceOn listener on the target advances; Next only clicks it.
|
|
598
|
+
onClick={advance}
|
|
599
|
+
>
|
|
600
|
+
{isLast ? doneLabel || t('tour.done') : t('tour.next')}
|
|
601
|
+
</Button>
|
|
602
|
+
</Cluster>
|
|
603
|
+
</Cluster>
|
|
604
|
+
</Stack>
|
|
605
|
+
{/* INSIDE the dialog on purpose — VoiceOver prunes content outside an
|
|
606
|
+
aria-modal dialog, so a region outside this div is never reached.
|
|
607
|
+
The dialog's name comes from aria-labelledby, so a plain child
|
|
608
|
+
span can't join it. Rendered unconditionally so only its text
|
|
609
|
+
mutates; same recipe as Switch's srOnly span otherwise. */}
|
|
610
|
+
<span role="status" aria-live="polite" className={styles.srOnly}>
|
|
611
|
+
{waitingText}
|
|
612
|
+
</span>
|
|
613
|
+
</div>
|
|
614
|
+
</div>,
|
|
615
|
+
document.body,
|
|
616
|
+
);
|
|
617
|
+
});
|