@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
@@ -1,30 +1,35 @@
|
|
1
1
|
/**
|
2
2
|
* @license MIT
|
3
3
|
* author: Cube Dev Team
|
4
|
-
* @cube-dev/ui-kit v0.
|
4
|
+
* @cube-dev/ui-kit v0.68.0
|
5
5
|
* Released under the MIT license.
|
6
6
|
*/
|
7
7
|
|
8
8
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
9
|
-
import {
|
10
|
-
import {
|
9
|
+
import { useHover } from '@react-aria/interactions';
|
10
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
11
|
+
import { forwardRef, useEffect, useMemo, useRef, } from 'react';
|
12
|
+
import { useKeyboard, useListBox, useListBoxSection, useOption, } from 'react-aria';
|
11
13
|
import { Section as BaseSection, Item, useListState } from 'react-stately';
|
12
|
-
import {
|
14
|
+
import { useWarn } from '../../../_internal/hooks/use-warn';
|
15
|
+
import { CheckIcon } from '../../../icons';
|
13
16
|
import { useProviderProps } from '../../../provider';
|
14
17
|
import { BASE_STYLES, COLOR_STYLES, extractStyles, OUTER_STYLES, tasty, } from '../../../tasty';
|
15
|
-
import { mergeProps,
|
18
|
+
import { mergeProps, useCombinedRefs } from '../../../utils/react';
|
16
19
|
import { useFocus } from '../../../utils/react/interactions';
|
17
|
-
|
20
|
+
// Import Menu styled components for header and footer
|
21
|
+
import { StyledDivider, StyledFooter, StyledHeader, StyledSectionHeading, } from '../../actions/Menu/styled';
|
18
22
|
import { useFieldProps, useFormProps, wrapWithField } from '../../form';
|
19
|
-
import { DEFAULT_INPUT_STYLES, INPUT_WRAPPER_STYLES, } from '../TextInput/TextInputBase';
|
20
23
|
const ListBoxWrapperElement = tasty({
|
24
|
+
qa: 'ListBox',
|
21
25
|
styles: {
|
22
|
-
display: '
|
26
|
+
display: 'grid',
|
27
|
+
gridColumns: '1sf',
|
28
|
+
gridRows: 'max-content 1sf max-content',
|
23
29
|
flow: 'column',
|
24
30
|
gap: 0,
|
25
31
|
position: 'relative',
|
26
|
-
radius:
|
27
|
-
fill: '#white',
|
32
|
+
radius: '1cr',
|
28
33
|
color: '#dark-02',
|
29
34
|
transition: 'theme',
|
30
35
|
outline: {
|
@@ -38,31 +43,31 @@ const ListBoxWrapperElement = tasty({
|
|
38
43
|
valid: '#success-text.50',
|
39
44
|
invalid: '#danger-text.50',
|
40
45
|
disabled: true,
|
46
|
+
'popover | searchable': false,
|
41
47
|
},
|
42
48
|
},
|
43
49
|
});
|
44
|
-
const SearchWrapperElement = tasty({
|
45
|
-
styles: {
|
46
|
-
...INPUT_WRAPPER_STYLES,
|
47
|
-
border: '#clear',
|
48
|
-
radius: '1r top',
|
49
|
-
borderBottom: '1bw solid #border',
|
50
|
-
},
|
51
|
-
});
|
52
|
-
const SearchInputElement = tasty({
|
53
|
-
as: 'input',
|
54
|
-
styles: DEFAULT_INPUT_STYLES,
|
55
|
-
});
|
56
50
|
const ListElement = tasty({
|
57
51
|
as: 'ul',
|
58
52
|
styles: {
|
59
|
-
display: '
|
60
|
-
|
61
|
-
flow: 'column',
|
62
|
-
margin: '0',
|
63
|
-
padding: '.5x',
|
53
|
+
display: 'block',
|
54
|
+
padding: 0,
|
64
55
|
listStyle: 'none',
|
65
|
-
|
56
|
+
boxSizing: 'border-box',
|
57
|
+
margin: {
|
58
|
+
'': '.5x .5x 0 .5x',
|
59
|
+
sections: '0 .5x',
|
60
|
+
},
|
61
|
+
height: 'max-content',
|
62
|
+
},
|
63
|
+
});
|
64
|
+
// NEW: dedicated scroll container for ListBox
|
65
|
+
const ListBoxScrollElement = tasty({
|
66
|
+
as: 'div',
|
67
|
+
styles: {
|
68
|
+
display: 'grid',
|
69
|
+
gridColumns: '1sf',
|
70
|
+
gridRows: '1sf',
|
66
71
|
overflow: 'auto',
|
67
72
|
scrollbar: 'styled',
|
68
73
|
},
|
@@ -71,13 +76,25 @@ const OptionElement = tasty({
|
|
71
76
|
as: 'li',
|
72
77
|
styles: {
|
73
78
|
display: 'flex',
|
74
|
-
flow: '
|
75
|
-
|
76
|
-
|
79
|
+
flow: 'row',
|
80
|
+
placeItems: 'center start',
|
81
|
+
gap: '.75x',
|
82
|
+
padding: '.5x 1x',
|
83
|
+
margin: {
|
84
|
+
'': '0 0 1bw 0',
|
85
|
+
':last-of-type': '0',
|
86
|
+
},
|
87
|
+
height: {
|
88
|
+
'[data-size="small"]': 'min 4x',
|
89
|
+
'[data-size="medium"]': 'min 5x',
|
90
|
+
},
|
91
|
+
boxSizing: 'border-box',
|
77
92
|
radius: '1r',
|
78
|
-
cursor:
|
93
|
+
cursor: {
|
94
|
+
'': 'default',
|
95
|
+
disabled: 'not-allowed',
|
96
|
+
},
|
79
97
|
transition: 'theme',
|
80
|
-
outline: 0,
|
81
98
|
border: 0,
|
82
99
|
userSelect: 'none',
|
83
100
|
color: {
|
@@ -89,23 +106,75 @@ const OptionElement = tasty({
|
|
89
106
|
},
|
90
107
|
fill: {
|
91
108
|
'': '#clear',
|
92
|
-
focused: '#dark.03',
|
93
|
-
selected: '#dark.
|
94
|
-
'selected & focused': '#dark.
|
95
|
-
|
109
|
+
'hovered | focused': '#dark.03',
|
110
|
+
selected: '#dark.09',
|
111
|
+
'selected & (hovered | focused)': '#dark.12',
|
112
|
+
'selected & hovered & focused': '#dark.15',
|
113
|
+
pressed: '#dark.09',
|
96
114
|
valid: '#success-bg',
|
97
115
|
invalid: '#danger-bg',
|
98
116
|
disabled: '#clear',
|
99
117
|
},
|
118
|
+
outline: 0,
|
119
|
+
backgroundClip: 'padding-box',
|
120
|
+
CheckboxWrapper: {
|
121
|
+
cursor: 'pointer',
|
122
|
+
padding: '.75x',
|
123
|
+
margin: '-.75x',
|
124
|
+
},
|
125
|
+
Checkbox: {
|
126
|
+
display: 'grid',
|
127
|
+
placeItems: 'center',
|
128
|
+
radius: '.5r',
|
129
|
+
width: '(2x - 2bw)',
|
130
|
+
height: '(2x - 2bw)',
|
131
|
+
flexShrink: 0,
|
132
|
+
transition: 'theme',
|
133
|
+
opacity: {
|
134
|
+
'': 0,
|
135
|
+
'selected | :hover | focused': 1,
|
136
|
+
},
|
137
|
+
fill: {
|
138
|
+
'': '#white',
|
139
|
+
selected: '#purple-text',
|
140
|
+
'invalid & !selected': '#white',
|
141
|
+
'invalid & selected': '#danger',
|
142
|
+
disabled: '#dark.12',
|
143
|
+
},
|
144
|
+
color: {
|
145
|
+
'': '#white',
|
146
|
+
'disabled & !selected': '#clear',
|
147
|
+
},
|
148
|
+
border: {
|
149
|
+
'': '#dark.30',
|
150
|
+
invalid: '#danger',
|
151
|
+
'disabled | (selected & !invalid)': '#clear',
|
152
|
+
},
|
153
|
+
},
|
154
|
+
Content: {
|
155
|
+
display: 'flex',
|
156
|
+
flow: 'column',
|
157
|
+
gap: '.25x',
|
158
|
+
flex: 1,
|
159
|
+
width: 'max 100%',
|
160
|
+
},
|
100
161
|
Label: {
|
101
162
|
preset: 't3',
|
102
163
|
color: 'inherit',
|
164
|
+
overflow: 'hidden',
|
165
|
+
textOverflow: 'ellipsis',
|
166
|
+
whiteSpace: 'nowrap',
|
167
|
+
width: 'max 100%',
|
103
168
|
},
|
104
169
|
Description: {
|
105
170
|
preset: 't4',
|
106
171
|
color: {
|
107
172
|
'': '#dark-03',
|
108
173
|
},
|
174
|
+
overflow: 'hidden',
|
175
|
+
textOverflow: 'ellipsis',
|
176
|
+
whiteSpace: 'nowrap',
|
177
|
+
width: 'max 100%',
|
109
178
|
},
|
110
179
|
},
|
111
180
|
});
|
@@ -113,35 +182,24 @@ const SectionWrapperElement = tasty({
|
|
113
182
|
as: 'li',
|
114
183
|
styles: {
|
115
184
|
display: 'block',
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
preset: 't4 strong',
|
121
|
-
color: '#dark-03',
|
122
|
-
padding: '.5x 1x .25x',
|
123
|
-
userSelect: 'none',
|
185
|
+
padding: {
|
186
|
+
'': 0,
|
187
|
+
':last-of-type': '0 0 .5x 0',
|
188
|
+
},
|
124
189
|
},
|
125
190
|
});
|
126
191
|
const SectionListElement = tasty({
|
192
|
+
qa: 'ListBoxSectionList',
|
127
193
|
as: 'ul',
|
128
194
|
styles: {
|
129
195
|
display: 'flex',
|
130
|
-
gap: '
|
196
|
+
gap: '0',
|
131
197
|
flow: 'column',
|
132
198
|
margin: '0',
|
133
199
|
padding: '0',
|
134
200
|
listStyle: 'none',
|
135
201
|
},
|
136
202
|
});
|
137
|
-
const DividerElement = tasty({
|
138
|
-
as: 'li',
|
139
|
-
styles: {
|
140
|
-
height: '1bw',
|
141
|
-
fill: '#border',
|
142
|
-
margin: '.5x 0',
|
143
|
-
},
|
144
|
-
});
|
145
203
|
const PROP_STYLES = [...BASE_STYLES, ...OUTER_STYLES, ...COLOR_STYLES];
|
146
204
|
export const ListBox = forwardRef(function ListBox(props, ref) {
|
147
205
|
props = useProviderProps(props);
|
@@ -150,84 +208,23 @@ export const ListBox = forwardRef(function ListBox(props, ref) {
|
|
150
208
|
valuePropsMapper: ({ value, onChange }) => {
|
151
209
|
const fieldProps = {};
|
152
210
|
if (props.selectionMode === 'multiple') {
|
153
|
-
fieldProps.selectedKeys =
|
154
|
-
? value
|
155
|
-
: value
|
156
|
-
? [value]
|
157
|
-
: [];
|
211
|
+
fieldProps.selectedKeys = value || [];
|
158
212
|
}
|
159
213
|
else {
|
160
214
|
fieldProps.selectedKey = value ?? null;
|
161
215
|
}
|
162
216
|
fieldProps.onSelectionChange = (key) => {
|
163
217
|
if (props.selectionMode === 'multiple') {
|
164
|
-
|
165
|
-
onChange(key);
|
166
|
-
}
|
167
|
-
else if (key instanceof Set) {
|
168
|
-
onChange(Array.from(key));
|
169
|
-
}
|
170
|
-
else {
|
171
|
-
onChange(key ? [key] : []);
|
172
|
-
}
|
218
|
+
onChange(key ? (Array.isArray(key) ? key : [key]) : []);
|
173
219
|
}
|
174
220
|
else {
|
175
|
-
|
176
|
-
onChange(key.size === 0 ? null : Array.from(key)[0]);
|
177
|
-
}
|
178
|
-
else {
|
179
|
-
onChange(key);
|
180
|
-
}
|
221
|
+
onChange(Array.isArray(key) ? key[0] : key);
|
181
222
|
}
|
182
223
|
};
|
183
224
|
return fieldProps;
|
184
225
|
},
|
185
226
|
});
|
186
|
-
let { qa, label, extra, labelStyles, isRequired, necessityIndicator, validationState, isDisabled,
|
187
|
-
const [searchValue, setSearchValue] = useState('');
|
188
|
-
const { contains } = useFilter({ sensitivity: 'base' });
|
189
|
-
// Choose the text filter function: user-provided `filter` prop (if any)
|
190
|
-
// or the default `contains` helper from `useFilter`.
|
191
|
-
const textFilterFn = useMemo(() => filter || contains, [filter, contains]);
|
192
|
-
// Collection-level filter function expected by `useListState`.
|
193
|
-
// It converts the text filter (textValue, searchValue) ⟶ boolean
|
194
|
-
// into the shape `(nodes) => Iterable<Node<T>>`.
|
195
|
-
// The current `searchValue` is captured in the closure – every re-render
|
196
|
-
// produces a new function so React Stately updates the collection when the
|
197
|
-
// search term changes.
|
198
|
-
const collectionFilter = useCallback((nodes) => {
|
199
|
-
const term = searchValue.trim();
|
200
|
-
// If there is no search term, return nodes untouched to avoid
|
201
|
-
// unnecessary object allocations.
|
202
|
-
if (!term) {
|
203
|
-
return nodes;
|
204
|
-
}
|
205
|
-
// Recursive helper to filter sections and items.
|
206
|
-
const filterNodes = (iter) => {
|
207
|
-
const result = [];
|
208
|
-
for (const node of iter) {
|
209
|
-
if (node.type === 'section') {
|
210
|
-
const filteredChildren = filterNodes(node.childNodes);
|
211
|
-
if (filteredChildren.length) {
|
212
|
-
// Preserve the original node but replace `childNodes` with the
|
213
|
-
// filtered iterable so that React-Stately can still traverse it.
|
214
|
-
result.push({
|
215
|
-
...node,
|
216
|
-
childNodes: filteredChildren,
|
217
|
-
});
|
218
|
-
}
|
219
|
-
}
|
220
|
-
else {
|
221
|
-
const text = node.textValue ?? String(node.rendered ?? '');
|
222
|
-
if (textFilterFn(text, term)) {
|
223
|
-
result.push(node);
|
224
|
-
}
|
225
|
-
}
|
226
|
-
}
|
227
|
-
return result;
|
228
|
-
};
|
229
|
-
return filterNodes(nodes);
|
230
|
-
}, [searchValue, textFilterFn]);
|
227
|
+
let { qa, label, extra, labelStyles, isRequired, necessityIndicator, validationState, isDisabled, listStyles, optionStyles, sectionStyles, headingStyles, listRef, message, description, styles, mods: externalMods, size = 'small', labelSuffix, selectedKey, defaultSelectedKey, selectedKeys, defaultSelectedKeys, shouldUseVirtualFocus, onSelectionChange, stateRef, focusOnHover, header, footer, headerStyles, footerStyles, escapeKeyBehavior, onEscape, isCheckable, onOptionClick, ...otherProps } = props;
|
231
228
|
// Wrap onSelectionChange to prevent selection when disabled and handle React Aria's Set format
|
232
229
|
const externalSelectionHandler = onSelectionChange || props.onChange;
|
233
230
|
const wrappedOnSelectionChange = useMemo(() => {
|
@@ -259,7 +256,6 @@ export const ListBox = forwardRef(function ListBox(props, ref) {
|
|
259
256
|
// Prepare props for useListState with correct selection props
|
260
257
|
const listStateProps = {
|
261
258
|
...props,
|
262
|
-
filter: collectionFilter,
|
263
259
|
onSelectionChange: wrappedOnSelectionChange,
|
264
260
|
isDisabled,
|
265
261
|
selectionMode: props.selectionMode || 'single',
|
@@ -267,14 +263,10 @@ export const ListBox = forwardRef(function ListBox(props, ref) {
|
|
267
263
|
// Set selection props based on mode
|
268
264
|
if (listStateProps.selectionMode === 'multiple') {
|
269
265
|
if (selectedKeys !== undefined) {
|
270
|
-
listStateProps.selectedKeys =
|
271
|
-
selectedKeys === 'all' ? 'all' : new Set(selectedKeys);
|
266
|
+
listStateProps.selectedKeys = new Set(selectedKeys);
|
272
267
|
}
|
273
268
|
if (defaultSelectedKeys !== undefined) {
|
274
|
-
listStateProps.defaultSelectedKeys =
|
275
|
-
defaultSelectedKeys === 'all'
|
276
|
-
? 'all'
|
277
|
-
: new Set(defaultSelectedKeys);
|
269
|
+
listStateProps.defaultSelectedKeys = new Set(defaultSelectedKeys);
|
278
270
|
}
|
279
271
|
// Remove single-selection props if any
|
280
272
|
delete listStateProps.selectedKey;
|
@@ -295,170 +287,264 @@ export const ListBox = forwardRef(function ListBox(props, ref) {
|
|
295
287
|
delete listStateProps.selectedKey;
|
296
288
|
delete listStateProps.defaultSelectedKey;
|
297
289
|
}
|
298
|
-
const listState = useListState(
|
290
|
+
const listState = useListState({
|
291
|
+
...listStateProps,
|
292
|
+
});
|
293
|
+
// Track whether the last focus change was due to keyboard navigation
|
294
|
+
const lastFocusSourceRef = useRef('other');
|
295
|
+
// Expose the list state instance via the provided ref (if any)
|
296
|
+
if (stateRef) {
|
297
|
+
stateRef.current = {
|
298
|
+
...listState,
|
299
|
+
lastFocusSourceRef,
|
300
|
+
};
|
301
|
+
}
|
302
|
+
// Warn if isCheckable is false in single selection mode
|
303
|
+
useWarn(isCheckable === false && props.selectionMode === 'single', {
|
304
|
+
key: ['listbox-checkable-single-mode'],
|
305
|
+
args: [
|
306
|
+
'CubeUIKit: isCheckable=false is not recommended in single selection mode as it may confuse users about selection behavior.',
|
307
|
+
],
|
308
|
+
});
|
309
|
+
// Custom keyboard handling to prevent selection clearing on Escape while allowing overlay dismiss
|
310
|
+
const { keyboardProps } = useKeyboard({
|
311
|
+
onKeyDown: (e) => {
|
312
|
+
// Mark focus changes from keyboard navigation
|
313
|
+
if (e.key === 'ArrowDown' ||
|
314
|
+
e.key === 'ArrowUp' ||
|
315
|
+
e.key === 'Home' ||
|
316
|
+
e.key === 'End' ||
|
317
|
+
e.key === 'PageUp' ||
|
318
|
+
e.key === 'PageDown') {
|
319
|
+
lastFocusSourceRef.current = 'keyboard';
|
320
|
+
}
|
321
|
+
if (e.key === 'Escape' && onEscape) {
|
322
|
+
// Don't prevent default - let the overlay system handle closing
|
323
|
+
// But we'll call onEscape to potentially override the default selection clearing
|
324
|
+
onEscape();
|
325
|
+
}
|
326
|
+
},
|
327
|
+
});
|
299
328
|
styles = extractStyles(otherProps, PROP_STYLES, styles);
|
300
329
|
ref = useCombinedRefs(ref);
|
301
|
-
searchInputRef = useCombinedRefs(searchInputRef);
|
302
330
|
listRef = useCombinedRefs(listRef);
|
303
331
|
const { listBoxProps } = useListBox({
|
304
332
|
...props,
|
305
333
|
'aria-label': props['aria-label'] || label?.toString(),
|
306
334
|
isDisabled,
|
307
|
-
shouldUseVirtualFocus:
|
335
|
+
shouldUseVirtualFocus: shouldUseVirtualFocus ?? false,
|
308
336
|
shouldFocusWrap: true,
|
337
|
+
escapeKeyBehavior: onEscape ? 'none' : 'clearSelection',
|
309
338
|
}, listState, listRef);
|
310
339
|
const { isFocused, focusProps } = useFocus({ isDisabled });
|
311
340
|
const isInvalid = validationState === 'invalid';
|
312
|
-
//
|
313
|
-
const
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
341
|
+
// ----- Virtualization logic -----
|
342
|
+
const itemsArray = useMemo(() => [...listState.collection], [listState.collection]);
|
343
|
+
const hasSections = useMemo(() => itemsArray.some((i) => i.type === 'section'), [itemsArray]);
|
344
|
+
const shouldVirtualize = !hasSections;
|
345
|
+
// Use ref to ensure estimateSize always accesses current itemsArray
|
346
|
+
const itemsArrayRef = useRef(itemsArray);
|
347
|
+
itemsArrayRef.current = itemsArray;
|
348
|
+
// Scroll container ref for virtualization
|
349
|
+
const scrollRef = useRef(null);
|
350
|
+
const rowVirtualizer = useVirtualizer({
|
351
|
+
count: shouldVirtualize ? itemsArray.length : 0,
|
352
|
+
getScrollElement: () => scrollRef.current,
|
353
|
+
estimateSize: (index) => {
|
354
|
+
const currentItem = itemsArrayRef.current[index];
|
355
|
+
if (currentItem?.props?.description) {
|
356
|
+
return 49;
|
357
|
+
}
|
358
|
+
return size === 'small' ? 33 : 41;
|
359
|
+
},
|
360
|
+
measureElement: (el) => {
|
361
|
+
return el.offsetHeight + 1;
|
362
|
+
},
|
363
|
+
overscan: 10,
|
364
|
+
});
|
365
|
+
// Trigger remeasurement when items change (for filtering scenarios)
|
366
|
+
useEffect(() => {
|
367
|
+
if (shouldVirtualize) {
|
368
|
+
rowVirtualizer.measure();
|
369
|
+
}
|
370
|
+
}, [shouldVirtualize, itemsArray, rowVirtualizer]);
|
371
|
+
// Keep focused item visible when virtualizing, but only for keyboard navigation
|
372
|
+
useEffect(() => {
|
373
|
+
if (!shouldVirtualize)
|
374
|
+
return;
|
375
|
+
const focusedKey = listState.selectionManager.focusedKey;
|
376
|
+
if (focusedKey != null) {
|
377
|
+
const idx = itemsArrayRef.current.findIndex((it) => it.key === focusedKey);
|
378
|
+
if (idx !== -1) {
|
379
|
+
// Check if the focused item is actually visible in the current viewport
|
380
|
+
// (not just rendered due to overscan)
|
381
|
+
const scrollElement = scrollRef.current;
|
382
|
+
if (scrollElement) {
|
383
|
+
const scrollTop = scrollElement.scrollTop;
|
384
|
+
const viewportHeight = scrollElement.clientHeight;
|
385
|
+
const viewportBottom = scrollTop + viewportHeight;
|
386
|
+
// Find the virtual item for this index
|
387
|
+
const virtualItems = rowVirtualizer.getVirtualItems();
|
388
|
+
const virtualItem = virtualItems.find((item) => item.index === idx);
|
389
|
+
let isAlreadyVisible = false;
|
390
|
+
if (virtualItem) {
|
391
|
+
const itemTop = virtualItem.start;
|
392
|
+
const itemBottom = virtualItem.start + virtualItem.size;
|
393
|
+
// Check if the item is fully visible in the viewport
|
394
|
+
// We should scroll if the item is partially hidden
|
395
|
+
isAlreadyVisible =
|
396
|
+
itemTop >= scrollTop && itemBottom <= viewportBottom;
|
349
397
|
}
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
const direction = isArrowDown ? 'forward' : 'backward';
|
354
|
-
if (currentKey == null) {
|
355
|
-
// No current focus, find first/last selectable item
|
356
|
-
nextKey = findFirstLastSelectableKey(direction);
|
357
|
-
}
|
358
|
-
else {
|
359
|
-
// Find next selectable item from current position
|
360
|
-
const candidateKey = direction === 'forward'
|
361
|
-
? collection.getKeyAfter(currentKey)
|
362
|
-
: collection.getKeyBefore(currentKey);
|
363
|
-
nextKey = findNextSelectableKey(candidateKey, direction);
|
364
|
-
// If no next key found and focus wrapping is enabled, wrap to first/last selectable item
|
365
|
-
if (nextKey == null) {
|
366
|
-
nextKey = findFirstLastSelectableKey(direction);
|
398
|
+
// Only scroll if the item is not already visible AND the focus change was due to keyboard navigation
|
399
|
+
if (!isAlreadyVisible && lastFocusSourceRef.current === 'keyboard') {
|
400
|
+
rowVirtualizer.scrollToIndex(idx, { align: 'auto' });
|
367
401
|
}
|
368
402
|
}
|
369
|
-
if (nextKey != null) {
|
370
|
-
selectionManager.setFocusedKey(nextKey);
|
371
|
-
}
|
372
|
-
}
|
373
|
-
else if (e.key === 'Enter' || (e.key === ' ' && !searchValue.trim())) {
|
374
|
-
const focusedKey = listState.selectionManager.focusedKey;
|
375
|
-
if (focusedKey != null) {
|
376
|
-
e.preventDefault();
|
377
|
-
// Use the SelectionManager's select method which handles all selection logic
|
378
|
-
// including single vs multiple selection modes and modifier keys
|
379
|
-
listState.selectionManager.select(focusedKey, e);
|
380
|
-
}
|
381
403
|
}
|
382
|
-
}
|
383
|
-
});
|
404
|
+
}
|
405
|
+
}, [shouldVirtualize, listState.selectionManager.focusedKey, itemsArray]);
|
406
|
+
// Merge React Aria listbox props with custom keyboard props so both sets of
|
407
|
+
// event handlers (e.g. Arrow navigation *and* our Escape handler) are
|
408
|
+
// preserved.
|
409
|
+
const mergedListBoxProps = mergeProps(listBoxProps, keyboardProps);
|
384
410
|
const mods = useMemo(() => ({
|
385
411
|
invalid: isInvalid,
|
386
412
|
valid: validationState === 'valid',
|
387
413
|
disabled: isDisabled,
|
388
414
|
focused: isFocused,
|
389
|
-
|
390
|
-
|
415
|
+
header: !!header,
|
416
|
+
footer: !!footer,
|
417
|
+
...externalMods,
|
391
418
|
}), [
|
392
419
|
isInvalid,
|
393
420
|
validationState,
|
394
421
|
isDisabled,
|
395
422
|
isFocused,
|
396
|
-
|
397
|
-
|
423
|
+
header,
|
424
|
+
footer,
|
425
|
+
externalMods,
|
398
426
|
]);
|
399
|
-
const
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
setSearchValue(value);
|
404
|
-
}, ...keyboardProps, ...modAttrs(mods) }), _jsx("div", { "data-element": "Prefix", children: _jsx("div", { "data-element": "InputIcon", children: isLoading ? _jsx(LoadingIcon, {}) : _jsx(SearchIcon, {}) }) })] })) : null;
|
405
|
-
const listBoxField = (_jsxs(ListBoxWrapperElement, { ref: ref, qa: qa || 'ListBox', ...modAttrs(mods), styles: styles, ...focusProps, children: [searchInput, _jsx(ListElement, { ...listBoxProps, ref: listRef, styles: listStyles, "aria-disabled": isDisabled || undefined, ...(!isSearchable ? keyboardProps : {}), children: (() => {
|
406
|
-
const renderedItems = [];
|
407
|
-
let isFirstSection = true;
|
408
|
-
for (const item of listState.collection) {
|
409
|
-
if (item.type === 'section') {
|
410
|
-
if (!isFirstSection) {
|
411
|
-
renderedItems.push(_jsx(DividerElement, { role: "separator", "aria-orientation": "horizontal" }, `divider-${String(item.key)}`));
|
412
|
-
}
|
413
|
-
renderedItems.push(_jsx(ListBoxSection, { item: item, state: listState, optionStyles: optionStyles, headingStyles: headingStyles, sectionStyles: sectionStyles, isParentDisabled: isDisabled, validationState: validationState }, item.key));
|
414
|
-
isFirstSection = false;
|
415
|
-
}
|
416
|
-
else {
|
417
|
-
renderedItems.push(_jsx(Option, { item: item, state: listState, styles: optionStyles, isParentDisabled: isDisabled, validationState: validationState }, item.key));
|
427
|
+
const listBoxField = (_jsxs(ListBoxWrapperElement, { ref: ref, qa: qa || 'ListBox', mods: mods, styles: styles, children: [header ? (_jsx(StyledHeader, { styles: headerStyles, "data-size": size, children: header })) : (_jsx("div", { role: "presentation" })), _jsx(ListBoxScrollElement, { ref: scrollRef, mods: mods, ...focusProps, children: _jsx(ListElement, { ...mergedListBoxProps, ref: listRef, styles: listStyles, "aria-disabled": isDisabled || undefined, mods: { sections: hasSections }, style: shouldVirtualize
|
428
|
+
? {
|
429
|
+
position: 'relative',
|
430
|
+
height: `${rowVirtualizer.getTotalSize() + 3}px`,
|
418
431
|
}
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
432
|
+
: undefined, children: shouldVirtualize
|
433
|
+
? rowVirtualizer.getVirtualItems().map((virtualItem) => {
|
434
|
+
const item = itemsArray[virtualItem.index];
|
435
|
+
return (_jsx(Option, { size: size, item: item, state: listState, styles: optionStyles, isParentDisabled: isDisabled, validationState: validationState, focusOnHover: focusOnHover, isCheckable: isCheckable,
|
436
|
+
// We don't need to measure the element here, because the height is already set by the virtualizer
|
437
|
+
// This is a workaround to avoid glitches when selecting/deselecting items
|
438
|
+
virtualRef: rowVirtualizer.measureElement, virtualStyle: {
|
439
|
+
position: 'absolute',
|
440
|
+
top: 0,
|
441
|
+
left: 0,
|
442
|
+
right: 0,
|
443
|
+
transform: `translateY(${virtualItem.start}px)`,
|
444
|
+
}, virtualIndex: virtualItem.index, lastFocusSourceRef: lastFocusSourceRef, onOptionClick: onOptionClick }, virtualItem.key));
|
445
|
+
})
|
446
|
+
: (() => {
|
447
|
+
const renderedItems = [];
|
448
|
+
let isFirstSection = true;
|
449
|
+
for (const item of listState.collection) {
|
450
|
+
if (item.type === 'section') {
|
451
|
+
if (!isFirstSection) {
|
452
|
+
renderedItems.push(_jsx(StyledDivider, { role: "separator", "aria-orientation": "horizontal" }, `divider-${String(item.key)}`));
|
453
|
+
}
|
454
|
+
renderedItems.push(_jsx(ListBoxSection, { item: item, state: listState, optionStyles: optionStyles, headingStyles: headingStyles, sectionStyles: sectionStyles, isParentDisabled: isDisabled, validationState: validationState, focusOnHover: focusOnHover, isCheckable: isCheckable, size: size, lastFocusSourceRef: lastFocusSourceRef, onOptionClick: onOptionClick }, item.key));
|
455
|
+
isFirstSection = false;
|
456
|
+
}
|
457
|
+
else {
|
458
|
+
renderedItems.push(_jsx(Option, { size: size, item: item, state: listState, styles: optionStyles, isParentDisabled: isDisabled, validationState: validationState, focusOnHover: focusOnHover, isCheckable: isCheckable, lastFocusSourceRef: lastFocusSourceRef, onOptionClick: onOptionClick }, item.key));
|
459
|
+
}
|
460
|
+
}
|
461
|
+
return renderedItems;
|
462
|
+
})() }) }), footer ? (_jsx(StyledFooter, { styles: footerStyles, "data-size": size, children: footer })) : (_jsx("div", { role: "presentation" }))] }));
|
428
463
|
return wrapWithField(listBoxField, ref, mergeProps({ ...props, styles: undefined }, {}));
|
429
464
|
});
|
430
|
-
function Option({ item, state, styles, isParentDisabled, validationState }) {
|
431
|
-
const
|
465
|
+
function Option({ size = 'medium', item, state, styles, isParentDisabled, validationState, focusOnHover = false, isCheckable, onOptionClick, virtualStyle, virtualRef, virtualIndex, lastFocusSourceRef, }) {
|
466
|
+
const localRef = useRef(null);
|
467
|
+
// Merge local ref with react-virtual measure ref when provided
|
468
|
+
const combinedRef = useCombinedRefs(localRef, virtualRef);
|
432
469
|
const isDisabled = isParentDisabled || state.disabledKeys.has(item.key);
|
433
470
|
const isSelected = state.selectionManager.isSelected(item.key);
|
434
471
|
const isFocused = state.selectionManager.focusedKey === item.key;
|
472
|
+
const { hoverProps, isHovered } = useHover({ isDisabled });
|
435
473
|
const { optionProps, isPressed } = useOption({
|
436
474
|
key: item.key,
|
437
475
|
isDisabled,
|
438
476
|
isSelected,
|
439
477
|
shouldSelectOnPressUp: true,
|
440
|
-
shouldFocusOnHover:
|
441
|
-
}, state,
|
478
|
+
shouldFocusOnHover: focusOnHover,
|
479
|
+
}, state, combinedRef);
|
442
480
|
const description = item?.props?.description;
|
443
|
-
|
481
|
+
// Custom click handler for the entire option
|
482
|
+
const handleOptionClick = (e) => {
|
483
|
+
// Mark focus changes from mouse clicks
|
484
|
+
if (lastFocusSourceRef) {
|
485
|
+
lastFocusSourceRef.current = 'mouse';
|
486
|
+
}
|
487
|
+
// If there's an onOptionClick callback and this is checkable in multiple mode,
|
488
|
+
// we need to distinguish between checkbox and content clicks
|
489
|
+
if (onOptionClick &&
|
490
|
+
isCheckable &&
|
491
|
+
state.selectionManager.selectionMode === 'multiple') {
|
492
|
+
// Check if the click target is within the checkbox area
|
493
|
+
const clickTarget = e.target;
|
494
|
+
const checkboxElement = localRef.current?.querySelector('[data-element="CheckboxWrapper"]');
|
495
|
+
if (checkboxElement &&
|
496
|
+
(checkboxElement === clickTarget ||
|
497
|
+
checkboxElement.contains(clickTarget))) {
|
498
|
+
// Checkbox area clicked - only toggle, don't call onOptionClick
|
499
|
+
// Let React Aria handle the selection
|
500
|
+
optionProps.onClick?.(e);
|
501
|
+
// Set focus to the clicked item
|
502
|
+
state.selectionManager.setFocusedKey(item.key);
|
503
|
+
}
|
504
|
+
else {
|
505
|
+
// Content area clicked - toggle and trigger callback
|
506
|
+
// Let React Aria handle the selection first
|
507
|
+
optionProps.onClick?.(e);
|
508
|
+
// Set focus to the clicked item
|
509
|
+
state.selectionManager.setFocusedKey(item.key);
|
510
|
+
// Then call the callback (which will close the popover in FilterPicker)
|
511
|
+
if (onOptionClick) {
|
512
|
+
onOptionClick(item.key);
|
513
|
+
}
|
514
|
+
}
|
515
|
+
}
|
516
|
+
else {
|
517
|
+
// Normal behavior - let React Aria handle it
|
518
|
+
optionProps.onClick?.(e);
|
519
|
+
// Set focus to the clicked item
|
520
|
+
state.selectionManager.setFocusedKey(item.key);
|
521
|
+
// Call onOptionClick if provided
|
522
|
+
if (onOptionClick) {
|
523
|
+
onOptionClick(item.key);
|
524
|
+
}
|
525
|
+
}
|
526
|
+
};
|
527
|
+
return (_jsxs(OptionElement, { id: `ListBoxItem-${String(item.key)}`, ...mergeProps(optionProps, hoverProps), ref: combinedRef, style: virtualStyle, "data-size": size, "data-index": virtualIndex, mods: {
|
444
528
|
selected: isSelected,
|
445
529
|
focused: isFocused,
|
446
530
|
disabled: isDisabled,
|
447
531
|
pressed: isPressed,
|
448
532
|
valid: isSelected && validationState === 'valid',
|
449
533
|
invalid: isSelected && validationState === 'invalid',
|
450
|
-
|
534
|
+
checkable: isCheckable,
|
535
|
+
hovered: isHovered, // We'll treat focus as hover for the checkbox visibility
|
536
|
+
}, styles: styles, onClick: handleOptionClick, children: [isCheckable && state.selectionManager.selectionMode === 'multiple' && (_jsx("div", { "data-element": "CheckboxWrapper", children: _jsx("div", { "data-element": "Checkbox", children: _jsx(CheckIcon, { size: 12, stroke: 3 }) }) })), _jsxs("div", { "data-element": "Content", children: [_jsx("div", { "data-element": "Label", children: item.rendered }), description ? (_jsx("div", { "data-element": "Description", children: description })) : null] })] }));
|
451
537
|
}
|
452
538
|
function ListBoxSection(props) {
|
453
|
-
const { item, state, optionStyles, headingStyles, sectionStyles, isParentDisabled, validationState, } = props;
|
539
|
+
const { item, state, optionStyles, headingStyles, sectionStyles, isParentDisabled, validationState, focusOnHover, isCheckable, onOptionClick, lastFocusSourceRef, } = props;
|
454
540
|
const heading = item.rendered;
|
455
541
|
const { itemProps, headingProps, groupProps } = useListBoxSection({
|
456
542
|
heading,
|
457
543
|
'aria-label': item['aria-label'],
|
458
544
|
});
|
459
|
-
return (_jsxs(SectionWrapperElement, { ...itemProps, styles: sectionStyles, children: [heading && (_jsx(
|
545
|
+
return (_jsxs(SectionWrapperElement, { ...itemProps, styles: sectionStyles, children: [heading && (_jsx(StyledSectionHeading, { ...headingProps, styles: headingStyles, children: heading })), _jsx(SectionListElement, { ...groupProps, children: [...item.childNodes]
|
460
546
|
.filter((node) => state.collection.getItem(node.key))
|
461
|
-
.map((node) => (_jsx(Option, { item: node, state: state, styles: optionStyles, isParentDisabled: isParentDisabled, validationState: validationState }, node.key))) })] }));
|
547
|
+
.map((node) => (_jsx(Option, { size: props.size, item: node, state: state, styles: optionStyles, isParentDisabled: isParentDisabled, validationState: validationState, focusOnHover: focusOnHover, isCheckable: isCheckable, lastFocusSourceRef: lastFocusSourceRef, onOptionClick: onOptionClick }, node.key))) })] }));
|
462
548
|
}
|
463
549
|
const ListBoxSectionComponent = Object.assign(BaseSection, {
|
464
550
|
displayName: 'Section',
|