@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,107 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from 'react';
|
|
2
|
+
import type { RichDoc, Range } from '../RichText/engine/model';
|
|
3
|
+
import type { EditKind } from './history';
|
|
4
|
+
import { linkAt, setLink, removeLink } from './links';
|
|
5
|
+
import { readSelection, writeSelection, selectionRect, type Rect } from './selection';
|
|
6
|
+
|
|
7
|
+
/** Open-state of the floating link editor: the captured model range, the href
|
|
8
|
+
* being edited, whether it's editing an existing link (vs. creating) — which
|
|
9
|
+
* gates the Remove action and the empty-href→remove branch — the anchor rect to
|
|
10
|
+
* position against, and a `key` that remounts the bubble on each open. */
|
|
11
|
+
export interface LinkEditorOpen {
|
|
12
|
+
range: Range;
|
|
13
|
+
href: string;
|
|
14
|
+
editing: boolean;
|
|
15
|
+
anchorRect: Rect;
|
|
16
|
+
key: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface UseLinkEditorArgs {
|
|
20
|
+
/** The editable root — read to resolve the live selection and to refocus. */
|
|
21
|
+
rootRef: React.RefObject<HTMLDivElement | null>;
|
|
22
|
+
/** The editor's commit path (history + onChange round-trip). */
|
|
23
|
+
commit: (result: { doc: RichDoc; selection: Range }, kind?: EditKind) => void;
|
|
24
|
+
/** The synchronously-latest controlled doc (`() => latest.current.value`). */
|
|
25
|
+
getValue: () => RichDoc;
|
|
26
|
+
/** The synchronously-latest readOnly flag (`() => latest.current.readOnly`). */
|
|
27
|
+
getReadOnly: () => boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The link-editor cluster, extracted from `RichTextEditor`: owns the open-state
|
|
32
|
+
* and the apply/remove/cancel handlers for the floating link editor. The editor
|
|
33
|
+
* keeps the `<RichTextLinkEditor>` JSX (it needs `rangeRect`/`rootRef` from
|
|
34
|
+
* render scope) and the toolbar's `linkActive` derivation (a render-memo on the
|
|
35
|
+
* live selection, not on this open-state) — only the state + handlers live here.
|
|
36
|
+
*
|
|
37
|
+
* Returns the open-state plus stable handlers. `openLinkEditor` opens for the
|
|
38
|
+
* live selection (editing the link under the caret if there is one — href
|
|
39
|
+
* pre-filled, Remove available — else creating over the selection, inserting at
|
|
40
|
+
* a collapsed caret on Apply); `onLinkApply`/`onLinkRemove` route through
|
|
41
|
+
* `commit`; `onLinkCancel` restores the captured selection and refocuses.
|
|
42
|
+
*/
|
|
43
|
+
export function useLinkEditor({ rootRef, commit, getValue, getReadOnly }: UseLinkEditorArgs) {
|
|
44
|
+
// Link editor state.
|
|
45
|
+
const [linkEditor, setLinkEditor] = useState<LinkEditorOpen | null>(null);
|
|
46
|
+
const linkKeyRef = useRef(0);
|
|
47
|
+
|
|
48
|
+
// Open the link editor for the live selection: edit the link under the caret
|
|
49
|
+
// if there is one (href pre-filled, Remove available), else create over the
|
|
50
|
+
// selection (or insert at a collapsed caret on Apply).
|
|
51
|
+
const openLinkEditor = useCallback(() => {
|
|
52
|
+
if (getReadOnly()) return;
|
|
53
|
+
const root = rootRef.current;
|
|
54
|
+
if (!root) return;
|
|
55
|
+
const range = readSelection(root);
|
|
56
|
+
if (!range) return;
|
|
57
|
+
const existing = linkAt(getValue(), range.focus);
|
|
58
|
+
const anchorRect = selectionRect(root);
|
|
59
|
+
linkKeyRef.current += 1;
|
|
60
|
+
setLinkEditor(
|
|
61
|
+
existing
|
|
62
|
+
? {
|
|
63
|
+
range: existing.range,
|
|
64
|
+
href: existing.href,
|
|
65
|
+
editing: true,
|
|
66
|
+
anchorRect,
|
|
67
|
+
key: linkKeyRef.current,
|
|
68
|
+
}
|
|
69
|
+
: { range, href: '', editing: false, anchorRect, key: linkKeyRef.current },
|
|
70
|
+
);
|
|
71
|
+
}, [rootRef, getValue, getReadOnly]);
|
|
72
|
+
|
|
73
|
+
const onLinkApply = useCallback(
|
|
74
|
+
(href: string) => {
|
|
75
|
+
const le = linkEditor;
|
|
76
|
+
if (!le) return;
|
|
77
|
+
const trimmed = href.trim();
|
|
78
|
+
if (trimmed !== '') {
|
|
79
|
+
commit(setLink(getValue(), le.range, trimmed));
|
|
80
|
+
} else if (le.editing) {
|
|
81
|
+
commit(removeLink(getValue(), le.range));
|
|
82
|
+
}
|
|
83
|
+
// empty href while creating → just close (cancel).
|
|
84
|
+
setLinkEditor(null);
|
|
85
|
+
rootRef.current?.focus();
|
|
86
|
+
},
|
|
87
|
+
[linkEditor, commit, getValue, rootRef],
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const onLinkRemove = useCallback(() => {
|
|
91
|
+
const le = linkEditor;
|
|
92
|
+
if (!le) return;
|
|
93
|
+
commit(removeLink(getValue(), le.range));
|
|
94
|
+
setLinkEditor(null);
|
|
95
|
+
rootRef.current?.focus();
|
|
96
|
+
}, [linkEditor, commit, getValue, rootRef]);
|
|
97
|
+
|
|
98
|
+
const onLinkCancel = useCallback(() => {
|
|
99
|
+
const le = linkEditor;
|
|
100
|
+
setLinkEditor(null);
|
|
101
|
+
const root = rootRef.current;
|
|
102
|
+
if (root && le) writeSelection(root, le.range);
|
|
103
|
+
root?.focus();
|
|
104
|
+
}, [linkEditor, rootRef]);
|
|
105
|
+
|
|
106
|
+
return { linkEditor, openLinkEditor, onLinkApply, onLinkRemove, onLinkCancel };
|
|
107
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// useMention.ts — menu-state hook for RichTextEditor @-mention autocomplete.
|
|
2
|
+
// Owns context detection (driven by the editor's selection/content cycle), async
|
|
3
|
+
// querying with stale-drop, and the active-index for keyboard navigation. DOM
|
|
4
|
+
// glue only; the pure decision lives in mentionContext.ts.
|
|
5
|
+
import { useCallback, useId, useRef, useState } from 'react';
|
|
6
|
+
import type { RichDoc, Range } from '../RichText/engine/model';
|
|
7
|
+
import { runsText } from '../RichText/engine/inlines';
|
|
8
|
+
import { isCollapsed } from '../RichText/engine/position';
|
|
9
|
+
import { selectionRect, type Rect } from './selection';
|
|
10
|
+
import { getMentionContext } from './mentionContext';
|
|
11
|
+
import type { MentionItem } from './mentions';
|
|
12
|
+
|
|
13
|
+
export interface UseMentionParams {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
rootRef: React.RefObject<HTMLElement | null>;
|
|
16
|
+
doc: RichDoc;
|
|
17
|
+
trigger: string;
|
|
18
|
+
onQuery?: (query: string) => MentionItem[] | Promise<MentionItem[]>;
|
|
19
|
+
/** Perform the insertion (editor wires this to commit(insertMention(...))). */
|
|
20
|
+
onInsert: (
|
|
21
|
+
blockId: string,
|
|
22
|
+
range: { from: number; to: number },
|
|
23
|
+
trigger: string,
|
|
24
|
+
item: MentionItem,
|
|
25
|
+
) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UseMentionResult {
|
|
29
|
+
open: boolean;
|
|
30
|
+
items: MentionItem[];
|
|
31
|
+
activeIndex: number;
|
|
32
|
+
anchorRect: Rect | null;
|
|
33
|
+
/**
|
|
34
|
+
* Read the caret rect LIVE (current viewport coords). The menu's Floating UI
|
|
35
|
+
* virtual anchor calls this on every `autoUpdate` (incl. scroll/resize) so the
|
|
36
|
+
* menu tracks the caret instead of sticking to the rect captured on open — the
|
|
37
|
+
* static `anchorRect` only updates on `selectionchange`, which scroll doesn't fire.
|
|
38
|
+
*/
|
|
39
|
+
getAnchorRect: () => Rect | null;
|
|
40
|
+
listboxId: string;
|
|
41
|
+
activeOptionId: string | undefined;
|
|
42
|
+
getOptionId: (index: number) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Recompute the menu from a model selection the EDITOR already read. The hook no
|
|
45
|
+
* longer owns a `selectionchange` listener — the editor drives this from its
|
|
46
|
+
* single consolidated subscription, passing the selection it read once. A
|
|
47
|
+
* `null` / non-collapsed / out-of-trigger-context selection closes the menu.
|
|
48
|
+
*/
|
|
49
|
+
recompute: (sel: Range | null) => void;
|
|
50
|
+
setActiveIndex: (index: number) => void;
|
|
51
|
+
move: (delta: 1 | -1) => void;
|
|
52
|
+
selectIndex: (index: number) => void;
|
|
53
|
+
commitActive: () => void;
|
|
54
|
+
close: () => void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** True when two Rect values are equal (avoids spurious re-renders). */
|
|
58
|
+
function rectEqual(a: Rect | null, b: Rect | null): boolean {
|
|
59
|
+
if (a === b) return true;
|
|
60
|
+
if (!a || !b) return false;
|
|
61
|
+
return a.top === b.top && a.left === b.left && a.width === b.width && a.height === b.height;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function useMention(params: UseMentionParams): UseMentionResult {
|
|
65
|
+
const { enabled, rootRef, doc, trigger, onQuery, onInsert } = params;
|
|
66
|
+
const baseId = useId();
|
|
67
|
+
const listboxId = `${baseId}-mention-listbox`;
|
|
68
|
+
const getOptionId = useCallback((index: number) => `${baseId}-mention-opt-${index}`, [baseId]);
|
|
69
|
+
|
|
70
|
+
const [open, setOpen] = useState(false);
|
|
71
|
+
const [items, setItems] = useState<MentionItem[]>([]);
|
|
72
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
73
|
+
const [anchorRect, setAnchorRect] = useState<Rect | null>(null);
|
|
74
|
+
|
|
75
|
+
// Detected context (block + range), kept in a ref for commitActive.
|
|
76
|
+
const ctxRef = useRef<{ blockId: string; from: number; to: number } | null>(null);
|
|
77
|
+
// Monotonic token to drop stale async resolutions.
|
|
78
|
+
const queryToken = useRef(0);
|
|
79
|
+
// Last query string we issued (dedupe redundant onQuery calls).
|
|
80
|
+
const lastQuery = useRef<string | null>(null);
|
|
81
|
+
// Track open + anchorRect in refs for stable-function pattern.
|
|
82
|
+
const openRef = useRef(false);
|
|
83
|
+
const anchorRectRef = useRef<Rect | null>(null);
|
|
84
|
+
|
|
85
|
+
// Keep latest props in refs so recompute() is stable and doesn't cause effect re-fires.
|
|
86
|
+
const enabledRef = useRef(enabled);
|
|
87
|
+
const docRef = useRef(doc);
|
|
88
|
+
const triggerRef = useRef(trigger);
|
|
89
|
+
const onQueryRef = useRef(onQuery);
|
|
90
|
+
enabledRef.current = enabled;
|
|
91
|
+
docRef.current = doc;
|
|
92
|
+
triggerRef.current = trigger;
|
|
93
|
+
onQueryRef.current = onQuery;
|
|
94
|
+
|
|
95
|
+
const close = useCallback(() => {
|
|
96
|
+
openRef.current = false;
|
|
97
|
+
setOpen(false);
|
|
98
|
+
anchorRectRef.current = null;
|
|
99
|
+
setAnchorRect(null);
|
|
100
|
+
ctxRef.current = null;
|
|
101
|
+
lastQuery.current = null;
|
|
102
|
+
queryToken.current += 1; // invalidate any in-flight query
|
|
103
|
+
}, []);
|
|
104
|
+
|
|
105
|
+
const runQuery = useCallback(
|
|
106
|
+
(query: string) => {
|
|
107
|
+
const qFn = onQueryRef.current;
|
|
108
|
+
if (!qFn) return;
|
|
109
|
+
const token = (queryToken.current += 1);
|
|
110
|
+
Promise.resolve(qFn(query)).then(
|
|
111
|
+
(resolved) => {
|
|
112
|
+
if (token !== queryToken.current) return; // stale
|
|
113
|
+
setItems(resolved);
|
|
114
|
+
setActiveIndex(0);
|
|
115
|
+
},
|
|
116
|
+
() => {
|
|
117
|
+
if (token !== queryToken.current) return;
|
|
118
|
+
setItems([]);
|
|
119
|
+
setActiveIndex(0);
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
},
|
|
123
|
+
[], // stable: reads onQueryRef.current
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Stable recompute — reads all mutable values via refs, never recreated. The
|
|
127
|
+
// editor passes the model selection it already read from its single
|
|
128
|
+
// `selectionchange` listener, so the menu doesn't re-walk the DOM here.
|
|
129
|
+
const recompute = useCallback(
|
|
130
|
+
(sel: Range | null) => {
|
|
131
|
+
const root = rootRef.current;
|
|
132
|
+
const qFn = onQueryRef.current;
|
|
133
|
+
if (!enabledRef.current || !root || !qFn) {
|
|
134
|
+
if (openRef.current) close();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!sel || !isCollapsed(sel)) {
|
|
138
|
+
if (openRef.current) close();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const currentDoc = docRef.current;
|
|
142
|
+
const block = currentDoc.blocks.find((b) => b.id === sel.anchor.blockId);
|
|
143
|
+
if (!block) {
|
|
144
|
+
if (openRef.current) close();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const text = runsText(block.inlines);
|
|
148
|
+
const trig = triggerRef.current;
|
|
149
|
+
const ctx = getMentionContext(text, sel.anchor.offset, trig);
|
|
150
|
+
if (!ctx) {
|
|
151
|
+
if (openRef.current) close();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
ctxRef.current = {
|
|
155
|
+
blockId: block.id,
|
|
156
|
+
from: ctx.triggerOffset,
|
|
157
|
+
to: ctx.triggerOffset + trig.length + ctx.query.length,
|
|
158
|
+
};
|
|
159
|
+
// Only update anchorRect state if the value changed (prevents render loops).
|
|
160
|
+
const newRect = selectionRect(root);
|
|
161
|
+
if (!rectEqual(anchorRectRef.current, newRect)) {
|
|
162
|
+
anchorRectRef.current = newRect;
|
|
163
|
+
setAnchorRect(newRect);
|
|
164
|
+
}
|
|
165
|
+
// Only flip open state if not already open (prevents render loops).
|
|
166
|
+
if (!openRef.current) {
|
|
167
|
+
openRef.current = true;
|
|
168
|
+
setOpen(true);
|
|
169
|
+
}
|
|
170
|
+
if (ctx.query !== lastQuery.current) {
|
|
171
|
+
lastQuery.current = ctx.query;
|
|
172
|
+
runQuery(ctx.query);
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
[rootRef, close, runQuery], // stable: reads props via refs
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
const move = useCallback(
|
|
179
|
+
(delta: 1 | -1) => {
|
|
180
|
+
setActiveIndex((i) => {
|
|
181
|
+
const n = items.length;
|
|
182
|
+
if (n === 0) return 0;
|
|
183
|
+
return (i + delta + n) % n;
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
[items.length],
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const selectIndex = useCallback(
|
|
190
|
+
(index: number) => {
|
|
191
|
+
const ctx = ctxRef.current;
|
|
192
|
+
const item = items[index];
|
|
193
|
+
if (!ctx || !item) return;
|
|
194
|
+
onInsert(ctx.blockId, { from: ctx.from, to: ctx.to }, triggerRef.current, item);
|
|
195
|
+
close();
|
|
196
|
+
},
|
|
197
|
+
[items, onInsert, close],
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
const commitActive = useCallback(() => selectIndex(activeIndex), [selectIndex, activeIndex]);
|
|
201
|
+
|
|
202
|
+
// Live caret rect — read on demand (current viewport coords). Stable identity so
|
|
203
|
+
// the menu's virtual anchor doesn't churn; Floating UI's autoUpdate calls it on
|
|
204
|
+
// scroll/resize so the menu follows the caret.
|
|
205
|
+
const getAnchorRect = useCallback((): Rect | null => {
|
|
206
|
+
const root = rootRef.current;
|
|
207
|
+
return root ? selectionRect(root) : null;
|
|
208
|
+
}, [rootRef]);
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
open,
|
|
212
|
+
items,
|
|
213
|
+
activeIndex,
|
|
214
|
+
anchorRect,
|
|
215
|
+
getAnchorRect,
|
|
216
|
+
listboxId,
|
|
217
|
+
activeOptionId: open && items.length > 0 ? getOptionId(activeIndex) : undefined,
|
|
218
|
+
getOptionId,
|
|
219
|
+
recompute,
|
|
220
|
+
setActiveIndex,
|
|
221
|
+
move,
|
|
222
|
+
selectIndex,
|
|
223
|
+
commitActive,
|
|
224
|
+
close,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// useOverlayRect.ts — shared gutter/handle overlay plumbing for <RichTextEditor>.
|
|
2
|
+
// The block-controls gutter and the image resize handle both (a) measure a target
|
|
3
|
+
// element's box relative to the editor shell, retrying across the mount race, and
|
|
4
|
+
// (b) report drag start/end while guarding against a mid-drag unmount. Both live
|
|
5
|
+
// here so the two overlays don't reimplement them. Internal; NOT exported from
|
|
6
|
+
// the package.
|
|
7
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from 'react';
|
|
8
|
+
|
|
9
|
+
/** A box measured relative to the editor shell (top/left/width/height, all in px). */
|
|
10
|
+
export interface ShellRect {
|
|
11
|
+
top: number;
|
|
12
|
+
left: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Measure `getEl()`'s box relative to the shell (`rootRef`), re-running whenever
|
|
19
|
+
* `key` or `getEl` changes. Returns `null` when the shell or target element is
|
|
20
|
+
* missing, retrying up to twice — the parent's element ref can attach after this
|
|
21
|
+
* child's layout pass on mount, so the first measurement can race and come up empty.
|
|
22
|
+
* Callers derive whatever they need from the returned rect (gutter: top/height;
|
|
23
|
+
* resize handle: the bottom-right corner = top+height / left+width).
|
|
24
|
+
*/
|
|
25
|
+
export function useShellRelativeRect(
|
|
26
|
+
rootRef: RefObject<HTMLElement | null>,
|
|
27
|
+
getEl: () => HTMLElement | null,
|
|
28
|
+
key: unknown,
|
|
29
|
+
): ShellRect | null {
|
|
30
|
+
const [rect, setRect] = useState<ShellRect | null>(null);
|
|
31
|
+
// Bumped to re-run measurement when the shell ref / target element is not yet
|
|
32
|
+
// attached on the first layout-effect pass. Capped at 2.
|
|
33
|
+
const [retry, setRetry] = useState(0);
|
|
34
|
+
useLayoutEffect(() => {
|
|
35
|
+
const root = rootRef.current;
|
|
36
|
+
const el = getEl();
|
|
37
|
+
if (!root || !el) {
|
|
38
|
+
setRect(null);
|
|
39
|
+
if (retry < 2) setRetry((n) => n + 1);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const rootBox = root.getBoundingClientRect();
|
|
43
|
+
const box = el.getBoundingClientRect();
|
|
44
|
+
setRect({
|
|
45
|
+
top: box.top - rootBox.top,
|
|
46
|
+
left: box.left - rootBox.left,
|
|
47
|
+
width: box.width,
|
|
48
|
+
height: box.height,
|
|
49
|
+
});
|
|
50
|
+
}, [rootRef, getEl, key, retry]);
|
|
51
|
+
return rect;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Returns a stable setter to report drag start/end, and fires `onDraggingChange(false)`
|
|
56
|
+
* on unmount — so an overlay that unmounts mid-drag (its content removed, the editor
|
|
57
|
+
* toggled to read-only, etc.) never leaves the editor stuck in a dragging state (no
|
|
58
|
+
* pointerup/cancel fires in that case). The setter reads the latest `onDraggingChange`
|
|
59
|
+
* via a ref, so it stays referentially stable across renders.
|
|
60
|
+
*/
|
|
61
|
+
export function useDraggingReporter(
|
|
62
|
+
onDraggingChange?: (dragging: boolean) => void,
|
|
63
|
+
): (dragging: boolean) => void {
|
|
64
|
+
// Latest callback, read by the stable setter + the unmount cleanup without resubscribing.
|
|
65
|
+
const ref = useRef(onDraggingChange);
|
|
66
|
+
ref.current = onDraggingChange;
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
return () => {
|
|
69
|
+
ref.current?.(false);
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
72
|
+
return useCallback((dragging: boolean) => ref.current?.(dragging), []);
|
|
73
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// useUpload.ts — drives the attachment upload lifecycle for RichTextEditor. Owns
|
|
2
|
+
// the in-flight File map (for retry), inserts spinner blocks, runs onUpload in
|
|
3
|
+
// parallel, and settles each block by id. Editor I/O is injected so the hook is
|
|
4
|
+
// unit-testable without a DOM editor.
|
|
5
|
+
import { useCallback, useRef } from 'react';
|
|
6
|
+
import type { RichDoc, Point } from '../RichText/engine/model';
|
|
7
|
+
import { emptyDoc } from '../RichText/engine/model';
|
|
8
|
+
import {
|
|
9
|
+
insertAttachmentBlock,
|
|
10
|
+
updateAttachmentBlock,
|
|
11
|
+
clearAttachmentFields,
|
|
12
|
+
} from '../RichText/engine/attachment';
|
|
13
|
+
import { computeDisplaySize, measureImageFromFile, type NaturalSize } from './imageSize';
|
|
14
|
+
|
|
15
|
+
/** What a consumer's upload handler must resolve with. */
|
|
16
|
+
export interface UploadResult {
|
|
17
|
+
/** Where the uploaded file now lives. Required. */
|
|
18
|
+
url: string;
|
|
19
|
+
/** Display name; defaults to the File's name. */
|
|
20
|
+
name?: string;
|
|
21
|
+
/** MIME type; defaults to the File's type. Decides image-preview vs file-chip. */
|
|
22
|
+
mime?: string;
|
|
23
|
+
/**
|
|
24
|
+
* NATURAL pixel dimensions of the image (not the on-screen size). The editor
|
|
25
|
+
* derives the initial display size from these — scaling by the device pixel
|
|
26
|
+
* ratio and capping to the editor width — so a retina screenshot isn't inserted
|
|
27
|
+
* at 2× its perceived size. Omit them and the editor measures the file itself.
|
|
28
|
+
*/
|
|
29
|
+
width?: number;
|
|
30
|
+
height?: number;
|
|
31
|
+
/** Initial alt text. */
|
|
32
|
+
alt?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Reject `onUpload` with this to show `message` on the failed attachment block
|
|
37
|
+
* (e.g. the server's "The file may not be larger than 5 MB."). Any other
|
|
38
|
+
* rejection shows only the generic "Upload failed", so raw network/library
|
|
39
|
+
* errors never reach the user. Write `message` for end users, localized.
|
|
40
|
+
*/
|
|
41
|
+
export class UploadError extends Error {
|
|
42
|
+
constructor(message: string) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.name = 'UploadError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Consumer config for `RichTextEditor`'s `upload` prop. */
|
|
49
|
+
export interface UploadConfig {
|
|
50
|
+
/** Upload one file; resolve with where it landed, reject to show an error (reject with an `UploadError` to show its message). */
|
|
51
|
+
onUpload: (file: File) => Promise<UploadResult>;
|
|
52
|
+
/** Optional native file-picker filter, e.g. "image/*,.pdf". Convenience only —
|
|
53
|
+
* it does NOT enforce types (paste bypasses it); enforce in `onUpload`. */
|
|
54
|
+
accept?: string;
|
|
55
|
+
/** Fired with `true` while ≥1 upload is in flight, `false` when all settle. */
|
|
56
|
+
onUploadingChange?: (uploading: boolean) => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface UseUploadArgs {
|
|
60
|
+
config: UploadConfig;
|
|
61
|
+
getValue: () => RichDoc;
|
|
62
|
+
/** Apply the synchronous spinner-block insert (records ONE undo step). */
|
|
63
|
+
applyInsert: (doc: RichDoc) => void;
|
|
64
|
+
/** Apply an async settle patch (resolve/error) WITHOUT a new undo step. */
|
|
65
|
+
applySettle: (doc: RichDoc) => void;
|
|
66
|
+
/** Current caret Point (where to insert). */
|
|
67
|
+
getCaret: () => Point;
|
|
68
|
+
/** Measure an image File's natural pixel size (injectable for tests). */
|
|
69
|
+
measureImage?: (file: File) => Promise<NaturalSize | null>;
|
|
70
|
+
/** Editor content width in CSS px — caps a pasted image's initial width. `0` = no cap. */
|
|
71
|
+
getContentWidth?: () => number;
|
|
72
|
+
/** Current device pixel ratio (injectable for tests). */
|
|
73
|
+
getDevicePixelRatio?: () => number;
|
|
74
|
+
/**
|
|
75
|
+
* Upload-failure feed for the editor's live region: `null` when an attempt
|
|
76
|
+
* starts (clears the last message, so a repeat failure re-announces), the
|
|
77
|
+
* file name + optional `UploadError` reason when it fails.
|
|
78
|
+
*/
|
|
79
|
+
onFailureChange?: (failure: { name: string; reason?: string } | null) => void;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function useUpload({
|
|
83
|
+
config,
|
|
84
|
+
getValue,
|
|
85
|
+
applyInsert,
|
|
86
|
+
applySettle,
|
|
87
|
+
getCaret,
|
|
88
|
+
measureImage = measureImageFromFile,
|
|
89
|
+
getContentWidth = () => 0,
|
|
90
|
+
getDevicePixelRatio = () => (typeof window !== 'undefined' && window.devicePixelRatio) || 1,
|
|
91
|
+
onFailureChange,
|
|
92
|
+
}: UseUploadArgs) {
|
|
93
|
+
const filesRef = useRef(new Map<string, File>()); // block id → File (for retry)
|
|
94
|
+
const inflightRef = useRef(0);
|
|
95
|
+
|
|
96
|
+
const setInflight = useCallback(
|
|
97
|
+
(delta: number) => {
|
|
98
|
+
const prev = inflightRef.current;
|
|
99
|
+
inflightRef.current = Math.max(0, prev + delta);
|
|
100
|
+
if (prev === 0 && inflightRef.current > 0) config.onUploadingChange?.(true);
|
|
101
|
+
if (prev > 0 && inflightRef.current === 0) config.onUploadingChange?.(false);
|
|
102
|
+
},
|
|
103
|
+
[config],
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const runUpload = useCallback(
|
|
107
|
+
(id: string, file: File) => {
|
|
108
|
+
setInflight(1);
|
|
109
|
+
onFailureChange?.(null);
|
|
110
|
+
config
|
|
111
|
+
.onUpload(file)
|
|
112
|
+
.then(
|
|
113
|
+
async (res) => {
|
|
114
|
+
filesRef.current.delete(id);
|
|
115
|
+
// Natural dims: prefer the consumer's reported size (documented as
|
|
116
|
+
// natural px), else measure the File. Then lay out at perceived size
|
|
117
|
+
// (÷DPR) capped to the editor width — so a retina screenshot doesn't
|
|
118
|
+
// come in at 2× the size you saw.
|
|
119
|
+
let naturalW = res.width;
|
|
120
|
+
let naturalH = res.height;
|
|
121
|
+
// Only a COMPLETE consumer pair short-circuits the measure; if either is
|
|
122
|
+
// missing we measure and take the measured pair WHOLESALE, so a partial
|
|
123
|
+
// (and possibly inconsistent) consumer value can't distort the aspect.
|
|
124
|
+
// The measure is best-effort — a throwing injected measurer must not
|
|
125
|
+
// strand the block mid-upload, so swallow and fall back to "unsized".
|
|
126
|
+
if (naturalW == null || naturalH == null) {
|
|
127
|
+
let measured: NaturalSize | null = null;
|
|
128
|
+
try {
|
|
129
|
+
measured = await measureImage(file);
|
|
130
|
+
} catch {
|
|
131
|
+
measured = null;
|
|
132
|
+
}
|
|
133
|
+
naturalW = measured?.width ?? naturalW;
|
|
134
|
+
naturalH = measured?.height ?? naturalH;
|
|
135
|
+
}
|
|
136
|
+
const display = computeDisplaySize(
|
|
137
|
+
naturalW,
|
|
138
|
+
naturalH,
|
|
139
|
+
getDevicePixelRatio(),
|
|
140
|
+
getContentWidth(),
|
|
141
|
+
);
|
|
142
|
+
applySettle(
|
|
143
|
+
updateAttachmentBlock(getValue(), id, {
|
|
144
|
+
status: 'ready',
|
|
145
|
+
src: res.url,
|
|
146
|
+
name: res.name ?? file.name,
|
|
147
|
+
mime: res.mime ?? file.type,
|
|
148
|
+
width: display?.width,
|
|
149
|
+
height: display?.height,
|
|
150
|
+
alt: res.alt,
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
(err: unknown) => {
|
|
155
|
+
// Opt-in only: a plain Error's message ("Failed to fetch", …) is not
|
|
156
|
+
// written for end users.
|
|
157
|
+
const reason = err instanceof UploadError && err.message ? err.message : undefined;
|
|
158
|
+
applySettle(
|
|
159
|
+
updateAttachmentBlock(getValue(), id, { status: 'error', uploadError: reason }),
|
|
160
|
+
);
|
|
161
|
+
onFailureChange?.({ name: file.name, reason });
|
|
162
|
+
},
|
|
163
|
+
)
|
|
164
|
+
.finally(() => setInflight(-1));
|
|
165
|
+
},
|
|
166
|
+
[
|
|
167
|
+
config,
|
|
168
|
+
getValue,
|
|
169
|
+
applySettle,
|
|
170
|
+
setInflight,
|
|
171
|
+
measureImage,
|
|
172
|
+
getContentWidth,
|
|
173
|
+
getDevicePixelRatio,
|
|
174
|
+
onFailureChange,
|
|
175
|
+
],
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
const uploadFiles = useCallback(
|
|
179
|
+
(files: File[]) => {
|
|
180
|
+
if (files.length === 0) return;
|
|
181
|
+
// Insert all spinner blocks first (in order), then kick off uploads.
|
|
182
|
+
let doc = getValue();
|
|
183
|
+
let caret = getCaret();
|
|
184
|
+
const pending: { id: string; file: File }[] = [];
|
|
185
|
+
for (const file of files) {
|
|
186
|
+
const r = insertAttachmentBlock(doc, caret, {
|
|
187
|
+
name: file.name,
|
|
188
|
+
mime: file.type,
|
|
189
|
+
status: 'uploading',
|
|
190
|
+
});
|
|
191
|
+
// Skip a file whose insert no-op'd (caret block not in the doc) rather
|
|
192
|
+
// than crashing the whole batch on a stale/invalid caret.
|
|
193
|
+
if (r.attachmentId === null) continue;
|
|
194
|
+
doc = r.doc;
|
|
195
|
+
caret = r.selection.anchor; // next insert goes after the trailing paragraph
|
|
196
|
+
pending.push({ id: r.attachmentId, file });
|
|
197
|
+
filesRef.current.set(r.attachmentId, file);
|
|
198
|
+
}
|
|
199
|
+
if (pending.length === 0) return;
|
|
200
|
+
applyInsert(doc);
|
|
201
|
+
pending.forEach(({ id, file }) => runUpload(id, file));
|
|
202
|
+
},
|
|
203
|
+
[getValue, getCaret, applyInsert, runUpload],
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const retry = useCallback(
|
|
207
|
+
(id: string) => {
|
|
208
|
+
const file = filesRef.current.get(id);
|
|
209
|
+
if (!file) return;
|
|
210
|
+
applySettle(
|
|
211
|
+
clearAttachmentFields(updateAttachmentBlock(getValue(), id, { status: 'uploading' }), id, [
|
|
212
|
+
'uploadError',
|
|
213
|
+
]),
|
|
214
|
+
);
|
|
215
|
+
runUpload(id, file);
|
|
216
|
+
},
|
|
217
|
+
[getValue, applySettle, runUpload],
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const remove = useCallback(
|
|
221
|
+
(id: string) => {
|
|
222
|
+
filesRef.current.delete(id);
|
|
223
|
+
const doc = getValue();
|
|
224
|
+
const blocks = doc.blocks.filter((b) => b.id !== id);
|
|
225
|
+
// If that emptied the doc, leave one empty paragraph (mirrors the engine's
|
|
226
|
+
// removeBlockUnit) — never silently re-keep the block the user removed.
|
|
227
|
+
applySettle(blocks.length ? { blocks } : emptyDoc());
|
|
228
|
+
},
|
|
229
|
+
[getValue, applySettle],
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const replace = useCallback(
|
|
233
|
+
(id: string, file: File) => {
|
|
234
|
+
filesRef.current.set(id, file);
|
|
235
|
+
// Keep align/alt; drop the old display size so the new file's natural size
|
|
236
|
+
// applies. Then run the upload (settles src/name/mime via runUpload).
|
|
237
|
+
let doc = updateAttachmentBlock(getValue(), id, { status: 'uploading' });
|
|
238
|
+
doc = clearAttachmentFields(doc, id, ['width', 'height']);
|
|
239
|
+
applySettle(doc);
|
|
240
|
+
runUpload(id, file);
|
|
241
|
+
},
|
|
242
|
+
[getValue, applySettle, runUpload],
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
return { uploadFiles, retry, remove, replace, accept: config.accept };
|
|
246
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
@use './Screen.tokens';
|
|
2
|
+
|
|
3
|
+
// Screen is a layout-owning primitive — the documented exception to the
|
|
4
|
+
// "no layout properties on components" rule (like Page / Rail). It takes over
|
|
5
|
+
// the viewport (min-height) and grows its main slot (flex) because laying out a
|
|
6
|
+
// full-bleed screen is its entire job. (stylelint's property-disallowed-list
|
|
7
|
+
// blocks flex-grow / flex-basis but not the `flex` shorthand or min-height, so
|
|
8
|
+
// no disable is needed here.)
|
|
9
|
+
.root {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
padding: var(--screen-padding);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.fillViewport {
|
|
16
|
+
min-height: 100vh;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.fillBlock {
|
|
20
|
+
min-height: var(--screen-block-min-height);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.main {
|
|
24
|
+
flex: 1;
|
|
25
|
+
display: grid;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.alignCenter {
|
|
29
|
+
place-items: center;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.alignStart {
|
|
33
|
+
place-items: start center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.backdropPlain {
|
|
37
|
+
background: var(--screen-backdrop-plain);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.backdropAccent {
|
|
41
|
+
background: var(--screen-backdrop-accent);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.backdropDanger {
|
|
45
|
+
background: var(--screen-backdrop-danger);
|
|
46
|
+
}
|