@cube-dev/ui-kit 0.66.1 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/es/_internal/hooks/index.js +1 -1
- package/es/_internal/hooks/use-chained-callback.js +1 -1
- package/es/_internal/hooks/use-debounced-value.js +1 -1
- package/es/_internal/hooks/use-deprecation-warning.js +1 -1
- package/es/_internal/hooks/use-effect-once.js +1 -1
- package/es/_internal/hooks/use-event.js +1 -1
- package/es/_internal/hooks/use-is-first-render.js +1 -1
- package/es/_internal/hooks/use-sync-ref.js +1 -1
- package/es/_internal/hooks/use-timer/index.js +1 -1
- package/es/_internal/hooks/use-timer/timer.js +1 -1
- package/es/_internal/hooks/use-timer/use-timer.js +1 -1
- package/es/_internal/hooks/use-update-effect.js +1 -1
- package/es/_internal/hooks/use-warn.js +1 -1
- package/es/_internal/index.js +1 -1
- package/es/components/Block.js +1 -1
- package/es/components/GlobalStyles.js +1 -1
- package/es/components/GridProvider.js +1 -1
- package/es/components/HiddenInput.js +1 -1
- package/es/components/OpenTrasition.js +1 -1
- package/es/components/Root.js +3 -2
- package/es/components/actions/Action/Action.js +1 -1
- package/es/components/actions/Button/Button.js +24 -21
- package/es/components/actions/Button/index.js +1 -1
- package/es/components/actions/ButtonGroup/ButtonGroup.js +1 -1
- package/es/components/actions/CommandMenu/CommandMenu.js +13 -23
- package/es/components/actions/CommandMenu/index.js +1 -1
- package/es/components/actions/CommandMenu/styled.js +1 -2
- package/es/components/actions/Menu/Menu.js +18 -13
- package/es/components/actions/Menu/MenuItem.js +2 -1
- package/es/components/actions/Menu/MenuSection.js +1 -1
- package/es/components/actions/Menu/MenuTrigger.js +48 -21
- package/es/components/actions/Menu/context.js +1 -1
- package/es/components/actions/Menu/index.js +1 -1
- package/es/components/actions/Menu/styled.js +47 -22
- package/es/components/actions/index.js +3 -1
- package/es/components/actions/use-action.js +1 -1
- package/es/components/actions/use-anchored-menu.js +98 -0
- package/es/components/actions/use-context-menu.js +206 -0
- package/es/components/content/ActiveZone/ActiveZone.js +1 -1
- package/es/components/content/Alert/Alert.js +1 -1
- package/es/components/content/Alert/index.js +1 -1
- package/es/components/content/Alert/types.js +1 -1
- package/es/components/content/Alert/use-alert.js +1 -1
- package/es/components/content/Avatar/Avatar.js +1 -1
- package/es/components/content/Badge/Badge.js +1 -1
- package/es/components/content/Card/Card.js +1 -1
- package/es/components/content/Content.js +1 -1
- package/es/components/content/CopyPasteBlock/CopyPasteBlock.js +1 -1
- package/es/components/content/CopyPasteBlock/index.js +1 -1
- package/es/components/content/CopySnippet/CopySnippet.js +1 -1
- package/es/components/content/CopySnippet/index.js +1 -1
- package/es/components/content/Divider.js +1 -1
- package/es/components/content/Footer.js +1 -1
- package/es/components/content/Header.js +1 -1
- package/es/components/content/HotKeys/HotKeys.js +1 -1
- package/es/components/content/HotKeys/index.js +1 -1
- package/es/components/content/Paragraph.js +1 -1
- package/es/components/content/Placeholder/Placeholder.js +1 -1
- package/es/components/content/PrismCode/PrismCode.js +1 -1
- package/es/components/content/PrismCode/prismSetup.js +1 -1
- package/es/components/content/PrismDiffCode/PrismDiffCode.js +1 -1
- package/es/components/content/Result/Result.js +1 -1
- package/es/components/content/Skeleton/Skeleton.js +1 -1
- package/es/components/content/Tag/Tag.js +2 -2
- package/es/components/content/Text.js +1 -1
- package/es/components/content/Title.js +1 -1
- package/es/components/fields/Checkbox/Checkbox.js +1 -1
- package/es/components/fields/Checkbox/CheckboxGroup.js +1 -1
- package/es/components/fields/Checkbox/context.js +1 -1
- package/es/components/fields/Checkbox/index.js +1 -1
- package/es/components/fields/ComboBox/ComboBox.js +25 -3
- package/es/components/fields/ComboBox/index.js +1 -1
- package/es/components/fields/DatePicker/DateInput.js +1 -1
- package/es/components/fields/DatePicker/DateInputBase.js +1 -1
- package/es/components/fields/DatePicker/DatePicker.js +1 -1
- package/es/components/fields/DatePicker/DatePickerButton.js +1 -1
- package/es/components/fields/DatePicker/DatePickerElement.js +1 -1
- package/es/components/fields/DatePicker/DatePickerInput.js +1 -1
- package/es/components/fields/DatePicker/DatePickerSegment.js +1 -1
- package/es/components/fields/DatePicker/DateRangePicker.js +1 -1
- package/es/components/fields/DatePicker/DateRangeSeparatedPicker.js +1 -1
- package/es/components/fields/DatePicker/TimeInput.js +1 -1
- package/es/components/fields/DatePicker/index.js +1 -1
- package/es/components/fields/DatePicker/intl.js +1 -1
- package/es/components/fields/DatePicker/parseDate.js +1 -1
- package/es/components/fields/DatePicker/props.js +1 -1
- package/es/components/fields/DatePicker/types.js +1 -1
- package/es/components/fields/DatePicker/utils.js +1 -1
- package/es/components/fields/FileInput/FileInput.js +1 -1
- package/es/components/fields/FilterListBox/FilterListBox.js +580 -0
- package/es/components/fields/FilterListBox/index.js +10 -0
- package/es/components/fields/FilterPicker/FilterPicker.js +426 -0
- package/es/components/fields/FilterPicker/index.js +10 -0
- package/es/components/fields/Input/Input.js +1 -1
- package/es/components/fields/Input/index.js +1 -1
- package/es/components/fields/ListBox/ListBox.js +324 -238
- package/es/components/fields/ListBox/index.js +1 -1
- package/es/components/fields/NumberInput/NumberInput.js +1 -1
- package/es/components/fields/NumberInput/StepButton.js +1 -1
- package/es/components/fields/PasswordInput/PasswordInput.js +1 -1
- package/es/components/fields/RadioGroup/Radio.js +1 -1
- package/es/components/fields/RadioGroup/RadioGroup.js +1 -1
- package/es/components/fields/RadioGroup/context.js +1 -1
- package/es/components/fields/RadioGroup/index.js +1 -1
- package/es/components/fields/SearchInput/SearchInput.js +1 -1
- package/es/components/fields/SearchInput/index.js +1 -1
- package/es/components/fields/Select/Select.js +48 -9
- package/es/components/fields/Select/index.js +1 -1
- package/es/components/fields/Slider/Gradation.js +1 -1
- package/es/components/fields/Slider/Header.js +1 -1
- package/es/components/fields/Slider/RangeSlider.js +1 -1
- package/es/components/fields/Slider/Slider.js +1 -1
- package/es/components/fields/Slider/SliderBase.js +4 -4
- package/es/components/fields/Slider/SliderInput.js +1 -1
- package/es/components/fields/Slider/SliderThumb.js +1 -1
- package/es/components/fields/Slider/SliderTrack.js +1 -1
- package/es/components/fields/Slider/elements.js +1 -1
- package/es/components/fields/Slider/index.js +1 -1
- package/es/components/fields/Slider/types.js +1 -1
- package/es/components/fields/Switch/Switch.js +1 -1
- package/es/components/fields/Switch/index.js +1 -1
- package/es/components/fields/TextArea/TextArea.js +1 -1
- package/es/components/fields/TextArea/index.js +1 -1
- package/es/components/fields/TextInput/TextInput.js +1 -1
- package/es/components/fields/TextInput/TextInputBase.js +1 -1
- package/es/components/fields/TextInput/index.js +1 -1
- package/es/components/fields/TextInputMapper/TextInputMapper.js +1 -1
- package/es/components/fields/TextInputMapper/index.js +1 -1
- package/es/components/fields/index.js +3 -1
- package/es/components/form/FieldWrapper/FieldWrapper.js +1 -1
- package/es/components/form/FieldWrapper/extract-field-wrapper-props.js +1 -1
- package/es/components/form/FieldWrapper/index.js +1 -1
- package/es/components/form/FieldWrapper/types.js +1 -1
- package/es/components/form/Form/Field.js +1 -1
- package/es/components/form/Form/Form.js +1 -1
- package/es/components/form/Form/ResetButton/ResetButton.js +1 -1
- package/es/components/form/Form/ResetButton/index.js +1 -1
- package/es/components/form/Form/SubmitButton/SubmitButton.js +1 -1
- package/es/components/form/Form/SubmitButton/index.js +1 -1
- package/es/components/form/Form/SubmitError.js +1 -1
- package/es/components/form/Form/index.js +1 -1
- package/es/components/form/Form/types.js +1 -1
- package/es/components/form/Form/use-field/index.js +1 -1
- package/es/components/form/Form/use-field/types.js +1 -1
- package/es/components/form/Form/use-field/use-field-props.js +1 -1
- package/es/components/form/Form/use-field/use-field.js +1 -1
- package/es/components/form/Form/use-form.js +1 -1
- package/es/components/form/Form/validation.js +1 -1
- package/es/components/form/Label.js +1 -1
- package/es/components/form/index.js +1 -1
- package/es/components/form/wrapper.js +5 -2
- package/es/components/layout/Flex.js +1 -1
- package/es/components/layout/Flow.js +1 -1
- package/es/components/layout/Grid.js +1 -1
- package/es/components/layout/Panel.js +1 -1
- package/es/components/layout/Prefix.js +1 -1
- package/es/components/layout/ResizablePanel.js +1 -1
- package/es/components/layout/Space.js +1 -1
- package/es/components/layout/Suffix.js +1 -1
- package/es/components/navigation/LegacyTabs/LegacyTabs.js +1 -1
- package/es/components/navigation/Link/Link.js +1 -1
- package/es/components/organisms/FileTabs/FileTabs.js +1 -1
- package/es/components/organisms/Modal/Modal.js +1 -1
- package/es/components/organisms/StatsCard/StatsCard.js +1 -1
- package/es/components/other/Base64Upload/Base64Upload.js +1 -1
- package/es/components/other/Calendar/Calendar.js +1 -1
- package/es/components/other/Calendar/CalendarCell.js +1 -1
- package/es/components/other/Calendar/CalendarGrid.js +1 -1
- package/es/components/other/Calendar/RangeCalendar.js +1 -1
- package/es/components/other/CloudLogo/CloudLogo.js +1 -1
- package/es/components/overlays/AlertDialog/AlertDialog.js +1 -1
- package/es/components/overlays/AlertDialog/AlertDialogApiProvider.js +1 -1
- package/es/components/overlays/AlertDialog/AlertDialogZone.js +1 -1
- package/es/components/overlays/AlertDialog/index.js +1 -1
- package/es/components/overlays/AlertDialog/types.js +1 -1
- package/es/components/overlays/Dialog/Dialog.js +1 -1
- package/es/components/overlays/Dialog/DialogContainer.js +1 -1
- package/es/components/overlays/Dialog/DialogForm.js +1 -1
- package/es/components/overlays/Dialog/DialogTrigger.js +1 -1
- package/es/components/overlays/Dialog/context.js +1 -1
- package/es/components/overlays/Dialog/index.js +2 -2
- package/es/components/overlays/Dialog/{dialog-container.js → use-dialog-container.js} +3 -3
- package/es/components/overlays/Modal/Modal.js +1 -1
- package/es/components/overlays/Modal/OpenTransition.js +1 -1
- package/es/components/overlays/Modal/Overlay.js +1 -1
- package/es/components/overlays/Modal/Popover.js +1 -1
- package/es/components/overlays/Modal/Tray.js +1 -1
- package/es/components/overlays/Modal/Underlay.js +1 -1
- package/es/components/overlays/Modal/index.js +1 -1
- package/es/components/overlays/Modal/types.js +1 -1
- package/es/components/overlays/NewNotifications/Bar/FloatingNotification.js +1 -1
- package/es/components/overlays/NewNotifications/Bar/NotificationsBar.js +1 -1
- package/es/components/overlays/NewNotifications/Bar/TransitionComponent.js +1 -1
- package/es/components/overlays/NewNotifications/Bar/index.js +1 -1
- package/es/components/overlays/NewNotifications/Dialog/NotificationsDialogTrigger.js +1 -1
- package/es/components/overlays/NewNotifications/Dialog/index.js +1 -1
- package/es/components/overlays/NewNotifications/Notification.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationAction.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationCloseButton.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationDescription.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationFooter.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationHeader.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationIcon.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationProvider.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/NotificationView.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/index.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationView/types.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsContext/NotificationsContext.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsContext/NotificationsProvider.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsContext/index.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsContext/use-notifications.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsList/NotificationsList.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsList/NotificationsListItem.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsList/index.js +1 -1
- package/es/components/overlays/NewNotifications/NotificationsList/types.js +1 -1
- package/es/components/overlays/NewNotifications/hooks/index.js +1 -1
- package/es/components/overlays/NewNotifications/hooks/types.js +1 -1
- package/es/components/overlays/NewNotifications/hooks/use-notification-list-item.js +1 -1
- package/es/components/overlays/NewNotifications/hooks/use-notifications-api.js +1 -1
- package/es/components/overlays/NewNotifications/hooks/use-notifications-list.js +1 -1
- package/es/components/overlays/NewNotifications/hooks/use-notifications-observer.js +1 -1
- package/es/components/overlays/NewNotifications/index.js +1 -1
- package/es/components/overlays/NewNotifications/types.js +1 -1
- package/es/components/overlays/Notification/Notification.js +1 -1
- package/es/components/overlays/OverlayWrapper.js +1 -1
- package/es/components/overlays/Toasts/Toast.js +1 -1
- package/es/components/overlays/Toasts/index.js +1 -1
- package/es/components/overlays/Toasts/types.js +1 -1
- package/es/components/overlays/Toasts/use-toasts-api.js +1 -1
- package/es/components/overlays/Tooltip/Tooltip.js +1 -1
- package/es/components/overlays/Tooltip/TooltipProvider.js +1 -1
- package/es/components/overlays/Tooltip/TooltipTrigger.js +1 -1
- package/es/components/overlays/Tooltip/context.js +1 -1
- package/es/components/overlays/Tooltip/index.js +1 -1
- package/es/components/portal/Portal.js +1 -1
- package/es/components/portal/PortalProvider.js +1 -1
- package/es/components/portal/index.js +1 -1
- package/es/components/portal/storybook/templates/CustomRoot.js +1 -1
- package/es/components/portal/storybook/templates/PortalOrder.js +1 -1
- package/es/components/portal/storybook/templates/basic.js +1 -1
- package/es/components/portal/storybook/templates/index.js +1 -1
- package/es/components/portal/types.js +1 -1
- package/es/components/portal/usePortal.js +1 -1
- package/es/components/shared/InvalidIcon.js +1 -1
- package/es/components/shared/ValidIcon.js +1 -1
- package/es/components/status/LoadingAnimation/LoadingAnimation.js +1 -1
- package/es/components/status/LoadingAnimation/index.js +1 -1
- package/es/components/status/Spin/Cube.js +1 -1
- package/es/components/status/Spin/InternalSpinner.js +1 -1
- package/es/components/status/Spin/Spin.js +1 -1
- package/es/components/status/Spin/SpinsContainer.js +1 -1
- package/es/components/status/Spin/index.js +1 -1
- package/es/components/status/Spin/types.js +1 -1
- package/es/components/status/index.js +1 -1
- package/es/data/themes.js +1 -1
- package/es/icons/AdjustmentsHorizontalIcon.js +1 -1
- package/es/icons/AdjustmentsIcon.js +1 -1
- package/es/icons/AiIcon.js +1 -1
- package/es/icons/AreaChartIcon.js +1 -1
- package/es/icons/BackwardIcon.js +1 -1
- package/es/icons/BarChartIcon.js +1 -1
- package/es/icons/BellFilledIcon.js +1 -1
- package/es/icons/BellIcon.js +1 -1
- package/es/icons/BooleanIcon.js +1 -1
- package/es/icons/CalendarEditIcon.js +1 -1
- package/es/icons/CalendarIcon.js +1 -1
- package/es/icons/CaretDownIcon.js +1 -1
- package/es/icons/CaretUpIcon.js +1 -1
- package/es/icons/ChartAreaStackedIcon.js +1 -1
- package/es/icons/ChartAreaStackedPercentageIcon.js +1 -1
- package/es/icons/ChartBarGroupedHorizontalIcon.js +1 -1
- package/es/icons/ChartBarGroupedIcon.js +1 -1
- package/es/icons/ChartBarHorizontalIcon.js +1 -1
- package/es/icons/ChartBarLineIcon.js +1 -1
- package/es/icons/ChartBarStackedHorizontalIcon.js +1 -1
- package/es/icons/ChartBarStackedIcon.js +1 -1
- package/es/icons/ChartBarStackedPercentageHorizontalIcon.js +1 -1
- package/es/icons/ChartBarStackedPercentageIcon.js +1 -1
- package/es/icons/ChartBoxPlot2Icon.js +1 -1
- package/es/icons/ChartBoxPlotIcon.js +1 -1
- package/es/icons/ChartBubbleIcon.js +1 -1
- package/es/icons/ChartDonut2Icon.js +1 -1
- package/es/icons/ChartFunnelIcon.js +1 -1
- package/es/icons/ChartKPIIcon.js +12 -0
- package/es/icons/ChartPie2Icon.js +1 -1
- package/es/icons/ChartScatterIcon.js +1 -1
- package/es/icons/CheckCircleFilledIcon.js +1 -1
- package/es/icons/CheckCircleIcon.js +1 -1
- package/es/icons/CheckIcon.js +1 -1
- package/es/icons/CircleFilledIcon.js +1 -1
- package/es/icons/ClearIcon.js +1 -1
- package/es/icons/CloseCircleFilledIcon.js +1 -1
- package/es/icons/CloseCircleIcon.js +1 -1
- package/es/icons/CloseIcon.js +1 -1
- package/es/icons/CodeIcon.js +1 -1
- package/es/icons/CopyIcon.js +1 -1
- package/es/icons/CountIcon.js +1 -1
- package/es/icons/CubeIcon.js +1 -1
- package/es/icons/DangerIcon.js +1 -1
- package/es/icons/DashboardIcon.js +1 -1
- package/es/icons/DatabaseIcon.js +1 -1
- package/es/icons/DirectionIcon.js +1 -1
- package/es/icons/DonutIcon.js +1 -1
- package/es/icons/DownIcon.js +1 -1
- package/es/icons/EditIcon.js +1 -1
- package/es/icons/ExclamationCircleFilledIcon.js +1 -1
- package/es/icons/ExclamationCircleIcon.js +1 -1
- package/es/icons/ExclamationIcon.js +1 -1
- package/es/icons/EyeIcon.js +1 -1
- package/es/icons/EyeInvisibleIcon.js +1 -1
- package/es/icons/FilterIcon.js +1 -1
- package/es/icons/FolderFilledIcon.js +1 -1
- package/es/icons/FolderIcon.js +1 -1
- package/es/icons/FolderOpenFilledIcon.js +1 -1
- package/es/icons/FolderOpenIcon.js +1 -1
- package/es/icons/ForwardIcon.js +1 -1
- package/es/icons/HierarchyIcon.js +1 -1
- package/es/icons/Icon.js +1 -1
- package/es/icons/InfoCircleIcon.js +1 -1
- package/es/icons/InfoIcon.js +1 -1
- package/es/icons/KeyIcon.js +1 -1
- package/es/icons/LeftIcon.js +1 -1
- package/es/icons/LineChartIcon.js +1 -1
- package/es/icons/LoadingIcon.js +1 -1
- package/es/icons/LockFilledIcon.js +1 -1
- package/es/icons/LockIcon.js +1 -1
- package/es/icons/MoreIcon.js +1 -1
- package/es/icons/NotAllowedIcon.js +1 -1
- package/es/icons/NumberIcon.js +1 -1
- package/es/icons/PauseCircleFilledIcon.js +1 -1
- package/es/icons/PauseCircleIcon.js +1 -1
- package/es/icons/PauseIcon.js +1 -1
- package/es/icons/PieChartIcon.js +1 -1
- package/es/icons/PlayCircleIcon.js +1 -1
- package/es/icons/PlayIcon.js +1 -1
- package/es/icons/PlusIcon.js +1 -1
- package/es/icons/ReloadIcon.js +1 -1
- package/es/icons/ReportIcon.js +1 -1
- package/es/icons/ReturnIcon.js +1 -1
- package/es/icons/RightIcon.js +1 -1
- package/es/icons/SchemeIcon.js +1 -1
- package/es/icons/SearchIcon.js +1 -1
- package/es/icons/SettingsIcon.js +1 -1
- package/es/icons/ShieldFilledIcon.js +1 -1
- package/es/icons/ShieldIcon.js +1 -1
- package/es/icons/SlashIcon.js +1 -1
- package/es/icons/SparklesIcon.js +1 -1
- package/es/icons/SqlIcon.js +1 -1
- package/es/icons/StatsIcon.js +1 -1
- package/es/icons/StopIcon.js +1 -1
- package/es/icons/StringIcon.js +1 -1
- package/es/icons/SwitchIcon.js +1 -1
- package/es/icons/TableIcon.js +1 -1
- package/es/icons/ThumbsDownIcon.js +1 -1
- package/es/icons/ThumbsUpIcon.js +1 -1
- package/es/icons/ThunderboltCrossedIcon.js +1 -1
- package/es/icons/ThunderboltFilledIcon.js +1 -1
- package/es/icons/ThunderboltIcon.js +1 -1
- package/es/icons/TimeIcon.js +1 -1
- package/es/icons/UnlockIcon.js +1 -1
- package/es/icons/UpIcon.js +1 -1
- package/es/icons/UserGroupIcon.js +1 -1
- package/es/icons/UserIcon.js +1 -1
- package/es/icons/UserLockIcon.js +1 -1
- package/es/icons/ViewIcon.js +1 -1
- package/es/icons/WarningFilledIcon.js +1 -1
- package/es/icons/WarningIcon.js +1 -1
- package/es/icons/add-new-icon.js +1 -1
- package/es/icons/index.js +2 -1
- package/es/icons/wrap-icon.js +1 -1
- package/es/index.js +1 -1
- package/es/provider.js +4 -1
- package/es/providers/TrackingProvider.js +1 -1
- package/es/services/notification.js +1 -1
- package/es/shared/form.js +1 -1
- package/es/shared/index.js +1 -1
- package/es/stories/Form.legacy-stories.js +1 -1
- package/es/stories/FormFieldArgs.js +1 -1
- package/es/stories/Layout.stories.js +1 -1
- package/es/stories/Tasty.stories.js +1 -1
- package/es/stories/components/ConfirmDeletionDialogForm.js +1 -1
- package/es/stories/components/DialogFormApp.js +1 -1
- package/es/stories/components/StyledButton.js +1 -1
- package/es/stories/lists/baseProps.js +1 -1
- package/es/tasty/index.js +1 -1
- package/es/tasty/providers/BreakpointsProvider.js +1 -1
- package/es/tasty/styles/align.js +1 -1
- package/es/tasty/styles/border.js +1 -1
- package/es/tasty/styles/boxShadow.combinator.js +1 -1
- package/es/tasty/styles/color.js +1 -1
- package/es/tasty/styles/createStyle.js +1 -1
- package/es/tasty/styles/dimension.js +1 -1
- package/es/tasty/styles/display.js +1 -1
- package/es/tasty/styles/fade.js +1 -1
- package/es/tasty/styles/fill.js +1 -1
- package/es/tasty/styles/flow.js +1 -1
- package/es/tasty/styles/font.js +1 -1
- package/es/tasty/styles/fontStyle.js +1 -1
- package/es/tasty/styles/gap.js +1 -1
- package/es/tasty/styles/groupRadius.js +1 -1
- package/es/tasty/styles/height.js +1 -1
- package/es/tasty/styles/index.js +1 -1
- package/es/tasty/styles/inset.js +1 -1
- package/es/tasty/styles/justify.js +1 -1
- package/es/tasty/styles/list.js +1 -1
- package/es/tasty/styles/margin.js +1 -1
- package/es/tasty/styles/marginBlock.js +1 -1
- package/es/tasty/styles/marginInline.js +1 -1
- package/es/tasty/styles/outline.js +1 -1
- package/es/tasty/styles/padding.js +1 -1
- package/es/tasty/styles/paddingBlock.js +1 -1
- package/es/tasty/styles/paddingInline.js +1 -1
- package/es/tasty/styles/place.js +1 -1
- package/es/tasty/styles/predefined.js +1 -1
- package/es/tasty/styles/preset.js +1 -1
- package/es/tasty/styles/radius.js +1 -1
- package/es/tasty/styles/reset.js +1 -1
- package/es/tasty/styles/scrollbar.js +1 -1
- package/es/tasty/styles/shadow.js +1 -1
- package/es/tasty/styles/styledScrollbar.js +1 -1
- package/es/tasty/styles/transition.js +1 -1
- package/es/tasty/styles/types.js +1 -1
- package/es/tasty/styles/width.js +1 -1
- package/es/tasty/tasty.js +1 -1
- package/es/tasty/types.js +1 -1
- package/es/tasty/utils/cache-wrapper.js +1 -1
- package/es/tasty/utils/case-converter.js +1 -1
- package/es/tasty/utils/colors.js +1 -1
- package/es/tasty/utils/dotize.js +1 -1
- package/es/tasty/utils/filterBaseProps.js +1 -1
- package/es/tasty/utils/getDisplayName.js +1 -1
- package/es/tasty/utils/getModCombinations.js +1 -1
- package/es/tasty/utils/mergeStyles.js +1 -1
- package/es/tasty/utils/modAttrs.js +1 -1
- package/es/tasty/utils/renderStyles.js +1 -1
- package/es/tasty/utils/responsive.js +1 -1
- package/es/tasty/utils/string.js +1 -1
- package/es/tasty/utils/styles.js +4 -1
- package/es/tasty/utils/warnings.js +1 -1
- package/es/tokens.js +1 -1
- package/es/type-checks.js +1 -1
- package/es/utils/ResizeSensor.js +1 -1
- package/es/utils/modules.js +1 -1
- package/es/utils/promise.js +1 -1
- package/es/utils/random.js +7 -1
- package/es/utils/range.js +1 -1
- package/es/utils/react/Slots.js +1 -1
- package/es/utils/react/chain.js +1 -1
- package/es/utils/react/index.js +3 -1
- package/es/utils/react/interactions.js +1 -1
- package/es/utils/react/isTextOnly.js +1 -1
- package/es/utils/react/mapProps.js +1 -1
- package/es/utils/react/mergeProps.js +1 -1
- package/es/utils/react/nullableValue.js +1 -1
- package/es/utils/react/sharedStore.js +51 -0
- package/es/utils/react/useCombinedRefs.js +1 -1
- package/es/utils/react/useControlledFocusVisible.js +42 -0
- package/es/utils/react/useEventBus.js +124 -0
- package/es/utils/react/useId.js +1 -1
- package/es/utils/react/useIsDarwin.js +1 -1
- package/es/utils/react/useKeySymbols.js +1 -1
- package/es/utils/react/useLayoutEffect.js +1 -1
- package/es/utils/react/useQaProps.js +1 -1
- package/es/utils/react/useViewportSize.js +1 -1
- package/es/utils/react/wrapNodeIfPlain.js +1 -1
- package/es/utils/transitions.js +1 -1
- package/es/utils/tree.js +1 -1
- package/es/utils/warnings.js +1 -1
- package/es/version.js +2 -2
- package/package.json +2 -1
- package/types/components/actions/Button/Button.d.ts +8 -5
- package/types/components/actions/Menu/Menu.d.ts +3 -0
- package/types/components/actions/Menu/MenuItem.d.ts +1 -1
- package/types/components/actions/Menu/MenuTrigger.d.ts +2 -3
- package/types/components/actions/Menu/styled.d.ts +1 -0
- package/types/components/actions/index.d.ts +2 -0
- package/types/components/actions/use-anchored-menu.d.ts +34 -0
- package/types/components/actions/use-context-menu.d.ts +42 -0
- package/types/components/content/Card/Card.d.ts +2 -2
- package/types/components/content/CopyPasteBlock/CopyPasteBlock.d.ts +1 -1
- package/types/components/fields/FilterListBox/FilterListBox.d.ts +51 -0
- package/types/components/fields/FilterListBox/index.d.ts +1 -0
- package/types/components/fields/FilterPicker/FilterPicker.d.ts +55 -0
- package/types/components/fields/FilterPicker/index.d.ts +1 -0
- package/types/components/fields/ListBox/ListBox.d.ts +48 -22
- package/types/components/fields/Select/Select.d.ts +8 -1
- package/types/components/fields/index.d.ts +2 -0
- package/types/components/overlays/Dialog/index.d.ts +1 -1
- package/types/icons/ChartKPIIcon.d.ts +4 -0
- package/types/icons/index.d.ts +1 -0
- package/types/shared/form.d.ts +2 -0
- package/types/tasty/utils/styles.d.ts +1 -0
- package/types/utils/random.d.ts +4 -0
- package/types/utils/react/index.d.ts +4 -0
- package/types/utils/react/sharedStore.d.ts +11 -0
- package/types/utils/react/useControlledFocusVisible.d.ts +10 -0
- package/types/utils/react/useEventBus.d.ts +74 -0
- /package/types/components/overlays/Dialog/{dialog-container.d.ts → use-dialog-container.d.ts} +0 -0
@@ -1,48 +1,58 @@
|
|
1
1
|
/**
|
2
2
|
* @license MIT
|
3
3
|
* author: Cube Dev Team
|
4
|
-
* @cube-dev/ui-kit v0.
|
4
|
+
* @cube-dev/ui-kit v0.68.0
|
5
5
|
* Released under the MIT license.
|
6
6
|
*/
|
7
7
|
|
8
8
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
9
9
|
import { PressResponder } from '@react-aria/interactions';
|
10
10
|
import { useDOMRef, useIsMobileDevice } from '@react-spectrum/utils';
|
11
|
-
import { forwardRef, Fragment, useRef } from 'react';
|
11
|
+
import { forwardRef, Fragment, useEffect, useMemo, useRef, } from 'react';
|
12
12
|
import { DismissButton, useMenuTrigger, useOverlayPosition, } from 'react-aria';
|
13
13
|
import { useMenuTriggerState } from 'react-stately';
|
14
|
+
import { generateRandomId } from '../../../utils/random';
|
14
15
|
import { SlotProvider } from '../../../utils/react';
|
16
|
+
import { useEventBus } from '../../../utils/react/useEventBus';
|
15
17
|
import { Popover, Tray } from '../../overlays/Modal';
|
16
18
|
import { MenuContext } from './context';
|
17
19
|
function MenuTrigger(props, ref) {
|
18
20
|
const menuPopoverRef = useRef(null);
|
19
21
|
const triggerRef = useRef();
|
20
22
|
const domRef = useDOMRef(ref);
|
21
|
-
const menuTriggerRef = domRef || triggerRef;
|
23
|
+
const menuTriggerRef = props.targetRef || domRef || triggerRef;
|
22
24
|
const menuRef = useRef(null);
|
23
|
-
const { children,
|
25
|
+
const { children, shouldFlip = true, closeOnSelect, trigger = 'press', isDisabled, isDummy, } = props;
|
26
|
+
// Generate a unique ID for this menu instance
|
27
|
+
const menuId = useMemo(() => generateRandomId(), []);
|
28
|
+
// Get event bus for menu synchronization
|
29
|
+
const { emit, on } = useEventBus();
|
24
30
|
if (!Array.isArray(children) || children.length > 2) {
|
25
31
|
throw new Error('MenuTrigger must have exactly 2 children');
|
26
32
|
}
|
27
33
|
let [menuTrigger, menu] = children;
|
28
34
|
const state = useMenuTriggerState(props);
|
35
|
+
// Listen for other menus opening and close this one if needed
|
36
|
+
useEffect(() => {
|
37
|
+
const unsubscribe = on('menu:open', (data) => {
|
38
|
+
// If another menu is opening and this menu is open, close this one
|
39
|
+
if (data.menuId !== menuId && state.isOpen && !isDummy) {
|
40
|
+
state.close();
|
41
|
+
}
|
42
|
+
});
|
43
|
+
return unsubscribe;
|
44
|
+
}, [on, menuId, state]);
|
45
|
+
// Emit event when this menu opens
|
46
|
+
useEffect(() => {
|
47
|
+
if (state.isOpen && !isDummy) {
|
48
|
+
emit('menu:open', { menuId });
|
49
|
+
}
|
50
|
+
}, [state.isOpen, emit, menuId, isDummy]);
|
29
51
|
if (typeof menuTrigger === 'function') {
|
30
52
|
menuTrigger = menuTrigger(state);
|
31
53
|
}
|
32
54
|
const { menuTriggerProps, menuProps } = useMenuTrigger({ isDisabled }, state, menuTriggerRef);
|
33
|
-
let initialPlacement;
|
34
|
-
switch (direction) {
|
35
|
-
case 'left':
|
36
|
-
case 'right':
|
37
|
-
case 'start':
|
38
|
-
case 'end':
|
39
|
-
initialPlacement = `${direction} ${align === 'end' ? 'bottom' : 'top'}`;
|
40
|
-
break;
|
41
|
-
case 'bottom':
|
42
|
-
case 'top':
|
43
|
-
default:
|
44
|
-
initialPlacement = `${direction} ${align}`;
|
45
|
-
}
|
55
|
+
let initialPlacement = props.placement ?? 'bottom start';
|
46
56
|
const isMobile = useIsMobileDevice();
|
47
57
|
const { overlayProps: positionProps, placement } = useOverlayPosition({
|
48
58
|
targetRef: menuTriggerRef,
|
@@ -53,8 +63,8 @@ function MenuTrigger(props, ref) {
|
|
53
63
|
isOpen: state.isOpen && !isMobile,
|
54
64
|
onClose: state.close,
|
55
65
|
containerPadding: props.containerPadding,
|
56
|
-
offset: props.offset
|
57
|
-
crossOffset: props.crossOffset,
|
66
|
+
offset: props.offset ?? 8,
|
67
|
+
crossOffset: props.crossOffset ?? 0,
|
58
68
|
});
|
59
69
|
const menuContext = {
|
60
70
|
...menuProps,
|
@@ -80,9 +90,26 @@ function MenuTrigger(props, ref) {
|
|
80
90
|
overlay = (_jsx(Tray, { isOpen: state.isOpen, onClose: state.close, children: contents }));
|
81
91
|
}
|
82
92
|
else {
|
83
|
-
overlay = (_jsx(Popover, { ref: menuPopoverRef, hideArrow: true, isNonModal: true, isOpen: state.isOpen, style: positionProps.style, placement: placement,
|
93
|
+
overlay = (_jsx(Popover, { ref: menuPopoverRef, hideArrow: true, isNonModal: true, isOpen: state.isOpen, style: positionProps.style, placement: placement, shouldCloseOnInteractOutside: (el) => {
|
94
|
+
const menuTriggerEl = el.closest('[data-menu-trigger]');
|
95
|
+
// If no menu trigger was clicked, allow closing
|
96
|
+
if (!menuTriggerEl)
|
97
|
+
return true;
|
98
|
+
// For dummy triggers (like useAnchoredMenu), check if the clicked element
|
99
|
+
// is the target element or its descendant
|
100
|
+
if (isDummy &&
|
101
|
+
(menuTriggerEl === menuTriggerRef.current ||
|
102
|
+
menuTriggerRef.current?.contains(el))) {
|
103
|
+
return true;
|
104
|
+
}
|
105
|
+
// If the same trigger that opened this menu was clicked, allow closing
|
106
|
+
if (menuTriggerEl === menuTriggerRef.current)
|
107
|
+
return true;
|
108
|
+
// Otherwise, don't close (let event mechanism handle it)
|
109
|
+
return false;
|
110
|
+
}, onClose: state.close, children: contents }));
|
84
111
|
}
|
85
|
-
return (_jsxs(Fragment, { children: [_jsx(SlotProvider, { slots: { actionButton: { holdAffordance: trigger === 'longPress' } }, children: _jsx(PressResponder, { ...menuTriggerProps, ref: menuTriggerRef, isPressed: state.isOpen, children: menuTrigger }) }), _jsx(MenuContext.Provider, { value: menuContext, children: overlay })] }));
|
112
|
+
return (_jsxs(Fragment, { children: [_jsx(SlotProvider, { slots: { actionButton: { holdAffordance: trigger === 'longPress' } }, children: !isDummy ? (_jsx(PressResponder, { ...menuTriggerProps, ref: menuTriggerRef, "data-menu-trigger": true, isPressed: state.isOpen, children: menuTrigger })) : null }), _jsx(MenuContext.Provider, { value: menuContext, children: overlay })] }));
|
86
113
|
}
|
87
114
|
/**
|
88
115
|
* The MenuTrigger serves as a wrapper around a Menu and its associated trigger,
|
@@ -1,16 +1,38 @@
|
|
1
1
|
/**
|
2
2
|
* @license MIT
|
3
3
|
* author: Cube Dev Team
|
4
|
-
* @cube-dev/ui-kit v0.
|
4
|
+
* @cube-dev/ui-kit v0.68.0
|
5
5
|
* Released under the MIT license.
|
6
6
|
*/
|
7
7
|
|
8
8
|
import { DEFAULT_BUTTON_STYLES, DEFAULT_NEUTRAL_STYLES } from '..';
|
9
9
|
import { tasty } from '../../../tasty';
|
10
10
|
import { Space } from '../../layout/Space';
|
11
|
+
export const StyledMenuWrapper = tasty({
|
12
|
+
qa: 'Menu',
|
13
|
+
styles: {
|
14
|
+
display: 'grid',
|
15
|
+
gridRows: 'max-content 1sf max-content',
|
16
|
+
fill: '#white',
|
17
|
+
margin: 0,
|
18
|
+
padding: 0,
|
19
|
+
border: true,
|
20
|
+
radius: '(1cr + 1bw)',
|
21
|
+
shadow: {
|
22
|
+
'': '',
|
23
|
+
'popover | tray': '0px 5px 15px #dark.05',
|
24
|
+
},
|
25
|
+
height: {
|
26
|
+
'': 'initial',
|
27
|
+
popover: 'initial max-content (50vh - 4x)',
|
28
|
+
tray: 'initial max-content (100vh - 4x)',
|
29
|
+
},
|
30
|
+
boxSizing: 'border-box',
|
31
|
+
},
|
32
|
+
});
|
11
33
|
export const StyledMenu = tasty({
|
12
34
|
as: 'ul',
|
13
|
-
qa: '
|
35
|
+
qa: 'MenuList',
|
14
36
|
styles: {
|
15
37
|
display: 'flex',
|
16
38
|
flow: 'column',
|
@@ -18,7 +40,7 @@ export const StyledMenu = tasty({
|
|
18
40
|
'': '1bw',
|
19
41
|
sections: false,
|
20
42
|
},
|
21
|
-
|
43
|
+
boxSizing: 'border-box',
|
22
44
|
margin: 0,
|
23
45
|
padding: {
|
24
46
|
'': '0.5x',
|
@@ -28,15 +50,6 @@ export const StyledMenu = tasty({
|
|
28
50
|
'': 'auto',
|
29
51
|
section: '',
|
30
52
|
},
|
31
|
-
border: {
|
32
|
-
'': '#border',
|
33
|
-
section: false,
|
34
|
-
},
|
35
|
-
radius: '(1cr + 1bw)',
|
36
|
-
boxShadow: {
|
37
|
-
'': '',
|
38
|
-
popover: '0px 5px 15px #dark.05',
|
39
|
-
},
|
40
53
|
scrollbar: 'styled',
|
41
54
|
},
|
42
55
|
});
|
@@ -56,28 +69,40 @@ export const StyledDivider = tasty({
|
|
56
69
|
export const StyledHeader = tasty(Space, {
|
57
70
|
qa: 'Header',
|
58
71
|
as: 'div',
|
72
|
+
role: 'heading',
|
73
|
+
'aria-level': 3,
|
59
74
|
styles: {
|
60
75
|
color: '#dark-02',
|
61
76
|
preset: 't3',
|
62
77
|
placeContent: 'space-between',
|
63
78
|
placeItems: 'center',
|
64
79
|
whiteSpace: 'nowrap',
|
65
|
-
padding: '.5x
|
66
|
-
height:
|
80
|
+
padding: '.5x 1.5x',
|
81
|
+
height: {
|
82
|
+
'': 'min 4x',
|
83
|
+
'[data-size="medium"]': 'min 5x',
|
84
|
+
},
|
85
|
+
boxSizing: 'border-box',
|
86
|
+
border: 'bottom',
|
67
87
|
},
|
68
88
|
});
|
69
89
|
export const StyledFooter = tasty(Space, {
|
70
90
|
qa: 'Footer',
|
71
91
|
as: 'div',
|
92
|
+
role: 'footer',
|
72
93
|
styles: {
|
73
94
|
color: '#dark-02',
|
74
95
|
preset: 't3',
|
75
|
-
border: '#border top',
|
76
96
|
placeContent: 'space-between',
|
77
97
|
placeItems: 'center',
|
78
98
|
whiteSpace: 'nowrap',
|
79
|
-
padding: '.5x
|
80
|
-
height:
|
99
|
+
padding: '.5x 1.5x',
|
100
|
+
height: {
|
101
|
+
'': 'min 4x',
|
102
|
+
'[data-size="medium"]': 'min 5x',
|
103
|
+
},
|
104
|
+
boxSizing: 'border-box',
|
105
|
+
border: 'top',
|
81
106
|
},
|
82
107
|
});
|
83
108
|
export const StyledSection = tasty({
|
@@ -114,9 +139,9 @@ export const StyledItem = tasty({
|
|
114
139
|
fill: {
|
115
140
|
'': '#clear',
|
116
141
|
focused: '#dark.03',
|
117
|
-
selected: '#dark.
|
118
|
-
'selected & focused': '#dark.
|
119
|
-
pressed: '#dark.
|
142
|
+
selected: '#dark.09',
|
143
|
+
'selected & focused': '#dark.12',
|
144
|
+
pressed: '#dark.09',
|
120
145
|
disabled: '#clear',
|
121
146
|
},
|
122
147
|
color: {
|
@@ -125,8 +150,8 @@ export const StyledItem = tasty({
|
|
125
150
|
disabled: '#dark-04',
|
126
151
|
},
|
127
152
|
cursor: {
|
128
|
-
'': '
|
129
|
-
disabled: '
|
153
|
+
'': 'default',
|
154
|
+
disabled: 'not-allowed',
|
130
155
|
},
|
131
156
|
shadow: '#clear',
|
132
157
|
padding: {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @license MIT
|
3
3
|
* author: Cube Dev Team
|
4
|
-
* @cube-dev/ui-kit v0.
|
4
|
+
* @cube-dev/ui-kit v0.68.0
|
5
5
|
* Released under the MIT license.
|
6
6
|
*/
|
7
7
|
|
@@ -13,6 +13,8 @@ export * from './Action/Action';
|
|
13
13
|
export * from './Menu';
|
14
14
|
export * from './CommandMenu';
|
15
15
|
export * from './use-action';
|
16
|
+
export * from './use-anchored-menu';
|
17
|
+
export * from './use-context-menu';
|
16
18
|
export { Button, ButtonGroup };
|
17
19
|
|
18
20
|
|
@@ -0,0 +1,98 @@
|
|
1
|
+
/**
|
2
|
+
* @license MIT
|
3
|
+
* author: Cube Dev Team
|
4
|
+
* @cube-dev/ui-kit v0.68.0
|
5
|
+
* Released under the MIT license.
|
6
|
+
*/
|
7
|
+
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
9
|
+
import { Pressable } from '@react-aria/interactions';
|
10
|
+
import { useEffect, useMemo, useRef, useState, } from 'react';
|
11
|
+
import { VisuallyHidden } from 'react-aria';
|
12
|
+
import { useEvent } from '../../_internal';
|
13
|
+
import { generateRandomId } from '../../utils/random';
|
14
|
+
import { mergeProps } from '../../utils/react';
|
15
|
+
import { useEventBus } from '../../utils/react/useEventBus';
|
16
|
+
import { MenuTrigger } from './Menu';
|
17
|
+
/**
|
18
|
+
* Generic hook to manage an anchored menu component.
|
19
|
+
*
|
20
|
+
* @param Component - A React component that represents the menu content (Menu or CommandMenu).
|
21
|
+
* @param defaultTriggerProps - Default props to pass to the MenuTrigger.
|
22
|
+
* @returns An object with `anchorRef` to position the menu, `open` function to open the menu with provided props, `close` function to close the menu, and `rendered` JSX element to include in your component tree.
|
23
|
+
*/
|
24
|
+
export function useAnchoredMenu(Component, defaultTriggerProps) {
|
25
|
+
const [isOpen, setIsOpen] = useState(false);
|
26
|
+
const [componentProps, setComponentProps] = useState(null);
|
27
|
+
const [triggerProps, setTriggerProps] = useState(null);
|
28
|
+
const anchorRef = useRef(null);
|
29
|
+
const setupRef = useRef(false);
|
30
|
+
useEffect(() => {
|
31
|
+
const el = anchorRef.current;
|
32
|
+
if (el) {
|
33
|
+
el.dataset.menuTrigger = '';
|
34
|
+
return () => {
|
35
|
+
delete el.dataset.menuTrigger;
|
36
|
+
};
|
37
|
+
}
|
38
|
+
}, []);
|
39
|
+
// Generate a unique ID for this menu instance
|
40
|
+
const menuId = useMemo(() => generateRandomId(), []);
|
41
|
+
// Get event bus for menu synchronization
|
42
|
+
const { emit, on } = useEventBus();
|
43
|
+
// Listen for other menus opening and close this one if needed
|
44
|
+
useEffect(() => {
|
45
|
+
const unsubscribe = on('menu:open', (data) => {
|
46
|
+
// If another menu is opening and this menu is open, close this one
|
47
|
+
if (data.menuId !== menuId && isOpen) {
|
48
|
+
setIsOpen(false);
|
49
|
+
}
|
50
|
+
});
|
51
|
+
return unsubscribe;
|
52
|
+
}, [on, menuId, isOpen]);
|
53
|
+
// Emit event when this menu opens
|
54
|
+
useEffect(() => {
|
55
|
+
if (isOpen) {
|
56
|
+
emit('menu:open', { menuId });
|
57
|
+
}
|
58
|
+
}, [isOpen, emit, menuId]);
|
59
|
+
function setupCheck() {
|
60
|
+
if (!setupRef.current) {
|
61
|
+
throw new Error('useAnchoredMenu: MenuTrigger must be rendered. Use `rendered` property to include it in your component tree.');
|
62
|
+
}
|
63
|
+
}
|
64
|
+
// 'open' accepts props required by the Component and opens the menu
|
65
|
+
const open = useEvent((props, triggerProps) => {
|
66
|
+
setupCheck();
|
67
|
+
setComponentProps(props);
|
68
|
+
setTriggerProps(triggerProps ?? null);
|
69
|
+
setIsOpen(true);
|
70
|
+
});
|
71
|
+
const update = useEvent((props, triggerProps) => {
|
72
|
+
setupCheck();
|
73
|
+
setComponentProps(props);
|
74
|
+
setTriggerProps(triggerProps ?? null);
|
75
|
+
});
|
76
|
+
const close = useEvent(() => {
|
77
|
+
setIsOpen(false);
|
78
|
+
});
|
79
|
+
// Render the menu only when componentProps is set
|
80
|
+
const renderedMenu = useMemo(() => {
|
81
|
+
if (!componentProps)
|
82
|
+
return null;
|
83
|
+
return (_jsxs(MenuTrigger, { isDummy: true, isOpen: isOpen, targetRef: anchorRef, placement: "bottom start", onOpenChange: setIsOpen, ...mergeProps(defaultTriggerProps, triggerProps || undefined), children: [_jsx(VisuallyHidden, { children: _jsx(Pressable, { children: _jsx("button", { "aria-label": "context-menu" }) }) }), _jsx(Component, { ...componentProps })] }));
|
84
|
+
}, [componentProps, triggerProps, isOpen, defaultTriggerProps]);
|
85
|
+
return {
|
86
|
+
anchorRef,
|
87
|
+
open,
|
88
|
+
update,
|
89
|
+
close,
|
90
|
+
isOpen,
|
91
|
+
get rendered() {
|
92
|
+
setupRef.current = true;
|
93
|
+
return renderedMenu;
|
94
|
+
},
|
95
|
+
};
|
96
|
+
}
|
97
|
+
|
98
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
/**
|
2
|
+
* @license MIT
|
3
|
+
* author: Cube Dev Team
|
4
|
+
* @cube-dev/ui-kit v0.68.0
|
5
|
+
* Released under the MIT license.
|
6
|
+
*/
|
7
|
+
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
9
|
+
import { Pressable } from '@react-aria/interactions';
|
10
|
+
import { useEffect, useMemo, useRef, useState, } from 'react';
|
11
|
+
import { VisuallyHidden } from 'react-aria';
|
12
|
+
import { useEvent } from '../../_internal';
|
13
|
+
import { generateRandomId } from '../../utils/random';
|
14
|
+
import { mergeProps } from '../../utils/react';
|
15
|
+
import { useEventBus } from '../../utils/react/useEventBus';
|
16
|
+
import { MenuTrigger } from './Menu';
|
17
|
+
/**
|
18
|
+
* Generic hook to manage a context menu component that opens at pointer coordinates.
|
19
|
+
*
|
20
|
+
* @param Component - A React component that represents the menu content (Menu or CommandMenu).
|
21
|
+
* @param defaultTriggerProps - Default props to pass to the MenuTrigger.
|
22
|
+
* @param defaultMenuProps - Default props to pass to the Menu component.
|
23
|
+
* @returns An object with `targetRef` to attach to the container element, `open` function to open the menu at event coordinates, `close` function to close the menu, and `rendered` JSX element to include in your component tree.
|
24
|
+
*/
|
25
|
+
export function useContextMenu(Component, defaultTriggerProps, defaultMenuProps) {
|
26
|
+
const [isOpen, setIsOpen] = useState(false);
|
27
|
+
const [componentProps, setComponentProps] = useState(null);
|
28
|
+
const [triggerProps, setTriggerProps] = useState(null);
|
29
|
+
const [anchorPosition, setAnchorPosition] = useState(null);
|
30
|
+
const targetRef = useRef(null);
|
31
|
+
const invisibleAnchorRef = useRef(null);
|
32
|
+
const setupRef = useRef(false);
|
33
|
+
// Generate a unique ID for this menu instance
|
34
|
+
const menuId = useMemo(() => generateRandomId(), []);
|
35
|
+
// Get event bus for menu synchronization
|
36
|
+
const { emit, on } = useEventBus();
|
37
|
+
// Listen for other menus opening and close this one if needed
|
38
|
+
useEffect(() => {
|
39
|
+
const unsubscribe = on('menu:open', (data) => {
|
40
|
+
// If another menu is opening and this menu is open, close this one
|
41
|
+
if (data.menuId !== menuId && isOpen) {
|
42
|
+
setIsOpen(false);
|
43
|
+
setAnchorPosition(null);
|
44
|
+
}
|
45
|
+
});
|
46
|
+
return unsubscribe;
|
47
|
+
}, [on, menuId, isOpen]);
|
48
|
+
// Emit event when this menu opens
|
49
|
+
useEffect(() => {
|
50
|
+
if (isOpen) {
|
51
|
+
emit('menu:open', { menuId });
|
52
|
+
}
|
53
|
+
}, [isOpen, emit, menuId]);
|
54
|
+
function setupCheck() {
|
55
|
+
if (!setupRef.current) {
|
56
|
+
throw new Error('useContextMenu: MenuTrigger must be rendered. Use `rendered` property to include it in your component tree.');
|
57
|
+
}
|
58
|
+
}
|
59
|
+
// Helper function to calculate position relative to targetRef, taking the
|
60
|
+
// element's scroll offset into account. Without the scroll offset the menu
|
61
|
+
// would be rendered at the wrong place inside scrollable containers.
|
62
|
+
const calculatePosition = (event) => {
|
63
|
+
const container = targetRef.current;
|
64
|
+
// If no event is provided, position at the center of the element
|
65
|
+
if (!event) {
|
66
|
+
if (!container) {
|
67
|
+
return { x: 0, y: 0 };
|
68
|
+
}
|
69
|
+
const containerRect = container.getBoundingClientRect();
|
70
|
+
const scrollLeft = container.scrollLeft;
|
71
|
+
const scrollTop = container.scrollTop;
|
72
|
+
const computed = window.getComputedStyle(container);
|
73
|
+
const borderLeft = parseFloat(computed.borderLeftWidth) || 0;
|
74
|
+
const borderTop = parseFloat(computed.borderTopWidth) || 0;
|
75
|
+
// Position at the center of the element's content area
|
76
|
+
const x = container.clientWidth / 2 + scrollLeft;
|
77
|
+
const y = container.clientHeight / 2 + scrollTop;
|
78
|
+
// Clamp to the full scroll size
|
79
|
+
const clampedX = Math.max(0, Math.min(x, container.scrollWidth));
|
80
|
+
const clampedY = Math.max(0, Math.min(y, container.scrollHeight));
|
81
|
+
return { x: clampedX, y: clampedY };
|
82
|
+
}
|
83
|
+
// If the target reference is missing, fall back to viewport coordinates.
|
84
|
+
if (!container) {
|
85
|
+
const { clientX = 0, clientY = 0 } = event;
|
86
|
+
return { x: clientX, y: clientY };
|
87
|
+
}
|
88
|
+
const containerRect = container.getBoundingClientRect();
|
89
|
+
// Get coordinates from the event (viewport-relative)
|
90
|
+
const { clientX, clientY } = event;
|
91
|
+
// Take the element's scroll offset into account so that the coordinates are
|
92
|
+
// relative to the **content** box, not the visible viewport of the
|
93
|
+
// element.
|
94
|
+
const scrollLeft = container.scrollLeft;
|
95
|
+
const scrollTop = container.scrollTop;
|
96
|
+
const computed = window.getComputedStyle(container);
|
97
|
+
const borderLeft = parseFloat(computed.borderLeftWidth) || 0;
|
98
|
+
const borderTop = parseFloat(computed.borderTopWidth) || 0;
|
99
|
+
const x = clientX - containerRect.left - borderLeft + scrollLeft;
|
100
|
+
const y = clientY - containerRect.top - borderTop + scrollTop;
|
101
|
+
// Clamp to the full scroll size so that the invisible anchor always stays
|
102
|
+
// inside the element regardless of the scroll position.
|
103
|
+
const clampedX = Math.max(0, Math.min(x, container.scrollWidth));
|
104
|
+
const clampedY = Math.max(0, Math.min(y, container.scrollHeight));
|
105
|
+
return { x: clampedX, y: clampedY };
|
106
|
+
};
|
107
|
+
// 'open' accepts props, trigger props, and optional event for positioning, then opens the menu
|
108
|
+
const open = useEvent((props, triggerProps, event) => {
|
109
|
+
setupCheck();
|
110
|
+
// Ensure the target element can serve as a positioning context for the
|
111
|
+
// invisible target element. If the consumer hasn't explicitly set
|
112
|
+
// `position: relative | absolute | fixed | sticky` we switch it to
|
113
|
+
// `relative` so that absolutely-positioned children are laid out correctly.
|
114
|
+
if (targetRef.current) {
|
115
|
+
const computedStyle = window.getComputedStyle(targetRef.current);
|
116
|
+
if (computedStyle.position === 'static') {
|
117
|
+
targetRef.current.style.position = 'relative';
|
118
|
+
}
|
119
|
+
}
|
120
|
+
// Prevent default context menu if it's a context menu event
|
121
|
+
if (event &&
|
122
|
+
'preventDefault' in event &&
|
123
|
+
typeof event.preventDefault === 'function') {
|
124
|
+
event.preventDefault();
|
125
|
+
}
|
126
|
+
const { x, y } = calculatePosition(event);
|
127
|
+
setAnchorPosition({ x, y });
|
128
|
+
// Merge defaultMenuProps with provided props
|
129
|
+
const finalProps = defaultMenuProps
|
130
|
+
? { ...defaultMenuProps, ...props }
|
131
|
+
: props;
|
132
|
+
setComponentProps(finalProps);
|
133
|
+
setTriggerProps(triggerProps ?? null);
|
134
|
+
setIsOpen(true);
|
135
|
+
});
|
136
|
+
const update = useEvent((props, triggerProps) => {
|
137
|
+
setupCheck();
|
138
|
+
// Merge defaultMenuProps with provided props
|
139
|
+
const finalProps = defaultMenuProps
|
140
|
+
? { ...defaultMenuProps, ...props }
|
141
|
+
: props;
|
142
|
+
setComponentProps(finalProps);
|
143
|
+
setTriggerProps(triggerProps ?? null);
|
144
|
+
});
|
145
|
+
const close = useEvent(() => {
|
146
|
+
setIsOpen(false);
|
147
|
+
setAnchorPosition(null);
|
148
|
+
});
|
149
|
+
// Context menu event handler
|
150
|
+
const onContextMenu = useEvent((event) => {
|
151
|
+
event.preventDefault();
|
152
|
+
if (isOpen) {
|
153
|
+
const pos = calculatePosition(event);
|
154
|
+
setAnchorPosition(pos);
|
155
|
+
}
|
156
|
+
else {
|
157
|
+
open(defaultMenuProps, undefined, event);
|
158
|
+
}
|
159
|
+
});
|
160
|
+
// Bind the onContextMenu event to targetRef
|
161
|
+
useEffect(() => {
|
162
|
+
const element = targetRef.current;
|
163
|
+
if (!element)
|
164
|
+
return;
|
165
|
+
element.addEventListener('contextmenu', onContextMenu);
|
166
|
+
return () => {
|
167
|
+
element.removeEventListener('contextmenu', onContextMenu);
|
168
|
+
};
|
169
|
+
}, [onContextMenu]);
|
170
|
+
// Render the menu only when componentProps is set
|
171
|
+
const renderedMenu = useMemo(() => {
|
172
|
+
if (!componentProps || !anchorPosition)
|
173
|
+
return null;
|
174
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { ref: invisibleAnchorRef, style: {
|
175
|
+
position: 'absolute',
|
176
|
+
left: `${anchorPosition.x}px`,
|
177
|
+
top: `${anchorPosition.y}px`,
|
178
|
+
width: '0px',
|
179
|
+
height: '0px',
|
180
|
+
lineHeight: '0',
|
181
|
+
pointerEvents: 'none',
|
182
|
+
visibility: 'hidden',
|
183
|
+
} }), _jsxs(MenuTrigger, { isDummy: true, isOpen: isOpen, targetRef: invisibleAnchorRef, offset: 0, crossOffset: 0, placement: triggerProps?.placement ||
|
184
|
+
defaultTriggerProps?.placement ||
|
185
|
+
'bottom start', onOpenChange: setIsOpen, ...mergeProps(defaultTriggerProps, triggerProps || undefined), children: [_jsx(VisuallyHidden, { children: _jsx(Pressable, { children: _jsx("button", { "aria-label": "Open context menu" }) }) }), _jsx(Component, { ...componentProps })] })] }));
|
186
|
+
}, [
|
187
|
+
componentProps,
|
188
|
+
triggerProps,
|
189
|
+
isOpen,
|
190
|
+
defaultTriggerProps,
|
191
|
+
anchorPosition,
|
192
|
+
]);
|
193
|
+
return {
|
194
|
+
targetRef,
|
195
|
+
open,
|
196
|
+
update,
|
197
|
+
close,
|
198
|
+
isOpen,
|
199
|
+
get rendered() {
|
200
|
+
setupRef.current = true;
|
201
|
+
return renderedMenu;
|
202
|
+
},
|
203
|
+
};
|
204
|
+
}
|
205
|
+
|
206
|
+
|