@cube-dev/ui-kit 0.0.0-canary-3cf647a → 0.0.0-canary-ea72271
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/_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.js +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.js +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 +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/InlineInput/InlineInput.js +1 -1
- package/dist/components/content/Item/Item.js +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/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/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/TimeInput.js +1 -1
- package/dist/components/fields/DatePicker/intl.js +1 -1
- package/dist/components/fields/DatePicker/parseDate.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/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/form/FieldWrapper/FieldWrapper.js +1 -1
- package/dist/components/form/FieldWrapper/extract-field-wrapper-props.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/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.d.ts +9 -0
- package/dist/components/layout/Board/Board.js +128 -52
- package/dist/components/layout/Board/Board.js.map +1 -1
- package/dist/components/layout/Board/BoardProvider.js +1 -1
- package/dist/components/layout/Board/Widget.d.ts +6 -0
- package/dist/components/layout/Board/Widget.js +4 -3
- package/dist/components/layout/Board/Widget.js.map +1 -1
- package/dist/components/layout/Board/WidgetHost.js +36 -13
- package/dist/components/layout/Board/WidgetHost.js.map +1 -1
- package/dist/components/layout/Board/board-context.js +10 -2
- package/dist/components/layout/Board/board-context.js.map +1 -1
- package/dist/components/layout/Board/board-store.js +2 -2
- package/dist/components/layout/Board/board-store.js.map +1 -1
- package/dist/components/layout/Board/grid-core/calculate.js +2 -2
- 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/layout.js +23 -2
- package/dist/components/layout/Board/grid-core/layout.js.map +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/use-board-layout.js +1 -1
- package/dist/components/layout/Board/use-board-registry.js +11 -2
- package/dist/components/layout/Board/use-board-registry.js.map +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/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/FileTabs/FileTabs.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/RangeCalendar.js +1 -1
- package/dist/components/other/CloudLogo/CloudLogo.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.js +1 -1
- package/dist/data/themes.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/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/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/colors.js +1 -1
- package/dist/tokens/index.js +1 -1
- package/dist/tokens/layout.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/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/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/layout/Board.md +13 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetHost.js","names":["mergeProps"],"sources":["../../../../src/components/layout/Board/WidgetHost.tsx"],"sourcesContent":["import { Styles, tasty } from '@tenphi/tasty';\nimport { CSSProperties, useRef, useState } from 'react';\nimport { useFocusWithin, useHover, useMove } from 'react-aria';\nimport { createPortal } from 'react-dom';\n\nimport { mergeProps } from '../../../utils/react';\n\nimport {\n BoardDragState,\n BoardRegistryContextValue,\n ViewportRect,\n} from './board-context';\nimport { WidgetRegistration } from './board-store';\nimport {\n calcGridColWidth,\n calcGridItemPosition,\n LayoutItem,\n PositionParams,\n ResizeHandleAxis,\n} from './grid-core';\n\nexport type ResizePhase = 'start' | 'move' | 'end';\n\nconst WidgetElement = tasty({\n qa: 'BoardWidget',\n styles: {\n position: 'absolute',\n top: 0,\n left: 0,\n fill: '#surface',\n radius: '1cr',\n border: true,\n shadow: {\n '': false,\n 'drag | resizing': '0 2x 4x #dark.20',\n },\n zIndex: {\n '': 1,\n 'drag | resizing': 10,\n },\n transition: 'theme, shadow',\n boxSizing: 'border-box',\n userSelect: {\n '': 'auto',\n 'drag | resizing': 'none',\n },\n cursor: {\n '': 'auto',\n draggable: 'grab',\n drag: 'grabbing',\n },\n touchAction: 'none',\n overflow: 'hidden',\n },\n});\n\nconst HandleElement = tasty({\n qa: 'BoardResizeHandle',\n styles: {\n position: 'absolute',\n zIndex: 20,\n fill: '#clear',\n // Overhang: how far the hit-zone extends beyond the widget edge.\n '--handle-size': '24px',\n '--handle-overhang': '-8px',\n '--handle-inset': '8px',\n width: {\n '': '$handle-size',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': 'auto',\n },\n height: {\n '': '$handle-size',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': 'auto',\n },\n top: {\n '': 'auto',\n '[data-axis=\"n\"] | [data-axis=\"ne\"] | [data-axis=\"nw\"]':\n '$handle-overhang',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': '$handle-inset',\n },\n bottom: {\n '': 'auto',\n '[data-axis=\"s\"] | [data-axis=\"se\"] | [data-axis=\"sw\"]':\n '$handle-overhang',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': '$handle-inset',\n },\n left: {\n '': 'auto',\n '[data-axis=\"w\"] | [data-axis=\"nw\"] | [data-axis=\"sw\"]':\n '$handle-overhang',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': '$handle-inset',\n },\n right: {\n '': 'auto',\n '[data-axis=\"e\"] | [data-axis=\"ne\"] | [data-axis=\"se\"]':\n '$handle-overhang',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': '$handle-inset',\n },\n cursor: {\n '': 'default',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': 'ns-resize',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': 'ew-resize',\n '[data-axis=\"ne\"] | [data-axis=\"sw\"]': 'nesw-resize',\n '[data-axis=\"nw\"] | [data-axis=\"se\"]': 'nwse-resize',\n },\n touchAction: 'none',\n },\n});\n\nconst GripElement = tasty({\n qa: 'BoardResizeGrip',\n styles: {\n position: 'absolute',\n width: '10px',\n height: '10px',\n boxSizing: 'border-box',\n pointerEvents: 'none',\n opacity: {\n '': 0,\n revealed: 1,\n },\n transition: 'opacity 120ms ease-in-out',\n borderTop: {\n '': '0',\n '[data-axis=\"ne\"] | [data-axis=\"nw\"]': '2px solid #dark.40',\n },\n borderBottom: {\n '': '0',\n '[data-axis=\"se\"] | [data-axis=\"sw\"]': '2px solid #dark.40',\n },\n borderLeft: {\n '': '0',\n '[data-axis=\"nw\"] | [data-axis=\"sw\"]': '2px solid #dark.40',\n },\n borderRight: {\n '': '0',\n '[data-axis=\"ne\"] | [data-axis=\"se\"]': '2px solid #dark.40',\n },\n radius: {\n '': '0',\n '[data-axis=\"se\"]': '0 0 4px 0',\n '[data-axis=\"sw\"]': '0 0 0 4px',\n '[data-axis=\"ne\"]': '0 4px 0 0',\n '[data-axis=\"nw\"]': '4px 0 0 0',\n },\n top: {\n '': 'auto',\n '[data-axis=\"ne\"] | [data-axis=\"nw\"]': '4px',\n },\n bottom: {\n '': 'auto',\n '[data-axis=\"se\"] | [data-axis=\"sw\"]': '4px',\n },\n left: {\n '': 'auto',\n '[data-axis=\"nw\"] | [data-axis=\"sw\"]': '4px',\n },\n right: {\n '': 'auto',\n '[data-axis=\"ne\"] | [data-axis=\"se\"]': '4px',\n },\n },\n});\n\n/** Corner axes get a visible grip affordance on hover/focus/resize. */\nfunction isCornerAxis(axis: ResizeHandleAxis): boolean {\n return axis.length === 2;\n}\n\ninterface ResizeHandleProps {\n axis: ResizeHandleAxis;\n onResize: (\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => void;\n}\n\nfunction ResizeHandle({ axis, onResize }: ResizeHandleProps) {\n const { moveProps } = useMove({\n onMoveStart() {\n onResize(axis, 'start', 0, 0);\n },\n onMove(e) {\n onResize(axis, 'move', e.deltaX, e.deltaY);\n },\n onMoveEnd() {\n onResize(axis, 'end', 0, 0);\n },\n });\n\n const stopProps = {\n onPointerDown: (e: React.PointerEvent) => e.stopPropagation(),\n onMouseDown: (e: React.MouseEvent) => e.stopPropagation(),\n onTouchStart: (e: React.TouchEvent) => e.stopPropagation(),\n };\n\n return (\n <HandleElement\n data-axis={axis}\n {...mergeProps(stopProps, moveProps)}\n aria-hidden=\"true\"\n />\n );\n}\n\nexport interface WidgetHostProps {\n boardId: string;\n item: LayoutItem;\n positionParams: PositionParams;\n registration: WidgetRegistration | undefined;\n isDraggable: boolean;\n isResizable: boolean;\n resizeHandles: ResizeHandleAxis[];\n registry: BoardRegistryContextValue;\n dragState: BoardDragState | null;\n onResize: (\n id: string,\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => void;\n}\n\n/**\n * The positioned, interactive wrapper a board renders for each layout item it\n * owns. Content is pulled from the shared store (by id), so any board can host\n * any widget. Dragging uses React Aria `useMove`; during a drag the widget\n * renders into the shared overlay portal so it can float outside its board.\n */\nexport function WidgetHost(props: WidgetHostProps) {\n const {\n boardId,\n item,\n positionParams,\n registration,\n isDraggable,\n isResizable,\n resizeHandles,\n registry,\n dragState,\n onResize,\n } = props;\n\n const hostRef = useRef<HTMLDivElement | null>(null);\n const isActiveDrag = dragState?.itemId === item.i;\n // Keyboard drags stay in place: moving the focused element into the overlay\n // portal would unmount it and stop arrow-key move events.\n const useOverlay = isActiveDrag && dragState?.pointerType !== 'keyboard';\n\n const [isResizing, setIsResizing] = useState(false);\n const [isFocusWithin, setIsFocusWithin] = useState(false);\n const { hoverProps, isHovered } = useHover({ isDisabled: isActiveDrag });\n const { focusWithinProps } = useFocusWithin({\n onFocusWithinChange: setIsFocusWithin,\n });\n\n // Reveal the resize grips when the widget is interacted with (but not while it\n // is being dragged, where the widget floats in the overlay).\n const gripsRevealed =\n isResizable &&\n !item.static &&\n !isActiveDrag &&\n (isHovered || isFocusWithin || isResizing);\n\n const { moveProps } = useMove({\n onMoveStart(e) {\n if (!isDraggable) return;\n const rect = hostRef.current?.getBoundingClientRect();\n const pos = calcGridItemPosition(\n positionParams,\n item.x,\n item.y,\n item.w,\n item.h,\n );\n const vr: ViewportRect = rect\n ? {\n left: rect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n }\n : {\n left: pos.left,\n top: pos.top,\n width: pos.width,\n height: pos.height,\n };\n registry.onDragStart(boardId, item.i, vr, e.pointerType);\n },\n onMove(e) {\n if (!isDraggable) return;\n if (e.pointerType === 'keyboard') {\n // Amplify arrow-key steps to a full grid cell so items actually move.\n const colWidth = calcGridColWidth(positionParams);\n const stepX = colWidth + positionParams.margin[0];\n const stepY = positionParams.rowHeight + positionParams.margin[1];\n registry.onDragMove(\n Math.sign(e.deltaX) * stepX,\n Math.sign(e.deltaY) * stepY,\n e.pointerType,\n );\n return;\n }\n registry.onDragMove(e.deltaX, e.deltaY, e.pointerType);\n },\n onMoveEnd() {\n if (!isDraggable) return;\n registry.onDragEnd();\n },\n });\n\n const a11yProps = {\n tabIndex: isDraggable ? 0 : undefined,\n 'aria-roledescription': isDraggable ? 'Draggable widget' : undefined,\n 'aria-label': registration?.qa ?? item.i,\n };\n\n const handleResize = (\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => {\n if (phase === 'start') setIsResizing(true);\n else if (phase === 'end') setIsResizing(false);\n onResize(item.i, axis, phase, dx, dy);\n };\n\n const mods = {\n drag: isActiveDrag,\n draggable: isDraggable && !isActiveDrag,\n static: !!item.static,\n resizing: isResizing,\n };\n\n const content = (\n <>\n {registration?.content}\n {isResizable && !item.static ? (\n <>\n {resizeHandles.map((axis) => (\n <ResizeHandle key={axis} axis={axis} onResize={handleResize} />\n ))}\n {resizeHandles.filter(isCornerAxis).map((axis) => (\n <GripElement\n key={`grip-${axis}`}\n data-axis={axis}\n mods={{ revealed: gripsRevealed }}\n aria-hidden=\"true\"\n />\n ))}\n </>\n ) : null}\n </>\n );\n\n const pos = calcGridItemPosition(\n positionParams,\n item.x,\n item.y,\n item.w,\n item.h,\n );\n\n // While dragging with a pointer, the widget's visual floats in the shared\n // overlay so it is never clipped by an ancestor's `overflow: hidden`. The\n // gesture-owning element (the one carrying `moveProps`) must NOT be the node\n // that moves into the overlay: React Aria's `useMove` binds its pointer\n // move/end listeners relative to the node that received `onPointerDown`, and\n // relocating that node into the portal tears it down and mounts a fresh one\n // (inside a `pointerEvents: 'none'` layer), which can drop the in-flight\n // gesture. Instead we keep a stable, always-mounted in-grid host that owns the\n // gesture for its whole lifetime, and portal a separate, non-interactive\n // visual clone into the overlay.\n const overlayNode = registry.overlayRef.current;\n const floatInOverlay = useOverlay && !!overlayNode && !!dragState;\n\n const hostStyle: CSSProperties = {\n transform: `translate(${pos.left}px, ${pos.top}px)`,\n width: `${pos.width}px`,\n height: `${pos.height}px`,\n // Kept mounted but hidden while its clone floats, so the gesture stays live\n // on this node (the pointer listeners never get torn down).\n ...(floatInOverlay ? { opacity: 0, pointerEvents: 'none' } : null),\n };\n\n // The floating clone carries the \"drag\" affordance (raised shadow/z-index);\n // keep the hidden host flat. Keyboard drags (which never float) still\n // highlight the in-grid host, so only suppress `drag` when floating.\n const hostMods = { ...mods, drag: isActiveDrag && !floatInOverlay };\n\n // The host is always rendered first, with a stable element shape, so React\n // reuses the same DOM node across the drag transition (never remounts it).\n const host = (\n <WidgetElement\n ref={hostRef}\n {...mergeProps(moveProps, hoverProps, focusWithinProps, a11yProps, {\n style: hostStyle,\n })}\n qa={registration?.qa}\n mods={hostMods}\n styles={registration?.styles as Styles}\n >\n {floatInOverlay ? null : content}\n </WidgetElement>\n );\n\n const overlayClone = floatInOverlay\n ? createPortal(\n <WidgetElement\n style={{\n position: 'absolute',\n left: `${dragState!.rect.left}px`,\n top: `${dragState!.rect.top}px`,\n width: `${dragState!.rect.width}px`,\n height: `${dragState!.rect.height}px`,\n pointerEvents: 'none',\n }}\n mods={{ ...mods, drag: true }}\n styles={registration?.styles as Styles}\n aria-hidden=\"true\"\n >\n {content}\n </WidgetElement>,\n overlayNode!,\n )\n : null;\n\n return (\n <>\n {host}\n {overlayClone}\n </>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetHost.js","names":["mergeProps"],"sources":["../../../../src/components/layout/Board/WidgetHost.tsx"],"sourcesContent":["import { Styles, tasty } from '@tenphi/tasty';\nimport { CSSProperties, useMemo, useRef, useState } from 'react';\nimport { useFocusWithin, useHover, useMove } from 'react-aria';\nimport { createPortal } from 'react-dom';\n\nimport { useEvent } from '../../../_internal/hooks';\nimport { mergeProps } from '../../../utils/react';\n\nimport {\n BoardDragState,\n BoardHost,\n BoardHostContext,\n BoardRegistryContextValue,\n ViewportRect,\n} from './board-context';\nimport { WidgetRegistration } from './board-store';\nimport {\n calcGridColWidth,\n calcGridItemPosition,\n LayoutItem,\n PositionParams,\n ResizeHandleAxis,\n} from './grid-core';\n\nexport type ResizePhase = 'start' | 'move' | 'end';\n\n/**\n * Slack (px) absorbed when converting an auto-height widget's content height to\n * whole rows, so sub-pixel measurement/rounding noise never bumps an extra row.\n */\nconst AUTO_HEIGHT_TOLERANCE = 4;\n\nconst WidgetElement = tasty({\n qa: 'BoardWidget',\n styles: {\n position: 'absolute',\n top: 0,\n left: 0,\n fill: '#surface',\n radius: '1cr',\n border: true,\n shadow: {\n '': false,\n // `$dialog-shadow` uses Glaze `#shadow-lg`, which adapts to dark / high-contrast schemes.\n 'drag | resizing': '$dialog-shadow',\n },\n zIndex: {\n '': 1,\n 'drag | resizing': 10,\n },\n transition: 'theme, shadow',\n boxSizing: 'border-box',\n userSelect: {\n '': 'auto',\n 'drag | resizing': 'none',\n },\n cursor: {\n '': 'auto',\n draggable: 'grab',\n drag: 'grabbing',\n },\n touchAction: 'none',\n overflow: 'hidden',\n },\n});\n\nconst HandleElement = tasty({\n qa: 'BoardResizeHandle',\n styles: {\n position: 'absolute',\n zIndex: 20,\n fill: '#clear',\n // Overhang: how far the hit-zone extends beyond the widget edge.\n '--handle-size': '24px',\n '--handle-overhang': '-8px',\n '--handle-inset': '8px',\n width: {\n '': '$handle-size',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': 'auto',\n },\n height: {\n '': '$handle-size',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': 'auto',\n },\n top: {\n '': 'auto',\n '[data-axis=\"n\"] | [data-axis=\"ne\"] | [data-axis=\"nw\"]':\n '$handle-overhang',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': '$handle-inset',\n },\n bottom: {\n '': 'auto',\n '[data-axis=\"s\"] | [data-axis=\"se\"] | [data-axis=\"sw\"]':\n '$handle-overhang',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': '$handle-inset',\n },\n left: {\n '': 'auto',\n '[data-axis=\"w\"] | [data-axis=\"nw\"] | [data-axis=\"sw\"]':\n '$handle-overhang',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': '$handle-inset',\n },\n right: {\n '': 'auto',\n '[data-axis=\"e\"] | [data-axis=\"ne\"] | [data-axis=\"se\"]':\n '$handle-overhang',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': '$handle-inset',\n },\n cursor: {\n '': 'default',\n '[data-axis=\"n\"] | [data-axis=\"s\"]': 'ns-resize',\n '[data-axis=\"e\"] | [data-axis=\"w\"]': 'ew-resize',\n '[data-axis=\"ne\"] | [data-axis=\"sw\"]': 'nesw-resize',\n '[data-axis=\"nw\"] | [data-axis=\"se\"]': 'nwse-resize',\n },\n touchAction: 'none',\n },\n});\n\nconst GripElement = tasty({\n qa: 'BoardResizeGrip',\n styles: {\n position: 'absolute',\n width: '10px',\n height: '10px',\n boxSizing: 'border-box',\n pointerEvents: 'none',\n opacity: {\n '': 0,\n revealed: 1,\n },\n transition: 'opacity 120ms ease-in-out',\n borderTop: {\n '': '0',\n '[data-axis=\"ne\"] | [data-axis=\"nw\"]': '2px solid #dark.40',\n },\n borderBottom: {\n '': '0',\n '[data-axis=\"se\"] | [data-axis=\"sw\"]': '2px solid #dark.40',\n },\n borderLeft: {\n '': '0',\n '[data-axis=\"nw\"] | [data-axis=\"sw\"]': '2px solid #dark.40',\n },\n borderRight: {\n '': '0',\n '[data-axis=\"ne\"] | [data-axis=\"se\"]': '2px solid #dark.40',\n },\n radius: {\n '': '0',\n '[data-axis=\"se\"]': '0 0 4px 0',\n '[data-axis=\"sw\"]': '0 0 0 4px',\n '[data-axis=\"ne\"]': '0 4px 0 0',\n '[data-axis=\"nw\"]': '4px 0 0 0',\n },\n top: {\n '': 'auto',\n '[data-axis=\"ne\"] | [data-axis=\"nw\"]': '4px',\n },\n bottom: {\n '': 'auto',\n '[data-axis=\"se\"] | [data-axis=\"sw\"]': '4px',\n },\n left: {\n '': 'auto',\n '[data-axis=\"nw\"] | [data-axis=\"sw\"]': '4px',\n },\n right: {\n '': 'auto',\n '[data-axis=\"ne\"] | [data-axis=\"se\"]': '4px',\n },\n },\n});\n\n/** Corner axes get a visible grip affordance on hover/focus/resize. */\nfunction isCornerAxis(axis: ResizeHandleAxis): boolean {\n return axis.length === 2;\n}\n\ninterface ResizeHandleProps {\n axis: ResizeHandleAxis;\n onResize: (\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => void;\n}\n\nfunction ResizeHandle({ axis, onResize }: ResizeHandleProps) {\n const { moveProps } = useMove({\n onMoveStart() {\n onResize(axis, 'start', 0, 0);\n },\n onMove(e) {\n onResize(axis, 'move', e.deltaX, e.deltaY);\n },\n onMoveEnd() {\n onResize(axis, 'end', 0, 0);\n },\n });\n\n const stopProps = {\n onPointerDown: (e: React.PointerEvent) => e.stopPropagation(),\n onMouseDown: (e: React.MouseEvent) => e.stopPropagation(),\n onTouchStart: (e: React.TouchEvent) => e.stopPropagation(),\n };\n\n return (\n <HandleElement\n data-axis={axis}\n {...mergeProps(stopProps, moveProps)}\n aria-hidden=\"true\"\n />\n );\n}\n\nexport interface WidgetHostProps {\n boardId: string;\n item: LayoutItem;\n positionParams: PositionParams;\n registration: WidgetRegistration | undefined;\n isDraggable: boolean;\n isResizable: boolean;\n resizeHandles: ResizeHandleAxis[];\n registry: BoardRegistryContextValue;\n dragState: BoardDragState | null;\n onResize: (\n id: string,\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => void;\n /**\n * Report the minimum number of rows this widget needs to fit its content\n * (typically a nested board). The owning board grows the item to this height\n * when it is taller than the current one, and treats it as the resize floor\n * so the widget cannot be dragged shorter than its content requires.\n */\n onAutoHeight: (id: string, neededRows: number) => void;\n}\n\n/**\n * The positioned, interactive wrapper a board renders for each layout item it\n * owns. Content is pulled from the shared store (by id), so any board can host\n * any widget. Dragging uses React Aria `useMove`; during a drag the widget\n * renders into the shared overlay portal so it can float outside its board.\n */\nexport function WidgetHost(props: WidgetHostProps) {\n const {\n boardId,\n item,\n positionParams,\n registration,\n isDraggable,\n isResizable,\n resizeHandles,\n registry,\n dragState,\n onResize,\n onAutoHeight,\n } = props;\n\n const hostRef = useRef<HTMLDivElement | null>(null);\n const isActiveDrag = dragState?.itemId === item.i;\n const isAutoHeight = registration?.isAutoHeight === true;\n\n // Translate a nested board's reported height deficit (signed px: positive when\n // it is squeezed, negative when it has slack) into the absolute number of rows\n // this widget needs, and report it to the owning board. The widget's chrome\n // cancels out: the needed pixel height is the widget's current pixel height\n // plus the deficit. A small tolerance keeps sub-pixel rounding from bumping an\n // extra row. Skipped during a drag (the widget is floating in the overlay).\n const requestHeightDeficit = useEvent((deficitPx: number) => {\n if (!isAutoHeight || isActiveDrag) return;\n const step = positionParams.rowHeight + positionParams.margin[1];\n if (step <= 0) return;\n const current = calcGridItemPosition(\n positionParams,\n item.x,\n item.y,\n item.w,\n item.h,\n );\n const neededPx = current.height + deficitPx;\n const neededRows = Math.max(\n 1,\n Math.ceil(\n (neededPx + positionParams.margin[1] - AUTO_HEIGHT_TOLERANCE) / step,\n ),\n );\n onAutoHeight(item.i, neededRows);\n });\n\n const hostValue = useMemo<BoardHost>(\n () => ({ isAutoHeight, requestHeightDeficit }),\n [isAutoHeight, requestHeightDeficit],\n );\n // Keyboard drags stay in place: moving the focused element into the overlay\n // portal would unmount it and stop arrow-key move events.\n const useOverlay = isActiveDrag && dragState?.pointerType !== 'keyboard';\n\n const [isResizing, setIsResizing] = useState(false);\n const [isFocusWithin, setIsFocusWithin] = useState(false);\n const { hoverProps, isHovered } = useHover({ isDisabled: isActiveDrag });\n const { focusWithinProps } = useFocusWithin({\n onFocusWithinChange: setIsFocusWithin,\n });\n\n // Reveal the resize grips when the widget is interacted with (but not while it\n // is being dragged, where the widget floats in the overlay).\n const gripsRevealed =\n isResizable &&\n !item.static &&\n !isActiveDrag &&\n (isHovered || isFocusWithin || isResizing);\n\n const { moveProps } = useMove({\n onMoveStart(e) {\n if (!isDraggable) return;\n const rect = hostRef.current?.getBoundingClientRect();\n const pos = calcGridItemPosition(\n positionParams,\n item.x,\n item.y,\n item.w,\n item.h,\n );\n const vr: ViewportRect = rect\n ? {\n left: rect.left,\n top: rect.top,\n width: rect.width,\n height: rect.height,\n }\n : {\n left: pos.left,\n top: pos.top,\n width: pos.width,\n height: pos.height,\n };\n registry.onDragStart(boardId, item.i, vr, e.pointerType, hostRef.current);\n },\n onMove(e) {\n if (!isDraggable) return;\n if (e.pointerType === 'keyboard') {\n // Amplify arrow-key steps to a full grid cell so items actually move.\n const colWidth = calcGridColWidth(positionParams);\n const stepX = colWidth + positionParams.margin[0];\n const stepY = positionParams.rowHeight + positionParams.margin[1];\n registry.onDragMove(\n Math.sign(e.deltaX) * stepX,\n Math.sign(e.deltaY) * stepY,\n e.pointerType,\n );\n return;\n }\n registry.onDragMove(e.deltaX, e.deltaY, e.pointerType);\n },\n onMoveEnd() {\n if (!isDraggable) return;\n registry.onDragEnd();\n },\n });\n\n const a11yProps = {\n tabIndex: isDraggable ? 0 : undefined,\n 'aria-roledescription': isDraggable ? 'Draggable widget' : undefined,\n 'aria-label': registration?.qa ?? item.i,\n };\n\n const handleResize = (\n axis: ResizeHandleAxis,\n phase: ResizePhase,\n dx: number,\n dy: number,\n ) => {\n if (phase === 'start') setIsResizing(true);\n else if (phase === 'end') setIsResizing(false);\n onResize(item.i, axis, phase, dx, dy);\n };\n\n const mods = {\n drag: isActiveDrag,\n draggable: isDraggable && !isActiveDrag,\n static: !!item.static,\n resizing: isResizing,\n };\n\n const content = (\n <BoardHostContext.Provider value={hostValue}>\n {registration?.content}\n {isResizable && !item.static ? (\n <>\n {resizeHandles.map((axis) => (\n <ResizeHandle key={axis} axis={axis} onResize={handleResize} />\n ))}\n {resizeHandles.filter(isCornerAxis).map((axis) => (\n <GripElement\n key={`grip-${axis}`}\n data-axis={axis}\n mods={{ revealed: gripsRevealed }}\n aria-hidden=\"true\"\n />\n ))}\n </>\n ) : null}\n </BoardHostContext.Provider>\n );\n\n const pos = calcGridItemPosition(\n positionParams,\n item.x,\n item.y,\n item.w,\n item.h,\n );\n\n // While dragging with a pointer, the widget's visual floats in the shared\n // overlay so it is never clipped by an ancestor's `overflow: hidden`. The\n // gesture-owning element (the one carrying `moveProps`) must NOT be the node\n // that moves into the overlay: React Aria's `useMove` binds its pointer\n // move/end listeners relative to the node that received `onPointerDown`, and\n // relocating that node into the portal tears it down and mounts a fresh one\n // (inside a `pointerEvents: 'none'` layer), which can drop the in-flight\n // gesture. Instead we keep a stable, always-mounted in-grid host that owns the\n // gesture for its whole lifetime, and portal a separate, non-interactive\n // visual clone into the overlay.\n const overlayNode = registry.overlayRef.current;\n const floatInOverlay = useOverlay && !!overlayNode && !!dragState;\n\n const hostStyle: CSSProperties = {\n transform: `translate(${pos.left}px, ${pos.top}px)`,\n width: `${pos.width}px`,\n height: `${pos.height}px`,\n // Kept mounted but hidden while its clone floats, so the gesture stays live\n // on this node (the pointer listeners never get torn down).\n ...(floatInOverlay ? { opacity: 0, pointerEvents: 'none' } : null),\n };\n\n // The floating clone carries the \"drag\" affordance (raised shadow/z-index);\n // keep the hidden host flat. Keyboard drags (which never float) still\n // highlight the in-grid host, so only suppress `drag` when floating.\n const hostMods = { ...mods, drag: isActiveDrag && !floatInOverlay };\n\n // The host is always rendered first, with a stable element shape, so React\n // reuses the same DOM node across the drag transition (never remounts it).\n const host = (\n <WidgetElement\n ref={hostRef}\n {...mergeProps(moveProps, hoverProps, focusWithinProps, a11yProps, {\n style: hostStyle,\n })}\n qa={registration?.qa}\n mods={hostMods}\n styles={registration?.styles as Styles}\n >\n {floatInOverlay ? null : content}\n </WidgetElement>\n );\n\n const overlayClone = floatInOverlay\n ? createPortal(\n <WidgetElement\n style={{\n position: 'absolute',\n left: `${dragState!.rect.left}px`,\n top: `${dragState!.rect.top}px`,\n width: `${dragState!.rect.width}px`,\n height: `${dragState!.rect.height}px`,\n pointerEvents: 'none',\n }}\n mods={{ ...mods, drag: true }}\n styles={registration?.styles as Styles}\n aria-hidden=\"true\"\n >\n {content}\n </WidgetElement>,\n overlayNode!,\n )\n : null;\n\n return (\n <>\n {host}\n {overlayClone}\n </>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/components/layout/Board/board-context.tsx
|
|
@@ -6,7 +6,15 @@ const BoardRegistryContext = createContext(null);
|
|
|
6
6
|
function useBoardRegistry() {
|
|
7
7
|
return useContext(BoardRegistryContext);
|
|
8
8
|
}
|
|
9
|
+
const BoardMetricsContext = createContext(null);
|
|
10
|
+
function useBoardMetrics() {
|
|
11
|
+
return useContext(BoardMetricsContext);
|
|
12
|
+
}
|
|
13
|
+
const BoardHostContext = createContext(null);
|
|
14
|
+
function useBoardHost() {
|
|
15
|
+
return useContext(BoardHostContext);
|
|
16
|
+
}
|
|
9
17
|
|
|
10
18
|
//#endregion
|
|
11
|
-
export { BoardRegistryContext, useBoardRegistry };
|
|
19
|
+
export { BoardHostContext, BoardMetricsContext, BoardRegistryContext, useBoardHost, useBoardMetrics, useBoardRegistry };
|
|
12
20
|
//# sourceMappingURL=board-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board-context.js","names":[],"sources":["../../../../src/components/layout/Board/board-context.tsx"],"sourcesContent":["import { createContext, MutableRefObject, useContext } from 'react';\n\nimport type { BoardWidgetStore } from './board-store';\nimport type {\n Compactor,\n LayoutConstraint,\n LayoutItem,\n PositionParams,\n} from './grid-core';\n\n/** A rectangle in viewport (client) coordinates. */\nexport interface ViewportRect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/**\n * Everything the cross-board registry needs to read from / write to a single\n * board. Methods read live refs so a single stable entry can be registered once\n * per board and stay current across renders.\n */\nexport interface BoardEntry {\n id: string;\n /** Viewport rect of the content area where widgets are positioned. */\n getContentRect: () => DOMRect | null;\n /** The DOM node of the content area (used to detect nested-in-drag boards). */\n getContentNode: () => HTMLElement | null;\n getPositionParams: () => PositionParams;\n getConstraints: () => LayoutConstraint[];\n getCompactor: () => Compactor;\n getMaxRows: () => number;\n getContainerHeight: () => number;\n getLayout: () => LayoutItem[];\n /** Update the board layout. `commit` fires `onLayoutChange`. */\n applyLayout: (layout: LayoutItem[], commit: boolean) => void;\n setPlaceholder: (item: LayoutItem | null) => void;\n isDroppable: () => boolean;\n}\n\n/** Emitted when a widget is dropped from one board into another. */\nexport interface WidgetTransferInfo {\n widgetId: string;\n fromBoardId: string;\n toBoardId: string;\n item: LayoutItem;\n}\n\n/** Live drag state, shared across boards for overlay + placeholders. */\nexport interface BoardDragState {\n sourceBoardId: string;\n /** Board currently owning the dragged item (changes as it crosses boards). */\n currentBoardId: string;\n itemId: string;\n /** Snapshot of the dragged item (grid units; w/h preserved across boards). */\n item: LayoutItem;\n /** Dragged widget rect in viewport coordinates (follows the pointer). */\n rect: ViewportRect;\n pointerType: string;\n}\n\nexport interface BoardRegistryContextValue {\n store: BoardWidgetStore;\n overlayRef: MutableRefObject<HTMLDivElement | null>;\n registerBoard: (entry: BoardEntry) => () => void;\n onDragStart: (\n boardId: string,\n itemId: string,\n rect: ViewportRect,\n pointerType: string,\n ) => void;\n onDragMove: (deltaX: number, deltaY: number, pointerType: string) => void;\n onDragEnd: () => void;\n dragState: BoardDragState | null;\n}\n\nexport const BoardRegistryContext =\n createContext<BoardRegistryContextValue | null>(null);\n\nexport function useBoardRegistry(): BoardRegistryContextValue | null {\n return useContext(BoardRegistryContext);\n}\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"board-context.js","names":[],"sources":["../../../../src/components/layout/Board/board-context.tsx"],"sourcesContent":["import { createContext, MutableRefObject, useContext } from 'react';\n\nimport type { BoardWidgetStore } from './board-store';\nimport type {\n Compactor,\n LayoutConstraint,\n LayoutItem,\n PositionParams,\n} from './grid-core';\n\n/** A rectangle in viewport (client) coordinates. */\nexport interface ViewportRect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/**\n * Everything the cross-board registry needs to read from / write to a single\n * board. Methods read live refs so a single stable entry can be registered once\n * per board and stay current across renders.\n */\nexport interface BoardEntry {\n id: string;\n /** Viewport rect of the content area where widgets are positioned. */\n getContentRect: () => DOMRect | null;\n /** The DOM node of the content area (used to detect nested-in-drag boards). */\n getContentNode: () => HTMLElement | null;\n getPositionParams: () => PositionParams;\n getConstraints: () => LayoutConstraint[];\n getCompactor: () => Compactor;\n getMaxRows: () => number;\n getContainerHeight: () => number;\n getLayout: () => LayoutItem[];\n /** Update the board layout. `commit` fires `onLayoutChange`. */\n applyLayout: (layout: LayoutItem[], commit: boolean) => void;\n setPlaceholder: (item: LayoutItem | null) => void;\n isDroppable: () => boolean;\n}\n\n/** Emitted when a widget is dropped from one board into another. */\nexport interface WidgetTransferInfo {\n widgetId: string;\n fromBoardId: string;\n toBoardId: string;\n item: LayoutItem;\n}\n\n/** Live drag state, shared across boards for overlay + placeholders. */\nexport interface BoardDragState {\n sourceBoardId: string;\n /** Board currently owning the dragged item (changes as it crosses boards). */\n currentBoardId: string;\n itemId: string;\n /** Snapshot of the dragged item (grid units; w/h preserved across boards). */\n item: LayoutItem;\n /** Dragged widget rect in viewport coordinates (follows the pointer). */\n rect: ViewportRect;\n pointerType: string;\n}\n\nexport interface BoardRegistryContextValue {\n store: BoardWidgetStore;\n overlayRef: MutableRefObject<HTMLDivElement | null>;\n registerBoard: (entry: BoardEntry) => () => void;\n onDragStart: (\n boardId: string,\n itemId: string,\n rect: ViewportRect,\n pointerType: string,\n /** The dragged widget's host node, used to exclude boards nested inside it. */\n widgetNode: HTMLElement | null,\n ) => void;\n onDragMove: (deltaX: number, deltaY: number, pointerType: string) => void;\n onDragEnd: () => void;\n dragState: BoardDragState | null;\n}\n\nexport const BoardRegistryContext =\n createContext<BoardRegistryContextValue | null>(null);\n\nexport function useBoardRegistry(): BoardRegistryContextValue | null {\n return useContext(BoardRegistryContext);\n}\n\n/**\n * The resolved grid metrics a `Board` exposes to any boards nested inside its\n * widgets. A nested board with `isAligned` reads these to inherit the parent's\n * column pitch (column width + horizontal margin) and target row height, so its\n * cells line up with the surrounding layout instead of stretching.\n */\nexport interface BoardMetrics {\n /** Resolved pixel width of one parent column. */\n colWidth: number;\n /** Resolved parent row height in pixels (the alignment target). */\n rowHeight: number;\n /** Parent [horizontal, vertical] margin between widgets in pixels. */\n margin: readonly [number, number];\n /** Parent [horizontal, vertical] container padding in pixels. */\n containerPadding: readonly [number, number];\n}\n\nexport const BoardMetricsContext = createContext<BoardMetrics | null>(null);\n\nexport function useBoardMetrics(): BoardMetrics | null {\n return useContext(BoardMetricsContext);\n}\n\n/**\n * Information a `WidgetHost` exposes to the content it renders (including a\n * nested `Board`). Lets a nested board know whether its host widget auto-sizes\n * its height and, if so, ask the host to grow to fit the board's natural size.\n */\nexport interface BoardHost {\n /** Whether the host widget grows its height to fit its content. */\n isAutoHeight: boolean;\n /**\n * Ask the host widget to grow so it provides `px` more content height. Only\n * ever increases the host's height. No-op when the host does not auto-size.\n */\n requestHeightDeficit: (px: number) => void;\n}\n\nexport const BoardHostContext = createContext<BoardHost | null>(null);\n\nexport function useBoardHost(): BoardHost | null {\n return useContext(BoardHostContext);\n}\n"],"mappings":";;;;AA+EA,MAAa,uBACX,cAAgD,KAAK;AAEvD,SAAgB,mBAAqD;AACnE,QAAO,WAAW,qBAAqB;;AAoBzC,MAAa,sBAAsB,cAAmC,KAAK;AAE3E,SAAgB,kBAAuC;AACrD,QAAO,WAAW,oBAAoB;;AAkBxC,MAAa,mBAAmB,cAAgC,KAAK;AAErE,SAAgB,eAAiC;AAC/C,QAAO,WAAW,iBAAiB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
//#region src/components/layout/Board/board-store.ts
|
|
3
3
|
/**
|
|
4
4
|
* A tiny external store mapping widget id -> registration.
|
|
@@ -16,7 +16,7 @@ var BoardWidgetStore = class {
|
|
|
16
16
|
const prev = this.map.get(reg.id);
|
|
17
17
|
this.map.set(reg.id, reg);
|
|
18
18
|
this.owners.set(reg.id, owner);
|
|
19
|
-
if (!prev || prev.content !== reg.content || prev.isDraggable !== reg.isDraggable || prev.isResizable !== reg.isResizable || prev.resizeHandles !== reg.resizeHandles || prev.constraints !== reg.constraints || prev.qa !== reg.qa || prev.styles !== reg.styles) {
|
|
19
|
+
if (!prev || prev.content !== reg.content || prev.isDraggable !== reg.isDraggable || prev.isResizable !== reg.isResizable || prev.resizeHandles !== reg.resizeHandles || prev.constraints !== reg.constraints || prev.qa !== reg.qa || prev.styles !== reg.styles || prev.isAutoHeight !== reg.isAutoHeight) {
|
|
20
20
|
this.version++;
|
|
21
21
|
this.emit();
|
|
22
22
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board-store.js","names":[],"sources":["../../../../src/components/layout/Board/board-store.ts"],"sourcesContent":["import type { Styles } from '@tenphi/tasty';\nimport type { ReactNode } from 'react';\nimport type { LayoutConstraint, ResizeHandleAxis } from './grid-core';\n\n/**\n * Declarative registration for a single widget.\n *\n * Widget *content* is decoupled from widget *position*: content is registered\n * here by `Board.Widget` keyed by id, while positioning/ownership lives in a\n * board's layout state. This decoupling is what allows a widget to be hosted\n * (and transferred) between different boards under the same `BoardProvider`.\n */\nexport interface WidgetRegistration {\n id: string;\n content: ReactNode;\n isDraggable?: boolean;\n isResizable?: boolean;\n resizeHandles?: ResizeHandleAxis[];\n constraints?: LayoutConstraint[];\n qa?: string;\n styles?: Styles;\n}\n\n/**\n * A tiny external store mapping widget id -> registration.\n *\n * Boards read from it via `useSyncExternalStore`, so a change to any widget's\n * content or config re-renders the hosting board without prop drilling through\n * the (possibly cross-board) tree.\n */\nexport class BoardWidgetStore {\n private map = new Map<string, WidgetRegistration>();\n // Tracks which mounted `Board.Widget` instance currently owns each id. This\n // guards against a stale unregister from an unmounting instance clobbering a\n // freshly-mounted instance's registration - which happens when a widget's\n // subtree is relocated (e.g. dragging a container widget that hosts a nested\n // board moves it into the overlay portal, remounting the inner widgets).\n private owners = new Map<string, object>();\n private listeners = new Set<() => void>();\n private version = 0;\n\n register(reg: WidgetRegistration, owner: object): void {\n const prev = this.map.get(reg.id);\n this.map.set(reg.id, reg);\n this.owners.set(reg.id, owner);\n\n // Notify on any reference change. The hosting board reads registrations\n // during render, but `Board.Widget` registers in a layout effect (after\n // commit), so a content/config change lands one commit late and would never\n // be shown without an emit. Reference comparison is loop-safe: a board's own\n // re-render reuses the same `children` element references from its\n // (un-rerendered) parent, so `content` only differs on a genuine parent\n // update -> we emit once and then settle.\n const changed =\n !prev ||\n prev.content !== reg.content ||\n prev.isDraggable !== reg.isDraggable ||\n prev.isResizable !== reg.isResizable ||\n prev.resizeHandles !== reg.resizeHandles ||\n prev.constraints !== reg.constraints ||\n prev.qa !== reg.qa ||\n prev.styles !== reg.styles;\n\n if (changed) {\n this.version++;\n this.emit();\n }\n }\n\n unregister(id: string, owner: object): void {\n // Ignore unregister calls from an instance that no longer owns the id (a\n // newer instance has already taken over).\n if (this.owners.get(id) !== owner) return;\n\n this.owners.delete(id);\n if (this.map.delete(id)) {\n this.version++;\n this.emit();\n }\n }\n\n get(id: string): WidgetRegistration | undefined {\n return this.map.get(id);\n }\n\n getVersion = (): number => this.version;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n private emit(): void {\n this.listeners.forEach((listener) => listener());\n }\n}\n"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"board-store.js","names":[],"sources":["../../../../src/components/layout/Board/board-store.ts"],"sourcesContent":["import type { Styles } from '@tenphi/tasty';\nimport type { ReactNode } from 'react';\nimport type { LayoutConstraint, ResizeHandleAxis } from './grid-core';\n\n/**\n * Declarative registration for a single widget.\n *\n * Widget *content* is decoupled from widget *position*: content is registered\n * here by `Board.Widget` keyed by id, while positioning/ownership lives in a\n * board's layout state. This decoupling is what allows a widget to be hosted\n * (and transferred) between different boards under the same `BoardProvider`.\n */\nexport interface WidgetRegistration {\n id: string;\n content: ReactNode;\n isDraggable?: boolean;\n isResizable?: boolean;\n resizeHandles?: ResizeHandleAxis[];\n constraints?: LayoutConstraint[];\n qa?: string;\n styles?: Styles;\n /** Grow this widget's height to fit its content (only ever increases). */\n isAutoHeight?: boolean;\n}\n\n/**\n * A tiny external store mapping widget id -> registration.\n *\n * Boards read from it via `useSyncExternalStore`, so a change to any widget's\n * content or config re-renders the hosting board without prop drilling through\n * the (possibly cross-board) tree.\n */\nexport class BoardWidgetStore {\n private map = new Map<string, WidgetRegistration>();\n // Tracks which mounted `Board.Widget` instance currently owns each id. This\n // guards against a stale unregister from an unmounting instance clobbering a\n // freshly-mounted instance's registration - which happens when a widget's\n // subtree is relocated (e.g. dragging a container widget that hosts a nested\n // board moves it into the overlay portal, remounting the inner widgets).\n private owners = new Map<string, object>();\n private listeners = new Set<() => void>();\n private version = 0;\n\n register(reg: WidgetRegistration, owner: object): void {\n const prev = this.map.get(reg.id);\n this.map.set(reg.id, reg);\n this.owners.set(reg.id, owner);\n\n // Notify on any reference change. The hosting board reads registrations\n // during render, but `Board.Widget` registers in a layout effect (after\n // commit), so a content/config change lands one commit late and would never\n // be shown without an emit. Reference comparison is loop-safe: a board's own\n // re-render reuses the same `children` element references from its\n // (un-rerendered) parent, so `content` only differs on a genuine parent\n // update -> we emit once and then settle.\n const changed =\n !prev ||\n prev.content !== reg.content ||\n prev.isDraggable !== reg.isDraggable ||\n prev.isResizable !== reg.isResizable ||\n prev.resizeHandles !== reg.resizeHandles ||\n prev.constraints !== reg.constraints ||\n prev.qa !== reg.qa ||\n prev.styles !== reg.styles ||\n prev.isAutoHeight !== reg.isAutoHeight;\n\n if (changed) {\n this.version++;\n this.emit();\n }\n }\n\n unregister(id: string, owner: object): void {\n // Ignore unregister calls from an instance that no longer owns the id (a\n // newer instance has already taken over).\n if (this.owners.get(id) !== owner) return;\n\n this.owners.delete(id);\n if (this.map.delete(id)) {\n this.version++;\n this.emit();\n }\n }\n\n get(id: string): WidgetRegistration | undefined {\n return this.map.get(id);\n }\n\n getVersion = (): number => this.version;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n private emit(): void {\n this.listeners.forEach((listener) => listener());\n }\n}\n"],"mappings":";;;;;;;;;AAgCA,IAAa,mBAAb,MAA8B;CAC5B,AAAQ,sBAAM,IAAI,KAAiC;CAMnD,AAAQ,yBAAS,IAAI,KAAqB;CAC1C,AAAQ,4BAAY,IAAI,KAAiB;CACzC,AAAQ,UAAU;CAElB,SAAS,KAAyB,OAAqB;EACrD,MAAM,OAAO,KAAK,IAAI,IAAI,IAAI,GAAG;AACjC,OAAK,IAAI,IAAI,IAAI,IAAI,IAAI;AACzB,OAAK,OAAO,IAAI,IAAI,IAAI,MAAM;AAoB9B,MAVE,CAAC,QACD,KAAK,YAAY,IAAI,WACrB,KAAK,gBAAgB,IAAI,eACzB,KAAK,gBAAgB,IAAI,eACzB,KAAK,kBAAkB,IAAI,iBAC3B,KAAK,gBAAgB,IAAI,eACzB,KAAK,OAAO,IAAI,MAChB,KAAK,WAAW,IAAI,UACpB,KAAK,iBAAiB,IAAI,cAEf;AACX,QAAK;AACL,QAAK,MAAM;;;CAIf,WAAW,IAAY,OAAqB;AAG1C,MAAI,KAAK,OAAO,IAAI,GAAG,KAAK,MAAO;AAEnC,OAAK,OAAO,OAAO,GAAG;AACtB,MAAI,KAAK,IAAI,OAAO,GAAG,EAAE;AACvB,QAAK;AACL,QAAK,MAAM;;;CAIf,IAAI,IAA4C;AAC9C,SAAO,KAAK,IAAI,IAAI,GAAG;;CAGzB,mBAA2B,KAAK;CAEhC,aAAa,aAAuC;AAClD,OAAK,UAAU,IAAI,SAAS;AAC5B,eAAa;AACX,QAAK,UAAU,OAAO,SAAS;;;CAInC,AAAQ,OAAa;AACnB,OAAK,UAAU,SAAS,aAAa,UAAU,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
//#region src/components/layout/Board/grid-core/calculate.ts
|
|
3
3
|
/** Calculate the width of a single grid column in pixels. */
|
|
4
4
|
function calcGridColWidth(positionParams) {
|
|
@@ -86,5 +86,5 @@ function clamp(num, lowerBound, upperBound) {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
//#endregion
|
|
89
|
-
export { calcGridColWidth, calcGridItemPosition, calcWH, calcXYRaw };
|
|
89
|
+
export { calcGridColWidth, calcGridItemPosition, calcWH, calcXYRaw, clamp };
|
|
90
90
|
//# sourceMappingURL=calculate.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
//#region src/components/layout/Board/grid-core/collision.ts
|
|
3
3
|
/**
|
|
4
4
|
* Check if two layout items collide (overlap).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { collides, getFirstCollision } from "./collision.js";
|
|
3
3
|
import { sortLayoutItemsByColRow, sortLayoutItemsByRowCol } from "./sort.js";
|
|
4
4
|
import { bottom, cloneLayout, cloneLayoutItem, getStatics } from "./layout.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
//#region src/components/layout/Board/grid-core/constraints.ts
|
|
3
3
|
function clamp(value, min, max) {
|
|
4
4
|
return Math.max(min, Math.min(max, value));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { getAllCollisions, getFirstCollision } from "./collision.js";
|
|
3
3
|
import { sortLayoutItems } from "./sort.js";
|
|
4
4
|
|
|
@@ -79,6 +79,27 @@ function modifyLayout(layout, layoutItem) {
|
|
|
79
79
|
return newLayout;
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
|
+
* Ensure all layout items fit within the grid bounds.
|
|
83
|
+
*
|
|
84
|
+
* **IMPORTANT**: mutates the layout items in place for performance. Clone the
|
|
85
|
+
* layout first (e.g. with `cloneLayout()`) if you need immutability.
|
|
86
|
+
*/
|
|
87
|
+
function correctBounds(layout, bounds) {
|
|
88
|
+
const collidesWith = getStatics(layout);
|
|
89
|
+
for (let i = 0; i < layout.length; i++) {
|
|
90
|
+
const l = layout[i];
|
|
91
|
+
if (l === void 0) continue;
|
|
92
|
+
if (l.x + l.w > bounds.cols) l.x = bounds.cols - l.w;
|
|
93
|
+
if (l.x < 0) {
|
|
94
|
+
l.x = 0;
|
|
95
|
+
l.w = bounds.cols;
|
|
96
|
+
}
|
|
97
|
+
if (!l.static) collidesWith.push(l);
|
|
98
|
+
else while (getFirstCollision(collidesWith, l)) l.y++;
|
|
99
|
+
}
|
|
100
|
+
return layout;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
82
103
|
* Move a layout element to a new position.
|
|
83
104
|
*
|
|
84
105
|
* Handles collision detection and cascading movements. Does not compact the
|
|
@@ -151,5 +172,5 @@ function moveElementAwayFromCollision(layout, collidesWith, itemToMove, isUserAc
|
|
|
151
172
|
}
|
|
152
173
|
|
|
153
174
|
//#endregion
|
|
154
|
-
export { bottom, cloneLayout, cloneLayoutItem, getLayoutItem, getStatics, modifyLayout, moveElement };
|
|
175
|
+
export { bottom, cloneLayout, cloneLayoutItem, correctBounds, getLayoutItem, getStatics, modifyLayout, moveElement };
|
|
155
176
|
//# sourceMappingURL=layout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","names":[],"sources":["../../../../../src/components/layout/Board/grid-core/layout.ts"],"sourcesContent":["/**\n * Core layout manipulation utilities.\n *\n * Vendored from react-grid-layout v2 (`src/core/layout.ts`).\n * See ./NOTICE.md for attribution and license.\n *\n * These functions create, modify, and query grid layouts. Most functions treat\n * layouts as immutable and return new arrays/objects, but a few mutate items in\n * place for performance (documented per function).\n */\n\nimport { getAllCollisions, getFirstCollision } from './collision';\nimport { sortLayoutItems } from './sort';\n\nimport type { CompactType, Layout, LayoutItem, Mutable } from './types';\n\n// ============================================================================\n// Layout Queries\n// ============================================================================\n\n/**\n * Get the bottom-most Y coordinate of the layout (max of y + h).\n */\nexport function bottom(layout: Layout): number {\n let max = 0;\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined) {\n const bottomY = item.y + item.h;\n if (bottomY > max) max = bottomY;\n }\n }\n return max;\n}\n\n/** Get a layout item by its ID. */\nexport function getLayoutItem(\n layout: Layout,\n id: string,\n): LayoutItem | undefined {\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined && item.i === id) {\n return item;\n }\n }\n return undefined;\n}\n\n/** Get all static items from the layout. */\nexport function getStatics(layout: Layout): LayoutItem[] {\n return layout.filter((l): l is LayoutItem => l.static === true);\n}\n\n// ============================================================================\n// Layout Cloning\n// ============================================================================\n\n/** Clone a layout item (shallow copy, boolean flags normalized). */\nexport function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem {\n return {\n i: layoutItem.i,\n x: layoutItem.x,\n y: layoutItem.y,\n w: layoutItem.w,\n h: layoutItem.h,\n minW: layoutItem.minW,\n maxW: layoutItem.maxW,\n minH: layoutItem.minH,\n maxH: layoutItem.maxH,\n moved: Boolean(layoutItem.moved),\n static: Boolean(layoutItem.static),\n isDraggable: layoutItem.isDraggable,\n isResizable: layoutItem.isResizable,\n resizeHandles: layoutItem.resizeHandles,\n constraints: layoutItem.constraints,\n isBounded: layoutItem.isBounded,\n };\n}\n\n/** Clone an entire layout. */\nexport function cloneLayout(layout: Layout): LayoutItem[] {\n const newLayout: LayoutItem[] = new Array(layout.length);\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined) {\n newLayout[i] = cloneLayoutItem(item);\n }\n }\n return newLayout;\n}\n\n// ============================================================================\n// Layout Modification\n// ============================================================================\n\n/** Replace a layout item in a layout (matched by `i`). Other items untouched. */\nexport function modifyLayout(\n layout: Layout,\n layoutItem: LayoutItem,\n): LayoutItem[] {\n const newLayout: LayoutItem[] = new Array(layout.length);\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined) {\n if (layoutItem.i === item.i) {\n newLayout[i] = layoutItem;\n } else {\n newLayout[i] = item;\n }\n }\n }\n return newLayout;\n}\n\n/**\n * Apply a transformation to a layout item. Finds the item by key, clones it,\n * applies the callback, and returns [new layout, modified item | null].\n */\nexport function withLayoutItem(\n layout: Layout,\n itemKey: string,\n cb: (item: LayoutItem) => LayoutItem,\n): [LayoutItem[], LayoutItem | null] {\n let item = getLayoutItem(layout, itemKey);\n if (!item) {\n return [[...layout], null];\n }\n\n item = cb(cloneLayoutItem(item));\n const newLayout = modifyLayout(layout, item);\n\n return [newLayout, item];\n}\n\n// ============================================================================\n// Bounds Correction\n// ============================================================================\n\n/**\n * Ensure all layout items fit within the grid bounds.\n *\n * **IMPORTANT**: mutates the layout items in place for performance. Clone the\n * layout first (e.g. with `cloneLayout()`) if you need immutability.\n */\nexport function correctBounds(\n layout: Mutable<LayoutItem>[],\n bounds: { cols: number },\n): LayoutItem[] {\n const collidesWith = getStatics(layout);\n\n for (let i = 0; i < layout.length; i++) {\n const l = layout[i];\n if (l === undefined) continue;\n\n // Overflows right\n if (l.x + l.w > bounds.cols) {\n l.x = bounds.cols - l.w;\n }\n\n // Overflows left\n if (l.x < 0) {\n l.x = 0;\n l.w = bounds.cols;\n }\n\n if (!l.static) {\n collidesWith.push(l);\n } else {\n // Static items that collide with other statics must be moved down\n while (getFirstCollision(collidesWith, l)) {\n l.y++;\n }\n }\n }\n\n return layout;\n}\n\n// ============================================================================\n// Move Operations\n// ============================================================================\n\n/**\n * Move a layout element to a new position.\n *\n * Handles collision detection and cascading movements. Does not compact the\n * layout - call the compactor separately.\n *\n * **Note**: mutates the `l` parameter directly for performance.\n */\nexport function moveElement(\n layout: Layout,\n l: LayoutItem,\n x: number | undefined,\n y: number | undefined,\n isUserAction: boolean | undefined,\n preventCollision: boolean | undefined,\n compactType: CompactType,\n cols: number,\n allowOverlap?: boolean,\n): LayoutItem[] {\n // Static items can't be moved unless explicitly draggable\n if (l.static && l.isDraggable !== true) {\n return [...layout];\n }\n\n // Short-circuit if position unchanged\n if (l.y === y && l.x === x) {\n return [...layout];\n }\n\n const oldX = l.x;\n const oldY = l.y;\n\n // Update position (mutates l directly - see JSDoc note)\n if (typeof x === 'number') (l as Mutable<LayoutItem>).x = x;\n if (typeof y === 'number') (l as Mutable<LayoutItem>).y = y;\n (l as Mutable<LayoutItem>).moved = true;\n\n // Sort for proper collision detection order\n let sorted = sortLayoutItems(layout, compactType);\n const movingUp =\n compactType === 'vertical' && typeof y === 'number'\n ? oldY >= y\n : compactType === 'horizontal' && typeof x === 'number'\n ? oldX >= x\n : false;\n\n if (movingUp) {\n sorted = sorted.reverse();\n }\n\n const collisions = getAllCollisions(sorted, l);\n const hasCollisions = collisions.length > 0;\n\n // Handle overlap mode - just clone and return\n if (hasCollisions && allowOverlap) {\n return cloneLayout(layout);\n }\n\n // Handle prevent collision mode - revert position.\n // Return same reference to signal no change occurred.\n if (hasCollisions && preventCollision) {\n (l as Mutable<LayoutItem>).x = oldX;\n (l as Mutable<LayoutItem>).y = oldY;\n (l as Mutable<LayoutItem>).moved = false;\n return layout as LayoutItem[];\n }\n\n // Resolve collisions by moving other items\n let resultLayout: LayoutItem[] = [...layout];\n for (let i = 0; i < collisions.length; i++) {\n const collision = collisions[i];\n if (collision === undefined) continue;\n\n // Skip already-moved items to prevent infinite loops\n if (collision.moved) continue;\n\n // Static items can't be moved - move the dragged item instead\n if (collision.static) {\n resultLayout = moveElementAwayFromCollision(\n resultLayout,\n collision,\n l,\n isUserAction,\n compactType,\n cols,\n );\n } else {\n resultLayout = moveElementAwayFromCollision(\n resultLayout,\n l,\n collision,\n isUserAction,\n compactType,\n cols,\n );\n }\n }\n\n return resultLayout;\n}\n\n/**\n * Move an item away from a collision. Attempts to move up/left first if there's\n * room, otherwise moves it down/right.\n */\nexport function moveElementAwayFromCollision(\n layout: Layout,\n collidesWith: LayoutItem,\n itemToMove: LayoutItem,\n isUserAction: boolean | undefined,\n compactType: CompactType,\n cols: number,\n): LayoutItem[] {\n const compactH = compactType === 'horizontal';\n const compactV = compactType === 'vertical';\n const preventCollision = collidesWith.static;\n\n // Try to move up/left first (only on primary collision from user action)\n if (isUserAction) {\n isUserAction = false; // Only try this once\n\n // Create a fake item to test if there's room above/left\n const fakeItem: LayoutItem = {\n x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x,\n y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y,\n w: itemToMove.w,\n h: itemToMove.h,\n i: '-1',\n };\n\n const firstCollision = getFirstCollision(layout, fakeItem);\n const collisionNorth =\n firstCollision !== undefined &&\n firstCollision.y + firstCollision.h > collidesWith.y;\n const collisionWest =\n firstCollision !== undefined &&\n collidesWith.x + collidesWith.w > firstCollision.x;\n\n // No collision above/left - we can move there\n if (!firstCollision) {\n return moveElement(\n layout,\n itemToMove,\n compactH ? fakeItem.x : undefined,\n compactV ? fakeItem.y : undefined,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n }\n\n // Handle specific collision cases\n if (collisionNorth && compactV) {\n return moveElement(\n layout,\n itemToMove,\n undefined,\n itemToMove.y + 1,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n }\n\n if (collisionNorth && compactType === null) {\n // Swap positions in free-form mode\n (collidesWith as Mutable<LayoutItem>).y = itemToMove.y;\n (itemToMove as Mutable<LayoutItem>).y = itemToMove.y + itemToMove.h;\n return [...layout];\n }\n\n if (collisionWest && compactH) {\n return moveElement(\n layout,\n collidesWith,\n itemToMove.x,\n undefined,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n }\n }\n\n // Default: move down/right by 1\n const newX = compactH ? itemToMove.x + 1 : undefined;\n const newY = compactV ? itemToMove.y + 1 : undefined;\n\n if (newX === undefined && newY === undefined) {\n return [...layout];\n }\n\n return moveElement(\n layout,\n itemToMove,\n newX,\n newY,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/** Validate that a layout has the required numeric properties. */\nexport function validateLayout(\n layout: Layout,\n contextName: string = 'Layout',\n): void {\n const requiredProps = ['x', 'y', 'w', 'h'] as const;\n\n if (!Array.isArray(layout)) {\n throw new Error(`${contextName} must be an array!`);\n }\n\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item === undefined) continue;\n\n for (const key of requiredProps) {\n const value = item[key];\n if (typeof value !== 'number' || Number.isNaN(value)) {\n throw new Error(\n `Board: ${contextName}[${i}].${key} must be a number! ` +\n `Received: ${String(value)} (${typeof value})`,\n );\n }\n }\n\n if (item.i !== undefined && typeof item.i !== 'string') {\n throw new Error(\n `Board: ${contextName}[${i}].i must be a string! ` +\n `Received: ${String(item.i)} (${typeof item.i})`,\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"layout.js","names":[],"sources":["../../../../../src/components/layout/Board/grid-core/layout.ts"],"sourcesContent":["/**\n * Core layout manipulation utilities.\n *\n * Vendored from react-grid-layout v2 (`src/core/layout.ts`).\n * See ./NOTICE.md for attribution and license.\n *\n * These functions create, modify, and query grid layouts. Most functions treat\n * layouts as immutable and return new arrays/objects, but a few mutate items in\n * place for performance (documented per function).\n */\n\nimport { getAllCollisions, getFirstCollision } from './collision';\nimport { sortLayoutItems } from './sort';\n\nimport type { CompactType, Layout, LayoutItem, Mutable } from './types';\n\n// ============================================================================\n// Layout Queries\n// ============================================================================\n\n/**\n * Get the bottom-most Y coordinate of the layout (max of y + h).\n */\nexport function bottom(layout: Layout): number {\n let max = 0;\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined) {\n const bottomY = item.y + item.h;\n if (bottomY > max) max = bottomY;\n }\n }\n return max;\n}\n\n/** Get a layout item by its ID. */\nexport function getLayoutItem(\n layout: Layout,\n id: string,\n): LayoutItem | undefined {\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined && item.i === id) {\n return item;\n }\n }\n return undefined;\n}\n\n/** Get all static items from the layout. */\nexport function getStatics(layout: Layout): LayoutItem[] {\n return layout.filter((l): l is LayoutItem => l.static === true);\n}\n\n// ============================================================================\n// Layout Cloning\n// ============================================================================\n\n/** Clone a layout item (shallow copy, boolean flags normalized). */\nexport function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem {\n return {\n i: layoutItem.i,\n x: layoutItem.x,\n y: layoutItem.y,\n w: layoutItem.w,\n h: layoutItem.h,\n minW: layoutItem.minW,\n maxW: layoutItem.maxW,\n minH: layoutItem.minH,\n maxH: layoutItem.maxH,\n moved: Boolean(layoutItem.moved),\n static: Boolean(layoutItem.static),\n isDraggable: layoutItem.isDraggable,\n isResizable: layoutItem.isResizable,\n resizeHandles: layoutItem.resizeHandles,\n constraints: layoutItem.constraints,\n isBounded: layoutItem.isBounded,\n };\n}\n\n/** Clone an entire layout. */\nexport function cloneLayout(layout: Layout): LayoutItem[] {\n const newLayout: LayoutItem[] = new Array(layout.length);\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined) {\n newLayout[i] = cloneLayoutItem(item);\n }\n }\n return newLayout;\n}\n\n// ============================================================================\n// Layout Modification\n// ============================================================================\n\n/** Replace a layout item in a layout (matched by `i`). Other items untouched. */\nexport function modifyLayout(\n layout: Layout,\n layoutItem: LayoutItem,\n): LayoutItem[] {\n const newLayout: LayoutItem[] = new Array(layout.length);\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item !== undefined) {\n if (layoutItem.i === item.i) {\n newLayout[i] = layoutItem;\n } else {\n newLayout[i] = item;\n }\n }\n }\n return newLayout;\n}\n\n/**\n * Apply a transformation to a layout item. Finds the item by key, clones it,\n * applies the callback, and returns [new layout, modified item | null].\n */\nexport function withLayoutItem(\n layout: Layout,\n itemKey: string,\n cb: (item: LayoutItem) => LayoutItem,\n): [LayoutItem[], LayoutItem | null] {\n let item = getLayoutItem(layout, itemKey);\n if (!item) {\n return [[...layout], null];\n }\n\n item = cb(cloneLayoutItem(item));\n const newLayout = modifyLayout(layout, item);\n\n return [newLayout, item];\n}\n\n// ============================================================================\n// Bounds Correction\n// ============================================================================\n\n/**\n * Ensure all layout items fit within the grid bounds.\n *\n * **IMPORTANT**: mutates the layout items in place for performance. Clone the\n * layout first (e.g. with `cloneLayout()`) if you need immutability.\n */\nexport function correctBounds(\n layout: Mutable<LayoutItem>[],\n bounds: { cols: number },\n): LayoutItem[] {\n const collidesWith = getStatics(layout);\n\n for (let i = 0; i < layout.length; i++) {\n const l = layout[i];\n if (l === undefined) continue;\n\n // Overflows right\n if (l.x + l.w > bounds.cols) {\n l.x = bounds.cols - l.w;\n }\n\n // Overflows left\n if (l.x < 0) {\n l.x = 0;\n l.w = bounds.cols;\n }\n\n if (!l.static) {\n collidesWith.push(l);\n } else {\n // Static items that collide with other statics must be moved down\n while (getFirstCollision(collidesWith, l)) {\n l.y++;\n }\n }\n }\n\n return layout;\n}\n\n// ============================================================================\n// Move Operations\n// ============================================================================\n\n/**\n * Move a layout element to a new position.\n *\n * Handles collision detection and cascading movements. Does not compact the\n * layout - call the compactor separately.\n *\n * **Note**: mutates the `l` parameter directly for performance.\n */\nexport function moveElement(\n layout: Layout,\n l: LayoutItem,\n x: number | undefined,\n y: number | undefined,\n isUserAction: boolean | undefined,\n preventCollision: boolean | undefined,\n compactType: CompactType,\n cols: number,\n allowOverlap?: boolean,\n): LayoutItem[] {\n // Static items can't be moved unless explicitly draggable\n if (l.static && l.isDraggable !== true) {\n return [...layout];\n }\n\n // Short-circuit if position unchanged\n if (l.y === y && l.x === x) {\n return [...layout];\n }\n\n const oldX = l.x;\n const oldY = l.y;\n\n // Update position (mutates l directly - see JSDoc note)\n if (typeof x === 'number') (l as Mutable<LayoutItem>).x = x;\n if (typeof y === 'number') (l as Mutable<LayoutItem>).y = y;\n (l as Mutable<LayoutItem>).moved = true;\n\n // Sort for proper collision detection order\n let sorted = sortLayoutItems(layout, compactType);\n const movingUp =\n compactType === 'vertical' && typeof y === 'number'\n ? oldY >= y\n : compactType === 'horizontal' && typeof x === 'number'\n ? oldX >= x\n : false;\n\n if (movingUp) {\n sorted = sorted.reverse();\n }\n\n const collisions = getAllCollisions(sorted, l);\n const hasCollisions = collisions.length > 0;\n\n // Handle overlap mode - just clone and return\n if (hasCollisions && allowOverlap) {\n return cloneLayout(layout);\n }\n\n // Handle prevent collision mode - revert position.\n // Return same reference to signal no change occurred.\n if (hasCollisions && preventCollision) {\n (l as Mutable<LayoutItem>).x = oldX;\n (l as Mutable<LayoutItem>).y = oldY;\n (l as Mutable<LayoutItem>).moved = false;\n return layout as LayoutItem[];\n }\n\n // Resolve collisions by moving other items\n let resultLayout: LayoutItem[] = [...layout];\n for (let i = 0; i < collisions.length; i++) {\n const collision = collisions[i];\n if (collision === undefined) continue;\n\n // Skip already-moved items to prevent infinite loops\n if (collision.moved) continue;\n\n // Static items can't be moved - move the dragged item instead\n if (collision.static) {\n resultLayout = moveElementAwayFromCollision(\n resultLayout,\n collision,\n l,\n isUserAction,\n compactType,\n cols,\n );\n } else {\n resultLayout = moveElementAwayFromCollision(\n resultLayout,\n l,\n collision,\n isUserAction,\n compactType,\n cols,\n );\n }\n }\n\n return resultLayout;\n}\n\n/**\n * Move an item away from a collision. Attempts to move up/left first if there's\n * room, otherwise moves it down/right.\n */\nexport function moveElementAwayFromCollision(\n layout: Layout,\n collidesWith: LayoutItem,\n itemToMove: LayoutItem,\n isUserAction: boolean | undefined,\n compactType: CompactType,\n cols: number,\n): LayoutItem[] {\n const compactH = compactType === 'horizontal';\n const compactV = compactType === 'vertical';\n const preventCollision = collidesWith.static;\n\n // Try to move up/left first (only on primary collision from user action)\n if (isUserAction) {\n isUserAction = false; // Only try this once\n\n // Create a fake item to test if there's room above/left\n const fakeItem: LayoutItem = {\n x: compactH ? Math.max(collidesWith.x - itemToMove.w, 0) : itemToMove.x,\n y: compactV ? Math.max(collidesWith.y - itemToMove.h, 0) : itemToMove.y,\n w: itemToMove.w,\n h: itemToMove.h,\n i: '-1',\n };\n\n const firstCollision = getFirstCollision(layout, fakeItem);\n const collisionNorth =\n firstCollision !== undefined &&\n firstCollision.y + firstCollision.h > collidesWith.y;\n const collisionWest =\n firstCollision !== undefined &&\n collidesWith.x + collidesWith.w > firstCollision.x;\n\n // No collision above/left - we can move there\n if (!firstCollision) {\n return moveElement(\n layout,\n itemToMove,\n compactH ? fakeItem.x : undefined,\n compactV ? fakeItem.y : undefined,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n }\n\n // Handle specific collision cases\n if (collisionNorth && compactV) {\n return moveElement(\n layout,\n itemToMove,\n undefined,\n itemToMove.y + 1,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n }\n\n if (collisionNorth && compactType === null) {\n // Swap positions in free-form mode\n (collidesWith as Mutable<LayoutItem>).y = itemToMove.y;\n (itemToMove as Mutable<LayoutItem>).y = itemToMove.y + itemToMove.h;\n return [...layout];\n }\n\n if (collisionWest && compactH) {\n return moveElement(\n layout,\n collidesWith,\n itemToMove.x,\n undefined,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n }\n }\n\n // Default: move down/right by 1\n const newX = compactH ? itemToMove.x + 1 : undefined;\n const newY = compactV ? itemToMove.y + 1 : undefined;\n\n if (newX === undefined && newY === undefined) {\n return [...layout];\n }\n\n return moveElement(\n layout,\n itemToMove,\n newX,\n newY,\n isUserAction,\n preventCollision,\n compactType,\n cols,\n );\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/** Validate that a layout has the required numeric properties. */\nexport function validateLayout(\n layout: Layout,\n contextName: string = 'Layout',\n): void {\n const requiredProps = ['x', 'y', 'w', 'h'] as const;\n\n if (!Array.isArray(layout)) {\n throw new Error(`${contextName} must be an array!`);\n }\n\n for (let i = 0; i < layout.length; i++) {\n const item = layout[i];\n if (item === undefined) continue;\n\n for (const key of requiredProps) {\n const value = item[key];\n if (typeof value !== 'number' || Number.isNaN(value)) {\n throw new Error(\n `Board: ${contextName}[${i}].${key} must be a number! ` +\n `Received: ${String(value)} (${typeof value})`,\n );\n }\n }\n\n if (item.i !== undefined && typeof item.i !== 'string') {\n throw new Error(\n `Board: ${contextName}[${i}].i must be a string! ` +\n `Received: ${String(item.i)} (${typeof item.i})`,\n );\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAuBA,SAAgB,OAAO,QAAwB;CAC7C,IAAI,MAAM;AACV,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO;AACpB,MAAI,SAAS,QAAW;GACtB,MAAM,UAAU,KAAK,IAAI,KAAK;AAC9B,OAAI,UAAU,IAAK,OAAM;;;AAG7B,QAAO;;;AAIT,SAAgB,cACd,QACA,IACwB;AACxB,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO;AACpB,MAAI,SAAS,UAAa,KAAK,MAAM,GACnC,QAAO;;;;AAOb,SAAgB,WAAW,QAA8B;AACvD,QAAO,OAAO,QAAQ,MAAuB,EAAE,WAAW,KAAK;;;AAQjE,SAAgB,gBAAgB,YAAoC;AAClE,QAAO;EACL,GAAG,WAAW;EACd,GAAG,WAAW;EACd,GAAG,WAAW;EACd,GAAG,WAAW;EACd,GAAG,WAAW;EACd,MAAM,WAAW;EACjB,MAAM,WAAW;EACjB,MAAM,WAAW;EACjB,MAAM,WAAW;EACjB,OAAO,QAAQ,WAAW,MAAM;EAChC,QAAQ,QAAQ,WAAW,OAAO;EAClC,aAAa,WAAW;EACxB,aAAa,WAAW;EACxB,eAAe,WAAW;EAC1B,aAAa,WAAW;EACxB,WAAW,WAAW;EACvB;;;AAIH,SAAgB,YAAY,QAA8B;CACxD,MAAM,YAA0B,IAAI,MAAM,OAAO,OAAO;AACxD,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO;AACpB,MAAI,SAAS,OACX,WAAU,KAAK,gBAAgB,KAAK;;AAGxC,QAAO;;;AAQT,SAAgB,aACd,QACA,YACc;CACd,MAAM,YAA0B,IAAI,MAAM,OAAO,OAAO;AACxD,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,OAAO,OAAO;AACpB,MAAI,SAAS,OACX,KAAI,WAAW,MAAM,KAAK,EACxB,WAAU,KAAK;MAEf,WAAU,KAAK;;AAIrB,QAAO;;;;;;;;AAiCT,SAAgB,cACd,QACA,QACc;CACd,MAAM,eAAe,WAAW,OAAO;AAEvC,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,IAAI,OAAO;AACjB,MAAI,MAAM,OAAW;AAGrB,MAAI,EAAE,IAAI,EAAE,IAAI,OAAO,KACrB,GAAE,IAAI,OAAO,OAAO,EAAE;AAIxB,MAAI,EAAE,IAAI,GAAG;AACX,KAAE,IAAI;AACN,KAAE,IAAI,OAAO;;AAGf,MAAI,CAAC,EAAE,OACL,cAAa,KAAK,EAAE;MAGpB,QAAO,kBAAkB,cAAc,EAAE,CACvC,GAAE;;AAKR,QAAO;;;;;;;;;;AAeT,SAAgB,YACd,QACA,GACA,GACA,GACA,cACA,kBACA,aACA,MACA,cACc;AAEd,KAAI,EAAE,UAAU,EAAE,gBAAgB,KAChC,QAAO,CAAC,GAAG,OAAO;AAIpB,KAAI,EAAE,MAAM,KAAK,EAAE,MAAM,EACvB,QAAO,CAAC,GAAG,OAAO;CAGpB,MAAM,OAAO,EAAE;CACf,MAAM,OAAO,EAAE;AAGf,KAAI,OAAO,MAAM,SAAU,CAAC,EAA0B,IAAI;AAC1D,KAAI,OAAO,MAAM,SAAU,CAAC,EAA0B,IAAI;AAC1D,CAAC,EAA0B,QAAQ;CAGnC,IAAI,SAAS,gBAAgB,QAAQ,YAAY;AAQjD,KANE,gBAAgB,cAAc,OAAO,MAAM,WACvC,QAAQ,IACR,gBAAgB,gBAAgB,OAAO,MAAM,WAC3C,QAAQ,IACR,MAGN,UAAS,OAAO,SAAS;CAG3B,MAAM,aAAa,iBAAiB,QAAQ,EAAE;CAC9C,MAAM,gBAAgB,WAAW,SAAS;AAG1C,KAAI,iBAAiB,aACnB,QAAO,YAAY,OAAO;AAK5B,KAAI,iBAAiB,kBAAkB;AACrC,EAAC,EAA0B,IAAI;AAC/B,EAAC,EAA0B,IAAI;AAC/B,EAAC,EAA0B,QAAQ;AACnC,SAAO;;CAIT,IAAI,eAA6B,CAAC,GAAG,OAAO;AAC5C,MAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,YAAY,WAAW;AAC7B,MAAI,cAAc,OAAW;AAG7B,MAAI,UAAU,MAAO;AAGrB,MAAI,UAAU,OACZ,gBAAe,6BACb,cACA,WACA,GACA,cACA,aACA,KACD;MAED,gBAAe,6BACb,cACA,GACA,WACA,cACA,aACA,KACD;;AAIL,QAAO;;;;;;AAOT,SAAgB,6BACd,QACA,cACA,YACA,cACA,aACA,MACc;CACd,MAAM,WAAW,gBAAgB;CACjC,MAAM,WAAW,gBAAgB;CACjC,MAAM,mBAAmB,aAAa;AAGtC,KAAI,cAAc;AAChB,iBAAe;EAGf,MAAM,WAAuB;GAC3B,GAAG,WAAW,KAAK,IAAI,aAAa,IAAI,WAAW,GAAG,EAAE,GAAG,WAAW;GACtE,GAAG,WAAW,KAAK,IAAI,aAAa,IAAI,WAAW,GAAG,EAAE,GAAG,WAAW;GACtE,GAAG,WAAW;GACd,GAAG,WAAW;GACd,GAAG;GACJ;EAED,MAAM,iBAAiB,kBAAkB,QAAQ,SAAS;EAC1D,MAAM,iBACJ,mBAAmB,UACnB,eAAe,IAAI,eAAe,IAAI,aAAa;EACrD,MAAM,gBACJ,mBAAmB,UACnB,aAAa,IAAI,aAAa,IAAI,eAAe;AAGnD,MAAI,CAAC,eACH,QAAO,YACL,QACA,YACA,WAAW,SAAS,IAAI,QACxB,WAAW,SAAS,IAAI,QACxB,cACA,kBACA,aACA,KACD;AAIH,MAAI,kBAAkB,SACpB,QAAO,YACL,QACA,YACA,QACA,WAAW,IAAI,GACf,cACA,kBACA,aACA,KACD;AAGH,MAAI,kBAAkB,gBAAgB,MAAM;AAE1C,GAAC,aAAqC,IAAI,WAAW;AACrD,GAAC,WAAmC,IAAI,WAAW,IAAI,WAAW;AAClE,UAAO,CAAC,GAAG,OAAO;;AAGpB,MAAI,iBAAiB,SACnB,QAAO,YACL,QACA,cACA,WAAW,GACX,QACA,cACA,kBACA,aACA,KACD;;CAKL,MAAM,OAAO,WAAW,WAAW,IAAI,IAAI;CAC3C,MAAM,OAAO,WAAW,WAAW,IAAI,IAAI;AAE3C,KAAI,SAAS,UAAa,SAAS,OACjC,QAAO,CAAC,GAAG,OAAO;AAGpB,QAAO,YACL,QACA,YACA,MACA,MACA,cACA,kBACA,aACA,KACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { getCompactor, horizontalCompactor, noCompactor, verticalCompactor } from "./grid-core/compactors.js";
|
|
3
3
|
import { aspectRatio, boundedX, boundedY, containerBounds, gridBounds, maxSize, minMaxSize, minSize, snapToGrid } from "./grid-core/constraints.js";
|
|
4
4
|
import { BoardProvider } from "./BoardProvider.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { useEvent } from "../../../_internal/hooks/use-event.js";
|
|
3
3
|
import { cloneLayout } from "./grid-core/layout.js";
|
|
4
4
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { useEvent } from "../../../_internal/hooks/use-event.js";
|
|
3
3
|
import { BoardWidgetStore } from "./board-store.js";
|
|
4
4
|
import { cloneLayout, getLayoutItem, moveElement } from "./grid-core/layout.js";
|
|
@@ -25,6 +25,7 @@ function useBoardRegistry(options) {
|
|
|
25
25
|
const targetSnapshotsRef = useRef(/* @__PURE__ */ new Map());
|
|
26
26
|
const previewRef = useRef(null);
|
|
27
27
|
const frozenRectsRef = useRef(/* @__PURE__ */ new Map());
|
|
28
|
+
const nestedInDraggedRef = useRef(/* @__PURE__ */ new Set());
|
|
28
29
|
const lastLandingRef = useRef(null);
|
|
29
30
|
const [dragState, setDragStateInternal] = useState(null);
|
|
30
31
|
const setDragState = useCallback((next) => {
|
|
@@ -45,6 +46,7 @@ function useBoardRegistry(options) {
|
|
|
45
46
|
const overlay = overlayRef.current;
|
|
46
47
|
boardsRef.current.forEach((entry) => {
|
|
47
48
|
if (!entry.isDroppable()) return;
|
|
49
|
+
if (nestedInDraggedRef.current.has(entry.id)) return;
|
|
48
50
|
if (overlay && overlay.contains(entry.getContentNode())) return;
|
|
49
51
|
const rect = getBoardRect(entry);
|
|
50
52
|
if (!rect) return;
|
|
@@ -58,10 +60,16 @@ function useBoardRegistry(options) {
|
|
|
58
60
|
});
|
|
59
61
|
return best;
|
|
60
62
|
}, [getBoardRect]);
|
|
61
|
-
const onDragStart = useEvent((boardId, itemId, rect, pointerType) => {
|
|
63
|
+
const onDragStart = useEvent((boardId, itemId, rect, pointerType, widgetNode) => {
|
|
62
64
|
const entry = boardsRef.current.get(boardId);
|
|
63
65
|
const item = entry ? getLayoutItem(entry.getLayout(), itemId) : void 0;
|
|
64
66
|
if (!entry || !item) return;
|
|
67
|
+
const nested = /* @__PURE__ */ new Set();
|
|
68
|
+
if (widgetNode) boardsRef.current.forEach((e) => {
|
|
69
|
+
const node = e.getContentNode();
|
|
70
|
+
if (node && widgetNode.contains(node)) nested.add(e.id);
|
|
71
|
+
});
|
|
72
|
+
nestedInDraggedRef.current = nested;
|
|
65
73
|
const frozen = /* @__PURE__ */ new Map();
|
|
66
74
|
boardsRef.current.forEach((e) => {
|
|
67
75
|
const r = e.getContentRect();
|
|
@@ -280,6 +288,7 @@ function useBoardRegistry(options) {
|
|
|
280
288
|
sourceSnapshotRef.current = [];
|
|
281
289
|
targetSnapshotsRef.current.clear();
|
|
282
290
|
frozenRectsRef.current.clear();
|
|
291
|
+
nestedInDraggedRef.current = /* @__PURE__ */ new Set();
|
|
283
292
|
previewRef.current = null;
|
|
284
293
|
lastLandingRef.current = null;
|
|
285
294
|
setDragState(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-board-registry.js","names":[],"sources":["../../../../src/components/layout/Board/use-board-registry.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { useEvent } from '../../../_internal/hooks';\n\nimport {\n BoardDragState,\n BoardEntry,\n BoardRegistryContextValue,\n ViewportRect,\n WidgetTransferInfo,\n} from './board-context';\nimport { BoardWidgetStore } from './board-store';\nimport {\n applyPositionConstraints,\n calcXYRaw,\n cloneLayout,\n getLayoutItem,\n LayoutItem,\n moveElement,\n} from './grid-core';\n\nfunction rectCenter(rect: ViewportRect): { x: number; y: number } {\n return {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2,\n };\n}\n\n/**\n * Cross-board drag orchestration.\n *\n * Owns the shared widget-content store, the drag overlay ref, and the registry\n * of boards. Handles moving an item inside a board and transferring it between\n * boards (including nested ones) by hit-testing the pointer against each board's\n * content rectangle.\n */\nexport interface UseBoardRegistryOptions {\n /** Fired when a widget is dropped from one board into another. */\n onWidgetTransfer?: (info: WidgetTransferInfo) => void;\n}\n\nexport function useBoardRegistry(\n options?: UseBoardRegistryOptions,\n): BoardRegistryContextValue {\n const store = useMemo(() => new BoardWidgetStore(), []);\n // Latest transfer callback, read from a ref so the stable `onDragEnd` handler\n // always calls the current one without re-creating the registry.\n const onTransferRef = useRef(options?.onWidgetTransfer);\n onTransferRef.current = options?.onWidgetTransfer;\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const boardsRef = useRef<Map<string, BoardEntry>>(new Map());\n const dragStateRef = useRef<BoardDragState | null>(null);\n const affectedRef = useRef<Set<string>>(new Set());\n // Snapshot of the source board's layout at drag start, used to restore the\n // source when the pointer leaves it (the dragged item is never removed from\n // the source mid-drag, so its gesture host stays mounted).\n const sourceSnapshotRef = useRef<LayoutItem[]>([]);\n // Snapshot of each visited target board's layout at the moment the pointer\n // first entered it. Used to restore a board when the pointer leaves it, and as\n // the clean seed for the reflow preview on (re-)entry. Never mutated.\n const targetSnapshotsRef = useRef<Map<string, LayoutItem[]>>(new Map());\n // The current target board's live working layout (including the incoming\n // item). Carried across frames so small pointer movements reflow the board\n // incrementally - exactly like an in-board drag - instead of recomputing from\n // scratch each frame (which lets collision resolution sink the item to the\n // bottom of an occupied column).\n const previewRef = useRef<{ boardId: string; working: LayoutItem[] } | null>(\n null,\n );\n // Board content rects captured at drag start. Reading geometry from here (not\n // live getBoundingClientRect) means the live-reflow preview can't move the\n // rects that selection/landing depend on -> no feedback loop.\n const frozenRectsRef = useRef<Map<string, DOMRect>>(new Map());\n // Last landing position computed for the current target board (grid units).\n const lastLandingRef = useRef<{ x: number; y: number } | null>(null);\n const [dragState, setDragStateInternal] = useState<BoardDragState | null>(\n null,\n );\n\n const setDragState = useCallback((next: BoardDragState | null) => {\n dragStateRef.current = next;\n setDragStateInternal(next);\n }, []);\n\n const registerBoard = useCallback((entry: BoardEntry) => {\n boardsRef.current.set(entry.id, entry);\n return () => {\n // Only remove if a newer board instance hasn't already taken over this id\n // (boards can remount when their host widget is relocated, e.g. dragged).\n if (boardsRef.current.get(entry.id) === entry) {\n boardsRef.current.delete(entry.id);\n }\n };\n }, []);\n\n // Geometry frozen at drag start; falls back to the live rect for boards that\n // mount mid-drag (they weren't captured at start).\n const getBoardRect = useCallback(\n (entry: BoardEntry): DOMRect | null =>\n frozenRectsRef.current.get(entry.id) ?? entry.getContentRect(),\n [],\n );\n\n /** Find the most-nested droppable board whose content rect contains a point. */\n const hitTest = useCallback(\n (point: { x: number; y: number }): BoardEntry | null => {\n let best: BoardEntry | null = null;\n let bestArea = Infinity;\n\n // During a pointer drag the dragged widget (and any board nested inside it)\n // lives in the overlay portal. Such boards must never be drop targets -\n // dropping a widget into a board nested within itself would remove it from\n // the tree that renders that board.\n const overlay = overlayRef.current;\n\n boardsRef.current.forEach((entry) => {\n if (!entry.isDroppable()) return;\n if (overlay && overlay.contains(entry.getContentNode())) return;\n const rect = getBoardRect(entry);\n if (!rect) return;\n if (\n point.x >= rect.left &&\n point.x <= rect.right &&\n point.y >= rect.top &&\n point.y <= rect.bottom\n ) {\n const area = rect.width * rect.height;\n if (area < bestArea) {\n bestArea = area;\n best = entry;\n }\n }\n });\n\n return best;\n },\n [getBoardRect],\n );\n\n const onDragStart = useEvent(\n (\n boardId: string,\n itemId: string,\n rect: ViewportRect,\n pointerType: string,\n ) => {\n const entry = boardsRef.current.get(boardId);\n const item = entry ? getLayoutItem(entry.getLayout(), itemId) : undefined;\n if (!entry || !item) return;\n\n // Freeze every board's geometry for the whole gesture so live-reflow\n // preview writes can't move the rects selection/landing read.\n const frozen = new Map<string, DOMRect>();\n boardsRef.current.forEach((e) => {\n const r = e.getContentRect();\n if (r) frozen.set(e.id, r);\n });\n frozenRectsRef.current = frozen;\n\n affectedRef.current = new Set([boardId]);\n sourceSnapshotRef.current = cloneLayout(entry.getLayout());\n previewRef.current = null;\n lastLandingRef.current = { x: item.x, y: item.y };\n // Layout-item constraints win; otherwise fall back to the ones declared on\n // the owning `Board.Widget` so position constraints apply during drag.\n const draggedItem: LayoutItem = {\n ...item,\n constraints: item.constraints ?? store.get(itemId)?.constraints,\n };\n const next: BoardDragState = {\n sourceBoardId: boardId,\n currentBoardId: boardId,\n itemId,\n item: draggedItem,\n rect,\n pointerType,\n };\n setDragState(next);\n entry.setPlaceholder({ ...item });\n },\n );\n\n /** Compute the constrained landing position of an item on a target board. */\n const computeLanding = useCallback(\n (\n target: BoardEntry,\n item: LayoutItem,\n rect: ViewportRect,\n ): { x: number; y: number } => {\n const pp = target.getPositionParams();\n const contentRect = getBoardRect(target);\n const localLeft = rect.left - (contentRect?.left ?? 0);\n const localTop = rect.top - (contentRect?.top ?? 0);\n const raw = calcXYRaw(pp, localTop, localLeft);\n\n return applyPositionConstraints(\n target.getConstraints(),\n item,\n raw.x,\n raw.y,\n {\n cols: pp.cols,\n maxRows: target.getMaxRows(),\n containerWidth: pp.containerWidth,\n containerHeight: target.getContainerHeight(),\n rowHeight: pp.rowHeight,\n margin: pp.margin,\n layout: target.getLayout(),\n },\n );\n },\n [getBoardRect],\n );\n\n const moveWithinBoard = useCallback(\n (entry: BoardEntry, item: LayoutItem, x: number, y: number) => {\n const pp = entry.getPositionParams();\n const compactor = entry.getCompactor();\n const layout = entry.getLayout();\n const live = getLayoutItem(layout, item.i);\n const working = live ? [...layout] : [...layout, { ...item, x, y }];\n const target = getLayoutItem(working, item.i);\n if (!target) return;\n\n const moved = moveElement(\n working,\n target,\n x,\n y,\n true,\n compactor.preventCollision,\n compactor.type,\n pp.cols,\n compactor.allowOverlap,\n );\n const compacted = [...compactor.compact(moved, pp.cols)];\n entry.applyLayout(compacted, false);\n entry.setPlaceholder(getLayoutItem(compacted, item.i) ?? null);\n },\n [],\n );\n\n /**\n * Live cross-board reflow preview. Pushes the target board's *other* widgets\n * aside to make room for the incoming item, without ever adding the dragged\n * item's host to the target (it stays visualized as a placeholder + overlay\n * clone, and its gesture host remains mounted in the source board).\n *\n * Continuity: the working layout (including the incoming item) is carried\n * across frames via `previewRef`, so a small pointer movement moves the item\n * one step and reflows the neighbours incrementally - identical to an in-board\n * drag. Recomputing from the clean snapshot every frame instead lets\n * `moveElement`/compaction sink the item to the bottom of an occupied column\n * (the \"pushed too far below\" bug). On (re-)entry the working layout is seeded\n * from a *clone* of the snapshot so the stored snapshot is never mutated.\n */\n const previewOnTarget = useCallback(\n (target: BoardEntry, item: LayoutItem, x: number, y: number) => {\n const pp = target.getPositionParams();\n const compactor = target.getCompactor();\n\n const carried =\n previewRef.current?.boardId === target.id\n ? previewRef.current.working\n : null;\n const base = (\n carried ??\n cloneLayout(\n targetSnapshotsRef.current.get(target.id) ?? target.getLayout(),\n )\n ).filter((l) => l.i !== item.i);\n\n // Reuse the item's carried position as the move origin (continuity). On\n // first entry there is none, so seed it just above (or left of) its target\n // cell: that makes the first `moveElement` an *active* placement (never a\n // no-op) that pushes colliding widgets aside instead of the item sinking.\n const prevItem = carried ? getLayoutItem(carried, item.i) : undefined;\n const dragged: LayoutItem = prevItem\n ? { ...prevItem }\n : compactor.type === 'horizontal'\n ? { ...item, x: Math.max(0, x) - 1, y }\n : { ...item, x, y: Math.max(0, y) - 1 };\n const working = [...base, dragged];\n\n const moved = moveElement(\n working,\n dragged,\n x,\n y,\n true,\n compactor.preventCollision,\n compactor.type,\n pp.cols,\n compactor.allowOverlap,\n );\n const compacted = [...compactor.compact(moved, pp.cols)];\n previewRef.current = { boardId: target.id, working: compacted };\n\n const landed = getLayoutItem(compacted, item.i) ?? { ...item, x, y };\n // Apply only the other widgets so the dragged item is never rendered as a\n // host on the target board.\n target.applyLayout(\n compacted.filter((l) => l.i !== item.i),\n false,\n );\n target.setPlaceholder({ ...landed });\n },\n [],\n );\n\n const onDragMove = useEvent(\n (deltaX: number, deltaY: number, _pointerType: string) => {\n const ds = dragStateRef.current;\n if (!ds) return;\n\n const newRect: ViewportRect = {\n ...ds.rect,\n left: ds.rect.left + deltaX,\n top: ds.rect.top + deltaY,\n };\n\n const source = boardsRef.current.get(ds.sourceBoardId);\n // Fall back to the source board so a pointer outside every board keeps the\n // widget anchored to where it came from. Frozen rects make this\n // deterministic per pointer position (no preview-induced flip-flop).\n const target = hitTest(rectCenter(newRect)) ?? source ?? null;\n\n if (!target) {\n setDragState({ ...ds, rect: newRect });\n return;\n }\n\n const { x, y } = computeLanding(target, ds.item, newRect);\n lastLandingRef.current = { x, y };\n\n // Same board: run the live in-board preview (item stays owned by the\n // source, so its gesture host is never unmounted).\n if (target.id === ds.sourceBoardId) {\n if (ds.currentBoardId !== ds.sourceBoardId) {\n // Returning from another board: restore that board's pushed widgets\n // to their pre-hover arrangement and clear its placeholder.\n const prev = boardsRef.current.get(ds.currentBoardId);\n const snap = targetSnapshotsRef.current.get(ds.currentBoardId);\n if (snap) prev?.applyLayout(cloneLayout(snap), false);\n prev?.setPlaceholder(null);\n previewRef.current = null;\n }\n moveWithinBoard(target, ds.item, x, y);\n setDragState({\n ...ds,\n currentBoardId: ds.sourceBoardId,\n rect: newRect,\n });\n return;\n }\n\n // Cross-board: preview the transfer live by pushing the target board's\n // other widgets aside (see `previewOnTarget`). The dragged item's host\n // stays mounted in the source board for the entire drag; the actual\n // transfer is committed on drop.\n if (ds.currentBoardId !== target.id) {\n const prev = boardsRef.current.get(ds.currentBoardId);\n if (ds.currentBoardId === ds.sourceBoardId) {\n // Leaving the source: restore it to its pre-drag arrangement.\n prev?.applyLayout(cloneLayout(sourceSnapshotRef.current), false);\n } else {\n // Leaving another target board: restore its pushed widgets.\n const snap = targetSnapshotsRef.current.get(ds.currentBoardId);\n if (snap) prev?.applyLayout(cloneLayout(snap), false);\n }\n prev?.setPlaceholder(null);\n // Drop the carried working layout so the newly entered target seeds a\n // fresh preview from its own clean snapshot.\n previewRef.current = null;\n\n // Snapshot the newly entered target once, as the stable base for its\n // reflow preview.\n if (!targetSnapshotsRef.current.has(target.id)) {\n targetSnapshotsRef.current.set(\n target.id,\n cloneLayout(target.getLayout()),\n );\n }\n }\n\n previewOnTarget(target, ds.item, x, y);\n affectedRef.current.add(target.id);\n setDragState({ ...ds, currentBoardId: target.id, rect: newRect });\n },\n );\n\n const onDragEnd = useEvent(() => {\n const ds = dragStateRef.current;\n if (!ds) return;\n\n const source = boardsRef.current.get(ds.sourceBoardId);\n const target = boardsRef.current.get(ds.currentBoardId);\n const droppedInSource = !target || target.id === ds.sourceBoardId;\n\n if (droppedInSource) {\n // Commit a freshly compacted source so the result never depends on the\n // last preview frame (which may have been mid-reflow).\n if (source) {\n const sp = source.getPositionParams();\n const sc = source.getCompactor();\n source.applyLayout([...sc.compact(source.getLayout(), sp.cols)], true);\n }\n } else {\n const landing = lastLandingRef.current ?? { x: ds.item.x, y: ds.item.y };\n\n // Remove the item from the source board and compact.\n if (source) {\n const sp = source.getPositionParams();\n const sc = source.getCompactor();\n const remaining = source.getLayout().filter((l) => l.i !== ds.itemId);\n source.applyLayout([...sc.compact(remaining, sp.cols)], true);\n }\n\n const tp = target!.getPositionParams();\n const tc = target!.getCompactor();\n\n // Prefer committing the exact arrangement the user was previewing (item\n // already placed with the neighbours reflowed around it via continuity).\n const carried =\n previewRef.current?.boardId === target!.id &&\n getLayoutItem(previewRef.current.working, ds.itemId)\n ? previewRef.current.working\n : null;\n\n let finalLayout: LayoutItem[];\n if (carried) {\n finalLayout = [...tc.compact(cloneLayout(carried), tp.cols)];\n } else {\n // No preview frame ran (e.g. a teleport drop). Seed the item just above\n // (or left of) its landing cell so `moveElement` actively places it\n // rather than no-opping and letting compaction sink it to the bottom.\n const newItem: LayoutItem =\n tc.type === 'horizontal'\n ? { ...ds.item, x: Math.max(0, landing.x) - 1, y: landing.y }\n : { ...ds.item, x: landing.x, y: Math.max(0, landing.y) - 1 };\n const base = [\n ...cloneLayout(\n (\n targetSnapshotsRef.current.get(target!.id) ?? target!.getLayout()\n ).filter((l) => l.i !== ds.itemId),\n ),\n newItem,\n ];\n const moved = moveElement(\n base,\n newItem,\n landing.x,\n landing.y,\n true,\n tc.preventCollision,\n tc.type,\n tp.cols,\n tc.allowOverlap,\n );\n finalLayout = [...tc.compact(moved, tp.cols)];\n }\n target!.applyLayout(finalLayout, true);\n\n // Signal the transfer so a controlled app can move the widget's\n // declaration into the destination container (positions are already\n // reported via each board's onLayoutChange).\n onTransferRef.current?.({\n widgetId: ds.itemId,\n fromBoardId: ds.sourceBoardId,\n toBoardId: target!.id,\n item: getLayoutItem(finalLayout, ds.itemId) ?? {\n ...ds.item,\n x: landing.x,\n y: landing.y,\n },\n });\n }\n\n const ids = new Set(affectedRef.current);\n ids.add(ds.sourceBoardId);\n ids.add(ds.currentBoardId);\n ids.forEach((id) => boardsRef.current.get(id)?.setPlaceholder(null));\n\n affectedRef.current.clear();\n sourceSnapshotRef.current = [];\n targetSnapshotsRef.current.clear();\n frozenRectsRef.current.clear();\n previewRef.current = null;\n lastLandingRef.current = null;\n setDragState(null);\n });\n\n return useMemo(\n () => ({\n store,\n overlayRef,\n registerBoard,\n onDragStart,\n onDragMove,\n onDragEnd,\n dragState,\n }),\n [store, registerBoard, onDragStart, onDragMove, onDragEnd, dragState],\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-board-registry.js","names":[],"sources":["../../../../src/components/layout/Board/use-board-registry.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { useEvent } from '../../../_internal/hooks';\n\nimport {\n BoardDragState,\n BoardEntry,\n BoardRegistryContextValue,\n ViewportRect,\n WidgetTransferInfo,\n} from './board-context';\nimport { BoardWidgetStore } from './board-store';\nimport {\n applyPositionConstraints,\n calcXYRaw,\n cloneLayout,\n getLayoutItem,\n LayoutItem,\n moveElement,\n} from './grid-core';\n\nfunction rectCenter(rect: ViewportRect): { x: number; y: number } {\n return {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2,\n };\n}\n\n/**\n * Cross-board drag orchestration.\n *\n * Owns the shared widget-content store, the drag overlay ref, and the registry\n * of boards. Handles moving an item inside a board and transferring it between\n * boards (including nested ones) by hit-testing the pointer against each board's\n * content rectangle.\n */\nexport interface UseBoardRegistryOptions {\n /** Fired when a widget is dropped from one board into another. */\n onWidgetTransfer?: (info: WidgetTransferInfo) => void;\n}\n\nexport function useBoardRegistry(\n options?: UseBoardRegistryOptions,\n): BoardRegistryContextValue {\n const store = useMemo(() => new BoardWidgetStore(), []);\n // Latest transfer callback, read from a ref so the stable `onDragEnd` handler\n // always calls the current one without re-creating the registry.\n const onTransferRef = useRef(options?.onWidgetTransfer);\n onTransferRef.current = options?.onWidgetTransfer;\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const boardsRef = useRef<Map<string, BoardEntry>>(new Map());\n const dragStateRef = useRef<BoardDragState | null>(null);\n const affectedRef = useRef<Set<string>>(new Set());\n // Snapshot of the source board's layout at drag start, used to restore the\n // source when the pointer leaves it (the dragged item is never removed from\n // the source mid-drag, so its gesture host stays mounted).\n const sourceSnapshotRef = useRef<LayoutItem[]>([]);\n // Snapshot of each visited target board's layout at the moment the pointer\n // first entered it. Used to restore a board when the pointer leaves it, and as\n // the clean seed for the reflow preview on (re-)entry. Never mutated.\n const targetSnapshotsRef = useRef<Map<string, LayoutItem[]>>(new Map());\n // The current target board's live working layout (including the incoming\n // item). Carried across frames so small pointer movements reflow the board\n // incrementally - exactly like an in-board drag - instead of recomputing from\n // scratch each frame (which lets collision resolution sink the item to the\n // bottom of an occupied column).\n const previewRef = useRef<{ boardId: string; working: LayoutItem[] } | null>(\n null,\n );\n // Board content rects captured at drag start. Reading geometry from here (not\n // live getBoundingClientRect) means the live-reflow preview can't move the\n // rects that selection/landing depend on -> no feedback loop.\n const frozenRectsRef = useRef<Map<string, DOMRect>>(new Map());\n // Ids of boards nested inside the dragged widget, captured at drag start.\n // Such a board must never be a drop target: dropping a widget into a board\n // nested within itself removes it from the tree that renders that board.\n // The overlay-containment check in `hitTest` only catches these once the\n // dragged widget has floated into the overlay, but `useMove` fires the first\n // `onMove` synchronously with `onMoveStart` (before React relocates the\n // widget into the overlay), so on a tiny one-move drag the nested board is\n // still in-grid and would be selected. Excluding these ids for the whole\n // gesture closes that window.\n const nestedInDraggedRef = useRef<Set<string>>(new Set());\n // Last landing position computed for the current target board (grid units).\n const lastLandingRef = useRef<{ x: number; y: number } | null>(null);\n const [dragState, setDragStateInternal] = useState<BoardDragState | null>(\n null,\n );\n\n const setDragState = useCallback((next: BoardDragState | null) => {\n dragStateRef.current = next;\n setDragStateInternal(next);\n }, []);\n\n const registerBoard = useCallback((entry: BoardEntry) => {\n boardsRef.current.set(entry.id, entry);\n return () => {\n // Only remove if a newer board instance hasn't already taken over this id\n // (boards can remount when their host widget is relocated, e.g. dragged).\n if (boardsRef.current.get(entry.id) === entry) {\n boardsRef.current.delete(entry.id);\n }\n };\n }, []);\n\n // Geometry frozen at drag start; falls back to the live rect for boards that\n // mount mid-drag (they weren't captured at start).\n const getBoardRect = useCallback(\n (entry: BoardEntry): DOMRect | null =>\n frozenRectsRef.current.get(entry.id) ?? entry.getContentRect(),\n [],\n );\n\n /** Find the most-nested droppable board whose content rect contains a point. */\n const hitTest = useCallback(\n (point: { x: number; y: number }): BoardEntry | null => {\n let best: BoardEntry | null = null;\n let bestArea = Infinity;\n\n // During a pointer drag the dragged widget (and any board nested inside it)\n // lives in the overlay portal. Such boards must never be drop targets -\n // dropping a widget into a board nested within itself would remove it from\n // the tree that renders that board.\n const overlay = overlayRef.current;\n\n boardsRef.current.forEach((entry) => {\n if (!entry.isDroppable()) return;\n if (nestedInDraggedRef.current.has(entry.id)) return;\n if (overlay && overlay.contains(entry.getContentNode())) return;\n const rect = getBoardRect(entry);\n if (!rect) return;\n if (\n point.x >= rect.left &&\n point.x <= rect.right &&\n point.y >= rect.top &&\n point.y <= rect.bottom\n ) {\n const area = rect.width * rect.height;\n if (area < bestArea) {\n bestArea = area;\n best = entry;\n }\n }\n });\n\n return best;\n },\n [getBoardRect],\n );\n\n const onDragStart = useEvent(\n (\n boardId: string,\n itemId: string,\n rect: ViewportRect,\n pointerType: string,\n widgetNode: HTMLElement | null,\n ) => {\n const entry = boardsRef.current.get(boardId);\n const item = entry ? getLayoutItem(entry.getLayout(), itemId) : undefined;\n if (!entry || !item) return;\n\n // Record boards nested inside the dragged widget so they are never picked\n // as a drop target (dropping a widget into a board nested within itself\n // would unmount it). Computed here, before the widget floats into the\n // overlay, while its nested boards are still in-grid descendants.\n const nested = new Set<string>();\n if (widgetNode) {\n boardsRef.current.forEach((e) => {\n const node = e.getContentNode();\n if (node && widgetNode.contains(node)) nested.add(e.id);\n });\n }\n nestedInDraggedRef.current = nested;\n\n // Freeze every board's geometry for the whole gesture so live-reflow\n // preview writes can't move the rects selection/landing read.\n const frozen = new Map<string, DOMRect>();\n boardsRef.current.forEach((e) => {\n const r = e.getContentRect();\n if (r) frozen.set(e.id, r);\n });\n frozenRectsRef.current = frozen;\n\n affectedRef.current = new Set([boardId]);\n sourceSnapshotRef.current = cloneLayout(entry.getLayout());\n previewRef.current = null;\n lastLandingRef.current = { x: item.x, y: item.y };\n // Layout-item constraints win; otherwise fall back to the ones declared on\n // the owning `Board.Widget` so position constraints apply during drag.\n const draggedItem: LayoutItem = {\n ...item,\n constraints: item.constraints ?? store.get(itemId)?.constraints,\n };\n const next: BoardDragState = {\n sourceBoardId: boardId,\n currentBoardId: boardId,\n itemId,\n item: draggedItem,\n rect,\n pointerType,\n };\n setDragState(next);\n entry.setPlaceholder({ ...item });\n },\n );\n\n /** Compute the constrained landing position of an item on a target board. */\n const computeLanding = useCallback(\n (\n target: BoardEntry,\n item: LayoutItem,\n rect: ViewportRect,\n ): { x: number; y: number } => {\n const pp = target.getPositionParams();\n const contentRect = getBoardRect(target);\n const localLeft = rect.left - (contentRect?.left ?? 0);\n const localTop = rect.top - (contentRect?.top ?? 0);\n const raw = calcXYRaw(pp, localTop, localLeft);\n\n return applyPositionConstraints(\n target.getConstraints(),\n item,\n raw.x,\n raw.y,\n {\n cols: pp.cols,\n maxRows: target.getMaxRows(),\n containerWidth: pp.containerWidth,\n containerHeight: target.getContainerHeight(),\n rowHeight: pp.rowHeight,\n margin: pp.margin,\n layout: target.getLayout(),\n },\n );\n },\n [getBoardRect],\n );\n\n const moveWithinBoard = useCallback(\n (entry: BoardEntry, item: LayoutItem, x: number, y: number) => {\n const pp = entry.getPositionParams();\n const compactor = entry.getCompactor();\n const layout = entry.getLayout();\n const live = getLayoutItem(layout, item.i);\n const working = live ? [...layout] : [...layout, { ...item, x, y }];\n const target = getLayoutItem(working, item.i);\n if (!target) return;\n\n const moved = moveElement(\n working,\n target,\n x,\n y,\n true,\n compactor.preventCollision,\n compactor.type,\n pp.cols,\n compactor.allowOverlap,\n );\n const compacted = [...compactor.compact(moved, pp.cols)];\n entry.applyLayout(compacted, false);\n entry.setPlaceholder(getLayoutItem(compacted, item.i) ?? null);\n },\n [],\n );\n\n /**\n * Live cross-board reflow preview. Pushes the target board's *other* widgets\n * aside to make room for the incoming item, without ever adding the dragged\n * item's host to the target (it stays visualized as a placeholder + overlay\n * clone, and its gesture host remains mounted in the source board).\n *\n * Continuity: the working layout (including the incoming item) is carried\n * across frames via `previewRef`, so a small pointer movement moves the item\n * one step and reflows the neighbours incrementally - identical to an in-board\n * drag. Recomputing from the clean snapshot every frame instead lets\n * `moveElement`/compaction sink the item to the bottom of an occupied column\n * (the \"pushed too far below\" bug). On (re-)entry the working layout is seeded\n * from a *clone* of the snapshot so the stored snapshot is never mutated.\n */\n const previewOnTarget = useCallback(\n (target: BoardEntry, item: LayoutItem, x: number, y: number) => {\n const pp = target.getPositionParams();\n const compactor = target.getCompactor();\n\n const carried =\n previewRef.current?.boardId === target.id\n ? previewRef.current.working\n : null;\n const base = (\n carried ??\n cloneLayout(\n targetSnapshotsRef.current.get(target.id) ?? target.getLayout(),\n )\n ).filter((l) => l.i !== item.i);\n\n // Reuse the item's carried position as the move origin (continuity). On\n // first entry there is none, so seed it just above (or left of) its target\n // cell: that makes the first `moveElement` an *active* placement (never a\n // no-op) that pushes colliding widgets aside instead of the item sinking.\n const prevItem = carried ? getLayoutItem(carried, item.i) : undefined;\n const dragged: LayoutItem = prevItem\n ? { ...prevItem }\n : compactor.type === 'horizontal'\n ? { ...item, x: Math.max(0, x) - 1, y }\n : { ...item, x, y: Math.max(0, y) - 1 };\n const working = [...base, dragged];\n\n const moved = moveElement(\n working,\n dragged,\n x,\n y,\n true,\n compactor.preventCollision,\n compactor.type,\n pp.cols,\n compactor.allowOverlap,\n );\n const compacted = [...compactor.compact(moved, pp.cols)];\n previewRef.current = { boardId: target.id, working: compacted };\n\n const landed = getLayoutItem(compacted, item.i) ?? { ...item, x, y };\n // Apply only the other widgets so the dragged item is never rendered as a\n // host on the target board.\n target.applyLayout(\n compacted.filter((l) => l.i !== item.i),\n false,\n );\n target.setPlaceholder({ ...landed });\n },\n [],\n );\n\n const onDragMove = useEvent(\n (deltaX: number, deltaY: number, _pointerType: string) => {\n const ds = dragStateRef.current;\n if (!ds) return;\n\n const newRect: ViewportRect = {\n ...ds.rect,\n left: ds.rect.left + deltaX,\n top: ds.rect.top + deltaY,\n };\n\n const source = boardsRef.current.get(ds.sourceBoardId);\n // Fall back to the source board so a pointer outside every board keeps the\n // widget anchored to where it came from. Frozen rects make this\n // deterministic per pointer position (no preview-induced flip-flop).\n const target = hitTest(rectCenter(newRect)) ?? source ?? null;\n\n if (!target) {\n setDragState({ ...ds, rect: newRect });\n return;\n }\n\n const { x, y } = computeLanding(target, ds.item, newRect);\n lastLandingRef.current = { x, y };\n\n // Same board: run the live in-board preview (item stays owned by the\n // source, so its gesture host is never unmounted).\n if (target.id === ds.sourceBoardId) {\n if (ds.currentBoardId !== ds.sourceBoardId) {\n // Returning from another board: restore that board's pushed widgets\n // to their pre-hover arrangement and clear its placeholder.\n const prev = boardsRef.current.get(ds.currentBoardId);\n const snap = targetSnapshotsRef.current.get(ds.currentBoardId);\n if (snap) prev?.applyLayout(cloneLayout(snap), false);\n prev?.setPlaceholder(null);\n previewRef.current = null;\n }\n moveWithinBoard(target, ds.item, x, y);\n setDragState({\n ...ds,\n currentBoardId: ds.sourceBoardId,\n rect: newRect,\n });\n return;\n }\n\n // Cross-board: preview the transfer live by pushing the target board's\n // other widgets aside (see `previewOnTarget`). The dragged item's host\n // stays mounted in the source board for the entire drag; the actual\n // transfer is committed on drop.\n if (ds.currentBoardId !== target.id) {\n const prev = boardsRef.current.get(ds.currentBoardId);\n if (ds.currentBoardId === ds.sourceBoardId) {\n // Leaving the source: restore it to its pre-drag arrangement.\n prev?.applyLayout(cloneLayout(sourceSnapshotRef.current), false);\n } else {\n // Leaving another target board: restore its pushed widgets.\n const snap = targetSnapshotsRef.current.get(ds.currentBoardId);\n if (snap) prev?.applyLayout(cloneLayout(snap), false);\n }\n prev?.setPlaceholder(null);\n // Drop the carried working layout so the newly entered target seeds a\n // fresh preview from its own clean snapshot.\n previewRef.current = null;\n\n // Snapshot the newly entered target once, as the stable base for its\n // reflow preview.\n if (!targetSnapshotsRef.current.has(target.id)) {\n targetSnapshotsRef.current.set(\n target.id,\n cloneLayout(target.getLayout()),\n );\n }\n }\n\n previewOnTarget(target, ds.item, x, y);\n affectedRef.current.add(target.id);\n setDragState({ ...ds, currentBoardId: target.id, rect: newRect });\n },\n );\n\n const onDragEnd = useEvent(() => {\n const ds = dragStateRef.current;\n if (!ds) return;\n\n const source = boardsRef.current.get(ds.sourceBoardId);\n const target = boardsRef.current.get(ds.currentBoardId);\n const droppedInSource = !target || target.id === ds.sourceBoardId;\n\n if (droppedInSource) {\n // Commit a freshly compacted source so the result never depends on the\n // last preview frame (which may have been mid-reflow).\n if (source) {\n const sp = source.getPositionParams();\n const sc = source.getCompactor();\n source.applyLayout([...sc.compact(source.getLayout(), sp.cols)], true);\n }\n } else {\n const landing = lastLandingRef.current ?? { x: ds.item.x, y: ds.item.y };\n\n // Remove the item from the source board and compact.\n if (source) {\n const sp = source.getPositionParams();\n const sc = source.getCompactor();\n const remaining = source.getLayout().filter((l) => l.i !== ds.itemId);\n source.applyLayout([...sc.compact(remaining, sp.cols)], true);\n }\n\n const tp = target!.getPositionParams();\n const tc = target!.getCompactor();\n\n // Prefer committing the exact arrangement the user was previewing (item\n // already placed with the neighbours reflowed around it via continuity).\n const carried =\n previewRef.current?.boardId === target!.id &&\n getLayoutItem(previewRef.current.working, ds.itemId)\n ? previewRef.current.working\n : null;\n\n let finalLayout: LayoutItem[];\n if (carried) {\n finalLayout = [...tc.compact(cloneLayout(carried), tp.cols)];\n } else {\n // No preview frame ran (e.g. a teleport drop). Seed the item just above\n // (or left of) its landing cell so `moveElement` actively places it\n // rather than no-opping and letting compaction sink it to the bottom.\n const newItem: LayoutItem =\n tc.type === 'horizontal'\n ? { ...ds.item, x: Math.max(0, landing.x) - 1, y: landing.y }\n : { ...ds.item, x: landing.x, y: Math.max(0, landing.y) - 1 };\n const base = [\n ...cloneLayout(\n (\n targetSnapshotsRef.current.get(target!.id) ?? target!.getLayout()\n ).filter((l) => l.i !== ds.itemId),\n ),\n newItem,\n ];\n const moved = moveElement(\n base,\n newItem,\n landing.x,\n landing.y,\n true,\n tc.preventCollision,\n tc.type,\n tp.cols,\n tc.allowOverlap,\n );\n finalLayout = [...tc.compact(moved, tp.cols)];\n }\n target!.applyLayout(finalLayout, true);\n\n // Signal the transfer so a controlled app can move the widget's\n // declaration into the destination container (positions are already\n // reported via each board's onLayoutChange).\n onTransferRef.current?.({\n widgetId: ds.itemId,\n fromBoardId: ds.sourceBoardId,\n toBoardId: target!.id,\n item: getLayoutItem(finalLayout, ds.itemId) ?? {\n ...ds.item,\n x: landing.x,\n y: landing.y,\n },\n });\n }\n\n const ids = new Set(affectedRef.current);\n ids.add(ds.sourceBoardId);\n ids.add(ds.currentBoardId);\n ids.forEach((id) => boardsRef.current.get(id)?.setPlaceholder(null));\n\n affectedRef.current.clear();\n sourceSnapshotRef.current = [];\n targetSnapshotsRef.current.clear();\n frozenRectsRef.current.clear();\n nestedInDraggedRef.current = new Set();\n previewRef.current = null;\n lastLandingRef.current = null;\n setDragState(null);\n });\n\n return useMemo(\n () => ({\n store,\n overlayRef,\n registerBoard,\n onDragStart,\n onDragMove,\n onDragEnd,\n dragState,\n }),\n [store, registerBoard, onDragStart, onDragMove, onDragEnd, dragState],\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { extractStyles } from "../../utils/styles.js";
|
|
3
3
|
import { CONTAINER_STYLES, filterBaseProps, tasty } from "@tenphi/tasty";
|
|
4
4
|
import { forwardRef } from "react";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { extractStyles } from "../../utils/styles.js";
|
|
3
3
|
import { CONTAINER_STYLES, filterBaseProps, tasty } from "@tenphi/tasty";
|
|
4
4
|
import { forwardRef } from "react";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { extractStyles } from "../../utils/styles.js";
|
|
3
3
|
import { CONTAINER_STYLES, filterBaseProps, tasty } from "@tenphi/tasty";
|
|
4
4
|
import { forwardRef } from "react";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { BASE_STYLES, BLOCK_STYLES, COLOR_STYLES, DIMENSION_STYLES, OUTER_STYLES, tasty } from "@tenphi/tasty";
|
|
3
3
|
import { forwardRef, useMemo } from "react";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | 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 { useCombinedRefs } from "../../utils/react/useCombinedRefs.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { mergeProps as mergeProps$1 } from "../../utils/react/mergeProps.js";
|
|
3
3
|
import { useCombinedRefs } from "../../utils/react/useCombinedRefs.js";
|
|
4
4
|
import { useEvent } from "../../_internal/hooks/use-event.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-
|
|
1
|
+
/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-ea72271 | Cube Dev Team */
|
|
2
2
|
import { extractStyles } from "../../utils/styles.js";
|
|
3
3
|
import { CONTAINER_STYLES, filterBaseProps, tasty } from "@tenphi/tasty";
|
|
4
4
|
import { forwardRef } from "react";
|