@cube-dev/ui-kit 0.65.1 → 0.66.1
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 +14 -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 +1 -1
- package/es/components/actions/Action/Action.js +1 -1
- package/es/components/actions/Button/Button.js +1 -1
- 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 +464 -0
- package/es/components/actions/CommandMenu/index.js +11 -0
- package/es/components/actions/CommandMenu/styled.js +110 -0
- package/es/components/{pickers → actions}/Menu/Menu.js +34 -8
- package/es/components/{pickers → actions}/Menu/MenuItem.js +10 -7
- package/es/components/{pickers → actions}/Menu/MenuSection.js +3 -3
- package/es/components/{pickers → actions}/Menu/MenuTrigger.js +2 -1
- package/es/components/{pickers → actions}/Menu/context.js +1 -1
- package/es/components/actions/Menu/index.js +17 -0
- package/es/components/{pickers → actions}/Menu/styled.js +31 -14
- package/es/components/actions/index.js +3 -1
- package/es/components/actions/use-action.js +1 -1
- 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 +14 -4
- 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 +1 -1
- 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 +3 -2
- 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/Input/Input.js +1 -1
- package/es/components/fields/Input/index.js +1 -1
- package/es/components/fields/ListBox/ListBox.js +1 -1
- 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 +19 -11
- 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 +1 -1
- 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 +1 -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 +1 -1
- 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/dialog-container.js +1 -1
- package/es/components/overlays/Dialog/index.js +1 -1
- 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/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 +1 -1
- package/es/icons/wrap-icon.js +1 -1
- package/es/index.js +4 -3
- package/es/provider.js +1 -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 +1 -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 +1 -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 +1 -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/useCombinedRefs.js +1 -1
- package/es/utils/react/useId.js +1 -1
- package/es/utils/react/useIsDarwin.js +1 -1
- package/es/utils/react/useKeySymbols.js +8 -8
- 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 +1 -1
- package/types/components/actions/CommandMenu/CommandMenu.d.ts +38 -0
- package/types/components/actions/CommandMenu/index.d.ts +2 -0
- package/types/components/actions/CommandMenu/styled.d.ts +5 -0
- package/types/components/{pickers → actions}/Menu/Menu.d.ts +12 -3
- package/types/components/{pickers → actions}/Menu/MenuItem.d.ts +1 -0
- package/types/components/{pickers → actions}/Menu/MenuSection.d.ts +1 -0
- package/types/components/{pickers → actions}/Menu/context.d.ts +4 -0
- package/types/components/actions/Menu/index.d.ts +7 -0
- package/types/components/{pickers → actions}/Menu/styled.d.ts +432 -0
- package/types/components/actions/index.d.ts +2 -0
- package/types/components/content/HotKeys/HotKeys.d.ts +3 -3
- package/types/components/fields/ComboBox/ComboBox.d.ts +1 -1
- package/types/components/fields/Select/Select.d.ts +3 -2
- package/types/components/status/Spin/Cube.d.ts +1 -1
- package/types/components/status/Spin/SpinsContainer.d.ts +1 -1
- package/types/index.d.ts +6 -4
- package/es/components/pickers/Menu/MenuButton.js +0 -96
- package/types/components/pickers/Menu/MenuButton.d.ts +0 -14
- /package/types/components/{pickers → actions}/Menu/MenuTrigger.d.ts +0 -0
@@ -0,0 +1,464 @@
|
|
1
|
+
/**
|
2
|
+
* @license MIT
|
3
|
+
* author: Cube Dev Team
|
4
|
+
* @cube-dev/ui-kit v0.66.1
|
5
|
+
* Released under the MIT license.
|
6
|
+
*/
|
7
|
+
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
9
|
+
import { useSyncRef } from '@react-aria/utils';
|
10
|
+
import { useDOMRef } from '@react-spectrum/utils';
|
11
|
+
import React, { useCallback, useMemo, useRef, useState, } from 'react';
|
12
|
+
import { useFilter, useMenu } from 'react-aria';
|
13
|
+
// Import Item and Section from Menu for CommandMenu compound component
|
14
|
+
import { Item, Section, useTreeState } from 'react-stately';
|
15
|
+
import { LoadingIcon } from '../../../icons';
|
16
|
+
import { CONTAINER_STYLES, extractStyles, filterBaseProps, } from '../../../tasty';
|
17
|
+
import { mergeProps } from '../../../utils/react';
|
18
|
+
import { useDialogContext } from '../../overlays/Dialog/context';
|
19
|
+
import { TooltipProvider } from '../../overlays/Tooltip/TooltipProvider';
|
20
|
+
import { useMenuContext } from '../Menu';
|
21
|
+
import { MenuItem } from '../Menu/MenuItem';
|
22
|
+
import { MenuSection } from '../Menu/MenuSection';
|
23
|
+
import { MenuTrigger } from '../Menu/MenuTrigger';
|
24
|
+
import { StyledDivider, StyledFooter, StyledHeader, StyledMenu, } from '../Menu/styled';
|
25
|
+
import { StyledCommandMenu, StyledEmptyState, StyledLoadingWrapper, StyledMenuWrapper, StyledSearchInput, } from './styled';
|
26
|
+
function CommandMenuBase(props, ref) {
|
27
|
+
const { searchPlaceholder = 'Search commands...', searchValue: controlledSearchValue, onSearchChange, filter: customFilter, emptyLabel = 'No commands found', searchInputStyles, headerStyles, footerStyles, isLoading = false, shouldFilter = true, autoFocus = true, size = 'small', qa, styles, selectedKeys, defaultSelectedKeys, onSelectionChange, header, footer, ...restMenuProps } = props;
|
28
|
+
const domRef = useDOMRef(ref);
|
29
|
+
const searchInputRef = useRef(null);
|
30
|
+
const contextProps = useMenuContext();
|
31
|
+
const dialogContext = useDialogContext();
|
32
|
+
// Convert string[] to Set<Key> for React Aria compatibility
|
33
|
+
const ariaSelectedKeys = selectedKeys ? new Set(selectedKeys) : undefined;
|
34
|
+
const ariaDefaultSelectedKeys = defaultSelectedKeys
|
35
|
+
? new Set(defaultSelectedKeys)
|
36
|
+
: undefined;
|
37
|
+
const handleSelectionChange = onSelectionChange
|
38
|
+
? (keys) => {
|
39
|
+
if (keys === 'all') {
|
40
|
+
// Handle 'all' selection case - collect all available keys
|
41
|
+
const allKeys = Array.from(treeState.collection.getKeys()).map((key) => String(key));
|
42
|
+
onSelectionChange(allKeys);
|
43
|
+
}
|
44
|
+
else if (keys instanceof Set) {
|
45
|
+
onSelectionChange(Array.from(keys).map((key) => String(key)));
|
46
|
+
}
|
47
|
+
else {
|
48
|
+
onSelectionChange([]);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
: undefined;
|
52
|
+
const completeProps = mergeProps(contextProps, restMenuProps, {
|
53
|
+
selectedKeys: ariaSelectedKeys,
|
54
|
+
defaultSelectedKeys: ariaDefaultSelectedKeys,
|
55
|
+
onSelectionChange: handleSelectionChange,
|
56
|
+
});
|
57
|
+
// Search state management
|
58
|
+
const [internalSearchValue, setInternalSearchValue] = useState('');
|
59
|
+
const searchValue = controlledSearchValue ?? internalSearchValue;
|
60
|
+
const handleSearchChange = useCallback((value) => {
|
61
|
+
if (controlledSearchValue === undefined) {
|
62
|
+
setInternalSearchValue(value);
|
63
|
+
}
|
64
|
+
onSearchChange?.(value);
|
65
|
+
}, [controlledSearchValue, onSearchChange]);
|
66
|
+
// Filter setup
|
67
|
+
const { contains } = useFilter({ sensitivity: 'base' });
|
68
|
+
const textFilterFn = useMemo(() => customFilter || contains, [customFilter, contains]);
|
69
|
+
// Enhanced filter function that supports keywords and forceMount
|
70
|
+
const enhancedFilter = useCallback((textValue, inputValue, item) => {
|
71
|
+
// Always show force-mounted items
|
72
|
+
if (item?.forceMount) {
|
73
|
+
return true;
|
74
|
+
}
|
75
|
+
// If shouldFilter is false, show all items
|
76
|
+
if (!shouldFilter) {
|
77
|
+
return true;
|
78
|
+
}
|
79
|
+
// Split input value into individual words and filter out empty strings
|
80
|
+
const searchWords = inputValue
|
81
|
+
.trim()
|
82
|
+
.toLowerCase()
|
83
|
+
.split(/\s+/)
|
84
|
+
.filter((word) => word.length > 0);
|
85
|
+
// If no search words, show all items
|
86
|
+
if (searchWords.length === 0) {
|
87
|
+
return true;
|
88
|
+
}
|
89
|
+
// Collect all searchable text for this item
|
90
|
+
const searchableTexts = [];
|
91
|
+
// Add main text value
|
92
|
+
searchableTexts.push(textValue.toLowerCase());
|
93
|
+
// Add keywords if available
|
94
|
+
if (item?.keywords && Array.isArray(item.keywords)) {
|
95
|
+
searchableTexts.push(...item.keywords.map((keyword) => keyword.toLowerCase()));
|
96
|
+
}
|
97
|
+
// Check if ALL search words match at least one of the searchable texts
|
98
|
+
return searchWords.every((searchWord) => searchableTexts.some((text) => text.includes(searchWord)));
|
99
|
+
}, [shouldFilter]);
|
100
|
+
// Collection filter for React Stately
|
101
|
+
const collectionFilter = useCallback((nodes) => {
|
102
|
+
const term = searchValue.trim();
|
103
|
+
// If no search term, return all nodes
|
104
|
+
if (!term) {
|
105
|
+
return nodes;
|
106
|
+
}
|
107
|
+
// Split search term into words for multi-word filtering
|
108
|
+
const searchWords = term
|
109
|
+
.toLowerCase()
|
110
|
+
.split(/\s+/)
|
111
|
+
.filter((word) => word.length > 0);
|
112
|
+
// If no valid search words, return all nodes
|
113
|
+
if (searchWords.length === 0) {
|
114
|
+
return nodes;
|
115
|
+
}
|
116
|
+
// Recursive helper to filter sections and items
|
117
|
+
const filterNodes = (iter) => {
|
118
|
+
const result = [];
|
119
|
+
for (const node of iter) {
|
120
|
+
if (node.type === 'section') {
|
121
|
+
const filteredChildren = filterNodes(node.childNodes);
|
122
|
+
if (filteredChildren.length) {
|
123
|
+
result.push({
|
124
|
+
...node,
|
125
|
+
childNodes: filteredChildren,
|
126
|
+
});
|
127
|
+
}
|
128
|
+
}
|
129
|
+
else {
|
130
|
+
const text = node.textValue ?? String(node.rendered ?? '');
|
131
|
+
if (enhancedFilter(text, term, node.props)) {
|
132
|
+
result.push(node);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}
|
136
|
+
return result;
|
137
|
+
};
|
138
|
+
return filterNodes(nodes);
|
139
|
+
}, [searchValue, enhancedFilter]);
|
140
|
+
// Create tree state with filter for both keyboard navigation and rendering
|
141
|
+
const treeStateProps = {
|
142
|
+
...completeProps,
|
143
|
+
filter: collectionFilter,
|
144
|
+
shouldUseVirtualFocus: true, // Always use virtual focus for CommandMenu
|
145
|
+
};
|
146
|
+
const treeState = useTreeState(treeStateProps);
|
147
|
+
const collectionItems = [...treeState.collection];
|
148
|
+
const hasSections = collectionItems.some((item) => item.type === 'section');
|
149
|
+
// Track focused key for aria-activedescendant
|
150
|
+
const [focusedKey, setFocusedKey] = React.useState(null);
|
151
|
+
const focusedKeyRef = useRef(null);
|
152
|
+
// Apply filtering to collection items for rendering and empty state checks
|
153
|
+
const filteredCollectionItems = useMemo(() => {
|
154
|
+
const term = searchValue.trim();
|
155
|
+
if (!term) {
|
156
|
+
return collectionItems;
|
157
|
+
}
|
158
|
+
// Split search term into words for multi-word filtering
|
159
|
+
const searchWords = term
|
160
|
+
.toLowerCase()
|
161
|
+
.split(/\s+/)
|
162
|
+
.filter((word) => word.length > 0);
|
163
|
+
// If no valid search words, return all items
|
164
|
+
if (searchWords.length === 0) {
|
165
|
+
return collectionItems;
|
166
|
+
}
|
167
|
+
const filterNodes = (items) => {
|
168
|
+
const result = [];
|
169
|
+
[...items].forEach((item) => {
|
170
|
+
if (item.type === 'section') {
|
171
|
+
const filteredChildren = filterNodes(item.childNodes);
|
172
|
+
if (filteredChildren.length) {
|
173
|
+
result.push({
|
174
|
+
...item,
|
175
|
+
childNodes: filteredChildren,
|
176
|
+
});
|
177
|
+
}
|
178
|
+
}
|
179
|
+
else {
|
180
|
+
const text = item.textValue ?? String(item.rendered ?? '');
|
181
|
+
if (enhancedFilter(text, term, item.props)) {
|
182
|
+
result.push(item);
|
183
|
+
}
|
184
|
+
}
|
185
|
+
});
|
186
|
+
return result;
|
187
|
+
};
|
188
|
+
return filterNodes(collectionItems);
|
189
|
+
}, [collectionItems, searchValue, enhancedFilter]);
|
190
|
+
const hasFilteredItems = filteredCollectionItems.length > 0;
|
191
|
+
const viewHasSections = filteredCollectionItems.some((item) => item.type === 'section');
|
192
|
+
// Helper function to find the first selectable item from filtered results
|
193
|
+
const findFirstSelectableItem = useCallback(() => {
|
194
|
+
// Use the filtered collection items instead of the full tree state collection
|
195
|
+
for (const item of filteredCollectionItems) {
|
196
|
+
if (item &&
|
197
|
+
item.type === 'item' &&
|
198
|
+
!treeState.selectionManager.isDisabled(item.key)) {
|
199
|
+
return item.key;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
return null;
|
203
|
+
}, [filteredCollectionItems, treeState.selectionManager]);
|
204
|
+
// Create a ref for the menu container
|
205
|
+
const menuRef = useRef(null);
|
206
|
+
// Use menu hook for accessibility
|
207
|
+
const { menuProps } = useMenu({
|
208
|
+
...completeProps,
|
209
|
+
'aria-label': 'Command palette menu',
|
210
|
+
filter: collectionFilter,
|
211
|
+
shouldUseVirtualFocus: true,
|
212
|
+
}, treeState, menuRef);
|
213
|
+
// Manual rendering of menu items (similar to Menu component)
|
214
|
+
const renderedItems = useMemo(() => {
|
215
|
+
const items = [];
|
216
|
+
let isFirstSection = true;
|
217
|
+
filteredCollectionItems.forEach((item) => {
|
218
|
+
if (item.type === 'section') {
|
219
|
+
if (!isFirstSection) {
|
220
|
+
items.push(_jsx(StyledDivider, { role: "separator", "aria-orientation": "horizontal" }, `divider-${String(item.key)}`));
|
221
|
+
}
|
222
|
+
items.push(_jsx(MenuSection, { item: item, state: treeState, styles: completeProps.sectionStyles, itemStyles: completeProps.itemStyles, headingStyles: completeProps.sectionHeadingStyles, selectionIcon: completeProps.selectionIcon, size: size }, item.key));
|
223
|
+
isFirstSection = false;
|
224
|
+
return;
|
225
|
+
}
|
226
|
+
let menuItem = (_jsx(MenuItem, { item: item, state: treeState, styles: completeProps.itemStyles, selectionIcon: completeProps.selectionIcon, size: size, onAction: item.onAction }, item.key));
|
227
|
+
// Apply tooltip wrapper if tooltip property is provided
|
228
|
+
if (item.props.tooltip) {
|
229
|
+
const tooltipProps = typeof item.props.tooltip === 'string'
|
230
|
+
? { title: item.props.tooltip }
|
231
|
+
: item.props.tooltip;
|
232
|
+
menuItem = (_jsx(TooltipProvider, { activeWrap: true, placement: "right", ...tooltipProps, children: menuItem }, item.key));
|
233
|
+
}
|
234
|
+
// Apply custom wrapper if provided
|
235
|
+
if (item.props.wrapper) {
|
236
|
+
menuItem = item.props.wrapper(menuItem);
|
237
|
+
}
|
238
|
+
// Ensure every child has a stable key, even if the wrapper component didn't set one.
|
239
|
+
items.push(React.cloneElement(menuItem, { key: item.key }));
|
240
|
+
});
|
241
|
+
return items;
|
242
|
+
}, [
|
243
|
+
filteredCollectionItems,
|
244
|
+
treeState,
|
245
|
+
completeProps.sectionStyles,
|
246
|
+
completeProps.itemStyles,
|
247
|
+
completeProps.selectionIcon,
|
248
|
+
completeProps.sectionHeadingStyles,
|
249
|
+
]);
|
250
|
+
// Auto-focus search input
|
251
|
+
React.useEffect(() => {
|
252
|
+
if (autoFocus && searchInputRef.current) {
|
253
|
+
// Use a small timeout to ensure the element is visible and focusable
|
254
|
+
// This is especially important when the CommandMenu is opened in a popover
|
255
|
+
const timeoutId = setTimeout(() => {
|
256
|
+
if (searchInputRef.current) {
|
257
|
+
searchInputRef.current.focus();
|
258
|
+
}
|
259
|
+
}, 0);
|
260
|
+
return () => clearTimeout(timeoutId);
|
261
|
+
}
|
262
|
+
}, [autoFocus]);
|
263
|
+
// Also focus when the component becomes visible (for trigger/popover usage)
|
264
|
+
React.useEffect(() => {
|
265
|
+
// Check if autoFocus is enabled and we're in a trigger context
|
266
|
+
if (autoFocus && contextProps.autoFocus && searchInputRef.current) {
|
267
|
+
// Use a small timeout to ensure the popover is fully rendered
|
268
|
+
const timeoutId = setTimeout(() => {
|
269
|
+
if (searchInputRef.current) {
|
270
|
+
searchInputRef.current.focus();
|
271
|
+
}
|
272
|
+
}, 50); // Slightly longer timeout for popover context
|
273
|
+
return () => clearTimeout(timeoutId);
|
274
|
+
}
|
275
|
+
}, [autoFocus, contextProps.autoFocus]);
|
276
|
+
// Track the previous search value to only run auto-focus when search actually changes
|
277
|
+
const prevSearchValueRef = useRef('');
|
278
|
+
// Auto-focus first item when search value changes (but not on initial render)
|
279
|
+
React.useEffect(() => {
|
280
|
+
const currentSearchValue = searchValue.trim();
|
281
|
+
const prevSearchValue = prevSearchValueRef.current;
|
282
|
+
// Only auto-focus when search value actually changes
|
283
|
+
if (currentSearchValue !== prevSearchValue && currentSearchValue !== '') {
|
284
|
+
const firstSelectableKey = findFirstSelectableItem();
|
285
|
+
if (firstSelectableKey && hasFilteredItems) {
|
286
|
+
// Focus the first item in the selection manager
|
287
|
+
treeState.selectionManager.setFocusedKey(firstSelectableKey);
|
288
|
+
setFocusedKey(firstSelectableKey);
|
289
|
+
focusedKeyRef.current = firstSelectableKey;
|
290
|
+
}
|
291
|
+
else {
|
292
|
+
// Clear focus if no items are available
|
293
|
+
treeState.selectionManager.setFocusedKey(null);
|
294
|
+
setFocusedKey(null);
|
295
|
+
focusedKeyRef.current = null;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
// Update the previous search value
|
299
|
+
prevSearchValueRef.current = currentSearchValue;
|
300
|
+
}, [searchValue, findFirstSelectableItem, hasFilteredItems]);
|
301
|
+
// Extract styles
|
302
|
+
const extractedStyles = useMemo(() => extractStyles(props, CONTAINER_STYLES), [props]);
|
303
|
+
// Determine if we should show empty state based on actual filtered collection
|
304
|
+
const hasSearchTerm = searchValue.trim().length > 0;
|
305
|
+
const showEmptyState = hasSearchTerm && !hasFilteredItems && !isLoading;
|
306
|
+
// Sync refs
|
307
|
+
useSyncRef(contextProps, menuRef);
|
308
|
+
const mods = useMemo(() => {
|
309
|
+
// Determine mods based on dialog context and menu context
|
310
|
+
let popoverMod = completeProps.mods?.popover || dialogContext?.type === 'popover';
|
311
|
+
let trayMod = completeProps.mods?.tray || dialogContext?.type === 'tray';
|
312
|
+
let modalMod = dialogContext?.type === 'modal';
|
313
|
+
return {
|
314
|
+
sections: viewHasSections,
|
315
|
+
footer: !!footer,
|
316
|
+
header: !!header,
|
317
|
+
popover: popoverMod,
|
318
|
+
tray: trayMod,
|
319
|
+
modal: modalMod,
|
320
|
+
};
|
321
|
+
}, [
|
322
|
+
viewHasSections,
|
323
|
+
footer,
|
324
|
+
header,
|
325
|
+
completeProps.mods,
|
326
|
+
dialogContext?.type,
|
327
|
+
]);
|
328
|
+
return (_jsxs(StyledCommandMenu, { ...filterBaseProps(props), ref: domRef, qa: qa || 'CommandMenu', "data-size": size, mods: mods, styles: mergeProps(extractedStyles, styles), children: [header && (_jsx(StyledHeader, { role: "presentation", styles: headerStyles, children: header })), _jsx(StyledSearchInput, { ref: searchInputRef, type: "search", placeholder: searchPlaceholder, value: searchValue, styles: searchInputStyles, "data-size": size, "aria-controls": `${qa || 'CommandMenu'}-menu`, role: "combobox", "aria-expanded": "true", "aria-haspopup": "listbox", "aria-activedescendant": focusedKey != null
|
329
|
+
? `${qa || 'CommandMenu'}-menu-option-${focusedKey}`
|
330
|
+
: undefined, onChange: (e) => handleSearchChange(e.target.value), onKeyDown: (e) => {
|
331
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
332
|
+
e.preventDefault();
|
333
|
+
const isArrowDown = e.key === 'ArrowDown';
|
334
|
+
const { selectionManager } = treeState;
|
335
|
+
// Use the ref to get the current focused key synchronously
|
336
|
+
const currentKey = focusedKeyRef.current || selectionManager.focusedKey;
|
337
|
+
// Helper function to get all visible item keys by applying filter to tree state collection
|
338
|
+
const getVisibleItemKeys = () => {
|
339
|
+
const keys = [];
|
340
|
+
const term = searchValue.trim();
|
341
|
+
// Use the tree state's collection and apply filter manually
|
342
|
+
for (const item of treeState.collection) {
|
343
|
+
if (item.type === 'item') {
|
344
|
+
const text = item.textValue ?? String(item.rendered ?? '');
|
345
|
+
if (enhancedFilter(text, term, item.props)) {
|
346
|
+
keys.push(item.key);
|
347
|
+
}
|
348
|
+
}
|
349
|
+
}
|
350
|
+
return keys;
|
351
|
+
};
|
352
|
+
// Helper function to find next selectable key in a direction
|
353
|
+
const findNextSelectableKey = (currentIndex, direction, visibleKeys) => {
|
354
|
+
const increment = direction === 'forward' ? 1 : -1;
|
355
|
+
for (let i = currentIndex + increment; i >= 0 && i < visibleKeys.length; i += increment) {
|
356
|
+
const key = visibleKeys[i];
|
357
|
+
if (!selectionManager.isDisabled(key)) {
|
358
|
+
return key;
|
359
|
+
}
|
360
|
+
}
|
361
|
+
return null;
|
362
|
+
};
|
363
|
+
// Helper function to find first or last selectable key
|
364
|
+
const findFirstLastSelectableKey = (direction, visibleKeys) => {
|
365
|
+
const keysToCheck = direction === 'forward'
|
366
|
+
? visibleKeys
|
367
|
+
: [...visibleKeys].reverse();
|
368
|
+
for (const key of keysToCheck) {
|
369
|
+
if (!selectionManager.isDisabled(key)) {
|
370
|
+
return key;
|
371
|
+
}
|
372
|
+
}
|
373
|
+
return null;
|
374
|
+
};
|
375
|
+
const visibleKeys = getVisibleItemKeys();
|
376
|
+
if (visibleKeys.length === 0) {
|
377
|
+
return; // No visible items to navigate
|
378
|
+
}
|
379
|
+
let nextKey;
|
380
|
+
const direction = isArrowDown ? 'forward' : 'backward';
|
381
|
+
if (currentKey == null) {
|
382
|
+
// No current focus, start from the first/last item
|
383
|
+
nextKey = findFirstLastSelectableKey(direction, visibleKeys);
|
384
|
+
}
|
385
|
+
else {
|
386
|
+
// Find current position in visible keys
|
387
|
+
const currentIndex = visibleKeys.indexOf(currentKey);
|
388
|
+
if (currentIndex === -1) {
|
389
|
+
// Current key not in visible items, start from beginning/end
|
390
|
+
nextKey = findFirstLastSelectableKey(direction, visibleKeys);
|
391
|
+
}
|
392
|
+
else {
|
393
|
+
// Find next selectable item from current position
|
394
|
+
nextKey = findNextSelectableKey(currentIndex, direction, visibleKeys);
|
395
|
+
// If no next key found, wrap to first/last selectable item
|
396
|
+
if (nextKey == null) {
|
397
|
+
nextKey = findFirstLastSelectableKey(direction, visibleKeys);
|
398
|
+
}
|
399
|
+
}
|
400
|
+
}
|
401
|
+
if (nextKey != null) {
|
402
|
+
selectionManager.setFocusedKey(nextKey);
|
403
|
+
setFocusedKey(nextKey);
|
404
|
+
focusedKeyRef.current = nextKey; // Update ref immediately
|
405
|
+
}
|
406
|
+
}
|
407
|
+
else if (e.key === 'Enter' ||
|
408
|
+
(e.key === ' ' && !searchValue.trim())) {
|
409
|
+
const currentFocusedKey = focusedKey || treeState.selectionManager.focusedKey;
|
410
|
+
if (currentFocusedKey != null) {
|
411
|
+
e.preventDefault();
|
412
|
+
// Trigger action for the focused item (like Menu does)
|
413
|
+
// First check if there's a selection mode, if so, handle selection
|
414
|
+
if (treeState.selectionManager.selectionMode !== 'none') {
|
415
|
+
treeState.selectionManager.select(currentFocusedKey, e);
|
416
|
+
}
|
417
|
+
else {
|
418
|
+
// Default behavior: trigger action
|
419
|
+
const node = treeState.collection.getItem(currentFocusedKey);
|
420
|
+
if (node) {
|
421
|
+
// Call the tree state's action handler
|
422
|
+
const onAction = completeProps.onAction;
|
423
|
+
if (onAction) {
|
424
|
+
onAction(currentFocusedKey);
|
425
|
+
}
|
426
|
+
// Also call the item's individual onAction if it exists
|
427
|
+
if (node.props?.onAction) {
|
428
|
+
node.props.onAction(currentFocusedKey);
|
429
|
+
}
|
430
|
+
}
|
431
|
+
}
|
432
|
+
// Close the menu if we're in a trigger context and closeOnSelect is enabled (default behavior)
|
433
|
+
const { onClose, closeOnSelect } = contextProps;
|
434
|
+
if (onClose && closeOnSelect !== false) {
|
435
|
+
onClose();
|
436
|
+
}
|
437
|
+
}
|
438
|
+
}
|
439
|
+
else if (e.key === 'Escape') {
|
440
|
+
if (searchValue) {
|
441
|
+
e.preventDefault();
|
442
|
+
handleSearchChange('');
|
443
|
+
}
|
444
|
+
}
|
445
|
+
} }), isLoading && (_jsx(StyledLoadingWrapper, { children: _jsx(LoadingIcon, { role: "progressbar", "aria-label": "Loading commands", "aria-hidden": false }) })), !isLoading && !showEmptyState && (_jsx(StyledMenuWrapper, { children: _jsx(StyledMenu, { ...menuProps, ref: menuRef, id: `${qa || 'CommandMenu'}-menu`, "aria-label": "Command menu", qa: "Menu", "data-size": size, mods: mods, styles: {
|
446
|
+
border: 'none',
|
447
|
+
boxShadow: 'none',
|
448
|
+
radius: 0,
|
449
|
+
padding: '0.5x',
|
450
|
+
}, children: renderedItems }) })), !isLoading && showEmptyState && (_jsx(StyledEmptyState, { children: emptyLabel })), footer && (_jsx(StyledFooter, { role: "presentation", styles: footerStyles, children: footer }))] }));
|
451
|
+
}
|
452
|
+
// forwardRef doesn't support generic parameters, so cast the result to the correct type
|
453
|
+
const _CommandMenu = React.forwardRef(CommandMenuBase);
|
454
|
+
// Attach Trigger alias from MenuTrigger for consistent API
|
455
|
+
// Also attach Item and Section for compound component pattern
|
456
|
+
const __CommandMenu = Object.assign(_CommandMenu, {
|
457
|
+
Trigger: MenuTrigger,
|
458
|
+
Item,
|
459
|
+
Section,
|
460
|
+
displayName: 'CommandMenu',
|
461
|
+
});
|
462
|
+
export { __CommandMenu as CommandMenu };
|
463
|
+
|
464
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
/**
|
2
|
+
* @license MIT
|
3
|
+
* author: Cube Dev Team
|
4
|
+
* @cube-dev/ui-kit v0.66.1
|
5
|
+
* Released under the MIT license.
|
6
|
+
*/
|
7
|
+
|
8
|
+
import { tasty } from '../../../tasty';
|
9
|
+
export const StyledCommandMenu = tasty({
|
10
|
+
qa: 'CommandMenu',
|
11
|
+
styles: {
|
12
|
+
display: 'grid',
|
13
|
+
flow: 'row',
|
14
|
+
gridColumns: 'minmax(0, 1fr)',
|
15
|
+
gridRows: {
|
16
|
+
'': 'max-content minmax(0, 1fr)',
|
17
|
+
header: 'max-content max-content minmax(0, 1fr)',
|
18
|
+
footer: 'max-content minmax(0, 1fr) max-content max-content',
|
19
|
+
'header & footer': 'max-content max-content minmax(0, 1fr) max-content max-content',
|
20
|
+
},
|
21
|
+
placeContent: 'stretch',
|
22
|
+
placeItems: 'stretch',
|
23
|
+
fill: '#white',
|
24
|
+
border: '#border',
|
25
|
+
radius: '(1cr + 1bw)',
|
26
|
+
shadow: {
|
27
|
+
'': false,
|
28
|
+
'popover | tray': '0px 5px 15px #dark.05',
|
29
|
+
},
|
30
|
+
overflow: 'hidden',
|
31
|
+
width: '20x 50x',
|
32
|
+
height: {
|
33
|
+
'': 'initial',
|
34
|
+
popover: 'initial max-content (50vh - 4x)',
|
35
|
+
tray: 'initial max-content (100vh - 4x)',
|
36
|
+
},
|
37
|
+
},
|
38
|
+
});
|
39
|
+
export const StyledSearchInput = tasty({
|
40
|
+
qa: 'SearchInput',
|
41
|
+
as: 'input',
|
42
|
+
styles: {
|
43
|
+
display: 'flex',
|
44
|
+
width: '100%',
|
45
|
+
color: '#dark',
|
46
|
+
fill: '#white',
|
47
|
+
border: '#border bottom',
|
48
|
+
outline: 'none',
|
49
|
+
transition: 'theme',
|
50
|
+
radius: 0,
|
51
|
+
padding: '@vertical-padding @right-padding @vertical-padding @left-padding',
|
52
|
+
textAlign: 'left',
|
53
|
+
reset: 'input',
|
54
|
+
preset: 't3',
|
55
|
+
margin: 0,
|
56
|
+
boxSizing: 'border-box',
|
57
|
+
userSelect: 'auto',
|
58
|
+
'@vertical-padding': {
|
59
|
+
'': '(.75x - 1bw)',
|
60
|
+
'[data-size="medium"]': '(1.25x - 1bw)',
|
61
|
+
},
|
62
|
+
'@left-padding': {
|
63
|
+
'': '1x',
|
64
|
+
'[data-size="medium"]': '1x',
|
65
|
+
},
|
66
|
+
'@right-padding': {
|
67
|
+
'': '1x',
|
68
|
+
'[data-size="medium"]': '1x',
|
69
|
+
},
|
70
|
+
'&::placeholder': {
|
71
|
+
color: '#dark-03',
|
72
|
+
},
|
73
|
+
},
|
74
|
+
});
|
75
|
+
export const StyledLoadingWrapper = tasty({
|
76
|
+
qa: 'LoadingWrapper',
|
77
|
+
styles: {
|
78
|
+
display: 'flex',
|
79
|
+
padding: '2x',
|
80
|
+
placeContent: 'center',
|
81
|
+
placeItems: 'center',
|
82
|
+
color: '#dark-03',
|
83
|
+
},
|
84
|
+
});
|
85
|
+
export const StyledEmptyState = tasty({
|
86
|
+
qa: 'EmptyState',
|
87
|
+
styles: {
|
88
|
+
display: 'flex',
|
89
|
+
padding: '2x',
|
90
|
+
placeContent: 'center',
|
91
|
+
placeItems: 'center',
|
92
|
+
color: '#dark-03',
|
93
|
+
preset: 't3',
|
94
|
+
},
|
95
|
+
});
|
96
|
+
export const StyledMenuWrapper = tasty({
|
97
|
+
qa: 'MenuWrapper',
|
98
|
+
styles: {
|
99
|
+
display: 'grid',
|
100
|
+
flow: 'row',
|
101
|
+
gridColumns: 'minmax(0, 1fr)',
|
102
|
+
placeContent: 'stretch',
|
103
|
+
placeItems: 'stretch',
|
104
|
+
width: '100%',
|
105
|
+
overflow: 'auto',
|
106
|
+
scrollbar: 'styled',
|
107
|
+
},
|
108
|
+
});
|
109
|
+
|
110
|
+
|
@@ -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.66.1
|
5
5
|
* Released under the MIT license.
|
6
6
|
*/
|
7
7
|
|
@@ -17,26 +17,52 @@ import { TooltipProvider, } from '../../overlays/Tooltip/TooltipProvider';
|
|
17
17
|
import { useMenuContext } from './context';
|
18
18
|
import { MenuItem } from './MenuItem';
|
19
19
|
import { MenuSection } from './MenuSection';
|
20
|
-
import { StyledDivider, StyledHeader, StyledMenu } from './styled';
|
20
|
+
import { StyledDivider, StyledFooter, StyledHeader, StyledMenu, } from './styled';
|
21
21
|
function Menu(props, ref) {
|
22
|
-
const { header, footer, itemStyles, sectionStyles, sectionHeadingStyles, selectionIcon, qa, ...rest } = props;
|
22
|
+
const { header, footer, itemStyles, sectionStyles, sectionHeadingStyles, selectionIcon, size = 'small', qa, selectedKeys, defaultSelectedKeys, onSelectionChange, ...rest } = props;
|
23
23
|
const domRef = useDOMRef(ref);
|
24
24
|
const contextProps = useMenuContext();
|
25
|
-
|
25
|
+
// Convert string[] to Set<Key> for React Aria compatibility
|
26
|
+
const ariaSelectedKeys = selectedKeys ? new Set(selectedKeys) : undefined;
|
27
|
+
const ariaDefaultSelectedKeys = defaultSelectedKeys
|
28
|
+
? new Set(defaultSelectedKeys)
|
29
|
+
: undefined;
|
30
|
+
const handleSelectionChange = onSelectionChange
|
31
|
+
? (keys) => {
|
32
|
+
if (keys === 'all') {
|
33
|
+
// Handle 'all' selection case - collect all available keys
|
34
|
+
const allKeys = Array.from(state.collection.getKeys()).map((key) => String(key));
|
35
|
+
onSelectionChange(allKeys);
|
36
|
+
}
|
37
|
+
else if (keys instanceof Set) {
|
38
|
+
onSelectionChange(Array.from(keys).map((key) => String(key)));
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
onSelectionChange([]);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
: undefined;
|
45
|
+
const completeProps = mergeProps(contextProps, rest, {
|
46
|
+
selectedKeys: ariaSelectedKeys,
|
47
|
+
defaultSelectedKeys: ariaDefaultSelectedKeys,
|
48
|
+
onSelectionChange: handleSelectionChange,
|
49
|
+
});
|
26
50
|
// Props used for collection building.
|
27
51
|
const treeProps = completeProps;
|
28
52
|
const state = useTreeState(treeProps);
|
29
53
|
const collectionItems = [...state.collection];
|
30
54
|
const hasSections = collectionItems.some((item) => item.type === 'section');
|
31
|
-
const { menuProps } = useMenu(
|
55
|
+
const { menuProps } = useMenu(completeProps, state, domRef);
|
32
56
|
const styles = useMemo(() => extractStyles(completeProps, CONTAINER_STYLES), [completeProps]);
|
33
57
|
const defaultProps = {
|
34
58
|
qa,
|
35
59
|
styles,
|
60
|
+
'data-size': size,
|
36
61
|
mods: {
|
37
62
|
sections: hasSections,
|
38
63
|
footer: !!footer,
|
39
64
|
header: !!header,
|
65
|
+
popover: completeProps.mods?.popover,
|
40
66
|
},
|
41
67
|
};
|
42
68
|
// Sync the ref stored in the context object with the DOM ref returned by useDOMRef.
|
@@ -51,11 +77,11 @@ function Menu(props, ref) {
|
|
51
77
|
if (!isFirstSection) {
|
52
78
|
items.push(_jsx(StyledDivider, { role: "separator", "aria-orientation": "horizontal" }, `divider-${String(item.key)}`));
|
53
79
|
}
|
54
|
-
items.push(_jsx(MenuSection, { item: item, state: state, styles: sectionStyles, itemStyles: itemStyles, headingStyles: sectionHeadingStyles, selectionIcon: selectionIcon }, item.key));
|
80
|
+
items.push(_jsx(MenuSection, { item: item, state: state, styles: sectionStyles, itemStyles: itemStyles, headingStyles: sectionHeadingStyles, selectionIcon: selectionIcon, size: size }, item.key));
|
55
81
|
isFirstSection = false;
|
56
82
|
return;
|
57
83
|
}
|
58
|
-
let menuItem = (_jsx(MenuItem, { item: item, state: state, styles: itemStyles, selectionIcon: selectionIcon, onAction: item.onAction }, item.key));
|
84
|
+
let menuItem = (_jsx(MenuItem, { item: item, state: state, styles: itemStyles, selectionIcon: selectionIcon, size: size, onAction: item.onAction }, item.key));
|
59
85
|
// Apply tooltip wrapper if tooltip property is provided
|
60
86
|
if (item.props.tooltip) {
|
61
87
|
const tooltipProps = typeof item.props.tooltip === 'string'
|
@@ -79,7 +105,7 @@ function Menu(props, ref) {
|
|
79
105
|
selectionIcon,
|
80
106
|
sectionHeadingStyles,
|
81
107
|
]);
|
82
|
-
return (_jsxs(StyledMenu, { ...mergeProps(defaultProps, menuProps, filterBaseProps(completeProps)), ref: domRef, role: menuProps.role ?? 'menu', children: [header && _jsx(StyledHeader, { role: "presentation", children: header }), renderedItems] }));
|
108
|
+
return (_jsxs(StyledMenu, { ...mergeProps(defaultProps, menuProps, filterBaseProps(completeProps)), ref: domRef, role: menuProps.role ?? 'menu', children: [header && _jsx(StyledHeader, { role: "presentation", children: header }), renderedItems, footer && _jsx(StyledFooter, { role: "presentation", children: footer })] }));
|
83
109
|
}
|
84
110
|
// forwardRef doesn't support generic parameters, so cast the result to the correct type
|
85
111
|
// https://stackoverflow.com/questions/58469229/react-with-typescript-generics-while-using-react-forwardref
|