@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,69 @@
|
|
|
1
|
+
@use '../../styles/mixins' as *;
|
|
2
|
+
@use './OtpInput.tokens';
|
|
3
|
+
|
|
4
|
+
.root {
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
flex-wrap: wrap;
|
|
7
|
+
gap: var(--otp-input-gap);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.cell {
|
|
11
|
+
padding: 0;
|
|
12
|
+
border: var(--border-width) solid var(--otp-input-border-color);
|
|
13
|
+
border-radius: var(--otp-input-radius);
|
|
14
|
+
background: var(--otp-input-bg);
|
|
15
|
+
color: var(--otp-input-fg);
|
|
16
|
+
font-family: inherit;
|
|
17
|
+
font-variant-numeric: tabular-nums;
|
|
18
|
+
text-align: center;
|
|
19
|
+
transition:
|
|
20
|
+
border-color var(--transition-fast),
|
|
21
|
+
outline-color var(--transition-fast);
|
|
22
|
+
|
|
23
|
+
&:focus-visible {
|
|
24
|
+
border-color: var(--otp-input-border-color-focus);
|
|
25
|
+
|
|
26
|
+
@include focus-ring(var(--otp-input-ring-focus));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:disabled {
|
|
30
|
+
background: var(--otp-input-bg-disabled);
|
|
31
|
+
border-color: var(--otp-input-border-color-disabled);
|
|
32
|
+
color: var(--otp-input-fg-disabled);
|
|
33
|
+
cursor: not-allowed;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.size-sm {
|
|
38
|
+
width: var(--otp-input-cell-size-sm);
|
|
39
|
+
height: var(--otp-input-cell-size-sm);
|
|
40
|
+
font-size: var(--otp-input-font-size-sm);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.size-md {
|
|
44
|
+
width: var(--otp-input-cell-size-md);
|
|
45
|
+
height: var(--otp-input-cell-size-md);
|
|
46
|
+
font-size: var(--otp-input-font-size-md);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.size-lg {
|
|
50
|
+
width: var(--otp-input-cell-size-lg);
|
|
51
|
+
height: var(--otp-input-cell-size-lg);
|
|
52
|
+
font-size: var(--otp-input-font-size-lg);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.size-xl {
|
|
56
|
+
width: var(--otp-input-cell-size-xl);
|
|
57
|
+
height: var(--otp-input-cell-size-xl);
|
|
58
|
+
font-size: var(--otp-input-font-size-xl);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.invalid {
|
|
62
|
+
border-color: var(--otp-input-border-color-invalid);
|
|
63
|
+
|
|
64
|
+
&:focus-visible {
|
|
65
|
+
border-color: var(--otp-input-border-color-invalid);
|
|
66
|
+
|
|
67
|
+
@include focus-ring(var(--otp-input-ring-invalid));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// OtpInput.tokens.scss — component-scoped tokens for <OtpInput>. Every value
|
|
2
|
+
// aliases the <Input> family or a primitive, so a code field sits flush with a
|
|
3
|
+
// same-size Input or Button without visual drift.
|
|
4
|
+
@use '../Input/Input.tokens';
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
// Group
|
|
8
|
+
--otp-input-gap: var(--space-2);
|
|
9
|
+
|
|
10
|
+
// Cell surface
|
|
11
|
+
--otp-input-bg: var(--input-bg);
|
|
12
|
+
--otp-input-fg: var(--input-fg);
|
|
13
|
+
--otp-input-border-color: var(--input-border-color);
|
|
14
|
+
--otp-input-radius: var(--input-radius);
|
|
15
|
+
|
|
16
|
+
// Focus
|
|
17
|
+
--otp-input-border-color-focus: var(--input-border-color-focus);
|
|
18
|
+
--otp-input-ring-focus: var(--input-ring-focus);
|
|
19
|
+
|
|
20
|
+
// Disabled
|
|
21
|
+
--otp-input-bg-disabled: var(--input-bg-disabled);
|
|
22
|
+
--otp-input-border-color-disabled: var(--input-border-color-disabled);
|
|
23
|
+
--otp-input-fg-disabled: var(--input-fg-disabled);
|
|
24
|
+
|
|
25
|
+
// Invalid
|
|
26
|
+
--otp-input-border-color-invalid: var(--input-border-color-invalid);
|
|
27
|
+
--otp-input-ring-invalid: var(--input-ring-invalid);
|
|
28
|
+
|
|
29
|
+
// Size — square cell, matching the <Input> height scale so an OtpInput
|
|
30
|
+
// lines up with the fields around it.
|
|
31
|
+
--otp-input-cell-size-sm: var(--size-sm);
|
|
32
|
+
--otp-input-cell-size-md: var(--size-md);
|
|
33
|
+
--otp-input-cell-size-lg: var(--size-lg);
|
|
34
|
+
|
|
35
|
+
// No <Input> step this big: --size-xl (80px) would overflow a phone at six
|
|
36
|
+
// cells, so xl has its own 48px primitive.
|
|
37
|
+
--otp-input-cell-size-xl: var(--size-otp-cell-xl);
|
|
38
|
+
|
|
39
|
+
// Size — a code is read back character by character, so the glyph runs one
|
|
40
|
+
// step larger than the equivalent <Input>.
|
|
41
|
+
--otp-input-font-size-sm: var(--font-size-md);
|
|
42
|
+
--otp-input-font-size-md: var(--font-size-lg);
|
|
43
|
+
--otp-input-font-size-lg: var(--font-size-xl);
|
|
44
|
+
--otp-input-font-size-xl: var(--font-size-2xl);
|
|
45
|
+
}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useLayoutEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
type ChangeEvent,
|
|
8
|
+
type FocusEvent as ReactFocusEvent,
|
|
9
|
+
type HTMLAttributes,
|
|
10
|
+
type KeyboardEvent as ReactKeyboardEvent,
|
|
11
|
+
type MouseEvent as ReactMouseEvent,
|
|
12
|
+
} from 'react';
|
|
13
|
+
import clsx from 'clsx';
|
|
14
|
+
import { useControllableState } from '../_internal/useControllableState';
|
|
15
|
+
import { useTranslation } from '../../i18n';
|
|
16
|
+
import styles from './OtpInput.module.scss';
|
|
17
|
+
|
|
18
|
+
/** Cell height. Matches the `<Input>` / `<Button>` size scale. */
|
|
19
|
+
export type OtpInputSize = 'sm' | 'md' | 'lg' | 'xl';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Which characters the code is made of.
|
|
23
|
+
* - `'numeric'` — digits only (default). What SMS and email one-time codes
|
|
24
|
+
* almost always are, and what the numeric mobile keypad is for.
|
|
25
|
+
* - `'alphanumeric'` — digits plus Latin letters, normalized to uppercase.
|
|
26
|
+
*/
|
|
27
|
+
export type OtpInputType = 'numeric' | 'alphanumeric';
|
|
28
|
+
|
|
29
|
+
const SANITIZE: Record<OtpInputType, (raw: string) => string> = {
|
|
30
|
+
numeric: (raw) => raw.replace(/[^0-9]/g, ''),
|
|
31
|
+
alphanumeric: (raw) => raw.replace(/[^0-9a-z]/gi, '').toUpperCase(),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Props for {@link OtpInput}. Extends `HTMLAttributes<HTMLDivElement>` (minus
|
|
36
|
+
* `onChange` and `defaultValue`, which are redeclared below with
|
|
37
|
+
* component-specific signatures) since the group `<div>` is the element a
|
|
38
|
+
* consumer ultimately controls.
|
|
39
|
+
*/
|
|
40
|
+
export interface OtpInputProps extends Omit<
|
|
41
|
+
HTMLAttributes<HTMLDivElement>,
|
|
42
|
+
'onChange' | 'defaultValue'
|
|
43
|
+
> {
|
|
44
|
+
/** How many boxes to render. Default `6`. */
|
|
45
|
+
length?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Controlled code. Sanitized and truncated to `length` on render, so a
|
|
48
|
+
* consumer echoing back a dirty string sees it cleaned rather than
|
|
49
|
+
* mis-sliced. Pair with `onChange`.
|
|
50
|
+
*/
|
|
51
|
+
value?: string;
|
|
52
|
+
/** Uncontrolled seed. Ignored when `value` is supplied. */
|
|
53
|
+
defaultValue?: string;
|
|
54
|
+
/**
|
|
55
|
+
* Fires on every edit with the whole code so far — always sanitized, never
|
|
56
|
+
* longer than `length`, and never with a gap in the middle.
|
|
57
|
+
*/
|
|
58
|
+
onChange?: (value: string) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Fires whenever the code becomes full with a value different from the
|
|
61
|
+
* last one — not on every keystroke while it is full. Use it to submit.
|
|
62
|
+
* Correcting a wrong character inside an already-full code re-fires with
|
|
63
|
+
* the corrected value; retyping the same character does not, since
|
|
64
|
+
* nothing changed.
|
|
65
|
+
*/
|
|
66
|
+
onComplete?: (value: string) => void;
|
|
67
|
+
/** Character set. Default `'numeric'`. See `OtpInputType`. */
|
|
68
|
+
type?: OtpInputType;
|
|
69
|
+
/**
|
|
70
|
+
* Cell size. Default `'md'`.
|
|
71
|
+
* - `'sm'` — 24px cells; dense admin screens.
|
|
72
|
+
* - `'md'` — 32px cells (default); most forms.
|
|
73
|
+
* - `'lg'` — 40px cells; a dedicated verification screen.
|
|
74
|
+
* - `'xl'` — 48px cells; a code field that IS the screen (IdP login
|
|
75
|
+
* challenge, touch-first). Six cells still fit a 360px phone. No
|
|
76
|
+
* `<Input>` counterpart at this height — don't line it up with fields.
|
|
77
|
+
*/
|
|
78
|
+
size?: OtpInputSize;
|
|
79
|
+
/**
|
|
80
|
+
* Error visual on every cell plus `aria-invalid="true"`. Pair with a visible
|
|
81
|
+
* message and point `aria-describedby` at it (or wrap in `<Field error>`).
|
|
82
|
+
*/
|
|
83
|
+
invalid?: boolean;
|
|
84
|
+
/** Disable every cell. */
|
|
85
|
+
disabled?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Marks the field required. There is no single native input to attach the
|
|
88
|
+
* native `required` attribute to — a per-cell `required` would let the
|
|
89
|
+
* browser block submit on an empty first cell while accepting a
|
|
90
|
+
* 1-of-`length` code as complete, which is worse than no native gate at
|
|
91
|
+
* all. Sets `aria-required="true"` on every cell instead (the group's
|
|
92
|
+
* `role="group"` does not support `aria-required` per ARIA 1.2 — only
|
|
93
|
+
* `textbox` and a handful of other roles do), the same way `aria-invalid`
|
|
94
|
+
* and `aria-describedby` are already repeated on every cell. Validating
|
|
95
|
+
* completeness is the consumer's job (pair with `invalid` + `onComplete`).
|
|
96
|
+
*/
|
|
97
|
+
required?: boolean;
|
|
98
|
+
/** Focus the first cell on mount. */
|
|
99
|
+
autoFocus?: boolean;
|
|
100
|
+
/** Id for the first cell, so an external `<label htmlFor>` focuses the field. */
|
|
101
|
+
id?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Accessible name for the group. Defaults to the localized
|
|
104
|
+
* `otpInput.groupLabel` ("Verification code") when omitted OR empty — an
|
|
105
|
+
* empty string is not an explicit name — so a standalone OtpInput is never
|
|
106
|
+
* an unnamed group.
|
|
107
|
+
*/
|
|
108
|
+
'aria-label'?: string;
|
|
109
|
+
/** Ids of elements naming the group. Injected by `<Field>`; wins over `aria-label`. */
|
|
110
|
+
'aria-labelledby'?: string;
|
|
111
|
+
/** Ids of description / error elements. Set on EVERY cell — see the remarks. */
|
|
112
|
+
'aria-describedby'?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* One-time-code field: `length` single-character boxes behaving as one control, with `autocomplete="one-time-code"` and auto-advance.
|
|
117
|
+
* @see docs/components/OtpInput.md
|
|
118
|
+
*/
|
|
119
|
+
export const OtpInput = forwardRef<HTMLDivElement, OtpInputProps>(function OtpInput(
|
|
120
|
+
{
|
|
121
|
+
length = 6,
|
|
122
|
+
value,
|
|
123
|
+
defaultValue,
|
|
124
|
+
onChange,
|
|
125
|
+
onComplete,
|
|
126
|
+
type = 'numeric',
|
|
127
|
+
size = 'md',
|
|
128
|
+
invalid,
|
|
129
|
+
disabled,
|
|
130
|
+
required,
|
|
131
|
+
autoFocus,
|
|
132
|
+
id,
|
|
133
|
+
'aria-label': ariaLabel,
|
|
134
|
+
'aria-labelledby': ariaLabelledby,
|
|
135
|
+
'aria-describedby': ariaDescribedby,
|
|
136
|
+
className,
|
|
137
|
+
...rest
|
|
138
|
+
},
|
|
139
|
+
ref,
|
|
140
|
+
) {
|
|
141
|
+
const t = useTranslation();
|
|
142
|
+
const sanitize = SANITIZE[type];
|
|
143
|
+
|
|
144
|
+
const [rawValue, setRawValue] = useControllableState<string>({
|
|
145
|
+
value,
|
|
146
|
+
defaultValue: defaultValue ?? '',
|
|
147
|
+
onChange,
|
|
148
|
+
});
|
|
149
|
+
const code = sanitize(rawValue ?? '').slice(0, length);
|
|
150
|
+
|
|
151
|
+
// The code is always contiguous, so the only reachable cells are the filled
|
|
152
|
+
// ones plus the first empty one.
|
|
153
|
+
const lastReachable = Math.min(code.length, length - 1);
|
|
154
|
+
|
|
155
|
+
const cellsRef = useRef<(HTMLInputElement | null)[]>([]);
|
|
156
|
+
const [focusedIndex, setFocusedIndex] = useState<number | null>(null);
|
|
157
|
+
// Standard roving tabindex: the group remembers where focus left it.
|
|
158
|
+
const activeIndex = Math.min(focusedIndex ?? lastReachable, lastReachable);
|
|
159
|
+
|
|
160
|
+
// The select() calls in focusCell/onClick/handleFocus run BEFORE the
|
|
161
|
+
// commit they're reacting to has rendered. That's durable only when React's
|
|
162
|
+
// controlled-input diff then skips writing `node.value` — true when the
|
|
163
|
+
// sanitized commit equals the raw keystroke, but false the moment
|
|
164
|
+
// sanitizing actually transforms the character (alphanumeric mode
|
|
165
|
+
// uppercasing a lowercase letter, for instance): React DOES write
|
|
166
|
+
// node.value on that render and collapses whatever was selected before it,
|
|
167
|
+
// so a second overtype keystroke right behind the first gets appended
|
|
168
|
+
// instead of replacing, and is silently sliced back off. Re-select after
|
|
169
|
+
// every commit, once React has actually written the DOM, so the selection
|
|
170
|
+
// this render leaves behind is the one the NEXT keystroke will see —
|
|
171
|
+
// regardless of whether sanitizing changed anything. A no-op on an empty
|
|
172
|
+
// cell, and skipped entirely when focus isn't on the active cell (Tab,
|
|
173
|
+
// Arrow, Home/End, and click already select correctly on their own).
|
|
174
|
+
useLayoutEffect(() => {
|
|
175
|
+
const cell = cellsRef.current[activeIndex];
|
|
176
|
+
if (cell && document.activeElement === cell) cell.select();
|
|
177
|
+
}, [code, activeIndex]);
|
|
178
|
+
|
|
179
|
+
const focusCell = useCallback((index: number) => {
|
|
180
|
+
const cell = cellsRef.current[index];
|
|
181
|
+
// `focus()` on an already-focused cell fires no focus event, so
|
|
182
|
+
// `handleFocus`'s select() below never runs — select here too, so
|
|
183
|
+
// overtyping the cell the user is already sitting in (fixing the last
|
|
184
|
+
// digit typed) replaces it instead of silently appending and truncating
|
|
185
|
+
// back to the same value.
|
|
186
|
+
cell?.focus();
|
|
187
|
+
cell?.select();
|
|
188
|
+
}, []);
|
|
189
|
+
|
|
190
|
+
const commit = useCallback(
|
|
191
|
+
(next: string) => {
|
|
192
|
+
setRawValue(next);
|
|
193
|
+
// Fire on any transition INTO a full-and-different code, not just the
|
|
194
|
+
// empty→full one: a corrected digit inside an already-full code (mistype,
|
|
195
|
+
// then fix the last character) is a real completion the consumer must
|
|
196
|
+
// hear about. Guarding on the value rather than just the length also
|
|
197
|
+
// means a same-value overtype (retyping the digit already there) does
|
|
198
|
+
// NOT re-fire — nothing about the code actually changed.
|
|
199
|
+
if (next.length === length && next !== code) onComplete?.(next);
|
|
200
|
+
},
|
|
201
|
+
[setRawValue, length, code, onComplete],
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const handleChange = (rawIndex: number) => (event: ChangeEvent<HTMLInputElement>) => {
|
|
205
|
+
// A controlled `value` can shrink out from under a focused cell — the
|
|
206
|
+
// standard "clear the code after a failed check" reset — leaving DOM
|
|
207
|
+
// focus on a cell past the contiguous range while `lastReachable` has
|
|
208
|
+
// already moved. At an out-of-range rawIndex this clamp doesn't change
|
|
209
|
+
// what the splice below commits: `code.slice(0, rawIndex) === code`
|
|
210
|
+
// (slicing past the end returns the whole string) AND the tail slice
|
|
211
|
+
// `code.slice(rawIndex + chars.length)` is also `''`, so the splice
|
|
212
|
+
// computes the same value whether or not the index is clamped. The
|
|
213
|
+
// clamp's only observable effect is the `focusCell` target a few lines
|
|
214
|
+
// down, which is what pulls focus back into range.
|
|
215
|
+
const index = Math.min(rawIndex, code.length);
|
|
216
|
+
const chars = sanitize(event.target.value);
|
|
217
|
+
if (chars.length === 0) {
|
|
218
|
+
// "Sanitizes to empty" also happens when the sanitizer REJECTS a
|
|
219
|
+
// character (a letter in numeric mode) typed over a filled, selected
|
|
220
|
+
// cell — that must be a no-op, not a truncation. Only a genuinely
|
|
221
|
+
// emptied cell (raw value itself is '') truncates the code from here
|
|
222
|
+
// on, so `value` stays a contiguous string that maps 1:1 onto the
|
|
223
|
+
// cells. React restores the cell's committed character on its own.
|
|
224
|
+
if (event.target.value === '') commit(code.slice(0, index));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// A delivery of exactly `length` characters IS the whole code — the
|
|
228
|
+
// platform dumps it into whichever cell happens to be focused, not
|
|
229
|
+
// necessarily the first — so it replaces the value outright rather than
|
|
230
|
+
// splicing in at that position, which would scatter it across two spots.
|
|
231
|
+
// A shorter (or over-long, uncommon) delivery keeps the splice-and-slice
|
|
232
|
+
// behavior, unchanged.
|
|
233
|
+
const next =
|
|
234
|
+
chars.length === length
|
|
235
|
+
? chars
|
|
236
|
+
: (code.slice(0, index) + chars + code.slice(index + chars.length)).slice(0, length);
|
|
237
|
+
commit(next);
|
|
238
|
+
focusCell(Math.min(index + chars.length, length - 1));
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const handleKeyDown = (rawIndex: number) => (event: ReactKeyboardEvent<HTMLInputElement>) => {
|
|
242
|
+
// Same stranding as handleChange's clamp: a controlled `value` shrink can
|
|
243
|
+
// leave DOM focus past the code's contiguous end. Unlike that clamp, which
|
|
244
|
+
// only ever redirects focus (see its comment), this one changes what gets
|
|
245
|
+
// committed. Backspace is the only case that reads `code`, and at an
|
|
246
|
+
// out-of-range index `code.slice(0, index - 1)` returns the whole string
|
|
247
|
+
// (`'1'.slice(0, 4) === '1'`), so the commit is a no-op and Backspace
|
|
248
|
+
// silently deletes nothing. Backspace and ArrowLeft are also the only
|
|
249
|
+
// cases that step focus from this index — Home and End ignore it, and
|
|
250
|
+
// ArrowRight is already bounded by lastReachable.
|
|
251
|
+
const index = Math.min(rawIndex, code.length);
|
|
252
|
+
switch (event.key) {
|
|
253
|
+
case 'Backspace':
|
|
254
|
+
// A filled cell is handled natively: focus selected its content, so
|
|
255
|
+
// Backspace deletes it and fires `change`. An empty cell has nothing
|
|
256
|
+
// to delete, so step back and clear the previous one instead.
|
|
257
|
+
if (!code[index] && index > 0) {
|
|
258
|
+
event.preventDefault();
|
|
259
|
+
commit(code.slice(0, index - 1));
|
|
260
|
+
focusCell(index - 1);
|
|
261
|
+
}
|
|
262
|
+
break;
|
|
263
|
+
case 'ArrowLeft':
|
|
264
|
+
event.preventDefault();
|
|
265
|
+
focusCell(Math.max(0, index - 1));
|
|
266
|
+
break;
|
|
267
|
+
case 'ArrowRight':
|
|
268
|
+
event.preventDefault();
|
|
269
|
+
focusCell(Math.min(lastReachable, index + 1));
|
|
270
|
+
break;
|
|
271
|
+
case 'Home':
|
|
272
|
+
event.preventDefault();
|
|
273
|
+
focusCell(0);
|
|
274
|
+
break;
|
|
275
|
+
case 'End':
|
|
276
|
+
event.preventDefault();
|
|
277
|
+
focusCell(lastReachable);
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
// A keystroke that reproduces the character already in the cell
|
|
281
|
+
// leaves the DOM value byte-identical, so React's value tracker
|
|
282
|
+
// fires no change event at all — `handleChange` never runs, nothing
|
|
283
|
+
// re-selects, and the caret is left collapsed. Every keystroke after
|
|
284
|
+
// that would then append instead of replace and get sliced back off
|
|
285
|
+
// by the length cap, bricking the cell. Select on the keystroke
|
|
286
|
+
// itself so the next character always lands on a selected cell
|
|
287
|
+
// regardless of whether this one produced a change event.
|
|
288
|
+
if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
289
|
+
event.currentTarget.select();
|
|
290
|
+
}
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// Clicking a cell beyond the first empty one would otherwise drop the
|
|
296
|
+
// character somewhere other than where it was aimed, because the code is
|
|
297
|
+
// contiguous. Redirect on mousedown, where `code` is still the rendered
|
|
298
|
+
// value — doing it in `onFocus` would race our own programmatic focus.
|
|
299
|
+
const handleMouseDown = (index: number) => (event: ReactMouseEvent<HTMLInputElement>) => {
|
|
300
|
+
if (index > lastReachable) {
|
|
301
|
+
event.preventDefault();
|
|
302
|
+
focusCell(lastReachable);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const handleFocus = (index: number) => (event: ReactFocusEvent<HTMLInputElement>) => {
|
|
307
|
+
setFocusedIndex(index);
|
|
308
|
+
// Select-on-focus is what makes typing into a filled cell a replacement
|
|
309
|
+
// rather than an append, so a multi-character `change` can only mean a
|
|
310
|
+
// paste or an autofill.
|
|
311
|
+
event.target.select();
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// Re-clicking a cell that already has focus moves the caret but fires no
|
|
315
|
+
// focus event, so it needs its own select — same reasoning as `focusCell`.
|
|
316
|
+
// Only when it really has focus: Chromium's select() also FOCUSES, so on a
|
|
317
|
+
// click that `handleMouseDown` redirected it would pull focus back to the
|
|
318
|
+
// clicked cell and undo the redirect (#597).
|
|
319
|
+
const handleClick = (event: ReactMouseEvent<HTMLInputElement>) => {
|
|
320
|
+
if (document.activeElement === event.currentTarget) event.currentTarget.select();
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const cellLabel = type === 'numeric' ? 'otpInput.digit' : 'otpInput.character';
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<div
|
|
327
|
+
// {...rest} first so the structural ARIA contract — role=group and the
|
|
328
|
+
// resolved group name — cannot be clobbered by a consumer.
|
|
329
|
+
{...rest}
|
|
330
|
+
ref={ref}
|
|
331
|
+
role="group"
|
|
332
|
+
aria-label={ariaLabelledby ? undefined : ariaLabel || t('otpInput.groupLabel')}
|
|
333
|
+
aria-labelledby={ariaLabelledby}
|
|
334
|
+
className={clsx(styles.root, className)}
|
|
335
|
+
>
|
|
336
|
+
{Array.from({ length }, (_unused, index) => (
|
|
337
|
+
<input
|
|
338
|
+
key={index}
|
|
339
|
+
ref={(node) => {
|
|
340
|
+
cellsRef.current[index] = node;
|
|
341
|
+
}}
|
|
342
|
+
type="text"
|
|
343
|
+
value={code[index] ?? ''}
|
|
344
|
+
onChange={handleChange(index)}
|
|
345
|
+
onKeyDown={handleKeyDown(index)}
|
|
346
|
+
onMouseDown={handleMouseDown(index)}
|
|
347
|
+
onFocus={handleFocus(index)}
|
|
348
|
+
onClick={handleClick}
|
|
349
|
+
id={index === 0 ? id : undefined}
|
|
350
|
+
autoFocus={autoFocus && index === 0}
|
|
351
|
+
disabled={disabled}
|
|
352
|
+
tabIndex={index === activeIndex ? 0 : -1}
|
|
353
|
+
inputMode={type === 'numeric' ? 'numeric' : 'text'}
|
|
354
|
+
pattern={type === 'numeric' ? '[0-9]*' : undefined}
|
|
355
|
+
autoComplete="one-time-code"
|
|
356
|
+
autoCorrect="off"
|
|
357
|
+
autoCapitalize="off"
|
|
358
|
+
spellCheck={false}
|
|
359
|
+
aria-label={t(cellLabel, { index: index + 1, total: length })}
|
|
360
|
+
aria-invalid={invalid || undefined}
|
|
361
|
+
aria-required={required || undefined}
|
|
362
|
+
aria-describedby={ariaDescribedby}
|
|
363
|
+
className={clsx(styles.cell, styles[`size-${size}`], invalid && styles.invalid)}
|
|
364
|
+
/>
|
|
365
|
+
))}
|
|
366
|
+
</div>
|
|
367
|
+
);
|
|
368
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
@use './Page.tokens';
|
|
2
|
+
|
|
3
|
+
.root {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.gapXs {
|
|
9
|
+
gap: var(--page-gap-xs);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.gapSm {
|
|
13
|
+
gap: var(--page-gap-sm);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.gapMd {
|
|
17
|
+
gap: var(--page-gap-md);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.gapLg {
|
|
21
|
+
gap: var(--page-gap-lg);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.gapXl {
|
|
25
|
+
gap: var(--page-gap-xl);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.gap2xl {
|
|
29
|
+
gap: var(--page-gap-2xl);
|
|
30
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Page.tokens.scss — Component-scoped tokens for <Page>. Each token
|
|
2
|
+
// defaults to the primitive the SCSS used before this migration.
|
|
3
|
+
:root {
|
|
4
|
+
// Gap per size variant (vertical rhythm between page sections)
|
|
5
|
+
--page-gap-xs: var(--space-1);
|
|
6
|
+
--page-gap-sm: var(--space-2);
|
|
7
|
+
--page-gap-md: var(--space-3);
|
|
8
|
+
--page-gap-lg: var(--space-4);
|
|
9
|
+
--page-gap-xl: var(--space-6);
|
|
10
|
+
--page-gap-2xl: var(--space-8);
|
|
11
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import { type StackGap } from '../Stack';
|
|
4
|
+
import styles from './Page.module.scss';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Gap union for `<Page>`. Reuses `StackGap` so the scale stays
|
|
8
|
+
* synchronized across layout primitives — when Stack gains a size,
|
|
9
|
+
* Page gains it automatically.
|
|
10
|
+
*/
|
|
11
|
+
export type PageGap = StackGap;
|
|
12
|
+
|
|
13
|
+
export interface PageProps extends HTMLAttributes<HTMLDivElement> {
|
|
14
|
+
/**
|
|
15
|
+
* Vertical rhythm between top-level page sections.
|
|
16
|
+
* - `xs` (4) / `sm` (8) / `md` (12) — tighter than canonical; rare.
|
|
17
|
+
* - `lg` (16, **default**) — the canonical CRM page rhythm; matches
|
|
18
|
+
* every shipped mockup.
|
|
19
|
+
* - `xl` (24) / `2xl` (32) — looser; for spacious overview / hero pages.
|
|
20
|
+
*/
|
|
21
|
+
gap?: PageGap;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const gapClass: Record<PageGap, string> = {
|
|
26
|
+
xs: styles.gapXs,
|
|
27
|
+
sm: styles.gapSm,
|
|
28
|
+
md: styles.gapMd,
|
|
29
|
+
lg: styles.gapLg,
|
|
30
|
+
xl: styles.gapXl,
|
|
31
|
+
'2xl': styles.gap2xl,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Page-root layout primitive: a thin Stack with the canonical `gap="lg"` rhythm between top-level sections.
|
|
36
|
+
* @see docs/components/Page.md
|
|
37
|
+
*/
|
|
38
|
+
export const Page = forwardRef<HTMLDivElement, PageProps>(function Page(
|
|
39
|
+
{ gap = 'lg', className, children, ...rest },
|
|
40
|
+
ref,
|
|
41
|
+
) {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
ref={ref}
|
|
45
|
+
className={clsx(styles.root, gapClass[gap], className)}
|
|
46
|
+
// {...rest} last so consumer overrides win (Pattern A — Page has no
|
|
47
|
+
// locked-in attributes; even data-* and aria-* can be overridden).
|
|
48
|
+
{...rest}
|
|
49
|
+
>
|
|
50
|
+
{children}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
});
|