@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,433 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useEffect,
|
|
4
|
+
useId,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
type ChangeEvent,
|
|
9
|
+
type ClipboardEvent,
|
|
10
|
+
type DragEvent,
|
|
11
|
+
type HTMLAttributes,
|
|
12
|
+
type KeyboardEvent,
|
|
13
|
+
} from 'react';
|
|
14
|
+
import clsx from 'clsx';
|
|
15
|
+
import { CurrencySelect } from '../CurrencySelect';
|
|
16
|
+
import { Input } from '../Input';
|
|
17
|
+
import { useLocale, useTranslation } from '../../i18n';
|
|
18
|
+
import {
|
|
19
|
+
canonicalToDraft,
|
|
20
|
+
currencyDisplayText,
|
|
21
|
+
currencyName,
|
|
22
|
+
currencyPrecision,
|
|
23
|
+
draftToCanonical,
|
|
24
|
+
formatDraft,
|
|
25
|
+
isValidCurrency,
|
|
26
|
+
localeSeparators,
|
|
27
|
+
parseAmount,
|
|
28
|
+
parseLocalAmount,
|
|
29
|
+
roundAmount,
|
|
30
|
+
type AmountDraft,
|
|
31
|
+
type CurrencyDisplay,
|
|
32
|
+
} from '../_internal/currency';
|
|
33
|
+
import styles from './MoneyInput.module.scss';
|
|
34
|
+
|
|
35
|
+
/** MoneyInput size — passed through to the picker + Input. */
|
|
36
|
+
export type MoneyInputSize = 'sm' | 'md' | 'lg';
|
|
37
|
+
|
|
38
|
+
/** `amount` is a canonical decimal string (`"1234.50"`, `"-3"`), never a JS number; `null` = empty. */
|
|
39
|
+
export interface MoneyValue {
|
|
40
|
+
amount: string | null;
|
|
41
|
+
currency: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MoneyInputProps extends Omit<
|
|
45
|
+
HTMLAttributes<HTMLDivElement>,
|
|
46
|
+
'onChange' | 'defaultValue'
|
|
47
|
+
> {
|
|
48
|
+
/** Controlled value. `amount` is a canonical decimal string or `null`; `currency` an ISO 4217 code. */
|
|
49
|
+
value: MoneyValue;
|
|
50
|
+
/** Fires on every amount edit and currency switch. Never fires for blur-without-edit or external value changes. */
|
|
51
|
+
onChange: (value: MoneyValue) => void;
|
|
52
|
+
/** ISO 4217 codes to offer. Exactly one renders a static prefix instead of a picker. */
|
|
53
|
+
currencies: string[];
|
|
54
|
+
/** How the selected currency renders: `"code"` (default), `"symbol"` or `"both"`. */
|
|
55
|
+
currencyDisplay?: CurrencyDisplay;
|
|
56
|
+
/** Overrides the currency picker's accessible name (default: "<group label> Currency"). */
|
|
57
|
+
currencyLabel?: string;
|
|
58
|
+
/** Allow a leading minus. Default `false`. */
|
|
59
|
+
allowNegative?: boolean;
|
|
60
|
+
/** BCP-47 locale for separators and currency names. Defaults to the i18n locale. */
|
|
61
|
+
locale?: string;
|
|
62
|
+
/** Control size, forwarded to both controls. Default `"md"`. */
|
|
63
|
+
size?: MoneyInputSize;
|
|
64
|
+
/** Error chrome on both controls. */
|
|
65
|
+
invalid?: boolean;
|
|
66
|
+
/** Disable both controls. */
|
|
67
|
+
disabled?: boolean;
|
|
68
|
+
/** Make both controls read-only. */
|
|
69
|
+
readOnly?: boolean;
|
|
70
|
+
/** Mark the amount required. */
|
|
71
|
+
required?: boolean;
|
|
72
|
+
/** Placeholder for the amount field. */
|
|
73
|
+
placeholder?: string;
|
|
74
|
+
/** Emits hidden `<name>` (canonical amount) and `<name>_currency` inputs for native form posts. */
|
|
75
|
+
name?: string;
|
|
76
|
+
/** Stable id; placed on the amount field so an external `<label htmlFor>` focuses it. */
|
|
77
|
+
id?: string;
|
|
78
|
+
/** Accessible name when used STANDALONE (outside `<Field>`). */
|
|
79
|
+
'aria-label'?: string;
|
|
80
|
+
/** Ids of elements labelling the group (injected by `<Field>`). */
|
|
81
|
+
'aria-labelledby'?: string;
|
|
82
|
+
/** Ids of description/error elements; forwarded to the amount field (injected by `<Field>`). */
|
|
83
|
+
'aria-describedby'?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const FALLBACK_PRECISION = 2;
|
|
87
|
+
const CANONICAL = /^-?\d+(\.\d+)?$/;
|
|
88
|
+
|
|
89
|
+
/** Pads a canonical amount's fraction to `prec` digits (`"13"` → `"13.00"`). */
|
|
90
|
+
const padCanonical = (amount: string, prec: number) => {
|
|
91
|
+
const [int, frac = ''] = amount.split('.');
|
|
92
|
+
return prec ? `${int}.${frac.padEnd(prec, '0')}` : int;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Money field: a currency picker plus a formatted decimal-string amount.
|
|
97
|
+
* @see docs/components/MoneyInput.md
|
|
98
|
+
*/
|
|
99
|
+
export const MoneyInput = forwardRef<HTMLDivElement, MoneyInputProps>(function MoneyInput(
|
|
100
|
+
{
|
|
101
|
+
value,
|
|
102
|
+
onChange,
|
|
103
|
+
currencies,
|
|
104
|
+
currencyDisplay = 'code',
|
|
105
|
+
currencyLabel,
|
|
106
|
+
allowNegative = false,
|
|
107
|
+
locale,
|
|
108
|
+
size = 'md',
|
|
109
|
+
invalid,
|
|
110
|
+
disabled,
|
|
111
|
+
readOnly,
|
|
112
|
+
required,
|
|
113
|
+
placeholder,
|
|
114
|
+
name,
|
|
115
|
+
id,
|
|
116
|
+
'aria-label': ariaLabel,
|
|
117
|
+
'aria-labelledby': ariaLabelledby,
|
|
118
|
+
'aria-describedby': ariaDescribedby,
|
|
119
|
+
className,
|
|
120
|
+
...rest
|
|
121
|
+
},
|
|
122
|
+
ref,
|
|
123
|
+
) {
|
|
124
|
+
const t = useTranslation();
|
|
125
|
+
const appLocale = useLocale();
|
|
126
|
+
const loc = locale ?? appLocale;
|
|
127
|
+
const uid = useId();
|
|
128
|
+
const currencyWordId = `${uid}-currency`;
|
|
129
|
+
const nameId = `${uid}-name`;
|
|
130
|
+
|
|
131
|
+
const valueCurrency = value.currency;
|
|
132
|
+
// Ruling B: a value currency outside `currencies` still shows in the picker (never emitted).
|
|
133
|
+
const outside = isValidCurrency(valueCurrency) && !currencies.includes(valueCurrency);
|
|
134
|
+
const offered = useMemo(
|
|
135
|
+
() => (outside ? [...currencies, valueCurrency] : currencies),
|
|
136
|
+
[outside, currencies, valueCurrency],
|
|
137
|
+
);
|
|
138
|
+
const single = offered.length === 1 && isValidCurrency(offered[0]);
|
|
139
|
+
// Single mode shows offered[0] as a static prefix, so an invalid value.currency ('') must not
|
|
140
|
+
// be emitted/posted behind it: offered[0] is the effective currency.
|
|
141
|
+
const currency = single ? offered[0] : valueCurrency;
|
|
142
|
+
const replaced = currency !== valueCurrency;
|
|
143
|
+
useEffect(() => {
|
|
144
|
+
if (process.env.NODE_ENV === 'production') return;
|
|
145
|
+
if (outside)
|
|
146
|
+
console.warn(`<MoneyInput>: value.currency "${valueCurrency}" is not in \`currencies\`.`);
|
|
147
|
+
if (replaced)
|
|
148
|
+
console.warn(
|
|
149
|
+
`<MoneyInput>: value.currency "${valueCurrency}" is invalid; using "${currency}".`,
|
|
150
|
+
);
|
|
151
|
+
}, [outside, replaced, valueCurrency, currency]);
|
|
152
|
+
const precision = isValidCurrency(currency) ? currencyPrecision(currency) : FALLBACK_PRECISION;
|
|
153
|
+
|
|
154
|
+
const malformed = value.amount !== null && !CANONICAL.test(value.amount);
|
|
155
|
+
useEffect(() => {
|
|
156
|
+
if (malformed && process.env.NODE_ENV !== 'production') {
|
|
157
|
+
console.warn(
|
|
158
|
+
`<MoneyInput>: value.amount "${value.amount}" is not a canonical decimal string.`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}, [malformed, value.amount]);
|
|
162
|
+
|
|
163
|
+
const display = (amount: string | null, prec: number, l: string) => {
|
|
164
|
+
// Malformed amounts display empty; over-precise ones display rounded. Neither is emitted.
|
|
165
|
+
if (amount === null || !CANONICAL.test(amount)) return '';
|
|
166
|
+
const d = canonicalToDraft(roundAmount(amount, prec));
|
|
167
|
+
return d ? formatDraft(d, { locale: l, precision: prec, pad: true }) : '';
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const [text, setText] = useState(() => display(value.amount, precision, loc));
|
|
171
|
+
// What we last emitted/displayed for; our own echoes must not resync (and clobber typing).
|
|
172
|
+
const synced = useRef({ amount: value.amount, currency, locale: loc });
|
|
173
|
+
const dirty = useRef(false);
|
|
174
|
+
const amountRef = useRef<HTMLInputElement>(null);
|
|
175
|
+
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
const s = synced.current;
|
|
178
|
+
if (s.amount === value.amount && s.currency === currency && s.locale === loc) return;
|
|
179
|
+
synced.current = { amount: value.amount, currency, locale: loc };
|
|
180
|
+
setText(display(value.amount, precision, loc));
|
|
181
|
+
}, [value.amount, currency, loc, precision]);
|
|
182
|
+
|
|
183
|
+
const emit = (amount: string | null, cur: string) => {
|
|
184
|
+
synced.current = { amount, currency: cur, locale: loc };
|
|
185
|
+
onChange({ amount, currency: cur });
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const { group, decimal } = localeSeparators(loc);
|
|
189
|
+
// Our own text is strictly own-locale: group chars are never decimals (de '1.23' stays 123).
|
|
190
|
+
// An existing sign survives edits even when negatives are off; only ADDING a '-' is rejected.
|
|
191
|
+
const parseOwn = (s: string) =>
|
|
192
|
+
parseLocalAmount(s, {
|
|
193
|
+
locale: loc,
|
|
194
|
+
precision,
|
|
195
|
+
allowNegative: allowNegative || text.startsWith('-'),
|
|
196
|
+
});
|
|
197
|
+
const isSignificant = (c: string) => (c >= '0' && c <= '9') || c === decimal || c === '-';
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Shared edit path. Writes the DOM value + caret directly so React's controlled-value
|
|
201
|
+
* reconciliation finds nothing to change and never throws the caret to the end.
|
|
202
|
+
*/
|
|
203
|
+
const applyEdit = (input: HTMLInputElement, raw: string, caret: number, inserted = false) => {
|
|
204
|
+
const prev = text;
|
|
205
|
+
const typed = !inserted && raw.length === prev.length + 1;
|
|
206
|
+
const count = (str: string, c: string) => str.split(c).length - 1;
|
|
207
|
+
const fracDigitsOf = (str: string) =>
|
|
208
|
+
str.includes(decimal) ? str.slice(str.indexOf(decimal) + 1).replace(/\D/g, '').length : 0;
|
|
209
|
+
// A digit typed inside a full fraction overwrites the next digit ('12.|00' + '5' → '12.5|0').
|
|
210
|
+
if (
|
|
211
|
+
typed &&
|
|
212
|
+
count(raw, decimal) === 1 &&
|
|
213
|
+
fracDigitsOf(raw) > precision &&
|
|
214
|
+
/\d/.test(raw[caret - 1]) &&
|
|
215
|
+
caret - 1 > raw.indexOf(decimal) &&
|
|
216
|
+
/\d/.test(raw[caret] ?? '')
|
|
217
|
+
) {
|
|
218
|
+
raw = raw.slice(0, caret) + raw.slice(caret + 1);
|
|
219
|
+
}
|
|
220
|
+
// Ruling D: ADDING a '-' when negatives are off rejects the edit (typed or pasted), never drops the sign.
|
|
221
|
+
const unsignedOnly = !allowNegative && count(raw, '-') > count(prev, '-');
|
|
222
|
+
const decimals = count(raw, decimal);
|
|
223
|
+
const dash = raw.indexOf('-');
|
|
224
|
+
const fracDigits = fracDigitsOf(raw);
|
|
225
|
+
const reject =
|
|
226
|
+
unsignedOnly ||
|
|
227
|
+
((typed || inserted) &&
|
|
228
|
+
(decimals > 1 || (dash !== -1 && (dash !== 0 || raw.lastIndexOf('-') !== 0)))) ||
|
|
229
|
+
(typed && decimals === 1 && fracDigits > precision);
|
|
230
|
+
if (reject) {
|
|
231
|
+
// Back to where the insertion started (caret - 1 for a typed char).
|
|
232
|
+
const back = Math.max(0, caret - Math.max(0, raw.length - prev.length));
|
|
233
|
+
input.value = prev;
|
|
234
|
+
input.setSelectionRange(back, back);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
dirty.current = true;
|
|
238
|
+
// `raw` is always own-locale here: pastes/drops are normalised in insertText first.
|
|
239
|
+
const draft = parseOwn(raw);
|
|
240
|
+
const next = draft ? formatDraft(draft, { locale: loc, precision, pad: false }) : '';
|
|
241
|
+
// Caret lands after the same count of significant chars (digits, decimal, '-') it followed in `raw`.
|
|
242
|
+
const before = raw.slice(0, caret);
|
|
243
|
+
let n = [...before].filter(isSignificant).length;
|
|
244
|
+
// formatDraft synthesizes a '0' for a missing integer part ('.' → '0.'); step over it too.
|
|
245
|
+
if (draft && !draft.int && draft.frac !== null && before.includes(decimal)) n++;
|
|
246
|
+
let pos = 0;
|
|
247
|
+
while (n > 0 && pos < next.length) if (isSignificant(next[pos++])) n--;
|
|
248
|
+
input.value = next;
|
|
249
|
+
input.setSelectionRange(pos, pos);
|
|
250
|
+
setText(next);
|
|
251
|
+
const amount = draft ? draftToCanonical(draft) : null;
|
|
252
|
+
if (amount !== synced.current.amount) emit(amount, currency);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Paste/drop: parse ONLY the incoming segment leniently (cross-locale separators, sign forms),
|
|
257
|
+
* rewrite it as own-locale plain text, splice it over the selection and run the own-locale path.
|
|
258
|
+
* Own formatted text never meets the lenient parser, so a group dot can't become a decimal.
|
|
259
|
+
*/
|
|
260
|
+
const insertText = (input: HTMLInputElement, segment: string) => {
|
|
261
|
+
if (readOnly) return;
|
|
262
|
+
// When in doubt, reject (no change, no emit) rather than guess.
|
|
263
|
+
const d = parseAmount(segment, { locale: loc, precision, allowNegative: true });
|
|
264
|
+
if (!d || d === 'invalid') return;
|
|
265
|
+
const start = input.selectionStart ?? text.length;
|
|
266
|
+
const end = input.selectionEnd ?? text.length;
|
|
267
|
+
const whole = start === 0 && end === text.length; // also true for an empty field
|
|
268
|
+
// A negative must replace the whole value, and only where a sign is allowed (never dropped silently).
|
|
269
|
+
if (d.negative && (!whole || (!allowNegative && !text.startsWith('-')))) return;
|
|
270
|
+
const own = (d.negative ? '-' : '') + d.int + (d.frac === null ? '' : decimal + d.frac);
|
|
271
|
+
const raw = text.slice(0, start) + own + text.slice(end);
|
|
272
|
+
// A partial paste must not overflow the fraction (it would silently drop digits).
|
|
273
|
+
const at = raw.indexOf(decimal);
|
|
274
|
+
if (!whole && at >= 0 && raw.slice(at + 1).replace(/\D/g, '').length > precision) return;
|
|
275
|
+
applyEdit(input, raw, start + own.length, true);
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
const onAmountPaste = (e: ClipboardEvent<HTMLInputElement>) => {
|
|
279
|
+
e.preventDefault();
|
|
280
|
+
insertText(e.currentTarget, e.clipboardData.getData('text/plain'));
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// ponytail: drop inserts at the current selection, not the pointer position.
|
|
284
|
+
const onAmountDrop = (e: DragEvent<HTMLInputElement>) => {
|
|
285
|
+
e.preventDefault();
|
|
286
|
+
insertText(e.currentTarget, e.dataTransfer.getData('text/plain'));
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// Typed / deleted / cut / undo edits only: own-locale, never lenient.
|
|
290
|
+
const onAmountChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
291
|
+
const input = e.target;
|
|
292
|
+
applyEdit(input, input.value, input.selectionStart ?? input.value.length);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const onAmountKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
|
296
|
+
const input = e.currentTarget;
|
|
297
|
+
const { selectionStart: start, selectionEnd: end, value: v } = input;
|
|
298
|
+
if (readOnly || start === null || end === null) return;
|
|
299
|
+
if (start === end) {
|
|
300
|
+
// Step over a group separator — or a decimal with a fraction after it (deleting that would
|
|
301
|
+
// scale the amount 10^n) — so the deletion hits the digit beyond it.
|
|
302
|
+
const stepOver = (i: number) => v[i] === group || (v[i] === decimal && i + 1 < v.length);
|
|
303
|
+
if (e.key === 'Backspace' && stepOver(start - 1))
|
|
304
|
+
input.setSelectionRange(start - 1, start - 1);
|
|
305
|
+
if (e.key === 'Delete' && stepOver(start)) input.setSelectionRange(start + 1, start + 1);
|
|
306
|
+
}
|
|
307
|
+
// Numpad '.' in a comma-decimal locale types the decimal (any precision).
|
|
308
|
+
if (e.key === '.' && decimal !== '.' && !v.includes(decimal)) {
|
|
309
|
+
e.preventDefault();
|
|
310
|
+
applyEdit(input, v.slice(0, start) + decimal + v.slice(end), start + 1);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const onBlur = () => {
|
|
315
|
+
const draft = parseOwn(text);
|
|
316
|
+
const canonical = draft ? draftToCanonical(draft) : null;
|
|
317
|
+
if (!draft || canonical === null) {
|
|
318
|
+
setText('');
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const padded: AmountDraft = {
|
|
322
|
+
...draft,
|
|
323
|
+
frac: precision ? (draft.frac ?? '').padEnd(precision, '0') : null,
|
|
324
|
+
};
|
|
325
|
+
setText(formatDraft(padded, { locale: loc, precision, pad: true }));
|
|
326
|
+
const amount = draftToCanonical(padded);
|
|
327
|
+
if (dirty.current && amount !== synced.current.amount) emit(amount, currency);
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const onCurrencyChange = (code: string | null) => {
|
|
331
|
+
if (!code) return;
|
|
332
|
+
const prec = currencyPrecision(code);
|
|
333
|
+
let amount = value.amount;
|
|
334
|
+
if (amount !== null && CANONICAL.test(amount)) {
|
|
335
|
+
amount = roundAmount(amount, prec);
|
|
336
|
+
// Ruling E: unfocused → padded canonical, matching what blur would emit for the same display.
|
|
337
|
+
if (document.activeElement !== amountRef.current) amount = padCanonical(amount, prec);
|
|
338
|
+
}
|
|
339
|
+
setText(display(amount, prec, loc));
|
|
340
|
+
emit(amount, code);
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const currencyWord = t('moneyInput.currencyLabel');
|
|
344
|
+
const currencyNaming = currencyLabel
|
|
345
|
+
? { 'aria-label': currencyLabel }
|
|
346
|
+
: ariaLabelledby
|
|
347
|
+
? { 'aria-labelledby': `${ariaLabelledby} ${currencyWordId}` }
|
|
348
|
+
: { 'aria-label': ariaLabel ? `${ariaLabel} ${currencyWord}` : currencyWord };
|
|
349
|
+
|
|
350
|
+
const describedBy = [ariaDescribedby, single ? nameId : undefined].filter(Boolean).join(' ');
|
|
351
|
+
|
|
352
|
+
return (
|
|
353
|
+
<div
|
|
354
|
+
// {...rest} first so the component's structural ARIA contract
|
|
355
|
+
// (role=group + the resolved labelledby/label) can't be clobbered.
|
|
356
|
+
{...rest}
|
|
357
|
+
ref={ref}
|
|
358
|
+
className={clsx(styles.root, className)}
|
|
359
|
+
role="group"
|
|
360
|
+
aria-label={ariaLabelledby ? undefined : ariaLabel}
|
|
361
|
+
aria-labelledby={ariaLabelledby}
|
|
362
|
+
>
|
|
363
|
+
<span id={currencyWordId} hidden>
|
|
364
|
+
{currencyWord}
|
|
365
|
+
</span>
|
|
366
|
+
{single ? (
|
|
367
|
+
<>
|
|
368
|
+
<span
|
|
369
|
+
aria-hidden="true"
|
|
370
|
+
className={clsx(
|
|
371
|
+
styles.prefix,
|
|
372
|
+
styles[`prefix-${size}`],
|
|
373
|
+
invalid && styles['prefix-invalid'],
|
|
374
|
+
disabled && styles['prefix-disabled'],
|
|
375
|
+
)}
|
|
376
|
+
>
|
|
377
|
+
{currencyDisplayText(offered[0], currencyDisplay, loc)}
|
|
378
|
+
</span>
|
|
379
|
+
<span id={nameId} hidden>
|
|
380
|
+
{currencyName(offered[0], loc)}
|
|
381
|
+
</span>
|
|
382
|
+
</>
|
|
383
|
+
) : (
|
|
384
|
+
<CurrencySelect
|
|
385
|
+
className={styles.currency}
|
|
386
|
+
currencies={offered}
|
|
387
|
+
currencyDisplay={currencyDisplay}
|
|
388
|
+
locale={loc}
|
|
389
|
+
value={currency}
|
|
390
|
+
onChange={onCurrencyChange}
|
|
391
|
+
clearable={false}
|
|
392
|
+
selectOnOpen
|
|
393
|
+
size={size}
|
|
394
|
+
invalid={invalid}
|
|
395
|
+
disabled={disabled}
|
|
396
|
+
readOnly={readOnly}
|
|
397
|
+
{...currencyNaming}
|
|
398
|
+
placeholder={t('currencySelect.search')}
|
|
399
|
+
/>
|
|
400
|
+
)}
|
|
401
|
+
<Input
|
|
402
|
+
ref={amountRef}
|
|
403
|
+
className={styles.amount}
|
|
404
|
+
id={id}
|
|
405
|
+
inputMode={allowNegative ? 'text' : 'decimal'}
|
|
406
|
+
autoComplete="off"
|
|
407
|
+
value={text}
|
|
408
|
+
onChange={onAmountChange}
|
|
409
|
+
onKeyDown={onAmountKeyDown}
|
|
410
|
+
onPaste={onAmountPaste}
|
|
411
|
+
onDrop={onAmountDrop}
|
|
412
|
+
onFocus={() => {
|
|
413
|
+
dirty.current = false;
|
|
414
|
+
}}
|
|
415
|
+
onBlur={onBlur}
|
|
416
|
+
size={size}
|
|
417
|
+
invalid={invalid}
|
|
418
|
+
disabled={disabled}
|
|
419
|
+
readOnly={readOnly}
|
|
420
|
+
required={required}
|
|
421
|
+
aria-label={t('moneyInput.amountLabel')}
|
|
422
|
+
aria-describedby={describedBy || undefined}
|
|
423
|
+
placeholder={placeholder}
|
|
424
|
+
/>
|
|
425
|
+
{name && (
|
|
426
|
+
<>
|
|
427
|
+
<input type="hidden" name={name} value={value.amount ?? ''} />
|
|
428
|
+
<input type="hidden" name={`${name}_currency`} value={currency} />
|
|
429
|
+
</>
|
|
430
|
+
)}
|
|
431
|
+
</div>
|
|
432
|
+
);
|
|
433
|
+
});
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
@use '../../styles/mixins' as *;
|
|
2
|
+
@use './OptionsPicker.tokens';
|
|
3
|
+
|
|
4
|
+
// Override Popover.Content's default padding — the picker manages its own
|
|
5
|
+
// section padding internally (searchBar, list rows, footer each have their
|
|
6
|
+
// own space-2 padding) so the sections stay flush to the left/right edges.
|
|
7
|
+
// Vertical inset only: the Popover arrow (a 12px square rotated 45deg, centered
|
|
8
|
+
// on the panel edge) pokes its inner tip ~8px into the panel, so without
|
|
9
|
+
// top/bottom clearance it overlaps the (focused) search input or the footer
|
|
10
|
+
// buttons. space-1 here + each section's own space-2 = space-3, which matches
|
|
11
|
+
// the Popover's default --popover-padding (the arrow's intended clearance).
|
|
12
|
+
.panel {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
min-width: var(--options-picker-panel-min-width);
|
|
16
|
+
max-width: var(--options-picker-panel-max-width);
|
|
17
|
+
padding: var(--space-1) 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.list {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
max-height: var(--options-picker-list-max-height);
|
|
24
|
+
overflow-y: auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.row {
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
gap: var(--options-picker-row-gap);
|
|
31
|
+
padding: var(--options-picker-row-padding);
|
|
32
|
+
border-radius: var(--options-picker-row-radius);
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
user-select: none;
|
|
35
|
+
|
|
36
|
+
&:hover {
|
|
37
|
+
background: var(--options-picker-row-bg-hover);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.rowSelected {
|
|
42
|
+
background: var(--options-picker-row-bg-selected);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.searchBar {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: var(--options-picker-search-gap);
|
|
49
|
+
padding: var(--options-picker-search-padding);
|
|
50
|
+
border-bottom: var(--border-width) solid var(--options-picker-search-border-color);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.searchIcon {
|
|
54
|
+
color: var(--options-picker-search-icon-fg);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Rule 4 note: internal flex layout — the public component is the panel,
|
|
58
|
+
// not the input. The picker owns the search bar's internal arrangement.
|
|
59
|
+
.searchInput {
|
|
60
|
+
flex: 1;
|
|
61
|
+
border: none;
|
|
62
|
+
background: transparent;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.count {
|
|
66
|
+
flex-shrink: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.footer {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: space-between;
|
|
73
|
+
gap: var(--options-picker-footer-gap);
|
|
74
|
+
padding: var(--options-picker-footer-padding);
|
|
75
|
+
border-top: var(--border-width) solid var(--options-picker-footer-border-color);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.group {
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Grid layout so the label stays left-aligned next to the dot and the
|
|
84
|
+
// hint floats to the right column. `justify-content: space-between` on a
|
|
85
|
+
// flex parent would put the label in the visual middle.
|
|
86
|
+
// Taller header so group sections read as visually distinct from the rows
|
|
87
|
+
// they label. The list itself is tightly packed (no gap), so the header's
|
|
88
|
+
// own vertical padding is what creates breathing room between groups.
|
|
89
|
+
.groupHeader {
|
|
90
|
+
display: grid;
|
|
91
|
+
grid-template-columns: auto 1fr auto;
|
|
92
|
+
align-items: center;
|
|
93
|
+
gap: var(--options-picker-group-header-gap);
|
|
94
|
+
padding: var(--options-picker-group-header-padding-y) var(--options-picker-group-header-padding-x);
|
|
95
|
+
background: var(--options-picker-group-header-bg);
|
|
96
|
+
|
|
97
|
+
// Overrides the tone token the nested <Text tone="muted"> resolves through,
|
|
98
|
+
// rather than changing its prop, so the hint has a real base token for the
|
|
99
|
+
// #504 hover gate to measure against.
|
|
100
|
+
// #521 moved both the prop and this token off `subtle`: the hint's resting
|
|
101
|
+
// value had already been --color-fg-muted since #511, and `subtle` now
|
|
102
|
+
// resolves to muted anyway, so the indirection through a deprecated tone was
|
|
103
|
+
// describing a step that no longer exists. See OptionsPicker.tokens.scss.
|
|
104
|
+
// What that widened, and what actually constrains it: this custom property
|
|
105
|
+
// inherits, so it now retones EVERY tone="muted" Text in the .groupHeader
|
|
106
|
+
// subtree, not just .groupHint. Nothing else in that subtree is muted today
|
|
107
|
+
// -- .groupLabel is Text's default tone and the dot is a Badge or a span --
|
|
108
|
+
// so the effect is identical. But it is held by SELECTOR SCOPE, not by the
|
|
109
|
+
// token being specific to the hint: adding a second muted Text inside a
|
|
110
|
+
// group header would silently pick this up. If that happens, move the
|
|
111
|
+
// override onto .groupHint itself rather than widening this comment.
|
|
112
|
+
--text-fg-muted: var(--options-picker-group-header-hint-fg);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Bottom border in the namespace's palette color. The width + style come
|
|
116
|
+
// from these rules; the actual `border-bottom-color` is injected inline
|
|
117
|
+
// from the React layer (using --color-palette-<name>-fg). Applied only
|
|
118
|
+
// when the group has a `color` prop set, so legacy `tone`-only groups
|
|
119
|
+
// stay borderless.
|
|
120
|
+
// The `button.groupHeader { border: none }` rule below (multi-mode
|
|
121
|
+
// button reset) is more specific than `.groupHeaderWithBorder` on its
|
|
122
|
+
// own, so we need separate selectors for the div + button branches
|
|
123
|
+
// that match or beat its specificity.
|
|
124
|
+
.groupHeaderWithBorder {
|
|
125
|
+
border-bottom: var(--options-picker-group-header-border-width) solid transparent;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
button.groupHeader.groupHeaderWithBorder {
|
|
129
|
+
border-bottom: var(--options-picker-group-header-border-width) solid transparent;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.groupLabel {
|
|
133
|
+
text-transform: uppercase;
|
|
134
|
+
letter-spacing: 0.04em;
|
|
135
|
+
text-align: start;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.groupHint {
|
|
139
|
+
font-family: var(--font-family-mono);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Group-header dot. Used by the palette-colored variant (when group.color
|
|
143
|
+
// is set, GroupDot renders a <span> with this class). The Badge-tone path
|
|
144
|
+
// applies the same class to the Badge wrapper — the size is identical so
|
|
145
|
+
// both rendering branches land at the same visual size.
|
|
146
|
+
.groupDot {
|
|
147
|
+
width: var(--options-picker-group-dot-size);
|
|
148
|
+
height: var(--options-picker-group-dot-size);
|
|
149
|
+
border-radius: var(--options-picker-group-dot-radius);
|
|
150
|
+
flex-shrink: 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Indent options that live inside a group so they read as nested under
|
|
154
|
+
// the group header (the header's dot + label is the "outdent" anchor).
|
|
155
|
+
.group .row {
|
|
156
|
+
padding-left: var(--options-picker-row-padding-left-grouped);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.empty {
|
|
160
|
+
padding: var(--options-picker-empty-padding-y) var(--options-picker-empty-padding-x);
|
|
161
|
+
text-align: center;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
button.groupHeader {
|
|
165
|
+
border: none;
|
|
166
|
+
cursor: pointer;
|
|
167
|
+
width: 100%;
|
|
168
|
+
text-align: left;
|
|
169
|
+
|
|
170
|
+
// Scoped to the BUTTON, and kept with the background it compensates for. In
|
|
171
|
+
// single mode the header renders as a <div role="presentation"> with no hover
|
|
172
|
+
// background and no cursor change; an unscoped selector popped the hint to
|
|
173
|
+
// full strength there — a hover affordance on something you cannot click.
|
|
174
|
+
// AvatarGroup's `&:is(button):hover` and Table's `.sortable` scope the same way.
|
|
175
|
+
&:hover {
|
|
176
|
+
background: var(--options-picker-group-header-bg-hover);
|
|
177
|
+
|
|
178
|
+
// --color-bg-muted-hover is dark enough that the muted hint falls under AA
|
|
179
|
+
// on it (#504), and it is the one neutral surface --color-fg-muted still
|
|
180
|
+
// does not clear after #522's retune -- light misses, dark passes. So the
|
|
181
|
+
// hover strengthens to --color-fg; see the token's own @contrast
|
|
182
|
+
// annotations for that pair. Same subtree caveat as the base override
|
|
183
|
+
// above.
|
|
184
|
+
// @contrast --color-fg-muted on --color-bg-muted-hover = 4.45:1 light
|
|
185
|
+
// @contrast --color-fg-muted on --color-bg-muted-hover = 4.58:1 dark
|
|
186
|
+
--text-fg-muted: var(--options-picker-group-header-hint-fg-hover);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// INSET. `.list` above is `overflow-y: auto` — which computes `overflow-x`
|
|
190
|
+
// to `auto` — with no padding, and this header is `width: 100%`, so an
|
|
191
|
+
// outset ring loses both vertical bands on every group header, always.
|
|
192
|
+
// Same shape as Tabs and TimeField (#505), and NO GATE
|
|
193
|
+
// DETECTS IT: two static rules were measured and both were mostly false
|
|
194
|
+
// positives, so none shipped. A browser sweep found all three; #512 carries
|
|
195
|
+
// the signature so the next one is looked for rather than stumbled on.
|
|
196
|
+
// The trade, since the mixin says to record it, and it is the worst one in
|
|
197
|
+
// the library: `--options-picker-group-header-border-width` is
|
|
198
|
+
// --border-width-emphasis = 2px, and the inset band is also 2px, so while
|
|
199
|
+
// focused this covers the group's colour-identity `border-bottom`
|
|
200
|
+
// COMPLETELY — not partially, as on TimedEvent. Accepted because the colour
|
|
201
|
+
// is also carried by the GroupDot beside the label, which the ring does not
|
|
202
|
+
// touch, so the identity survives the focus; and because the alternative is
|
|
203
|
+
// an indicator that is permanently absent rather than briefly redundant.
|
|
204
|
+
&:focus-visible {
|
|
205
|
+
@include focus-ring($offset: calc(-1 * var(--ring-offset)));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.rowFocused {
|
|
210
|
+
background: var(--options-picker-row-bg-focused);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Async-mode live region (Hard rule 10) — announced, never painted.
|
|
214
|
+
.srOnly {
|
|
215
|
+
@include visually-hidden;
|
|
216
|
+
}
|