@eocrm/design-system 0.0.0-stage → 0.6.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AI-PRIMER.md +341 -0
- package/LICENSE +202 -0
- package/README.md +266 -2
- package/docs/components/Accordion.md +114 -0
- package/docs/components/AgentAvatar.md +58 -0
- package/docs/components/Alert.md +81 -0
- package/docs/components/AppLayout.md +70 -0
- package/docs/components/Avatar.md +49 -0
- package/docs/components/AvatarGroup.md +47 -0
- package/docs/components/Badge.md +60 -0
- package/docs/components/Banner.md +89 -0
- package/docs/components/BrandIcon.md +32 -0
- package/docs/components/Breadcrumb.md +72 -0
- package/docs/components/Button.md +107 -0
- package/docs/components/ButtonGroup.md +78 -0
- package/docs/components/Calendar.md +158 -0
- package/docs/components/Card.md +165 -0
- package/docs/components/CatalogPicker.md +83 -0
- package/docs/components/Chart.md +114 -0
- package/docs/components/ChatBubble.md +55 -0
- package/docs/components/ChatLauncher.md +97 -0
- package/docs/components/Checkbox.md +55 -0
- package/docs/components/CircularProgress.md +53 -0
- package/docs/components/Cluster.md +96 -0
- package/docs/components/Code.md +35 -0
- package/docs/components/CodeBlock.md +67 -0
- package/docs/components/ColorPicker.md +115 -0
- package/docs/components/ConfirmationPopover.md +70 -0
- package/docs/components/Constrain.md +39 -0
- package/docs/components/CurrencySelect.md +57 -0
- package/docs/components/CursorPagination.md +43 -0
- package/docs/components/DashboardCanvas.md +79 -0
- package/docs/components/DashboardWidget.md +131 -0
- package/docs/components/DataTable.md +88 -0
- package/docs/components/DatePicker.md +68 -0
- package/docs/components/DateRangePicker.md +71 -0
- package/docs/components/DateStrip.md +56 -0
- package/docs/components/DefinitionList.md +82 -0
- package/docs/components/Divider.md +57 -0
- package/docs/components/Dot.md +26 -0
- package/docs/components/Drawer.md +94 -0
- package/docs/components/DropdownMenu.md +299 -0
- package/docs/components/EmojiPicker.md +84 -0
- package/docs/components/EmptyState.md +55 -0
- package/docs/components/EntityChip.md +102 -0
- package/docs/components/ErrorState.md +72 -0
- package/docs/components/Field.md +91 -0
- package/docs/components/FileUpload.md +109 -0
- package/docs/components/FilterChip.md +88 -0
- package/docs/components/FlowCanvas.md +108 -0
- package/docs/components/FormRow.md +31 -0
- package/docs/components/FormSection.md +37 -0
- package/docs/components/Grid.md +103 -0
- package/docs/components/Highlight.md +75 -0
- package/docs/components/HighlightedText.md +50 -0
- package/docs/components/IconPicker.md +134 -0
- package/docs/components/IconTile.md +30 -0
- package/docs/components/Image.md +84 -0
- package/docs/components/ImageCrop.md +163 -0
- package/docs/components/Indent.md +31 -0
- package/docs/components/InlineDatePicker.md +58 -0
- package/docs/components/InlineDateRangePicker.md +57 -0
- package/docs/components/Input.md +54 -0
- package/docs/components/Kanban.md +122 -0
- package/docs/components/Kbd.md +41 -0
- package/docs/components/Lightbox.md +105 -0
- package/docs/components/Link.md +65 -0
- package/docs/components/LinkCard.md +41 -0
- package/docs/components/LiquidEditor.md +84 -0
- package/docs/components/List.md +68 -0
- package/docs/components/LiveRegion.md +29 -0
- package/docs/components/LocaleProvider.md +25 -0
- package/docs/components/Logo.md +41 -0
- package/docs/components/Masonry.md +48 -0
- package/docs/components/MediaTile.md +95 -0
- package/docs/components/Modal.md +107 -0
- package/docs/components/MoneyInput.md +62 -0
- package/docs/components/OptionsPicker.md +123 -0
- package/docs/components/OtpInput.md +65 -0
- package/docs/components/Page.md +35 -0
- package/docs/components/PageHeader.md +133 -0
- package/docs/components/Pagination.md +44 -0
- package/docs/components/Palette.md +32 -0
- package/docs/components/PasswordInput.md +45 -0
- package/docs/components/PasswordStrengthMeter.md +27 -0
- package/docs/components/PersonDisplay.md +153 -0
- package/docs/components/PhoneInput.md +54 -0
- package/docs/components/PillMenu.md +91 -0
- package/docs/components/Popover.md +127 -0
- package/docs/components/Progress.md +56 -0
- package/docs/components/QrCode.md +34 -0
- package/docs/components/Radio.md +37 -0
- package/docs/components/RadioGroup.md +56 -0
- package/docs/components/Rail.md +191 -0
- package/docs/components/RelativeDateInput.md +114 -0
- package/docs/components/RichText.md +44 -0
- package/docs/components/RichTextEditor.md +112 -0
- package/docs/components/Screen.md +37 -0
- package/docs/components/ScrollArea.md +39 -0
- package/docs/components/Select.md +131 -0
- package/docs/components/SettingRow.md +98 -0
- package/docs/components/Skeleton.md +68 -0
- package/docs/components/Slider.md +92 -0
- package/docs/components/SlotGrid.md +55 -0
- package/docs/components/SocialButton.md +31 -0
- package/docs/components/Sortable.md +127 -0
- package/docs/components/SortableGroup.md +52 -0
- package/docs/components/Sparkline.md +51 -0
- package/docs/components/Split.md +76 -0
- package/docs/components/Stack.md +59 -0
- package/docs/components/StagePath.md +66 -0
- package/docs/components/StatGroup.md +61 -0
- package/docs/components/StatTile.md +58 -0
- package/docs/components/Sticky.md +69 -0
- package/docs/components/Switch.md +89 -0
- package/docs/components/Table.md +184 -0
- package/docs/components/TableOfContents.md +76 -0
- package/docs/components/Tabs.md +94 -0
- package/docs/components/Text.md +63 -0
- package/docs/components/Textarea.md +59 -0
- package/docs/components/Thread.md +52 -0
- package/docs/components/TimeField.md +70 -0
- package/docs/components/Timeline.md +57 -0
- package/docs/components/Title.md +54 -0
- package/docs/components/ToastViewport.md +61 -0
- package/docs/components/Tooltip.md +63 -0
- package/docs/components/TopBar.md +214 -0
- package/docs/components/Tour.md +85 -0
- package/docs/components/TreeView.md +113 -0
- package/docs/components/VisuallyHidden.md +43 -0
- package/docs/components/WidgetPreview.md +54 -0
- package/docs/components/useBelowBreakpoint.md +11 -0
- package/docs/components/useMonth.md +18 -0
- package/docs/setup.md +51 -0
- package/docs/theming.md +95 -0
- package/docs/tokens.md +123 -0
- package/docs/transient-state.md +56 -0
- package/package.json +86 -4
- package/src/_meta/manifest.ts +293 -0
- package/src/app/AppProvider.tsx +78 -0
- package/src/app/index.ts +3 -0
- package/src/app/themeTokens.ts +95 -0
- package/src/calendar/dateMath.ts +114 -0
- package/src/calendar/formatters.ts +75 -0
- package/src/calendar/index.ts +39 -0
- package/src/calendar/types.ts +36 -0
- package/src/calendar/useAgenda.ts +70 -0
- package/src/calendar/useDay.ts +51 -0
- package/src/calendar/useMonth.ts +82 -0
- package/src/calendar/useWeek.ts +62 -0
- package/src/calendar/weekInfo.ts +83 -0
- package/src/components/Accordion/Accordion.module.scss +304 -0
- package/src/components/Accordion/Accordion.tokens.scss +64 -0
- package/src/components/Accordion/Accordion.tsx +272 -0
- package/src/components/Accordion/AccordionContent.tsx +36 -0
- package/src/components/Accordion/AccordionItem.tsx +66 -0
- package/src/components/Accordion/AccordionTrigger.tsx +121 -0
- package/src/components/Accordion/context.ts +47 -0
- package/src/components/Accordion/index.ts +14 -0
- package/src/components/Alert/Alert.module.scss +92 -0
- package/src/components/Alert/Alert.tokens.scss +60 -0
- package/src/components/Alert/Alert.tsx +136 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/AppLayout/AppLayout.module.scss +130 -0
- package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
- package/src/components/AppLayout/AppLayout.tsx +211 -0
- package/src/components/AppLayout/index.ts +2 -0
- package/src/components/Avatar/AgentAvatar.module.scss +117 -0
- package/src/components/Avatar/AgentAvatar.tsx +122 -0
- package/src/components/Avatar/Avatar.module.scss +181 -0
- package/src/components/Avatar/Avatar.tokens.scss +107 -0
- package/src/components/Avatar/Avatar.tsx +210 -0
- package/src/components/Avatar/AvatarGroup.module.scss +128 -0
- package/src/components/Avatar/AvatarGroup.tsx +119 -0
- package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
- package/src/components/Avatar/index.ts +6 -0
- package/src/components/Badge/Badge.module.scss +124 -0
- package/src/components/Badge/Badge.tokens.scss +74 -0
- package/src/components/Badge/Badge.tsx +164 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Banner/Banner.module.scss +73 -0
- package/src/components/Banner/Banner.tokens.scss +51 -0
- package/src/components/Banner/Banner.tsx +138 -0
- package/src/components/Banner/index.ts +2 -0
- package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
- package/src/components/BrandIcon/BrandIcon.tsx +99 -0
- package/src/components/BrandIcon/index.ts +2 -0
- package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
- package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
- package/src/components/Breadcrumb/index.ts +2 -0
- package/src/components/Button/Button.module.scss +167 -0
- package/src/components/Button/Button.tokens.scss +90 -0
- package/src/components/Button/Button.tsx +205 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
- package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
- package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
- package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
- package/src/components/ButtonGroup/context.ts +45 -0
- package/src/components/ButtonGroup/index.ts +2 -0
- package/src/components/Calendar/AgendaView.module.scss +231 -0
- package/src/components/Calendar/AgendaView.tsx +214 -0
- package/src/components/Calendar/AllDayBand.module.scss +18 -0
- package/src/components/Calendar/AllDayBand.tsx +75 -0
- package/src/components/Calendar/Calendar.module.scss +23 -0
- package/src/components/Calendar/Calendar.tokens.scss +262 -0
- package/src/components/Calendar/Calendar.tsx +370 -0
- package/src/components/Calendar/DayCell.module.scss +30 -0
- package/src/components/Calendar/DayCell.tsx +50 -0
- package/src/components/Calendar/DayView.module.scss +10 -0
- package/src/components/Calendar/DayView.tsx +163 -0
- package/src/components/Calendar/EventChip.module.scss +171 -0
- package/src/components/Calendar/EventChip.tsx +115 -0
- package/src/components/Calendar/HourGrid.module.scss +123 -0
- package/src/components/Calendar/HourGrid.tsx +381 -0
- package/src/components/Calendar/MonthView.module.scss +99 -0
- package/src/components/Calendar/MonthView.tsx +296 -0
- package/src/components/Calendar/TimedEvent.module.scss +205 -0
- package/src/components/Calendar/TimedEvent.tsx +247 -0
- package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
- package/src/components/Calendar/ViewSwitcher.tsx +47 -0
- package/src/components/Calendar/WeekView.module.scss +10 -0
- package/src/components/Calendar/WeekView.tsx +137 -0
- package/src/components/Calendar/eventColor.ts +60 -0
- package/src/components/Calendar/index.ts +18 -0
- package/src/components/Calendar/types.ts +451 -0
- package/src/components/Calendar/useEventDrag.ts +783 -0
- package/src/components/Calendar/utils.ts +622 -0
- package/src/components/Card/Card.module.scss +264 -0
- package/src/components/Card/Card.tokens.scss +55 -0
- package/src/components/Card/Card.tsx +170 -0
- package/src/components/Card/CardBody.tsx +45 -0
- package/src/components/Card/CardHeader.tsx +113 -0
- package/src/components/Card/CardList.tsx +24 -0
- package/src/components/Card/CardListRow.tsx +24 -0
- package/src/components/Card/index.ts +7 -0
- package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
- package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
- package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
- package/src/components/CatalogPicker/index.ts +2 -0
- package/src/components/Chart/Chart.module.scss +287 -0
- package/src/components/Chart/Chart.tokens.scss +63 -0
- package/src/components/Chart/Chart.tsx +607 -0
- package/src/components/Chart/ChartLegend.tsx +99 -0
- package/src/components/Chart/ChartTable.tsx +62 -0
- package/src/components/Chart/ChartTooltip.tsx +91 -0
- package/src/components/Chart/chartModel.ts +689 -0
- package/src/components/Chart/index.ts +2 -0
- package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
- package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
- package/src/components/ChatBubble/ChatBubble.tsx +61 -0
- package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
- package/src/components/ChatBubble/index.ts +3 -0
- package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
- package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
- package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
- package/src/components/ChatLauncher/index.ts +2 -0
- package/src/components/ChatLauncher/isAtBottom.ts +12 -0
- package/src/components/Checkbox/Checkbox.module.scss +147 -0
- package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
- package/src/components/Checkbox/Checkbox.tsx +188 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
- package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
- package/src/components/CircularProgress/CircularProgress.tsx +139 -0
- package/src/components/CircularProgress/index.ts +7 -0
- package/src/components/Cluster/Cluster.module.scss +145 -0
- package/src/components/Cluster/Cluster.tokens.scss +11 -0
- package/src/components/Cluster/Cluster.tsx +215 -0
- package/src/components/Cluster/index.ts +2 -0
- package/src/components/Code/Code.module.scss +28 -0
- package/src/components/Code/Code.tokens.scss +15 -0
- package/src/components/Code/Code.tsx +44 -0
- package/src/components/Code/index.ts +2 -0
- package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
- package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
- package/src/components/CodeBlock/CodeBlock.tsx +274 -0
- package/src/components/CodeBlock/highlight.ts +179 -0
- package/src/components/CodeBlock/index.ts +8 -0
- package/src/components/CodeBlock/sampleSync.ts +42 -0
- package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
- package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
- package/src/components/ColorPicker/ColorPicker.tsx +367 -0
- package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
- package/src/components/ColorPicker/SVSquare.tsx +189 -0
- package/src/components/ColorPicker/colorMath.ts +141 -0
- package/src/components/ColorPicker/index.ts +6 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
- package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
- package/src/components/ConfirmationPopover/index.ts +2 -0
- package/src/components/Constrain/Constrain.module.scss +99 -0
- package/src/components/Constrain/Constrain.tsx +79 -0
- package/src/components/Constrain/index.ts +2 -0
- package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
- package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
- package/src/components/CurrencySelect/index.ts +3 -0
- package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
- package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
- package/src/components/CursorPagination/CursorPagination.tsx +121 -0
- package/src/components/CursorPagination/index.ts +2 -0
- package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
- package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
- package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
- package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
- package/src/components/DashboardCanvas/engine.ts +363 -0
- package/src/components/DashboardCanvas/index.ts +9 -0
- package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
- package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
- package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
- package/src/components/DashboardWidget/index.ts +7 -0
- package/src/components/DataTable/BodyRow.tsx +197 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
- package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
- package/src/components/DataTable/DataTable.module.scss +511 -0
- package/src/components/DataTable/DataTable.tokens.scss +80 -0
- package/src/components/DataTable/DataTable.tsx +734 -0
- package/src/components/DataTable/HeaderCell.module.scss +215 -0
- package/src/components/DataTable/HeaderCell.tsx +440 -0
- package/src/components/DataTable/columnShift.ts +117 -0
- package/src/components/DataTable/index.ts +23 -0
- package/src/components/DataTable/pinStyle.ts +47 -0
- package/src/components/DataTable/reorderColumns.ts +66 -0
- package/src/components/DataTable/types.ts +289 -0
- package/src/components/DataTable/useColumnDragShift.ts +216 -0
- package/src/components/DataTable/useDataTable.ts +372 -0
- package/src/components/DataTable/useResizeHandle.ts +97 -0
- package/src/components/DatePicker/DatePicker.module.scss +180 -0
- package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
- package/src/components/DatePicker/DatePicker.tsx +664 -0
- package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
- package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
- package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
- package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
- package/src/components/DatePicker/index.ts +4 -0
- package/src/components/DatePicker/utils.ts +364 -0
- package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
- package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
- package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
- package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
- package/src/components/DateRangePicker/index.ts +5 -0
- package/src/components/DateRangePicker/utils.ts +151 -0
- package/src/components/DateStrip/DateStrip.module.scss +78 -0
- package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
- package/src/components/DateStrip/DateStrip.tsx +205 -0
- package/src/components/DateStrip/index.ts +2 -0
- package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
- package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
- package/src/components/DefinitionList/DefinitionList.tsx +198 -0
- package/src/components/DefinitionList/index.ts +9 -0
- package/src/components/Divider/Divider.module.scss +144 -0
- package/src/components/Divider/Divider.tokens.scss +21 -0
- package/src/components/Divider/Divider.tsx +103 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Dot/Dot.module.scss +40 -0
- package/src/components/Dot/Dot.tokens.scss +4 -0
- package/src/components/Dot/Dot.tsx +45 -0
- package/src/components/Dot/index.ts +2 -0
- package/src/components/Drawer/Body.tsx +23 -0
- package/src/components/Drawer/Close.tsx +35 -0
- package/src/components/Drawer/Content.tsx +93 -0
- package/src/components/Drawer/Drawer.module.scss +232 -0
- package/src/components/Drawer/Drawer.tokens.scss +38 -0
- package/src/components/Drawer/Drawer.tsx +23 -0
- package/src/components/Drawer/DrawerRoot.tsx +190 -0
- package/src/components/Drawer/Footer.tsx +24 -0
- package/src/components/Drawer/Header.tsx +64 -0
- package/src/components/Drawer/Overlay.tsx +82 -0
- package/src/components/Drawer/context.ts +44 -0
- package/src/components/Drawer/index.ts +12 -0
- package/src/components/Drawer/useDragToClose.ts +149 -0
- package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
- package/src/components/DropdownMenu/Content.tsx +419 -0
- package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
- package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
- package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
- package/src/components/DropdownMenu/Group.tsx +76 -0
- package/src/components/DropdownMenu/Item.tsx +148 -0
- package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
- package/src/components/DropdownMenu/Radio.tsx +178 -0
- package/src/components/DropdownMenu/Root.tsx +100 -0
- package/src/components/DropdownMenu/Sub.tsx +332 -0
- package/src/components/DropdownMenu/Trigger.tsx +76 -0
- package/src/components/DropdownMenu/context.ts +65 -0
- package/src/components/DropdownMenu/index.ts +20 -0
- package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
- package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
- package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
- package/src/components/EmojiPicker/emojiData.ts +245 -0
- package/src/components/EmojiPicker/index.ts +3 -0
- package/src/components/EmptyState/EmptyState.module.scss +102 -0
- package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
- package/src/components/EmptyState/EmptyState.tsx +112 -0
- package/src/components/EmptyState/index.ts +7 -0
- package/src/components/EntityChip/EntityChip.module.scss +275 -0
- package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
- package/src/components/EntityChip/EntityChip.tsx +649 -0
- package/src/components/EntityChip/index.ts +10 -0
- package/src/components/ErrorState/ErrorState.module.scss +105 -0
- package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
- package/src/components/ErrorState/ErrorState.tsx +125 -0
- package/src/components/ErrorState/index.ts +8 -0
- package/src/components/Field/Field.module.scss +46 -0
- package/src/components/Field/Field.tsx +185 -0
- package/src/components/Field/index.ts +2 -0
- package/src/components/FileUpload/FileUpload.module.scss +187 -0
- package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
- package/src/components/FileUpload/FileUpload.tsx +569 -0
- package/src/components/FileUpload/formatBytes.ts +34 -0
- package/src/components/FileUpload/iconForFile.ts +40 -0
- package/src/components/FileUpload/index.ts +2 -0
- package/src/components/FilterChip/FilterChip.module.scss +61 -0
- package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
- package/src/components/FilterChip/FilterChip.tsx +208 -0
- package/src/components/FilterChip/index.ts +5 -0
- package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
- package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
- package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
- package/src/components/FlowCanvas/FlowControls.tsx +46 -0
- package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
- package/src/components/FlowCanvas/FlowNode.tsx +76 -0
- package/src/components/FlowCanvas/edgePath.ts +85 -0
- package/src/components/FlowCanvas/index.ts +4 -0
- package/src/components/FlowCanvas/layout.ts +148 -0
- package/src/components/FlowCanvas/spatialNav.ts +76 -0
- package/src/components/FlowCanvas/types.ts +59 -0
- package/src/components/FlowCanvas/useViewport.ts +122 -0
- package/src/components/FormRow/FormRow.module.scss +2 -0
- package/src/components/FormRow/FormRow.tsx +37 -0
- package/src/components/FormRow/index.ts +2 -0
- package/src/components/FormSection/FormSection.module.scss +24 -0
- package/src/components/FormSection/FormSection.tsx +46 -0
- package/src/components/FormSection/index.ts +2 -0
- package/src/components/Grid/Grid.module.scss +162 -0
- package/src/components/Grid/Grid.tokens.scss +13 -0
- package/src/components/Grid/Grid.tsx +226 -0
- package/src/components/Grid/GridItem.tsx +77 -0
- package/src/components/Grid/index.ts +11 -0
- package/src/components/Highlight/Highlight.module.scss +43 -0
- package/src/components/Highlight/Highlight.tokens.scss +35 -0
- package/src/components/Highlight/Highlight.tsx +164 -0
- package/src/components/Highlight/HighlightOverlay.tsx +100 -0
- package/src/components/Highlight/index.ts +2 -0
- package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
- package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
- package/src/components/HighlightedText/HighlightedText.tsx +50 -0
- package/src/components/HighlightedText/highlightRanges.ts +44 -0
- package/src/components/HighlightedText/index.ts +2 -0
- package/src/components/IconPicker/IconPicker.module.scss +175 -0
- package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
- package/src/components/IconPicker/IconPicker.tsx +629 -0
- package/src/components/IconPicker/index.ts +9 -0
- package/src/components/IconTile/IconTile.module.scss +57 -0
- package/src/components/IconTile/IconTile.tokens.scss +16 -0
- package/src/components/IconTile/IconTile.tsx +91 -0
- package/src/components/IconTile/index.ts +2 -0
- package/src/components/Image/Image.module.scss +266 -0
- package/src/components/Image/Image.tokens.scss +55 -0
- package/src/components/Image/Image.tsx +342 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
- package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
- package/src/components/ImageCrop/ImageCrop.tsx +542 -0
- package/src/components/ImageCrop/cropGeometry.ts +120 -0
- package/src/components/ImageCrop/extractCropBlob.ts +140 -0
- package/src/components/ImageCrop/index.ts +11 -0
- package/src/components/ImageCrop/useCropPreview.ts +161 -0
- package/src/components/Indent/Indent.module.scss +33 -0
- package/src/components/Indent/Indent.tokens.scss +10 -0
- package/src/components/Indent/Indent.tsx +46 -0
- package/src/components/Indent/index.ts +2 -0
- package/src/components/Input/Input.module.scss +99 -0
- package/src/components/Input/Input.tokens.scss +54 -0
- package/src/components/Input/Input.tsx +105 -0
- package/src/components/Input/Suggestions.tsx +260 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Kanban/Kanban.module.scss +39 -0
- package/src/components/Kanban/Kanban.tokens.scss +15 -0
- package/src/components/Kanban/Kanban.tsx +951 -0
- package/src/components/Kanban/index.ts +7 -0
- package/src/components/Kbd/Kbd.module.scss +47 -0
- package/src/components/Kbd/Kbd.tokens.scss +26 -0
- package/src/components/Kbd/Kbd.tsx +73 -0
- package/src/components/Kbd/index.ts +2 -0
- package/src/components/Lightbox/Lightbox.module.scss +283 -0
- package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
- package/src/components/Lightbox/Lightbox.tsx +506 -0
- package/src/components/Lightbox/index.ts +2 -0
- package/src/components/Link/Link.module.scss +78 -0
- package/src/components/Link/Link.tokens.scss +28 -0
- package/src/components/Link/Link.tsx +114 -0
- package/src/components/Link/index.ts +2 -0
- package/src/components/LinkCard/LinkCard.module.scss +92 -0
- package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
- package/src/components/LinkCard/LinkCard.tsx +72 -0
- package/src/components/LinkCard/index.ts +2 -0
- package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
- package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
- package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
- package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
- package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
- package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
- package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
- package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
- package/src/components/LiquidEditor/index.ts +7 -0
- package/src/components/LiquidEditor/liquidFilters.ts +23 -0
- package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
- package/src/components/LiquidEditor/types.ts +101 -0
- package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
- package/src/components/List/List.module.scss +105 -0
- package/src/components/List/List.tokens.scss +42 -0
- package/src/components/List/List.tsx +124 -0
- package/src/components/List/index.ts +9 -0
- package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
- package/src/components/LiveRegion/LiveRegion.tsx +116 -0
- package/src/components/LiveRegion/index.ts +2 -0
- package/src/components/Logo/Logo.module.scss +139 -0
- package/src/components/Logo/Logo.tokens.scss +14 -0
- package/src/components/Logo/Logo.tsx +126 -0
- package/src/components/Logo/index.ts +2 -0
- package/src/components/Masonry/Masonry.module.scss +42 -0
- package/src/components/Masonry/Masonry.tokens.scss +8 -0
- package/src/components/Masonry/Masonry.tsx +136 -0
- package/src/components/Masonry/index.ts +2 -0
- package/src/components/Masonry/masonryUtils.ts +42 -0
- package/src/components/MediaTile/MediaTile.module.scss +183 -0
- package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
- package/src/components/MediaTile/MediaTile.tsx +208 -0
- package/src/components/MediaTile/index.ts +8 -0
- package/src/components/Modal/Body.tsx +27 -0
- package/src/components/Modal/Close.tsx +45 -0
- package/src/components/Modal/Content.tsx +98 -0
- package/src/components/Modal/Footer.tsx +28 -0
- package/src/components/Modal/Header.tsx +51 -0
- package/src/components/Modal/Modal.module.scss +262 -0
- package/src/components/Modal/Modal.tokens.scss +50 -0
- package/src/components/Modal/Modal.tsx +23 -0
- package/src/components/Modal/ModalRoot.tsx +299 -0
- package/src/components/Modal/Overlay.tsx +101 -0
- package/src/components/Modal/context.ts +60 -0
- package/src/components/Modal/index.ts +11 -0
- package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
- package/src/components/MoneyInput/MoneyInput.tsx +433 -0
- package/src/components/MoneyInput/index.ts +2 -0
- package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
- package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
- package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
- package/src/components/OptionsPicker/index.ts +9 -0
- package/src/components/OtpInput/OtpInput.module.scss +69 -0
- package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
- package/src/components/OtpInput/OtpInput.tsx +368 -0
- package/src/components/OtpInput/index.ts +2 -0
- package/src/components/Page/Page.module.scss +30 -0
- package/src/components/Page/Page.tokens.scss +11 -0
- package/src/components/Page/Page.tsx +53 -0
- package/src/components/Page/index.ts +2 -0
- package/src/components/PageHeader/PageHeader.module.scss +197 -0
- package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
- package/src/components/PageHeader/PageHeader.tsx +310 -0
- package/src/components/PageHeader/index.ts +20 -0
- package/src/components/Pagination/Pagination.module.scss +117 -0
- package/src/components/Pagination/Pagination.tokens.scss +54 -0
- package/src/components/Pagination/Pagination.tsx +165 -0
- package/src/components/Pagination/index.ts +4 -0
- package/src/components/Pagination/paginationRange.ts +72 -0
- package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
- package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
- package/src/components/PasswordInput/PasswordInput.tsx +210 -0
- package/src/components/PasswordInput/index.ts +2 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
- package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
- package/src/components/PasswordStrengthMeter/index.ts +2 -0
- package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
- package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
- package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
- package/src/components/PersonDisplay/index.ts +10 -0
- package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
- package/src/components/PhoneInput/PhoneInput.tsx +271 -0
- package/src/components/PhoneInput/index.ts +4 -0
- package/src/components/PhoneInput/phone.ts +128 -0
- package/src/components/PillMenu/PillMenu.module.scss +117 -0
- package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
- package/src/components/PillMenu/PillMenu.tsx +324 -0
- package/src/components/PillMenu/index.ts +2 -0
- package/src/components/Popover/Anchor.tsx +37 -0
- package/src/components/Popover/Close.tsx +45 -0
- package/src/components/Popover/Content.tsx +213 -0
- package/src/components/Popover/Heading.tsx +33 -0
- package/src/components/Popover/Popover.module.scss +177 -0
- package/src/components/Popover/Popover.tokens.scss +22 -0
- package/src/components/Popover/Popover.tsx +23 -0
- package/src/components/Popover/PopoverRoot.tsx +75 -0
- package/src/components/Popover/Trigger.tsx +86 -0
- package/src/components/Popover/context.ts +22 -0
- package/src/components/Popover/index.ts +7 -0
- package/src/components/Progress/Progress.module.scss +110 -0
- package/src/components/Progress/Progress.tokens.scss +44 -0
- package/src/components/Progress/Progress.tsx +129 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/QrCode/QrCode.module.scss +97 -0
- package/src/components/QrCode/QrCode.tokens.scss +17 -0
- package/src/components/QrCode/QrCode.tsx +233 -0
- package/src/components/QrCode/index.ts +2 -0
- package/src/components/QrCode/qr.ts +161 -0
- package/src/components/Radio/Radio.module.scss +175 -0
- package/src/components/Radio/Radio.tokens.scss +59 -0
- package/src/components/Radio/Radio.tsx +127 -0
- package/src/components/Radio/RadioGroup.module.scss +42 -0
- package/src/components/Radio/RadioGroup.tsx +120 -0
- package/src/components/Radio/RadioGroupContext.tsx +30 -0
- package/src/components/Radio/index.ts +4 -0
- package/src/components/Rail/Rail.module.scss +510 -0
- package/src/components/Rail/Rail.tokens.scss +92 -0
- package/src/components/Rail/Rail.tsx +287 -0
- package/src/components/Rail/RailCollapseToggle.tsx +57 -0
- package/src/components/Rail/RailFooter.tsx +17 -0
- package/src/components/Rail/RailGroup.tsx +728 -0
- package/src/components/Rail/RailGroupContext.ts +9 -0
- package/src/components/Rail/RailHeader.tsx +23 -0
- package/src/components/Rail/RailItem.tsx +119 -0
- package/src/components/Rail/RailSection.tsx +39 -0
- package/src/components/Rail/RailSpacer.tsx +19 -0
- package/src/components/Rail/index.ts +9 -0
- package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
- package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
- package/src/components/RelativeDateInput/index.ts +10 -0
- package/src/components/RelativeDateInput/relativeDate.ts +127 -0
- package/src/components/RichText/RichText.module.scss +5 -0
- package/src/components/RichText/RichText.tsx +70 -0
- package/src/components/RichText/RichTextAttachment.module.scss +82 -0
- package/src/components/RichText/RichTextAttachment.tsx +122 -0
- package/src/components/RichText/_prose.scss +79 -0
- package/src/components/RichText/attachmentIcon.tsx +24 -0
- package/src/components/RichText/engine/attachment.ts +154 -0
- package/src/components/RichText/engine/autolink.ts +64 -0
- package/src/components/RichText/engine/blockUnit.ts +174 -0
- package/src/components/RichText/engine/colorMarks.ts +85 -0
- package/src/components/RichText/engine/escape.ts +11 -0
- package/src/components/RichText/engine/fromHtml.ts +353 -0
- package/src/components/RichText/engine/fromMarkdown.ts +20 -0
- package/src/components/RichText/engine/inlines.ts +82 -0
- package/src/components/RichText/engine/listDepths.ts +32 -0
- package/src/components/RichText/engine/marks.ts +80 -0
- package/src/components/RichText/engine/mdToHtml.ts +178 -0
- package/src/components/RichText/engine/model.ts +157 -0
- package/src/components/RichText/engine/position.ts +118 -0
- package/src/components/RichText/engine/renderDoc.tsx +395 -0
- package/src/components/RichText/engine/renderLink.ts +15 -0
- package/src/components/RichText/engine/renderMention.ts +16 -0
- package/src/components/RichText/engine/safeHref.ts +22 -0
- package/src/components/RichText/engine/toHtml.ts +154 -0
- package/src/components/RichText/engine/toMarkdown.ts +97 -0
- package/src/components/RichText/engine/transforms.ts +434 -0
- package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
- package/src/components/RichText/index.ts +31 -0
- package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
- package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
- package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
- package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
- package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
- package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
- package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
- package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
- package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
- package/src/components/RichTextEditor/autolinkInput.ts +65 -0
- package/src/components/RichTextEditor/blockDrop.ts +9 -0
- package/src/components/RichTextEditor/blockReflow.ts +62 -0
- package/src/components/RichTextEditor/commands.ts +300 -0
- package/src/components/RichTextEditor/history.ts +93 -0
- package/src/components/RichTextEditor/icons.tsx +152 -0
- package/src/components/RichTextEditor/imageSize.ts +70 -0
- package/src/components/RichTextEditor/index.ts +5 -0
- package/src/components/RichTextEditor/input.ts +209 -0
- package/src/components/RichTextEditor/inputRules.ts +71 -0
- package/src/components/RichTextEditor/links.ts +103 -0
- package/src/components/RichTextEditor/mentionContext.ts +37 -0
- package/src/components/RichTextEditor/mentions.ts +28 -0
- package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
- package/src/components/RichTextEditor/selection.ts +415 -0
- package/src/components/RichTextEditor/shortcuts.ts +44 -0
- package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
- package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
- package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
- package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
- package/src/components/RichTextEditor/useMention.ts +226 -0
- package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
- package/src/components/RichTextEditor/useUpload.ts +246 -0
- package/src/components/Screen/Screen.module.scss +46 -0
- package/src/components/Screen/Screen.tokens.scss +20 -0
- package/src/components/Screen/Screen.tsx +97 -0
- package/src/components/Screen/index.ts +2 -0
- package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
- package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
- package/src/components/ScrollArea/ScrollArea.tsx +154 -0
- package/src/components/ScrollArea/index.ts +2 -0
- package/src/components/Select/Chip.tsx +45 -0
- package/src/components/Select/Empty.tsx +39 -0
- package/src/components/Select/Error.tsx +51 -0
- package/src/components/Select/HiddenInputs.tsx +44 -0
- package/src/components/Select/Listbox.tsx +557 -0
- package/src/components/Select/Loading.tsx +30 -0
- package/src/components/Select/Select.module.scss +512 -0
- package/src/components/Select/Select.tokens.scss +140 -0
- package/src/components/Select/Select.tsx +685 -0
- package/src/components/Select/Trigger.tsx +952 -0
- package/src/components/Select/context.ts +101 -0
- package/src/components/Select/emptyStateText.ts +19 -0
- package/src/components/Select/index.ts +9 -0
- package/src/components/Select/useSelectState.ts +157 -0
- package/src/components/Select/utils-types.ts +7 -0
- package/src/components/Select/utils.ts +122 -0
- package/src/components/SettingRow/SettingRow.module.scss +166 -0
- package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
- package/src/components/SettingRow/SettingRow.tsx +242 -0
- package/src/components/SettingRow/index.ts +7 -0
- package/src/components/Skeleton/Skeleton.module.scss +55 -0
- package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
- package/src/components/Skeleton/Skeleton.tsx +131 -0
- package/src/components/Skeleton/index.ts +4 -0
- package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
- package/src/components/Slider/Slider.module.scss +293 -0
- package/src/components/Slider/Slider.tokens.scss +98 -0
- package/src/components/Slider/Slider.tsx +624 -0
- package/src/components/Slider/index.ts +9 -0
- package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
- package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
- package/src/components/SlotGrid/SlotGrid.tsx +111 -0
- package/src/components/SlotGrid/index.ts +2 -0
- package/src/components/SocialButton/SocialButton.module.scss +4 -0
- package/src/components/SocialButton/SocialButton.tsx +40 -0
- package/src/components/SocialButton/index.ts +2 -0
- package/src/components/Sortable/Sortable.module.scss +177 -0
- package/src/components/Sortable/Sortable.tokens.scss +27 -0
- package/src/components/Sortable/Sortable.tsx +572 -0
- package/src/components/Sortable/containerAwareCollision.ts +125 -0
- package/src/components/Sortable/index.ts +13 -0
- package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
- package/src/components/SortableGroup/SortableGroup.tsx +315 -0
- package/src/components/SortableGroup/index.ts +4 -0
- package/src/components/SortableGroup/moveSortableItem.ts +39 -0
- package/src/components/Sparkline/Sparkline.module.scss +28 -0
- package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
- package/src/components/Sparkline/Sparkline.tsx +133 -0
- package/src/components/Sparkline/index.ts +2 -0
- package/src/components/Sparkline/sparklineModel.ts +119 -0
- package/src/components/Split/Split.module.scss +158 -0
- package/src/components/Split/Split.tokens.scss +10 -0
- package/src/components/Split/Split.tsx +231 -0
- package/src/components/Split/index.ts +2 -0
- package/src/components/Stack/Stack.module.scss +67 -0
- package/src/components/Stack/Stack.tokens.scss +11 -0
- package/src/components/Stack/Stack.tsx +100 -0
- package/src/components/Stack/index.ts +2 -0
- package/src/components/StagePath/StagePath.module.scss +255 -0
- package/src/components/StagePath/StagePath.tokens.scss +43 -0
- package/src/components/StagePath/StagePath.tsx +176 -0
- package/src/components/StagePath/index.ts +2 -0
- package/src/components/StatGroup/StatGroup.module.scss +6 -0
- package/src/components/StatGroup/StatGroup.tsx +70 -0
- package/src/components/StatGroup/StatGroupContext.ts +10 -0
- package/src/components/StatGroup/StatTile.module.scss +99 -0
- package/src/components/StatGroup/StatTile.tokens.scss +35 -0
- package/src/components/StatGroup/StatTile.tsx +143 -0
- package/src/components/StatGroup/index.ts +4 -0
- package/src/components/Sticky/Sticky.module.scss +98 -0
- package/src/components/Sticky/Sticky.tokens.scss +17 -0
- package/src/components/Sticky/Sticky.tsx +103 -0
- package/src/components/Sticky/index.ts +2 -0
- package/src/components/Switch/Switch.module.scss +182 -0
- package/src/components/Switch/Switch.tokens.scss +59 -0
- package/src/components/Switch/Switch.tsx +214 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/Table.module.scss +308 -0
- package/src/components/Table/Table.tokens.scss +79 -0
- package/src/components/Table/Table.tsx +381 -0
- package/src/components/Table/index.ts +15 -0
- package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
- package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
- package/src/components/TableOfContents/TableOfContents.tsx +192 -0
- package/src/components/TableOfContents/activeSection.ts +18 -0
- package/src/components/TableOfContents/index.ts +2 -0
- package/src/components/Tabs/Tabs.module.scss +359 -0
- package/src/components/Tabs/Tabs.tokens.scss +50 -0
- package/src/components/Tabs/Tabs.tsx +538 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Text/Text.module.scss +115 -0
- package/src/components/Text/Text.tokens.scss +55 -0
- package/src/components/Text/Text.tsx +197 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Textarea/Textarea.module.scss +94 -0
- package/src/components/Textarea/Textarea.tokens.scss +48 -0
- package/src/components/Textarea/Textarea.tsx +246 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Thread/Thread.module.scss +161 -0
- package/src/components/Thread/Thread.tokens.scss +32 -0
- package/src/components/Thread/Thread.tsx +176 -0
- package/src/components/Thread/index.ts +2 -0
- package/src/components/TimeField/TimeField.module.scss +232 -0
- package/src/components/TimeField/TimeField.tsx +793 -0
- package/src/components/TimeField/index.ts +2 -0
- package/src/components/Timeline/Timeline.module.scss +58 -0
- package/src/components/Timeline/Timeline.tokens.scss +13 -0
- package/src/components/Timeline/Timeline.tsx +53 -0
- package/src/components/Timeline/index.ts +2 -0
- package/src/components/Title/Title.module.scss +84 -0
- package/src/components/Title/Title.tokens.scss +37 -0
- package/src/components/Title/Title.tsx +150 -0
- package/src/components/Title/index.ts +2 -0
- package/src/components/Toast/Toast.module.scss +299 -0
- package/src/components/Toast/Toast.tokens.scss +65 -0
- package/src/components/Toast/Toast.tsx +122 -0
- package/src/components/Toast/ToastViewport.tsx +166 -0
- package/src/components/Toast/api.ts +175 -0
- package/src/components/Toast/index.ts +5 -0
- package/src/components/Toast/store.ts +133 -0
- package/src/components/Toast/useToastTimer.ts +94 -0
- package/src/components/Tooltip/Tooltip.module.scss +99 -0
- package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
- package/src/components/Tooltip/Tooltip.tsx +341 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/TopBar/TopBar.module.scss +235 -0
- package/src/components/TopBar/TopBar.tokens.scss +79 -0
- package/src/components/TopBar/TopBar.tsx +87 -0
- package/src/components/TopBar/TopBarEnd.tsx +20 -0
- package/src/components/TopBar/TopBarIconButton.tsx +86 -0
- package/src/components/TopBar/TopBarSearch.tsx +319 -0
- package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
- package/src/components/TopBar/TopBarStart.tsx +20 -0
- package/src/components/TopBar/index.ts +11 -0
- package/src/components/Tour/Spotlight.tsx +121 -0
- package/src/components/Tour/Tour.module.scss +210 -0
- package/src/components/Tour/Tour.tokens.scss +58 -0
- package/src/components/Tour/Tour.tsx +617 -0
- package/src/components/Tour/index.ts +2 -0
- package/src/components/Tour/useTourTarget.ts +115 -0
- package/src/components/TreeView/TreeView.module.scss +268 -0
- package/src/components/TreeView/TreeView.tokens.scss +36 -0
- package/src/components/TreeView/TreeView.tsx +536 -0
- package/src/components/TreeView/index.ts +3 -0
- package/src/components/TreeView/treeModel.ts +224 -0
- package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
- package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
- package/src/components/VisuallyHidden/index.ts +2 -0
- package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
- package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
- package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
- package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
- package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
- package/src/components/WidgetPreview/index.ts +2 -0
- package/src/components/_internal/Trend.tsx +27 -0
- package/src/components/_internal/choiceTile.scss +74 -0
- package/src/components/_internal/collapse.scss +10 -0
- package/src/components/_internal/collapse.ts +58 -0
- package/src/components/_internal/currency.ts +257 -0
- package/src/components/_internal/dragAnnouncements.ts +200 -0
- package/src/components/_internal/fieldWiring.ts +225 -0
- package/src/components/_internal/gridSpan.ts +54 -0
- package/src/components/_internal/isoDay.ts +35 -0
- package/src/components/_internal/letterKey.ts +26 -0
- package/src/components/_internal/overlay/focusRestore.ts +21 -0
- package/src/components/_internal/overlay/index.ts +12 -0
- package/src/components/_internal/overlay/tourHold.ts +23 -0
- package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
- package/src/components/_internal/overlay/useInOverlay.ts +81 -0
- package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
- package/src/components/_internal/overlay/useScrollLock.ts +112 -0
- package/src/components/_internal/refs.ts +48 -0
- package/src/components/_internal/statusColor.ts +26 -0
- package/src/components/_internal/timeUtils.ts +23 -0
- package/src/components/_internal/useAsyncOptions.ts +145 -0
- package/src/components/_internal/useClippedTooltip.ts +50 -0
- package/src/components/_internal/useControllableState.ts +50 -0
- package/src/components.manifest.json +1141 -0
- package/src/hooks/useBelowBreakpoint.ts +58 -0
- package/src/i18n/I18nProvider.tsx +52 -0
- package/src/i18n/LocaleProvider.tsx +17 -0
- package/src/i18n/en.ts +648 -0
- package/src/i18n/format.ts +71 -0
- package/src/i18n/index.ts +13 -0
- package/src/i18n/messages.ts +1275 -0
- package/src/i18n/ru.ts +677 -0
- package/src/i18n/useLocale.ts +19 -0
- package/src/i18n/useTranslation.ts +58 -0
- package/src/index.ts +913 -0
- package/src/palette/index.ts +2 -0
- package/src/palette/palette.ts +108 -0
- package/src/styles/dark.scss +4 -0
- package/src/styles/global.scss +7 -0
- package/src/styles/mixins.scss +143 -0
- package/src/styles/reset.scss +78 -0
- package/src/styles/tokens.scss +18 -0
- package/src/styles/typography.scss +44 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useEffect,
|
|
4
|
+
useState,
|
|
5
|
+
type CSSProperties,
|
|
6
|
+
type HTMLAttributes,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
type Ref,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import clsx from 'clsx';
|
|
11
|
+
import { DropdownMenu } from '../DropdownMenu';
|
|
12
|
+
import { paletteTokens, type PaletteColor } from '../../palette';
|
|
13
|
+
import { useTranslation } from '../../i18n/useTranslation';
|
|
14
|
+
import { resolveStatusColor, type StatusCategory } from '../_internal/statusColor';
|
|
15
|
+
import styles from './PillMenu.module.scss';
|
|
16
|
+
|
|
17
|
+
/** Workflow category — maps to a default palette color. */
|
|
18
|
+
export type PillMenuCategory = StatusCategory;
|
|
19
|
+
|
|
20
|
+
/** One value (a status, a task type, a priority…): the current one or a menu option. */
|
|
21
|
+
export interface PillMenuOption {
|
|
22
|
+
/** Stable id — passed to `onSelect` when this option is chosen. */
|
|
23
|
+
id: string | number;
|
|
24
|
+
/** Visible name. */
|
|
25
|
+
name: string;
|
|
26
|
+
/**
|
|
27
|
+
* Optional glyph rendered before the name — in the pill and in its menu
|
|
28
|
+
* row (e.g. a task-type or priority icon). Decorative: wrapped
|
|
29
|
+
* `aria-hidden`, so the name alone is announced. Size it to the text
|
|
30
|
+
* (~14px lucide icon), at most 16px: menu rows place it in DropdownMenu's
|
|
31
|
+
* fixed 16px icon slot.
|
|
32
|
+
*/
|
|
33
|
+
icon?: ReactNode;
|
|
34
|
+
/** Semantic category → default color: to_do slate / in_progress blue / open violet / done green / won green / lost red. */
|
|
35
|
+
category?: PillMenuCategory;
|
|
36
|
+
/** Explicit palette color — wins over `category` (per-state custom colors). */
|
|
37
|
+
color?: PaletteColor;
|
|
38
|
+
/**
|
|
39
|
+
* Extra `data-*` attributes spread onto this value's interactive element:
|
|
40
|
+
* the trigger button (or the read-only chip) when it is `current`, its menu
|
|
41
|
+
* row when it is one of `options` (e.g. `{ 'data-tour': 'status-pill' }` to
|
|
42
|
+
* target it from a `Tour`, or a test/analytics id). Spread first, so a key
|
|
43
|
+
* here can't override the `id` / `role` / `aria-*` / handlers the component
|
|
44
|
+
* owns; on a menu row it also can't override the row's own `data-tone`.
|
|
45
|
+
* A `data-*` passed on `<PillMenu>` itself (via `{...rest}`) beats
|
|
46
|
+
* `current.attrs`.
|
|
47
|
+
*
|
|
48
|
+
* Anti-pattern: when `current` is the same object as an entry in `options`
|
|
49
|
+
* (`current={options.find(...)}`), its attrs land on BOTH the pill and that
|
|
50
|
+
* menu row (duplicate `data-tour` / `data-testid` while open). Give
|
|
51
|
+
* `current` its own attrs: `current={{ ...opt, attrs: { 'data-tour': 'stage-pill' } }}`.
|
|
52
|
+
*/
|
|
53
|
+
attrs?: Record<`data-${string}`, string>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// `aria-labelledby` is omitted: the trigger's name is component-owned (see
|
|
57
|
+
// `label`), and aria-labelledby would override it. TS doesn't excess-check
|
|
58
|
+
// hyphenated JSX attributes, so this is documentation — it's also stripped
|
|
59
|
+
// at runtime.
|
|
60
|
+
export interface PillMenuProps extends Omit<
|
|
61
|
+
HTMLAttributes<HTMLElement>,
|
|
62
|
+
'onSelect' | 'aria-labelledby'
|
|
63
|
+
> {
|
|
64
|
+
/** The value currently shown on the trigger (or the read-only chip). */
|
|
65
|
+
current: PillMenuOption;
|
|
66
|
+
/**
|
|
67
|
+
* What the value IS, for the trigger's accessible name: `label="type"` →
|
|
68
|
+
* "Change type: Bug". Default: a string `caption` ("Change Pipeline: …"),
|
|
69
|
+
* else the localized "status" ("Change status: …").
|
|
70
|
+
* Pass it as it reads right after "Change" / "Изменить", lower-case, in the
|
|
71
|
+
* UI's language — it is data, not a translatable string. In ru that is the
|
|
72
|
+
* accusative: `label="категорию"`, not "категория".
|
|
73
|
+
*
|
|
74
|
+
* Inside a `<Field>`, pass the field's label here (`label="priority"` under
|
|
75
|
+
* "Priority"): the trigger keeps its own name, so the visible field label
|
|
76
|
+
* reaches AT only through this (WCAG 2.5.3). A dev warning fires if it's
|
|
77
|
+
* missing there.
|
|
78
|
+
*/
|
|
79
|
+
label?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Visible caption rendered inside the pill before the value, separated by a
|
|
82
|
+
* middle dot: `caption="Pipeline"` → "Pipeline · Faeton". For a trigger
|
|
83
|
+
* that must say both what it picks and the current value.
|
|
84
|
+
*
|
|
85
|
+
* Names the trigger only as a fallback: `label` wins ("Change pipeline:
|
|
86
|
+
* Faeton"); with no `label`, a non-blank string caption is used ("Change Pipeline:
|
|
87
|
+
* Faeton") so the visible words stay in the accessible name (WCAG 2.5.3
|
|
88
|
+
* label-in-name). A non-string caption never names it — pass `label` then,
|
|
89
|
+
* containing the caption's words. In the read-only chip (no accessible
|
|
90
|
+
* name override) the caption text is read along with the value; the dot is
|
|
91
|
+
* `aria-hidden` in both. Muted by weight (regular vs the value's medium),
|
|
92
|
+
* not colour: the palette fills leave no contrast headroom for a dimmer
|
|
93
|
+
* foreground. Omitted or blank → no caption, no dot.
|
|
94
|
+
*/
|
|
95
|
+
caption?: ReactNode;
|
|
96
|
+
/**
|
|
97
|
+
* Transition targets, offered in the dropdown. Omitted or empty renders
|
|
98
|
+
* read-only mode: a static colored chip with no button, no menu, no
|
|
99
|
+
* aria-haspopup.
|
|
100
|
+
*/
|
|
101
|
+
options?: PillMenuOption[];
|
|
102
|
+
/** Fired with the chosen option's `id` when a transition target is picked. */
|
|
103
|
+
onSelect?: (id: string | number) => void;
|
|
104
|
+
/** Disables the trigger. Stays colored, dims via opacity. */
|
|
105
|
+
disabled?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Transition in flight: the trigger is non-interactive and keeps its color.
|
|
108
|
+
* Announced from a polite live region the component owns — `aria-busy` is
|
|
109
|
+
* also set but reaches no screen reader on its own. The trigger's accessible
|
|
110
|
+
* name does not change (contrast `EntityChip`): you activated this control,
|
|
111
|
+
* so the change is announced rather than folded into the name.
|
|
112
|
+
*
|
|
113
|
+
* No effect in read-only mode (no `options`), which renders no trigger and
|
|
114
|
+
* so has nothing to mark busy.
|
|
115
|
+
*/
|
|
116
|
+
busy?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Stretch the trigger (or read-only chip) to its container's width, for a
|
|
119
|
+
* form column of full-width controls (`Input`, `Select`, `DatePicker` in
|
|
120
|
+
* vertical `Field`s). Icon + name stay at the start, the chevron moves to
|
|
121
|
+
* the end edge like a `Select` trigger, and the menu is at least as wide as
|
|
122
|
+
* the trigger. Keeps the full-colour fill. Defaults to `false`
|
|
123
|
+
* (content-width pill).
|
|
124
|
+
*/
|
|
125
|
+
fullWidth?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Error state — sets `aria-invalid` on the trigger. `<Field error>` injects
|
|
128
|
+
* it for you. No visual change: the fill IS the value's colour, and the
|
|
129
|
+
* Field's error text carries the error. The read-only chip ignores it (a
|
|
130
|
+
* non-focusable chip isn't a control AT can report invalid).
|
|
131
|
+
*/
|
|
132
|
+
invalid?: boolean;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Injectable custom-property pair for a value's resolved color. */
|
|
136
|
+
function statusColorStyle(status: PillMenuOption): CSSProperties {
|
|
137
|
+
const { bg, fg } = paletteTokens(resolveStatusColor(status));
|
|
138
|
+
return { '--pill-menu-bg': bg, '--pill-menu-fg': fg } as CSSProperties;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Renders the optional caption + icon + name, shared by the pill and the read-only chip (rows use Item's icon slot). */
|
|
142
|
+
function OptionContent({ option, caption }: { option: PillMenuOption; caption?: ReactNode }) {
|
|
143
|
+
return (
|
|
144
|
+
<>
|
|
145
|
+
{caption != null &&
|
|
146
|
+
caption !== false &&
|
|
147
|
+
!(typeof caption === 'string' && !caption.trim()) && (
|
|
148
|
+
<>
|
|
149
|
+
<span className={styles.caption}>{caption}</span>
|
|
150
|
+
<span className={styles.caption} aria-hidden="true">
|
|
151
|
+
·
|
|
152
|
+
</span>
|
|
153
|
+
</>
|
|
154
|
+
)}
|
|
155
|
+
{option.icon != null && (
|
|
156
|
+
<span className={styles.icon} aria-hidden="true">
|
|
157
|
+
{option.icon}
|
|
158
|
+
</span>
|
|
159
|
+
)}
|
|
160
|
+
{option.name}
|
|
161
|
+
</>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Coloured value menu: a coloured pill trigger opening a menu of values (status, type, priority); read-only chip when `options` is omitted.
|
|
167
|
+
* @see docs/components/PillMenu.md
|
|
168
|
+
*/
|
|
169
|
+
export const PillMenu = forwardRef<HTMLElement, PillMenuProps>(function PillMenu(
|
|
170
|
+
{
|
|
171
|
+
current,
|
|
172
|
+
options,
|
|
173
|
+
onSelect,
|
|
174
|
+
label,
|
|
175
|
+
caption,
|
|
176
|
+
disabled = false,
|
|
177
|
+
busy = false,
|
|
178
|
+
fullWidth = false,
|
|
179
|
+
invalid = false,
|
|
180
|
+
className,
|
|
181
|
+
style,
|
|
182
|
+
...props
|
|
183
|
+
},
|
|
184
|
+
ref,
|
|
185
|
+
) {
|
|
186
|
+
// Inside a <Field>, auto-wiring also injects `required` (not valid on a
|
|
187
|
+
// button — there's no aria-required for it) and `aria-labelledby`, which
|
|
188
|
+
// would OVERRIDE the component-owned name: "Change type: Bug" would read
|
|
189
|
+
// as the bare field label "Type", dropping the current value. Neither
|
|
190
|
+
// reaches the DOM; `label` names the value instead. `id` and
|
|
191
|
+
// `aria-describedby` (the error/help text) do pass through.
|
|
192
|
+
const {
|
|
193
|
+
required: _required,
|
|
194
|
+
'aria-labelledby': fieldLabelledBy,
|
|
195
|
+
...rest
|
|
196
|
+
} = props as typeof props & { required?: boolean; 'aria-labelledby'?: string };
|
|
197
|
+
const t = useTranslation();
|
|
198
|
+
// Trigger mode only: the read-only chip has no name for `label` to fix.
|
|
199
|
+
// A boolean dep, not `options` — callers pass a fresh array every render.
|
|
200
|
+
const hasTrigger = options != null && options.length > 0;
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
if (process.env.NODE_ENV !== 'production' && hasTrigger && fieldLabelledBy && !label) {
|
|
203
|
+
console.warn(
|
|
204
|
+
'<PillMenu> received `aria-labelledby` (e.g. inside a <Field>) but no `label`. `aria-labelledby` is ignored — the trigger keeps its own name ("Change <string caption, or status>: …") — so the field label doesn\'t reach assistive tech unless it matches. Pass `label` (e.g. label="priority").',
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}, [fieldLabelledBy, label, hasTrigger]);
|
|
208
|
+
// Deferred for the same reason as Switch: a PillMenu that mounts already
|
|
209
|
+
// busy would otherwise mount its region and text together and announce
|
|
210
|
+
// nothing. See CLAUDE.md Hard rule 10.
|
|
211
|
+
const [busyText, setBusyText] = useState('');
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
setBusyText(busy ? t('pillMenu.busy') : '');
|
|
214
|
+
}, [busy, t]);
|
|
215
|
+
// Component color wins over any consumer `style` — merged AFTER so its
|
|
216
|
+
// `--pill-menu-*` custom properties can't be shadowed by a consumer's
|
|
217
|
+
// own inline style object.
|
|
218
|
+
const mergedStyle: CSSProperties = { ...style, ...statusColorStyle(current) };
|
|
219
|
+
const isBlocked = disabled || busy;
|
|
220
|
+
|
|
221
|
+
// DropdownMenu.Trigger clones an unconditional pointerdown/keydown toggle
|
|
222
|
+
// onto the button — a native `disabled` attribute doesn't stop those
|
|
223
|
+
// handlers from running (jsdom, and some browsers, still deliver
|
|
224
|
+
// pointerdown to disabled buttons). Drive `open` explicitly so it's
|
|
225
|
+
// pinned closed while blocked, regardless of what the trigger's own
|
|
226
|
+
// handlers try to do.
|
|
227
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
228
|
+
|
|
229
|
+
// If the menu is open and a parent re-render flips busy/disabled true,
|
|
230
|
+
// DropdownMenu never fires onOpenChange for that externally-forced close
|
|
231
|
+
// (the `open` prop just renders false) — so uncontrolledOpen would stay
|
|
232
|
+
// stale-true, and the menu would pop back open with no user action once
|
|
233
|
+
// busy/disabled flips off again. React-sanctioned adjust-state-during-
|
|
234
|
+
// render: reset synchronously, before paint.
|
|
235
|
+
if (isBlocked && uncontrolledOpen) setUncontrolledOpen(false);
|
|
236
|
+
|
|
237
|
+
if (!hasTrigger) {
|
|
238
|
+
return (
|
|
239
|
+
// Spread order: current.attrs, then {...rest} (an instance data-* wins),
|
|
240
|
+
// then the chip's own ref/className/style resolution.
|
|
241
|
+
<span
|
|
242
|
+
{...current.attrs}
|
|
243
|
+
{...rest}
|
|
244
|
+
ref={ref as Ref<HTMLSpanElement>}
|
|
245
|
+
className={clsx(styles.chip, fullWidth && styles.fullWidth, className)}
|
|
246
|
+
style={mergedStyle}
|
|
247
|
+
>
|
|
248
|
+
<OptionContent option={current} caption={caption} />
|
|
249
|
+
</span>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<DropdownMenu
|
|
255
|
+
open={isBlocked ? false : uncontrolledOpen}
|
|
256
|
+
onOpenChange={(next) => {
|
|
257
|
+
if (!isBlocked) setUncontrolledOpen(next);
|
|
258
|
+
}}
|
|
259
|
+
>
|
|
260
|
+
<DropdownMenu.Trigger>
|
|
261
|
+
{/* Spread order: current.attrs, then {...rest} (an instance data-*
|
|
262
|
+
wins), then the trigger's aria-label / disabled / aria-busy contract. */}
|
|
263
|
+
<button
|
|
264
|
+
{...current.attrs}
|
|
265
|
+
{...rest}
|
|
266
|
+
ref={ref as Ref<HTMLButtonElement>}
|
|
267
|
+
type="button"
|
|
268
|
+
className={clsx(styles.trigger, fullWidth && styles.fullWidth, className)}
|
|
269
|
+
style={mergedStyle}
|
|
270
|
+
disabled={isBlocked}
|
|
271
|
+
aria-busy={busy || undefined}
|
|
272
|
+
aria-invalid={invalid || undefined}
|
|
273
|
+
aria-label={t('pillMenu.change', {
|
|
274
|
+
label:
|
|
275
|
+
label ||
|
|
276
|
+
(typeof caption === 'string' && caption.trim() ? caption : undefined) ||
|
|
277
|
+
t('pillMenu.defaultLabel'),
|
|
278
|
+
name: current.name,
|
|
279
|
+
})}
|
|
280
|
+
>
|
|
281
|
+
<OptionContent option={current} caption={caption} />
|
|
282
|
+
<svg
|
|
283
|
+
width="10"
|
|
284
|
+
height="6"
|
|
285
|
+
viewBox="0 0 10 6"
|
|
286
|
+
aria-hidden="true"
|
|
287
|
+
className={styles.chevron}
|
|
288
|
+
>
|
|
289
|
+
<path d="M1 1 L5 5 L9 1" stroke="currentColor" strokeWidth="1.5" fill="none" />
|
|
290
|
+
</svg>
|
|
291
|
+
</button>
|
|
292
|
+
</DropdownMenu.Trigger>
|
|
293
|
+
{/* OUTSIDE the <button> on purpose. `button` is Children Presentational
|
|
294
|
+
in ARIA, so a live region nested inside it is spec'd to be pruned —
|
|
295
|
+
the same argument #496 makes about the Retry button inside
|
|
296
|
+
role="img". Chrome happens to expose it, but relying on that is
|
|
297
|
+
exactly the reasoning that left `aria-busy` shipping for years. The
|
|
298
|
+
trigger also goes `disabled` while busy, which is when this needs to
|
|
299
|
+
speak. */}
|
|
300
|
+
<span role="status" aria-live="polite" className={styles.srOnly}>
|
|
301
|
+
{busyText}
|
|
302
|
+
</span>
|
|
303
|
+
<DropdownMenu.Content className={styles.menu}>
|
|
304
|
+
{options.map((option) => (
|
|
305
|
+
<DropdownMenu.Item
|
|
306
|
+
key={option.id}
|
|
307
|
+
// attrs first so they cannot override the row handlers or data-tone
|
|
308
|
+
{...option.attrs}
|
|
309
|
+
onSelect={() => onSelect?.(option.id)}
|
|
310
|
+
className={styles.option}
|
|
311
|
+
style={statusColorStyle(option)}
|
|
312
|
+
// The name stays a plain string child: DropdownMenu's typeahead
|
|
313
|
+
// only reads string children, so wrapping it broke type-to-select.
|
|
314
|
+
// The glyph goes in Item's own fixed-size icon slot (aligned rows,
|
|
315
|
+
// item gap) instead.
|
|
316
|
+
icon={option.icon != null ? <span aria-hidden="true">{option.icon}</span> : undefined}
|
|
317
|
+
>
|
|
318
|
+
{option.name}
|
|
319
|
+
</DropdownMenu.Item>
|
|
320
|
+
))}
|
|
321
|
+
</DropdownMenu.Content>
|
|
322
|
+
</DropdownMenu>
|
|
323
|
+
);
|
|
324
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { cloneElement, isValidElement, type ReactElement, type Ref } from 'react';
|
|
2
|
+
import { usePopoverContext } from './context';
|
|
3
|
+
import { mergeRefs } from '../_internal/refs';
|
|
4
|
+
|
|
5
|
+
export interface PopoverAnchorProps {
|
|
6
|
+
/**
|
|
7
|
+
* Exactly one React element that accepts a ref. Unlike `Popover.Trigger`,
|
|
8
|
+
* Anchor injects ONLY the floating-positioning ref — no `onClick`, no keyboard
|
|
9
|
+
* handler, and no `aria-haspopup` / `aria-expanded` / `aria-controls`. Use it
|
|
10
|
+
* when the anchor element already owns its open-toggle and ARIA (e.g. an
|
|
11
|
+
* interactive `FilterChip` whose body `<button>` self-manages
|
|
12
|
+
* `aria-haspopup`/`aria-expanded`), and you drive the popover's open state
|
|
13
|
+
* yourself (controlled `open` + `onOpenChange`). The child must accept a ref
|
|
14
|
+
* (`forwardRef`); raw DOM elements and this library's components qualify, and
|
|
15
|
+
* it should be focusable (a `<button>` or `tabIndex` host) so Escape can
|
|
16
|
+
* return focus to it on close. Wrapping such a chip in `Popover.Trigger`
|
|
17
|
+
* instead would stamp that ARIA onto its `role="group"` root, not the body
|
|
18
|
+
* button.
|
|
19
|
+
*/
|
|
20
|
+
children: ReactElement;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Positions `Popover.Content` against its child, injecting only the floating ref and no interaction or ARIA (`Popover.Anchor`).
|
|
25
|
+
* @see docs/components/Popover.md
|
|
26
|
+
*/
|
|
27
|
+
export function Anchor({ children }: PopoverAnchorProps) {
|
|
28
|
+
const ctx = usePopoverContext('Anchor');
|
|
29
|
+
if (!isValidElement(children)) {
|
|
30
|
+
throw new Error('<Popover.Anchor> requires exactly one React element child.');
|
|
31
|
+
}
|
|
32
|
+
const childProps = children.props as { ref?: Ref<HTMLElement> };
|
|
33
|
+
// Ref only — NO aria/onClick/onKeyDown. The anchor owns its own toggle + ARIA.
|
|
34
|
+
return cloneElement(children, {
|
|
35
|
+
ref: mergeRefs(ctx.triggerRef, childProps.ref),
|
|
36
|
+
} as object);
|
|
37
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cloneElement,
|
|
3
|
+
isValidElement,
|
|
4
|
+
useCallback,
|
|
5
|
+
type MouseEvent as ReactMouseEvent,
|
|
6
|
+
type ReactElement,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import { usePopoverContext } from './context';
|
|
9
|
+
import { chain } from '../_internal/refs';
|
|
10
|
+
|
|
11
|
+
export interface PopoverCloseProps {
|
|
12
|
+
/**
|
|
13
|
+
* Exactly one React element. The Close clones this element to inject an
|
|
14
|
+
* `onClick` that closes the popover, chained with the child's existing
|
|
15
|
+
* `onClick` (consumer runs first).
|
|
16
|
+
*/
|
|
17
|
+
children: ReactElement;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Wraps a single element so activating it closes the popover (`Popover.Close`).
|
|
22
|
+
* @see docs/components/Popover.md
|
|
23
|
+
*/
|
|
24
|
+
export function Close({ children }: PopoverCloseProps) {
|
|
25
|
+
const ctx = usePopoverContext('Close');
|
|
26
|
+
|
|
27
|
+
if (!isValidElement(children)) {
|
|
28
|
+
throw new Error('<Popover.Close> requires exactly one React element child.');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const childProps = children.props as {
|
|
32
|
+
onClick?: (e: ReactMouseEvent<HTMLElement>) => void;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const handleClick = useCallback(
|
|
36
|
+
(_e: ReactMouseEvent<HTMLElement>) => {
|
|
37
|
+
ctx.closeAll();
|
|
38
|
+
},
|
|
39
|
+
[ctx],
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return cloneElement(children, {
|
|
43
|
+
onClick: chain(childProps.onClick, handleClick),
|
|
44
|
+
} as object);
|
|
45
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { forwardRef, useEffect, useLayoutEffect, useRef, type HTMLAttributes } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import {
|
|
4
|
+
arrow,
|
|
5
|
+
autoUpdate,
|
|
6
|
+
flip,
|
|
7
|
+
offset,
|
|
8
|
+
shift,
|
|
9
|
+
size,
|
|
10
|
+
useFloating,
|
|
11
|
+
type Placement,
|
|
12
|
+
} from '@floating-ui/react-dom';
|
|
13
|
+
import clsx from 'clsx';
|
|
14
|
+
import { usePopoverContext } from './context';
|
|
15
|
+
import { mergeRefs } from '../_internal/refs';
|
|
16
|
+
import { isTourHeld, overlayStack, useFloatingSurface, useInOverlay } from '../_internal/overlay';
|
|
17
|
+
import styles from './Popover.module.scss';
|
|
18
|
+
|
|
19
|
+
/** Which side of the trigger the popover prefers. Floating UI auto-flips if it doesn't fit. */
|
|
20
|
+
export type PopoverSide = 'top' | 'right' | 'bottom' | 'left';
|
|
21
|
+
/** Which edge of the popover aligns to the corresponding trigger edge. */
|
|
22
|
+
export type PopoverAlign = 'start' | 'center' | 'end';
|
|
23
|
+
|
|
24
|
+
export interface PopoverContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
25
|
+
/** Preferred side. Default `'bottom'`. Auto-flips on collision via Floating UI. */
|
|
26
|
+
side?: PopoverSide;
|
|
27
|
+
/** Edge alignment. Default `'center'`. */
|
|
28
|
+
align?: PopoverAlign;
|
|
29
|
+
/** Gap in px between trigger and panel. Default `10` (room for the arrow). */
|
|
30
|
+
sideOffset?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Minimum width in px or any CSS length. Defaults to the token
|
|
33
|
+
* `--size-popover-min-width` (220px) applied via SCSS.
|
|
34
|
+
*/
|
|
35
|
+
minWidth?: number | string;
|
|
36
|
+
/**
|
|
37
|
+
* Maximum width in px or any CSS length, overriding the default cap
|
|
38
|
+
* (`--popover-max-width`, 360px). Use for wide content — calendars, tables —
|
|
39
|
+
* that would otherwise overflow the panel. Accepts a number (px),
|
|
40
|
+
* `'fit-content'`, `'none'` to remove the cap, or any CSS length.
|
|
41
|
+
*/
|
|
42
|
+
maxWidth?: number | string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The floating panel: portaled, auto-flipping, `role="dialog"` with an aria-hidden arrow (`Popover.Content`).
|
|
47
|
+
* @see docs/components/Popover.md
|
|
48
|
+
*/
|
|
49
|
+
export const Content = forwardRef<HTMLDivElement, PopoverContentProps>(function Content(
|
|
50
|
+
{
|
|
51
|
+
side = 'bottom',
|
|
52
|
+
align = 'center',
|
|
53
|
+
sideOffset = 10,
|
|
54
|
+
minWidth,
|
|
55
|
+
maxWidth,
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
'aria-labelledby': ariaLabelledBy,
|
|
59
|
+
...rest
|
|
60
|
+
},
|
|
61
|
+
forwardedRef,
|
|
62
|
+
) {
|
|
63
|
+
const ctx = usePopoverContext('Content');
|
|
64
|
+
const { closeAll, setOpen } = ctx;
|
|
65
|
+
const inOverlay = useInOverlay(ctx.triggerRef, ctx.open);
|
|
66
|
+
// #274: hosts yield Escape while we're open — our capture listener
|
|
67
|
+
// closes us (or one menu level) on the same press instead.
|
|
68
|
+
const floatingId = useFloatingSurface(ctx.open);
|
|
69
|
+
const arrowRef = useRef<HTMLSpanElement | null>(null);
|
|
70
|
+
|
|
71
|
+
const placement: Placement = (align === 'center' ? side : `${side}-${align}`) as Placement;
|
|
72
|
+
|
|
73
|
+
const {
|
|
74
|
+
refs,
|
|
75
|
+
floatingStyles,
|
|
76
|
+
placement: resolvedPlacement,
|
|
77
|
+
middlewareData,
|
|
78
|
+
} = useFloating({
|
|
79
|
+
open: ctx.open,
|
|
80
|
+
placement,
|
|
81
|
+
transform: false,
|
|
82
|
+
middleware: [
|
|
83
|
+
offset(sideOffset),
|
|
84
|
+
flip(),
|
|
85
|
+
shift({ padding: 8 }),
|
|
86
|
+
// #598: expose the room left in the viewport. Only a popover holding a
|
|
87
|
+
// <ScrollArea> as a direct child, or inside one wrapper element that is
|
|
88
|
+
// a direct child, uses it (Popover.module.scss
|
|
89
|
+
// `:has(> [data-scroll-area], …)`): it caps there and the ScrollArea
|
|
90
|
+
// shrinks, so the header stays put.
|
|
91
|
+
// A CSS variable rather than inline max-height, so popovers without a
|
|
92
|
+
// ScrollArea keep today's layout (and the arrow is never clipped).
|
|
93
|
+
size({
|
|
94
|
+
padding: 8,
|
|
95
|
+
apply({ availableHeight, elements }) {
|
|
96
|
+
elements.floating.style.setProperty(
|
|
97
|
+
'--popover-available-height',
|
|
98
|
+
`${Math.max(0, availableHeight)}px`,
|
|
99
|
+
);
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
arrow({ element: arrowRef }),
|
|
103
|
+
],
|
|
104
|
+
whileElementsMounted: autoUpdate,
|
|
105
|
+
elements: { reference: ctx.triggerRef.current },
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const [resolvedSide, resolvedAlign = 'center'] = resolvedPlacement.split('-') as [
|
|
109
|
+
PopoverSide,
|
|
110
|
+
PopoverAlign?,
|
|
111
|
+
];
|
|
112
|
+
const staticSide = ({ top: 'bottom', bottom: 'top', left: 'right', right: 'left' } as const)[
|
|
113
|
+
resolvedSide
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
// Focus the panel on open. preventScroll matches DropdownMenu/Tooltip.
|
|
117
|
+
useLayoutEffect(() => {
|
|
118
|
+
if (!ctx.open) return;
|
|
119
|
+
queueMicrotask(() => ctx.contentRef.current?.focus({ preventScroll: true }));
|
|
120
|
+
}, [ctx.open, ctx.contentRef]);
|
|
121
|
+
|
|
122
|
+
// Escape closes; capture phase fires before focused widgets that may
|
|
123
|
+
// stopPropagation.
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (!ctx.open) return;
|
|
126
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
127
|
+
if (e.key === 'Escape') {
|
|
128
|
+
// #280: defer to a DEEPER floating surface (e.g. a Select open inside
|
|
129
|
+
// this popover) — only the innermost closes on this press.
|
|
130
|
+
if (!overlayStack.isTopFloating(floatingId)) return;
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
overlayStack.consumeEscape(e); // hosts yield even if we ran first (#274)
|
|
133
|
+
closeAll();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
document.addEventListener('keydown', onKeyDown, true);
|
|
137
|
+
return () => document.removeEventListener('keydown', onKeyDown, true);
|
|
138
|
+
}, [ctx.open, closeAll, floatingId]);
|
|
139
|
+
|
|
140
|
+
// Outside-click closes.
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (!ctx.open) return;
|
|
143
|
+
const onPointerDown = (e: PointerEvent) => {
|
|
144
|
+
const target = e.target as Node | null;
|
|
145
|
+
if (!target) return;
|
|
146
|
+
const panel = ctx.contentRef.current;
|
|
147
|
+
const trigger = ctx.triggerRef.current;
|
|
148
|
+
if (panel && panel.contains(target)) return;
|
|
149
|
+
if (trigger && trigger.contains(target)) return;
|
|
150
|
+
// #684: a tour pointing into this popover doesn't dismiss it.
|
|
151
|
+
if (isTourHeld(target, panel, trigger)) return;
|
|
152
|
+
// A floating surface (DropdownMenu / nested Popover / ConfirmationPopover)
|
|
153
|
+
// opened from WITHIN this popover portals to document.body, so it is not a
|
|
154
|
+
// DOM descendant of `panel` — without this a pointerdown inside it would
|
|
155
|
+
// read as "outside" and dismiss this popover before the user can use the
|
|
156
|
+
// nested surface (e.g. clicking a kebab menu item or its confirm dialog).
|
|
157
|
+
// Treat clicks inside any dropdown-menu / popover surface as inside, mirroring
|
|
158
|
+
// DropdownMenu's own outside-click exemption.
|
|
159
|
+
const el = target instanceof Element ? target : target.parentElement;
|
|
160
|
+
if (el?.closest('[data-dropdown-menu-content], [data-popover-content]')) return;
|
|
161
|
+
setOpen(false);
|
|
162
|
+
};
|
|
163
|
+
document.addEventListener('pointerdown', onPointerDown, true);
|
|
164
|
+
return () => document.removeEventListener('pointerdown', onPointerDown, true);
|
|
165
|
+
}, [ctx.open, ctx.contentRef, ctx.triggerRef, setOpen]);
|
|
166
|
+
|
|
167
|
+
if (!ctx.open) return null;
|
|
168
|
+
|
|
169
|
+
const arrowXY = middlewareData.arrow;
|
|
170
|
+
const minWidthStyle =
|
|
171
|
+
minWidth !== undefined
|
|
172
|
+
? typeof minWidth === 'number'
|
|
173
|
+
? `${minWidth}px`
|
|
174
|
+
: minWidth
|
|
175
|
+
: undefined;
|
|
176
|
+
const maxWidthStyle =
|
|
177
|
+
maxWidth !== undefined
|
|
178
|
+
? typeof maxWidth === 'number'
|
|
179
|
+
? `${maxWidth}px`
|
|
180
|
+
: maxWidth
|
|
181
|
+
: undefined;
|
|
182
|
+
|
|
183
|
+
return createPortal(
|
|
184
|
+
<div
|
|
185
|
+
{...rest}
|
|
186
|
+
ref={mergeRefs<HTMLDivElement>(ctx.contentRef, refs.setFloating, forwardedRef)}
|
|
187
|
+
id={ctx.contentId}
|
|
188
|
+
role="dialog"
|
|
189
|
+
aria-modal="false"
|
|
190
|
+
aria-labelledby={ctx.headingId ?? ariaLabelledBy}
|
|
191
|
+
tabIndex={-1}
|
|
192
|
+
data-side={resolvedSide}
|
|
193
|
+
data-align={resolvedAlign}
|
|
194
|
+
data-popover-content=""
|
|
195
|
+
data-in-overlay={inOverlay ? '' : undefined}
|
|
196
|
+
style={{ ...floatingStyles, minWidth: minWidthStyle, maxWidth: maxWidthStyle }}
|
|
197
|
+
className={clsx(styles.content, className)}
|
|
198
|
+
>
|
|
199
|
+
{children}
|
|
200
|
+
<span
|
|
201
|
+
ref={arrowRef}
|
|
202
|
+
aria-hidden="true"
|
|
203
|
+
className={styles.arrow}
|
|
204
|
+
style={{
|
|
205
|
+
left: typeof arrowXY?.x === 'number' ? `${arrowXY.x}px` : undefined,
|
|
206
|
+
top: typeof arrowXY?.y === 'number' ? `${arrowXY.y}px` : undefined,
|
|
207
|
+
[staticSide]: '-6px',
|
|
208
|
+
}}
|
|
209
|
+
/>
|
|
210
|
+
</div>,
|
|
211
|
+
document.body,
|
|
212
|
+
);
|
|
213
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createElement, useId, useLayoutEffect, type HTMLAttributes } from 'react';
|
|
2
|
+
import { usePopoverContext } from './context';
|
|
3
|
+
import { sanitizeId } from '../_internal/refs';
|
|
4
|
+
|
|
5
|
+
export interface PopoverHeadingProps extends HTMLAttributes<HTMLHeadingElement> {
|
|
6
|
+
/**
|
|
7
|
+
* Heading level. Defaults to `'h3'`. Pick the level that fits the
|
|
8
|
+
* surrounding document outline (Popover content is usually a level 3
|
|
9
|
+
* inside a level 2 section).
|
|
10
|
+
*/
|
|
11
|
+
as?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Semantic heading (default `h3`) that names the popover via `aria-labelledby` (`Popover.Heading`).
|
|
16
|
+
* @see docs/components/Popover.md
|
|
17
|
+
*/
|
|
18
|
+
export function Heading({ as = 'h3', id: idProp, children, ...rest }: PopoverHeadingProps) {
|
|
19
|
+
const { setHeadingId } = usePopoverContext('Heading');
|
|
20
|
+
const reactId = useId();
|
|
21
|
+
const id = idProp ?? `popover-heading-${sanitizeId(reactId)}`;
|
|
22
|
+
|
|
23
|
+
useLayoutEffect(() => {
|
|
24
|
+
setHeadingId(id);
|
|
25
|
+
return () => setHeadingId(null);
|
|
26
|
+
// setHeadingId is stable per Popover instance; id changes only if
|
|
27
|
+
// consumer provides one — re-fire is correct in that case.
|
|
28
|
+
}, [setHeadingId, id]);
|
|
29
|
+
|
|
30
|
+
// `createElement` keeps the dynamic tag type-safe across h2–h6 without
|
|
31
|
+
// tripping JSX.IntrinsicElements' SVG-tag variance issue.
|
|
32
|
+
return createElement(as, { id, ...rest }, children);
|
|
33
|
+
}
|