@cube-dev/ui-kit 0.159.0 → 0.160.0
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/dist/CHANGELOG.md +20 -0
- package/dist/_internal/hooks/use-chained-callback.js +1 -1
- package/dist/_internal/hooks/use-debounced-value.js +1 -1
- package/dist/_internal/hooks/use-deprecation-warning.js +1 -1
- package/dist/_internal/hooks/use-event.js +1 -1
- package/dist/_internal/hooks/use-is-first-render.js +1 -1
- package/dist/_internal/hooks/use-sync-ref.js +1 -1
- package/dist/_internal/hooks/use-timer/timer.js +1 -1
- package/dist/_internal/hooks/use-timer/use-timer.js +1 -1
- package/dist/_internal/hooks/use-warn.js +1 -1
- package/dist/components/Block.js +1 -1
- package/dist/components/CollectionItem.js +1 -1
- package/dist/components/GlobalStyles.js +1 -1
- package/dist/components/GridProvider.js +1 -1
- package/dist/components/HiddenInput.js +1 -1
- package/dist/components/Root.js +1 -1
- package/dist/components/actions/Action/Action.js +1 -1
- package/dist/components/actions/Banner/Banner.js +1 -1
- package/dist/components/actions/Button/Button.d.ts +2 -2
- package/dist/components/actions/Button/Button.js +5 -3
- package/dist/components/actions/Button/Button.js.map +1 -1
- package/dist/components/actions/ButtonGroup/ButtonGroup.js +1 -1
- package/dist/components/actions/ButtonSplit/ButtonSplit.js +1 -1
- package/dist/components/actions/ButtonSplit/context.js +1 -1
- package/dist/components/actions/CommandMenu/CommandMenu.js +1 -1
- package/dist/components/actions/CommandMenu/styled.js +1 -1
- package/dist/components/actions/ItemAction/ItemAction.d.ts +1 -1
- package/dist/components/actions/ItemAction/ItemAction.js +4 -3
- package/dist/components/actions/ItemAction/ItemAction.js.map +1 -1
- package/dist/components/actions/ItemActionContext.js +1 -1
- package/dist/components/actions/ItemButton/ItemButton.js +1 -1
- package/dist/components/actions/Link/Link.js +1 -1
- package/dist/components/actions/Menu/Menu.js +1 -1
- package/dist/components/actions/Menu/MenuItem.js +1 -1
- package/dist/components/actions/Menu/MenuSection.js +1 -1
- package/dist/components/actions/Menu/MenuTrigger.js +1 -1
- package/dist/components/actions/Menu/SubMenuTrigger.js +1 -1
- package/dist/components/actions/Menu/SubmenuTriggerContext.js +1 -1
- package/dist/components/actions/Menu/context.js +1 -1
- package/dist/components/actions/Menu/styled.js +1 -1
- package/dist/components/actions/index.js +1 -1
- package/dist/components/actions/use-action.js +1 -1
- package/dist/components/actions/use-anchored-menu.js +1 -1
- package/dist/components/actions/use-context-menu.js +1 -1
- package/dist/components/content/ActiveZone/ActiveZone.js +1 -1
- package/dist/components/content/Alert/Alert.js +1 -1
- package/dist/components/content/Alert/use-alert.js +1 -1
- package/dist/components/content/Avatar/Avatar.js +1 -1
- package/dist/components/content/Badge/Badge.js +1 -1
- package/dist/components/content/Card/Card.js +1 -1
- package/dist/components/content/Content.js +1 -1
- package/dist/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
- package/dist/components/content/CopySnippet/CopySnippet.js +1 -1
- package/dist/components/content/Disclosure/Disclosure.js +8 -4
- package/dist/components/content/Disclosure/Disclosure.js.map +1 -1
- package/dist/components/content/Divider.js +1 -1
- package/dist/components/content/Footer.js +1 -1
- package/dist/components/content/Header.js +1 -1
- package/dist/components/content/HotKeys/HotKeys.js +1 -1
- package/dist/components/content/InfoBadge/InfoBadge.js +1 -1
- package/dist/components/content/InlineInput/InlineInput.js +1 -1
- package/dist/components/content/Item/Item.d.ts +1 -1
- package/dist/components/content/Item/Item.js +12 -6
- package/dist/components/content/Item/Item.js.map +1 -1
- package/dist/components/content/ItemBadge/ItemBadge.js +1 -1
- package/dist/components/content/ItemCard/ItemCard.js +1 -1
- package/dist/components/content/Layout/GridLayout.js +1 -1
- package/dist/components/content/Layout/Layout.js +1 -1
- package/dist/components/content/Layout/LayoutBlock.js +1 -1
- package/dist/components/content/Layout/LayoutCenter.js +1 -1
- package/dist/components/content/Layout/LayoutContainer.js +1 -1
- package/dist/components/content/Layout/LayoutContent.js +1 -1
- package/dist/components/content/Layout/LayoutContext.js +1 -1
- package/dist/components/content/Layout/LayoutFlex.js +1 -1
- package/dist/components/content/Layout/LayoutFooter.js +1 -1
- package/dist/components/content/Layout/LayoutGrid.js +1 -1
- package/dist/components/content/Layout/LayoutHeader.js +1 -1
- package/dist/components/content/Layout/LayoutPane.js +1 -1
- package/dist/components/content/Layout/LayoutPanel.js +1 -1
- package/dist/components/content/Layout/LayoutPanelHeader.js +1 -1
- package/dist/components/content/Layout/LayoutToolbar.js +1 -1
- package/dist/components/content/Layout/hooks/useTinyScrollbar.js +1 -1
- package/dist/components/content/Layout/index.js +1 -1
- package/dist/components/content/Layout/utils.js +1 -1
- package/dist/components/content/Paragraph.js +1 -1
- package/dist/components/content/Placeholder/Placeholder.js +1 -1
- package/dist/components/content/PrismCode/PrismCode.js +1 -1
- package/dist/components/content/PrismCode/prismSetup.js +1 -1
- package/dist/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
- package/dist/components/content/Result/Result.js +1 -1
- package/dist/components/content/Skeleton/Skeleton.js +1 -1
- package/dist/components/content/Tag/Tag.js +1 -1
- package/dist/components/content/Text.js +1 -1
- package/dist/components/content/TextItem/TextItem.js +1 -1
- package/dist/components/content/Title.js +1 -1
- package/dist/components/content/Tree/Tree.js +1 -1
- package/dist/components/content/Tree/TreeNode.js +1 -1
- package/dist/components/content/Tree/styled.js +1 -1
- package/dist/components/content/Tree/tree-index.js +1 -1
- package/dist/components/content/Tree/use-checkbox-tree.js +1 -1
- package/dist/components/content/Tree/use-load-data.js +1 -1
- package/dist/components/content/highlightText.js +1 -1
- package/dist/components/content/use-auto-tooltip.js +1 -1
- package/dist/components/data/DataTable/DataTable.js +1 -1
- package/dist/components/data/ItemTable/ItemTable.js +1 -1
- package/dist/components/data/ItemTable/ItemTableBulkBar.js +1 -1
- package/dist/components/data/ItemTable/ItemTableDragPreview.js +1 -1
- package/dist/components/data/ItemTable/ItemTableFooter.js +1 -1
- package/dist/components/data/ItemTable/ItemTableToolbar.js +1 -1
- package/dist/components/data/TableBase/ColumnResizer.js +1 -1
- package/dist/components/data/TableBase/RowCollection.js +1 -1
- package/dist/components/data/TableBase/TableHeaderCell.js +1 -1
- package/dist/components/data/TableBase/TableRow.js +1 -1
- package/dist/components/data/TableBase/TableView.js +1 -1
- package/dist/components/data/TableBase/column-menu.js +1 -1
- package/dist/components/data/TableBase/column-tint.js +1 -1
- package/dist/components/data/TableBase/row-menu.js +1 -1
- package/dist/components/data/TableBase/styled.js +1 -1
- package/dist/components/data/TableBase/types.js +1 -1
- package/dist/components/data/TableBase/use-cell-selection.js +0 -0
- package/dist/components/data/TableBase/use-column-order.js +1 -1
- package/dist/components/data/TableBase/use-container-width.js +1 -1
- package/dist/components/data/TableBase/use-row-move-animation.js +1 -1
- package/dist/components/data/TableBase/use-scrollability.js +1 -1
- package/dist/components/data/TableBase/use-table-columns.js +1 -1
- package/dist/components/data/TableBase/use-table-search.js +1 -1
- package/dist/components/data/TableBase/use-table-selection.js +1 -1
- package/dist/components/data/TableBase/use-table-sort.js +1 -1
- package/dist/components/data/TableBase/use-table-sorts.js +1 -1
- package/dist/components/data/TableBase/use-table-storage.js +1 -1
- package/dist/components/fields/Checkbox/Checkbox.js +1 -1
- package/dist/components/fields/Checkbox/CheckboxGroup.js +1 -1
- package/dist/components/fields/Checkbox/context.js +1 -1
- package/dist/components/fields/ColorInput/ColorInput.js +1 -1
- package/dist/components/fields/ColorPicker/ColorPicker.js +1 -1
- package/dist/components/fields/ColorSwatchGroup/ColorSwatchGroup.js +1 -1
- package/dist/components/fields/ComboBox/ComboBox.js +1 -1
- package/dist/components/fields/CommandTextArea/CommandTextArea.js +1 -1
- package/dist/components/fields/CommandTextArea/caretPosition.js +1 -1
- package/dist/components/fields/CommandTextArea/useCaretAnchor.js +1 -1
- package/dist/components/fields/DatePicker/DateInput.js +1 -1
- package/dist/components/fields/DatePicker/DateInputBase.js +1 -1
- package/dist/components/fields/DatePicker/DatePicker.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerButton.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerElement.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerInput.js +1 -1
- package/dist/components/fields/DatePicker/DatePickerSegment.js +1 -1
- package/dist/components/fields/DatePicker/DateRangePicker.js +1 -1
- package/dist/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
- package/dist/components/fields/DatePicker/MonthPicker.js +1 -1
- package/dist/components/fields/DatePicker/PeriodPicker.js +1 -1
- package/dist/components/fields/DatePicker/QuarterPicker.js +1 -1
- package/dist/components/fields/DatePicker/TimeInput.js +1 -1
- package/dist/components/fields/DatePicker/WeekPicker.js +1 -1
- package/dist/components/fields/DatePicker/YearPicker.js +1 -1
- package/dist/components/fields/DatePicker/parseDate.js +1 -1
- package/dist/components/fields/DatePicker/period.js +1 -1
- package/dist/components/fields/DatePicker/props.js +1 -1
- package/dist/components/fields/DatePicker/utils.js +1 -1
- package/dist/components/fields/FileInput/FileInput.js +1 -1
- package/dist/components/fields/FilterListBox/FilterListBox.js +1 -1
- package/dist/components/fields/FilterPicker/FilterPicker.js +1 -1
- package/dist/components/fields/Input/Input.js +1 -1
- package/dist/components/fields/ListBox/DraggableListBox.js +1 -1
- package/dist/components/fields/ListBox/ListBox.js +1 -1
- package/dist/components/fields/ListBoxPopover/ListBoxPopover.js +1 -1
- package/dist/components/fields/ListBoxPopover/listNavigation.js +1 -1
- package/dist/components/fields/ListBoxPopover/useCompositeFocus.js +1 -1
- package/dist/components/fields/NumberInput/NumberInput.js +1 -1
- package/dist/components/fields/NumberInput/StepButton.js +1 -1
- package/dist/components/fields/PasswordInput/PasswordInput.js +1 -1
- package/dist/components/fields/Picker/Picker.js +1 -1
- package/dist/components/fields/RadioGroup/Radio.js +1 -1
- package/dist/components/fields/RadioGroup/RadioGroup.js +1 -1
- package/dist/components/fields/RadioGroup/context.js +1 -1
- package/dist/components/fields/SearchComboBox/SearchComboBox.js +1 -1
- package/dist/components/fields/SearchInput/SearchInput.js +1 -1
- package/dist/components/fields/Select/Select.js +1 -1
- package/dist/components/fields/Slider/Gradation.js +1 -1
- package/dist/components/fields/Slider/HueSlider.js +1 -1
- package/dist/components/fields/Slider/RangeSlider.js +1 -1
- package/dist/components/fields/Slider/Slider.js +1 -1
- package/dist/components/fields/Slider/SliderBase.js +1 -1
- package/dist/components/fields/Slider/SliderThumb.js +1 -1
- package/dist/components/fields/Slider/SliderTrack.js +1 -1
- package/dist/components/fields/Slider/elements.js +1 -1
- package/dist/components/fields/Slider/index.js +1 -1
- package/dist/components/fields/Switch/Switch.js +1 -1
- package/dist/components/fields/TextArea/TextArea.js +1 -1
- package/dist/components/fields/TextInput/TextInput.js +1 -1
- package/dist/components/fields/TextInput/TextInputBase.js +1 -1
- package/dist/components/fields/TextInputMapper/TextInputMapper.js +1 -1
- package/dist/components/fields/color/ColorPanel.js +1 -1
- package/dist/components/fields/color/ColorSwatch.js +1 -1
- package/dist/components/fields/color/channels.js +1 -1
- package/dist/components/fields/color/color.js +1 -1
- package/dist/components/fields/color/context.js +1 -1
- package/dist/components/form/FieldWrapper/FieldWrapper.js +1 -1
- package/dist/components/form/Form/Field.js +1 -1
- package/dist/components/form/Form/Form.js +1 -1
- package/dist/components/form/Form/ResetButton/ResetButton.js +1 -1
- package/dist/components/form/Form/SubmitButton/SubmitButton.js +1 -1
- package/dist/components/form/Form/SubmitError.js +1 -1
- package/dist/components/form/Form/index.js +1 -1
- package/dist/components/form/Form/use-field/use-field-props.js +1 -1
- package/dist/components/form/Form/use-field/use-field.js +1 -1
- package/dist/components/form/Form/use-form.js +1 -1
- package/dist/components/form/Form/validation.js +1 -1
- package/dist/components/form/Label.js +1 -1
- package/dist/components/form/validation/ValidationIndicator.js +1 -1
- package/dist/components/form/validation/resolve-validation-props.js +1 -1
- package/dist/components/form/validation/use-validation-props.js +1 -1
- package/dist/components/form/wrapper.js +1 -1
- package/dist/components/helpers/DisplayTransition/DisplayTransition.js +1 -1
- package/dist/components/helpers/IconSwitch/IconSwitch.js +1 -1
- package/dist/components/layout/Board/Board.js +28 -4
- package/dist/components/layout/Board/Board.js.map +1 -1
- package/dist/components/layout/Board/BoardProvider.js +1 -1
- package/dist/components/layout/Board/BoardResponsive.js +1 -1
- package/dist/components/layout/Board/Widget.js +1 -1
- package/dist/components/layout/Board/WidgetHost.js +6 -3
- package/dist/components/layout/Board/WidgetHost.js.map +1 -1
- package/dist/components/layout/Board/board-context.js +1 -1
- package/dist/components/layout/Board/board-store.js +1 -1
- package/dist/components/layout/Board/grid-core/calculate.js +1 -1
- package/dist/components/layout/Board/grid-core/collision.js +1 -1
- package/dist/components/layout/Board/grid-core/compactors.js +1 -1
- package/dist/components/layout/Board/grid-core/constraints.js +1 -1
- package/dist/components/layout/Board/grid-core/group-move.js +138 -33
- package/dist/components/layout/Board/grid-core/group-move.js.map +1 -1
- package/dist/components/layout/Board/grid-core/layout.js +1 -1
- package/dist/components/layout/Board/grid-core/sort.js +1 -1
- package/dist/components/layout/Board/index.js +1 -1
- package/dist/components/layout/Board/responsive-utils.js +1 -1
- package/dist/components/layout/Board/use-board-layout.js +1 -1
- package/dist/components/layout/Board/use-board-registry.js +1 -1
- package/dist/components/layout/Board/use-board-select-modifier-key.js +1 -1
- package/dist/components/layout/Board/use-board-selection.js +1 -1
- package/dist/components/layout/Flex.js +1 -1
- package/dist/components/layout/Flow.js +1 -1
- package/dist/components/layout/Grid.js +1 -1
- package/dist/components/layout/Panel.js +1 -1
- package/dist/components/layout/Prefix.js +1 -1
- package/dist/components/layout/ResizablePanel.js +1 -1
- package/dist/components/layout/Space.js +1 -1
- package/dist/components/layout/Suffix.js +1 -1
- package/dist/components/navigation/Pagination/Pagination.js +1 -1
- package/dist/components/navigation/Pagination/use-pagination.js +1 -1
- package/dist/components/navigation/Tabs/DraggableTabList.js +1 -1
- package/dist/components/navigation/Tabs/TabButton.js +1 -1
- package/dist/components/navigation/Tabs/TabDropIndicator.js +1 -1
- package/dist/components/navigation/Tabs/TabPanel.js +1 -1
- package/dist/components/navigation/Tabs/TabPicker.js +1 -1
- package/dist/components/navigation/Tabs/Tabs.js +1 -1
- package/dist/components/navigation/Tabs/TabsAction.js +1 -1
- package/dist/components/navigation/Tabs/TabsContext.js +1 -1
- package/dist/components/navigation/Tabs/popover-placement.js +1 -1
- package/dist/components/navigation/Tabs/styled.js +1 -1
- package/dist/components/navigation/Tabs/types.js +1 -1
- package/dist/components/navigation/Tabs/use-tab-editing.js +1 -1
- package/dist/components/navigation/Tabs/use-tab-indicator.js +1 -1
- package/dist/components/organisms/StatsCard/StatsCard.js +1 -1
- package/dist/components/other/Calendar/Calendar.js +1 -1
- package/dist/components/other/Calendar/CalendarCell.js +1 -1
- package/dist/components/other/Calendar/CalendarGrid.js +1 -1
- package/dist/components/other/Calendar/PeriodCalendar.js +1 -1
- package/dist/components/other/Calendar/RangeCalendar.js +1 -1
- package/dist/components/other/CubeLogo/CubeLogo.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialog.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
- package/dist/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
- package/dist/components/overlays/Dialog/Dialog.js +1 -1
- package/dist/components/overlays/Dialog/DialogContainer.js +1 -1
- package/dist/components/overlays/Dialog/DialogForm.js +1 -1
- package/dist/components/overlays/Dialog/DialogTrigger.js +1 -1
- package/dist/components/overlays/Dialog/context.js +1 -1
- package/dist/components/overlays/Dialog/use-dialog-container.js +1 -1
- package/dist/components/overlays/Modal/Modal.js +1 -1
- package/dist/components/overlays/Modal/OpenTransitionContext.js +1 -1
- package/dist/components/overlays/Modal/Overlay.js +1 -1
- package/dist/components/overlays/Modal/Popover.js +1 -1
- package/dist/components/overlays/Modal/Tray.js +1 -1
- package/dist/components/overlays/Modal/Underlay.js +1 -1
- package/dist/components/overlays/Notifications/Notification.js +1 -1
- package/dist/components/overlays/Notifications/NotificationAction.js +1 -1
- package/dist/components/overlays/Notifications/NotificationCard.js +1 -1
- package/dist/components/overlays/Notifications/NotificationContext.js +1 -1
- package/dist/components/overlays/Notifications/NotificationItem.js +1 -1
- package/dist/components/overlays/Notifications/OverlayContainer.js +1 -1
- package/dist/components/overlays/Notifications/OverlayProvider.js +1 -1
- package/dist/components/overlays/Notifications/PersistentNotificationsList.js +1 -1
- package/dist/components/overlays/Notifications/dismissed-storage.js +1 -1
- package/dist/components/overlays/Notifications/format-relative-time.js +1 -1
- package/dist/components/overlays/Notifications/index.js +1 -1
- package/dist/components/overlays/Notifications/use-notification-state.js +1 -1
- package/dist/components/overlays/Notifications/use-notifications.js +1 -1
- package/dist/components/overlays/Notifications/use-overlay-timers.js +1 -1
- package/dist/components/overlays/Notifications/use-persistent-notifications.js +1 -1
- package/dist/components/overlays/Notifications/use-persistent-state.js +1 -1
- package/dist/components/overlays/Notifications/use-toast-state.js +1 -1
- package/dist/components/overlays/Toast/ToastItem.js +1 -1
- package/dist/components/overlays/Toast/index.js +1 -1
- package/dist/components/overlays/Toast/useProgressToast.js +1 -1
- package/dist/components/overlays/Toast/useToast.js +1 -1
- package/dist/components/overlays/Tooltip/Tooltip.js +1 -1
- package/dist/components/overlays/Tooltip/TooltipProvider.js +1 -1
- package/dist/components/overlays/Tooltip/TooltipTrigger.js +1 -1
- package/dist/components/overlays/Tooltip/context.js +1 -1
- package/dist/components/portal/Portal.js +1 -1
- package/dist/components/portal/PortalProvider.js +1 -1
- package/dist/components/portal/usePortal.js +1 -1
- package/dist/components/shared/DraggableCollection.js +1 -1
- package/dist/components/shared/InvalidIcon.js +1 -1
- package/dist/components/shared/ValidIcon.js +1 -1
- package/dist/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
- package/dist/components/status/Spin/Cube.js +1 -1
- package/dist/components/status/Spin/InternalSpinner.js +1 -1
- package/dist/components/status/Spin/Spin.js +1 -1
- package/dist/components/status/Spin/SpinsContainer.js +1 -1
- package/dist/data/item-themes.d.ts +1 -1
- package/dist/data/item-themes.js +45 -2
- package/dist/data/item-themes.js.map +1 -1
- package/dist/data/themes.js +1 -1
- package/dist/eslint-plugin/defaults.generated.js +1 -1
- package/dist/eslint-plugin/index.js +1 -1
- package/dist/eslint-plugin/rules/no-redundant-default-prop.js +1 -1
- package/dist/i18n/I18nProvider.js +1 -1
- package/dist/i18n/createFormatter.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/instance.js +1 -1
- package/dist/i18n/locales/de-DE/uikit.js +1 -1
- package/dist/i18n/locales/en-US/uikit.js +1 -1
- package/dist/i18n/locales/es-ES/uikit.js +1 -1
- package/dist/i18n/locales/es-MX/uikit.js +1 -1
- package/dist/i18n/locales/fr-FR/uikit.js +1 -1
- package/dist/i18n/locales/it-IT/uikit.js +1 -1
- package/dist/i18n/locales/ja-JP/uikit.js +1 -1
- package/dist/i18n/locales/nb-NO/uikit.js +1 -1
- package/dist/i18n/locales/pt-BR/uikit.js +1 -1
- package/dist/i18n/locales/pt-PT/uikit.js +1 -1
- package/dist/i18n/locales/sv-SE/uikit.js +1 -1
- package/dist/i18n/locales/vi-VN/uikit.js +1 -1
- package/dist/i18n/locales.js +1 -1
- package/dist/i18n/useFormatter.js +1 -1
- package/dist/i18n/useI18n.js +1 -1
- package/dist/icons/AdjustmentsHorizontalIcon.js +1 -1
- package/dist/icons/AdjustmentsIcon.js +1 -1
- package/dist/icons/AiIcon.js +1 -1
- package/dist/icons/AreaChartIcon.js +1 -1
- package/dist/icons/ArrowNarrowDownIcon.js +1 -1
- package/dist/icons/ArrowNarrowUpIcon.js +1 -1
- package/dist/icons/BackwardIcon.js +1 -1
- package/dist/icons/BarChartIcon.js +1 -1
- package/dist/icons/BellFilledIcon.js +1 -1
- package/dist/icons/BellIcon.js +1 -1
- package/dist/icons/BooleanIcon.js +1 -1
- package/dist/icons/CalendarEditIcon.js +1 -1
- package/dist/icons/CalendarIcon.js +1 -1
- package/dist/icons/CaretDownIcon.js +1 -1
- package/dist/icons/CaretUpIcon.js +1 -1
- package/dist/icons/ChartAreaStackedIcon.js +1 -1
- package/dist/icons/ChartAreaStackedPercentageIcon.js +1 -1
- package/dist/icons/ChartBarGroupedHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarGroupedIcon.js +1 -1
- package/dist/icons/ChartBarHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarLineIcon.js +1 -1
- package/dist/icons/ChartBarStackedHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarStackedIcon.js +1 -1
- package/dist/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
- package/dist/icons/ChartBarStackedPercentageIcon.js +1 -1
- package/dist/icons/ChartBoxPlot2Icon.js +1 -1
- package/dist/icons/ChartBoxPlotIcon.js +1 -1
- package/dist/icons/ChartBubbleIcon.js +1 -1
- package/dist/icons/ChartDonut2Icon.js +1 -1
- package/dist/icons/ChartFunnelIcon.js +1 -1
- package/dist/icons/ChartHeatmapIcon.js +1 -1
- package/dist/icons/ChartKPIIcon.js +1 -1
- package/dist/icons/ChartPie2Icon.js +1 -1
- package/dist/icons/ChartScatterIcon.js +1 -1
- package/dist/icons/CheckCircleFilledIcon.js +1 -1
- package/dist/icons/CheckCircleIcon.js +1 -1
- package/dist/icons/CheckIcon.js +1 -1
- package/dist/icons/CircleFilledIcon.js +1 -1
- package/dist/icons/ClearIcon.js +1 -1
- package/dist/icons/CloseCircleFilledIcon.js +1 -1
- package/dist/icons/CloseCircleIcon.js +1 -1
- package/dist/icons/CloseIcon.js +1 -1
- package/dist/icons/CodeIcon.js +1 -1
- package/dist/icons/ColumnTotalIcon.js +1 -1
- package/dist/icons/CopyIcon.js +1 -1
- package/dist/icons/CountIcon.js +1 -1
- package/dist/icons/CubeIcon.js +1 -1
- package/dist/icons/CubePauseIcon.js +1 -1
- package/dist/icons/CubePlayIcon.js +1 -1
- package/dist/icons/CurrencyDollarIcon.js +1 -1
- package/dist/icons/DangerIcon.js +1 -1
- package/dist/icons/DashboardIcon.js +1 -1
- package/dist/icons/DatabaseIcon.js +1 -1
- package/dist/icons/DecimalDecreaseIcon.js +1 -1
- package/dist/icons/DecimalIncreaseIcon.js +1 -1
- package/dist/icons/DirectionIcon.js +1 -1
- package/dist/icons/DonutIcon.js +1 -1
- package/dist/icons/DownIcon.js +1 -1
- package/dist/icons/EditIcon.js +1 -1
- package/dist/icons/ExclamationCircleFilledIcon.js +1 -1
- package/dist/icons/ExclamationCircleIcon.js +1 -1
- package/dist/icons/ExclamationIcon.js +1 -1
- package/dist/icons/EyeIcon.js +1 -1
- package/dist/icons/EyeInvisibleIcon.js +1 -1
- package/dist/icons/FilterIcon.js +1 -1
- package/dist/icons/FolderFilledIcon.js +1 -1
- package/dist/icons/FolderIcon.js +1 -1
- package/dist/icons/FolderOpenFilledIcon.js +1 -1
- package/dist/icons/FolderOpenIcon.js +1 -1
- package/dist/icons/ForwardIcon.js +1 -1
- package/dist/icons/GripVerticalIcon.js +1 -1
- package/dist/icons/HierarchyIcon.js +1 -1
- package/dist/icons/HierarchyOpenIcon.js +1 -1
- package/dist/icons/Icon.js +1 -1
- package/dist/icons/InfoCircleIcon.js +1 -1
- package/dist/icons/InfoIcon.js +1 -1
- package/dist/icons/KeyIcon.js +1 -1
- package/dist/icons/LeftIcon.js +1 -1
- package/dist/icons/LineChartIcon.js +1 -1
- package/dist/icons/LoadingIcon.js +1 -1
- package/dist/icons/LockFilledIcon.js +1 -1
- package/dist/icons/LockIcon.js +1 -1
- package/dist/icons/MoreIcon.js +1 -1
- package/dist/icons/NotAllowedIcon.js +1 -1
- package/dist/icons/Number123Icon.js +1 -1
- package/dist/icons/NumberIcon.js +1 -1
- package/dist/icons/PauseCircleFilledIcon.js +1 -1
- package/dist/icons/PauseCircleIcon.js +1 -1
- package/dist/icons/PauseIcon.js +1 -1
- package/dist/icons/PercentageIcon.js +1 -1
- package/dist/icons/PieChartIcon.js +1 -1
- package/dist/icons/PipetteIcon.js +1 -1
- package/dist/icons/PlayCircleIcon.js +1 -1
- package/dist/icons/PlayIcon.js +1 -1
- package/dist/icons/PlusIcon.js +1 -1
- package/dist/icons/ProgressBarIcon.js +1 -1
- package/dist/icons/ReloadIcon.js +1 -1
- package/dist/icons/ReportIcon.js +1 -1
- package/dist/icons/ReturnIcon.js +1 -1
- package/dist/icons/RightIcon.js +1 -1
- package/dist/icons/RowTotalsIcon.js +1 -1
- package/dist/icons/SchemeIcon.js +1 -1
- package/dist/icons/SearchIcon.js +1 -1
- package/dist/icons/SemanticQueryIcon.js +1 -1
- package/dist/icons/SettingsIcon.js +1 -1
- package/dist/icons/ShieldFilledIcon.js +1 -1
- package/dist/icons/ShieldIcon.js +1 -1
- package/dist/icons/SlashIcon.js +1 -1
- package/dist/icons/SparklesIcon.js +1 -1
- package/dist/icons/SqlIcon.js +1 -1
- package/dist/icons/StatsIcon.js +1 -1
- package/dist/icons/StopIcon.js +1 -1
- package/dist/icons/StringIcon.js +1 -1
- package/dist/icons/SubtotalsIcon.js +1 -1
- package/dist/icons/SwitchIcon.js +1 -1
- package/dist/icons/TableIcon.js +1 -1
- package/dist/icons/ThumbsDownIcon.js +1 -1
- package/dist/icons/ThumbsUpIcon.js +1 -1
- package/dist/icons/ThunderboltCrossedIcon.js +1 -1
- package/dist/icons/ThunderboltFilledIcon.js +1 -1
- package/dist/icons/ThunderboltIcon.js +1 -1
- package/dist/icons/TimeIcon.js +1 -1
- package/dist/icons/TrashIcon.js +1 -1
- package/dist/icons/UnlockIcon.js +1 -1
- package/dist/icons/UpIcon.js +1 -1
- package/dist/icons/UserGroupIcon.js +1 -1
- package/dist/icons/UserIcon.js +1 -1
- package/dist/icons/UserLockIcon.js +1 -1
- package/dist/icons/ViewIcon.js +1 -1
- package/dist/icons/WarningFilledIcon.js +1 -1
- package/dist/icons/WarningIcon.js +1 -1
- package/dist/icons/wrap-icon.js +1 -1
- package/dist/index.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/providers/TrackingProvider.js +1 -1
- package/dist/providers/navigationAdapter.default.js +1 -1
- package/dist/tokens/base.js +1 -1
- package/dist/tokens/color-theme.js +1 -1
- package/dist/tokens/colors.js +1 -1
- package/dist/tokens/index.js +1 -1
- package/dist/tokens/layout.js +1 -1
- package/dist/tokens/lazy-styles.js +1 -1
- package/dist/tokens/palette-config.js +1 -1
- package/dist/tokens/palette.js +1 -1
- package/dist/tokens/shadows.js +1 -1
- package/dist/tokens/sizes.js +1 -1
- package/dist/tokens/spacing.js +1 -1
- package/dist/tokens/typography.js +1 -1
- package/dist/utils/ResizeSensor.js +1 -1
- package/dist/utils/is-dev-env.js +1 -1
- package/dist/utils/modules.js +1 -1
- package/dist/utils/promise.js +1 -1
- package/dist/utils/raf.js +1 -1
- package/dist/utils/random.js +1 -1
- package/dist/utils/range.js +1 -1
- package/dist/utils/react/RenderCache.js +1 -1
- package/dist/utils/react/Slots.js +1 -1
- package/dist/utils/react/chain.js +1 -1
- package/dist/utils/react/disabledProps.js +1 -1
- package/dist/utils/react/forwardRefWithGenerics.js +1 -1
- package/dist/utils/react/index.js +1 -1
- package/dist/utils/react/interactions.js +1 -1
- package/dist/utils/react/isTextOnly.js +1 -1
- package/dist/utils/react/mapProps.js +1 -1
- package/dist/utils/react/mergeProps.js +1 -1
- package/dist/utils/react/nullableValue.js +1 -1
- package/dist/utils/react/resolveIcon.js +1 -1
- package/dist/utils/react/sharedStore.js +1 -1
- package/dist/utils/react/useBufferedValue.js +1 -1
- package/dist/utils/react/useCombinedRefs.js +1 -1
- package/dist/utils/react/useControlledFocusVisible.js +1 -1
- package/dist/utils/react/useEventBus.js +1 -1
- package/dist/utils/react/useId.js +1 -1
- package/dist/utils/react/useIsDarwin.js +1 -1
- package/dist/utils/react/useKeySymbols.js +1 -1
- package/dist/utils/react/useLayoutEffect.js +1 -1
- package/dist/utils/react/useLocalStorage.js +1 -1
- package/dist/utils/react/useMergeStyles.js +1 -1
- package/dist/utils/react/usePopoverSync.js +1 -1
- package/dist/utils/react/useQaProps.js +1 -1
- package/dist/utils/react/useViewportSize.js +1 -1
- package/dist/utils/react/wrapNodeIfPlain.js +1 -1
- package/dist/utils/selection.js +1 -1
- package/dist/utils/styles.js +1 -1
- package/dist/utils/tree.js +1 -1
- package/dist/utils/warnings.js +1 -1
- package/dist/version.js +2 -2
- package/docs/components/actions/Button.md +2 -1
- package/docs/components/content/Item.md +17 -2
- package/docs/components/layout/Board.md +23 -12
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Board.js","names":["mergeProps"],"sources":["../../../../src/components/layout/Board/Board.tsx"],"sourcesContent":["import { useResizeObserver } from '@react-aria/utils';\nimport {\n AllBaseProps,\n CONTAINER_STYLES,\n ContainerStyleProps,\n filterBaseProps,\n mergeStyles,\n Styles,\n tasty,\n} from '@tenphi/tasty';\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { useFocusWithin } from 'react-aria';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { useI18n } from '../../../i18n';\nimport { mergeProps, useCombinedRefs } from '../../../utils/react';\nimport { extractStyles } from '../../../utils/styles';\n\nimport {\n BoardEntry,\n BoardGridLinesContext,\n BoardMetrics,\n BoardMetricsContext,\n useBoardGridLines,\n useBoardHost,\n useBoardMetrics,\n useBoardRegistry,\n} from './board-context';\nimport { BoardProvider } from './BoardProvider';\nimport {\n applySizeConstraints,\n bottom,\n calcGridColWidth,\n calcGridItemPosition,\n calcWH,\n cloneLayout,\n Compactor,\n CompactType,\n correctBounds,\n defaultConstraints,\n getAllCollisions,\n getCompactor,\n getLayoutItem,\n LayoutConstraint,\n LayoutItem,\n modifyLayout,\n Position,\n PositionParams,\n ResizeHandleAxis,\n} from './grid-core';\nimport { useBoardLayout } from './use-board-layout';\nimport { useBoardSelectModifierKey } from './use-board-select-modifier-key';\nimport { BoardSelectionMode, useBoardSelection } from './use-board-selection';\nimport { ResizePhase, WidgetHost } from './WidgetHost';\n\nimport type { CubeBoardWidgetProps } from './Widget';\n\nconst BoardElement = tasty({\n qa: 'Board',\n styles: {\n position: 'relative',\n display: 'block',\n width: '100%',\n flexGrow: 1,\n height: 'min 0',\n fill: '#surface',\n boxSizing: 'border-box',\n // The board takes focus programmatically (never by Tab — it is `tabIndex=-1`)\n // as a parking spot: after `onWidgetsDelete` the focused widget host is\n // about to unmount, and after a marquee focus is nowhere near the board, so\n // in both cases Escape and Delete — handled here rather than on `document` —\n // would have nothing to reach. A focus ring on a parking spot is noise: it\n // announces a state the user cannot act on and did not ask for. Same reason\n // `Dialog` drops it on its own focusable container.\n outline: 0,\n },\n});\n\nconst ContentLayer = tasty({\n styles: {\n position: 'absolute',\n inset: 0,\n },\n});\n\n// The drop-slot preview. `#primary` rather than the legacy `#purple` alias -\n// same hue, current token. It has to stay distinguishable from a *selected*\n// widget (a tint + solid border + ring, see `WidgetHost`) and from a live\n// marquee (dashed), since all three can be on screen at once.\nconst PlaceholderElement = tasty({\n qa: 'BoardPlaceholder',\n styles: {\n position: 'absolute',\n top: 0,\n left: 0,\n fill: '#primary.10',\n radius: '1cr',\n border: '#primary.40',\n zIndex: 2,\n pointerEvents: 'none',\n transition: 'inset 80ms linear, width 80ms linear, height 80ms linear',\n boxSizing: 'border-box',\n },\n});\n\n// The rubber-band selection rectangle. Dashed is the discriminator: nothing else\n// on a board is dashed, and it reads as a transient lasso rather than a place\n// something is about to land. Sits above the widgets (1) and the placeholder (2).\nconst MarqueeElement = tasty({\n qa: 'BoardMarquee',\n styles: {\n position: 'absolute',\n top: 0,\n left: 0,\n fill: '#primary-accent-surface.06',\n border: '1bw dashed #primary-border',\n radius: '1cr',\n zIndex: 3,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n});\n\n// Visually-hidden live region. Selection changes are announced here because a\n// board widget cannot carry `aria-selected`: that attribute is only valid on\n// collection roles (`option`, `gridcell`, `row`, …) whose children must be\n// presentational, and widgets host arbitrary interactive content. This element\n// also owns the shared \"Selected\" hint every selected host points at via\n// `aria-describedby`.\nconst A11yLayer = tasty({\n styles: {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n border: 0,\n },\n});\n\n// Grid overlay drawn behind the widgets. Each snap cell is painted as a faint\n// block (column stripes intersected with a row-band alpha mask); the margin gaps\n// between cells stay transparent. The element is positioned as an explicit\n// rectangle inset by the board's resolved padding and sized to the grid content\n// so the padding reads as a symmetric frame on every edge. Its size, position\n// and gradients come from the board's position params via inline `style`. The\n// fill uses the `#border` token (via its CSS var) so it adapts to the scheme.\nconst GridOverlayElement = tasty({\n qa: 'BoardGridOverlay',\n styles: {\n position: 'absolute',\n zIndex: 0,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n opacity: '.5',\n },\n});\n\nexport type BoardCompactType = 'vertical' | 'horizontal' | 'free' | null;\n\n/**\n * Payload passed to the drag/resize lifecycle callbacks. `layout` is the board's\n * current layout at the moment the callback fires, `item` is the affected item\n * (falls back to `oldItem` if the item just left this board via a cross-board\n * transfer), `oldItem` is that item as it was when the gesture started, and\n * `placeholder` is the current drop-slot preview (if any).\n *\n * The plural fields describe the whole gesture: a group drag moves every\n * selected widget at once, so `items`/`oldItems`/`placeholders` list them all,\n * grabbed widget first. An ordinary drag or a resize produces exactly one entry,\n * so `items[0] === item` and `placeholders[0] === placeholder` always hold.\n */\nexport interface BoardInteractionInfo {\n layout: LayoutItem[];\n item: LayoutItem;\n oldItem: LayoutItem;\n placeholder: LayoutItem | null;\n /** Every item in this gesture, grabbed first. */\n items: LayoutItem[];\n /** Those items as they were when the gesture started, same order. */\n oldItems: LayoutItem[];\n /** Every drop-slot preview. Empty exactly when `placeholder` is `null`. */\n placeholders: LayoutItem[];\n}\n\n/** Visibility of the internal grid-line overlay. */\nexport type BoardGridLines = boolean | 'drag';\n\n/**\n * The subset of `Board.Widget` props a `Board` can set as defaults for every\n * widget it hosts (via `widgetProps`). Excludes `id`/`children`, which are\n * per-widget. Per-widget `Board.Widget` props override these.\n */\nexport type CubeBoardWidgetDefaults = Omit<\n CubeBoardWidgetProps,\n 'id' | 'children'\n>;\n\nexport interface CubeBoardProps\n extends Omit<\n AllBaseProps,\n 'children' | 'onDragStart' | 'onDrag' | 'onResize'\n >,\n Omit<ContainerStyleProps, 'margin'> {\n /** Stable board id (used for cross-board drag). Auto-generated if omitted. */\n id?: string;\n /** Controlled layout. */\n layout?: LayoutItem[];\n /** Initial layout for uncontrolled usage. */\n defaultLayout?: LayoutItem[];\n onLayoutChange?: (layout: LayoutItem[]) => void;\n /** Called when a drag gesture starts. */\n onDragStart?: (info: BoardInteractionInfo) => void;\n /** Called on every step of a drag gesture. */\n onDrag?: (info: BoardInteractionInfo) => void;\n /** Called when a drag gesture ends (after the layout is committed). */\n onDragStop?: (info: BoardInteractionInfo) => void;\n /** Called when a resize gesture starts. */\n onResizeStart?: (info: BoardInteractionInfo) => void;\n /** Called on every step of a resize gesture. */\n onResize?: (info: BoardInteractionInfo) => void;\n /** Called when a resize gesture ends (after the layout is committed). */\n onResizeStop?: (info: BoardInteractionInfo) => void;\n /** Number of columns. @default 12 */\n cols?: number;\n /** Row height in pixels. @default 100 */\n rowHeight?: number;\n /** [horizontal, vertical] margin between widgets in pixels. @default [8, 8] */\n margin?: [number, number];\n /**\n * [horizontal, vertical] padding inside the board. Defaults to `margin`, or\n * to `[0, 0]` for an aligned nested board (`isAligned`) so its grid lines up\n * with the ancestor board's.\n */\n containerPadding?: [number, number];\n /** Maximum number of rows. @default Infinity */\n maxRows?: number;\n /**\n * Empty grid rows kept below the content. The board renders this many rows\n * taller than its widgets need, so there is always somewhere to start a\n * marquee and somewhere to drop a widget past the end — a board that hugs its\n * content has neither once the grid is full. Clamped by `maxRows`.\n * @default 0\n */\n extraRows?: number;\n /**\n * Compaction behavior. `'vertical'` / `'horizontal'` reflow widgets to remove\n * gaps; `'free'` places each widget exactly where dropped and never pushes its\n * neighbours (pair with `allowOverlap` to let widgets stack, otherwise moving\n * onto an occupied cell is blocked); `null` disables compaction but still\n * resolves collisions the legacy react-grid-layout way. @default 'vertical'\n */\n compact?: BoardCompactType;\n /** Allow widgets to overlap. @default false */\n allowOverlap?: boolean;\n /** Block movement into occupied cells instead of pushing. @default false */\n preventCollision?: boolean;\n /** Enable dragging for all widgets. @default true */\n isDraggable?: boolean;\n /** Enable resizing for all widgets. @default true */\n isResizable?: boolean;\n /** Whether this board accepts widgets dropped from other boards. @default true */\n isDroppable?: boolean;\n /** Which resize handles to show. @default ['se'] */\n resizeHandles?: ResizeHandleAxis[];\n /**\n * CSS selector for elements that must not start a pointer drag (e.g. form\n * controls inside a widget: `\"input,textarea,button,a,.no-drag\"`). Does not\n * affect keyboard moves — those only run when the widget host itself is\n * focused. Can be overridden per widget on `Board.Widget`.\n */\n dragCancel?: string;\n /**\n * CSS selector for the only elements from which a pointer drag may start.\n * Can be overridden per widget on `Board.Widget`.\n */\n dragHandle?: string;\n /**\n * Show grid lines behind the widgets. `true` always shows them, `'drag'`\n * shows them only while a widget is being dragged or resized, `false` never.\n * @default false\n */\n showGridLines?: BoardGridLines;\n /**\n * Align this board's grid with an ancestor `Board`'s layout. Only takes\n * effect when the board is nested inside another `Board`'s widget. When set,\n * every cell matches the parent's cell size exactly: the board inherits the\n * parent's column pitch (deriving its own column count from its measured\n * width) and uses the parent's row height verbatim. It never shrinks rows to\n * fit; pair it with an `isAutoHeight` container so the widget grows to fit its\n * rows at that height. @default false\n */\n isAligned?: boolean;\n /**\n * Whether widgets can be selected, and how many at a time. `'multiple'` also\n * enables the marquee and rigid group movement: dragging any selected widget\n * moves the whole selection. @default 'none'\n */\n selectionMode?: BoardSelectionMode;\n /** Controlled selection. Keys are layout item ids (`LayoutItem.i`). */\n selectedKeys?: string[];\n /** Initial selection for uncontrolled usage. */\n defaultSelectedKeys?: string[];\n /**\n * Called when the selection changes. Keys are deduped and returned in the\n * board's layout order, never in click order.\n */\n onSelectionChange?: (keys: string[]) => void;\n /**\n * CSS selector for descendants whose clicks must never change the selection\n * (form controls, buttons, links). Mirrors `dragCancel`; can be overridden per\n * widget. Pass `''` to disable the guard entirely.\n * @default BOARD_SELECTION_CANCEL\n */\n selectionCancel?: string;\n /**\n * Draw a rubber-band (marquee) selection when a drag starts on empty board\n * space. Only meaningful with `selectionMode=\"multiple\"`.\n * @default selectionMode === 'multiple'\n */\n allowMarqueeSelection?: boolean;\n /**\n * Called when the user presses <kbd>Delete</kbd>/<kbd>Backspace</kbd> with a\n * non-empty selection, and focus is inside the board but not in an editable\n * field. Board never mutates the layout itself — removing the widgets is the\n * consumer's job. Board only handles these keys when this handler is set.\n */\n onWidgetsDelete?: (keys: string[]) => void;\n /** Grid/item layout constraints. */\n constraints?: LayoutConstraint[];\n /**\n * Explicit container width in pixels. When provided, disables automatic width\n * measurement (useful for SSR and tests).\n */\n width?: number;\n /**\n * Default props applied to every widget this board hosts. Per-widget\n * `Board.Widget` props override these. Use it to add a card border to every\n * widget (`widgetProps={{ isCard: true }}`) or set shared sizing/`styles`\n * defaults without repeating them on each `Board.Widget`.\n */\n widgetProps?: Partial<CubeBoardWidgetDefaults>;\n children?: ReactNode;\n}\n\n/**\n * Descendants whose clicks never change the selection. A widget is a large\n * surface the user also clicks to *work with*, so anything interactive inside it\n * must keep its click. `[data-no-select]` is the escape hatch for an app's own\n * custom controls.\n */\nexport const BOARD_SELECTION_CANCEL =\n 'input,textarea,select,button,a,[role=\"button\"],[role=\"menuitem\"],' +\n '[role=\"checkbox\"],[role=\"switch\"],[role=\"tab\"],[contenteditable=\"true\"],' +\n '[data-no-select]';\n\n/** Manhattan distance a pointer must travel before a press becomes a marquee. */\nconst MARQUEE_THRESHOLD = 4;\n\n/**\n * Whether an event landed in a text-editing context. Checking the *event target*\n * beats `document.activeElement`: it stays correct for content rendered through\n * a portal, and it cannot be fooled by focus that moved between the keystroke\n * and the handler.\n */\nfunction isEditableTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n if (!el || typeof el.closest !== 'function') return false;\n\n return !!el.closest('input,textarea,select,[contenteditable=\"true\"]');\n}\n\nfunction compactTypeToCore(compact: BoardCompactType): CompactType {\n if (compact === 'free') return null;\n return compact;\n}\n\nfunction BoardInner(\n props: CubeBoardProps,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n id: providedId,\n layout: controlledLayout,\n defaultLayout,\n onLayoutChange,\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize: onResizeProp,\n onResizeStop,\n cols = 12,\n rowHeight = 100,\n margin = [8, 8],\n containerPadding,\n maxRows = Infinity,\n extraRows = 0,\n compact = 'vertical',\n allowOverlap = false,\n preventCollision = false,\n isDraggable = true,\n isResizable = true,\n isDroppable = true,\n resizeHandles = ['se'],\n dragCancel,\n dragHandle,\n showGridLines,\n isAligned = false,\n selectionMode = 'none',\n selectedKeys,\n defaultSelectedKeys,\n onSelectionChange,\n selectionCancel = BOARD_SELECTION_CANCEL,\n allowMarqueeSelection = selectionMode === 'multiple',\n onWidgetsDelete,\n constraints,\n width: providedWidth,\n widgetProps,\n children,\n ...otherProps\n } = props;\n\n const registry = useBoardRegistry()!;\n const parentMetrics = useBoardMetrics();\n const host = useBoardHost();\n const inheritedGridLines = useBoardGridLines();\n const aligned = isAligned && !!parentMetrics;\n // `widgetProps` may carry container style props directly (e.g. `fill`,\n // `padding`, `radius`) alongside an explicit `styles` object, mirroring\n // `Board.Widget`. Extract them into a single style map here so those defaults\n // actually reach every widget - forwarding only `widgetProps.styles` would\n // drop the direct props. A direct prop wins over the same key in `styles`.\n const widgetPropsStyles = useMemo<Styles | undefined>(() => {\n if (!widgetProps) return undefined;\n const extracted = extractStyles(widgetProps, CONTAINER_STYLES);\n return Object.keys(extracted).length > 0 ? extracted : undefined;\n }, [widgetProps]);\n // A nested board with no explicit `showGridLines` inherits the ancestor's:\n // when the ancestor has grid lines enabled, show them here while dragging.\n const effectiveShowGridLines: BoardGridLines =\n showGridLines ?? (inheritedGridLines ? 'drag' : false);\n const generatedId = useId();\n const boardId = providedId ?? generatedId;\n // One shared description node for every selected widget, so marking a widget\n // selected costs no per-widget DOM.\n const selectedHintId = `${generatedId}-selected`;\n const { t } = useI18n();\n\n const containerRef = useCombinedRefs(ref);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const [measuredWidth, setMeasuredWidth] = useState<number>(0);\n // Rendered height is only needed for aligned nested boards (to fit rows into\n // the space the container grants). It never drives the board's own height, so\n // measuring it cannot create a feedback loop.\n const [measuredHeight, setMeasuredHeight] = useState<number>(0);\n const width = providedWidth ?? measuredWidth;\n\n const onResizeContainer = useEvent(() => {\n const el = containerRef.current;\n if (!el) return;\n // A hidden container (e.g. the board inside an inactive tab after a\n // spring-loaded tab switch) reports 0. Keep the last non-zero measurement so\n // the board stays \"ready\" and keeps its widget hosts mounted while briefly\n // hidden. Otherwise the board would render nothing, unmounting the widget\n // that owns an in-flight drag gesture and stranding the drag (React Aria's\n // `useMove` tears down its listeners on unmount, so the drop never fires).\n const nextWidth = el.offsetWidth;\n const nextHeight = el.offsetHeight;\n if (nextWidth > 0) setMeasuredWidth(nextWidth);\n if (nextHeight > 0) setMeasuredHeight(nextHeight);\n });\n useResizeObserver({ ref: containerRef, onResize: onResizeContainer });\n useEffect(() => {\n if (providedWidth == null) {\n onResizeContainer();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [providedWidth]);\n\n const {\n layout,\n layoutRef,\n placeholders,\n placeholder,\n placeholdersRef,\n placeholderRef,\n setPlaceholders,\n applyLayout,\n } = useBoardLayout({\n layout: controlledLayout,\n defaultLayout,\n onLayoutChange,\n });\n\n // The accessible name a widget announces under. Mirrors `WidgetHost`'s own\n // fallback chain so the live region and the host never disagree.\n const getWidgetLabel = useEvent((key: string) => {\n const registration = registry.store.get(key);\n\n return registration?.['aria-label'] ?? registration?.qa ?? key;\n });\n\n // Whether a widget accepts selection at all. Every selection path resolves it\n // here — press, keyboard and marquee — so a lasso can never pick up a widget\n // that a press cannot.\n const isWidgetSelectable = (key: string) =>\n (registry.store.get(key)?.isSelectable ?? widgetProps?.isSelectable) !==\n false;\n\n const {\n selectedKeySet,\n selectedKeysRef,\n setSelection,\n select,\n clearSelection,\n announcement,\n } = useBoardSelection({\n selectionMode,\n selectedKeys,\n defaultSelectedKeys,\n onSelectionChange,\n layout,\n getLabel: getWidgetLabel,\n });\n\n const selectModifierKey = useBoardSelectModifierKey();\n\n // Re-render when any widget's registered content/config changes.\n useSyncExternalStore(registry.store.subscribe, registry.store.getVersion);\n\n // In aligned mode the board inherits the parent's gap so widget edges line up\n // with the surrounding layout; otherwise it uses its own `margin`.\n const effectiveMargin: readonly [number, number] = aligned\n ? parentMetrics!.margin\n : margin;\n // The board keeps its own padding (it sits inside the container's chrome);\n // when unspecified it defaults to the effective gap. An aligned nested board\n // is the exception: its grid origin must sit flush on the container widget's\n // edge (which already coincides with the parent's column-0 origin) so its\n // columns line up with the ancestor board's. Inheriting the gap there would\n // inset every column by one margin and break the alignment, so it defaults\n // to zero padding instead.\n const resolvedPadding: readonly [number, number] =\n containerPadding ?? (aligned ? [0, 0] : effectiveMargin);\n\n const rows = Math.max(\n bottom(layout),\n ...placeholders.map((p) => p.y + p.h),\n 0,\n );\n\n // Rows the board actually paints. `rows` stays the *content* extent — layout\n // math must not see the reserved band — while this is the extent the board\n // renders, so the band is real board surface: `ContentLayer` (inset: 0)\n // covers it, which is what lets a marquee start there and a widget be dropped\n // past the end.\n const renderedRows = Math.min(rows + Math.max(0, extraRows), maxRows);\n\n // Derive the aligned column count so each column keeps the parent's pixel\n // pitch: as the container widget is resized, columns are added/removed rather\n // than stretched. `containerWidth` is then back-solved so `calcGridColWidth`\n // returns exactly the parent's column width.\n const parentColWidth = aligned ? parentMetrics!.colWidth : 0;\n // `width` is `offsetWidth` (an integer the browser rounds), while\n // `parentColWidth` is fractional. A container sized to exactly N parent\n // columns can therefore measure a fraction of a pixel short, so a bare\n // `Math.floor` would drop the last column and leave its space unused. Add a\n // small pixel tolerance to absorb that rounding; it only rounds up when the\n // width is within ~2px of a full column, so it can't invent a column that\n // genuinely doesn't fit.\n const ALIGN_WIDTH_TOLERANCE = 2;\n const alignedCols =\n aligned && width > 0\n ? Math.max(\n 1,\n Math.floor(\n (width -\n resolvedPadding[0] * 2 +\n effectiveMargin[0] +\n ALIGN_WIDTH_TOLERANCE) /\n (parentColWidth + effectiveMargin[0]),\n ),\n )\n : cols;\n const effectiveCols = aligned ? alignedCols : cols;\n const effectiveContainerWidth = aligned\n ? parentColWidth * effectiveCols +\n effectiveMargin[0] * Math.max(0, effectiveCols - 1) +\n resolvedPadding[0] * 2\n : width;\n\n // An aligned board uses the parent's row height verbatim, so every cell is\n // exactly the parent's cell size (width already matches via the inherited\n // column pitch). It never shrinks rows to fit; pair it with an `isAutoHeight`\n // container so the widget grows to fit the rows at this height instead.\n const effectiveRowHeight = aligned ? parentMetrics!.rowHeight : rowHeight;\n\n const positionParams = useMemo<PositionParams>(\n () => ({\n margin: effectiveMargin,\n containerPadding: resolvedPadding,\n containerWidth: effectiveContainerWidth,\n cols: effectiveCols,\n rowHeight: effectiveRowHeight,\n maxRows,\n }),\n [\n effectiveMargin[0],\n effectiveMargin[1],\n resolvedPadding[0],\n resolvedPadding[1],\n effectiveContainerWidth,\n effectiveCols,\n effectiveRowHeight,\n maxRows,\n ],\n );\n\n // 'free' means no compaction (nothing is pushed up/left or recompacted) AND a\n // dragged widget never pushes or swaps its neighbours: it is placed exactly\n // where dropped. Without `allowOverlap` a move onto an occupied cell is\n // blocked (the widget stays at its last free spot); with `allowOverlap`\n // widgets may stack. The explicit `preventCollision` prop still applies to the\n // compacting modes (`vertical` / `horizontal`) and to the legacy `null` mode.\n const compactor = useMemo<Compactor>(\n () =>\n getCompactor(\n compactTypeToCore(compact),\n allowOverlap,\n compact === 'free' ? !allowOverlap : preventCollision,\n ),\n [compact, allowOverlap, preventCollision],\n );\n\n const resolvedConstraints = constraints ?? defaultConstraints;\n\n const computedHeight =\n renderedRows > 0\n ? renderedRows * effectiveRowHeight +\n Math.max(0, renderedRows - 1) * effectiveMargin[1] +\n resolvedPadding[1] * 2\n : effectiveRowHeight;\n // An aligned board fills the height the container grants it, so it reports its\n // measured height; otherwise it reports the height its content needs.\n const containerHeight =\n aligned && measuredHeight > 0 ? measuredHeight : computedHeight;\n\n // Live refs so the stable registry entry always reads current values.\n const liveRef = useRef({\n positionParams,\n compactor,\n constraints: resolvedConstraints,\n maxRows,\n containerHeight,\n isDroppable,\n });\n liveRef.current = {\n positionParams,\n compactor,\n constraints: resolvedConstraints,\n maxRows,\n containerHeight,\n isDroppable,\n };\n\n const applyLayoutEvent = useEvent(applyLayout);\n const setPlaceholdersEvent = useEvent(setPlaceholders);\n\n const entryRef = useRef<BoardEntry | null>(null);\n if (!entryRef.current) {\n entryRef.current = {\n id: boardId,\n getContentRect: () => contentRef.current?.getBoundingClientRect() ?? null,\n getContentNode: () => contentRef.current,\n getPositionParams: () => liveRef.current.positionParams,\n getConstraints: () => liveRef.current.constraints,\n getCompactor: () => liveRef.current.compactor,\n getMaxRows: () => liveRef.current.maxRows,\n getContainerHeight: () => liveRef.current.containerHeight,\n getLayout: () => layoutRef.current,\n // The registry reads this synchronously at drag start, so it must be the\n // ref rather than the rendered value.\n getSelectedKeys: () =>\n selectedKeysRef.current.size > 0 ? selectedKeysRef.current : null,\n applyLayout: (next, commit) => applyLayoutEvent(next, commit),\n setPlaceholders: (items) => setPlaceholdersEvent(items),\n isDroppable: () => liveRef.current.isDroppable,\n };\n }\n\n useEffect(() => {\n const entry = entryRef.current!;\n // Keep the entry's id in sync with the (possibly changed) board id before\n // registering. The previous effect's cleanup has already removed the old id,\n // so registering here keys the entry under the current id.\n entry.id = boardId;\n return registry.registerBoard(entry);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [boardId]);\n\n // When the aligned column count changes (the container was resized), reflow\n // the layout to the new width: clamp items back into bounds and recompact so\n // nothing overflows the narrower/wider grid.\n const recompactForCols = useEvent((nextCols: number) => {\n const corrected = correctBounds(cloneLayout(layoutRef.current), {\n cols: nextCols,\n });\n const compacted = [\n ...liveRef.current.compactor.compact(corrected, nextCols),\n ];\n applyLayoutEvent(compacted, true);\n });\n // `null` until the first *measured* aligned column count is established. This\n // avoids treating the initial zero-width -> measured-width transition as a\n // column-count change: a board that measures its own width (no explicit\n // `width` prop) renders first with `width === 0`, so `effectiveCols` falls\n // back to `cols` and only becomes the derived aligned count once measured.\n // Seeding the baseline on that first measured value (without committing)\n // prevents an unsolicited reflow + `onLayoutChange` before the user interacts.\n const prevAlignedColsRef = useRef<number | null>(null);\n useEffect(() => {\n if (!aligned) {\n // Re-entering aligned mode should re-seed from the next measured value.\n prevAlignedColsRef.current = null;\n return;\n }\n // Wait for a real width measurement; the fallback-`cols` value that stands\n // in before measurement is not a meaningful aligned column count.\n if (width <= 0) return;\n if (prevAlignedColsRef.current === null) {\n prevAlignedColsRef.current = effectiveCols;\n return;\n }\n if (prevAlignedColsRef.current === effectiveCols) return;\n prevAlignedColsRef.current = effectiveCols;\n recompactForCols(effectiveCols);\n }, [aligned, width, effectiveCols, recompactForCols]);\n\n // Natural height this board wants: its rows at the (parent) row height. When\n // the container is shorter than this, an `isAutoHeight` host grows to fit it\n // (aligned boards no longer shrink their rows).\n const naturalHeight =\n renderedRows > 0\n ? renderedRows * effectiveRowHeight +\n Math.max(0, renderedRows - 1) * effectiveMargin[1] +\n resolvedPadding[1] * 2\n : effectiveRowHeight;\n\n // Report this aligned board's height deficit to an auto-sizing host so the\n // host can both grow to fit and pin its resize floor. The value is signed:\n // positive when the board is squeezed (needs more height), negative when the\n // container is taller than needed (so the floor can be lowered). The host\n // never shrinks the widget on its own - it only grows and clamps resizing.\n const requestHeightDeficit = host?.requestHeightDeficit;\n useEffect(() => {\n if (!aligned || !host?.isAutoHeight || !requestHeightDeficit) return;\n if (measuredHeight <= 0) return;\n requestHeightDeficit(naturalHeight - measuredHeight);\n }, [\n aligned,\n host?.isAutoHeight,\n requestHeightDeficit,\n naturalHeight,\n measuredHeight,\n ]);\n\n // In-board resize orchestration.\n const resizeStateRef = useRef<{\n id: string;\n axis: ResizeHandleAxis;\n item: LayoutItem;\n origin: Position;\n accX: number;\n accY: number;\n } | null>(null);\n\n // Minimum rows each auto-height widget currently needs to fit its content.\n // Read during resize so a widget can never be dragged shorter than its\n // content, and used to grow the item when the content needs more room.\n const autoHeightMinRowsRef = useRef<Record<string, number>>({});\n\n const handleResize = useEvent(\n (\n id: string,\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => {\n const pp = liveRef.current.positionParams;\n\n if (phase === 'start') {\n const rawItem = getLayoutItem(layoutRef.current, id);\n if (!rawItem) return;\n // Layout-item min/max and constraints win; otherwise fall back to the\n // ones declared on the owning `Board.Widget` (and then the board-level\n // `widgetProps` defaults) so `applySizeConstraints` (via `minMaxSize`)\n // picks them up.\n const reg = registry.store.get(id);\n const item: LayoutItem = {\n ...rawItem,\n minW: rawItem.minW ?? reg?.minW ?? widgetProps?.minW,\n maxW: rawItem.maxW ?? reg?.maxW ?? widgetProps?.maxW,\n minH: rawItem.minH ?? reg?.minH ?? widgetProps?.minH,\n maxH: rawItem.maxH ?? reg?.maxH ?? widgetProps?.maxH,\n constraints:\n rawItem.constraints ?? reg?.constraints ?? widgetProps?.constraints,\n };\n resizeStateRef.current = {\n id,\n axis,\n item: { ...item },\n origin: calcGridItemPosition(pp, item.x, item.y, item.w, item.h),\n accX: 0,\n accY: 0,\n };\n setPlaceholders([{ ...item }]);\n onResizeStart?.({\n layout: layoutRef.current,\n item: { ...item },\n oldItem: { ...item },\n placeholder: { ...item },\n items: [{ ...item }],\n oldItems: [{ ...item }],\n placeholders: [{ ...item }],\n });\n return;\n }\n\n const rs = resizeStateRef.current;\n if (!rs) return;\n\n if (phase === 'end') {\n const finalLayout = [...layoutRef.current];\n applyLayout(finalLayout, true);\n setPlaceholders([]);\n const resizedItem = getLayoutItem(finalLayout, id) ?? rs.item;\n onResizeStop?.({\n layout: finalLayout,\n item: resizedItem,\n oldItem: rs.item,\n placeholder: null,\n items: [resizedItem],\n oldItems: [rs.item],\n placeholders: [],\n });\n resizeStateRef.current = null;\n return;\n }\n\n rs.accX += dx;\n rs.accY += dy;\n\n const { origin, item, axis: handle } = rs;\n let newW = origin.width;\n let newH = origin.height;\n if (handle.includes('e')) newW = origin.width + rs.accX;\n if (handle.includes('w')) newW = origin.width - rs.accX;\n if (handle.includes('s')) newH = origin.height + rs.accY;\n if (handle.includes('n')) newH = origin.height - rs.accY;\n newW = Math.max(newW, 8);\n newH = Math.max(newH, 8);\n\n const raw = calcWH(pp, newW, newH, item.x, item.y, handle);\n const constrained = applySizeConstraints(\n liveRef.current.constraints,\n item,\n raw.w,\n raw.h,\n handle,\n {\n cols: pp.cols,\n maxRows: liveRef.current.maxRows,\n containerWidth: pp.containerWidth,\n containerHeight: liveRef.current.containerHeight,\n rowHeight: pp.rowHeight,\n margin: pp.margin,\n layout: layoutRef.current,\n },\n );\n\n // An auto-height widget cannot be resized shorter than the content it\n // hosts (a nested board) currently needs, so pin its height to the floor.\n const floorRows = autoHeightMinRowsRef.current[id] ?? 0;\n const finalW = constrained.w;\n const finalH = Math.max(constrained.h, floorRows);\n\n let x = item.x;\n let y = item.y;\n if (handle.includes('w')) x = item.x + item.w - finalW;\n if (handle.includes('n')) y = item.y + item.h - finalH;\n x = Math.max(0, x);\n y = Math.max(0, y);\n\n let newItem: LayoutItem = {\n ...item,\n x,\n y,\n w: finalW,\n h: finalH,\n };\n\n // Collision-blocking modes (`free` without `allowOverlap`, or an explicit\n // `preventCollision`) run a no-op/gap-filling compactor that never\n // resolves overlaps, so a resize must be blocked here the same way the\n // drag path blocks a move (`moveElement` reverts on collision). Without\n // this, growing or moving an edge via a resize handle could push the box\n // onto an occupied cell. When the new box overlaps a neighbour, revert to\n // the last committed box for this widget so the gesture stalls at the\n // last valid size/position instead of overlapping.\n const compactor = liveRef.current.compactor;\n if (compactor.preventCollision && !compactor.allowOverlap) {\n const collides = getAllCollisions(layoutRef.current, newItem).some(\n (other) => other.i !== id,\n );\n if (collides) {\n const lastValid = getLayoutItem(layoutRef.current, id);\n if (lastValid) newItem = { ...lastValid };\n }\n }\n\n const working = modifyLayout(layoutRef.current, newItem);\n const compacted = [...compactor.compact(working, pp.cols)];\n applyLayout(compacted, false);\n const nextPlaceholder = getLayoutItem(compacted, id) ?? newItem;\n setPlaceholders([nextPlaceholder]);\n const resizedItem = getLayoutItem(compacted, id) ?? newItem;\n onResizeProp?.({\n layout: compacted,\n item: resizedItem,\n oldItem: rs.item,\n placeholder: nextPlaceholder,\n items: [resizedItem],\n oldItems: [rs.item],\n placeholders: [nextPlaceholder],\n });\n },\n );\n\n // Record an auto-height widget's needed rows. Grow the item when its content\n // needs more height (only ever increases); the stored value is also the\n // resize floor enforced in `handleResize`.\n const handleAutoHeight = useEvent((id: string, neededRows: number) => {\n autoHeightMinRowsRef.current[id] = neededRows;\n const current = getLayoutItem(layoutRef.current, id);\n if (!current || neededRows <= current.h) return;\n // While a drag or resize gesture is in flight the layout is transient - the\n // registry (drag) and `handleResize` write uncommitted previews and commit\n // only on drop / release. Growing an auto-height widget here with\n // `commit: true` would fire `onLayoutChange` mid-gesture and persist the\n // in-flight positions of the widget being moved. Skip the grow-commit; the\n // floor ref is already updated above (so `handleResize` still respects it),\n // and the deficit effect re-fires once the gesture settles.\n if (registry.dragState || resizeStateRef.current) return;\n const pp = liveRef.current.positionParams;\n const working = modifyLayout(layoutRef.current, {\n ...current,\n h: neededRows,\n });\n const compacted = [...liveRef.current.compactor.compact(working, pp.cols)];\n applyLayout(compacted, true);\n });\n\n // The dragged item captured at gesture start, so drag callbacks can report the\n // original position throughout (and after a cross-board transfer removes the\n // item from this board's layout).\n const dragOldItemRef = useRef<LayoutItem | null>(null);\n // The same, for every other member of a group drag. Empty for an ordinary\n // drag, which is what keeps `items`/`oldItems` single-entry there.\n const dragOldItemsRef = useRef<LayoutItem[]>([]);\n\n const handleDragLifecycle = useEvent((id: string, phase: ResizePhase) => {\n const currentLayout = layoutRef.current;\n const liveItem = getLayoutItem(currentLayout, id);\n\n if (phase === 'start') {\n dragOldItemRef.current = liveItem ? { ...liveItem } : null;\n // The registry has already resolved the group by the time this fires, so\n // its drag state is the authority on who is moving.\n const ds = registry.getDragState();\n dragOldItemsRef.current =\n ds && ds.itemId === id ? ds.items.map((it) => ({ ...it })) : [];\n }\n const oldItem = dragOldItemRef.current ?? liveItem;\n if (!oldItem) return;\n const item = liveItem ?? oldItem;\n\n const oldItems = dragOldItemsRef.current.length\n ? dragOldItemsRef.current\n : [oldItem];\n const items = oldItems.map(\n (old) => getLayoutItem(currentLayout, old.i) ?? old,\n );\n\n const info: BoardInteractionInfo = {\n layout: currentLayout,\n item,\n oldItem,\n // Read the live refs, not render-time state: the registry calls\n // `setPlaceholders` synchronously right before this fires, and that only\n // schedules a re-render, so `placeholders` state still holds the previous\n // value (or a stale preview after the drop clears it).\n placeholder: placeholderRef.current,\n items,\n oldItems,\n placeholders: placeholdersRef.current,\n };\n if (phase === 'start') onDragStart?.(info);\n else if (phase === 'move') onDrag?.(info);\n else {\n onDragStop?.(info);\n dragOldItemRef.current = null;\n dragOldItemsRef.current = [];\n }\n });\n\n // ---- Marquee (rubber-band) selection --------------------------------------\n //\n // Board owns this rather than exposing hooks for an app to build it, because\n // deciding which widgets a band covers needs every widget's box — and the DOM\n // is the wrong place to read them from. Widget hosts transition `inset`/`width`\n // /`height` while the board reflows, and a host being dragged is swapped for an\n // `opacity: 0` stand-in with a fixed-position clone in the overlay, so\n // `getBoundingClientRect` during a marquee returns interpolated or misleading\n // boxes. `calcGridItemPosition` derives the same rectangles exactly, from the\n // layout, with no forced reflow and no sensitivity to ancestor transforms.\n const [marqueeRect, setMarqueeRect] = useState<Position | null>(null);\n\n const handleContentPointerDown = useEvent((event: React.PointerEvent) => {\n if (\n selectionMode !== 'multiple' ||\n !allowMarqueeSelection ||\n event.button !== 0 ||\n registry.dragState\n ) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n // A press on a widget selects it and arms a drag; the lasso owns empty\n // canvas only.\n if (target?.closest('[data-board-widget-host]')) return;\n if (selectionCancel && target?.closest(selectionCancel)) return;\n\n const content = contentRef.current;\n if (!content) return;\n\n const origin = content.getBoundingClientRect();\n const startX = event.clientX;\n const startY = event.clientY;\n // Holding the modifier means \"add to what I have\"; a bare lasso replaces.\n const additive = event[selectModifierKey] || event.shiftKey;\n const base = additive ? [...selectedKeysRef.current] : [];\n let passedThreshold = false;\n\n const hitTest = (clientX: number, clientY: number) => {\n const left = Math.min(startX, clientX) - origin.left;\n const right = Math.max(startX, clientX) - origin.left;\n const top = Math.min(startY, clientY) - origin.top;\n const bottom = Math.max(startY, clientY) - origin.top;\n const next = new Set(base);\n\n for (const it of layoutRef.current) {\n if (!isWidgetSelectable(it.i)) continue;\n const pos = calcGridItemPosition(\n liveRef.current.positionParams,\n it.x,\n it.y,\n it.w,\n it.h,\n );\n if (\n pos.left < right &&\n pos.left + pos.width > left &&\n pos.top < bottom &&\n pos.top + pos.height > top\n ) {\n next.add(it.i);\n }\n }\n\n return {\n next,\n box: { left, top, width: right - left, height: bottom - top },\n };\n };\n\n const handleMove = (e: PointerEvent) => {\n if (\n !passedThreshold &&\n Math.abs(e.clientX - startX) + Math.abs(e.clientY - startY) <\n MARQUEE_THRESHOLD\n ) {\n return;\n }\n passedThreshold = true;\n setMarqueeRect(hitTest(e.clientX, e.clientY).box);\n };\n\n const finish = (e: PointerEvent) => {\n window.removeEventListener('pointermove', handleMove);\n window.removeEventListener('pointerup', finish);\n window.removeEventListener('pointercancel', finish);\n setMarqueeRect(null);\n\n // One commit per gesture: `onSelectionChange` and the announcement fire on\n // release, never once per pointer frame.\n if (passedThreshold) {\n setSelection(hitTest(e.clientX, e.clientY).next);\n } else if (!additive) {\n // A plain click on empty board space clears.\n clearSelection();\n }\n // Keep focus somewhere inside the board so Escape has a handler to reach.\n containerRef.current?.focus({ preventScroll: true });\n };\n\n window.addEventListener('pointermove', handleMove);\n window.addEventListener('pointerup', finish);\n window.addEventListener('pointercancel', finish);\n });\n\n const marqueeStyle = marqueeRect\n ? {\n left: `${marqueeRect.left}px`,\n top: `${marqueeRect.top}px`,\n width: `${marqueeRect.width}px`,\n height: `${marqueeRect.height}px`,\n }\n : null;\n\n // Selection is focus-like, so it does not outlive focus leaving the board.\n // Tabbing away, or clicking any focusable thing elsewhere on the page, drops\n // it — the same way a text selection or a focus ring would go.\n const { focusWithinProps: boardFocusWithinProps } = useFocusWithin({\n isDisabled: selectionMode === 'none',\n onBlurWithin: () => clearSelection(),\n });\n\n // ---- Board-level keys -----------------------------------------------------\n //\n // On the board element, never on `document`: a library-owned document listener\n // fires for keystrokes that never went near a board, and two boards on a page\n // would both react.\n const handleBoardKeyDown = useEvent((event: React.KeyboardEvent) => {\n if (selectionMode === 'none') return;\n\n const selected = selectedKeysRef.current;\n if (selected.size === 0) return;\n\n if (event.key === 'Escape') {\n // `preventDefault` only when we actually consumed the key, so an Escape\n // with nothing selected still closes an ancestor Dialog or Popover.\n event.preventDefault();\n event.stopPropagation();\n clearSelection();\n\n return;\n }\n\n if (\n (event.key === 'Delete' || event.key === 'Backspace') &&\n onWidgetsDelete &&\n !isEditableTarget(event.target)\n ) {\n event.preventDefault();\n event.stopPropagation();\n const keys = [...selected];\n clearSelection();\n onWidgetsDelete(keys);\n // The deleted widgets' hosts are about to unmount, so focus would be left\n // on a detached node. Park it on the board.\n containerRef.current?.focus({ preventScroll: true });\n }\n });\n\n const styles: Styles = extractStyles(otherProps, CONTAINER_STYLES);\n\n const dragState = registry.dragState;\n const ready = width > 0;\n\n // Gate widget position transitions off until the widgets have been painted at\n // their initial positions once. Without this, the first render animates every\n // widget sliding in from its default spot (0, 0). We render one frame with the\n // gate closed (no `inset` transition), let the browser paint, then lift it so\n // later reflows animate. A double rAF waits past the first committed paint;\n // re-arm whenever the board (re)becomes ready so a board that hides and\n // remeasures (e.g. inside a tab) re-settles too.\n const [settled, setSettled] = useState(false);\n useEffect(() => {\n if (!ready) {\n setSettled(false);\n return;\n }\n let id1 = 0;\n let id2 = 0;\n id1 = requestAnimationFrame(() => {\n id2 = requestAnimationFrame(() => setSettled(true));\n });\n return () => {\n cancelAnimationFrame(id1);\n if (id2) cancelAnimationFrame(id2);\n };\n }, [ready]);\n\n // When the widget that hosts this nested board is the one being dragged, its\n // whole content (including this board) floats as a single unit, so its own\n // grid lines add nothing but clutter. Suppress them for that drag.\n const hostWidgetIsDragging =\n !!dragState && dragState.nestedBoardIds.has(boardId);\n\n const placeholderStyles = useMemo(\n () =>\n placeholders.map((p) => {\n const pos = calcGridItemPosition(positionParams, p.x, p.y, p.w, p.h);\n\n return {\n i: p.i,\n style: {\n left: `${pos.left}px`,\n top: `${pos.top}px`,\n width: `${pos.width}px`,\n height: `${pos.height}px`,\n },\n };\n }),\n [placeholders, positionParams],\n );\n\n const gridLinesVisible =\n !hostWidgetIsDragging &&\n (effectiveShowGridLines === true ||\n (effectiveShowGridLines === 'drag' && (!!dragState || !!placeholder)));\n const gridOverlayStyle = gridLinesVisible\n ? (() => {\n const colWidth = calcGridColWidth(positionParams);\n const rowHeightPx = positionParams.rowHeight;\n // A grid with margins has real gaps between cells, so any line-based\n // overlay either misses a cell edge (single line at the cell pitch) or\n // shows a double line in every gap (a line at both edges). Instead,\n // paint each snap cell as a faint block sized exactly `colWidth` x\n // `rowHeightPx` with the margin gaps left transparent: the blocks line\n // up 1:1 with the drop-zone placeholder and there are no lines to\n // double. Column stripes form the background; a row-band alpha mask\n // intersects them into cells.\n const pitchX = colWidth + effectiveMargin[0];\n const pitchY = rowHeightPx + effectiveMargin[1];\n // Position the overlay as an explicit rectangle inset by the board's\n // resolved padding and sized to exactly cover the grid content (cols x\n // rows). This makes the padding a symmetric frame on all four edges (the\n // previous `inset: 0` + top-left-anchored repeat left the padding\n // unvisualized on the right/bottom and inside any extra min-height) and\n // lets the cell pattern tile from the overlay's own origin.\n const padX = resolvedPadding[0];\n const padY = resolvedPadding[1];\n const gridWidth = Math.max(0, effectiveContainerWidth - padX * 2);\n // Painted over the reserved band too — grid cells are what make the\n // band read as board rather than as page background behind it.\n const gridHeight =\n renderedRows > 0\n ? renderedRows * rowHeightPx +\n (renderedRows - 1) * effectiveMargin[1]\n : 0;\n const fill = 'var(--border-color)';\n const columns = `repeating-linear-gradient(to right, ${fill} 0, ${fill} ${colWidth}px, transparent ${colWidth}px, transparent ${pitchX}px)`;\n const rowsGrad = `repeating-linear-gradient(to bottom, #000 0, #000 ${rowHeightPx}px, transparent ${rowHeightPx}px, transparent ${pitchY}px)`;\n return {\n left: `${padX}px`,\n top: `${padY}px`,\n width: `${gridWidth}px`,\n height: `${gridHeight}px`,\n backgroundImage: columns,\n backgroundPosition: '0 0',\n backgroundRepeat: 'repeat',\n maskImage: rowsGrad,\n WebkitMaskImage: rowsGrad,\n maskPosition: '0 0',\n WebkitMaskPosition: '0 0',\n maskRepeat: 'repeat',\n WebkitMaskRepeat: 'repeat',\n };\n })()\n : null;\n\n // Metrics this board exposes to any aligned boards nested inside its widgets.\n const boardMetrics = useMemo<BoardMetrics>(\n () => ({\n colWidth: calcGridColWidth(positionParams),\n rowHeight: positionParams.rowHeight,\n margin: positionParams.margin,\n containerPadding: positionParams.containerPadding,\n }),\n [positionParams],\n );\n\n return (\n <BoardMetricsContext.Provider value={boardMetrics}>\n <BoardGridLinesContext.Provider\n value={\n effectiveShowGridLines === true || effectiveShowGridLines === 'drag'\n }\n >\n <BoardElement\n {...mergeProps(\n filterBaseProps(otherProps, { eventProps: true }),\n boardFocusWithinProps,\n { onKeyDown: handleBoardKeyDown },\n )}\n ref={containerRef}\n styles={styles}\n // A board that owns keys needs somewhere for focus to land after a\n // marquee or a delete, so Escape always reaches `handleBoardKeyDown`.\n tabIndex={selectionMode !== 'none' ? -1 : undefined}\n data-board-id={boardId}\n // Non-aligned: use min-height (not a fixed height) so the board\n // auto-sizes to its content by default but can still grow to fill a\n // taller parent. Widgets are absolutely positioned, so growing never\n // shifts them, and the content layer (inset: 0) always covers the full\n // board -> the whole board is droppable. Aligned: omit the inline height\n // so the board fills (and is bounded by) the space the container grants,\n // which is what drives the reduced row height.\n style={aligned ? undefined : { minHeight: `${containerHeight}px` }}\n mods={{\n dragging: !!dragState,\n 'drop-target': dragState?.currentBoardId === boardId,\n }}\n >\n <ContentLayer\n ref={contentRef}\n onPointerDown={handleContentPointerDown}\n >\n {ready && gridOverlayStyle ? (\n <GridOverlayElement aria-hidden=\"true\" style={gridOverlayStyle} />\n ) : null}\n {ready\n ? layout.map((item) => {\n const registration = registry.store.get(item.i);\n const widgetDraggable =\n isDraggable &&\n (registration?.isDraggable ?? widgetProps?.isDraggable) !==\n false &&\n item.isDraggable !== false &&\n !item.static;\n const widgetResizable =\n isResizable &&\n (registration?.isResizable ?? widgetProps?.isResizable) !==\n false &&\n item.isResizable !== false &&\n !item.static;\n const handles =\n item.resizeHandles ??\n registration?.resizeHandles ??\n widgetProps?.resizeHandles ??\n resizeHandles;\n const widgetDragCancel =\n registration?.dragCancel ??\n widgetProps?.dragCancel ??\n dragCancel;\n const widgetDragHandle =\n registration?.dragHandle ??\n widgetProps?.dragHandle ??\n dragHandle;\n // Per-widget `isCard`/`styles` override the board-level\n // `widgetProps` defaults; `isCard` defaults to `false`\n // (borderless - widgets are always filled and rounded).\n const widgetIsCard =\n registration?.isCard ?? widgetProps?.isCard ?? false;\n // Per-widget `isAutoHeight`/`qa` fall back to the board-level\n // `widgetProps` defaults (mirroring the other widget props).\n const widgetIsAutoHeight =\n registration?.isAutoHeight ??\n widgetProps?.isAutoHeight ??\n false;\n const widgetQa = registration?.qa ?? widgetProps?.qa;\n const widgetSelectable =\n selectionMode !== 'none' && isWidgetSelectable(item.i);\n const widgetSelectionCancel =\n registration?.selectionCancel ??\n widgetProps?.selectionCancel ??\n selectionCancel;\n // Merge board-level `widgetProps` styles (its `styles` object\n // plus direct style props) with the per-widget styles so\n // shared defaults survive when a widget sets even a single\n // style prop; per-widget styles win on conflicts. Only merge\n // when both exist to preserve reference stability (and avoid\n // churn) in the common single-source case.\n const widgetStyles =\n registration?.styles && widgetPropsStyles\n ? mergeStyles(widgetPropsStyles, registration.styles)\n : registration?.styles ?? widgetPropsStyles;\n\n return (\n <WidgetHost\n key={item.i}\n boardId={boardId}\n item={item}\n positionParams={positionParams}\n registration={registration}\n isCard={widgetIsCard}\n styles={widgetStyles as Styles}\n isDraggable={widgetDraggable}\n isResizable={widgetResizable}\n resizeHandles={handles}\n isAutoHeight={widgetIsAutoHeight}\n qa={widgetQa}\n dragCancel={widgetDragCancel}\n dragHandle={widgetDragHandle}\n isSelectable={widgetSelectable}\n isSelected={selectedKeySet.has(item.i)}\n selectionCancel={widgetSelectionCancel}\n selectedHintId={selectedHintId}\n onSelect={select}\n onSelectionReset={clearSelection}\n selectModifierKey={selectModifierKey}\n registry={registry}\n dragState={dragState}\n settled={settled}\n onResize={handleResize}\n onAutoHeight={handleAutoHeight}\n onDragLifecycle={handleDragLifecycle}\n />\n );\n })\n : null}\n {placeholderStyles.map(({ i, style }) => (\n <PlaceholderElement key={i} aria-hidden=\"true\" style={style} />\n ))}\n {marqueeStyle ? (\n <MarqueeElement aria-hidden=\"true\" style={marqueeStyle} />\n ) : null}\n </ContentLayer>\n {selectionMode !== 'none' ? (\n <A11yLayer>\n <span id={selectedHintId}>{t('board.selected', 'Selected')}</span>\n <span role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </span>\n </A11yLayer>\n ) : null}\n {children}\n </BoardElement>\n </BoardGridLinesContext.Provider>\n </BoardMetricsContext.Provider>\n );\n}\n\nconst BoardInnerForwarded = forwardRef(BoardInner);\n\n/**\n * A draggable and resizable widget grid. Widgets are declared with\n * `Board.Widget` and positioned via a `layout`. Wrap multiple boards in a\n * `BoardProvider` to enable dragging widgets between them.\n */\nexport const Board = forwardRef(function Board(\n props: CubeBoardProps,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const existingRegistry = useBoardRegistry();\n\n if (existingRegistry) {\n return <BoardInnerForwarded {...props} ref={ref} />;\n }\n\n return (\n <BoardProvider>\n <BoardInnerForwarded {...props} ref={ref} />\n </BoardProvider>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAkEA,MAAM,eAAe,MAAM;CACzB,IAAI;CACJ,QAAQ;EACN,UAAU;EACV,SAAS;EACT,OAAO;EACP,UAAU;EACV,QAAQ;EACR,MAAM;EACN,WAAW;EAQX,SAAS;EACV;CACF,CAAC;AAEF,MAAM,eAAe,MAAM,EACzB,QAAQ;CACN,UAAU;CACV,OAAO;CACR,EACF,CAAC;AAMF,MAAM,qBAAqB,MAAM;CAC/B,IAAI;CACJ,QAAQ;EACN,UAAU;EACV,KAAK;EACL,MAAM;EACN,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,eAAe;EACf,YAAY;EACZ,WAAW;EACZ;CACF,CAAC;AAKF,MAAM,iBAAiB,MAAM;CAC3B,IAAI;CACJ,QAAQ;EACN,UAAU;EACV,KAAK;EACL,MAAM;EACN,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,eAAe;EACf,WAAW;EACZ;CACF,CAAC;AAQF,MAAM,YAAY,MAAM,EACtB,QAAQ;CACN,UAAU;CACV,OAAO;CACP,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,UAAU;CACV,UAAU;CACV,YAAY;CACZ,QAAQ;CACT,EACF,CAAC;AASF,MAAM,qBAAqB,MAAM;CAC/B,IAAI;CACJ,QAAQ;EACN,UAAU;EACV,QAAQ;EACR,eAAe;EACf,WAAW;EACX,SAAS;EACV;CACF,CAAC;;;;;;;AAmMF,MAAa,yBACX;;AAKF,MAAM,oBAAoB;;;;;;;AAQ1B,SAAS,iBAAiB,QAAqC;CAC7D,MAAM,KAAK;AACX,KAAI,CAAC,MAAM,OAAO,GAAG,YAAY,WAAY,QAAO;AAEpD,QAAO,CAAC,CAAC,GAAG,QAAQ,mDAAiD;;AAGvE,SAAS,kBAAkB,SAAwC;AACjE,KAAI,YAAY,OAAQ,QAAO;AAC/B,QAAO;;AAGT,SAAS,WACP,OACA,KACA;CACA,MAAM,EACJ,IAAI,YACJ,QAAQ,kBACR,eACA,gBACA,aACA,QACA,YACA,eACA,UAAU,cACV,cACA,OAAO,IACP,YAAY,KACZ,SAAS,CAAC,GAAG,EAAE,EACf,kBACA,UAAU,UACV,YAAY,GACZ,UAAU,YACV,eAAe,OACf,mBAAmB,OACnB,cAAc,MACd,cAAc,MACd,cAAc,MACd,gBAAgB,CAAC,KAAK,EACtB,YACA,YACA,eACA,YAAY,OACZ,gBAAgB,QAChB,cACA,qBACA,mBACA,kBAAkB,wBAClB,wBAAwB,kBAAkB,YAC1C,iBACA,aACA,OAAO,eACP,aACA,UACA,GAAG,eACD;CAEJ,MAAM,WAAW,kBAAkB;CACnC,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,OAAO,cAAc;CAC3B,MAAM,qBAAqB,mBAAmB;CAC9C,MAAM,UAAU,aAAa,CAAC,CAAC;CAM/B,MAAM,oBAAoB,cAAkC;AAC1D,MAAI,CAAC,YAAa,QAAO;EACzB,MAAM,YAAY,cAAc,aAAa,iBAAiB;AAC9D,SAAO,OAAO,KAAK,UAAU,CAAC,SAAS,IAAI,YAAY;IACtD,CAAC,YAAY,CAAC;CAGjB,MAAM,yBACJ,kBAAkB,qBAAqB,SAAS;CAClD,MAAM,cAAc,OAAO;CAC3B,MAAM,UAAU,cAAc;CAG9B,MAAM,iBAAiB,GAAG,YAAY;CACtC,MAAM,EAAE,MAAM,SAAS;CAEvB,MAAM,eAAe,gBAAgB,IAAI;CACzC,MAAM,aAAa,OAA8B,KAAK;CACtD,MAAM,CAAC,eAAe,oBAAoB,SAAiB,EAAE;CAI7D,MAAM,CAAC,gBAAgB,qBAAqB,SAAiB,EAAE;CAC/D,MAAM,QAAQ,iBAAiB;CAE/B,MAAM,oBAAoB,eAAe;EACvC,MAAM,KAAK,aAAa;AACxB,MAAI,CAAC,GAAI;EAOT,MAAM,YAAY,GAAG;EACrB,MAAM,aAAa,GAAG;AACtB,MAAI,YAAY,EAAG,kBAAiB,UAAU;AAC9C,MAAI,aAAa,EAAG,mBAAkB,WAAW;GACjD;AACF,mBAAkB;EAAE,KAAK;EAAc,UAAU;EAAmB,CAAC;AACrE,iBAAgB;AACd,MAAI,iBAAiB,KACnB,oBAAmB;IAGpB,CAAC,cAAc,CAAC;CAEnB,MAAM,EACJ,QACA,WACA,cACA,aACA,iBACA,gBACA,iBACA,gBACE,eAAe;EACjB,QAAQ;EACR;EACA;EACD,CAAC;CAIF,MAAM,iBAAiB,UAAU,QAAgB;EAC/C,MAAM,eAAe,SAAS,MAAM,IAAI,IAAI;AAE5C,SAAO,eAAe,iBAAiB,cAAc,MAAM;GAC3D;CAKF,MAAM,sBAAsB,SACzB,SAAS,MAAM,IAAI,IAAI,EAAE,gBAAgB,aAAa,kBACvD;CAEF,MAAM,EACJ,gBACA,iBACA,cACA,QACA,gBACA,iBACE,kBAAkB;EACpB;EACA;EACA;EACA;EACA;EACA,UAAU;EACX,CAAC;CAEF,MAAM,oBAAoB,2BAA2B;AAGrD,sBAAqB,SAAS,MAAM,WAAW,SAAS,MAAM,WAAW;CAIzE,MAAM,kBAA6C,UAC/C,cAAe,SACf;CAQJ,MAAM,kBACJ,qBAAqB,UAAU,CAAC,GAAG,EAAE,GAAG;CAE1C,MAAM,OAAO,KAAK,IAChB,OAAO,OAAO,EACd,GAAG,aAAa,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EACrC,EACD;CAOD,MAAM,eAAe,KAAK,IAAI,OAAO,KAAK,IAAI,GAAG,UAAU,EAAE,QAAQ;CAMrE,MAAM,iBAAiB,UAAU,cAAe,WAAW;CAS3D,MAAM,cACJ,WAAW,QAAQ,IACf,KAAK,IACH,GACA,KAAK,OACF,QACC,gBAAgB,KAAK,IACrB,gBAAgB,KARE,MAUjB,iBAAiB,gBAAgB,IACrC,CACF,GACD;CACN,MAAM,gBAAgB,UAAU,cAAc;CAC9C,MAAM,0BAA0B,UAC5B,iBAAiB,gBACjB,gBAAgB,KAAK,KAAK,IAAI,GAAG,gBAAgB,EAAE,GACnD,gBAAgB,KAAK,IACrB;CAMJ,MAAM,qBAAqB,UAAU,cAAe,YAAY;CAEhE,MAAM,iBAAiB,eACd;EACL,QAAQ;EACR,kBAAkB;EAClB,gBAAgB;EAChB,MAAM;EACN,WAAW;EACX;EACD,GACD;EACE,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB;EACA;EACA;EACA;EACD,CACF;CAQD,MAAM,YAAY,cAEd,aACE,kBAAkB,QAAQ,EAC1B,cACA,YAAY,SAAS,CAAC,eAAe,iBACtC,EACH;EAAC;EAAS;EAAc;EAAiB,CAC1C;CAED,MAAM,sBAAsB,eAAe;CAE3C,MAAM,iBACJ,eAAe,IACX,eAAe,qBACf,KAAK,IAAI,GAAG,eAAe,EAAE,GAAG,gBAAgB,KAChD,gBAAgB,KAAK,IACrB;CAGN,MAAM,kBACJ,WAAW,iBAAiB,IAAI,iBAAiB;CAGnD,MAAM,UAAU,OAAO;EACrB;EACA;EACA,aAAa;EACb;EACA;EACA;EACD,CAAC;AACF,SAAQ,UAAU;EAChB;EACA;EACA,aAAa;EACb;EACA;EACA;EACD;CAED,MAAM,mBAAmB,SAAS,YAAY;CAC9C,MAAM,uBAAuB,SAAS,gBAAgB;CAEtD,MAAM,WAAW,OAA0B,KAAK;AAChD,KAAI,CAAC,SAAS,QACZ,UAAS,UAAU;EACjB,IAAI;EACJ,sBAAsB,WAAW,SAAS,uBAAuB,IAAI;EACrE,sBAAsB,WAAW;EACjC,yBAAyB,QAAQ,QAAQ;EACzC,sBAAsB,QAAQ,QAAQ;EACtC,oBAAoB,QAAQ,QAAQ;EACpC,kBAAkB,QAAQ,QAAQ;EAClC,0BAA0B,QAAQ,QAAQ;EAC1C,iBAAiB,UAAU;EAG3B,uBACE,gBAAgB,QAAQ,OAAO,IAAI,gBAAgB,UAAU;EAC/D,cAAc,MAAM,WAAW,iBAAiB,MAAM,OAAO;EAC7D,kBAAkB,UAAU,qBAAqB,MAAM;EACvD,mBAAmB,QAAQ,QAAQ;EACpC;AAGH,iBAAgB;EACd,MAAM,QAAQ,SAAS;AAIvB,QAAM,KAAK;AACX,SAAO,SAAS,cAAc,MAAM;IAEnC,CAAC,QAAQ,CAAC;CAKb,MAAM,mBAAmB,UAAU,aAAqB;EACtD,MAAM,YAAY,cAAc,YAAY,UAAU,QAAQ,EAAE,EAC9D,MAAM,UACP,CAAC;AAIF,mBAHkB,CAChB,GAAG,QAAQ,QAAQ,UAAU,QAAQ,WAAW,SAAS,CAC1D,EAC2B,KAAK;GACjC;CAQF,MAAM,qBAAqB,OAAsB,KAAK;AACtD,iBAAgB;AACd,MAAI,CAAC,SAAS;AAEZ,sBAAmB,UAAU;AAC7B;;AAIF,MAAI,SAAS,EAAG;AAChB,MAAI,mBAAmB,YAAY,MAAM;AACvC,sBAAmB,UAAU;AAC7B;;AAEF,MAAI,mBAAmB,YAAY,cAAe;AAClD,qBAAmB,UAAU;AAC7B,mBAAiB,cAAc;IAC9B;EAAC;EAAS;EAAO;EAAe;EAAiB,CAAC;CAKrD,MAAM,gBACJ,eAAe,IACX,eAAe,qBACf,KAAK,IAAI,GAAG,eAAe,EAAE,GAAG,gBAAgB,KAChD,gBAAgB,KAAK,IACrB;CAON,MAAM,uBAAuB,MAAM;AACnC,iBAAgB;AACd,MAAI,CAAC,WAAW,CAAC,MAAM,gBAAgB,CAAC,qBAAsB;AAC9D,MAAI,kBAAkB,EAAG;AACzB,uBAAqB,gBAAgB,eAAe;IACnD;EACD;EACA,MAAM;EACN;EACA;EACA;EACD,CAAC;CAGF,MAAM,iBAAiB,OAOb,KAAK;CAKf,MAAM,uBAAuB,OAA+B,EAAE,CAAC;CAE/D,MAAM,eAAe,UAEjB,IACA,MACA,OACA,IACA,OACG;EACH,MAAM,KAAK,QAAQ,QAAQ;AAE3B,MAAI,UAAU,SAAS;GACrB,MAAM,UAAU,cAAc,UAAU,SAAS,GAAG;AACpD,OAAI,CAAC,QAAS;GAKd,MAAM,MAAM,SAAS,MAAM,IAAI,GAAG;GAClC,MAAM,OAAmB;IACvB,GAAG;IACH,MAAM,QAAQ,QAAQ,KAAK,QAAQ,aAAa;IAChD,MAAM,QAAQ,QAAQ,KAAK,QAAQ,aAAa;IAChD,MAAM,QAAQ,QAAQ,KAAK,QAAQ,aAAa;IAChD,MAAM,QAAQ,QAAQ,KAAK,QAAQ,aAAa;IAChD,aACE,QAAQ,eAAe,KAAK,eAAe,aAAa;IAC3D;AACD,kBAAe,UAAU;IACvB;IACA;IACA,MAAM,EAAE,GAAG,MAAM;IACjB,QAAQ,qBAAqB,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,EAAE;IAChE,MAAM;IACN,MAAM;IACP;AACD,mBAAgB,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;AAC9B,mBAAgB;IACd,QAAQ,UAAU;IAClB,MAAM,EAAE,GAAG,MAAM;IACjB,SAAS,EAAE,GAAG,MAAM;IACpB,aAAa,EAAE,GAAG,MAAM;IACxB,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,GAAG,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,GAAG,MAAM,CAAC;IAC5B,CAAC;AACF;;EAGF,MAAM,KAAK,eAAe;AAC1B,MAAI,CAAC,GAAI;AAET,MAAI,UAAU,OAAO;GACnB,MAAM,cAAc,CAAC,GAAG,UAAU,QAAQ;AAC1C,eAAY,aAAa,KAAK;AAC9B,mBAAgB,EAAE,CAAC;GACnB,MAAM,cAAc,cAAc,aAAa,GAAG,IAAI,GAAG;AACzD,kBAAe;IACb,QAAQ;IACR,MAAM;IACN,SAAS,GAAG;IACZ,aAAa;IACb,OAAO,CAAC,YAAY;IACpB,UAAU,CAAC,GAAG,KAAK;IACnB,cAAc,EAAE;IACjB,CAAC;AACF,kBAAe,UAAU;AACzB;;AAGF,KAAG,QAAQ;AACX,KAAG,QAAQ;EAEX,MAAM,EAAE,QAAQ,MAAM,MAAM,WAAW;EACvC,IAAI,OAAO,OAAO;EAClB,IAAI,OAAO,OAAO;AAClB,MAAI,OAAO,SAAS,IAAI,CAAE,QAAO,OAAO,QAAQ,GAAG;AACnD,MAAI,OAAO,SAAS,IAAI,CAAE,QAAO,OAAO,QAAQ,GAAG;AACnD,MAAI,OAAO,SAAS,IAAI,CAAE,QAAO,OAAO,SAAS,GAAG;AACpD,MAAI,OAAO,SAAS,IAAI,CAAE,QAAO,OAAO,SAAS,GAAG;AACpD,SAAO,KAAK,IAAI,MAAM,EAAE;AACxB,SAAO,KAAK,IAAI,MAAM,EAAE;EAExB,MAAM,MAAM,OAAO,IAAI,MAAM,MAAM,KAAK,GAAG,KAAK,GAAG,OAAO;EAC1D,MAAM,cAAc,qBAClB,QAAQ,QAAQ,aAChB,MACA,IAAI,GACJ,IAAI,GACJ,QACA;GACE,MAAM,GAAG;GACT,SAAS,QAAQ,QAAQ;GACzB,gBAAgB,GAAG;GACnB,iBAAiB,QAAQ,QAAQ;GACjC,WAAW,GAAG;GACd,QAAQ,GAAG;GACX,QAAQ,UAAU;GACnB,CACF;EAID,MAAM,YAAY,qBAAqB,QAAQ,OAAO;EACtD,MAAM,SAAS,YAAY;EAC3B,MAAM,SAAS,KAAK,IAAI,YAAY,GAAG,UAAU;EAEjD,IAAI,IAAI,KAAK;EACb,IAAI,IAAI,KAAK;AACb,MAAI,OAAO,SAAS,IAAI,CAAE,KAAI,KAAK,IAAI,KAAK,IAAI;AAChD,MAAI,OAAO,SAAS,IAAI,CAAE,KAAI,KAAK,IAAI,KAAK,IAAI;AAChD,MAAI,KAAK,IAAI,GAAG,EAAE;AAClB,MAAI,KAAK,IAAI,GAAG,EAAE;EAElB,IAAI,UAAsB;GACxB,GAAG;GACH;GACA;GACA,GAAG;GACH,GAAG;GACJ;EAUD,MAAM,YAAY,QAAQ,QAAQ;AAClC,MAAI,UAAU,oBAAoB,CAAC,UAAU,cAI3C;OAHiB,iBAAiB,UAAU,SAAS,QAAQ,CAAC,MAC3D,UAAU,MAAM,MAAM,GACxB,EACa;IACZ,MAAM,YAAY,cAAc,UAAU,SAAS,GAAG;AACtD,QAAI,UAAW,WAAU,EAAE,GAAG,WAAW;;;EAI7C,MAAM,UAAU,aAAa,UAAU,SAAS,QAAQ;EACxD,MAAM,YAAY,CAAC,GAAG,UAAU,QAAQ,SAAS,GAAG,KAAK,CAAC;AAC1D,cAAY,WAAW,MAAM;EAC7B,MAAM,kBAAkB,cAAc,WAAW,GAAG,IAAI;AACxD,kBAAgB,CAAC,gBAAgB,CAAC;EAClC,MAAM,cAAc,cAAc,WAAW,GAAG,IAAI;AACpD,iBAAe;GACb,QAAQ;GACR,MAAM;GACN,SAAS,GAAG;GACZ,aAAa;GACb,OAAO,CAAC,YAAY;GACpB,UAAU,CAAC,GAAG,KAAK;GACnB,cAAc,CAAC,gBAAgB;GAChC,CAAC;GAEL;CAKD,MAAM,mBAAmB,UAAU,IAAY,eAAuB;AACpE,uBAAqB,QAAQ,MAAM;EACnC,MAAM,UAAU,cAAc,UAAU,SAAS,GAAG;AACpD,MAAI,CAAC,WAAW,cAAc,QAAQ,EAAG;AAQzC,MAAI,SAAS,aAAa,eAAe,QAAS;EAClD,MAAM,KAAK,QAAQ,QAAQ;EAC3B,MAAM,UAAU,aAAa,UAAU,SAAS;GAC9C,GAAG;GACH,GAAG;GACJ,CAAC;AAEF,cADkB,CAAC,GAAG,QAAQ,QAAQ,UAAU,QAAQ,SAAS,GAAG,KAAK,CAAC,EACnD,KAAK;GAC5B;CAKF,MAAM,iBAAiB,OAA0B,KAAK;CAGtD,MAAM,kBAAkB,OAAqB,EAAE,CAAC;CAEhD,MAAM,sBAAsB,UAAU,IAAY,UAAuB;EACvE,MAAM,gBAAgB,UAAU;EAChC,MAAM,WAAW,cAAc,eAAe,GAAG;AAEjD,MAAI,UAAU,SAAS;AACrB,kBAAe,UAAU,WAAW,EAAE,GAAG,UAAU,GAAG;GAGtD,MAAM,KAAK,SAAS,cAAc;AAClC,mBAAgB,UACd,MAAM,GAAG,WAAW,KAAK,GAAG,MAAM,KAAK,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;;EAEnE,MAAM,UAAU,eAAe,WAAW;AAC1C,MAAI,CAAC,QAAS;EACd,MAAM,OAAO,YAAY;EAEzB,MAAM,WAAW,gBAAgB,QAAQ,SACrC,gBAAgB,UAChB,CAAC,QAAQ;EACb,MAAM,QAAQ,SAAS,KACpB,QAAQ,cAAc,eAAe,IAAI,EAAE,IAAI,IACjD;EAED,MAAM,OAA6B;GACjC,QAAQ;GACR;GACA;GAKA,aAAa,eAAe;GAC5B;GACA;GACA,cAAc,gBAAgB;GAC/B;AACD,MAAI,UAAU,QAAS,eAAc,KAAK;WACjC,UAAU,OAAQ,UAAS,KAAK;OACpC;AACH,gBAAa,KAAK;AAClB,kBAAe,UAAU;AACzB,mBAAgB,UAAU,EAAE;;GAE9B;CAYF,MAAM,CAAC,aAAa,kBAAkB,SAA0B,KAAK;CAErE,MAAM,2BAA2B,UAAU,UAA8B;AACvE,MACE,kBAAkB,cAClB,CAAC,yBACD,MAAM,WAAW,KACjB,SAAS,UAET;EAGF,MAAM,SAAS,MAAM;AAGrB,MAAI,QAAQ,QAAQ,2BAA2B,CAAE;AACjD,MAAI,mBAAmB,QAAQ,QAAQ,gBAAgB,CAAE;EAEzD,MAAM,UAAU,WAAW;AAC3B,MAAI,CAAC,QAAS;EAEd,MAAM,SAAS,QAAQ,uBAAuB;EAC9C,MAAM,SAAS,MAAM;EACrB,MAAM,SAAS,MAAM;EAErB,MAAM,WAAW,MAAM,sBAAsB,MAAM;EACnD,MAAM,OAAO,WAAW,CAAC,GAAG,gBAAgB,QAAQ,GAAG,EAAE;EACzD,IAAI,kBAAkB;EAEtB,MAAM,WAAW,SAAiB,YAAoB;GACpD,MAAM,OAAO,KAAK,IAAI,QAAQ,QAAQ,GAAG,OAAO;GAChD,MAAM,QAAQ,KAAK,IAAI,QAAQ,QAAQ,GAAG,OAAO;GACjD,MAAM,MAAM,KAAK,IAAI,QAAQ,QAAQ,GAAG,OAAO;GAC/C,MAAM,SAAS,KAAK,IAAI,QAAQ,QAAQ,GAAG,OAAO;GAClD,MAAM,OAAO,IAAI,IAAI,KAAK;AAE1B,QAAK,MAAM,MAAM,UAAU,SAAS;AAClC,QAAI,CAAC,mBAAmB,GAAG,EAAE,CAAE;IAC/B,MAAM,MAAM,qBACV,QAAQ,QAAQ,gBAChB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,EACJ;AACD,QACE,IAAI,OAAO,SACX,IAAI,OAAO,IAAI,QAAQ,QACvB,IAAI,MAAM,UACV,IAAI,MAAM,IAAI,SAAS,IAEvB,MAAK,IAAI,GAAG,EAAE;;AAIlB,UAAO;IACL;IACA,KAAK;KAAE;KAAM;KAAK,OAAO,QAAQ;KAAM,QAAQ,SAAS;KAAK;IAC9D;;EAGH,MAAM,cAAc,MAAoB;AACtC,OACE,CAAC,mBACD,KAAK,IAAI,EAAE,UAAU,OAAO,GAAG,KAAK,IAAI,EAAE,UAAU,OAAO,GACzD,kBAEF;AAEF,qBAAkB;AAClB,kBAAe,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAI;;EAGnD,MAAM,UAAU,MAAoB;AAClC,UAAO,oBAAoB,eAAe,WAAW;AACrD,UAAO,oBAAoB,aAAa,OAAO;AAC/C,UAAO,oBAAoB,iBAAiB,OAAO;AACnD,kBAAe,KAAK;AAIpB,OAAI,gBACF,cAAa,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,KAAK;YACvC,CAAC,SAEV,iBAAgB;AAGlB,gBAAa,SAAS,MAAM,EAAE,eAAe,MAAM,CAAC;;AAGtD,SAAO,iBAAiB,eAAe,WAAW;AAClD,SAAO,iBAAiB,aAAa,OAAO;AAC5C,SAAO,iBAAiB,iBAAiB,OAAO;GAChD;CAEF,MAAM,eAAe,cACjB;EACE,MAAM,GAAG,YAAY,KAAK;EAC1B,KAAK,GAAG,YAAY,IAAI;EACxB,OAAO,GAAG,YAAY,MAAM;EAC5B,QAAQ,GAAG,YAAY,OAAO;EAC/B,GACD;CAKJ,MAAM,EAAE,kBAAkB,0BAA0B,eAAe;EACjE,YAAY,kBAAkB;EAC9B,oBAAoB,gBAAgB;EACrC,CAAC;CAOF,MAAM,qBAAqB,UAAU,UAA+B;AAClE,MAAI,kBAAkB,OAAQ;EAE9B,MAAM,WAAW,gBAAgB;AACjC,MAAI,SAAS,SAAS,EAAG;AAEzB,MAAI,MAAM,QAAQ,UAAU;AAG1B,SAAM,gBAAgB;AACtB,SAAM,iBAAiB;AACvB,mBAAgB;AAEhB;;AAGF,OACG,MAAM,QAAQ,YAAY,MAAM,QAAQ,gBACzC,mBACA,CAAC,iBAAiB,MAAM,OAAO,EAC/B;AACA,SAAM,gBAAgB;AACtB,SAAM,iBAAiB;GACvB,MAAM,OAAO,CAAC,GAAG,SAAS;AAC1B,mBAAgB;AAChB,mBAAgB,KAAK;AAGrB,gBAAa,SAAS,MAAM,EAAE,eAAe,MAAM,CAAC;;GAEtD;CAEF,MAAM,SAAiB,cAAc,YAAY,iBAAiB;CAElE,MAAM,YAAY,SAAS;CAC3B,MAAM,QAAQ,QAAQ;CAStB,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAC7C,iBAAgB;AACd,MAAI,CAAC,OAAO;AACV,cAAW,MAAM;AACjB;;EAEF,IAAI,MAAM;EACV,IAAI,MAAM;AACV,QAAM,4BAA4B;AAChC,SAAM,4BAA4B,WAAW,KAAK,CAAC;IACnD;AACF,eAAa;AACX,wBAAqB,IAAI;AACzB,OAAI,IAAK,sBAAqB,IAAI;;IAEnC,CAAC,MAAM,CAAC;CAKX,MAAM,uBACJ,CAAC,CAAC,aAAa,UAAU,eAAe,IAAI,QAAQ;CAEtD,MAAM,oBAAoB,cAEtB,aAAa,KAAK,MAAM;EACtB,MAAM,MAAM,qBAAqB,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;AAEpE,SAAO;GACL,GAAG,EAAE;GACL,OAAO;IACL,MAAM,GAAG,IAAI,KAAK;IAClB,KAAK,GAAG,IAAI,IAAI;IAChB,OAAO,GAAG,IAAI,MAAM;IACpB,QAAQ,GAAG,IAAI,OAAO;IACvB;GACF;GACD,EACJ,CAAC,cAAc,eAAe,CAC/B;CAMD,MAAM,mBAHJ,CAAC,yBACA,2BAA2B,QACzB,2BAA2B,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,uBAEjD;EACL,MAAM,WAAW,iBAAiB,eAAe;EACjD,MAAM,cAAc,eAAe;EASnC,MAAM,SAAS,WAAW,gBAAgB;EAC1C,MAAM,SAAS,cAAc,gBAAgB;EAO7C,MAAM,OAAO,gBAAgB;EAC7B,MAAM,OAAO,gBAAgB;EAC7B,MAAM,YAAY,KAAK,IAAI,GAAG,0BAA0B,OAAO,EAAE;EAGjE,MAAM,aACJ,eAAe,IACX,eAAe,eACd,eAAe,KAAK,gBAAgB,KACrC;EACN,MAAM,OAAO;EACb,MAAM,UAAU,uCAAuC,KAAK,MAAM,KAAK,GAAG,SAAS,kBAAkB,SAAS,kBAAkB,OAAO;EACvI,MAAM,WAAW,qDAAqD,YAAY,kBAAkB,YAAY,kBAAkB,OAAO;AACzI,SAAO;GACL,MAAM,GAAG,KAAK;GACd,KAAK,GAAG,KAAK;GACb,OAAO,GAAG,UAAU;GACpB,QAAQ,GAAG,WAAW;GACtB,iBAAiB;GACjB,oBAAoB;GACpB,kBAAkB;GAClB,WAAW;GACX,iBAAiB;GACjB,cAAc;GACd,oBAAoB;GACpB,YAAY;GACZ,kBAAkB;GACnB;KACC,GACJ;CAGJ,MAAM,eAAe,eACZ;EACL,UAAU,iBAAiB,eAAe;EAC1C,WAAW,eAAe;EAC1B,QAAQ,eAAe;EACvB,kBAAkB,eAAe;EAClC,GACD,CAAC,eAAe,CACjB;AAED,QACE,oBAAC,oBAAoB;EAAS,OAAO;YACnC,oBAAC,sBAAsB;GACrB,OACE,2BAA2B,QAAQ,2BAA2B;aAGhE,qBAAC;IACC,GAAIA,aACF,gBAAgB,YAAY,EAAE,YAAY,MAAM,CAAC,EACjD,uBACA,EAAE,WAAW,oBAAoB,CAClC;IACD,KAAK;IACG;IAGR,UAAU,kBAAkB,SAAS,KAAK;IAC1C,iBAAe;IAQf,OAAO,UAAU,SAAY,EAAE,WAAW,GAAG,gBAAgB,KAAK;IAClE,MAAM;KACJ,UAAU,CAAC,CAAC;KACZ,eAAe,WAAW,mBAAmB;KAC9C;;KAED,qBAAC;MACC,KAAK;MACL,eAAe;;OAEd,SAAS,mBACR,oBAAC;QAAmB,eAAY;QAAO,OAAO;SAAoB,GAChE;OACH,QACG,OAAO,KAAK,SAAS;QACnB,MAAM,eAAe,SAAS,MAAM,IAAI,KAAK,EAAE;QAC/C,MAAM,kBACJ,gBACC,cAAc,eAAe,aAAa,iBACzC,SACF,KAAK,gBAAgB,SACrB,CAAC,KAAK;QACR,MAAM,kBACJ,gBACC,cAAc,eAAe,aAAa,iBACzC,SACF,KAAK,gBAAgB,SACrB,CAAC,KAAK;QACR,MAAM,UACJ,KAAK,iBACL,cAAc,iBACd,aAAa,iBACb;QACF,MAAM,mBACJ,cAAc,cACd,aAAa,cACb;QACF,MAAM,mBACJ,cAAc,cACd,aAAa,cACb;QAIF,MAAM,eACJ,cAAc,UAAU,aAAa,UAAU;QAGjD,MAAM,qBACJ,cAAc,gBACd,aAAa,gBACb;QACF,MAAM,WAAW,cAAc,MAAM,aAAa;QAClD,MAAM,mBACJ,kBAAkB,UAAU,mBAAmB,KAAK,EAAE;QACxD,MAAM,wBACJ,cAAc,mBACd,aAAa,mBACb;AAYF,eACE,oBAAC;SAEU;SACH;SACU;SACF;SACd,QAAQ;SACR,QAZF,cAAc,UAAU,oBACpB,YAAY,mBAAmB,aAAa,OAAO,GACnD,cAAc,UAAU;SAW1B,aAAa;SACb,aAAa;SACb,eAAe;SACf,cAAc;SACd,IAAI;SACJ,YAAY;SACZ,YAAY;SACZ,cAAc;SACd,YAAY,eAAe,IAAI,KAAK,EAAE;SACtC,iBAAiB;SACD;SAChB,UAAU;SACV,kBAAkB;SACC;SACT;SACC;SACF;SACT,UAAU;SACV,cAAc;SACd,iBAAiB;WA1BZ,KAAK,EA2BV;SAEJ,GACF;OACH,kBAAkB,KAAK,EAAE,GAAG,YAC3B,oBAAC;QAA2B,eAAY;QAAc;UAA7B,EAAsC,CAC/D;OACD,eACC,oBAAC;QAAe,eAAY;QAAO,OAAO;SAAgB,GACxD;;OACS;KACd,kBAAkB,SACjB,qBAAC,wBACC,oBAAC;MAAK,IAAI;gBAAiB,EAAE,kBAAkB,WAAW;OAAQ,EAClE,oBAAC;MAAK,MAAK;MAAS,aAAU;MAAS,eAAY;gBAChD;OACI,IACG,GACV;KACH;;KACY;IACgB;GACJ;;AAInC,MAAM,sBAAsB,WAAW,WAAW;;;;;;AAOlD,MAAa,QAAQ,WAAW,SAAS,MACvC,OACA,KACA;AAGA,KAFyB,kBAAkB,CAGzC,QAAO,oBAAC;EAAoB,GAAI;EAAY;GAAO;AAGrD,QACE,oBAAC,2BACC,oBAAC;EAAoB,GAAI;EAAY;GAAO,GAC9B;EAElB"}
|
|
1
|
+
{"version":3,"file":"Board.js","names":["mergeProps"],"sources":["../../../../src/components/layout/Board/Board.tsx"],"sourcesContent":["import { useResizeObserver } from '@react-aria/utils';\nimport {\n AllBaseProps,\n CONTAINER_STYLES,\n ContainerStyleProps,\n filterBaseProps,\n mergeStyles,\n Styles,\n tasty,\n} from '@tenphi/tasty';\nimport {\n forwardRef,\n ReactNode,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { useFocusWithin } from 'react-aria';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { useI18n } from '../../../i18n';\nimport { mergeProps, useCombinedRefs } from '../../../utils/react';\nimport { extractStyles } from '../../../utils/styles';\n\nimport {\n BoardEntry,\n BoardGridLinesContext,\n BoardMetrics,\n BoardMetricsContext,\n useBoardGridLines,\n useBoardHost,\n useBoardMetrics,\n useBoardRegistry,\n} from './board-context';\nimport { BoardProvider } from './BoardProvider';\nimport {\n applySizeConstraints,\n bottom,\n calcGridColWidth,\n calcGridItemPosition,\n calcWH,\n cloneLayout,\n Compactor,\n CompactType,\n correctBounds,\n defaultConstraints,\n getAllCollisions,\n getCompactor,\n getLayoutItem,\n LayoutConstraint,\n LayoutItem,\n modifyLayout,\n Position,\n PositionParams,\n ResizeHandleAxis,\n} from './grid-core';\nimport { useBoardLayout } from './use-board-layout';\nimport { useBoardSelectModifierKey } from './use-board-select-modifier-key';\nimport { BoardSelectionMode, useBoardSelection } from './use-board-selection';\nimport { ResizePhase, WidgetHost } from './WidgetHost';\n\nimport type { CubeBoardWidgetProps } from './Widget';\n\nconst BoardElement = tasty({\n qa: 'Board',\n styles: {\n position: 'relative',\n display: 'block',\n width: '100%',\n flexGrow: 1,\n height: 'min 0',\n fill: '#surface',\n boxSizing: 'border-box',\n // The board takes focus programmatically (never by Tab — it is `tabIndex=-1`)\n // as a parking spot: after `onWidgetsDelete` the focused widget host is\n // about to unmount, and after a marquee focus is nowhere near the board, so\n // in both cases Escape and Delete — handled here rather than on `document` —\n // would have nothing to reach. A focus ring on a parking spot is noise: it\n // announces a state the user cannot act on and did not ask for. Same reason\n // `Dialog` drops it on its own focusable container.\n outline: 0,\n // A lasso is a widget gesture, not a text gesture: without this, dragging a\n // band across the widgets paints a native text selection under it and leaves\n // stray highlighted text behind. `WidgetHost` does the same for a widget\n // drag (`'drag | resizing'`), which the marquee never goes through.\n userSelect: {\n '': 'auto',\n marquee: 'none',\n },\n },\n});\n\nconst ContentLayer = tasty({\n styles: {\n position: 'absolute',\n inset: 0,\n },\n});\n\n// The drop-slot preview. `#primary` rather than the legacy `#purple` alias -\n// same hue, current token. It has to stay distinguishable from a *selected*\n// widget (a tint + solid border + ring, see `WidgetHost`) and from a live\n// marquee (dashed), since all three can be on screen at once.\nconst PlaceholderElement = tasty({\n qa: 'BoardPlaceholder',\n styles: {\n position: 'absolute',\n top: 0,\n left: 0,\n fill: '#primary.10',\n radius: '1cr',\n border: '#primary.40',\n zIndex: 2,\n pointerEvents: 'none',\n transition: 'inset 80ms linear, width 80ms linear, height 80ms linear',\n boxSizing: 'border-box',\n },\n});\n\n// The rubber-band selection rectangle. Dashed is the discriminator: nothing else\n// on a board is dashed, and it reads as a transient lasso rather than a place\n// something is about to land. Sits above the widgets (1) and the placeholder (2).\nconst MarqueeElement = tasty({\n qa: 'BoardMarquee',\n styles: {\n position: 'absolute',\n top: 0,\n left: 0,\n fill: '#primary-accent-surface.06',\n border: '1bw dashed #primary-border',\n radius: '1cr',\n zIndex: 3,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n },\n});\n\n// Visually-hidden live region. Selection changes are announced here because a\n// board widget cannot carry `aria-selected`: that attribute is only valid on\n// collection roles (`option`, `gridcell`, `row`, …) whose children must be\n// presentational, and widgets host arbitrary interactive content. This element\n// also owns the shared \"Selected\" hint every selected host points at via\n// `aria-describedby`.\nconst A11yLayer = tasty({\n styles: {\n position: 'absolute',\n width: '1px',\n height: '1px',\n padding: 0,\n margin: '-1px',\n overflow: 'hidden',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n border: 0,\n },\n});\n\n// Grid overlay drawn behind the widgets. Each snap cell is painted as a faint\n// block (column stripes intersected with a row-band alpha mask); the margin gaps\n// between cells stay transparent. The element is positioned as an explicit\n// rectangle inset by the board's resolved padding and sized to the grid content\n// so the padding reads as a symmetric frame on every edge. Its size, position\n// and gradients come from the board's position params via inline `style`. The\n// fill uses the `#border` token (via its CSS var) so it adapts to the scheme.\nconst GridOverlayElement = tasty({\n qa: 'BoardGridOverlay',\n styles: {\n position: 'absolute',\n zIndex: 0,\n pointerEvents: 'none',\n boxSizing: 'border-box',\n opacity: '.5',\n },\n});\n\nexport type BoardCompactType = 'vertical' | 'horizontal' | 'free' | null;\n\n/**\n * Payload passed to the drag/resize lifecycle callbacks. `layout` is the board's\n * current layout at the moment the callback fires, `item` is the affected item\n * (falls back to `oldItem` if the item just left this board via a cross-board\n * transfer), `oldItem` is that item as it was when the gesture started, and\n * `placeholder` is the current drop-slot preview (if any).\n *\n * The plural fields describe the whole gesture: a group drag moves every\n * selected widget at once, so `items`/`oldItems`/`placeholders` list them all,\n * grabbed widget first. An ordinary drag or a resize produces exactly one entry,\n * so `items[0] === item` and `placeholders[0] === placeholder` always hold.\n */\nexport interface BoardInteractionInfo {\n layout: LayoutItem[];\n item: LayoutItem;\n oldItem: LayoutItem;\n placeholder: LayoutItem | null;\n /** Every item in this gesture, grabbed first. */\n items: LayoutItem[];\n /** Those items as they were when the gesture started, same order. */\n oldItems: LayoutItem[];\n /** Every drop-slot preview. Empty exactly when `placeholder` is `null`. */\n placeholders: LayoutItem[];\n}\n\n/** Visibility of the internal grid-line overlay. */\nexport type BoardGridLines = boolean | 'drag';\n\n/**\n * The subset of `Board.Widget` props a `Board` can set as defaults for every\n * widget it hosts (via `widgetProps`). Excludes `id`/`children`, which are\n * per-widget. Per-widget `Board.Widget` props override these.\n */\nexport type CubeBoardWidgetDefaults = Omit<\n CubeBoardWidgetProps,\n 'id' | 'children'\n>;\n\nexport interface CubeBoardProps\n extends Omit<\n AllBaseProps,\n 'children' | 'onDragStart' | 'onDrag' | 'onResize'\n >,\n Omit<ContainerStyleProps, 'margin'> {\n /** Stable board id (used for cross-board drag). Auto-generated if omitted. */\n id?: string;\n /** Controlled layout. */\n layout?: LayoutItem[];\n /** Initial layout for uncontrolled usage. */\n defaultLayout?: LayoutItem[];\n onLayoutChange?: (layout: LayoutItem[]) => void;\n /** Called when a drag gesture starts. */\n onDragStart?: (info: BoardInteractionInfo) => void;\n /** Called on every step of a drag gesture. */\n onDrag?: (info: BoardInteractionInfo) => void;\n /** Called when a drag gesture ends (after the layout is committed). */\n onDragStop?: (info: BoardInteractionInfo) => void;\n /** Called when a resize gesture starts. */\n onResizeStart?: (info: BoardInteractionInfo) => void;\n /** Called on every step of a resize gesture. */\n onResize?: (info: BoardInteractionInfo) => void;\n /** Called when a resize gesture ends (after the layout is committed). */\n onResizeStop?: (info: BoardInteractionInfo) => void;\n /** Number of columns. @default 12 */\n cols?: number;\n /** Row height in pixels. @default 100 */\n rowHeight?: number;\n /** [horizontal, vertical] margin between widgets in pixels. @default [8, 8] */\n margin?: [number, number];\n /**\n * [horizontal, vertical] padding inside the board. Defaults to `margin`, or\n * to `[0, 0]` for an aligned nested board (`isAligned`) so its grid lines up\n * with the ancestor board's.\n */\n containerPadding?: [number, number];\n /** Maximum number of rows. @default Infinity */\n maxRows?: number;\n /**\n * Empty grid rows kept below the content. The board renders this many rows\n * taller than its widgets need, so there is always somewhere to start a\n * marquee and somewhere to drop a widget past the end — a board that hugs its\n * content has neither once the grid is full. Clamped by `maxRows`.\n * @default 0\n */\n extraRows?: number;\n /**\n * Compaction behavior. `'vertical'` / `'horizontal'` reflow widgets to remove\n * gaps; `'free'` places each widget exactly where dropped and never pushes its\n * neighbours (pair with `allowOverlap` to let widgets stack, otherwise moving\n * onto an occupied cell is blocked); `null` disables compaction but still\n * resolves collisions the legacy react-grid-layout way. @default 'vertical'\n */\n compact?: BoardCompactType;\n /** Allow widgets to overlap. @default false */\n allowOverlap?: boolean;\n /** Block movement into occupied cells instead of pushing. @default false */\n preventCollision?: boolean;\n /** Enable dragging for all widgets. @default true */\n isDraggable?: boolean;\n /** Enable resizing for all widgets. @default true */\n isResizable?: boolean;\n /** Whether this board accepts widgets dropped from other boards. @default true */\n isDroppable?: boolean;\n /** Which resize handles to show. @default ['se'] */\n resizeHandles?: ResizeHandleAxis[];\n /**\n * CSS selector for elements that must not start a pointer drag (e.g. form\n * controls inside a widget: `\"input,textarea,button,a,.no-drag\"`). Does not\n * affect keyboard moves — those only run when the widget host itself is\n * focused. Can be overridden per widget on `Board.Widget`.\n */\n dragCancel?: string;\n /**\n * CSS selector for the only elements from which a pointer drag may start.\n * Can be overridden per widget on `Board.Widget`.\n */\n dragHandle?: string;\n /**\n * Show grid lines behind the widgets. `true` always shows them, `'drag'`\n * shows them only while a widget is being dragged or resized, `false` never.\n * @default false\n */\n showGridLines?: BoardGridLines;\n /**\n * Align this board's grid with an ancestor `Board`'s layout. Only takes\n * effect when the board is nested inside another `Board`'s widget. When set,\n * every cell matches the parent's cell size exactly: the board inherits the\n * parent's column pitch (deriving its own column count from its measured\n * width) and uses the parent's row height verbatim. It never shrinks rows to\n * fit; pair it with an `isAutoHeight` container so the widget grows to fit its\n * rows at that height. @default false\n */\n isAligned?: boolean;\n /**\n * Whether widgets can be selected, and how many at a time. `'multiple'` also\n * enables the marquee and rigid group movement: dragging any selected widget\n * moves the whole selection. @default 'none'\n */\n selectionMode?: BoardSelectionMode;\n /** Controlled selection. Keys are layout item ids (`LayoutItem.i`). */\n selectedKeys?: string[];\n /** Initial selection for uncontrolled usage. */\n defaultSelectedKeys?: string[];\n /**\n * Called when the selection changes. Keys are deduped and returned in the\n * board's layout order, never in click order.\n */\n onSelectionChange?: (keys: string[]) => void;\n /**\n * CSS selector for descendants whose clicks must never change the selection\n * (form controls, buttons, links). Mirrors `dragCancel`; can be overridden per\n * widget. Pass `''` to disable the guard entirely.\n * @default BOARD_SELECTION_CANCEL\n */\n selectionCancel?: string;\n /**\n * Draw a rubber-band (marquee) selection when a drag starts on empty board\n * space. Only meaningful with `selectionMode=\"multiple\"`.\n * @default selectionMode === 'multiple'\n */\n allowMarqueeSelection?: boolean;\n /**\n * Called when the user presses <kbd>Delete</kbd>/<kbd>Backspace</kbd> with a\n * non-empty selection, and focus is inside the board but not in an editable\n * field. Board never mutates the layout itself — removing the widgets is the\n * consumer's job. Board only handles these keys when this handler is set.\n */\n onWidgetsDelete?: (keys: string[]) => void;\n /** Grid/item layout constraints. */\n constraints?: LayoutConstraint[];\n /**\n * Explicit container width in pixels. When provided, disables automatic width\n * measurement (useful for SSR and tests).\n */\n width?: number;\n /**\n * Default props applied to every widget this board hosts. Per-widget\n * `Board.Widget` props override these. Use it to add a card border to every\n * widget (`widgetProps={{ isCard: true }}`) or set shared sizing/`styles`\n * defaults without repeating them on each `Board.Widget`.\n */\n widgetProps?: Partial<CubeBoardWidgetDefaults>;\n children?: ReactNode;\n}\n\n/**\n * Descendants whose clicks never change the selection. A widget is a large\n * surface the user also clicks to *work with*, so anything interactive inside it\n * must keep its click. `[data-no-select]` is the escape hatch for an app's own\n * custom controls.\n */\nexport const BOARD_SELECTION_CANCEL =\n 'input,textarea,select,button,a,[role=\"button\"],[role=\"menuitem\"],' +\n '[role=\"checkbox\"],[role=\"switch\"],[role=\"tab\"],[contenteditable=\"true\"],' +\n '[data-no-select]';\n\n/** Manhattan distance a pointer must travel before a press becomes a marquee. */\nconst MARQUEE_THRESHOLD = 4;\n\n/** Shared empty set, so \"no pre-selection\" is a stable reference. */\nconst NO_KEYS: ReadonlySet<string> = new Set();\n\n/**\n * Whether an event landed in a text-editing context. Checking the *event target*\n * beats `document.activeElement`: it stays correct for content rendered through\n * a portal, and it cannot be fooled by focus that moved between the keystroke\n * and the handler.\n */\nfunction isEditableTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n if (!el || typeof el.closest !== 'function') return false;\n\n return !!el.closest('input,textarea,select,[contenteditable=\"true\"]');\n}\n\nfunction compactTypeToCore(compact: BoardCompactType): CompactType {\n if (compact === 'free') return null;\n return compact;\n}\n\nfunction BoardInner(\n props: CubeBoardProps,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n id: providedId,\n layout: controlledLayout,\n defaultLayout,\n onLayoutChange,\n onDragStart,\n onDrag,\n onDragStop,\n onResizeStart,\n onResize: onResizeProp,\n onResizeStop,\n cols = 12,\n rowHeight = 100,\n margin = [8, 8],\n containerPadding,\n maxRows = Infinity,\n extraRows = 0,\n compact = 'vertical',\n allowOverlap = false,\n preventCollision = false,\n isDraggable = true,\n isResizable = true,\n isDroppable = true,\n resizeHandles = ['se'],\n dragCancel,\n dragHandle,\n showGridLines,\n isAligned = false,\n selectionMode = 'none',\n selectedKeys,\n defaultSelectedKeys,\n onSelectionChange,\n selectionCancel = BOARD_SELECTION_CANCEL,\n allowMarqueeSelection = selectionMode === 'multiple',\n onWidgetsDelete,\n constraints,\n width: providedWidth,\n widgetProps,\n children,\n ...otherProps\n } = props;\n\n const registry = useBoardRegistry()!;\n const parentMetrics = useBoardMetrics();\n const host = useBoardHost();\n const inheritedGridLines = useBoardGridLines();\n const aligned = isAligned && !!parentMetrics;\n // `widgetProps` may carry container style props directly (e.g. `fill`,\n // `padding`, `radius`) alongside an explicit `styles` object, mirroring\n // `Board.Widget`. Extract them into a single style map here so those defaults\n // actually reach every widget - forwarding only `widgetProps.styles` would\n // drop the direct props. A direct prop wins over the same key in `styles`.\n const widgetPropsStyles = useMemo<Styles | undefined>(() => {\n if (!widgetProps) return undefined;\n const extracted = extractStyles(widgetProps, CONTAINER_STYLES);\n return Object.keys(extracted).length > 0 ? extracted : undefined;\n }, [widgetProps]);\n // A nested board with no explicit `showGridLines` inherits the ancestor's:\n // when the ancestor has grid lines enabled, show them here while dragging.\n const effectiveShowGridLines: BoardGridLines =\n showGridLines ?? (inheritedGridLines ? 'drag' : false);\n const generatedId = useId();\n const boardId = providedId ?? generatedId;\n // One shared description node for every selected widget, so marking a widget\n // selected costs no per-widget DOM.\n const selectedHintId = `${generatedId}-selected`;\n const { t } = useI18n();\n\n const containerRef = useCombinedRefs(ref);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const [measuredWidth, setMeasuredWidth] = useState<number>(0);\n // Rendered height is only needed for aligned nested boards (to fit rows into\n // the space the container grants). It never drives the board's own height, so\n // measuring it cannot create a feedback loop.\n const [measuredHeight, setMeasuredHeight] = useState<number>(0);\n const width = providedWidth ?? measuredWidth;\n\n const onResizeContainer = useEvent(() => {\n const el = containerRef.current;\n if (!el) return;\n // A hidden container (e.g. the board inside an inactive tab after a\n // spring-loaded tab switch) reports 0. Keep the last non-zero measurement so\n // the board stays \"ready\" and keeps its widget hosts mounted while briefly\n // hidden. Otherwise the board would render nothing, unmounting the widget\n // that owns an in-flight drag gesture and stranding the drag (React Aria's\n // `useMove` tears down its listeners on unmount, so the drop never fires).\n const nextWidth = el.offsetWidth;\n const nextHeight = el.offsetHeight;\n if (nextWidth > 0) setMeasuredWidth(nextWidth);\n if (nextHeight > 0) setMeasuredHeight(nextHeight);\n });\n useResizeObserver({ ref: containerRef, onResize: onResizeContainer });\n useEffect(() => {\n if (providedWidth == null) {\n onResizeContainer();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [providedWidth]);\n\n const {\n layout,\n layoutRef,\n placeholders,\n placeholder,\n placeholdersRef,\n placeholderRef,\n setPlaceholders,\n applyLayout,\n } = useBoardLayout({\n layout: controlledLayout,\n defaultLayout,\n onLayoutChange,\n });\n\n // The accessible name a widget announces under. Mirrors `WidgetHost`'s own\n // fallback chain so the live region and the host never disagree.\n const getWidgetLabel = useEvent((key: string) => {\n const registration = registry.store.get(key);\n\n return registration?.['aria-label'] ?? registration?.qa ?? key;\n });\n\n // Whether a widget accepts selection at all. Every selection path resolves it\n // here — press, keyboard and marquee — so a lasso can never pick up a widget\n // that a press cannot.\n const isWidgetSelectable = (key: string) =>\n (registry.store.get(key)?.isSelectable ?? widgetProps?.isSelectable) !==\n false;\n\n const {\n selectedKeySet,\n selectedKeysRef,\n setSelection,\n select,\n clearSelection,\n announcement,\n } = useBoardSelection({\n selectionMode,\n selectedKeys,\n defaultSelectedKeys,\n onSelectionChange,\n layout,\n getLabel: getWidgetLabel,\n });\n\n const selectModifierKey = useBoardSelectModifierKey();\n\n // Re-render when any widget's registered content/config changes.\n useSyncExternalStore(registry.store.subscribe, registry.store.getVersion);\n\n // In aligned mode the board inherits the parent's gap so widget edges line up\n // with the surrounding layout; otherwise it uses its own `margin`.\n const effectiveMargin: readonly [number, number] = aligned\n ? parentMetrics!.margin\n : margin;\n // The board keeps its own padding (it sits inside the container's chrome);\n // when unspecified it defaults to the effective gap. An aligned nested board\n // is the exception: its grid origin must sit flush on the container widget's\n // edge (which already coincides with the parent's column-0 origin) so its\n // columns line up with the ancestor board's. Inheriting the gap there would\n // inset every column by one margin and break the alignment, so it defaults\n // to zero padding instead.\n const resolvedPadding: readonly [number, number] =\n containerPadding ?? (aligned ? [0, 0] : effectiveMargin);\n\n const rows = Math.max(\n bottom(layout),\n ...placeholders.map((p) => p.y + p.h),\n 0,\n );\n\n // Rows the board actually paints. `rows` stays the *content* extent — layout\n // math must not see the reserved band — while this is the extent the board\n // renders, so the band is real board surface: `ContentLayer` (inset: 0)\n // covers it, which is what lets a marquee start there and a widget be dropped\n // past the end.\n const renderedRows = Math.min(rows + Math.max(0, extraRows), maxRows);\n\n // Derive the aligned column count so each column keeps the parent's pixel\n // pitch: as the container widget is resized, columns are added/removed rather\n // than stretched. `containerWidth` is then back-solved so `calcGridColWidth`\n // returns exactly the parent's column width.\n const parentColWidth = aligned ? parentMetrics!.colWidth : 0;\n // `width` is `offsetWidth` (an integer the browser rounds), while\n // `parentColWidth` is fractional. A container sized to exactly N parent\n // columns can therefore measure a fraction of a pixel short, so a bare\n // `Math.floor` would drop the last column and leave its space unused. Add a\n // small pixel tolerance to absorb that rounding; it only rounds up when the\n // width is within ~2px of a full column, so it can't invent a column that\n // genuinely doesn't fit.\n const ALIGN_WIDTH_TOLERANCE = 2;\n const alignedCols =\n aligned && width > 0\n ? Math.max(\n 1,\n Math.floor(\n (width -\n resolvedPadding[0] * 2 +\n effectiveMargin[0] +\n ALIGN_WIDTH_TOLERANCE) /\n (parentColWidth + effectiveMargin[0]),\n ),\n )\n : cols;\n const effectiveCols = aligned ? alignedCols : cols;\n const effectiveContainerWidth = aligned\n ? parentColWidth * effectiveCols +\n effectiveMargin[0] * Math.max(0, effectiveCols - 1) +\n resolvedPadding[0] * 2\n : width;\n\n // An aligned board uses the parent's row height verbatim, so every cell is\n // exactly the parent's cell size (width already matches via the inherited\n // column pitch). It never shrinks rows to fit; pair it with an `isAutoHeight`\n // container so the widget grows to fit the rows at this height instead.\n const effectiveRowHeight = aligned ? parentMetrics!.rowHeight : rowHeight;\n\n const positionParams = useMemo<PositionParams>(\n () => ({\n margin: effectiveMargin,\n containerPadding: resolvedPadding,\n containerWidth: effectiveContainerWidth,\n cols: effectiveCols,\n rowHeight: effectiveRowHeight,\n maxRows,\n }),\n [\n effectiveMargin[0],\n effectiveMargin[1],\n resolvedPadding[0],\n resolvedPadding[1],\n effectiveContainerWidth,\n effectiveCols,\n effectiveRowHeight,\n maxRows,\n ],\n );\n\n // 'free' means no compaction (nothing is pushed up/left or recompacted) AND a\n // dragged widget never pushes or swaps its neighbours: it is placed exactly\n // where dropped. Without `allowOverlap` a move onto an occupied cell is\n // blocked (the widget stays at its last free spot); with `allowOverlap`\n // widgets may stack. The explicit `preventCollision` prop still applies to the\n // compacting modes (`vertical` / `horizontal`) and to the legacy `null` mode.\n const compactor = useMemo<Compactor>(\n () =>\n getCompactor(\n compactTypeToCore(compact),\n allowOverlap,\n compact === 'free' ? !allowOverlap : preventCollision,\n ),\n [compact, allowOverlap, preventCollision],\n );\n\n const resolvedConstraints = constraints ?? defaultConstraints;\n\n const computedHeight =\n renderedRows > 0\n ? renderedRows * effectiveRowHeight +\n Math.max(0, renderedRows - 1) * effectiveMargin[1] +\n resolvedPadding[1] * 2\n : effectiveRowHeight;\n // An aligned board fills the height the container grants it, so it reports its\n // measured height; otherwise it reports the height its content needs.\n const containerHeight =\n aligned && measuredHeight > 0 ? measuredHeight : computedHeight;\n\n // Live refs so the stable registry entry always reads current values.\n const liveRef = useRef({\n positionParams,\n compactor,\n constraints: resolvedConstraints,\n maxRows,\n containerHeight,\n isDroppable,\n });\n liveRef.current = {\n positionParams,\n compactor,\n constraints: resolvedConstraints,\n maxRows,\n containerHeight,\n isDroppable,\n };\n\n const applyLayoutEvent = useEvent(applyLayout);\n const setPlaceholdersEvent = useEvent(setPlaceholders);\n\n const entryRef = useRef<BoardEntry | null>(null);\n if (!entryRef.current) {\n entryRef.current = {\n id: boardId,\n getContentRect: () => contentRef.current?.getBoundingClientRect() ?? null,\n getContentNode: () => contentRef.current,\n getPositionParams: () => liveRef.current.positionParams,\n getConstraints: () => liveRef.current.constraints,\n getCompactor: () => liveRef.current.compactor,\n getMaxRows: () => liveRef.current.maxRows,\n getContainerHeight: () => liveRef.current.containerHeight,\n getLayout: () => layoutRef.current,\n // The registry reads this synchronously at drag start, so it must be the\n // ref rather than the rendered value.\n getSelectedKeys: () =>\n selectedKeysRef.current.size > 0 ? selectedKeysRef.current : null,\n applyLayout: (next, commit) => applyLayoutEvent(next, commit),\n setPlaceholders: (items) => setPlaceholdersEvent(items),\n isDroppable: () => liveRef.current.isDroppable,\n };\n }\n\n useEffect(() => {\n const entry = entryRef.current!;\n // Keep the entry's id in sync with the (possibly changed) board id before\n // registering. The previous effect's cleanup has already removed the old id,\n // so registering here keys the entry under the current id.\n entry.id = boardId;\n return registry.registerBoard(entry);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [boardId]);\n\n // When the aligned column count changes (the container was resized), reflow\n // the layout to the new width: clamp items back into bounds and recompact so\n // nothing overflows the narrower/wider grid.\n const recompactForCols = useEvent((nextCols: number) => {\n const corrected = correctBounds(cloneLayout(layoutRef.current), {\n cols: nextCols,\n });\n const compacted = [\n ...liveRef.current.compactor.compact(corrected, nextCols),\n ];\n applyLayoutEvent(compacted, true);\n });\n // `null` until the first *measured* aligned column count is established. This\n // avoids treating the initial zero-width -> measured-width transition as a\n // column-count change: a board that measures its own width (no explicit\n // `width` prop) renders first with `width === 0`, so `effectiveCols` falls\n // back to `cols` and only becomes the derived aligned count once measured.\n // Seeding the baseline on that first measured value (without committing)\n // prevents an unsolicited reflow + `onLayoutChange` before the user interacts.\n const prevAlignedColsRef = useRef<number | null>(null);\n useEffect(() => {\n if (!aligned) {\n // Re-entering aligned mode should re-seed from the next measured value.\n prevAlignedColsRef.current = null;\n return;\n }\n // Wait for a real width measurement; the fallback-`cols` value that stands\n // in before measurement is not a meaningful aligned column count.\n if (width <= 0) return;\n if (prevAlignedColsRef.current === null) {\n prevAlignedColsRef.current = effectiveCols;\n return;\n }\n if (prevAlignedColsRef.current === effectiveCols) return;\n prevAlignedColsRef.current = effectiveCols;\n recompactForCols(effectiveCols);\n }, [aligned, width, effectiveCols, recompactForCols]);\n\n // Natural height this board wants: its rows at the (parent) row height. When\n // the container is shorter than this, an `isAutoHeight` host grows to fit it\n // (aligned boards no longer shrink their rows).\n const naturalHeight =\n renderedRows > 0\n ? renderedRows * effectiveRowHeight +\n Math.max(0, renderedRows - 1) * effectiveMargin[1] +\n resolvedPadding[1] * 2\n : effectiveRowHeight;\n\n // Report this aligned board's height deficit to an auto-sizing host so the\n // host can both grow to fit and pin its resize floor. The value is signed:\n // positive when the board is squeezed (needs more height), negative when the\n // container is taller than needed (so the floor can be lowered). The host\n // never shrinks the widget on its own - it only grows and clamps resizing.\n const requestHeightDeficit = host?.requestHeightDeficit;\n useEffect(() => {\n if (!aligned || !host?.isAutoHeight || !requestHeightDeficit) return;\n if (measuredHeight <= 0) return;\n requestHeightDeficit(naturalHeight - measuredHeight);\n }, [\n aligned,\n host?.isAutoHeight,\n requestHeightDeficit,\n naturalHeight,\n measuredHeight,\n ]);\n\n // In-board resize orchestration.\n const resizeStateRef = useRef<{\n id: string;\n axis: ResizeHandleAxis;\n item: LayoutItem;\n origin: Position;\n accX: number;\n accY: number;\n } | null>(null);\n\n // Minimum rows each auto-height widget currently needs to fit its content.\n // Read during resize so a widget can never be dragged shorter than its\n // content, and used to grow the item when the content needs more room.\n const autoHeightMinRowsRef = useRef<Record<string, number>>({});\n\n const handleResize = useEvent(\n (\n id: string,\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => {\n const pp = liveRef.current.positionParams;\n\n if (phase === 'start') {\n const rawItem = getLayoutItem(layoutRef.current, id);\n if (!rawItem) return;\n // Layout-item min/max and constraints win; otherwise fall back to the\n // ones declared on the owning `Board.Widget` (and then the board-level\n // `widgetProps` defaults) so `applySizeConstraints` (via `minMaxSize`)\n // picks them up.\n const reg = registry.store.get(id);\n const item: LayoutItem = {\n ...rawItem,\n minW: rawItem.minW ?? reg?.minW ?? widgetProps?.minW,\n maxW: rawItem.maxW ?? reg?.maxW ?? widgetProps?.maxW,\n minH: rawItem.minH ?? reg?.minH ?? widgetProps?.minH,\n maxH: rawItem.maxH ?? reg?.maxH ?? widgetProps?.maxH,\n constraints:\n rawItem.constraints ?? reg?.constraints ?? widgetProps?.constraints,\n };\n resizeStateRef.current = {\n id,\n axis,\n item: { ...item },\n origin: calcGridItemPosition(pp, item.x, item.y, item.w, item.h),\n accX: 0,\n accY: 0,\n };\n setPlaceholders([{ ...item }]);\n onResizeStart?.({\n layout: layoutRef.current,\n item: { ...item },\n oldItem: { ...item },\n placeholder: { ...item },\n items: [{ ...item }],\n oldItems: [{ ...item }],\n placeholders: [{ ...item }],\n });\n return;\n }\n\n const rs = resizeStateRef.current;\n if (!rs) return;\n\n if (phase === 'end') {\n const finalLayout = [...layoutRef.current];\n applyLayout(finalLayout, true);\n setPlaceholders([]);\n const resizedItem = getLayoutItem(finalLayout, id) ?? rs.item;\n onResizeStop?.({\n layout: finalLayout,\n item: resizedItem,\n oldItem: rs.item,\n placeholder: null,\n items: [resizedItem],\n oldItems: [rs.item],\n placeholders: [],\n });\n resizeStateRef.current = null;\n return;\n }\n\n rs.accX += dx;\n rs.accY += dy;\n\n const { origin, item, axis: handle } = rs;\n let newW = origin.width;\n let newH = origin.height;\n if (handle.includes('e')) newW = origin.width + rs.accX;\n if (handle.includes('w')) newW = origin.width - rs.accX;\n if (handle.includes('s')) newH = origin.height + rs.accY;\n if (handle.includes('n')) newH = origin.height - rs.accY;\n newW = Math.max(newW, 8);\n newH = Math.max(newH, 8);\n\n const raw = calcWH(pp, newW, newH, item.x, item.y, handle);\n const constrained = applySizeConstraints(\n liveRef.current.constraints,\n item,\n raw.w,\n raw.h,\n handle,\n {\n cols: pp.cols,\n maxRows: liveRef.current.maxRows,\n containerWidth: pp.containerWidth,\n containerHeight: liveRef.current.containerHeight,\n rowHeight: pp.rowHeight,\n margin: pp.margin,\n layout: layoutRef.current,\n },\n );\n\n // An auto-height widget cannot be resized shorter than the content it\n // hosts (a nested board) currently needs, so pin its height to the floor.\n const floorRows = autoHeightMinRowsRef.current[id] ?? 0;\n const finalW = constrained.w;\n const finalH = Math.max(constrained.h, floorRows);\n\n let x = item.x;\n let y = item.y;\n if (handle.includes('w')) x = item.x + item.w - finalW;\n if (handle.includes('n')) y = item.y + item.h - finalH;\n x = Math.max(0, x);\n y = Math.max(0, y);\n\n let newItem: LayoutItem = {\n ...item,\n x,\n y,\n w: finalW,\n h: finalH,\n };\n\n // Collision-blocking modes (`free` without `allowOverlap`, or an explicit\n // `preventCollision`) run a no-op/gap-filling compactor that never\n // resolves overlaps, so a resize must be blocked here the same way the\n // drag path blocks a move (`moveElement` reverts on collision). Without\n // this, growing or moving an edge via a resize handle could push the box\n // onto an occupied cell. When the new box overlaps a neighbour, revert to\n // the last committed box for this widget so the gesture stalls at the\n // last valid size/position instead of overlapping.\n const compactor = liveRef.current.compactor;\n if (compactor.preventCollision && !compactor.allowOverlap) {\n const collides = getAllCollisions(layoutRef.current, newItem).some(\n (other) => other.i !== id,\n );\n if (collides) {\n const lastValid = getLayoutItem(layoutRef.current, id);\n if (lastValid) newItem = { ...lastValid };\n }\n }\n\n const working = modifyLayout(layoutRef.current, newItem);\n const compacted = [...compactor.compact(working, pp.cols)];\n applyLayout(compacted, false);\n const nextPlaceholder = getLayoutItem(compacted, id) ?? newItem;\n setPlaceholders([nextPlaceholder]);\n const resizedItem = getLayoutItem(compacted, id) ?? newItem;\n onResizeProp?.({\n layout: compacted,\n item: resizedItem,\n oldItem: rs.item,\n placeholder: nextPlaceholder,\n items: [resizedItem],\n oldItems: [rs.item],\n placeholders: [nextPlaceholder],\n });\n },\n );\n\n // Record an auto-height widget's needed rows. Grow the item when its content\n // needs more height (only ever increases); the stored value is also the\n // resize floor enforced in `handleResize`.\n const handleAutoHeight = useEvent((id: string, neededRows: number) => {\n autoHeightMinRowsRef.current[id] = neededRows;\n const current = getLayoutItem(layoutRef.current, id);\n if (!current || neededRows <= current.h) return;\n // While a drag or resize gesture is in flight the layout is transient - the\n // registry (drag) and `handleResize` write uncommitted previews and commit\n // only on drop / release. Growing an auto-height widget here with\n // `commit: true` would fire `onLayoutChange` mid-gesture and persist the\n // in-flight positions of the widget being moved. Skip the grow-commit; the\n // floor ref is already updated above (so `handleResize` still respects it),\n // and the deficit effect re-fires once the gesture settles.\n if (registry.dragState || resizeStateRef.current) return;\n const pp = liveRef.current.positionParams;\n const working = modifyLayout(layoutRef.current, {\n ...current,\n h: neededRows,\n });\n const compacted = [...liveRef.current.compactor.compact(working, pp.cols)];\n applyLayout(compacted, true);\n });\n\n // The dragged item captured at gesture start, so drag callbacks can report the\n // original position throughout (and after a cross-board transfer removes the\n // item from this board's layout).\n const dragOldItemRef = useRef<LayoutItem | null>(null);\n // The same, for every other member of a group drag. Empty for an ordinary\n // drag, which is what keeps `items`/`oldItems` single-entry there.\n const dragOldItemsRef = useRef<LayoutItem[]>([]);\n\n const handleDragLifecycle = useEvent((id: string, phase: ResizePhase) => {\n const currentLayout = layoutRef.current;\n const liveItem = getLayoutItem(currentLayout, id);\n\n if (phase === 'start') {\n dragOldItemRef.current = liveItem ? { ...liveItem } : null;\n // The registry has already resolved the group by the time this fires, so\n // its drag state is the authority on who is moving.\n const ds = registry.getDragState();\n dragOldItemsRef.current =\n ds && ds.itemId === id ? ds.items.map((it) => ({ ...it })) : [];\n }\n const oldItem = dragOldItemRef.current ?? liveItem;\n if (!oldItem) return;\n const item = liveItem ?? oldItem;\n\n const oldItems = dragOldItemsRef.current.length\n ? dragOldItemsRef.current\n : [oldItem];\n const items = oldItems.map(\n (old) => getLayoutItem(currentLayout, old.i) ?? old,\n );\n\n const info: BoardInteractionInfo = {\n layout: currentLayout,\n item,\n oldItem,\n // Read the live refs, not render-time state: the registry calls\n // `setPlaceholders` synchronously right before this fires, and that only\n // schedules a re-render, so `placeholders` state still holds the previous\n // value (or a stale preview after the drop clears it).\n placeholder: placeholderRef.current,\n items,\n oldItems,\n placeholders: placeholdersRef.current,\n };\n if (phase === 'start') onDragStart?.(info);\n else if (phase === 'move') onDrag?.(info);\n else {\n onDragStop?.(info);\n dragOldItemRef.current = null;\n dragOldItemsRef.current = [];\n }\n });\n\n // ---- Marquee (rubber-band) selection --------------------------------------\n //\n // Board owns this rather than exposing hooks for an app to build it, because\n // deciding which widgets a band covers needs every widget's box — and the DOM\n // is the wrong place to read them from. Widget hosts transition `inset`/`width`\n // /`height` while the board reflows, and a host being dragged is swapped for an\n // `opacity: 0` stand-in with a fixed-position clone in the overlay, so\n // `getBoundingClientRect` during a marquee returns interpolated or misleading\n // boxes. `calcGridItemPosition` derives the same rectangles exactly, from the\n // layout, with no forced reflow and no sensitivity to ancestor transforms.\n const [marqueeRect, setMarqueeRect] = useState<Position | null>(null);\n // Which widgets the band covers *right now*. Committing only on release\n // leaves the user guessing what they are about to select, so the band drives a\n // provisional state on the hosts as it grows and shrinks. The board already\n // re-renders once per pointer frame for the band itself, so this is free.\n const [preSelectedKeys, setPreSelectedKeys] =\n useState<ReadonlySet<string>>(NO_KEYS);\n // Drives `user-select: none` for the duration of the gesture. Set on press\n // rather than at the threshold, so even a press that never becomes a marquee\n // cannot start painting a text selection.\n const [isMarqueeActive, setIsMarqueeActive] = useState(false);\n\n const handleContentPointerDown = useEvent((event: React.PointerEvent) => {\n if (\n selectionMode !== 'multiple' ||\n !allowMarqueeSelection ||\n event.button !== 0 ||\n registry.dragState\n ) {\n return;\n }\n\n const target = event.target as HTMLElement | null;\n // A press on a widget selects it and arms a drag; the lasso owns empty\n // canvas only.\n if (target?.closest('[data-board-widget-host]')) return;\n if (selectionCancel && target?.closest(selectionCancel)) return;\n\n const content = contentRef.current;\n if (!content) return;\n\n // Suppress the compatibility mouse events that would begin a native text\n // selection. Safe here specifically because every case that wants default\n // behaviour — a widget, an interactive descendant — has already bailed out\n // above, and focus is placed explicitly in `finish`.\n event.preventDefault();\n setIsMarqueeActive(true);\n\n const origin = content.getBoundingClientRect();\n const startX = event.clientX;\n const startY = event.clientY;\n // Holding the modifier means \"add to what I have\"; a bare lasso replaces.\n const additive = event[selectModifierKey] || event.shiftKey;\n const base = additive ? [...selectedKeysRef.current] : [];\n let passedThreshold = false;\n\n const hitTest = (clientX: number, clientY: number) => {\n const left = Math.min(startX, clientX) - origin.left;\n const right = Math.max(startX, clientX) - origin.left;\n const top = Math.min(startY, clientY) - origin.top;\n const bottom = Math.max(startY, clientY) - origin.top;\n const next = new Set(base);\n\n for (const it of layoutRef.current) {\n if (!isWidgetSelectable(it.i)) continue;\n const pos = calcGridItemPosition(\n liveRef.current.positionParams,\n it.x,\n it.y,\n it.w,\n it.h,\n );\n if (\n pos.left < right &&\n pos.left + pos.width > left &&\n pos.top < bottom &&\n pos.top + pos.height > top\n ) {\n next.add(it.i);\n }\n }\n\n return {\n next,\n box: { left, top, width: right - left, height: bottom - top },\n };\n };\n\n // Belt and braces for the `preventDefault` above: a press that starts on\n // empty canvas and then travels into text still gets a `selectstart` in some\n // browsers, and `user-select: none` alone does not unwind a selection that is\n // already growing.\n const blockSelectStart = (e: Event) => e.preventDefault();\n\n const handleMove = (e: PointerEvent) => {\n if (\n !passedThreshold &&\n Math.abs(e.clientX - startX) + Math.abs(e.clientY - startY) <\n MARQUEE_THRESHOLD\n ) {\n return;\n }\n if (!passedThreshold) {\n // Drop a selection the user made inside this board *before* the lasso\n // started, so the band never drags a stale highlight along with it.\n // Scoped to this board: a selection anywhere else on the page is theirs.\n const selection = window.getSelection();\n const anchor = selection?.anchorNode;\n if (anchor && containerRef.current?.contains(anchor)) {\n selection?.removeAllRanges();\n }\n }\n passedThreshold = true;\n\n const { box, next } = hitTest(e.clientX, e.clientY);\n setMarqueeRect(box);\n setPreSelectedKeys(next);\n };\n\n const finish = (e: PointerEvent) => {\n window.removeEventListener('pointermove', handleMove);\n window.removeEventListener('pointerup', finish);\n window.removeEventListener('pointercancel', finish);\n window.removeEventListener('selectstart', blockSelectStart);\n setMarqueeRect(null);\n setPreSelectedKeys(NO_KEYS);\n setIsMarqueeActive(false);\n\n // One commit per gesture: `onSelectionChange` and the announcement fire on\n // release, never once per pointer frame.\n if (passedThreshold) {\n setSelection(hitTest(e.clientX, e.clientY).next);\n } else if (!additive) {\n // A plain click on empty board space clears.\n clearSelection();\n }\n // Keep focus somewhere inside the board so Escape has a handler to reach.\n containerRef.current?.focus({ preventScroll: true });\n };\n\n window.addEventListener('pointermove', handleMove);\n window.addEventListener('pointerup', finish);\n window.addEventListener('pointercancel', finish);\n window.addEventListener('selectstart', blockSelectStart);\n });\n\n const marqueeStyle = marqueeRect\n ? {\n left: `${marqueeRect.left}px`,\n top: `${marqueeRect.top}px`,\n width: `${marqueeRect.width}px`,\n height: `${marqueeRect.height}px`,\n }\n : null;\n\n // Selection is focus-like, so it does not outlive focus leaving the board.\n // Tabbing away, or clicking any focusable thing elsewhere on the page, drops\n // it — the same way a text selection or a focus ring would go.\n const { focusWithinProps: boardFocusWithinProps } = useFocusWithin({\n isDisabled: selectionMode === 'none',\n onBlurWithin: () => clearSelection(),\n });\n\n // ---- Board-level keys -----------------------------------------------------\n //\n // On the board element, never on `document`: a library-owned document listener\n // fires for keystrokes that never went near a board, and two boards on a page\n // would both react.\n const handleBoardKeyDown = useEvent((event: React.KeyboardEvent) => {\n if (selectionMode === 'none') return;\n\n const selected = selectedKeysRef.current;\n if (selected.size === 0) return;\n\n if (event.key === 'Escape') {\n // `preventDefault` only when we actually consumed the key, so an Escape\n // with nothing selected still closes an ancestor Dialog or Popover.\n event.preventDefault();\n event.stopPropagation();\n clearSelection();\n\n return;\n }\n\n if (\n (event.key === 'Delete' || event.key === 'Backspace') &&\n onWidgetsDelete &&\n !isEditableTarget(event.target)\n ) {\n event.preventDefault();\n event.stopPropagation();\n const keys = [...selected];\n clearSelection();\n onWidgetsDelete(keys);\n // The deleted widgets' hosts are about to unmount, so focus would be left\n // on a detached node. Park it on the board.\n containerRef.current?.focus({ preventScroll: true });\n }\n });\n\n const styles: Styles = extractStyles(otherProps, CONTAINER_STYLES);\n\n const dragState = registry.dragState;\n const ready = width > 0;\n\n // Gate widget position transitions off until the widgets have been painted at\n // their initial positions once. Without this, the first render animates every\n // widget sliding in from its default spot (0, 0). We render one frame with the\n // gate closed (no `inset` transition), let the browser paint, then lift it so\n // later reflows animate. A double rAF waits past the first committed paint;\n // re-arm whenever the board (re)becomes ready so a board that hides and\n // remeasures (e.g. inside a tab) re-settles too.\n const [settled, setSettled] = useState(false);\n useEffect(() => {\n if (!ready) {\n setSettled(false);\n return;\n }\n let id1 = 0;\n let id2 = 0;\n id1 = requestAnimationFrame(() => {\n id2 = requestAnimationFrame(() => setSettled(true));\n });\n return () => {\n cancelAnimationFrame(id1);\n if (id2) cancelAnimationFrame(id2);\n };\n }, [ready]);\n\n // When the widget that hosts this nested board is the one being dragged, its\n // whole content (including this board) floats as a single unit, so its own\n // grid lines add nothing but clutter. Suppress them for that drag.\n const hostWidgetIsDragging =\n !!dragState && dragState.nestedBoardIds.has(boardId);\n\n const placeholderStyles = useMemo(\n () =>\n placeholders.map((p) => {\n const pos = calcGridItemPosition(positionParams, p.x, p.y, p.w, p.h);\n\n return {\n i: p.i,\n style: {\n left: `${pos.left}px`,\n top: `${pos.top}px`,\n width: `${pos.width}px`,\n height: `${pos.height}px`,\n },\n };\n }),\n [placeholders, positionParams],\n );\n\n const gridLinesVisible =\n !hostWidgetIsDragging &&\n (effectiveShowGridLines === true ||\n (effectiveShowGridLines === 'drag' && (!!dragState || !!placeholder)));\n const gridOverlayStyle = gridLinesVisible\n ? (() => {\n const colWidth = calcGridColWidth(positionParams);\n const rowHeightPx = positionParams.rowHeight;\n // A grid with margins has real gaps between cells, so any line-based\n // overlay either misses a cell edge (single line at the cell pitch) or\n // shows a double line in every gap (a line at both edges). Instead,\n // paint each snap cell as a faint block sized exactly `colWidth` x\n // `rowHeightPx` with the margin gaps left transparent: the blocks line\n // up 1:1 with the drop-zone placeholder and there are no lines to\n // double. Column stripes form the background; a row-band alpha mask\n // intersects them into cells.\n const pitchX = colWidth + effectiveMargin[0];\n const pitchY = rowHeightPx + effectiveMargin[1];\n // Position the overlay as an explicit rectangle inset by the board's\n // resolved padding and sized to exactly cover the grid content (cols x\n // rows). This makes the padding a symmetric frame on all four edges (the\n // previous `inset: 0` + top-left-anchored repeat left the padding\n // unvisualized on the right/bottom and inside any extra min-height) and\n // lets the cell pattern tile from the overlay's own origin.\n const padX = resolvedPadding[0];\n const padY = resolvedPadding[1];\n const gridWidth = Math.max(0, effectiveContainerWidth - padX * 2);\n // Painted over the reserved band too — grid cells are what make the\n // band read as board rather than as page background behind it.\n const gridHeight =\n renderedRows > 0\n ? renderedRows * rowHeightPx +\n (renderedRows - 1) * effectiveMargin[1]\n : 0;\n const fill = 'var(--border-color)';\n const columns = `repeating-linear-gradient(to right, ${fill} 0, ${fill} ${colWidth}px, transparent ${colWidth}px, transparent ${pitchX}px)`;\n const rowsGrad = `repeating-linear-gradient(to bottom, #000 0, #000 ${rowHeightPx}px, transparent ${rowHeightPx}px, transparent ${pitchY}px)`;\n return {\n left: `${padX}px`,\n top: `${padY}px`,\n width: `${gridWidth}px`,\n height: `${gridHeight}px`,\n backgroundImage: columns,\n backgroundPosition: '0 0',\n backgroundRepeat: 'repeat',\n maskImage: rowsGrad,\n WebkitMaskImage: rowsGrad,\n maskPosition: '0 0',\n WebkitMaskPosition: '0 0',\n maskRepeat: 'repeat',\n WebkitMaskRepeat: 'repeat',\n };\n })()\n : null;\n\n // Metrics this board exposes to any aligned boards nested inside its widgets.\n const boardMetrics = useMemo<BoardMetrics>(\n () => ({\n colWidth: calcGridColWidth(positionParams),\n rowHeight: positionParams.rowHeight,\n margin: positionParams.margin,\n containerPadding: positionParams.containerPadding,\n }),\n [positionParams],\n );\n\n return (\n <BoardMetricsContext.Provider value={boardMetrics}>\n <BoardGridLinesContext.Provider\n value={\n effectiveShowGridLines === true || effectiveShowGridLines === 'drag'\n }\n >\n <BoardElement\n {...mergeProps(\n filterBaseProps(otherProps, { eventProps: true }),\n boardFocusWithinProps,\n { onKeyDown: handleBoardKeyDown },\n )}\n ref={containerRef}\n styles={styles}\n // A board that owns keys needs somewhere for focus to land after a\n // marquee or a delete, so Escape always reaches `handleBoardKeyDown`.\n tabIndex={selectionMode !== 'none' ? -1 : undefined}\n data-board-id={boardId}\n // Non-aligned: use min-height (not a fixed height) so the board\n // auto-sizes to its content by default but can still grow to fill a\n // taller parent. Widgets are absolutely positioned, so growing never\n // shifts them, and the content layer (inset: 0) always covers the full\n // board -> the whole board is droppable. Aligned: omit the inline height\n // so the board fills (and is bounded by) the space the container grants,\n // which is what drives the reduced row height.\n style={aligned ? undefined : { minHeight: `${containerHeight}px` }}\n mods={{\n dragging: !!dragState,\n 'drop-target': dragState?.currentBoardId === boardId,\n marquee: isMarqueeActive,\n }}\n >\n <ContentLayer\n ref={contentRef}\n onPointerDown={handleContentPointerDown}\n >\n {ready && gridOverlayStyle ? (\n <GridOverlayElement aria-hidden=\"true\" style={gridOverlayStyle} />\n ) : null}\n {ready\n ? layout.map((item) => {\n const registration = registry.store.get(item.i);\n const widgetDraggable =\n isDraggable &&\n (registration?.isDraggable ?? widgetProps?.isDraggable) !==\n false &&\n item.isDraggable !== false &&\n !item.static;\n const widgetResizable =\n isResizable &&\n (registration?.isResizable ?? widgetProps?.isResizable) !==\n false &&\n item.isResizable !== false &&\n !item.static;\n const handles =\n item.resizeHandles ??\n registration?.resizeHandles ??\n widgetProps?.resizeHandles ??\n resizeHandles;\n const widgetDragCancel =\n registration?.dragCancel ??\n widgetProps?.dragCancel ??\n dragCancel;\n const widgetDragHandle =\n registration?.dragHandle ??\n widgetProps?.dragHandle ??\n dragHandle;\n // Per-widget `isCard`/`styles` override the board-level\n // `widgetProps` defaults; `isCard` defaults to `false`\n // (borderless - widgets are always filled and rounded).\n const widgetIsCard =\n registration?.isCard ?? widgetProps?.isCard ?? false;\n // Per-widget `isAutoHeight`/`qa` fall back to the board-level\n // `widgetProps` defaults (mirroring the other widget props).\n const widgetIsAutoHeight =\n registration?.isAutoHeight ??\n widgetProps?.isAutoHeight ??\n false;\n const widgetQa = registration?.qa ?? widgetProps?.qa;\n const widgetSelectable =\n selectionMode !== 'none' && isWidgetSelectable(item.i);\n const widgetSelectionCancel =\n registration?.selectionCancel ??\n widgetProps?.selectionCancel ??\n selectionCancel;\n // Merge board-level `widgetProps` styles (its `styles` object\n // plus direct style props) with the per-widget styles so\n // shared defaults survive when a widget sets even a single\n // style prop; per-widget styles win on conflicts. Only merge\n // when both exist to preserve reference stability (and avoid\n // churn) in the common single-source case.\n const widgetStyles =\n registration?.styles && widgetPropsStyles\n ? mergeStyles(widgetPropsStyles, registration.styles)\n : registration?.styles ?? widgetPropsStyles;\n\n return (\n <WidgetHost\n key={item.i}\n boardId={boardId}\n item={item}\n positionParams={positionParams}\n registration={registration}\n isCard={widgetIsCard}\n styles={widgetStyles as Styles}\n isDraggable={widgetDraggable}\n isResizable={widgetResizable}\n resizeHandles={handles}\n isAutoHeight={widgetIsAutoHeight}\n qa={widgetQa}\n dragCancel={widgetDragCancel}\n dragHandle={widgetDragHandle}\n isSelectable={widgetSelectable}\n isSelected={selectedKeySet.has(item.i)}\n isPreSelected={preSelectedKeys.has(item.i)}\n selectionCancel={widgetSelectionCancel}\n selectedHintId={selectedHintId}\n onSelect={select}\n onSelectionReset={clearSelection}\n selectModifierKey={selectModifierKey}\n registry={registry}\n dragState={dragState}\n settled={settled}\n onResize={handleResize}\n onAutoHeight={handleAutoHeight}\n onDragLifecycle={handleDragLifecycle}\n />\n );\n })\n : null}\n {placeholderStyles.map(({ i, style }) => (\n <PlaceholderElement key={i} aria-hidden=\"true\" style={style} />\n ))}\n {marqueeStyle ? (\n <MarqueeElement aria-hidden=\"true\" style={marqueeStyle} />\n ) : null}\n </ContentLayer>\n {selectionMode !== 'none' ? (\n <A11yLayer>\n <span id={selectedHintId}>{t('board.selected', 'Selected')}</span>\n <span role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {announcement}\n </span>\n </A11yLayer>\n ) : null}\n {children}\n </BoardElement>\n </BoardGridLinesContext.Provider>\n </BoardMetricsContext.Provider>\n );\n}\n\nconst BoardInnerForwarded = forwardRef(BoardInner);\n\n/**\n * A draggable and resizable widget grid. Widgets are declared with\n * `Board.Widget` and positioned via a `layout`. Wrap multiple boards in a\n * `BoardProvider` to enable dragging widgets between them.\n */\nexport const Board = forwardRef(function Board(\n props: CubeBoardProps,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const existingRegistry = useBoardRegistry();\n\n if (existingRegistry) {\n return <BoardInnerForwarded {...props} ref={ref} />;\n }\n\n return (\n <BoardProvider>\n <BoardInnerForwarded {...props} ref={ref} />\n </BoardProvider>\n );\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.160.0 | Cube Dev Team */
|
|
2
2
|
import { BoardDragActiveContext, BoardRegistryContext } from "./board-context.js";
|
|
3
3
|
import { useBoardRegistry } from "./use-board-registry.js";
|
|
4
4
|
import { tasty } from "@tenphi/tasty";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.160.0 | Cube Dev Team */
|
|
2
2
|
import { useCombinedRefs } from "../../../utils/react/useCombinedRefs.js";
|
|
3
3
|
import { useEvent } from "../../../_internal/hooks/use-event.js";
|
|
4
4
|
import { getCompactor } from "./grid-core/compactors.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.160.0 | Cube Dev Team */
|
|
2
2
|
import { extractStyles } from "../../../utils/styles.js";
|
|
3
3
|
import { useLayoutEffect as useLayoutEffect$1 } from "../../../utils/react/useLayoutEffect.js";
|
|
4
4
|
import { useBoardRegistry } from "./board-context.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.160.0 | Cube Dev Team */
|
|
2
2
|
import { mergeProps as mergeProps$1 } from "../../../utils/react/mergeProps.js";
|
|
3
3
|
import { useEvent } from "../../../_internal/hooks/use-event.js";
|
|
4
4
|
import { useI18n } from "../../../i18n/useI18n.js";
|
|
@@ -27,11 +27,13 @@ const WidgetElement = tasty({
|
|
|
27
27
|
border: {
|
|
28
28
|
"": false,
|
|
29
29
|
card: true,
|
|
30
|
+
"pre-selected": "#primary-border",
|
|
30
31
|
selected: "#primary-border"
|
|
31
32
|
},
|
|
32
33
|
shadow: {
|
|
33
34
|
"": false,
|
|
34
35
|
"hovered & !card & (draggable | resizing)": "0 0 0 1bw #border",
|
|
36
|
+
"pre-selected": "0 0 0 1bw #primary.40",
|
|
35
37
|
selected: "0 0 0 1bw #primary",
|
|
36
38
|
"drag | resizing": "$dialog-shadow"
|
|
37
39
|
},
|
|
@@ -261,7 +263,7 @@ function ResizeHandle({ axis, onResize }) {
|
|
|
261
263
|
* renders into the shared overlay portal so it can float outside its board.
|
|
262
264
|
*/
|
|
263
265
|
function WidgetHost(props) {
|
|
264
|
-
const { boardId, item, positionParams, registration, isCard, styles: widgetStyles, isDraggable, isResizable, resizeHandles, isAutoHeight, qa, dragCancel, dragHandle, registry, dragState, settled, onResize, onAutoHeight, onDragLifecycle, isSelectable = false, isSelected = false, selectionCancel, selectedHintId, onSelect, onSelectionReset, selectModifierKey = "metaKey" } = props;
|
|
266
|
+
const { boardId, item, positionParams, registration, isCard, styles: widgetStyles, isDraggable, isResizable, resizeHandles, isAutoHeight, qa, dragCancel, dragHandle, registry, dragState, settled, onResize, onAutoHeight, onDragLifecycle, isSelectable = false, isSelected = false, isPreSelected = false, selectionCancel, selectedHintId, onSelect, onSelectionReset, selectModifierKey = "metaKey" } = props;
|
|
265
267
|
const { t } = useI18n();
|
|
266
268
|
const ariaLabel = registration?.["aria-label"];
|
|
267
269
|
const hostRef = useRef(null);
|
|
@@ -424,7 +426,8 @@ function WidgetHost(props) {
|
|
|
424
426
|
card: isCard,
|
|
425
427
|
hovered: isHovered,
|
|
426
428
|
"focus-visible": isFocusVisible,
|
|
427
|
-
selected: isSelected
|
|
429
|
+
selected: isSelected,
|
|
430
|
+
"pre-selected": isPreSelected && !isSelected
|
|
428
431
|
};
|
|
429
432
|
const content = /* @__PURE__ */ jsxs(BoardHostContext.Provider, {
|
|
430
433
|
value: hostValue,
|