@eocrm/design-system 0.0.0-stage → 0.6.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI-PRIMER.md +341 -0
- package/README.md +262 -2
- package/docs/components/Accordion.md +114 -0
- package/docs/components/AgentAvatar.md +58 -0
- package/docs/components/Alert.md +81 -0
- package/docs/components/AppLayout.md +70 -0
- package/docs/components/Avatar.md +49 -0
- package/docs/components/AvatarGroup.md +47 -0
- package/docs/components/Badge.md +60 -0
- package/docs/components/Banner.md +89 -0
- package/docs/components/BrandIcon.md +32 -0
- package/docs/components/Breadcrumb.md +72 -0
- package/docs/components/Button.md +107 -0
- package/docs/components/ButtonGroup.md +78 -0
- package/docs/components/Calendar.md +158 -0
- package/docs/components/Card.md +165 -0
- package/docs/components/CatalogPicker.md +83 -0
- package/docs/components/Chart.md +114 -0
- package/docs/components/ChatBubble.md +55 -0
- package/docs/components/ChatLauncher.md +97 -0
- package/docs/components/Checkbox.md +55 -0
- package/docs/components/CircularProgress.md +53 -0
- package/docs/components/Cluster.md +96 -0
- package/docs/components/Code.md +35 -0
- package/docs/components/CodeBlock.md +67 -0
- package/docs/components/ColorPicker.md +115 -0
- package/docs/components/ConfirmationPopover.md +70 -0
- package/docs/components/Constrain.md +39 -0
- package/docs/components/CurrencySelect.md +57 -0
- package/docs/components/CursorPagination.md +43 -0
- package/docs/components/DashboardCanvas.md +79 -0
- package/docs/components/DashboardWidget.md +131 -0
- package/docs/components/DataTable.md +88 -0
- package/docs/components/DatePicker.md +68 -0
- package/docs/components/DateRangePicker.md +71 -0
- package/docs/components/DateStrip.md +56 -0
- package/docs/components/DefinitionList.md +82 -0
- package/docs/components/Divider.md +57 -0
- package/docs/components/Dot.md +26 -0
- package/docs/components/Drawer.md +94 -0
- package/docs/components/DropdownMenu.md +299 -0
- package/docs/components/EmojiPicker.md +84 -0
- package/docs/components/EmptyState.md +55 -0
- package/docs/components/EntityChip.md +102 -0
- package/docs/components/ErrorState.md +72 -0
- package/docs/components/Field.md +91 -0
- package/docs/components/FileUpload.md +109 -0
- package/docs/components/FilterChip.md +88 -0
- package/docs/components/FlowCanvas.md +108 -0
- package/docs/components/FormRow.md +31 -0
- package/docs/components/FormSection.md +37 -0
- package/docs/components/Grid.md +103 -0
- package/docs/components/Highlight.md +75 -0
- package/docs/components/HighlightedText.md +50 -0
- package/docs/components/IconPicker.md +134 -0
- package/docs/components/IconTile.md +30 -0
- package/docs/components/Image.md +84 -0
- package/docs/components/ImageCrop.md +163 -0
- package/docs/components/Indent.md +31 -0
- package/docs/components/InlineDatePicker.md +58 -0
- package/docs/components/InlineDateRangePicker.md +57 -0
- package/docs/components/Input.md +54 -0
- package/docs/components/Kanban.md +122 -0
- package/docs/components/Kbd.md +41 -0
- package/docs/components/Lightbox.md +105 -0
- package/docs/components/Link.md +65 -0
- package/docs/components/LinkCard.md +41 -0
- package/docs/components/LiquidEditor.md +84 -0
- package/docs/components/List.md +68 -0
- package/docs/components/LiveRegion.md +29 -0
- package/docs/components/LocaleProvider.md +25 -0
- package/docs/components/Logo.md +41 -0
- package/docs/components/Masonry.md +48 -0
- package/docs/components/MediaTile.md +95 -0
- package/docs/components/Modal.md +107 -0
- package/docs/components/MoneyInput.md +62 -0
- package/docs/components/OptionsPicker.md +123 -0
- package/docs/components/OtpInput.md +65 -0
- package/docs/components/Page.md +35 -0
- package/docs/components/PageHeader.md +133 -0
- package/docs/components/Pagination.md +44 -0
- package/docs/components/Palette.md +32 -0
- package/docs/components/PasswordInput.md +45 -0
- package/docs/components/PasswordStrengthMeter.md +27 -0
- package/docs/components/PersonDisplay.md +153 -0
- package/docs/components/PhoneInput.md +54 -0
- package/docs/components/PillMenu.md +91 -0
- package/docs/components/Popover.md +127 -0
- package/docs/components/Progress.md +56 -0
- package/docs/components/QrCode.md +34 -0
- package/docs/components/Radio.md +37 -0
- package/docs/components/RadioGroup.md +56 -0
- package/docs/components/Rail.md +191 -0
- package/docs/components/RelativeDateInput.md +114 -0
- package/docs/components/RichText.md +44 -0
- package/docs/components/RichTextEditor.md +112 -0
- package/docs/components/Screen.md +37 -0
- package/docs/components/ScrollArea.md +39 -0
- package/docs/components/Select.md +131 -0
- package/docs/components/SettingRow.md +98 -0
- package/docs/components/Skeleton.md +68 -0
- package/docs/components/Slider.md +92 -0
- package/docs/components/SlotGrid.md +55 -0
- package/docs/components/SocialButton.md +31 -0
- package/docs/components/Sortable.md +127 -0
- package/docs/components/SortableGroup.md +52 -0
- package/docs/components/Sparkline.md +51 -0
- package/docs/components/Split.md +76 -0
- package/docs/components/Stack.md +59 -0
- package/docs/components/StagePath.md +66 -0
- package/docs/components/StatGroup.md +61 -0
- package/docs/components/StatTile.md +58 -0
- package/docs/components/Sticky.md +69 -0
- package/docs/components/Switch.md +89 -0
- package/docs/components/Table.md +184 -0
- package/docs/components/TableOfContents.md +76 -0
- package/docs/components/Tabs.md +94 -0
- package/docs/components/Text.md +63 -0
- package/docs/components/Textarea.md +59 -0
- package/docs/components/Thread.md +52 -0
- package/docs/components/TimeField.md +70 -0
- package/docs/components/Timeline.md +57 -0
- package/docs/components/Title.md +54 -0
- package/docs/components/ToastViewport.md +61 -0
- package/docs/components/Tooltip.md +63 -0
- package/docs/components/TopBar.md +214 -0
- package/docs/components/Tour.md +85 -0
- package/docs/components/TreeView.md +113 -0
- package/docs/components/VisuallyHidden.md +43 -0
- package/docs/components/WidgetPreview.md +54 -0
- package/docs/components/useBelowBreakpoint.md +11 -0
- package/docs/components/useMonth.md +18 -0
- package/docs/setup.md +51 -0
- package/docs/theming.md +95 -0
- package/docs/tokens.md +123 -0
- package/docs/transient-state.md +56 -0
- package/package.json +82 -4
- package/src/_meta/manifest.ts +293 -0
- package/src/app/AppProvider.tsx +78 -0
- package/src/app/index.ts +3 -0
- package/src/app/themeTokens.ts +95 -0
- package/src/calendar/dateMath.ts +114 -0
- package/src/calendar/formatters.ts +75 -0
- package/src/calendar/index.ts +39 -0
- package/src/calendar/types.ts +36 -0
- package/src/calendar/useAgenda.ts +70 -0
- package/src/calendar/useDay.ts +51 -0
- package/src/calendar/useMonth.ts +82 -0
- package/src/calendar/useWeek.ts +62 -0
- package/src/calendar/weekInfo.ts +83 -0
- package/src/components/Accordion/Accordion.module.scss +304 -0
- package/src/components/Accordion/Accordion.tokens.scss +64 -0
- package/src/components/Accordion/Accordion.tsx +272 -0
- package/src/components/Accordion/AccordionContent.tsx +36 -0
- package/src/components/Accordion/AccordionItem.tsx +66 -0
- package/src/components/Accordion/AccordionTrigger.tsx +121 -0
- package/src/components/Accordion/context.ts +47 -0
- package/src/components/Accordion/index.ts +14 -0
- package/src/components/Alert/Alert.module.scss +92 -0
- package/src/components/Alert/Alert.tokens.scss +60 -0
- package/src/components/Alert/Alert.tsx +136 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/AppLayout/AppLayout.module.scss +130 -0
- package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
- package/src/components/AppLayout/AppLayout.tsx +211 -0
- package/src/components/AppLayout/index.ts +2 -0
- package/src/components/Avatar/AgentAvatar.module.scss +117 -0
- package/src/components/Avatar/AgentAvatar.tsx +122 -0
- package/src/components/Avatar/Avatar.module.scss +181 -0
- package/src/components/Avatar/Avatar.tokens.scss +107 -0
- package/src/components/Avatar/Avatar.tsx +210 -0
- package/src/components/Avatar/AvatarGroup.module.scss +128 -0
- package/src/components/Avatar/AvatarGroup.tsx +119 -0
- package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
- package/src/components/Avatar/index.ts +6 -0
- package/src/components/Badge/Badge.module.scss +124 -0
- package/src/components/Badge/Badge.tokens.scss +74 -0
- package/src/components/Badge/Badge.tsx +164 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Banner/Banner.module.scss +73 -0
- package/src/components/Banner/Banner.tokens.scss +51 -0
- package/src/components/Banner/Banner.tsx +138 -0
- package/src/components/Banner/index.ts +2 -0
- package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
- package/src/components/BrandIcon/BrandIcon.tsx +99 -0
- package/src/components/BrandIcon/index.ts +2 -0
- package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
- package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
- package/src/components/Breadcrumb/index.ts +2 -0
- package/src/components/Button/Button.module.scss +167 -0
- package/src/components/Button/Button.tokens.scss +90 -0
- package/src/components/Button/Button.tsx +205 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
- package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
- package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
- package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
- package/src/components/ButtonGroup/context.ts +45 -0
- package/src/components/ButtonGroup/index.ts +2 -0
- package/src/components/Calendar/AgendaView.module.scss +231 -0
- package/src/components/Calendar/AgendaView.tsx +214 -0
- package/src/components/Calendar/AllDayBand.module.scss +18 -0
- package/src/components/Calendar/AllDayBand.tsx +75 -0
- package/src/components/Calendar/Calendar.module.scss +23 -0
- package/src/components/Calendar/Calendar.tokens.scss +262 -0
- package/src/components/Calendar/Calendar.tsx +370 -0
- package/src/components/Calendar/DayCell.module.scss +30 -0
- package/src/components/Calendar/DayCell.tsx +50 -0
- package/src/components/Calendar/DayView.module.scss +10 -0
- package/src/components/Calendar/DayView.tsx +163 -0
- package/src/components/Calendar/EventChip.module.scss +171 -0
- package/src/components/Calendar/EventChip.tsx +115 -0
- package/src/components/Calendar/HourGrid.module.scss +123 -0
- package/src/components/Calendar/HourGrid.tsx +381 -0
- package/src/components/Calendar/MonthView.module.scss +99 -0
- package/src/components/Calendar/MonthView.tsx +296 -0
- package/src/components/Calendar/TimedEvent.module.scss +205 -0
- package/src/components/Calendar/TimedEvent.tsx +247 -0
- package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
- package/src/components/Calendar/ViewSwitcher.tsx +47 -0
- package/src/components/Calendar/WeekView.module.scss +10 -0
- package/src/components/Calendar/WeekView.tsx +137 -0
- package/src/components/Calendar/eventColor.ts +60 -0
- package/src/components/Calendar/index.ts +18 -0
- package/src/components/Calendar/types.ts +451 -0
- package/src/components/Calendar/useEventDrag.ts +783 -0
- package/src/components/Calendar/utils.ts +622 -0
- package/src/components/Card/Card.module.scss +264 -0
- package/src/components/Card/Card.tokens.scss +55 -0
- package/src/components/Card/Card.tsx +170 -0
- package/src/components/Card/CardBody.tsx +45 -0
- package/src/components/Card/CardHeader.tsx +113 -0
- package/src/components/Card/CardList.tsx +24 -0
- package/src/components/Card/CardListRow.tsx +24 -0
- package/src/components/Card/index.ts +7 -0
- package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
- package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
- package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
- package/src/components/CatalogPicker/index.ts +2 -0
- package/src/components/Chart/Chart.module.scss +287 -0
- package/src/components/Chart/Chart.tokens.scss +63 -0
- package/src/components/Chart/Chart.tsx +607 -0
- package/src/components/Chart/ChartLegend.tsx +99 -0
- package/src/components/Chart/ChartTable.tsx +62 -0
- package/src/components/Chart/ChartTooltip.tsx +91 -0
- package/src/components/Chart/chartModel.ts +689 -0
- package/src/components/Chart/index.ts +2 -0
- package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
- package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
- package/src/components/ChatBubble/ChatBubble.tsx +61 -0
- package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
- package/src/components/ChatBubble/index.ts +3 -0
- package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
- package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
- package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
- package/src/components/ChatLauncher/index.ts +2 -0
- package/src/components/ChatLauncher/isAtBottom.ts +12 -0
- package/src/components/Checkbox/Checkbox.module.scss +147 -0
- package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
- package/src/components/Checkbox/Checkbox.tsx +188 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
- package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
- package/src/components/CircularProgress/CircularProgress.tsx +139 -0
- package/src/components/CircularProgress/index.ts +7 -0
- package/src/components/Cluster/Cluster.module.scss +145 -0
- package/src/components/Cluster/Cluster.tokens.scss +11 -0
- package/src/components/Cluster/Cluster.tsx +215 -0
- package/src/components/Cluster/index.ts +2 -0
- package/src/components/Code/Code.module.scss +28 -0
- package/src/components/Code/Code.tokens.scss +15 -0
- package/src/components/Code/Code.tsx +44 -0
- package/src/components/Code/index.ts +2 -0
- package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
- package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
- package/src/components/CodeBlock/CodeBlock.tsx +274 -0
- package/src/components/CodeBlock/highlight.ts +179 -0
- package/src/components/CodeBlock/index.ts +8 -0
- package/src/components/CodeBlock/sampleSync.ts +42 -0
- package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
- package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
- package/src/components/ColorPicker/ColorPicker.tsx +367 -0
- package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
- package/src/components/ColorPicker/SVSquare.tsx +189 -0
- package/src/components/ColorPicker/colorMath.ts +141 -0
- package/src/components/ColorPicker/index.ts +6 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
- package/src/components/ConfirmationPopover/index.ts +2 -0
- package/src/components/Constrain/Constrain.module.scss +99 -0
- package/src/components/Constrain/Constrain.tsx +79 -0
- package/src/components/Constrain/index.ts +2 -0
- package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
- package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
- package/src/components/CurrencySelect/index.ts +3 -0
- package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
- package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
- package/src/components/CursorPagination/CursorPagination.tsx +121 -0
- package/src/components/CursorPagination/index.ts +2 -0
- package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
- package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
- package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
- package/src/components/DashboardCanvas/engine.ts +363 -0
- package/src/components/DashboardCanvas/index.ts +9 -0
- package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
- package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
- package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
- package/src/components/DashboardWidget/index.ts +7 -0
- package/src/components/DataTable/BodyRow.tsx +197 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
- package/src/components/DataTable/DataTable.module.scss +511 -0
- package/src/components/DataTable/DataTable.tokens.scss +80 -0
- package/src/components/DataTable/DataTable.tsx +734 -0
- package/src/components/DataTable/HeaderCell.module.scss +215 -0
- package/src/components/DataTable/HeaderCell.tsx +440 -0
- package/src/components/DataTable/columnShift.ts +117 -0
- package/src/components/DataTable/index.ts +23 -0
- package/src/components/DataTable/pinStyle.ts +47 -0
- package/src/components/DataTable/reorderColumns.ts +66 -0
- package/src/components/DataTable/types.ts +289 -0
- package/src/components/DataTable/useColumnDragShift.ts +216 -0
- package/src/components/DataTable/useDataTable.ts +372 -0
- package/src/components/DataTable/useResizeHandle.ts +97 -0
- package/src/components/DatePicker/DatePicker.module.scss +180 -0
- package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
- package/src/components/DatePicker/DatePicker.tsx +664 -0
- package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
- package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
- package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
- package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
- package/src/components/DatePicker/index.ts +4 -0
- package/src/components/DatePicker/utils.ts +364 -0
- package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
- package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
- package/src/components/DateRangePicker/index.ts +5 -0
- package/src/components/DateRangePicker/utils.ts +151 -0
- package/src/components/DateStrip/DateStrip.module.scss +78 -0
- package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
- package/src/components/DateStrip/DateStrip.tsx +205 -0
- package/src/components/DateStrip/index.ts +2 -0
- package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
- package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
- package/src/components/DefinitionList/DefinitionList.tsx +198 -0
- package/src/components/DefinitionList/index.ts +9 -0
- package/src/components/Divider/Divider.module.scss +144 -0
- package/src/components/Divider/Divider.tokens.scss +21 -0
- package/src/components/Divider/Divider.tsx +103 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Dot/Dot.module.scss +40 -0
- package/src/components/Dot/Dot.tokens.scss +4 -0
- package/src/components/Dot/Dot.tsx +45 -0
- package/src/components/Dot/index.ts +2 -0
- package/src/components/Drawer/Body.tsx +23 -0
- package/src/components/Drawer/Close.tsx +35 -0
- package/src/components/Drawer/Content.tsx +93 -0
- package/src/components/Drawer/Drawer.module.scss +232 -0
- package/src/components/Drawer/Drawer.tokens.scss +38 -0
- package/src/components/Drawer/Drawer.tsx +23 -0
- package/src/components/Drawer/DrawerRoot.tsx +190 -0
- package/src/components/Drawer/Footer.tsx +24 -0
- package/src/components/Drawer/Header.tsx +64 -0
- package/src/components/Drawer/Overlay.tsx +82 -0
- package/src/components/Drawer/context.ts +44 -0
- package/src/components/Drawer/index.ts +12 -0
- package/src/components/Drawer/useDragToClose.ts +149 -0
- package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
- package/src/components/DropdownMenu/Content.tsx +419 -0
- package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
- package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
- package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
- package/src/components/DropdownMenu/Group.tsx +76 -0
- package/src/components/DropdownMenu/Item.tsx +148 -0
- package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
- package/src/components/DropdownMenu/Radio.tsx +178 -0
- package/src/components/DropdownMenu/Root.tsx +100 -0
- package/src/components/DropdownMenu/Sub.tsx +332 -0
- package/src/components/DropdownMenu/Trigger.tsx +76 -0
- package/src/components/DropdownMenu/context.ts +65 -0
- package/src/components/DropdownMenu/index.ts +20 -0
- package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
- package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
- package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
- package/src/components/EmojiPicker/emojiData.ts +245 -0
- package/src/components/EmojiPicker/index.ts +3 -0
- package/src/components/EmptyState/EmptyState.module.scss +102 -0
- package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
- package/src/components/EmptyState/EmptyState.tsx +112 -0
- package/src/components/EmptyState/index.ts +7 -0
- package/src/components/EntityChip/EntityChip.module.scss +275 -0
- package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
- package/src/components/EntityChip/EntityChip.tsx +649 -0
- package/src/components/EntityChip/index.ts +10 -0
- package/src/components/ErrorState/ErrorState.module.scss +105 -0
- package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
- package/src/components/ErrorState/ErrorState.tsx +125 -0
- package/src/components/ErrorState/index.ts +8 -0
- package/src/components/Field/Field.module.scss +46 -0
- package/src/components/Field/Field.tsx +185 -0
- package/src/components/Field/index.ts +2 -0
- package/src/components/FileUpload/FileUpload.module.scss +187 -0
- package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
- package/src/components/FileUpload/FileUpload.tsx +569 -0
- package/src/components/FileUpload/formatBytes.ts +34 -0
- package/src/components/FileUpload/iconForFile.ts +40 -0
- package/src/components/FileUpload/index.ts +2 -0
- package/src/components/FilterChip/FilterChip.module.scss +61 -0
- package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
- package/src/components/FilterChip/FilterChip.tsx +208 -0
- package/src/components/FilterChip/index.ts +5 -0
- package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
- package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
- package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
- package/src/components/FlowCanvas/FlowControls.tsx +46 -0
- package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
- package/src/components/FlowCanvas/FlowNode.tsx +76 -0
- package/src/components/FlowCanvas/edgePath.ts +85 -0
- package/src/components/FlowCanvas/index.ts +4 -0
- package/src/components/FlowCanvas/layout.ts +148 -0
- package/src/components/FlowCanvas/spatialNav.ts +76 -0
- package/src/components/FlowCanvas/types.ts +59 -0
- package/src/components/FlowCanvas/useViewport.ts +122 -0
- package/src/components/FormRow/FormRow.module.scss +2 -0
- package/src/components/FormRow/FormRow.tsx +37 -0
- package/src/components/FormRow/index.ts +2 -0
- package/src/components/FormSection/FormSection.module.scss +24 -0
- package/src/components/FormSection/FormSection.tsx +46 -0
- package/src/components/FormSection/index.ts +2 -0
- package/src/components/Grid/Grid.module.scss +162 -0
- package/src/components/Grid/Grid.tokens.scss +13 -0
- package/src/components/Grid/Grid.tsx +226 -0
- package/src/components/Grid/GridItem.tsx +77 -0
- package/src/components/Grid/index.ts +11 -0
- package/src/components/Highlight/Highlight.module.scss +43 -0
- package/src/components/Highlight/Highlight.tokens.scss +35 -0
- package/src/components/Highlight/Highlight.tsx +164 -0
- package/src/components/Highlight/HighlightOverlay.tsx +100 -0
- package/src/components/Highlight/index.ts +2 -0
- package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
- package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
- package/src/components/HighlightedText/HighlightedText.tsx +50 -0
- package/src/components/HighlightedText/highlightRanges.ts +44 -0
- package/src/components/HighlightedText/index.ts +2 -0
- package/src/components/IconPicker/IconPicker.module.scss +175 -0
- package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
- package/src/components/IconPicker/IconPicker.tsx +629 -0
- package/src/components/IconPicker/index.ts +9 -0
- package/src/components/IconTile/IconTile.module.scss +57 -0
- package/src/components/IconTile/IconTile.tokens.scss +16 -0
- package/src/components/IconTile/IconTile.tsx +91 -0
- package/src/components/IconTile/index.ts +2 -0
- package/src/components/Image/Image.module.scss +266 -0
- package/src/components/Image/Image.tokens.scss +55 -0
- package/src/components/Image/Image.tsx +342 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
- package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
- package/src/components/ImageCrop/ImageCrop.tsx +542 -0
- package/src/components/ImageCrop/cropGeometry.ts +120 -0
- package/src/components/ImageCrop/extractCropBlob.ts +140 -0
- package/src/components/ImageCrop/index.ts +11 -0
- package/src/components/ImageCrop/useCropPreview.ts +161 -0
- package/src/components/Indent/Indent.module.scss +33 -0
- package/src/components/Indent/Indent.tokens.scss +10 -0
- package/src/components/Indent/Indent.tsx +46 -0
- package/src/components/Indent/index.ts +2 -0
- package/src/components/Input/Input.module.scss +99 -0
- package/src/components/Input/Input.tokens.scss +54 -0
- package/src/components/Input/Input.tsx +105 -0
- package/src/components/Input/Suggestions.tsx +260 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Kanban/Kanban.module.scss +39 -0
- package/src/components/Kanban/Kanban.tokens.scss +15 -0
- package/src/components/Kanban/Kanban.tsx +951 -0
- package/src/components/Kanban/index.ts +7 -0
- package/src/components/Kbd/Kbd.module.scss +47 -0
- package/src/components/Kbd/Kbd.tokens.scss +26 -0
- package/src/components/Kbd/Kbd.tsx +73 -0
- package/src/components/Kbd/index.ts +2 -0
- package/src/components/Lightbox/Lightbox.module.scss +283 -0
- package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
- package/src/components/Lightbox/Lightbox.tsx +506 -0
- package/src/components/Lightbox/index.ts +2 -0
- package/src/components/Link/Link.module.scss +78 -0
- package/src/components/Link/Link.tokens.scss +28 -0
- package/src/components/Link/Link.tsx +114 -0
- package/src/components/Link/index.ts +2 -0
- package/src/components/LinkCard/LinkCard.module.scss +92 -0
- package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
- package/src/components/LinkCard/LinkCard.tsx +72 -0
- package/src/components/LinkCard/index.ts +2 -0
- package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
- package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
- package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
- package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
- package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
- package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
- package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
- package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
- package/src/components/LiquidEditor/index.ts +7 -0
- package/src/components/LiquidEditor/liquidFilters.ts +23 -0
- package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
- package/src/components/LiquidEditor/types.ts +101 -0
- package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
- package/src/components/List/List.module.scss +105 -0
- package/src/components/List/List.tokens.scss +42 -0
- package/src/components/List/List.tsx +124 -0
- package/src/components/List/index.ts +9 -0
- package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
- package/src/components/LiveRegion/LiveRegion.tsx +116 -0
- package/src/components/LiveRegion/index.ts +2 -0
- package/src/components/Logo/Logo.module.scss +139 -0
- package/src/components/Logo/Logo.tokens.scss +14 -0
- package/src/components/Logo/Logo.tsx +126 -0
- package/src/components/Logo/index.ts +2 -0
- package/src/components/Masonry/Masonry.module.scss +42 -0
- package/src/components/Masonry/Masonry.tokens.scss +8 -0
- package/src/components/Masonry/Masonry.tsx +136 -0
- package/src/components/Masonry/index.ts +2 -0
- package/src/components/Masonry/masonryUtils.ts +42 -0
- package/src/components/MediaTile/MediaTile.module.scss +183 -0
- package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
- package/src/components/MediaTile/MediaTile.tsx +208 -0
- package/src/components/MediaTile/index.ts +8 -0
- package/src/components/Modal/Body.tsx +27 -0
- package/src/components/Modal/Close.tsx +45 -0
- package/src/components/Modal/Content.tsx +98 -0
- package/src/components/Modal/Footer.tsx +28 -0
- package/src/components/Modal/Header.tsx +51 -0
- package/src/components/Modal/Modal.module.scss +262 -0
- package/src/components/Modal/Modal.tokens.scss +50 -0
- package/src/components/Modal/Modal.tsx +23 -0
- package/src/components/Modal/ModalRoot.tsx +299 -0
- package/src/components/Modal/Overlay.tsx +101 -0
- package/src/components/Modal/context.ts +60 -0
- package/src/components/Modal/index.ts +11 -0
- package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
- package/src/components/MoneyInput/MoneyInput.tsx +433 -0
- package/src/components/MoneyInput/index.ts +2 -0
- package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
- package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
- package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
- package/src/components/OptionsPicker/index.ts +9 -0
- package/src/components/OtpInput/OtpInput.module.scss +69 -0
- package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
- package/src/components/OtpInput/OtpInput.tsx +368 -0
- package/src/components/OtpInput/index.ts +2 -0
- package/src/components/Page/Page.module.scss +30 -0
- package/src/components/Page/Page.tokens.scss +11 -0
- package/src/components/Page/Page.tsx +53 -0
- package/src/components/Page/index.ts +2 -0
- package/src/components/PageHeader/PageHeader.module.scss +197 -0
- package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
- package/src/components/PageHeader/PageHeader.tsx +310 -0
- package/src/components/PageHeader/index.ts +20 -0
- package/src/components/Pagination/Pagination.module.scss +117 -0
- package/src/components/Pagination/Pagination.tokens.scss +54 -0
- package/src/components/Pagination/Pagination.tsx +165 -0
- package/src/components/Pagination/index.ts +4 -0
- package/src/components/Pagination/paginationRange.ts +72 -0
- package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
- package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
- package/src/components/PasswordInput/PasswordInput.tsx +210 -0
- package/src/components/PasswordInput/index.ts +2 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
- package/src/components/PasswordStrengthMeter/index.ts +2 -0
- package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
- package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
- package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
- package/src/components/PersonDisplay/index.ts +10 -0
- package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
- package/src/components/PhoneInput/PhoneInput.tsx +271 -0
- package/src/components/PhoneInput/index.ts +4 -0
- package/src/components/PhoneInput/phone.ts +128 -0
- package/src/components/PillMenu/PillMenu.module.scss +117 -0
- package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
- package/src/components/PillMenu/PillMenu.tsx +324 -0
- package/src/components/PillMenu/index.ts +2 -0
- package/src/components/Popover/Anchor.tsx +37 -0
- package/src/components/Popover/Close.tsx +45 -0
- package/src/components/Popover/Content.tsx +213 -0
- package/src/components/Popover/Heading.tsx +33 -0
- package/src/components/Popover/Popover.module.scss +177 -0
- package/src/components/Popover/Popover.tokens.scss +22 -0
- package/src/components/Popover/Popover.tsx +23 -0
- package/src/components/Popover/PopoverRoot.tsx +75 -0
- package/src/components/Popover/Trigger.tsx +86 -0
- package/src/components/Popover/context.ts +22 -0
- package/src/components/Popover/index.ts +7 -0
- package/src/components/Progress/Progress.module.scss +110 -0
- package/src/components/Progress/Progress.tokens.scss +44 -0
- package/src/components/Progress/Progress.tsx +129 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/QrCode/QrCode.module.scss +97 -0
- package/src/components/QrCode/QrCode.tokens.scss +17 -0
- package/src/components/QrCode/QrCode.tsx +233 -0
- package/src/components/QrCode/index.ts +2 -0
- package/src/components/QrCode/qr.ts +161 -0
- package/src/components/Radio/Radio.module.scss +175 -0
- package/src/components/Radio/Radio.tokens.scss +59 -0
- package/src/components/Radio/Radio.tsx +127 -0
- package/src/components/Radio/RadioGroup.module.scss +42 -0
- package/src/components/Radio/RadioGroup.tsx +120 -0
- package/src/components/Radio/RadioGroupContext.tsx +30 -0
- package/src/components/Radio/index.ts +4 -0
- package/src/components/Rail/Rail.module.scss +510 -0
- package/src/components/Rail/Rail.tokens.scss +92 -0
- package/src/components/Rail/Rail.tsx +287 -0
- package/src/components/Rail/RailCollapseToggle.tsx +57 -0
- package/src/components/Rail/RailFooter.tsx +17 -0
- package/src/components/Rail/RailGroup.tsx +728 -0
- package/src/components/Rail/RailGroupContext.ts +9 -0
- package/src/components/Rail/RailHeader.tsx +23 -0
- package/src/components/Rail/RailItem.tsx +119 -0
- package/src/components/Rail/RailSection.tsx +39 -0
- package/src/components/Rail/RailSpacer.tsx +19 -0
- package/src/components/Rail/index.ts +9 -0
- package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
- package/src/components/RelativeDateInput/index.ts +10 -0
- package/src/components/RelativeDateInput/relativeDate.ts +127 -0
- package/src/components/RichText/RichText.module.scss +5 -0
- package/src/components/RichText/RichText.tsx +70 -0
- package/src/components/RichText/RichTextAttachment.module.scss +82 -0
- package/src/components/RichText/RichTextAttachment.tsx +122 -0
- package/src/components/RichText/_prose.scss +79 -0
- package/src/components/RichText/attachmentIcon.tsx +24 -0
- package/src/components/RichText/engine/attachment.ts +154 -0
- package/src/components/RichText/engine/autolink.ts +64 -0
- package/src/components/RichText/engine/blockUnit.ts +174 -0
- package/src/components/RichText/engine/colorMarks.ts +85 -0
- package/src/components/RichText/engine/escape.ts +11 -0
- package/src/components/RichText/engine/fromHtml.ts +353 -0
- package/src/components/RichText/engine/fromMarkdown.ts +20 -0
- package/src/components/RichText/engine/inlines.ts +82 -0
- package/src/components/RichText/engine/listDepths.ts +32 -0
- package/src/components/RichText/engine/marks.ts +80 -0
- package/src/components/RichText/engine/mdToHtml.ts +178 -0
- package/src/components/RichText/engine/model.ts +157 -0
- package/src/components/RichText/engine/position.ts +118 -0
- package/src/components/RichText/engine/renderDoc.tsx +395 -0
- package/src/components/RichText/engine/renderLink.ts +15 -0
- package/src/components/RichText/engine/renderMention.ts +16 -0
- package/src/components/RichText/engine/safeHref.ts +22 -0
- package/src/components/RichText/engine/toHtml.ts +154 -0
- package/src/components/RichText/engine/toMarkdown.ts +97 -0
- package/src/components/RichText/engine/transforms.ts +434 -0
- package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
- package/src/components/RichText/index.ts +31 -0
- package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
- package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
- package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
- package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
- package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
- package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
- package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
- package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
- package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
- package/src/components/RichTextEditor/autolinkInput.ts +65 -0
- package/src/components/RichTextEditor/blockDrop.ts +9 -0
- package/src/components/RichTextEditor/blockReflow.ts +62 -0
- package/src/components/RichTextEditor/commands.ts +300 -0
- package/src/components/RichTextEditor/history.ts +93 -0
- package/src/components/RichTextEditor/icons.tsx +152 -0
- package/src/components/RichTextEditor/imageSize.ts +70 -0
- package/src/components/RichTextEditor/index.ts +5 -0
- package/src/components/RichTextEditor/input.ts +209 -0
- package/src/components/RichTextEditor/inputRules.ts +71 -0
- package/src/components/RichTextEditor/links.ts +103 -0
- package/src/components/RichTextEditor/mentionContext.ts +37 -0
- package/src/components/RichTextEditor/mentions.ts +28 -0
- package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
- package/src/components/RichTextEditor/selection.ts +415 -0
- package/src/components/RichTextEditor/shortcuts.ts +44 -0
- package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
- package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
- package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
- package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
- package/src/components/RichTextEditor/useMention.ts +226 -0
- package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
- package/src/components/RichTextEditor/useUpload.ts +246 -0
- package/src/components/Screen/Screen.module.scss +46 -0
- package/src/components/Screen/Screen.tokens.scss +20 -0
- package/src/components/Screen/Screen.tsx +97 -0
- package/src/components/Screen/index.ts +2 -0
- package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
- package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
- package/src/components/ScrollArea/ScrollArea.tsx +154 -0
- package/src/components/ScrollArea/index.ts +2 -0
- package/src/components/Select/Chip.tsx +45 -0
- package/src/components/Select/Empty.tsx +39 -0
- package/src/components/Select/Error.tsx +51 -0
- package/src/components/Select/HiddenInputs.tsx +44 -0
- package/src/components/Select/Listbox.tsx +557 -0
- package/src/components/Select/Loading.tsx +30 -0
- package/src/components/Select/Select.module.scss +512 -0
- package/src/components/Select/Select.tokens.scss +140 -0
- package/src/components/Select/Select.tsx +685 -0
- package/src/components/Select/Trigger.tsx +952 -0
- package/src/components/Select/context.ts +101 -0
- package/src/components/Select/emptyStateText.ts +19 -0
- package/src/components/Select/index.ts +9 -0
- package/src/components/Select/useSelectState.ts +157 -0
- package/src/components/Select/utils-types.ts +7 -0
- package/src/components/Select/utils.ts +122 -0
- package/src/components/SettingRow/SettingRow.module.scss +166 -0
- package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
- package/src/components/SettingRow/SettingRow.tsx +242 -0
- package/src/components/SettingRow/index.ts +7 -0
- package/src/components/Skeleton/Skeleton.module.scss +55 -0
- package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
- package/src/components/Skeleton/Skeleton.tsx +131 -0
- package/src/components/Skeleton/index.ts +4 -0
- package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
- package/src/components/Slider/Slider.module.scss +293 -0
- package/src/components/Slider/Slider.tokens.scss +98 -0
- package/src/components/Slider/Slider.tsx +624 -0
- package/src/components/Slider/index.ts +9 -0
- package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
- package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
- package/src/components/SlotGrid/SlotGrid.tsx +111 -0
- package/src/components/SlotGrid/index.ts +2 -0
- package/src/components/SocialButton/SocialButton.module.scss +4 -0
- package/src/components/SocialButton/SocialButton.tsx +40 -0
- package/src/components/SocialButton/index.ts +2 -0
- package/src/components/Sortable/Sortable.module.scss +177 -0
- package/src/components/Sortable/Sortable.tokens.scss +27 -0
- package/src/components/Sortable/Sortable.tsx +572 -0
- package/src/components/Sortable/containerAwareCollision.ts +125 -0
- package/src/components/Sortable/index.ts +13 -0
- package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
- package/src/components/SortableGroup/SortableGroup.tsx +315 -0
- package/src/components/SortableGroup/index.ts +4 -0
- package/src/components/SortableGroup/moveSortableItem.ts +39 -0
- package/src/components/Sparkline/Sparkline.module.scss +28 -0
- package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
- package/src/components/Sparkline/Sparkline.tsx +133 -0
- package/src/components/Sparkline/index.ts +2 -0
- package/src/components/Sparkline/sparklineModel.ts +119 -0
- package/src/components/Split/Split.module.scss +158 -0
- package/src/components/Split/Split.tokens.scss +10 -0
- package/src/components/Split/Split.tsx +231 -0
- package/src/components/Split/index.ts +2 -0
- package/src/components/Stack/Stack.module.scss +67 -0
- package/src/components/Stack/Stack.tokens.scss +11 -0
- package/src/components/Stack/Stack.tsx +100 -0
- package/src/components/Stack/index.ts +2 -0
- package/src/components/StagePath/StagePath.module.scss +255 -0
- package/src/components/StagePath/StagePath.tokens.scss +43 -0
- package/src/components/StagePath/StagePath.tsx +176 -0
- package/src/components/StagePath/index.ts +2 -0
- package/src/components/StatGroup/StatGroup.module.scss +6 -0
- package/src/components/StatGroup/StatGroup.tsx +70 -0
- package/src/components/StatGroup/StatGroupContext.ts +10 -0
- package/src/components/StatGroup/StatTile.module.scss +99 -0
- package/src/components/StatGroup/StatTile.tokens.scss +35 -0
- package/src/components/StatGroup/StatTile.tsx +143 -0
- package/src/components/StatGroup/index.ts +4 -0
- package/src/components/Sticky/Sticky.module.scss +98 -0
- package/src/components/Sticky/Sticky.tokens.scss +17 -0
- package/src/components/Sticky/Sticky.tsx +103 -0
- package/src/components/Sticky/index.ts +2 -0
- package/src/components/Switch/Switch.module.scss +182 -0
- package/src/components/Switch/Switch.tokens.scss +59 -0
- package/src/components/Switch/Switch.tsx +214 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/Table.module.scss +308 -0
- package/src/components/Table/Table.tokens.scss +79 -0
- package/src/components/Table/Table.tsx +381 -0
- package/src/components/Table/index.ts +15 -0
- package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
- package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
- package/src/components/TableOfContents/TableOfContents.tsx +192 -0
- package/src/components/TableOfContents/activeSection.ts +18 -0
- package/src/components/TableOfContents/index.ts +2 -0
- package/src/components/Tabs/Tabs.module.scss +359 -0
- package/src/components/Tabs/Tabs.tokens.scss +50 -0
- package/src/components/Tabs/Tabs.tsx +538 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Text/Text.module.scss +115 -0
- package/src/components/Text/Text.tokens.scss +55 -0
- package/src/components/Text/Text.tsx +197 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Textarea/Textarea.module.scss +94 -0
- package/src/components/Textarea/Textarea.tokens.scss +48 -0
- package/src/components/Textarea/Textarea.tsx +246 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Thread/Thread.module.scss +161 -0
- package/src/components/Thread/Thread.tokens.scss +32 -0
- package/src/components/Thread/Thread.tsx +176 -0
- package/src/components/Thread/index.ts +2 -0
- package/src/components/TimeField/TimeField.module.scss +232 -0
- package/src/components/TimeField/TimeField.tsx +793 -0
- package/src/components/TimeField/index.ts +2 -0
- package/src/components/Timeline/Timeline.module.scss +58 -0
- package/src/components/Timeline/Timeline.tokens.scss +13 -0
- package/src/components/Timeline/Timeline.tsx +53 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Title/Title.module.scss +84 -0
- package/src/components/Title/Title.tokens.scss +37 -0
- package/src/components/Title/Title.tsx +150 -0
- package/src/components/Title/index.ts +2 -0
- package/src/components/Toast/Toast.module.scss +299 -0
- package/src/components/Toast/Toast.tokens.scss +65 -0
- package/src/components/Toast/Toast.tsx +122 -0
- package/src/components/Toast/ToastViewport.tsx +166 -0
- package/src/components/Toast/api.ts +175 -0
- package/src/components/Toast/index.ts +5 -0
- package/src/components/Toast/store.ts +133 -0
- package/src/components/Toast/useToastTimer.ts +94 -0
- package/src/components/Tooltip/Tooltip.module.scss +99 -0
- package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
- package/src/components/Tooltip/Tooltip.tsx +341 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/TopBar/TopBar.module.scss +235 -0
- package/src/components/TopBar/TopBar.tokens.scss +79 -0
- package/src/components/TopBar/TopBar.tsx +87 -0
- package/src/components/TopBar/TopBarEnd.tsx +20 -0
- package/src/components/TopBar/TopBarIconButton.tsx +86 -0
- package/src/components/TopBar/TopBarSearch.tsx +319 -0
- package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
- package/src/components/TopBar/TopBarStart.tsx +20 -0
- package/src/components/TopBar/index.ts +11 -0
- package/src/components/Tour/Spotlight.tsx +121 -0
- package/src/components/Tour/Tour.module.scss +210 -0
- package/src/components/Tour/Tour.tokens.scss +58 -0
- package/src/components/Tour/Tour.tsx +617 -0
- package/src/components/Tour/index.ts +2 -0
- package/src/components/Tour/useTourTarget.ts +115 -0
- package/src/components/TreeView/TreeView.module.scss +268 -0
- package/src/components/TreeView/TreeView.tokens.scss +36 -0
- package/src/components/TreeView/TreeView.tsx +536 -0
- package/src/components/TreeView/index.ts +3 -0
- package/src/components/TreeView/treeModel.ts +224 -0
- package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
- package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
- package/src/components/VisuallyHidden/index.ts +2 -0
- package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
- package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
- package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
- package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
- package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
- package/src/components/WidgetPreview/index.ts +2 -0
- package/src/components/_internal/Trend.tsx +27 -0
- package/src/components/_internal/choiceTile.scss +74 -0
- package/src/components/_internal/collapse.scss +10 -0
- package/src/components/_internal/collapse.ts +58 -0
- package/src/components/_internal/currency.ts +257 -0
- package/src/components/_internal/dragAnnouncements.ts +200 -0
- package/src/components/_internal/fieldWiring.ts +225 -0
- package/src/components/_internal/gridSpan.ts +54 -0
- package/src/components/_internal/isoDay.ts +35 -0
- package/src/components/_internal/letterKey.ts +26 -0
- package/src/components/_internal/overlay/focusRestore.ts +21 -0
- package/src/components/_internal/overlay/index.ts +12 -0
- package/src/components/_internal/overlay/tourHold.ts +23 -0
- package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
- package/src/components/_internal/overlay/useInOverlay.ts +81 -0
- package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
- package/src/components/_internal/overlay/useScrollLock.ts +112 -0
- package/src/components/_internal/refs.ts +48 -0
- package/src/components/_internal/statusColor.ts +26 -0
- package/src/components/_internal/timeUtils.ts +23 -0
- package/src/components/_internal/useAsyncOptions.ts +145 -0
- package/src/components/_internal/useClippedTooltip.ts +50 -0
- package/src/components/_internal/useControllableState.ts +50 -0
- package/src/components.manifest.json +1141 -0
- package/src/hooks/useBelowBreakpoint.ts +58 -0
- package/src/i18n/I18nProvider.tsx +52 -0
- package/src/i18n/LocaleProvider.tsx +17 -0
- package/src/i18n/en.ts +648 -0
- package/src/i18n/format.ts +71 -0
- package/src/i18n/index.ts +13 -0
- package/src/i18n/messages.ts +1275 -0
- package/src/i18n/ru.ts +677 -0
- package/src/i18n/useLocale.ts +19 -0
- package/src/i18n/useTranslation.ts +58 -0
- package/src/index.ts +913 -0
- package/src/palette/index.ts +2 -0
- package/src/palette/palette.ts +108 -0
- package/src/styles/dark.scss +4 -0
- package/src/styles/global.scss +7 -0
- package/src/styles/mixins.scss +143 -0
- package/src/styles/reset.scss +78 -0
- package/src/styles/tokens.scss +18 -0
- package/src/styles/typography.scss +44 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Shared look for DateStrip / SlotGrid tiles: a <label> wrapping a visually
|
|
2
|
+
// hidden native radio. Unchecked = Button secondary, checked = Button primary.
|
|
3
|
+
// Consumers of the mixin pass their component tokens so each stays themable.
|
|
4
|
+
@use '../../styles/mixins' as *;
|
|
5
|
+
|
|
6
|
+
@mixin choice-tile(
|
|
7
|
+
$input,
|
|
8
|
+
$bg,
|
|
9
|
+
$bg-hover,
|
|
10
|
+
$fg,
|
|
11
|
+
$border,
|
|
12
|
+
$bg-checked,
|
|
13
|
+
$bg-checked-hover,
|
|
14
|
+
$fg-checked,
|
|
15
|
+
$radius,
|
|
16
|
+
$ring,
|
|
17
|
+
$opacity-disabled
|
|
18
|
+
) {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
width: 100%;
|
|
24
|
+
border: var(--border-width) solid $border;
|
|
25
|
+
border-radius: $radius;
|
|
26
|
+
background: $bg;
|
|
27
|
+
color: $fg;
|
|
28
|
+
font: inherit;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
user-select: none;
|
|
31
|
+
transition:
|
|
32
|
+
background var(--transition-fast),
|
|
33
|
+
border-color var(--transition-fast),
|
|
34
|
+
color var(--transition-fast);
|
|
35
|
+
|
|
36
|
+
#{$input} {
|
|
37
|
+
@include visually-hidden;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&:hover:not(:has(#{$input}:disabled)) {
|
|
41
|
+
background: $bg-hover;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&:has(#{$input}:checked) {
|
|
45
|
+
border-color: transparent;
|
|
46
|
+
background: $bg-checked;
|
|
47
|
+
color: $fg-checked;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&:has(#{$input}:checked):hover {
|
|
51
|
+
background: $bg-checked-hover;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&:has(#{$input}:focus-visible) {
|
|
55
|
+
@include focus-ring($ring);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&:has(#{$input}:disabled) {
|
|
59
|
+
opacity: $opacity-disabled;
|
|
60
|
+
cursor: not-allowed;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Forced colors (Windows High Contrast) drops backgrounds, which is all
|
|
64
|
+
// that marks the checked tile — add an outline outside its border (text
|
|
65
|
+
// color, forced to a system color) so checked still reads as different.
|
|
66
|
+
// Not while focus-visible: this rule would come after the focus ring and
|
|
67
|
+
// replace it (arrows select as they move, so the focused tile is usually
|
|
68
|
+
// the checked one) — the ring is the stronger signal there.
|
|
69
|
+
@media (forced-colors: active) {
|
|
70
|
+
&:has(#{$input}:checked:not(:focus-visible)) {
|
|
71
|
+
outline: var(--border-width) solid currentcolor;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Container-width collapse thresholds shared by Grid's `collapseBelow` and
|
|
2
|
+
// Sortable's grid-arrangement `collapseBelow`. SCSS constants (not CSS custom
|
|
3
|
+
// properties): container-query conditions can't read custom properties.
|
|
4
|
+
// Keep in sync with the CollapseBreakpoint JSDoc AND the COLLAPSE_BREAKPOINT_PX
|
|
5
|
+
// record in collapse.ts — Rail evaluates the same scale in JS via matchMedia
|
|
6
|
+
// (against the VIEWPORT, since a container query on the rail's own width would
|
|
7
|
+
// be circular), so the two copies of these numbers must not drift.
|
|
8
|
+
$collapse-sm: 480px;
|
|
9
|
+
$collapse-md: 640px;
|
|
10
|
+
$collapse-lg: 768px;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared `collapseBelow` threshold scale: `sm` 480px / `md` 640px / `lg` 768px.
|
|
5
|
+
*
|
|
6
|
+
* The scale is shared; **the measurement basis is per-component**:
|
|
7
|
+
*
|
|
8
|
+
* - **Container** (`@container (max-width: …)`) for Grid / Sortable (grid
|
|
9
|
+
* arrangement) / Split / DashboardCanvas / DataTable. Collapsing re-templates
|
|
10
|
+
* content *inside* a box whose width the collapse doesn't change, so querying
|
|
11
|
+
* the box's own width is stable and needs no JS.
|
|
12
|
+
* - **Viewport** (`matchMedia`, via the `useBelowBreakpoint` hook in
|
|
13
|
+
* `src/hooks/`) for Rail and AppLayout's overlay sidebar. A container query
|
|
14
|
+
* there would be circular — the thing being measured IS what the collapse
|
|
15
|
+
* changes (Rail's own width 240px → 56px; the sidebar's presence in
|
|
16
|
+
* AppLayout's row). Rail's collapsed state also drives React behavior (Item
|
|
17
|
+
* tooltips, Group flyouts, section titles), which CSS can't express, so the
|
|
18
|
+
* threshold has to exist in JS regardless.
|
|
19
|
+
*/
|
|
20
|
+
export type CollapseBreakpoint = 'sm' | 'md' | 'lg';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Pixel value of each breakpoint, for components that evaluate the threshold in
|
|
24
|
+
* JS (`matchMedia`) rather than in CSS.
|
|
25
|
+
*
|
|
26
|
+
* **Keep in sync with `collapse.scss`** (`$collapse-sm` / `-md` / `-lg`) — the
|
|
27
|
+
* SCSS constants are the CSS-side copy of these same numbers. Both are
|
|
28
|
+
* inclusive upper bounds: `max-width: 480px` matches AT 480px.
|
|
29
|
+
*/
|
|
30
|
+
export const COLLAPSE_BREAKPOINT_PX: Record<CollapseBreakpoint, number> = {
|
|
31
|
+
sm: 480,
|
|
32
|
+
md: 640,
|
|
33
|
+
lg: 768,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Graduated collapse: breakpoint → column count. Below each breakpoint the
|
|
38
|
+
* grid re-templates to that many equal columns and every item's span is
|
|
39
|
+
* clamped to fit. E.g. `{ md: 6, sm: 1 }` = 12-col grid above 640px, 6-col
|
|
40
|
+
* between 480–640px, single column below 480px. When several breakpoints
|
|
41
|
+
* match, the smallest wins.
|
|
42
|
+
*/
|
|
43
|
+
export type CollapseColumnsMap = Partial<Record<CollapseBreakpoint, number>>;
|
|
44
|
+
|
|
45
|
+
/** Largest → smallest; step CSS is declared in this order so the smallest matching breakpoint wins by source order. */
|
|
46
|
+
export const COLLAPSE_BREAKPOINTS: readonly CollapseBreakpoint[] = ['lg', 'md', 'sm'];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The container's graduated-collapse map, provided by Grid / Sortable (grid
|
|
50
|
+
* arrangement) to their Items so each can stamp per-breakpoint clamped span
|
|
51
|
+
* custom properties. `null` when the container has no map-form collapse.
|
|
52
|
+
*/
|
|
53
|
+
export const CollapseColumnsContext = createContext<CollapseColumnsMap | null>(null);
|
|
54
|
+
|
|
55
|
+
/** Track template for a collapse step — mirrors Grid's fixed-column template. */
|
|
56
|
+
export function collapseTrackTemplate(columns: number): string {
|
|
57
|
+
return `repeat(${columns}, minmax(0, 1fr))`;
|
|
58
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/** Shared currency parse/format helpers for MoneyInput / CurrencySelect. Amounts stay strings (never JS numbers). */
|
|
2
|
+
|
|
3
|
+
export type CurrencyDisplay = 'code' | 'symbol' | 'both';
|
|
4
|
+
|
|
5
|
+
/** Parsed, in-progress amount. `frac === null` → no decimal point typed; `''` → trailing point. */
|
|
6
|
+
export interface AmountDraft {
|
|
7
|
+
negative: boolean;
|
|
8
|
+
int: string;
|
|
9
|
+
frac: string | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Callers must guard codes with isValidCurrency; the Intl helpers below assume a valid code.
|
|
13
|
+
export function currencyPrecision(code: string): number {
|
|
14
|
+
return new Intl.NumberFormat('en', { style: 'currency', currency: code }).resolvedOptions()
|
|
15
|
+
.maximumFractionDigits!;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function currencySymbol(code: string, locale: string): string {
|
|
19
|
+
const parts = new Intl.NumberFormat(locale, {
|
|
20
|
+
style: 'currency',
|
|
21
|
+
currency: code,
|
|
22
|
+
currencyDisplay: 'symbol',
|
|
23
|
+
}).formatToParts(0);
|
|
24
|
+
return parts.find((p) => p.type === 'currency')?.value ?? code;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function currencyName(code: string, locale: string): string {
|
|
28
|
+
try {
|
|
29
|
+
return new Intl.DisplayNames(locale, { type: 'currency' }).of(code) ?? code;
|
|
30
|
+
} catch {
|
|
31
|
+
return code;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function currencyDisplayText(
|
|
36
|
+
code: string,
|
|
37
|
+
display: CurrencyDisplay,
|
|
38
|
+
locale: string,
|
|
39
|
+
): string {
|
|
40
|
+
if (display === 'code') return code;
|
|
41
|
+
const symbol = currencySymbol(code, locale);
|
|
42
|
+
return display === 'symbol' ? symbol : `${code} ${symbol}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function isValidCurrency(code: string): boolean {
|
|
46
|
+
try {
|
|
47
|
+
new Intl.NumberFormat('en', { style: 'currency', currency: code });
|
|
48
|
+
return true;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function localeSeparators(locale: string): { group: string; decimal: string } {
|
|
55
|
+
const parts = new Intl.NumberFormat(locale).formatToParts(1234.5);
|
|
56
|
+
return {
|
|
57
|
+
group: parts.find((p) => p.type === 'group')?.value ?? ',',
|
|
58
|
+
decimal: parts.find((p) => p.type === 'decimal')?.value ?? '.',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Space-like grouping chars allowed inside a pasted number (one kind per number). */
|
|
63
|
+
const SPACE_GROUP = /[ '’]/g;
|
|
64
|
+
// One affix token: currency symbols and/or one letter word ('US$', 'руб.', prefix label 'Total:').
|
|
65
|
+
const PREFIX_TOKEN = /^(?:\p{Sc}*\p{L}+[.:]?\p{Sc}*|\p{Sc}+)$/u;
|
|
66
|
+
const SUFFIX_TOKEN = /^(?:\p{Sc}*\p{L}+\.?\p{Sc}*|\p{Sc}+)$/u;
|
|
67
|
+
const SUFFIX_WORDS = new Set(['руб', 'р']);
|
|
68
|
+
let isoCodes: Set<string> | undefined;
|
|
69
|
+
/** A real ISO 4217 code (not merely well-formed), so magnitude words ('K', 'bn', 'млн') never pass. */
|
|
70
|
+
// Without Intl.supportedValuesOf no suffix word counts as a currency (reject, never throw).
|
|
71
|
+
const isIsoCode = (w: string) =>
|
|
72
|
+
(isoCodes ??= new Set(
|
|
73
|
+
typeof Intl.supportedValuesOf === 'function' ? Intl.supportedValuesOf('currency') : [],
|
|
74
|
+
)).has(w.toUpperCase());
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Splits one affix side into sign marks; null when anything but symbols / ONE word / sign remains.
|
|
78
|
+
* A prefix word is a free label ('Total', 'Итого:'); a suffix word must be a currency
|
|
79
|
+
* (ISO code or 'руб'/'р') — anything else may be a magnitude ('5 тыс.', '$2 million').
|
|
80
|
+
*/
|
|
81
|
+
function readAffix(side: string, open: string, signs: string, suffix: boolean) {
|
|
82
|
+
const marks = { open: 0, minus: 0, plus: 0 };
|
|
83
|
+
for (const c of side) {
|
|
84
|
+
if (c === open) marks.open++;
|
|
85
|
+
else if (c === '-' && signs.includes('-')) marks.minus++;
|
|
86
|
+
else if (c === '+' && signs.includes('+')) marks.plus++;
|
|
87
|
+
}
|
|
88
|
+
const rest = side.replace(new RegExp(`[\\${open}${signs.replace('-', '\\-')}]`, 'g'), ' ');
|
|
89
|
+
const tokens = rest.split(/[ ]+/).filter(Boolean);
|
|
90
|
+
if (!tokens.every((tk) => (suffix ? SUFFIX_TOKEN : PREFIX_TOKEN).test(tk))) return null;
|
|
91
|
+
const words = tokens.map((tk) => tk.replace(/[^\p{L}]/gu, '')).filter(Boolean);
|
|
92
|
+
if (words.length > 1) return null;
|
|
93
|
+
if (suffix && words.length && !SUFFIX_WORDS.has(words[0].toLowerCase()) && !isIsoCode(words[0]))
|
|
94
|
+
return null;
|
|
95
|
+
return marks;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Lenient parse of a PASTED segment: exactly one number, with optional currency symbols / one word
|
|
100
|
+
* per side, a sign ('-', '−', '+', trailing '-') or accounting parentheses. Grouping must be
|
|
101
|
+
* unambiguous (first group 1–3 digits, then exactly 3, one group char kind); the cross-locale rules
|
|
102
|
+
* pick the decimal. Anything doubtful → `'invalid'`; no digits at all → `null`.
|
|
103
|
+
*/
|
|
104
|
+
export function parseAmount(
|
|
105
|
+
text: string,
|
|
106
|
+
opts: { locale: string; precision: number; allowNegative: boolean },
|
|
107
|
+
): AmountDraft | null | 'invalid' {
|
|
108
|
+
const t = text.replace(/−/g, '-').trim().replace(/\.$/, ''); // trailing sentence period
|
|
109
|
+
const first = t.search(/\d/);
|
|
110
|
+
if (first < 0) return null;
|
|
111
|
+
let last = t.length - 1;
|
|
112
|
+
while (!/\d/.test(t[last])) last--;
|
|
113
|
+
// '.5' — but a separator glued to a word belongs to it ('Rs.100', 'руб.10').
|
|
114
|
+
const leadingSep = /[.,]/.test(t[first - 1] ?? '') && !/\p{L}/u.test(t[first - 2] ?? '');
|
|
115
|
+
const from = leadingSep ? first - 1 : first;
|
|
116
|
+
// Letters glued to the number ('5K', '3bn', 'USD5') are magnitudes or noise.
|
|
117
|
+
if (/\p{L}/u.test(t[from - 1] ?? '') || /\p{L}/u.test(t[last + 1] ?? '')) return 'invalid';
|
|
118
|
+
const core = t.slice(from, last + 1);
|
|
119
|
+
|
|
120
|
+
const pre = readAffix(t.slice(0, from), '(', '-+', false);
|
|
121
|
+
const post = readAffix(t.slice(last + 1), ')', '-', true);
|
|
122
|
+
if (!pre || !post) return 'invalid';
|
|
123
|
+
const parens = pre.open + post.open;
|
|
124
|
+
const signs = pre.minus + pre.plus + post.minus;
|
|
125
|
+
if (pre.open > 1 || post.open > 1 || parens === 1 || signs > 1 || (parens && signs)) {
|
|
126
|
+
return 'invalid';
|
|
127
|
+
}
|
|
128
|
+
const negative = opts.allowNegative && (parens === 2 || pre.minus + post.minus === 1);
|
|
129
|
+
|
|
130
|
+
if (!/^[\d.,]+$/.test(core.replace(SPACE_GROUP, ''))) return 'invalid'; // tab, newline, '-', letters
|
|
131
|
+
const { group: lg, decimal: ld } = localeSeparators(opts.locale);
|
|
132
|
+
const count = (c: string) => core.split(c).length - 1;
|
|
133
|
+
const dots = count('.');
|
|
134
|
+
const commas = count(',');
|
|
135
|
+
let dec: string | null = null;
|
|
136
|
+
let grp: string | null = null;
|
|
137
|
+
if (dots && commas) {
|
|
138
|
+
dec = core.lastIndexOf('.') > core.lastIndexOf(',') ? '.' : ',';
|
|
139
|
+
grp = dec === '.' ? ',' : '.';
|
|
140
|
+
if (count(dec) > 1) return 'invalid';
|
|
141
|
+
} else if (dots > 1 || commas > 1) {
|
|
142
|
+
grp = dots ? '.' : ',';
|
|
143
|
+
} else if (dots || commas) {
|
|
144
|
+
const c = dots ? '.' : ',';
|
|
145
|
+
const fracLen = core.length - core.indexOf(c) - 1;
|
|
146
|
+
if (c === ld) dec = c;
|
|
147
|
+
// Numpad-dot rule: in a comma-decimal locale, a lone '.' + 1..precision digits is a decimal.
|
|
148
|
+
else if (
|
|
149
|
+
c === '.' &&
|
|
150
|
+
ld === ',' &&
|
|
151
|
+
opts.precision <= 2 &&
|
|
152
|
+
fracLen >= 1 &&
|
|
153
|
+
fracLen <= opts.precision
|
|
154
|
+
)
|
|
155
|
+
dec = c;
|
|
156
|
+
// Neither the locale's group nor its decimal + exactly 3 digits (ru '1.234'): don't guess.
|
|
157
|
+
else if (c !== lg && fracLen === 3) return 'invalid';
|
|
158
|
+
else if (c === lg || c === '.') grp = c;
|
|
159
|
+
else dec = c;
|
|
160
|
+
// '1,234' / '1.234' as a decimal below precision 3 could equally be grouping: don't guess.
|
|
161
|
+
if (dec && fracLen === 3 && opts.precision < 3) return 'invalid';
|
|
162
|
+
}
|
|
163
|
+
const spaces = new Set(core.match(SPACE_GROUP) ?? []);
|
|
164
|
+
if (spaces.size) {
|
|
165
|
+
if (grp || spaces.size > 1) return 'invalid'; // one group char kind
|
|
166
|
+
grp = [...spaces][0];
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const at = dec ? core.indexOf(dec) : -1;
|
|
170
|
+
const intPart = at < 0 ? core : core.slice(0, at);
|
|
171
|
+
const fracPart = at < 0 ? null : core.slice(at + 1);
|
|
172
|
+
if (fracPart !== null && !/^\d*$/.test(fracPart)) return 'invalid';
|
|
173
|
+
if (grp) {
|
|
174
|
+
const groups = intPart.split(grp);
|
|
175
|
+
if (!/^\d{1,3}$/.test(groups[0]) || !groups.slice(1).every((g) => /^\d{3}$/.test(g))) {
|
|
176
|
+
return 'invalid';
|
|
177
|
+
}
|
|
178
|
+
} else if (!/^\d*$/.test(intPart)) return 'invalid';
|
|
179
|
+
|
|
180
|
+
const int = grp ? intPart.split(grp).join('') : intPart;
|
|
181
|
+
// Full fraction: the caller truncates (whole-value paste) or rejects the overflow (partial paste).
|
|
182
|
+
const frac = fracPart;
|
|
183
|
+
return { negative, int, frac };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Strict parse of the field's OWN text: only the locale group char is stripped and only the
|
|
188
|
+
* locale decimal is a decimal. No cross-locale or numpad guessing.
|
|
189
|
+
*/
|
|
190
|
+
export function parseLocalAmount(
|
|
191
|
+
text: string,
|
|
192
|
+
opts: { locale: string; precision: number; allowNegative: boolean },
|
|
193
|
+
): AmountDraft | null {
|
|
194
|
+
const { group, decimal } = localeSeparators(opts.locale);
|
|
195
|
+
const s = [...text.split(group).join('')]
|
|
196
|
+
.filter((c) => (c >= '0' && c <= '9') || c === decimal || c === '-')
|
|
197
|
+
.join('');
|
|
198
|
+
if (!s) return null;
|
|
199
|
+
const negative = opts.allowNegative && s.startsWith('-');
|
|
200
|
+
return toDraft(s.replace(/-/g, ''), decimal, opts.precision, negative);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function toDraft(s: string, decimal: string, precision: number, negative: boolean) {
|
|
204
|
+
const at = s.indexOf(decimal);
|
|
205
|
+
const digits = (v: string) => v.replace(/\D/g, '');
|
|
206
|
+
const int = digits(at < 0 ? s : s.slice(0, at));
|
|
207
|
+
const frac = at < 0 ? null : digits(s.slice(at + 1)).slice(0, precision);
|
|
208
|
+
if (!int && frac === null && !negative) return null;
|
|
209
|
+
return { negative, int, frac };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Prefix '-' only for a negative with a non-zero digit (never '-0' / '-0.00'). */
|
|
213
|
+
const signed = (negative: boolean, body: string) =>
|
|
214
|
+
(negative && /[1-9]/.test(body) ? '-' : '') + body;
|
|
215
|
+
|
|
216
|
+
export function draftToCanonical(d: AmountDraft): string | null {
|
|
217
|
+
// A lone decimal separator ('.', ',') is a partial draft, not zero (#663).
|
|
218
|
+
if (!d.int && !d.frac) return null;
|
|
219
|
+
const int = d.int.replace(/^0+(?=\d)/, '') || '0';
|
|
220
|
+
const body = `${int}${d.frac ? `.${d.frac}` : ''}`;
|
|
221
|
+
return signed(d.negative, body);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function canonicalToDraft(s: string | null): AmountDraft | null {
|
|
225
|
+
if (s === null || s === '') return null;
|
|
226
|
+
const negative = s.startsWith('-');
|
|
227
|
+
const [int, frac] = (negative ? s.slice(1) : s).split('.');
|
|
228
|
+
// Strip leading zeros so an external '0012.5' displays like typed input would (#663).
|
|
229
|
+
return { negative, int: int.replace(/^0+(?=\d)/, ''), frac: frac ?? null };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function formatDraft(
|
|
233
|
+
d: AmountDraft,
|
|
234
|
+
opts: { locale: string; precision: number; pad: boolean },
|
|
235
|
+
): string {
|
|
236
|
+
const { group, decimal } = localeSeparators(opts.locale);
|
|
237
|
+
const sign = d.negative ? '-' : '';
|
|
238
|
+
// A lone separator shows as itself, not '0.': a synthesized 0 would parse back as an amount (#663).
|
|
239
|
+
if (!d.int && !d.frac) return d.frac === null || opts.precision === 0 ? sign : sign + decimal;
|
|
240
|
+
const int = (d.int || '0').replace(/\B(?=(\d{3})+$)/g, group);
|
|
241
|
+
if (opts.precision === 0) return sign + int;
|
|
242
|
+
let frac = d.frac === null ? null : d.frac.slice(0, opts.precision);
|
|
243
|
+
if (opts.pad) frac = (frac ?? '').padEnd(opts.precision, '0');
|
|
244
|
+
return sign + int + (frac === null ? '' : decimal + frac);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** String half-up (away from zero) rounding; never pads. */
|
|
248
|
+
export function roundAmount(canonical: string, precision: number): string {
|
|
249
|
+
const negative = canonical.startsWith('-');
|
|
250
|
+
const [int, frac = ''] = (negative ? canonical.slice(1) : canonical).split('.');
|
|
251
|
+
if (frac.length <= precision) return signed(negative, canonical.slice(negative ? 1 : 0));
|
|
252
|
+
let n = BigInt(int + frac.slice(0, precision));
|
|
253
|
+
if (frac[precision] >= '5') n += 1n;
|
|
254
|
+
const s = n.toString().padStart(precision + 1, '0');
|
|
255
|
+
const cut = s.length - precision;
|
|
256
|
+
return signed(negative, precision ? `${s.slice(0, cut)}.${s.slice(cut)}` : s);
|
|
257
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// dragAnnouncements.ts — localized screen-reader copy for dnd-kit drags.
|
|
2
|
+
//
|
|
3
|
+
// dnd-kit's built-in announcements are hard-coded English AND interpolate raw
|
|
4
|
+
// ids ("Draggable item deal-7 was moved over droppable area col-3"), which is
|
|
5
|
+
// both a Hard rule 9 violation and useless to a listener. Every `<DndContext>`
|
|
6
|
+
// in the library passes `accessibility={useDragAccessibility(...)}` instead.
|
|
7
|
+
//
|
|
8
|
+
// Internal — not exported from `src/index.ts`.
|
|
9
|
+
import { useMemo, useRef, type RefObject } from 'react';
|
|
10
|
+
import type { Active, Announcements, ScreenReaderInstructions } from '@dnd-kit/core';
|
|
11
|
+
import { useTranslation } from '../../i18n';
|
|
12
|
+
|
|
13
|
+
/** Collapse whitespace and cap the length so an announcement stays listenable. */
|
|
14
|
+
export function tidy(text: string): string {
|
|
15
|
+
const flat = text.replace(/\s+/g, ' ').trim();
|
|
16
|
+
return flat.length > 80 ? `${flat.slice(0, 79)}…` : flat;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* What a draggable publishes on its dnd-kit `data` so the announcements can
|
|
21
|
+
* name it. Read with `dragLabelOf`.
|
|
22
|
+
*/
|
|
23
|
+
export interface DragLabelData {
|
|
24
|
+
/** Consumer's explicit `aria-label`. Wins outright when set. */
|
|
25
|
+
dragLabel?: string;
|
|
26
|
+
/** The rendered node to read text from when there is no explicit label. */
|
|
27
|
+
dragNode?: RefObject<HTMLElement | null>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The name to announce for a draggable: the consumer's `aria-label` if there is
|
|
32
|
+
* one, else the node's rendered text.
|
|
33
|
+
*
|
|
34
|
+
* Reading the DOM rather than walking the React children is deliberate. A card
|
|
35
|
+
* with a `<DropdownMenu>` / `<Tooltip>` / `<ConfirmationPopover>` in it has the
|
|
36
|
+
* closed panel's contents in its children tree but NOT in the document, so a
|
|
37
|
+
* children walk announces "Draft Q3 OKRs View Archive" while the DOM announces
|
|
38
|
+
* "Draft Q3 OKRs". Collapsed and portalled subtrees drop out by construction.
|
|
39
|
+
*/
|
|
40
|
+
export function dragLabelOf(data: Record<string, unknown> | undefined): string | undefined {
|
|
41
|
+
const { dragLabel, dragNode } = (data ?? {}) as DragLabelData;
|
|
42
|
+
if (typeof dragLabel === 'string' && dragLabel.trim()) return tidy(dragLabel);
|
|
43
|
+
const node = dragNode?.current;
|
|
44
|
+
if (!node) return undefined;
|
|
45
|
+
const text = tidy(domText(node));
|
|
46
|
+
return text || undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* `textContent` for announcements: separates element boundaries with a space
|
|
51
|
+
* (raw `textContent` glues siblings — "Acme Corp$50,000") and skips
|
|
52
|
+
* `aria-hidden` subtrees, which are decoration a screen reader is already told
|
|
53
|
+
* to ignore.
|
|
54
|
+
*/
|
|
55
|
+
function domText(el: Element): string {
|
|
56
|
+
let out = '';
|
|
57
|
+
for (const child of el.childNodes) {
|
|
58
|
+
if (child.nodeType === 3) out += child.nodeValue ?? '';
|
|
59
|
+
else if (child.nodeType === 1 && (child as Element).getAttribute('aria-hidden') !== 'true')
|
|
60
|
+
out += ` ${domText(child as Element)}`;
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The accessible name a consumer gave a container (a Kanban column, a
|
|
67
|
+
* SortableGroup list) — `aria-label`, or the text of whatever `aria-labelledby`
|
|
68
|
+
* points at, since naming a column by its visible `<Title>` is the natural
|
|
69
|
+
* choice. Returns undefined when neither is set; the caller falls back to a
|
|
70
|
+
* positional stand-in.
|
|
71
|
+
*/
|
|
72
|
+
export function containerName(props: {
|
|
73
|
+
'aria-label'?: string;
|
|
74
|
+
'aria-labelledby'?: string;
|
|
75
|
+
}): string | undefined {
|
|
76
|
+
const label = props['aria-label'];
|
|
77
|
+
if (typeof label === 'string' && label.trim()) return tidy(label);
|
|
78
|
+
const ids = props['aria-labelledby'];
|
|
79
|
+
if (!ids || typeof document === 'undefined') return undefined;
|
|
80
|
+
const text = ids
|
|
81
|
+
.split(/\s+/)
|
|
82
|
+
.map((id) => document.getElementById(id)?.textContent ?? '')
|
|
83
|
+
.join(' ');
|
|
84
|
+
return text.trim() ? tidy(text) : undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** The `active` / `over` shape dnd-kit hands to an announcement callback. */
|
|
88
|
+
export type DragEntry = Pick<Active, 'id' | 'data'>;
|
|
89
|
+
|
|
90
|
+
/** What a component knows about the slot an id occupies (or would land in). */
|
|
91
|
+
export interface DragTarget {
|
|
92
|
+
/** Human name. Empty / omitted → the message says "the item" instead. */
|
|
93
|
+
label?: string;
|
|
94
|
+
/** 1-based slot within `container`. */
|
|
95
|
+
index: number;
|
|
96
|
+
/** Number of slots in `container`, counting the incoming item. */
|
|
97
|
+
total: number;
|
|
98
|
+
/** Human name of the list the slot belongs to. Omit in single-list components. */
|
|
99
|
+
container?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Default `describe`: the name from `dragLabelOf`, plus the index / items
|
|
104
|
+
* `useSortable` already publishes under `data.sortable`. Returns `null` for
|
|
105
|
+
* anything that is not a sortable item (including a missing entry).
|
|
106
|
+
*/
|
|
107
|
+
export function sortableTarget(entry: DragEntry | null): DragTarget | null {
|
|
108
|
+
const data = entry?.data.current;
|
|
109
|
+
const sortable = data?.sortable as { index: number; items: unknown[] } | undefined;
|
|
110
|
+
if (!sortable || sortable.index < 0) return null;
|
|
111
|
+
return {
|
|
112
|
+
label: dragLabelOf(data),
|
|
113
|
+
index: sortable.index + 1,
|
|
114
|
+
total: sortable.items.length,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Describes the slot an `active` / `over` entry names. `activeId` is passed so
|
|
120
|
+
* a container droppable can answer "where would THIS card land in me" — the
|
|
121
|
+
* multi-list components need it to position a drop onto an empty column.
|
|
122
|
+
*
|
|
123
|
+
* `entry` is null when dnd-kit resolved no `over` at all. Most components
|
|
124
|
+
* return null straight back; a component whose drop has its OWN fallback for
|
|
125
|
+
* that case (DataTable's last-resolved band slot, #383) must answer with that
|
|
126
|
+
* slot here too, or it announces "nothing moved" about a real reorder.
|
|
127
|
+
*/
|
|
128
|
+
export type DescribeDragTarget = (
|
|
129
|
+
entry: DragEntry | null,
|
|
130
|
+
activeId: Active['id'],
|
|
131
|
+
) => DragTarget | null;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Build the `accessibility` prop for a `<DndContext>`: localized announcements
|
|
135
|
+
* for the whole drag lifecycle plus localized keyboard instructions.
|
|
136
|
+
*
|
|
137
|
+
* @param describe Resolves an entry (or `null` when there is no `over`) to a
|
|
138
|
+
* human slot. Return `null` when nothing would land anywhere
|
|
139
|
+
* — that announces "not over a drop target" / "nothing
|
|
140
|
+
* moved".
|
|
141
|
+
* @param isRejectedDrop Optional. Consulted on drag end BEFORE `over`: return
|
|
142
|
+
* `true` when the component refuses to commit the release, so
|
|
143
|
+
* it announces a cancel rather than a drop that never
|
|
144
|
+
* happened (Kanban's outside-the-board release, #390).
|
|
145
|
+
*/
|
|
146
|
+
export function useDragAccessibility(
|
|
147
|
+
describe: DescribeDragTarget,
|
|
148
|
+
isRejectedDrop?: () => boolean,
|
|
149
|
+
): { announcements: Announcements; screenReaderInstructions: ScreenReaderInstructions } {
|
|
150
|
+
const t = useTranslation();
|
|
151
|
+
|
|
152
|
+
// Latched during render so the returned object can stay stable across the
|
|
153
|
+
// re-renders a live drag causes (dnd-kit re-subscribes its monitor listener
|
|
154
|
+
// whenever `announcements` changes identity). Both writes are idempotent —
|
|
155
|
+
// a StrictMode double render stores the same functions.
|
|
156
|
+
const describeRef = useRef(describe);
|
|
157
|
+
describeRef.current = describe;
|
|
158
|
+
const rejectedRef = useRef(isRejectedDrop);
|
|
159
|
+
rejectedRef.current = isRejectedDrop;
|
|
160
|
+
|
|
161
|
+
return useMemo(() => {
|
|
162
|
+
const nameOf = (entry: DragEntry, activeId: Active['id']) =>
|
|
163
|
+
describeRef.current(entry, activeId)?.label || t('drag.unnamed');
|
|
164
|
+
|
|
165
|
+
const at = (
|
|
166
|
+
key: 'movedOver' | 'dropped',
|
|
167
|
+
item: string,
|
|
168
|
+
target: DragTarget,
|
|
169
|
+
): string | undefined => {
|
|
170
|
+
const { index, total, container } = target;
|
|
171
|
+
return container == null
|
|
172
|
+
? t(`drag.${key}`, { item, index, total })
|
|
173
|
+
: t(key === 'movedOver' ? 'drag.movedOverIn' : 'drag.droppedIn', {
|
|
174
|
+
item,
|
|
175
|
+
index,
|
|
176
|
+
total,
|
|
177
|
+
container,
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
announcements: {
|
|
183
|
+
onDragStart: ({ active }) => t('drag.pickedUp', { item: nameOf(active, active.id) }),
|
|
184
|
+
onDragOver: ({ active, over }) => {
|
|
185
|
+
const item = nameOf(active, active.id);
|
|
186
|
+
const target = describeRef.current(over, active.id);
|
|
187
|
+
return target ? at('movedOver', item, target) : t('drag.movedOutside', { item });
|
|
188
|
+
},
|
|
189
|
+
onDragEnd: ({ active, over }) => {
|
|
190
|
+
const item = nameOf(active, active.id);
|
|
191
|
+
if (rejectedRef.current?.()) return t('drag.cancelled', { item });
|
|
192
|
+
const target = describeRef.current(over, active.id);
|
|
193
|
+
return target ? at('dropped', item, target) : t('drag.droppedNowhere', { item });
|
|
194
|
+
},
|
|
195
|
+
onDragCancel: ({ active }) => t('drag.cancelled', { item: nameOf(active, active.id) }),
|
|
196
|
+
} satisfies Announcements,
|
|
197
|
+
screenReaderInstructions: { draggable: t('drag.instructions') },
|
|
198
|
+
};
|
|
199
|
+
}, [t]);
|
|
200
|
+
}
|