@cube-dev/ui-kit 0.67.0 → 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 +20 -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 +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 -1
- 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 +1 -1
- 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 +1 -1
- package/es/components/actions/use-action.js +1 -1
- package/es/components/actions/use-anchored-menu.js +1 -1
- package/es/components/actions/use-context-menu.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 +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 +1 -1
- 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 +12 -6
- 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 +1 -1
- package/es/components/overlays/Dialog/use-dialog-container.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/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 +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 +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 +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 +2 -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 +1 -1
- package/es/utils/react/useCombinedRefs.js +1 -1
- package/es/utils/react/useControlledFocusVisible.js +42 -0
- package/es/utils/react/useEventBus.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 +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/styled.d.ts +1 -0
- 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 +6 -0
- package/types/components/fields/index.d.ts +2 -0
- 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/react/index.d.ts +2 -0
- package/types/utils/react/useControlledFocusVisible.d.ts +10 -0
@@ -0,0 +1,580 @@
|
|
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 React, { forwardRef, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
10
|
+
import { useFilter, useKeyboard } from 'react-aria';
|
11
|
+
import { Section as BaseSection, Item } from 'react-stately';
|
12
|
+
import { LoadingIcon, SearchIcon } from '../../../icons';
|
13
|
+
import { useProviderProps } from '../../../provider';
|
14
|
+
import { BASE_STYLES, COLOR_STYLES, extractStyles, OUTER_STYLES, tasty, } from '../../../tasty';
|
15
|
+
import { mergeProps, modAttrs, useCombinedRefs } from '../../../utils/react';
|
16
|
+
import { useFocus } from '../../../utils/react/interactions';
|
17
|
+
import { StyledHeader } from '../../actions/Menu/styled';
|
18
|
+
import { Block } from '../../Block';
|
19
|
+
import { useFieldProps, useFormProps, wrapWithField } from '../../form';
|
20
|
+
import { ListBox } from '../ListBox/ListBox';
|
21
|
+
import { DEFAULT_INPUT_STYLES, INPUT_WRAPPER_STYLES, } from '../TextInput/TextInputBase';
|
22
|
+
const FilterListBoxWrapperElement = tasty({
|
23
|
+
styles: {
|
24
|
+
display: 'grid',
|
25
|
+
flow: 'column',
|
26
|
+
gridColumns: '1sf',
|
27
|
+
gridRows: 'max-content max-content 1sf',
|
28
|
+
gap: 0,
|
29
|
+
position: 'relative',
|
30
|
+
radius: true,
|
31
|
+
color: '#dark-02',
|
32
|
+
transition: 'theme',
|
33
|
+
outline: {
|
34
|
+
'': '#purple-03.0',
|
35
|
+
'invalid & focused': '#danger.50',
|
36
|
+
focused: '#purple-03',
|
37
|
+
},
|
38
|
+
height: {
|
39
|
+
'': false,
|
40
|
+
popover: 'initial max-content (50vh - 4x)',
|
41
|
+
},
|
42
|
+
border: {
|
43
|
+
'': true,
|
44
|
+
focused: '#purple-text',
|
45
|
+
valid: '#success-text.50',
|
46
|
+
invalid: '#danger-text.50',
|
47
|
+
disabled: true,
|
48
|
+
popover: false,
|
49
|
+
},
|
50
|
+
},
|
51
|
+
});
|
52
|
+
const SearchWrapperElement = tasty({
|
53
|
+
styles: {
|
54
|
+
...INPUT_WRAPPER_STYLES,
|
55
|
+
border: 'bottom',
|
56
|
+
radius: '1r top',
|
57
|
+
fill: '#clear',
|
58
|
+
},
|
59
|
+
});
|
60
|
+
const SearchInputElement = tasty({
|
61
|
+
as: 'input',
|
62
|
+
styles: {
|
63
|
+
...DEFAULT_INPUT_STYLES,
|
64
|
+
fill: '#clear',
|
65
|
+
},
|
66
|
+
});
|
67
|
+
const StyledHeaderWithoutBorder = tasty(StyledHeader, {
|
68
|
+
styles: {
|
69
|
+
border: false,
|
70
|
+
},
|
71
|
+
});
|
72
|
+
const PROP_STYLES = [...BASE_STYLES, ...OUTER_STYLES, ...COLOR_STYLES];
|
73
|
+
export const FilterListBox = forwardRef(function FilterListBox(props, ref) {
|
74
|
+
props = useProviderProps(props);
|
75
|
+
props = useFormProps(props);
|
76
|
+
props = useFieldProps(props, {
|
77
|
+
valuePropsMapper: ({ value, onChange }) => {
|
78
|
+
const fieldProps = {};
|
79
|
+
if (props.selectionMode === 'multiple') {
|
80
|
+
fieldProps.selectedKeys = value || [];
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
fieldProps.selectedKey = value ?? null;
|
84
|
+
}
|
85
|
+
fieldProps.onSelectionChange = (key) => {
|
86
|
+
if (props.selectionMode === 'multiple') {
|
87
|
+
onChange(key ? (Array.isArray(key) ? key : [key]) : []);
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
onChange(Array.isArray(key) ? key[0] : key);
|
91
|
+
}
|
92
|
+
};
|
93
|
+
return fieldProps;
|
94
|
+
},
|
95
|
+
});
|
96
|
+
let { qa, label, extra, labelStyles, isRequired, necessityIndicator, validationState, isDisabled, isLoading, searchPlaceholder = 'Search...', autoFocus, filter, mods: externalMods, emptyLabel, searchInputStyles, listStyles, optionStyles, sectionStyles, headingStyles, searchInputRef, listRef, message, description, styles, focusOnHover, labelSuffix, selectedKey, defaultSelectedKey, selectedKeys, defaultSelectedKeys, onSelectionChange: externalOnSelectionChange, allowsCustomValue = false, header, footer, size = 'small', headerStyles, footerStyles, listBoxStyles, children, onEscape, isCheckable, onOptionClick, selectionMode = 'single', ...otherProps } = props;
|
97
|
+
// Collect original option keys to avoid duplicating them as custom values.
|
98
|
+
const originalKeys = useMemo(() => {
|
99
|
+
const keys = new Set();
|
100
|
+
const collectKeys = (nodes) => {
|
101
|
+
React.Children.forEach(nodes, (child) => {
|
102
|
+
if (!child || typeof child !== 'object')
|
103
|
+
return;
|
104
|
+
if (child.type === Item) {
|
105
|
+
if (child.key != null)
|
106
|
+
keys.add(String(child.key));
|
107
|
+
}
|
108
|
+
if (child.props?.children) {
|
109
|
+
collectKeys(child.props.children);
|
110
|
+
}
|
111
|
+
});
|
112
|
+
};
|
113
|
+
if (children)
|
114
|
+
collectKeys(children);
|
115
|
+
return keys;
|
116
|
+
}, [children]);
|
117
|
+
// State to keep track of custom (user-entered) items that were selected.
|
118
|
+
const [customKeys, setCustomKeys] = useState(new Set());
|
119
|
+
// Initialize custom keys from current selection
|
120
|
+
React.useEffect(() => {
|
121
|
+
if (!allowsCustomValue)
|
122
|
+
return;
|
123
|
+
const currentSelectedKeys = selectedKeys
|
124
|
+
? Array.from(selectedKeys).map(String)
|
125
|
+
: selectedKey != null
|
126
|
+
? [String(selectedKey)]
|
127
|
+
: [];
|
128
|
+
if (currentSelectedKeys.length === 0)
|
129
|
+
return;
|
130
|
+
const keysToAdd = currentSelectedKeys.filter((k) => !originalKeys.has(k));
|
131
|
+
if (keysToAdd.length) {
|
132
|
+
setCustomKeys((prev) => new Set([...Array.from(prev), ...keysToAdd]));
|
133
|
+
}
|
134
|
+
}, [allowsCustomValue, selectedKeys, selectedKey, originalKeys]);
|
135
|
+
// Merge original children with any custom items so they persist in the list.
|
136
|
+
// If there are selected custom values, they should appear on top with other
|
137
|
+
// selected items (which are already sorted by the parent component, e.g. FilterPicker).
|
138
|
+
const mergedChildren = useMemo(() => {
|
139
|
+
if (!children && customKeys.size === 0)
|
140
|
+
return children;
|
141
|
+
// Build React elements for custom values (kept stable via their key).
|
142
|
+
const customArray = Array.from(customKeys).map((key) => (_jsx(Item, { textValue: key, children: key }, key)));
|
143
|
+
// Identify which custom keys are currently selected so we can promote them.
|
144
|
+
const selectedKeysSet = new Set();
|
145
|
+
if (selectionMode === 'multiple') {
|
146
|
+
Array.from(selectedKeys ?? []).forEach((k) => selectedKeysSet.add(String(k)));
|
147
|
+
}
|
148
|
+
else {
|
149
|
+
if (selectedKey != null)
|
150
|
+
selectedKeysSet.add(String(selectedKey));
|
151
|
+
}
|
152
|
+
const selectedCustom = [];
|
153
|
+
const unselectedCustom = [];
|
154
|
+
customArray.forEach((item) => {
|
155
|
+
if (selectedKeysSet.has(String(item.key))) {
|
156
|
+
selectedCustom.push(item);
|
157
|
+
}
|
158
|
+
else {
|
159
|
+
unselectedCustom.push(item);
|
160
|
+
}
|
161
|
+
});
|
162
|
+
if (!children) {
|
163
|
+
// No original items – just return selected custom followed by the rest.
|
164
|
+
return [...selectedCustom, ...unselectedCustom];
|
165
|
+
}
|
166
|
+
const originalArray = Array.isArray(children) ? children : [children];
|
167
|
+
// Final order: selected custom items -> original array (already possibly
|
168
|
+
// sorted by parent) -> unselected custom items.
|
169
|
+
return [...selectedCustom, ...originalArray, ...unselectedCustom];
|
170
|
+
}, [children, customKeys, selectionMode, selectedKey, selectedKeys]);
|
171
|
+
// Determine an aria-label for the internal ListBox to avoid React Aria warnings.
|
172
|
+
const innerAriaLabel = props['aria-label'] ||
|
173
|
+
(typeof label === 'string' ? label : undefined);
|
174
|
+
const [searchValue, setSearchValue] = useState('');
|
175
|
+
const { contains } = useFilter({ sensitivity: 'base' });
|
176
|
+
// Choose the text filter function: user-provided `filter` prop (if any)
|
177
|
+
// or the default `contains` helper from `useFilter`.
|
178
|
+
const textFilterFn = useMemo(() => filter || contains, [filter, contains]);
|
179
|
+
// Filter children based on search value
|
180
|
+
const filteredChildren = useMemo(() => {
|
181
|
+
const term = searchValue.trim();
|
182
|
+
if (!term || !mergedChildren) {
|
183
|
+
return mergedChildren;
|
184
|
+
}
|
185
|
+
// Helper to check if a node matches the search term
|
186
|
+
const nodeMatches = (node) => {
|
187
|
+
if (!node?.props)
|
188
|
+
return false;
|
189
|
+
// Get text content from the node
|
190
|
+
const textValue = node.props.textValue ||
|
191
|
+
(typeof node.props.children === 'string' ? node.props.children : '') ||
|
192
|
+
String(node.props.children || '');
|
193
|
+
return textFilterFn(textValue, term);
|
194
|
+
};
|
195
|
+
// Helper to filter React children recursively
|
196
|
+
const filterChildren = (childNodes) => {
|
197
|
+
if (!childNodes)
|
198
|
+
return null;
|
199
|
+
const childArray = Array.isArray(childNodes) ? childNodes : [childNodes];
|
200
|
+
const filteredNodes = [];
|
201
|
+
childArray.forEach((child) => {
|
202
|
+
if (!child || typeof child !== 'object') {
|
203
|
+
return;
|
204
|
+
}
|
205
|
+
// Handle ListBox.Section
|
206
|
+
if (child.type === BaseSection ||
|
207
|
+
child.type?.displayName === 'Section') {
|
208
|
+
const sectionChildren = Array.isArray(child.props.children)
|
209
|
+
? child.props.children
|
210
|
+
: [child.props.children];
|
211
|
+
const filteredSectionChildren = sectionChildren.filter((sectionChild) => {
|
212
|
+
return (sectionChild &&
|
213
|
+
typeof sectionChild === 'object' &&
|
214
|
+
nodeMatches(sectionChild));
|
215
|
+
});
|
216
|
+
if (filteredSectionChildren.length > 0) {
|
217
|
+
// Store filtered children in a way that doesn't require cloning the section
|
218
|
+
const filteredSection = {
|
219
|
+
...child,
|
220
|
+
filteredChildren: filteredSectionChildren,
|
221
|
+
};
|
222
|
+
filteredNodes.push(filteredSection);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
// Handle ListBox.Item
|
226
|
+
else if (child.type === Item) {
|
227
|
+
if (nodeMatches(child)) {
|
228
|
+
filteredNodes.push(child);
|
229
|
+
}
|
230
|
+
}
|
231
|
+
// Handle other components
|
232
|
+
else if (nodeMatches(child)) {
|
233
|
+
filteredNodes.push(child);
|
234
|
+
}
|
235
|
+
});
|
236
|
+
return filteredNodes;
|
237
|
+
};
|
238
|
+
return filterChildren(mergedChildren);
|
239
|
+
}, [mergedChildren, searchValue, textFilterFn]);
|
240
|
+
// Handle custom values if allowed
|
241
|
+
const enhancedChildren = useMemo(() => {
|
242
|
+
let childrenToProcess = filteredChildren;
|
243
|
+
// Handle custom values if allowed
|
244
|
+
if (!allowsCustomValue)
|
245
|
+
return childrenToProcess;
|
246
|
+
const term = searchValue.trim();
|
247
|
+
if (!term)
|
248
|
+
return childrenToProcess;
|
249
|
+
// Helper to determine if the term is already present (exact match on rendered textValue or the key).
|
250
|
+
const doesTermExist = (nodes) => {
|
251
|
+
let exists = false;
|
252
|
+
const checkNodes = (childNodes) => {
|
253
|
+
React.Children.forEach(childNodes, (child) => {
|
254
|
+
if (!child || typeof child !== 'object')
|
255
|
+
return;
|
256
|
+
// Check items directly
|
257
|
+
if (child.type === Item) {
|
258
|
+
const childText = child.props.textValue ||
|
259
|
+
(typeof child.props.children === 'string'
|
260
|
+
? child.props.children
|
261
|
+
: '') ||
|
262
|
+
String(child.props.children ?? '');
|
263
|
+
if (term === childText || String(child.key) === term) {
|
264
|
+
exists = true;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
// Recurse into sections or other wrappers
|
268
|
+
if (child.props?.children) {
|
269
|
+
checkNodes(child.props.children);
|
270
|
+
}
|
271
|
+
});
|
272
|
+
};
|
273
|
+
checkNodes(nodes);
|
274
|
+
return exists;
|
275
|
+
};
|
276
|
+
if (doesTermExist(mergedChildren)) {
|
277
|
+
return childrenToProcess;
|
278
|
+
}
|
279
|
+
// Append the custom option at the end.
|
280
|
+
const customOption = (_jsx(Item, { textValue: term, children: term }, term));
|
281
|
+
if (Array.isArray(childrenToProcess)) {
|
282
|
+
return [...childrenToProcess, customOption];
|
283
|
+
}
|
284
|
+
if (childrenToProcess) {
|
285
|
+
return [childrenToProcess, customOption];
|
286
|
+
}
|
287
|
+
return customOption;
|
288
|
+
}, [allowsCustomValue, filteredChildren, mergedChildren, searchValue]);
|
289
|
+
// Convert custom objects back to React elements for rendering
|
290
|
+
const finalChildren = useMemo(() => {
|
291
|
+
if (!enhancedChildren)
|
292
|
+
return enhancedChildren;
|
293
|
+
const convertToReactElements = (nodes) => {
|
294
|
+
if (!nodes)
|
295
|
+
return nodes;
|
296
|
+
const nodeArray = Array.isArray(nodes) ? nodes : [nodes];
|
297
|
+
return nodeArray.map((node, index) => {
|
298
|
+
if (!node || typeof node !== 'object') {
|
299
|
+
return node;
|
300
|
+
}
|
301
|
+
// Handle our custom filtered section objects
|
302
|
+
if (node.filteredChildren) {
|
303
|
+
const childrenToUse = node.filteredChildren;
|
304
|
+
// Return the original section but with the processed children
|
305
|
+
return React.cloneElement(node, {
|
306
|
+
key: node.key || index,
|
307
|
+
children: childrenToUse,
|
308
|
+
});
|
309
|
+
}
|
310
|
+
// Handle regular React elements
|
311
|
+
return node;
|
312
|
+
});
|
313
|
+
};
|
314
|
+
return convertToReactElements(enhancedChildren);
|
315
|
+
}, [enhancedChildren]);
|
316
|
+
styles = extractStyles(otherProps, PROP_STYLES, styles);
|
317
|
+
ref = useCombinedRefs(ref);
|
318
|
+
searchInputRef = useCombinedRefs(searchInputRef);
|
319
|
+
listRef = useCombinedRefs(listRef);
|
320
|
+
const { isFocused, focusProps } = useFocus({ isDisabled });
|
321
|
+
const isInvalid = validationState === 'invalid';
|
322
|
+
const listBoxRef = useRef(null);
|
323
|
+
// Ref to access internal ListBox state (selection manager, etc.)
|
324
|
+
const listStateRef = useRef(null);
|
325
|
+
// No separate focusedKey state needed; rely directly on selectionManager.focusedKey.
|
326
|
+
// When the search value changes, the visible collection of items may change as well.
|
327
|
+
// If the currently focused item is no longer visible, move virtual focus to the first
|
328
|
+
// available item so that arrow navigation and Enter behaviour continue to work.
|
329
|
+
// If there are no available items, reset the selection so Enter won't select anything.
|
330
|
+
useLayoutEffect(() => {
|
331
|
+
const listState = listStateRef.current;
|
332
|
+
if (!listState)
|
333
|
+
return;
|
334
|
+
const { selectionManager, collection } = listState;
|
335
|
+
// Helper to collect visible item keys (supports sections)
|
336
|
+
const collectVisibleKeys = (nodes, out) => {
|
337
|
+
const term = searchValue.trim();
|
338
|
+
for (const node of nodes) {
|
339
|
+
if (node.type === 'item') {
|
340
|
+
const text = node.textValue ?? String(node.rendered ?? '');
|
341
|
+
if (!term || textFilterFn(text, term)) {
|
342
|
+
out.push(node.key);
|
343
|
+
}
|
344
|
+
}
|
345
|
+
else if (node.childNodes) {
|
346
|
+
collectVisibleKeys(node.childNodes, out);
|
347
|
+
}
|
348
|
+
}
|
349
|
+
};
|
350
|
+
const visibleKeys = [];
|
351
|
+
collectVisibleKeys(collection, visibleKeys);
|
352
|
+
// If there are no visible items, reset the focused key so Enter won't select anything
|
353
|
+
if (visibleKeys.length === 0) {
|
354
|
+
selectionManager.setFocusedKey(null);
|
355
|
+
return;
|
356
|
+
}
|
357
|
+
// Early exit if the current focused key is still present in the visible items.
|
358
|
+
const currentFocused = selectionManager.focusedKey;
|
359
|
+
if (currentFocused != null && visibleKeys.includes(currentFocused)) {
|
360
|
+
return;
|
361
|
+
}
|
362
|
+
// Set focus to the first visible item
|
363
|
+
selectionManager.setFocusedKey(visibleKeys[0]);
|
364
|
+
}, [searchValue, enhancedChildren, textFilterFn]);
|
365
|
+
// Keyboard navigation handler for search input
|
366
|
+
const { keyboardProps } = useKeyboard({
|
367
|
+
onKeyDown: (e) => {
|
368
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
369
|
+
e.preventDefault();
|
370
|
+
const listState = listStateRef.current;
|
371
|
+
if (!listState)
|
372
|
+
return;
|
373
|
+
const { selectionManager, collection } = listState;
|
374
|
+
// Helper to collect visible item keys (supports sections)
|
375
|
+
const collectVisibleKeys = (nodes, out) => {
|
376
|
+
const term = searchValue.trim();
|
377
|
+
for (const node of nodes) {
|
378
|
+
if (node.type === 'item') {
|
379
|
+
const text = node.textValue ?? String(node.rendered ?? '');
|
380
|
+
if (!term || textFilterFn(text, term)) {
|
381
|
+
out.push(node.key);
|
382
|
+
}
|
383
|
+
}
|
384
|
+
else if (node.childNodes) {
|
385
|
+
collectVisibleKeys(node.childNodes, out);
|
386
|
+
}
|
387
|
+
}
|
388
|
+
};
|
389
|
+
const visibleKeys = [];
|
390
|
+
collectVisibleKeys(collection, visibleKeys);
|
391
|
+
if (visibleKeys.length === 0)
|
392
|
+
return;
|
393
|
+
const isArrowDown = e.key === 'ArrowDown';
|
394
|
+
const direction = isArrowDown ? 1 : -1;
|
395
|
+
const currentKey = selectionManager.focusedKey;
|
396
|
+
let nextKey = null;
|
397
|
+
if (currentKey == null) {
|
398
|
+
// If nothing focused yet, pick first/last depending on direction
|
399
|
+
nextKey = isArrowDown
|
400
|
+
? visibleKeys[0]
|
401
|
+
: visibleKeys[visibleKeys.length - 1];
|
402
|
+
}
|
403
|
+
else {
|
404
|
+
const currentIndex = visibleKeys.indexOf(currentKey);
|
405
|
+
if (currentIndex !== -1) {
|
406
|
+
const newIndex = currentIndex + direction;
|
407
|
+
if (newIndex >= 0 && newIndex < visibleKeys.length) {
|
408
|
+
nextKey = visibleKeys[newIndex];
|
409
|
+
}
|
410
|
+
else {
|
411
|
+
// Wrap around
|
412
|
+
nextKey = isArrowDown
|
413
|
+
? visibleKeys[0]
|
414
|
+
: visibleKeys[visibleKeys.length - 1];
|
415
|
+
}
|
416
|
+
}
|
417
|
+
else {
|
418
|
+
// Fallback
|
419
|
+
nextKey = isArrowDown
|
420
|
+
? visibleKeys[0]
|
421
|
+
: visibleKeys[visibleKeys.length - 1];
|
422
|
+
}
|
423
|
+
}
|
424
|
+
if (nextKey != null) {
|
425
|
+
// Mark this focus change as keyboard navigation
|
426
|
+
if (listState.lastFocusSourceRef) {
|
427
|
+
listState.lastFocusSourceRef.current = 'keyboard';
|
428
|
+
}
|
429
|
+
selectionManager.setFocusedKey(nextKey);
|
430
|
+
}
|
431
|
+
}
|
432
|
+
else if (e.key === 'Home' ||
|
433
|
+
e.key === 'End' ||
|
434
|
+
e.key === 'PageUp' ||
|
435
|
+
e.key === 'PageDown') {
|
436
|
+
e.preventDefault();
|
437
|
+
const listState = listStateRef.current;
|
438
|
+
if (!listState)
|
439
|
+
return;
|
440
|
+
const { selectionManager, collection } = listState;
|
441
|
+
// Helper to collect visible item keys (supports sections)
|
442
|
+
const collectVisibleKeys = (nodes, out) => {
|
443
|
+
const term = searchValue.trim();
|
444
|
+
for (const node of nodes) {
|
445
|
+
if (node.type === 'item') {
|
446
|
+
const text = node.textValue ?? String(node.rendered ?? '');
|
447
|
+
if (!term || textFilterFn(text, term)) {
|
448
|
+
out.push(node.key);
|
449
|
+
}
|
450
|
+
}
|
451
|
+
else if (node.childNodes) {
|
452
|
+
collectVisibleKeys(node.childNodes, out);
|
453
|
+
}
|
454
|
+
}
|
455
|
+
};
|
456
|
+
const visibleKeys = [];
|
457
|
+
collectVisibleKeys(collection, visibleKeys);
|
458
|
+
if (visibleKeys.length === 0)
|
459
|
+
return;
|
460
|
+
const targetKey = e.key === 'Home' || e.key === 'PageUp'
|
461
|
+
? visibleKeys[0]
|
462
|
+
: visibleKeys[visibleKeys.length - 1];
|
463
|
+
// Mark this focus change as keyboard navigation
|
464
|
+
if (listState.lastFocusSourceRef) {
|
465
|
+
listState.lastFocusSourceRef.current = 'keyboard';
|
466
|
+
}
|
467
|
+
selectionManager.setFocusedKey(targetKey);
|
468
|
+
}
|
469
|
+
else if (e.key === 'Enter' || (e.key === ' ' && !searchValue)) {
|
470
|
+
const listState = listStateRef.current;
|
471
|
+
if (!listState)
|
472
|
+
return;
|
473
|
+
const keyToSelect = listState.selectionManager.focusedKey;
|
474
|
+
if (keyToSelect != null) {
|
475
|
+
e.preventDefault();
|
476
|
+
listState.selectionManager.select(keyToSelect, e);
|
477
|
+
if (e.key === 'Enter' &&
|
478
|
+
isCheckable &&
|
479
|
+
onEscape &&
|
480
|
+
selectionMode === 'multiple') {
|
481
|
+
onEscape();
|
482
|
+
}
|
483
|
+
}
|
484
|
+
}
|
485
|
+
else if (e.key === 'Escape') {
|
486
|
+
if (searchValue) {
|
487
|
+
// Clear the current search if any text is present.
|
488
|
+
e.preventDefault();
|
489
|
+
setSearchValue('');
|
490
|
+
}
|
491
|
+
else {
|
492
|
+
// Notify parent that Escape was pressed on an empty input.
|
493
|
+
if (onEscape) {
|
494
|
+
e.preventDefault();
|
495
|
+
onEscape();
|
496
|
+
}
|
497
|
+
}
|
498
|
+
}
|
499
|
+
},
|
500
|
+
});
|
501
|
+
const mods = useMemo(() => ({
|
502
|
+
invalid: isInvalid,
|
503
|
+
valid: validationState === 'valid',
|
504
|
+
disabled: !!isDisabled,
|
505
|
+
focused: isFocused,
|
506
|
+
loading: !!isLoading,
|
507
|
+
searchable: true,
|
508
|
+
...externalMods,
|
509
|
+
}), [
|
510
|
+
isInvalid,
|
511
|
+
validationState,
|
512
|
+
isDisabled,
|
513
|
+
isFocused,
|
514
|
+
isLoading,
|
515
|
+
externalMods,
|
516
|
+
]);
|
517
|
+
const hasResults = enhancedChildren &&
|
518
|
+
(Array.isArray(enhancedChildren)
|
519
|
+
? enhancedChildren.length > 0
|
520
|
+
: enhancedChildren !== null);
|
521
|
+
const showEmptyMessage = !hasResults && searchValue.trim();
|
522
|
+
// Handler must be defined before we render ListBox so we can pass it.
|
523
|
+
const handleSelectionChange = (selection) => {
|
524
|
+
if (allowsCustomValue) {
|
525
|
+
// Normalize current selection into an array of string keys
|
526
|
+
let selectedValues = [];
|
527
|
+
if (selection != null) {
|
528
|
+
if (Array.isArray(selection)) {
|
529
|
+
selectedValues = selection.map(String);
|
530
|
+
}
|
531
|
+
else {
|
532
|
+
selectedValues = [String(selection)];
|
533
|
+
}
|
534
|
+
}
|
535
|
+
// Build next custom keys set based on selected values
|
536
|
+
const nextSet = new Set();
|
537
|
+
selectedValues.forEach((val) => {
|
538
|
+
if (!originalKeys.has(val)) {
|
539
|
+
nextSet.add(val);
|
540
|
+
}
|
541
|
+
});
|
542
|
+
// Update internal custom keys state
|
543
|
+
setCustomKeys(nextSet);
|
544
|
+
}
|
545
|
+
if (externalOnSelectionChange) {
|
546
|
+
externalOnSelectionChange(selection);
|
547
|
+
}
|
548
|
+
};
|
549
|
+
// Custom option click handler that ensures search input receives focus
|
550
|
+
const handleOptionClick = (key) => {
|
551
|
+
// Focus the search input to enable keyboard navigation
|
552
|
+
// Use setTimeout to ensure this happens after React state updates
|
553
|
+
setTimeout(() => {
|
554
|
+
if (searchInputRef.current) {
|
555
|
+
searchInputRef.current.focus();
|
556
|
+
}
|
557
|
+
}, 0);
|
558
|
+
// Call the original onOptionClick if provided
|
559
|
+
if (onOptionClick) {
|
560
|
+
onOptionClick(key);
|
561
|
+
}
|
562
|
+
};
|
563
|
+
const searchInput = (_jsxs(SearchWrapperElement, { mods: mods, "data-size": "small", children: [_jsx(SearchInputElement, { ref: searchInputRef, "data-is-prefix": true, type: "search", placeholder: searchPlaceholder, value: searchValue, disabled: isDisabled, autoFocus: autoFocus, "data-autofocus": autoFocus ? '' : undefined, styles: searchInputStyles, "data-size": size, role: "combobox", "aria-expanded": "true", "aria-haspopup": "listbox", "aria-activedescendant": listStateRef.current?.selectionManager.focusedKey != null
|
564
|
+
? `ListBoxItem-${listStateRef.current?.selectionManager.focusedKey}`
|
565
|
+
: undefined, onChange: (e) => {
|
566
|
+
const value = e.target.value;
|
567
|
+
setSearchValue(value);
|
568
|
+
}, ...keyboardProps, ...modAttrs(mods) }), _jsx("div", { "data-element": "Prefix", children: _jsx("div", { "data-element": "InputIcon", children: isLoading ? _jsx(LoadingIcon, {}) : _jsx(SearchIcon, {}) }) })] }));
|
569
|
+
const filterListBoxField = (_jsxs(FilterListBoxWrapperElement, { ref: ref, qa: qa || 'FilterListBox', ...modAttrs(mods), styles: styles, ...focusProps, children: [header ? (_jsx(StyledHeaderWithoutBorder, { "data-size": size, styles: headerStyles, children: header })) : (_jsx("div", { role: "presentation" })), searchInput, showEmptyMessage ? (_jsx("div", { style: { padding: '0.75rem 1rem' }, children: _jsx(Block, { preset: "t4", color: "#dark-03", children: emptyLabel !== undefined ? emptyLabel : 'No results found' }) })) : (_jsx(ListBox, { ref: listBoxRef, "aria-label": innerAriaLabel, selectedKey: selectedKey, defaultSelectedKey: defaultSelectedKey, selectedKeys: selectedKeys, defaultSelectedKeys: defaultSelectedKeys, selectionMode: selectionMode, isDisabled: isDisabled, listRef: listRef, stateRef: listStateRef, listStyles: listStyles, optionStyles: optionStyles, sectionStyles: sectionStyles, headingStyles: headingStyles, validationState: validationState, disallowEmptySelection: props.disallowEmptySelection, disabledKeys: props.disabledKeys, focusOnHover: focusOnHover, shouldUseVirtualFocus: true, footer: footer, footerStyles: footerStyles, mods: mods, size: size, isCheckable: isCheckable, onSelectionChange: handleSelectionChange, onEscape: onEscape, onOptionClick: handleOptionClick, children: finalChildren }))] }));
|
570
|
+
return wrapWithField(filterListBoxField, ref, mergeProps({ ...props, styles: undefined }, {}));
|
571
|
+
});
|
572
|
+
FilterListBox.Item = ListBox.Item;
|
573
|
+
FilterListBox.Section = BaseSection;
|
574
|
+
Object.defineProperty(FilterListBox, 'cubeInputType', {
|
575
|
+
value: 'FilterListBox',
|
576
|
+
enumerable: false,
|
577
|
+
configurable: false,
|
578
|
+
});
|
579
|
+
|
580
|
+
|