@rio-cloud/rio-uikit 2.1.0 → 2.2.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/CircularProgress.d.ts +2 -0
- package/CircularProgress.js +5 -0
- package/CircularProgress.js.map +1 -0
- package/RadioCardGroup.d.ts +2 -0
- package/RadioCardGroup.js +7 -0
- package/RadioCardGroup.js.map +1 -0
- package/SearchHighlightText.d.ts +2 -0
- package/SearchHighlightText.js +5 -0
- package/SearchHighlightText.js.map +1 -0
- package/TextTruncateMiddle.d.ts +2 -0
- package/TextTruncateMiddle.js +5 -0
- package/TextTruncateMiddle.js.map +1 -0
- package/Tracker.d.ts +2 -0
- package/Tracker.js +5 -0
- package/Tracker.js.map +1 -0
- package/classNames.d.ts +2 -0
- package/classNames.js +5 -0
- package/classNames.js.map +1 -0
- package/components/accentBar/AccentBar.js +1 -1
- package/components/accentBar/AccentBar.js.map +1 -1
- package/components/actionBarItem/ActionBarItem.js +7 -7
- package/components/actionBarItem/ActionBarItem.js.map +1 -1
- package/components/actionBarItem/ActionBarItemIcon.js +1 -1
- package/components/actionBarItem/ActionBarItemIcon.js.map +1 -1
- package/components/actionBarItem/ActionBarItemList.js +1 -1
- package/components/actionBarItem/ActionBarItemList.js.map +1 -1
- package/components/actionBarItem/ActionBarItemListItem.js +1 -1
- package/components/actionBarItem/ActionBarItemListItem.js.map +1 -1
- package/components/actionBarItem/ActionBarItemListSeparator.js +1 -1
- package/components/actionBarItem/ActionBarItemListSeparator.js.map +1 -1
- package/components/actionBarItem/ActionBarItemPopoverContent.js +3 -3
- package/components/actionBarItem/ActionBarItemPopoverContent.js.map +1 -1
- package/components/actionBarItem/ActionBarOverlay.js +1 -1
- package/components/actionBarItem/ActionBarOverlay.js.map +1 -1
- package/components/activity/Activity.js +1 -1
- package/components/activity/Activity.js.map +1 -1
- package/components/animatedTextReveal/AnimatedTextReveal.js +1 -1
- package/components/animatedTextReveal/AnimatedTextReveal.js.map +1 -1
- package/components/applicationHeader/AppMenu.js +2 -2
- package/components/applicationHeader/AppMenu.js.map +1 -1
- package/components/applicationHeader/AppMenuDropdown.js +13 -11
- package/components/applicationHeader/AppMenuDropdown.js.map +1 -1
- package/components/applicationHeader/ApplicationHeader.js +1 -1
- package/components/applicationHeader/ApplicationHeader.js.map +1 -1
- package/components/applicationHeader/MobileHeaderModal.js +8 -8
- package/components/applicationHeader/MobileHeaderModal.js.map +1 -1
- package/components/applicationHeader/MobileSubmoduleNavigation.js +1 -1
- package/components/applicationHeader/MobileSubmoduleNavigation.js.map +1 -1
- package/components/applicationHeader/NavItems.js +4 -4
- package/components/applicationHeader/NavItems.js.map +1 -1
- package/components/applicationLayout/ApplicationLayout.js +10 -10
- package/components/applicationLayout/ApplicationLayout.js.map +1 -1
- package/components/applicationLayout/ApplicationLayoutBody.js +2 -2
- package/components/applicationLayout/ApplicationLayoutBody.js.map +1 -1
- package/components/applicationLayout/ApplicationLayoutBodyBanner.js +1 -1
- package/components/applicationLayout/ApplicationLayoutBodyBanner.js.map +1 -1
- package/components/applicationLayout/ApplicationLayoutBodyBottomBar.js +1 -1
- package/components/applicationLayout/ApplicationLayoutBodyBottomBar.js.map +1 -1
- package/components/applicationLayout/ApplicationLayoutBodyNavigation.js +1 -1
- package/components/applicationLayout/ApplicationLayoutBodyNavigation.js.map +1 -1
- package/components/applicationLayout/ApplicationLayoutHeader.js +1 -1
- package/components/applicationLayout/ApplicationLayoutHeader.js.map +1 -1
- package/components/applicationLayout/ApplicationLayoutSidebar.js +1 -1
- package/components/applicationLayout/ApplicationLayoutSidebar.js.map +1 -1
- package/components/applicationLayout/SubNavigation.js +1 -1
- package/components/applicationLayout/SubNavigation.js.map +1 -1
- package/components/assetTree/AssetTree.js +1 -1
- package/components/assetTree/AssetTree.js.map +1 -1
- package/components/assetTree/Tree.js +1 -1
- package/components/assetTree/Tree.js.map +1 -1
- package/components/assetTree/TreeIcon.js +3 -3
- package/components/assetTree/TreeIcon.js.map +1 -1
- package/components/assetTree/TreeLeaf.js +4 -4
- package/components/assetTree/TreeLeaf.js.map +1 -1
- package/components/assetTree/TreeNode.js +1 -1
- package/components/assetTree/TreeNode.js.map +1 -1
- package/components/assetTree/TreeNodeContainer.js +1 -1
- package/components/assetTree/TreeNodeContainer.js.map +1 -1
- package/components/assetTree/TreeOption.js +3 -3
- package/components/assetTree/TreeOption.js.map +1 -1
- package/components/assetTree/TreeOptions.js +4 -4
- package/components/assetTree/TreeOptions.js.map +1 -1
- package/components/assetTree/TreeRoot.js +3 -3
- package/components/assetTree/TreeRoot.js.map +1 -1
- package/components/assetTree/TreeSearch.js +3 -3
- package/components/assetTree/TreeSearch.js.map +1 -1
- package/components/assetTree/TreeSidebar.js +1 -1
- package/components/assetTree/TreeSidebar.js.map +1 -1
- package/components/assetTree/TreeSidebarCategories.js +4 -4
- package/components/assetTree/TreeSidebarCategories.js.map +1 -1
- package/components/assetTree/TreeSummary.js +1 -1
- package/components/assetTree/TreeSummary.js.map +1 -1
- package/components/assetTree/TypeCounter.js +1 -1
- package/components/assetTree/TypeCounter.js.map +1 -1
- package/components/autosuggest/AutoSuggest.js +1 -1
- package/components/autosuggest/AutoSuggest.js.map +1 -1
- package/components/avatar/Avatar.js +1 -1
- package/components/avatar/Avatar.js.map +1 -1
- package/components/banner/Banner.js +1 -1
- package/components/banner/Banner.js.map +1 -1
- package/components/banner/BannerContent.js +1 -1
- package/components/banner/BannerContent.js.map +1 -1
- package/components/barList/BarList.js +1 -1
- package/components/barList/BarList.js.map +1 -1
- package/components/bottomSheet/BottomSheet.js +1 -1
- package/components/bottomSheet/BottomSheet.js.map +1 -1
- package/components/button/Button.d.ts +53 -7
- package/components/button/Button.js +87 -64
- package/components/button/Button.js.map +1 -1
- package/components/button/ButtonToolbar.js +1 -1
- package/components/button/ButtonToolbar.js.map +1 -1
- package/components/button/ToggleButton.d.ts +4 -1
- package/components/button/ToggleButton.js.map +1 -1
- package/components/calendarStripe/CalendarStripe.js +16 -16
- package/components/calendarStripe/CalendarStripe.js.map +1 -1
- package/components/card/Card.js +1 -1
- package/components/card/Card.js.map +1 -1
- package/components/charts/RadialBarChart.js +106 -103
- package/components/charts/RadialBarChart.js.map +1 -1
- package/components/checkbox/Checkbox.js +6 -6
- package/components/checkbox/Checkbox.js.map +1 -1
- package/components/circularProgress/CircularProgress.d.ts +139 -0
- package/components/circularProgress/CircularProgress.js +197 -0
- package/components/circularProgress/CircularProgress.js.map +1 -0
- package/components/clearableInput/ClearableInput.js +9 -9
- package/components/clearableInput/ClearableInput.js.map +1 -1
- package/components/dataTabs/DataTabHeader.js +1 -1
- package/components/dataTabs/DataTabHeader.js.map +1 -1
- package/components/dataTabs/DataTabs.js +4 -4
- package/components/dataTabs/DataTabs.js.map +1 -1
- package/components/datepicker/DatePicker.js +6 -6
- package/components/datepicker/DatePicker.js.map +1 -1
- package/components/datepicker/DateRangePicker.js +1 -1
- package/components/datepicker/DateRangePicker.js.map +1 -1
- package/components/datepicker/DayPicker.js +1 -1
- package/components/datepicker/DayPicker.js.map +1 -1
- package/components/dialog/Dialog.js +55 -55
- package/components/dialog/Dialog.js.map +1 -1
- package/components/dialog/DialogBody.js +1 -1
- package/components/dialog/DialogBody.js.map +1 -1
- package/components/dialog/DialogFooter.js +1 -1
- package/components/dialog/DialogFooter.js.map +1 -1
- package/components/dialog/DialogHeader.js +1 -1
- package/components/dialog/DialogHeader.js.map +1 -1
- package/components/dialog/MediaDialog.js +1 -1
- package/components/dialog/MediaDialog.js.map +1 -1
- package/components/dialog/SplitDialog.js +1 -1
- package/components/dialog/SplitDialog.js.map +1 -1
- package/components/divider/Divider.js +1 -1
- package/components/divider/Divider.js.map +1 -1
- package/components/dropdown/ButtonDropdown.js +1 -1
- package/components/dropdown/ButtonDropdown.js.map +1 -1
- package/components/dropdown/DropdownSubmenu.js +3 -3
- package/components/dropdown/DropdownSubmenu.js.map +1 -1
- package/components/dropdown/DropdownToggleButton.d.ts +1 -1
- package/components/dropdown/DropdownToggleButton.js +4 -3
- package/components/dropdown/DropdownToggleButton.js.map +1 -1
- package/components/dropdown/SplitCaretButton.js +6 -6
- package/components/dropdown/SplitCaretButton.js.map +1 -1
- package/components/editableContent/EditableContent.js +1 -1
- package/components/editableContent/EditableContent.js.map +1 -1
- package/components/ellipsis/TextTruncateMiddle.d.ts +23 -0
- package/components/ellipsis/TextTruncateMiddle.js +21 -0
- package/components/ellipsis/TextTruncateMiddle.js.map +1 -0
- package/components/expander/ExpanderList.js +5 -5
- package/components/expander/ExpanderList.js.map +1 -1
- package/components/expander/ExpanderPanel.js +1 -1
- package/components/expander/ExpanderPanel.js.map +1 -1
- package/components/feedback/FeedbackRating.js +1 -1
- package/components/feedback/FeedbackRating.js.map +1 -1
- package/components/feedback/FeedbackReactions.js +1 -1
- package/components/feedback/FeedbackReactions.js.map +1 -1
- package/components/formLabel/FormLabel.js +6 -9
- package/components/formLabel/FormLabel.js.map +1 -1
- package/components/formLabel/LabeledElement.js +1 -1
- package/components/formLabel/LabeledElement.js.map +1 -1
- package/components/listMenu/ListMenu.js +2 -5
- package/components/listMenu/ListMenu.js.map +1 -1
- package/components/listMenu/ListMenuGroup.js +2 -2
- package/components/listMenu/ListMenuGroup.js.map +1 -1
- package/components/loadMore/LoadMoreButton.js +1 -1
- package/components/loadMore/LoadMoreButton.js.map +1 -1
- package/components/loadMore/LoadMoreProgress.js +1 -1
- package/components/loadMore/LoadMoreProgress.js.map +1 -1
- package/components/map/components/features/MapSettings.js +4 -4
- package/components/map/components/features/MapSettings.js.map +1 -1
- package/components/map/components/features/settings/MapSettingsItem.js +1 -1
- package/components/map/components/features/settings/MapSettingsItem.js.map +1 -1
- package/components/map/components/features/settings/MapSettingsPanel.js +6 -20
- package/components/map/components/features/settings/MapSettingsPanel.js.map +1 -1
- package/components/map/components/features/settings/MapSettingsTile.js +87 -61
- package/components/map/components/features/settings/MapSettingsTile.js.map +1 -1
- package/components/map/components/features/settings/ZoomButtons.js +1 -1
- package/components/map/components/features/settings/ZoomButtons.js.map +1 -1
- package/components/map/components/features/settings/builtinSettings/MapTypeSettings.d.ts +38 -1
- package/components/map/components/features/settings/builtinSettings/MapTypeSettings.js +128 -92
- package/components/map/components/features/settings/builtinSettings/MapTypeSettings.js.map +1 -1
- package/components/map/utils/eventHandling.js +9 -9
- package/components/map/utils/eventHandling.js.map +1 -1
- package/components/map/utils/mapUtils.d.ts +6 -6
- package/components/map/utils/mapUtils.js +14 -19
- package/components/map/utils/mapUtils.js.map +1 -1
- package/components/mapMarker/ClusterMapMarker.js +1 -1
- package/components/mapMarker/ClusterMapMarker.js.map +1 -1
- package/components/mapMarker/SingleMapMarker.js +1 -1
- package/components/mapMarker/SingleMapMarker.js.map +1 -1
- package/components/menuItems/MenuItem.js +1 -1
- package/components/menuItems/MenuItem.js.map +1 -1
- package/components/menuItems/MenuItemList.js +1 -1
- package/components/menuItems/MenuItemList.js.map +1 -1
- package/components/navigation/AppNavigationBar.js +4 -4
- package/components/navigation/AppNavigationBar.js.map +1 -1
- package/components/noData/NoData.js +1 -1
- package/components/noData/NoData.js.map +1 -1
- package/components/numberControl/NumberControl.js +4 -4
- package/components/numberControl/NumberControl.js.map +1 -1
- package/components/numberInput/NumberInput.js +1 -1
- package/components/numberInput/NumberInput.js.map +1 -1
- package/components/onboarding/OnboardingTip.js +4 -4
- package/components/onboarding/OnboardingTip.js.map +1 -1
- package/components/page/Page.js +1 -1
- package/components/page/Page.js.map +1 -1
- package/components/pager/Pager.js +1 -1
- package/components/pager/Pager.js.map +1 -1
- package/components/radiobutton/RadioButton.d.ts +1 -1
- package/components/radiobutton/RadioButton.js +5 -5
- package/components/radiobutton/RadioButton.js.map +1 -1
- package/components/radiobutton/RadioCardGroup.d.ts +86 -0
- package/components/radiobutton/RadioCardGroup.js +110 -0
- package/components/radiobutton/RadioCardGroup.js.map +1 -0
- package/components/resizer/Resizer.js +1 -1
- package/components/resizer/Resizer.js.map +1 -1
- package/components/responsiveColumnStripe/ResponsiveColumnStripe.js +1 -1
- package/components/responsiveColumnStripe/ResponsiveColumnStripe.js.map +1 -1
- package/components/rioglyph/Rioglyph.js +1 -1
- package/components/rioglyph/Rioglyph.js.map +1 -1
- package/components/rioglyph/RioglyphIconType.d.ts +1 -1
- package/components/rules/RuleConnector.js +1 -1
- package/components/rules/RuleConnector.js.map +1 -1
- package/components/rules/RuleContainer.js +27 -27
- package/components/rules/RuleContainer.js.map +1 -1
- package/components/saveableInput/SaveableDateInput.js +1 -1
- package/components/saveableInput/SaveableDateInput.js.map +1 -1
- package/components/saveableInput/SaveableInput.js +49 -49
- package/components/saveableInput/SaveableInput.js.map +1 -1
- package/components/searchHighlight/SearchHighlightText.d.ts +28 -0
- package/components/searchHighlight/SearchHighlightText.js +15 -0
- package/components/searchHighlight/SearchHighlightText.js.map +1 -0
- package/components/selects/BaseSelectDropdown.js +1 -1
- package/components/selects/BaseSelectDropdown.js.map +1 -1
- package/components/selects/ClearButton.js +4 -4
- package/components/selects/ClearButton.js.map +1 -1
- package/components/selects/Multiselect.js +6 -6
- package/components/selects/Multiselect.js.map +1 -1
- package/components/selects/MultiselectToggleFilter.js +4 -4
- package/components/selects/MultiselectToggleFilter.js.map +1 -1
- package/components/selects/MultiselectToggleSelection.js +1 -1
- package/components/selects/MultiselectToggleSelection.js.map +1 -1
- package/components/selects/Select.js +6 -6
- package/components/selects/Select.js.map +1 -1
- package/components/selects/SelectFilter.js +1 -1
- package/components/selects/SelectFilter.js.map +1 -1
- package/components/selects/WithFeedbackAndAddon.js +1 -1
- package/components/selects/WithFeedbackAndAddon.js.map +1 -1
- package/components/sidebars/Sidebar.js +54 -54
- package/components/sidebars/Sidebar.js.map +1 -1
- package/components/sidebars/SidebarBackdrop.js +4 -4
- package/components/sidebars/SidebarBackdrop.js.map +1 -1
- package/components/sidebars/SidebarFooter.js +1 -1
- package/components/sidebars/SidebarFooter.js.map +1 -1
- package/components/sidebars/SidebarFullscreenToggle.js +4 -4
- package/components/sidebars/SidebarFullscreenToggle.js.map +1 -1
- package/components/slider/RangeSlider.js +1 -1
- package/components/slider/RangeSlider.js.map +1 -1
- package/components/slider/Slider.js +1 -1
- package/components/slider/Slider.js.map +1 -1
- package/components/smoothScrollbars/SmoothScrollbars.js +1 -1
- package/components/smoothScrollbars/SmoothScrollbars.js.map +1 -1
- package/components/spinner/Spinner.js +5 -4
- package/components/spinner/Spinner.js.map +1 -1
- package/components/states/CustomState.d.ts +69 -1
- package/components/states/CustomState.js +1 -1
- package/components/states/CustomState.js.map +1 -1
- package/components/states/EmptyState.d.ts +1 -1
- package/components/states/EmptyState.js.map +1 -1
- package/components/states/ErrorState.d.ts +1 -1
- package/components/states/ErrorState.js.map +1 -1
- package/components/states/ForbiddenState.d.ts +1 -1
- package/components/states/ForbiddenState.js.map +1 -1
- package/components/states/MaintenanceState.d.ts +1 -1
- package/components/states/MaintenanceState.js.map +1 -1
- package/components/states/NotBookedState.d.ts +1 -1
- package/components/states/NotBookedState.js.map +1 -1
- package/components/states/NotFoundState.d.ts +1 -1
- package/components/states/NotFoundState.js.map +1 -1
- package/components/states/StateButton.js +1 -1
- package/components/states/StateButton.js.map +1 -1
- package/components/statsWidget/StatsWidget.js +1 -1
- package/components/statsWidget/StatsWidget.js.map +1 -1
- package/components/statsWidget/StatsWidgetBody.js +1 -1
- package/components/statsWidget/StatsWidgetBody.js.map +1 -1
- package/components/statsWidget/StatsWidgetFooter.js +1 -1
- package/components/statsWidget/StatsWidgetFooter.js.map +1 -1
- package/components/statsWidget/StatsWidgetHeader.js +1 -1
- package/components/statsWidget/StatsWidgetHeader.js.map +1 -1
- package/components/statsWidget/StatsWidgetNumber.js +2 -2
- package/components/statsWidget/StatsWidgetNumber.js.map +1 -1
- package/components/statsWidget/StatsWidgetSpacer.js +1 -1
- package/components/statsWidget/StatsWidgetSpacer.js.map +1 -1
- package/components/statsWidget/StatsWidgets.js +1 -1
- package/components/statsWidget/StatsWidgets.js.map +1 -1
- package/components/statusBar/StatusBar.d.ts +126 -2
- package/components/statusBar/StatusBar.js +24 -17
- package/components/statusBar/StatusBar.js.map +1 -1
- package/components/statusBar/StatusBarIcon.d.ts +1 -1
- package/components/statusBar/StatusBarIcon.js +4 -4
- package/components/statusBar/StatusBarIcon.js.map +1 -1
- package/components/statusBar/StatusBarLabel.d.ts +1 -1
- package/components/statusBar/StatusBarLabel.js +5 -7
- package/components/statusBar/StatusBarLabel.js.map +1 -1
- package/components/statusBar/StatusBarProgressBar.d.ts +1 -1
- package/components/statusBar/StatusBarProgressBar.js +1 -1
- package/components/statusBar/StatusBarProgressBar.js.map +1 -1
- package/components/steppedProgressBar/SteppedProgressBar.js +1 -1
- package/components/steppedProgressBar/SteppedProgressBar.js.map +1 -1
- package/components/switch/Switch.d.ts +16 -1
- package/components/switch/Switch.js +77 -35
- package/components/switch/Switch.js.map +1 -1
- package/components/table/TableCardsSorting.js +4 -4
- package/components/table/TableCardsSorting.js.map +1 -1
- package/components/table/TableHead.js +1 -1
- package/components/table/TableHead.js.map +1 -1
- package/components/table/TableSearch.js +1 -1
- package/components/table/TableSearch.js.map +1 -1
- package/components/table/TableSettingsColumnButtons.d.ts +1 -1
- package/components/table/TableSettingsColumnButtons.js +1 -1
- package/components/table/TableSettingsColumnButtons.js.map +1 -1
- package/components/table/TableSettingsColumnDetails.d.ts +1 -1
- package/components/table/TableSettingsColumnDetails.js +1 -1
- package/components/table/TableSettingsColumnDetails.js.map +1 -1
- package/components/table/TableSettingsDialog.d.ts +51 -1
- package/components/table/TableSettingsDialog.js +164 -148
- package/components/table/TableSettingsDialog.js.map +1 -1
- package/components/table/TableSettingsDialogFooter.js +1 -1
- package/components/table/TableSettingsDialogFooter.js.map +1 -1
- package/components/table/TableSettingsListContainer.d.ts +1 -1
- package/components/table/TableSettingsListContainer.js.map +1 -1
- package/components/table/TableSettingsListItem.d.ts +1 -1
- package/components/table/TableSettingsListItem.js +8 -8
- package/components/table/TableSettingsListItem.js.map +1 -1
- package/components/table/TableToolbar.js +1 -1
- package/components/table/TableToolbar.js.map +1 -1
- package/components/table/TableViewToggles.js +1 -1
- package/components/table/TableViewToggles.js.map +1 -1
- package/components/tag/Tag.js +1 -1
- package/components/tag/Tag.js.map +1 -1
- package/components/tag/TagList.js +1 -1
- package/components/tag/TagList.js.map +1 -1
- package/components/tagManager/CustomSuggestionItem.js +1 -1
- package/components/tagManager/CustomSuggestionItem.js.map +1 -1
- package/components/tagManager/TagManager.d.ts +14 -2
- package/components/tagManager/TagManager.js +6 -6
- package/components/tagManager/TagManager.js.map +1 -1
- package/components/tagManager/TagManagerItemList.d.ts +1 -1
- package/components/tagManager/TagManagerItemList.js +1 -1
- package/components/tagManager/TagManagerItemList.js.map +1 -1
- package/components/teaser/Teaser.js +1 -1
- package/components/teaser/Teaser.js.map +1 -1
- package/components/teaser/TeaserContainer.js +1 -1
- package/components/teaser/TeaserContainer.js.map +1 -1
- package/components/timepicker/TimePicker.d.ts +20 -0
- package/components/timepicker/TimePicker.js +153 -99
- package/components/timepicker/TimePicker.js.map +1 -1
- package/components/tooltip/Tooltip.js +1 -1
- package/components/tooltip/Tooltip.js.map +1 -1
- package/components/tracker/Tracker.d.ts +85 -0
- package/components/tracker/Tracker.js +54 -0
- package/components/tracker/Tracker.js.map +1 -0
- package/components/tracker/TrackerBlock.d.ts +11 -0
- package/components/tracker/TrackerBlock.js +34 -0
- package/components/tracker/TrackerBlock.js.map +1 -0
- package/components/video/ResponsiveVideo.js +1 -1
- package/components/video/ResponsiveVideo.js.map +1 -1
- package/hooks/useCookies.d.ts +79 -0
- package/hooks/useCookies.js +33 -0
- package/hooks/useCookies.js.map +1 -0
- package/hooks/useInterval.js +5 -5
- package/hooks/useInterval.js.map +1 -1
- package/hooks/useIsFocusWithin.js +3 -3
- package/hooks/useIsFocusWithin.js.map +1 -1
- package/hooks/useLatest.d.ts +16 -0
- package/hooks/useLatest.js +11 -0
- package/hooks/useLatest.js.map +1 -0
- package/hooks/usePostMessage.d.ts +2 -1
- package/hooks/usePostMessage.js.map +1 -1
- package/hooks/useRioCookieConsent.d.ts +49 -0
- package/hooks/useRioCookieConsent.js +44 -0
- package/hooks/useRioCookieConsent.js.map +1 -0
- package/hooks/useSearch.d.ts +1 -1
- package/hooks/useSearch.js +28 -17
- package/hooks/useSearch.js.map +1 -1
- package/hooks/useSearchHighlight.d.ts +60 -0
- package/hooks/useSearchHighlight.js +54 -0
- package/hooks/useSearchHighlight.js.map +1 -0
- package/hooks/useTimeout.js +11 -11
- package/hooks/useTimeout.js.map +1 -1
- package/hooks/useUrlState.d.ts +62 -0
- package/hooks/useUrlState.js +137 -0
- package/hooks/useUrlState.js.map +1 -0
- package/mergeClassNameOverrides.d.ts +1 -0
- package/mergeClassNameOverrides.js +5 -0
- package/mergeClassNameOverrides.js.map +1 -0
- package/package.json +17 -18
- package/routeUtils.js +11 -5
- package/routeUtils.js.map +1 -1
- package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js +1 -1
- package/themes/Volkswagen/components/applicationHeader/VolkswagenApplicationHeader.js.map +1 -1
- package/useCookies.d.ts +2 -0
- package/useCookies.js +5 -0
- package/useCookies.js.map +1 -0
- package/useRioCookieConsent.d.ts +2 -0
- package/useRioCookieConsent.js +5 -0
- package/useRioCookieConsent.js.map +1 -0
- package/useSearchHighlight.d.ts +2 -0
- package/useSearchHighlight.js +6 -0
- package/useSearchHighlight.js.map +1 -0
- package/useUrlState.d.ts +2 -0
- package/useUrlState.js +5 -0
- package/useUrlState.js.map +1 -0
- package/utils/classNames.d.ts +3 -0
- package/utils/classNames.js +5 -0
- package/utils/classNames.js.map +1 -0
- package/utils/mergeClassNameOverrides.d.ts +1 -0
- package/utils/mergeClassNameOverrides.js +55 -0
- package/utils/mergeClassNameOverrides.js.map +1 -0
- package/utils/routeUtils.d.ts +122 -13
- package/utils/routeUtils.js +89 -31
- package/utils/routeUtils.js.map +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.js.map +1 -1
- package/components/states/BaseStateProps.d.ts +0 -70
- package/components/statusBar/StatusBarProps.d.ts +0 -127
- package/components/table/TableSettingsDialog.types.d.ts +0 -39
- package/components/tagManager/TagManagerTag.d.ts +0 -14
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { Children as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
const
|
|
1
|
+
import { jsxs as k, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import { Children as x, isValidElement as N } from "react";
|
|
3
|
+
import { AnimatePresence as R, motion as v } from "motion/react";
|
|
4
|
+
import A from "../../utils/classNames.js";
|
|
5
|
+
import w from "./RuleConnector.js";
|
|
6
|
+
const F = (a) => {
|
|
7
7
|
const {
|
|
8
|
-
show:
|
|
9
|
-
unchecked:
|
|
8
|
+
show: l = !0,
|
|
9
|
+
unchecked: r = !1,
|
|
10
10
|
background: s = "bg-lightest",
|
|
11
11
|
borderColor: d = "",
|
|
12
|
-
hideConnector:
|
|
13
|
-
customConnector:
|
|
12
|
+
hideConnector: c = !1,
|
|
13
|
+
customConnector: o,
|
|
14
14
|
className: m = "",
|
|
15
|
-
children:
|
|
16
|
-
...
|
|
17
|
-
} =
|
|
18
|
-
if (!
|
|
15
|
+
children: u,
|
|
16
|
+
...p
|
|
17
|
+
} = a;
|
|
18
|
+
if (!l)
|
|
19
19
|
return null;
|
|
20
|
-
const
|
|
20
|
+
const y = A(
|
|
21
21
|
"RuleContainerBox",
|
|
22
22
|
"position-relative",
|
|
23
23
|
"rounded padding-20",
|
|
24
24
|
s,
|
|
25
|
-
|
|
25
|
+
r && `border border-width border-style-dashed ${d}`,
|
|
26
26
|
m
|
|
27
|
-
);
|
|
28
|
-
return /* @__PURE__ */
|
|
29
|
-
/* @__PURE__ */
|
|
30
|
-
if (!
|
|
27
|
+
), t = x.toArray(u).filter(Boolean), h = t.length > 1 ? "sync" : "wait";
|
|
28
|
+
return /* @__PURE__ */ k("div", { className: "RuleContainer", ...p, children: [
|
|
29
|
+
/* @__PURE__ */ n("div", { className: y, "data-testid": "ruleContainerBox", children: /* @__PURE__ */ n(R, { mode: h, children: t.map((e, C) => {
|
|
30
|
+
if (!e)
|
|
31
31
|
return null;
|
|
32
|
-
const
|
|
33
|
-
return /* @__PURE__ */
|
|
34
|
-
|
|
32
|
+
const i = e, f = N(e) && e.key != null ? String(e.key) : null, b = `${i.type?.name || i.type || "RuleContainerChild"}-${C}`, g = f || b;
|
|
33
|
+
return /* @__PURE__ */ n(
|
|
34
|
+
v.div,
|
|
35
35
|
{
|
|
36
36
|
initial: { opacity: 0 },
|
|
37
37
|
animate: { opacity: 1 },
|
|
38
38
|
exit: { opacity: 0 },
|
|
39
|
-
children:
|
|
39
|
+
children: e
|
|
40
40
|
},
|
|
41
|
-
|
|
41
|
+
g
|
|
42
42
|
);
|
|
43
43
|
}) }) }),
|
|
44
|
-
|
|
44
|
+
o || /* @__PURE__ */ n(w, { hidden: r || c })
|
|
45
45
|
] });
|
|
46
46
|
};
|
|
47
47
|
export {
|
|
48
|
-
|
|
48
|
+
F as default
|
|
49
49
|
};
|
|
50
50
|
//# sourceMappingURL=RuleContainer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuleContainer.js","sources":["../../../src/components/rules/RuleContainer.tsx"],"sourcesContent":["import { Children, type HTMLAttributes, type JSX, type PropsWithChildren } from 'react';\nimport
|
|
1
|
+
{"version":3,"file":"RuleContainer.js","sources":["../../../src/components/rules/RuleContainer.tsx"],"sourcesContent":["import { Children, isValidElement, type HTMLAttributes, type JSX, type PropsWithChildren } from 'react';\nimport { AnimatePresence, motion } from 'motion/react';\n\nimport classNames from '../../utils/classNames';\nimport RuleConnector from './RuleConnector';\n\nexport type RuleContainerProps = {\n /**\n * Defines whether the container is shown.\n *\n * @default true\n */\n show?: boolean;\n\n /**\n * Determines the container style for when no rule option is selected.\n *\n * It also hides the connector in this case.\n *\n * @default false\n */\n unchecked?: boolean;\n\n /**\n * The box background class name.\n *\n * @default 'bg-lightest'\n */\n background?: string;\n\n /**\n * The border color class name.\n */\n borderColor?: string;\n\n /**\n * Defines whether the connector is shown.\n *\n * @default false\n */\n hideConnector?: boolean;\n\n /**\n * Overwrites the default connector.\n */\n customConnector?: string | JSX.Element;\n\n /**\n * Additional classes for the wrapper element.\n */\n className?: string;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'className'>;\n\nconst RuleContainer = (props: PropsWithChildren<RuleContainerProps>) => {\n const {\n show = true,\n unchecked = false,\n background = 'bg-lightest',\n borderColor = '',\n hideConnector = false,\n customConnector,\n className = '',\n children,\n ...remainingProps\n } = props;\n\n if (!show) {\n return null;\n }\n\n const boxClassNames = classNames(\n 'RuleContainerBox',\n 'position-relative',\n 'rounded padding-20',\n background,\n unchecked && `border border-width border-style-dashed ${borderColor}`,\n className\n );\n\n const childrenArray = Children.toArray(children).filter(Boolean);\n const animatePresenceMode = childrenArray.length > 1 ? 'sync' : 'wait';\n\n return (\n <div className='RuleContainer' {...remainingProps}>\n <div className={boxClassNames} data-testid='ruleContainerBox'>\n <AnimatePresence mode={animatePresenceMode}>\n {childrenArray.map((child, index) => {\n if (!child) {\n return null;\n }\n\n // just bending the type system a bit so that it matches the existing implementation :)\n const childAsElement = child as unknown as { type: string & { name: string } };\n\n const keyFromChild = isValidElement(child) && child.key != null ? String(child.key) : null;\n const fallbackKey = `${childAsElement.type?.name || childAsElement.type || 'RuleContainerChild'}-${index}`;\n\n const key = keyFromChild || fallbackKey;\n\n // In case there are multiple children of RuleContainer, use the\n // type name or the type itself as a key to animate between the two children\n return (\n <motion.div\n key={key}\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n >\n {child}\n </motion.div>\n );\n })}\n </AnimatePresence>\n </div>\n {customConnector ? customConnector : <RuleConnector hidden={unchecked || hideConnector} />}\n </div>\n );\n};\n\nexport default RuleContainer;\n"],"names":["RuleContainer","props","show","unchecked","background","borderColor","hideConnector","customConnector","className","children","remainingProps","boxClassNames","classNames","childrenArray","Children","animatePresenceMode","jsxs","jsx","AnimatePresence","child","index","childAsElement","keyFromChild","isValidElement","fallbackKey","key","motion","RuleConnector"],"mappings":";;;;;AAqDA,MAAMA,IAAgB,CAACC,MAAiD;AACpE,QAAM;AAAA,IACF,MAAAC,IAAO;AAAA,IACP,WAAAC,IAAY;AAAA,IACZ,YAAAC,IAAa;AAAA,IACb,aAAAC,IAAc;AAAA,IACd,eAAAC,IAAgB;AAAA,IAChB,iBAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,UAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,IACHT;AAEJ,MAAI,CAACC;AACD,WAAO;AAGX,QAAMS,IAAgBC;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACAR;AAAA,IACAD,KAAa,2CAA2CE,CAAW;AAAA,IACnEG;AAAA,EAAA,GAGEK,IAAgBC,EAAS,QAAQL,CAAQ,EAAE,OAAO,OAAO,GACzDM,IAAsBF,EAAc,SAAS,IAAI,SAAS;AAEhE,SACI,gBAAAG,EAAC,OAAA,EAAI,WAAU,iBAAiB,GAAGN,GAC/B,UAAA;AAAA,IAAA,gBAAAO,EAAC,OAAA,EAAI,WAAWN,GAAe,eAAY,oBACvC,UAAA,gBAAAM,EAACC,GAAA,EAAgB,MAAMH,GAClB,UAAAF,EAAc,IAAI,CAACM,GAAOC,MAAU;AACjC,UAAI,CAACD;AACD,eAAO;AAIX,YAAME,IAAiBF,GAEjBG,IAAeC,EAAeJ,CAAK,KAAKA,EAAM,OAAO,OAAO,OAAOA,EAAM,GAAG,IAAI,MAChFK,IAAc,GAAGH,EAAe,MAAM,QAAQA,EAAe,QAAQ,oBAAoB,IAAID,CAAK,IAElGK,IAAMH,KAAgBE;AAI5B,aACI,gBAAAP;AAAA,QAACS,EAAO;AAAA,QAAP;AAAA,UAEG,SAAS,EAAE,SAAS,EAAA;AAAA,UACpB,SAAS,EAAE,SAAS,EAAA;AAAA,UACpB,MAAM,EAAE,SAAS,EAAA;AAAA,UAEhB,UAAAP;AAAA,QAAA;AAAA,QALIM;AAAA,MAAA;AAAA,IAQjB,CAAC,GACL,GACJ;AAAA,IACClB,KAAoC,gBAAAU,EAACU,GAAA,EAAc,QAAQxB,KAAaG,EAAA,CAAe;AAAA,EAAA,GAC5F;AAER;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs as N, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import { useState as r, useRef as f } from "react";
|
|
3
|
-
import h from "classnames";
|
|
4
3
|
import { noop as l } from "es-toolkit/function";
|
|
4
|
+
import h from "../../utils/classNames.js";
|
|
5
5
|
import X from "../button/Button.js";
|
|
6
6
|
import Z from "../datepicker/DatePicker.js";
|
|
7
7
|
import $ from "../../hooks/useIsFocusWithin.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SaveableDateInput.js","sources":["../../../src/components/saveableInput/SaveableDateInput.tsx"],"sourcesContent":["import { useRef, useState, type HTMLAttributes, type CSSProperties } from 'react';\nimport classNames from 'classnames';\nimport { noop } from 'es-toolkit/function';\nimport type { Moment } from 'moment';\n\nimport Button from '../../Button';\nimport DatePicker, { type DatePickerProps } from '../datepicker/DatePicker';\nimport useIsFocusWithin from '../../hooks/useIsFocusWithin';\nimport useEsc from '../../hooks/useEsc';\n\nconst DEFAULT_BUTTON_STYLE = 'primary';\n\nexport type SaveableDateInputProps = {\n /**\n * The input placeholder.\n */\n placeholder?: string;\n\n /**\n * The actual input value.\n */\n value?: Date | Moment | string;\n\n /**\n * Used to control the save button from the outside to disable it in case\n * the entered value is not valid.\n *\n * @default true\n */\n isValid?: boolean;\n\n /**\n * This is the error message that is shown below the input. It uses the built-in error handling,\n * and will be shown when the \"isValid\" prop is set to false.\n */\n errorMessage?: string | React.ReactNode;\n\n /**\n * Defines wether the error icon is shown or not. If enabled, it will be shown when the \"isValid\" prop\n * is set to false.\n *\n * @default false\n */\n hideErrorIcon?: boolean;\n\n /**\n * Callback function triggered when the value changes and is saved.\n *\n * @param value\n * @param previousValue\n * @returns\n */\n onValueChanged?: (value: Moment | string, previousValue: Moment | string | Date) => void;\n\n /**\n * Callback function that gets triggered on every input change. Use this to control the component\n * or when implementing key validation.\n *\n * @param keyValue the key value that has been entered\n * @returns\n */\n onInputChange?: (value: Moment | string, isValid: boolean) => void;\n\n /**\n * Callback function that gets triggered when the input is in edit mode. Use this\n * to control the component and to handle the previous value on the outside.\n *\n * @returns\n */\n onEnterEdit?: () => void;\n\n /**\n * Callback function that gets triggered when edit mode is exited (either saved or cancelled).\n *\n * @param wasSaved - true if value was saved, false if cancelled/reset\n * @returns\n */\n onExitEdit?: (wasSaved: boolean) => void;\n\n /**\n * Callback function that gets triggered when the user aborts the edit mode. Use this\n * to control the component and handle the resetting of previous value on the outside.\n *\n * @returns\n */\n onCancel?: () => void;\n\n /**\n * Behavior when trying to exit edit mode with invalid input:\n * - 'stay-open': Keep edit mode open until valid input is provided\n * - 'reset-and-close': Close edit mode and reset to initial value\n *\n * @default 'stay-open'\n */\n invalidExitBehavior?: 'stay-open' | 'reset-and-close';\n\n /**\n * Defines the button style: `default` or `primary`.\n *\n * @default 'primary'\n */\n buttonStyle?: 'primary' | 'default';\n\n /**\n * Additional HTML attributes to be set on the input element.\n */\n inputProps?: HTMLAttributes<HTMLInputElement>;\n\n /**\n * Additional props passed to the underlying DatePicker component.\n *\n * @default {}\n */\n datePickerProps?: DatePickerProps;\n\n /**\n * Disables the component so the user cannot enter the edit mode.\n *\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Additional classes to be set on the input itself.\n */\n inputClassName?: string;\n\n /**\n * Additional classes to be set on the wrapper element.\n */\n className?: string;\n};\n\n// Validate date outside the component (via form library) if controlled usage\n// Use as controlled component: value, is Valid, and change callback\n// - if is valid, on save, call callback \"onValueChanged\"\n// - if not valid, keep edit mode open, outside is showing error message\n// - close edit mode only if date is valid - or close edit mode and reset to initial value -> customizable via prop\n// Keep picker open until user has clicked save, otherwise he might forget to click save if the dropdown closes automatically\n\nconst SaveableDateInput = (props: SaveableDateInputProps) => {\n const {\n placeholder,\n value: externalValue = '',\n isValid = true,\n errorMessage,\n hideErrorIcon = false,\n onValueChanged = noop,\n onInputChange, // for controlled usage\n onEnterEdit = noop,\n onExitEdit = noop,\n onCancel = noop,\n buttonStyle = DEFAULT_BUTTON_STYLE,\n inputClassName,\n inputProps,\n invalidExitBehavior = 'stay-open',\n datePickerProps = {},\n disabled = false,\n className,\n ...remainingProps\n } = props;\n\n // if callback is provided, assume it is controlled case\n const isControlledCase = onInputChange !== undefined;\n\n const [inputValue, setInputValue] = useState<Date | Moment | string>(externalValue);\n\n const [editInput, setEditInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const initialInputValueRef = useRef(inputValue);\n\n useIsFocusWithin({\n ref: wrapperRef,\n onFocusWithin: () => {\n setIsFocused(true);\n },\n onBlurWithin: () => {\n setIsFocused(false);\n },\n });\n\n // Handle escape key to cancel edit mode\n useEsc(() => {\n if (isFocused && editInput) {\n handleCancelEdit();\n }\n });\n\n // Update internal state in a controlled environment\n const [previousExternalValue, setPreviousExternalValue] = useState(externalValue);\n if (previousExternalValue !== externalValue) {\n setInputValue(externalValue);\n setPreviousExternalValue(externalValue);\n // Update initial value ref when external value changes while not in edit mode\n if (!editInput) {\n initialInputValueRef.current = externalValue;\n }\n }\n\n const handleToggleInput = () => {\n if (!editInput) {\n // Enter edit mode\n setEditInput(true);\n initialInputValueRef.current = inputValue;\n\n // open the dropdown\n setIsPickerOpen(true);\n\n onEnterEdit();\n } else {\n // Try to exit edit mode\n handleSaveAttempt();\n }\n };\n\n const handleSaveAttempt = () => {\n if (isValid) {\n // Save the value (only if valid)\n setEditInput(false);\n onValueChanged(inputValue as Moment | string, initialInputValueRef.current);\n onExitEdit(true);\n\n // close the dropdown\n setIsPickerOpen(false);\n } else {\n // Handle invalid input based on behavior setting\n if (invalidExitBehavior === 'reset-and-close') {\n handleCancelEdit();\n }\n // If 'stay-open', do nothing - keep edit mode open\n }\n };\n\n const handleCancelEdit = () => {\n setEditInput(false);\n\n // Reset to initial value\n if (isControlledCase) {\n // In controlled mode, trigger change to reset to initial value\n onInputChange(initialInputValueRef.current as Moment | string, true);\n } else {\n setInputValue(initialInputValueRef.current);\n }\n\n // Close the dropdown\n setIsPickerOpen(false);\n\n onCancel();\n onExitEdit(false);\n };\n\n const handleDateChange = (value: Moment | string, isValid: boolean) => {\n if (isControlledCase) {\n onInputChange(value, isValid);\n } else {\n setInputValue(value);\n }\n };\n\n const handleCloseDropdown = () => setIsPickerOpen(false);\n\n const wrapperClasses = classNames('form-group', !isValid && 'has-feedback has-error', className);\n\n const buttonIconClasses = classNames('rioglyph', editInput ? 'rioglyph-ok' : 'rioglyph-pencil');\n\n const dateInputClasses = classNames('margin-0 width-100pct', inputClassName);\n\n // Button should be disabled if:\n // - Component is disabled, OR\n // - In edit mode and invalid input (and behavior is stay-open)\n const disableButton = disabled || (editInput && !isValid && invalidExitBehavior === 'stay-open');\n\n let inputStyle: CSSProperties = {\n borderTopRightRadius: 0,\n borderBottomRightRadius: 0,\n };\n\n if (!isValid && hideErrorIcon) {\n // If the error icon shall not be shown, remove the input padding to avoid cutting of the date value\n inputStyle = { ...inputStyle, paddingRight: '10px' };\n }\n\n return (\n <div ref={wrapperRef} {...remainingProps} className={wrapperClasses}>\n <div className='input-group'>\n <DatePicker\n {...{ ...datePickerProps, open: isPickerOpen }}\n className={dateInputClasses}\n inputProps={{\n ...inputProps,\n placeholder,\n disabled: !editInput,\n style: inputStyle,\n }}\n value={inputValue}\n onChange={handleDateChange}\n onClose={handleCloseDropdown}\n />\n {!isValid && !hideErrorIcon && (\n <span className='right-25 margin-right-10 form-control-feedback rioglyph rioglyph-error-sign' />\n )}\n <div className='input-group-btn'>\n <Button\n ref={buttonRef}\n bsStyle={buttonStyle}\n iconOnly\n onClick={handleToggleInput}\n disabled={disableButton}\n >\n <span className={buttonIconClasses} />\n </Button>\n </div>\n </div>\n {!isValid && errorMessage && (\n <span className='help-block z-index-max'>\n <span>{errorMessage}</span>\n </span>\n )}\n </div>\n );\n};\n\nexport default SaveableDateInput;\n"],"names":["DEFAULT_BUTTON_STYLE","SaveableDateInput","props","placeholder","externalValue","isValid","errorMessage","hideErrorIcon","onValueChanged","noop","onInputChange","onEnterEdit","onExitEdit","onCancel","buttonStyle","inputClassName","inputProps","invalidExitBehavior","datePickerProps","disabled","className","remainingProps","isControlledCase","inputValue","setInputValue","useState","editInput","setEditInput","isFocused","setIsFocused","isPickerOpen","setIsPickerOpen","wrapperRef","useRef","buttonRef","initialInputValueRef","useIsFocusWithin","useEsc","handleCancelEdit","previousExternalValue","setPreviousExternalValue","handleToggleInput","handleSaveAttempt","handleDateChange","value","handleCloseDropdown","wrapperClasses","classNames","buttonIconClasses","dateInputClasses","disableButton","inputStyle","jsxs","jsx","DatePicker","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SaveableDateInput.js","sources":["../../../src/components/saveableInput/SaveableDateInput.tsx"],"sourcesContent":["import { useRef, useState, type HTMLAttributes, type CSSProperties } from 'react';\nimport { noop } from 'es-toolkit/function';\nimport type { Moment } from 'moment';\n\nimport classNames from '../../utils/classNames';\nimport Button from '../../Button';\nimport DatePicker, { type DatePickerProps } from '../datepicker/DatePicker';\nimport useIsFocusWithin from '../../hooks/useIsFocusWithin';\nimport useEsc from '../../hooks/useEsc';\n\nconst DEFAULT_BUTTON_STYLE = 'primary';\n\nexport type SaveableDateInputProps = {\n /**\n * The input placeholder.\n */\n placeholder?: string;\n\n /**\n * The actual input value.\n */\n value?: Date | Moment | string;\n\n /**\n * Used to control the save button from the outside to disable it in case\n * the entered value is not valid.\n *\n * @default true\n */\n isValid?: boolean;\n\n /**\n * This is the error message that is shown below the input. It uses the built-in error handling,\n * and will be shown when the \"isValid\" prop is set to false.\n */\n errorMessage?: string | React.ReactNode;\n\n /**\n * Defines wether the error icon is shown or not. If enabled, it will be shown when the \"isValid\" prop\n * is set to false.\n *\n * @default false\n */\n hideErrorIcon?: boolean;\n\n /**\n * Callback function triggered when the value changes and is saved.\n *\n * @param value\n * @param previousValue\n * @returns\n */\n onValueChanged?: (value: Moment | string, previousValue: Moment | string | Date) => void;\n\n /**\n * Callback function that gets triggered on every input change. Use this to control the component\n * or when implementing key validation.\n *\n * @param keyValue the key value that has been entered\n * @returns\n */\n onInputChange?: (value: Moment | string, isValid: boolean) => void;\n\n /**\n * Callback function that gets triggered when the input is in edit mode. Use this\n * to control the component and to handle the previous value on the outside.\n *\n * @returns\n */\n onEnterEdit?: () => void;\n\n /**\n * Callback function that gets triggered when edit mode is exited (either saved or cancelled).\n *\n * @param wasSaved - true if value was saved, false if cancelled/reset\n * @returns\n */\n onExitEdit?: (wasSaved: boolean) => void;\n\n /**\n * Callback function that gets triggered when the user aborts the edit mode. Use this\n * to control the component and handle the resetting of previous value on the outside.\n *\n * @returns\n */\n onCancel?: () => void;\n\n /**\n * Behavior when trying to exit edit mode with invalid input:\n * - 'stay-open': Keep edit mode open until valid input is provided\n * - 'reset-and-close': Close edit mode and reset to initial value\n *\n * @default 'stay-open'\n */\n invalidExitBehavior?: 'stay-open' | 'reset-and-close';\n\n /**\n * Defines the button style: `default` or `primary`.\n *\n * @default 'primary'\n */\n buttonStyle?: 'primary' | 'default';\n\n /**\n * Additional HTML attributes to be set on the input element.\n */\n inputProps?: HTMLAttributes<HTMLInputElement>;\n\n /**\n * Additional props passed to the underlying DatePicker component.\n *\n * @default {}\n */\n datePickerProps?: DatePickerProps;\n\n /**\n * Disables the component so the user cannot enter the edit mode.\n *\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Additional classes to be set on the input itself.\n */\n inputClassName?: string;\n\n /**\n * Additional classes to be set on the wrapper element.\n */\n className?: string;\n};\n\n// Validate date outside the component (via form library) if controlled usage\n// Use as controlled component: value, is Valid, and change callback\n// - if is valid, on save, call callback \"onValueChanged\"\n// - if not valid, keep edit mode open, outside is showing error message\n// - close edit mode only if date is valid - or close edit mode and reset to initial value -> customizable via prop\n// Keep picker open until user has clicked save, otherwise he might forget to click save if the dropdown closes automatically\n\nconst SaveableDateInput = (props: SaveableDateInputProps) => {\n const {\n placeholder,\n value: externalValue = '',\n isValid = true,\n errorMessage,\n hideErrorIcon = false,\n onValueChanged = noop,\n onInputChange, // for controlled usage\n onEnterEdit = noop,\n onExitEdit = noop,\n onCancel = noop,\n buttonStyle = DEFAULT_BUTTON_STYLE,\n inputClassName,\n inputProps,\n invalidExitBehavior = 'stay-open',\n datePickerProps = {},\n disabled = false,\n className,\n ...remainingProps\n } = props;\n\n // if callback is provided, assume it is controlled case\n const isControlledCase = onInputChange !== undefined;\n\n const [inputValue, setInputValue] = useState<Date | Moment | string>(externalValue);\n\n const [editInput, setEditInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const initialInputValueRef = useRef(inputValue);\n\n useIsFocusWithin({\n ref: wrapperRef,\n onFocusWithin: () => {\n setIsFocused(true);\n },\n onBlurWithin: () => {\n setIsFocused(false);\n },\n });\n\n // Handle escape key to cancel edit mode\n useEsc(() => {\n if (isFocused && editInput) {\n handleCancelEdit();\n }\n });\n\n // Update internal state in a controlled environment\n const [previousExternalValue, setPreviousExternalValue] = useState(externalValue);\n if (previousExternalValue !== externalValue) {\n setInputValue(externalValue);\n setPreviousExternalValue(externalValue);\n // Update initial value ref when external value changes while not in edit mode\n if (!editInput) {\n initialInputValueRef.current = externalValue;\n }\n }\n\n const handleToggleInput = () => {\n if (!editInput) {\n // Enter edit mode\n setEditInput(true);\n initialInputValueRef.current = inputValue;\n\n // open the dropdown\n setIsPickerOpen(true);\n\n onEnterEdit();\n } else {\n // Try to exit edit mode\n handleSaveAttempt();\n }\n };\n\n const handleSaveAttempt = () => {\n if (isValid) {\n // Save the value (only if valid)\n setEditInput(false);\n onValueChanged(inputValue as Moment | string, initialInputValueRef.current);\n onExitEdit(true);\n\n // close the dropdown\n setIsPickerOpen(false);\n } else {\n // Handle invalid input based on behavior setting\n if (invalidExitBehavior === 'reset-and-close') {\n handleCancelEdit();\n }\n // If 'stay-open', do nothing - keep edit mode open\n }\n };\n\n const handleCancelEdit = () => {\n setEditInput(false);\n\n // Reset to initial value\n if (isControlledCase) {\n // In controlled mode, trigger change to reset to initial value\n onInputChange(initialInputValueRef.current as Moment | string, true);\n } else {\n setInputValue(initialInputValueRef.current);\n }\n\n // Close the dropdown\n setIsPickerOpen(false);\n\n onCancel();\n onExitEdit(false);\n };\n\n const handleDateChange = (value: Moment | string, isValid: boolean) => {\n if (isControlledCase) {\n onInputChange(value, isValid);\n } else {\n setInputValue(value);\n }\n };\n\n const handleCloseDropdown = () => setIsPickerOpen(false);\n\n const wrapperClasses = classNames('form-group', !isValid && 'has-feedback has-error', className);\n\n const buttonIconClasses = classNames('rioglyph', editInput ? 'rioglyph-ok' : 'rioglyph-pencil');\n\n const dateInputClasses = classNames('margin-0 width-100pct', inputClassName);\n\n // Button should be disabled if:\n // - Component is disabled, OR\n // - In edit mode and invalid input (and behavior is stay-open)\n const disableButton = disabled || (editInput && !isValid && invalidExitBehavior === 'stay-open');\n\n let inputStyle: CSSProperties = {\n borderTopRightRadius: 0,\n borderBottomRightRadius: 0,\n };\n\n if (!isValid && hideErrorIcon) {\n // If the error icon shall not be shown, remove the input padding to avoid cutting of the date value\n inputStyle = { ...inputStyle, paddingRight: '10px' };\n }\n\n return (\n <div ref={wrapperRef} {...remainingProps} className={wrapperClasses}>\n <div className='input-group'>\n <DatePicker\n {...{ ...datePickerProps, open: isPickerOpen }}\n className={dateInputClasses}\n inputProps={{\n ...inputProps,\n placeholder,\n disabled: !editInput,\n style: inputStyle,\n }}\n value={inputValue}\n onChange={handleDateChange}\n onClose={handleCloseDropdown}\n />\n {!isValid && !hideErrorIcon && (\n <span className='right-25 margin-right-10 form-control-feedback rioglyph rioglyph-error-sign' />\n )}\n <div className='input-group-btn'>\n <Button\n ref={buttonRef}\n bsStyle={buttonStyle}\n iconOnly\n onClick={handleToggleInput}\n disabled={disableButton}\n >\n <span className={buttonIconClasses} />\n </Button>\n </div>\n </div>\n {!isValid && errorMessage && (\n <span className='help-block z-index-max'>\n <span>{errorMessage}</span>\n </span>\n )}\n </div>\n );\n};\n\nexport default SaveableDateInput;\n"],"names":["DEFAULT_BUTTON_STYLE","SaveableDateInput","props","placeholder","externalValue","isValid","errorMessage","hideErrorIcon","onValueChanged","noop","onInputChange","onEnterEdit","onExitEdit","onCancel","buttonStyle","inputClassName","inputProps","invalidExitBehavior","datePickerProps","disabled","className","remainingProps","isControlledCase","inputValue","setInputValue","useState","editInput","setEditInput","isFocused","setIsFocused","isPickerOpen","setIsPickerOpen","wrapperRef","useRef","buttonRef","initialInputValueRef","useIsFocusWithin","useEsc","handleCancelEdit","previousExternalValue","setPreviousExternalValue","handleToggleInput","handleSaveAttempt","handleDateChange","value","handleCloseDropdown","wrapperClasses","classNames","buttonIconClasses","dateInputClasses","disableButton","inputStyle","jsxs","jsx","DatePicker","Button"],"mappings":"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"}
|
|
@@ -1,65 +1,65 @@
|
|
|
1
1
|
import { jsxs as T, jsx as e } from "react/jsx-runtime";
|
|
2
|
-
import { useState as
|
|
3
|
-
import
|
|
4
|
-
import { isEmpty as ne } from "es-toolkit/compat";
|
|
2
|
+
import { useState as l, useRef as x, useEffect as ne } from "react";
|
|
3
|
+
import { isEmpty as ae } from "es-toolkit/compat";
|
|
5
4
|
import { noop as b } from "es-toolkit/function";
|
|
6
|
-
import
|
|
7
|
-
import se from "
|
|
8
|
-
import re from "../../hooks/
|
|
9
|
-
|
|
5
|
+
import f from "../../utils/classNames.js";
|
|
6
|
+
import se from "../button/Button.js";
|
|
7
|
+
import re from "../../hooks/useKey.js";
|
|
8
|
+
import oe from "../../hooks/useEsc.js";
|
|
9
|
+
const le = "primary", ie = (c) => {
|
|
10
10
|
const n = x(null);
|
|
11
|
-
return
|
|
12
|
-
n.current &&
|
|
13
|
-
}, [n.current,
|
|
14
|
-
},
|
|
11
|
+
return ne(() => {
|
|
12
|
+
n.current && c && n.current.focus();
|
|
13
|
+
}, [n.current, c]), n;
|
|
14
|
+
}, ve = (c) => {
|
|
15
15
|
const {
|
|
16
16
|
placeholder: n,
|
|
17
17
|
fixedPreviousValue: m = "",
|
|
18
|
-
previousValue:
|
|
18
|
+
previousValue: P = "",
|
|
19
19
|
value: i = "",
|
|
20
20
|
isValid: a = !0,
|
|
21
21
|
errorMessage: E,
|
|
22
22
|
hideErrorIcon: I = !1,
|
|
23
|
-
onValueChanged:
|
|
23
|
+
onValueChanged: R = b,
|
|
24
24
|
onInputChange: N,
|
|
25
|
-
onEsc:
|
|
26
|
-
onEnterEdit:
|
|
27
|
-
buttonStyle:
|
|
25
|
+
onEsc: S = b,
|
|
26
|
+
onEnterEdit: z = b,
|
|
27
|
+
buttonStyle: U = le,
|
|
28
28
|
inputClassName: j,
|
|
29
29
|
inputProps: w,
|
|
30
30
|
icon: h,
|
|
31
|
-
unit:
|
|
31
|
+
unit: y,
|
|
32
32
|
disabled: D = !1,
|
|
33
33
|
className: L,
|
|
34
|
-
...
|
|
35
|
-
} =
|
|
36
|
-
|
|
37
|
-
const [
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}),
|
|
43
|
-
|
|
34
|
+
..._
|
|
35
|
+
} = c, u = P || m, [s, g] = l(i), [r, v] = l(u), [t, V] = l(!1), [C, O] = l(!1), p = x(s), k = x(r), [A, K] = l(i);
|
|
36
|
+
A !== i && (g(i), K(i));
|
|
37
|
+
const [M, Y] = l(u);
|
|
38
|
+
M !== u && (v(u), Y(u));
|
|
39
|
+
const $ = ie(t);
|
|
40
|
+
re((o) => {
|
|
41
|
+
C && t && a && o.key === "Enter" && B();
|
|
42
|
+
}), oe(() => {
|
|
43
|
+
C && (g(p.current), v(k.current), V(!1), S());
|
|
44
44
|
});
|
|
45
|
-
const
|
|
46
|
-
t === !1 ? (V(!0), m || (
|
|
47
|
-
},
|
|
45
|
+
const B = () => {
|
|
46
|
+
t === !1 ? (V(!0), m || (k.current = r), p.current = s, z()) : (V(!1), p.current !== s && (v(m || p.current), R(s, r)));
|
|
47
|
+
}, q = (o) => {
|
|
48
48
|
if (N) {
|
|
49
|
-
const
|
|
50
|
-
N(
|
|
49
|
+
const ee = o.nativeEvent?.data, te = o.target.value;
|
|
50
|
+
N(ee ?? te, o.currentTarget.value);
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
-
g(
|
|
54
|
-
},
|
|
53
|
+
g(o.target.value);
|
|
54
|
+
}, G = () => O(!0), H = () => O(!1), F = !ae(r) && r !== s && !t, d = !!y, J = f("form-group", !a && "has-feedback has-error", L), Q = f(
|
|
55
55
|
"form-control",
|
|
56
56
|
F && "padding-bottom-0 padding-top-10 text-size-12",
|
|
57
|
-
|
|
57
|
+
d && "padding-right-50",
|
|
58
58
|
// This value is not perfect as with longer units it might conflict with the value
|
|
59
|
-
!
|
|
59
|
+
!d && !a && I && "padding-right-10",
|
|
60
60
|
// remove the padding for the error icon if not needed
|
|
61
61
|
j
|
|
62
|
-
),
|
|
62
|
+
), W = f(
|
|
63
63
|
"position-absolute",
|
|
64
64
|
"top-2",
|
|
65
65
|
"left-10",
|
|
@@ -67,34 +67,34 @@ const le = "primary", oe = (p) => {
|
|
|
67
67
|
"text-size-10",
|
|
68
68
|
"text-decoration-line-through",
|
|
69
69
|
h && "padding-left-20"
|
|
70
|
-
),
|
|
71
|
-
return /* @__PURE__ */ T("div", { ...
|
|
70
|
+
), X = f("rioglyph", t ? "rioglyph-ok" : "rioglyph-pencil"), Z = t && !a || D;
|
|
71
|
+
return /* @__PURE__ */ T("div", { ..._, className: J, children: [
|
|
72
72
|
/* @__PURE__ */ T("div", { className: "input-group", children: [
|
|
73
73
|
h && /* @__PURE__ */ e("span", { className: "input-group-addon", children: /* @__PURE__ */ e("span", { className: `rioglyph ${h}`, "aria-hidden": "true", "aria-label": "input icon" }) }),
|
|
74
74
|
/* @__PURE__ */ e(
|
|
75
75
|
"input",
|
|
76
76
|
{
|
|
77
77
|
type: "text",
|
|
78
|
-
ref:
|
|
78
|
+
ref: $,
|
|
79
79
|
placeholder: n,
|
|
80
|
-
className:
|
|
80
|
+
className: Q,
|
|
81
81
|
value: s,
|
|
82
|
-
onChange:
|
|
83
|
-
onFocus:
|
|
84
|
-
onBlur:
|
|
82
|
+
onChange: q,
|
|
83
|
+
onFocus: G,
|
|
84
|
+
onBlur: H,
|
|
85
85
|
disabled: !t,
|
|
86
86
|
...w
|
|
87
87
|
}
|
|
88
88
|
),
|
|
89
|
-
|
|
90
|
-
F && /* @__PURE__ */ e("div", { className:
|
|
91
|
-
/* @__PURE__ */ e("div", { className: "input-group-btn", children: /* @__PURE__ */ e(
|
|
89
|
+
d && /* @__PURE__ */ e("div", { className: "position-absolute right-0 margin-right-50", "aria-label": "unit", children: y }),
|
|
90
|
+
F && /* @__PURE__ */ e("div", { className: W, "aria-label": "previous value", children: r }),
|
|
91
|
+
/* @__PURE__ */ e("div", { className: "input-group-btn", children: /* @__PURE__ */ e(se, { bsStyle: U, iconOnly: !0, onClick: B, disabled: Z, children: /* @__PURE__ */ e("span", { className: X }) }) })
|
|
92
92
|
] }),
|
|
93
|
-
!a && !I && !
|
|
93
|
+
!a && !I && !d && /* @__PURE__ */ e("span", { className: "right-25 margin-right-10 form-control-feedback rioglyph rioglyph-error-sign" }),
|
|
94
94
|
!a && E && /* @__PURE__ */ e("span", { className: "help-block z-index-max", children: /* @__PURE__ */ e("span", { children: E }) })
|
|
95
95
|
] });
|
|
96
96
|
};
|
|
97
97
|
export {
|
|
98
|
-
|
|
98
|
+
ve as default
|
|
99
99
|
};
|
|
100
100
|
//# sourceMappingURL=SaveableInput.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SaveableInput.js","sources":["../../../src/components/saveableInput/SaveableInput.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState, type ChangeEvent, type HTMLAttributes } from 'react';\nimport classNames from 'classnames';\nimport { isEmpty } from 'es-toolkit/compat';\nimport { noop } from 'es-toolkit/function';\n\nimport Button from '../../Button';\nimport useKey from '../../hooks/useKey';\nimport useEsc from '../../hooks/useEsc';\n\nconst DEFAULT_BUTTON_STYLE = 'primary';\n\nconst useFocus = (isEditable: boolean) => {\n const inputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (inputRef.current && isEditable) {\n inputRef.current.focus();\n }\n }, [inputRef.current, isEditable]);\n\n return inputRef;\n};\n\nexport type SaveableInputProps = {\n /**\n * The input placeholder.\n */\n placeholder?: string;\n\n /**\n * The previous or old value shown above the input value.\n * This value will *not* be changed for new input values.\n */\n fixedPreviousValue?: string;\n\n /**\n * The previous or old value shown above the input value.\n * This value *changes* when a new input value is accepted.\n */\n previousValue?: string;\n\n /**\n * The actual input value.\n */\n value?: string;\n\n /**\n * Used to control the save button from the outside to disable it in case\n * the entered value is not valid.\n *\n * @default true\n */\n isValid?: boolean;\n\n /**\n * This is the error message that is shown below the input. It uses the built-in error handling,\n * and will be shown when the \"isValid\" prop is set to false.\n */\n errorMessage?: string | React.ReactNode;\n\n /**\n * Defines wether the error icon is shown or not. If enabled, it will be shown when the \"isValid\" prop\n * is set to false.\n *\n * @default false\n */\n hideErrorIcon?: boolean;\n\n /**\n * Callback function triggered when the value changes.\n * @param value\n * @param previousValue\n * @returns\n */\n onValueChanged?: (value: string, previousValue: string) => void;\n\n /**\n * Callback function that gets triggered on every input change. Use this to control the component\n * or when implementing key validation.\n * @param keyValue the key value that has been entered\n * @param inputValue the current complete value of the input\n * @returns\n */\n onInputChange?: (keyValue: string, inputValue: string) => void;\n\n /**\n * Callback function that gets triggered when the user aborts the edit mode. Use this\n * to control the component and handle the resetting of previous value on the outside.\n * @returns\n */\n onEsc?: () => void;\n\n /**\n * Callback function that gets triggered when the input is in edit mode. Use this\n * to control the component dna to handle the previous value on the outside.\n * @returns\n */\n onEnterEdit?: () => void;\n\n /**\n * Defines the button style: `default` or `primary`.\n *\n * @default 'primary'\n */\n buttonStyle?: 'primary' | 'default';\n\n /**\n * Additional HTML attributes to be set on the input element.\n */\n inputProps?: HTMLAttributes<HTMLInputElement>;\n\n /**\n * Adds a given unit to the input.\n */\n unit?: string | React.ReactNode;\n\n /**\n * Icon class name that shall be used. If defined, the input element is wrapped in an input-group\n * and the icon will be set in an input-addon. Example: `rioglyph-search`.\n */\n icon?: string;\n\n /**\n * Disables the component so the user cannot enter the edit mode.\n *\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Additional classes to be set on the input itself.\n */\n inputClassName?: string;\n\n /**\n * Additional classes to be set on the wrapper element.\n */\n className?: string;\n};\n\n// Features:\n// [ ] what shall happen when user leaves component while in edit mode (click outside or tab) - close on blur?\n// [x] avoid save without change\n// [x] use fixed previous value\n// [x] enter = save\n// [x] esc key to abort and leave edit mode\n// [x] tab focus + enter = go into edit mode\n// [x] validate after each key, i.e for number inputs - use onInputChange callback\n// [x] support form feedback error - wrap it with form-group and feedback classes\n// [x] allow for unit and icon\n// [x] disabled input\n\nconst SaveableInput = (props: SaveableInputProps) => {\n const {\n placeholder,\n fixedPreviousValue = '',\n previousValue = '',\n value: externalValue = '',\n isValid = true,\n errorMessage,\n hideErrorIcon = false,\n onValueChanged = noop,\n onInputChange,\n onEsc = noop,\n onEnterEdit = noop,\n buttonStyle = DEFAULT_BUTTON_STYLE,\n inputClassName,\n inputProps,\n icon,\n unit,\n disabled = false,\n className,\n ...remainingProps\n } = props;\n\n const externalOldValue = previousValue || fixedPreviousValue;\n\n const [inputValue, setInputValue] = useState(externalValue);\n const [oldInputValue, setOldInputValue] = useState(externalOldValue);\n\n const [editInput, setEditInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const initialInputValueRef = useRef(inputValue);\n const initialOldInputValueRef = useRef(oldInputValue);\n\n // Update internal state in a controlled environment\n const [previousExternalValue, setPreviousExternalValue] = useState(externalValue);\n if (previousExternalValue !== externalValue) {\n setInputValue(externalValue);\n setPreviousExternalValue(externalValue);\n }\n\n // Update internal state in a controlled environment\n const [previousExternalOldValue, setPreviousExternalOldValue] = useState(externalOldValue);\n if (previousExternalOldValue !== externalOldValue) {\n setOldInputValue(externalOldValue);\n setPreviousExternalOldValue(externalOldValue);\n }\n\n // Set focus on input when being in edit mode\n const inputRef = useFocus(editInput);\n\n // Allow to exit \"edit\" mode with \"Enter\" to accept changes\n useKey((event: KeyboardEvent) => {\n if (isFocused && editInput && isValid && event.key === 'Enter') {\n handleToggleInput();\n }\n });\n\n // Allow to exit \"edit\" mode with \"Esc\" to ignore changes\n useEsc(() => {\n if (isFocused) {\n // Restore local state to initial vales as it was when entering edit mode\n setInputValue(initialInputValueRef.current);\n setOldInputValue(initialOldInputValueRef.current);\n setEditInput(false);\n onEsc();\n }\n });\n\n const handleToggleInput = () => {\n if (editInput === false) {\n setEditInput(true);\n\n // Temporarily store values of input and oldInput to be used when\n // discarding changes on \"esc\" or to avoid saving without changes\n if (!fixedPreviousValue) {\n initialOldInputValueRef.current = oldInputValue;\n }\n initialInputValueRef.current = inputValue;\n\n onEnterEdit();\n } else {\n setEditInput(false);\n\n // In case the new input value has not changed to the initial value\n // reset the internal old value to the initial\n if (initialInputValueRef.current !== inputValue) {\n setOldInputValue(fixedPreviousValue || initialInputValueRef.current);\n onValueChanged(inputValue, oldInputValue);\n }\n }\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n // Only update internal value if the external \"onInputChange\" callback function is not defined\n // as it will be used in a controlled way\n if (onInputChange) {\n // Use type assertion to access nativeEvent.data\n const nativeEventData = (event.nativeEvent as InputEvent)?.data;\n\n // Whe \"backspace\" is used to remove a value, the nativeEventData is undefined. In this case\n // we need to use the target value for the callback otherwise the user will not be able to\n // remove a character from the input\n const currentInputValue = event.target.value;\n\n onInputChange(nativeEventData ?? currentInputValue, event.currentTarget.value);\n return;\n }\n\n setInputValue(event.target.value);\n };\n\n const handleFocus = () => setIsFocused(true);\n const handleBlur = () => setIsFocused(false);\n\n const showOldValue = !isEmpty(oldInputValue) && oldInputValue !== inputValue && !editInput;\n\n const wrapperClasses = classNames('form-group', !isValid && 'has-feedback has-error', className);\n\n const inputClasses = classNames(\n 'form-control',\n showOldValue && 'padding-bottom-0 padding-top-10 text-size-12',\n unit && 'padding-right-50', // This value is not perfect as with longer units it might conflict with the value\n !unit && !isValid && hideErrorIcon && 'padding-right-10', // remove the padding for the error icon if not needed\n inputClassName\n );\n\n const oldValueClasses = classNames(\n 'position-absolute',\n 'top-2',\n 'left-10',\n 'margin-left-3',\n 'text-size-10',\n 'text-decoration-line-through',\n icon && 'padding-left-20'\n );\n\n const buttonIconClasses = classNames('rioglyph', editInput ? 'rioglyph-ok' : 'rioglyph-pencil');\n\n const disableButton = (editInput && !isValid) || disabled;\n\n return (\n <div {...remainingProps} className={wrapperClasses}>\n <div className='input-group'>\n {icon && (\n <span className='input-group-addon'>\n <span className={`rioglyph ${icon}`} aria-hidden='true' aria-label='input icon' />\n </span>\n )}\n <input\n type='text'\n ref={inputRef}\n placeholder={placeholder}\n className={inputClasses}\n value={inputValue}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={!editInput}\n {...inputProps}\n />\n {unit && (\n <div className='position-absolute right-0 margin-right-50' aria-label='unit'>\n {unit}\n </div>\n )}\n {showOldValue && (\n <div className={oldValueClasses} aria-label='previous value'>\n {oldInputValue}\n </div>\n )}\n <div className='input-group-btn'>\n <Button bsStyle={buttonStyle} iconOnly onClick={handleToggleInput} disabled={disableButton}>\n <span className={buttonIconClasses} />\n </Button>\n </div>\n </div>\n {!isValid && !hideErrorIcon && !unit && (\n <span className='right-25 margin-right-10 form-control-feedback rioglyph rioglyph-error-sign' />\n )}\n {!isValid && errorMessage && (\n <span className='help-block z-index-max'>\n <span>{errorMessage}</span>\n </span>\n )}\n </div>\n );\n};\n\nexport default SaveableInput;\n"],"names":["DEFAULT_BUTTON_STYLE","useFocus","isEditable","inputRef","useRef","useEffect","SaveableInput","props","placeholder","fixedPreviousValue","previousValue","externalValue","isValid","errorMessage","hideErrorIcon","onValueChanged","noop","onInputChange","onEsc","onEnterEdit","buttonStyle","inputClassName","inputProps","icon","unit","disabled","className","remainingProps","externalOldValue","inputValue","setInputValue","useState","oldInputValue","setOldInputValue","editInput","setEditInput","isFocused","setIsFocused","initialInputValueRef","initialOldInputValueRef","previousExternalValue","setPreviousExternalValue","previousExternalOldValue","setPreviousExternalOldValue","useKey","event","handleToggleInput","useEsc","handleInputChange","nativeEventData","currentInputValue","handleFocus","handleBlur","showOldValue","isEmpty","wrapperClasses","classNames","inputClasses","oldValueClasses","buttonIconClasses","disableButton","jsxs","jsx","Button"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SaveableInput.js","sources":["../../../src/components/saveableInput/SaveableInput.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState, type ChangeEvent, type HTMLAttributes } from 'react';\nimport { isEmpty } from 'es-toolkit/compat';\nimport { noop } from 'es-toolkit/function';\n\nimport classNames from '../../utils/classNames';\nimport Button from '../../Button';\nimport useKey from '../../hooks/useKey';\nimport useEsc from '../../hooks/useEsc';\n\nconst DEFAULT_BUTTON_STYLE = 'primary';\n\nconst useFocus = (isEditable: boolean) => {\n const inputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n if (inputRef.current && isEditable) {\n inputRef.current.focus();\n }\n }, [inputRef.current, isEditable]);\n\n return inputRef;\n};\n\nexport type SaveableInputProps = {\n /**\n * The input placeholder.\n */\n placeholder?: string;\n\n /**\n * The previous or old value shown above the input value.\n * This value will *not* be changed for new input values.\n */\n fixedPreviousValue?: string;\n\n /**\n * The previous or old value shown above the input value.\n * This value *changes* when a new input value is accepted.\n */\n previousValue?: string;\n\n /**\n * The actual input value.\n */\n value?: string;\n\n /**\n * Used to control the save button from the outside to disable it in case\n * the entered value is not valid.\n *\n * @default true\n */\n isValid?: boolean;\n\n /**\n * This is the error message that is shown below the input. It uses the built-in error handling,\n * and will be shown when the \"isValid\" prop is set to false.\n */\n errorMessage?: string | React.ReactNode;\n\n /**\n * Defines wether the error icon is shown or not. If enabled, it will be shown when the \"isValid\" prop\n * is set to false.\n *\n * @default false\n */\n hideErrorIcon?: boolean;\n\n /**\n * Callback function triggered when the value changes.\n * @param value\n * @param previousValue\n * @returns\n */\n onValueChanged?: (value: string, previousValue: string) => void;\n\n /**\n * Callback function that gets triggered on every input change. Use this to control the component\n * or when implementing key validation.\n * @param keyValue the key value that has been entered\n * @param inputValue the current complete value of the input\n * @returns\n */\n onInputChange?: (keyValue: string, inputValue: string) => void;\n\n /**\n * Callback function that gets triggered when the user aborts the edit mode. Use this\n * to control the component and handle the resetting of previous value on the outside.\n * @returns\n */\n onEsc?: () => void;\n\n /**\n * Callback function that gets triggered when the input is in edit mode. Use this\n * to control the component dna to handle the previous value on the outside.\n * @returns\n */\n onEnterEdit?: () => void;\n\n /**\n * Defines the button style: `default` or `primary`.\n *\n * @default 'primary'\n */\n buttonStyle?: 'primary' | 'default';\n\n /**\n * Additional HTML attributes to be set on the input element.\n */\n inputProps?: HTMLAttributes<HTMLInputElement>;\n\n /**\n * Adds a given unit to the input.\n */\n unit?: string | React.ReactNode;\n\n /**\n * Icon class name that shall be used. If defined, the input element is wrapped in an input-group\n * and the icon will be set in an input-addon. Example: `rioglyph-search`.\n */\n icon?: string;\n\n /**\n * Disables the component so the user cannot enter the edit mode.\n *\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Additional classes to be set on the input itself.\n */\n inputClassName?: string;\n\n /**\n * Additional classes to be set on the wrapper element.\n */\n className?: string;\n};\n\n// Features:\n// [ ] what shall happen when user leaves component while in edit mode (click outside or tab) - close on blur?\n// [x] avoid save without change\n// [x] use fixed previous value\n// [x] enter = save\n// [x] esc key to abort and leave edit mode\n// [x] tab focus + enter = go into edit mode\n// [x] validate after each key, i.e for number inputs - use onInputChange callback\n// [x] support form feedback error - wrap it with form-group and feedback classes\n// [x] allow for unit and icon\n// [x] disabled input\n\nconst SaveableInput = (props: SaveableInputProps) => {\n const {\n placeholder,\n fixedPreviousValue = '',\n previousValue = '',\n value: externalValue = '',\n isValid = true,\n errorMessage,\n hideErrorIcon = false,\n onValueChanged = noop,\n onInputChange,\n onEsc = noop,\n onEnterEdit = noop,\n buttonStyle = DEFAULT_BUTTON_STYLE,\n inputClassName,\n inputProps,\n icon,\n unit,\n disabled = false,\n className,\n ...remainingProps\n } = props;\n\n const externalOldValue = previousValue || fixedPreviousValue;\n\n const [inputValue, setInputValue] = useState(externalValue);\n const [oldInputValue, setOldInputValue] = useState(externalOldValue);\n\n const [editInput, setEditInput] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const initialInputValueRef = useRef(inputValue);\n const initialOldInputValueRef = useRef(oldInputValue);\n\n // Update internal state in a controlled environment\n const [previousExternalValue, setPreviousExternalValue] = useState(externalValue);\n if (previousExternalValue !== externalValue) {\n setInputValue(externalValue);\n setPreviousExternalValue(externalValue);\n }\n\n // Update internal state in a controlled environment\n const [previousExternalOldValue, setPreviousExternalOldValue] = useState(externalOldValue);\n if (previousExternalOldValue !== externalOldValue) {\n setOldInputValue(externalOldValue);\n setPreviousExternalOldValue(externalOldValue);\n }\n\n // Set focus on input when being in edit mode\n const inputRef = useFocus(editInput);\n\n // Allow to exit \"edit\" mode with \"Enter\" to accept changes\n useKey((event: KeyboardEvent) => {\n if (isFocused && editInput && isValid && event.key === 'Enter') {\n handleToggleInput();\n }\n });\n\n // Allow to exit \"edit\" mode with \"Esc\" to ignore changes\n useEsc(() => {\n if (isFocused) {\n // Restore local state to initial vales as it was when entering edit mode\n setInputValue(initialInputValueRef.current);\n setOldInputValue(initialOldInputValueRef.current);\n setEditInput(false);\n onEsc();\n }\n });\n\n const handleToggleInput = () => {\n if (editInput === false) {\n setEditInput(true);\n\n // Temporarily store values of input and oldInput to be used when\n // discarding changes on \"esc\" or to avoid saving without changes\n if (!fixedPreviousValue) {\n initialOldInputValueRef.current = oldInputValue;\n }\n initialInputValueRef.current = inputValue;\n\n onEnterEdit();\n } else {\n setEditInput(false);\n\n // In case the new input value has not changed to the initial value\n // reset the internal old value to the initial\n if (initialInputValueRef.current !== inputValue) {\n setOldInputValue(fixedPreviousValue || initialInputValueRef.current);\n onValueChanged(inputValue, oldInputValue);\n }\n }\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n // Only update internal value if the external \"onInputChange\" callback function is not defined\n // as it will be used in a controlled way\n if (onInputChange) {\n // Use type assertion to access nativeEvent.data\n const nativeEventData = (event.nativeEvent as InputEvent)?.data;\n\n // Whe \"backspace\" is used to remove a value, the nativeEventData is undefined. In this case\n // we need to use the target value for the callback otherwise the user will not be able to\n // remove a character from the input\n const currentInputValue = event.target.value;\n\n onInputChange(nativeEventData ?? currentInputValue, event.currentTarget.value);\n return;\n }\n\n setInputValue(event.target.value);\n };\n\n const handleFocus = () => setIsFocused(true);\n const handleBlur = () => setIsFocused(false);\n\n const showOldValue = !isEmpty(oldInputValue) && oldInputValue !== inputValue && !editInput;\n const hasUnit = Boolean(unit);\n\n const wrapperClasses = classNames('form-group', !isValid && 'has-feedback has-error', className);\n\n const inputClasses = classNames(\n 'form-control',\n showOldValue && 'padding-bottom-0 padding-top-10 text-size-12',\n hasUnit && 'padding-right-50', // This value is not perfect as with longer units it might conflict with the value\n !hasUnit && !isValid && hideErrorIcon && 'padding-right-10', // remove the padding for the error icon if not needed\n inputClassName\n );\n\n const oldValueClasses = classNames(\n 'position-absolute',\n 'top-2',\n 'left-10',\n 'margin-left-3',\n 'text-size-10',\n 'text-decoration-line-through',\n icon && 'padding-left-20'\n );\n\n const buttonIconClasses = classNames('rioglyph', editInput ? 'rioglyph-ok' : 'rioglyph-pencil');\n\n const disableButton = (editInput && !isValid) || disabled;\n\n return (\n <div {...remainingProps} className={wrapperClasses}>\n <div className='input-group'>\n {icon && (\n <span className='input-group-addon'>\n <span className={`rioglyph ${icon}`} aria-hidden='true' aria-label='input icon' />\n </span>\n )}\n <input\n type='text'\n ref={inputRef}\n placeholder={placeholder}\n className={inputClasses}\n value={inputValue}\n onChange={handleInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={!editInput}\n {...inputProps}\n />\n {hasUnit && (\n <div className='position-absolute right-0 margin-right-50' aria-label='unit'>\n {unit}\n </div>\n )}\n {showOldValue && (\n <div className={oldValueClasses} aria-label='previous value'>\n {oldInputValue}\n </div>\n )}\n <div className='input-group-btn'>\n <Button bsStyle={buttonStyle} iconOnly onClick={handleToggleInput} disabled={disableButton}>\n <span className={buttonIconClasses} />\n </Button>\n </div>\n </div>\n {!isValid && !hideErrorIcon && !hasUnit && (\n <span className='right-25 margin-right-10 form-control-feedback rioglyph rioglyph-error-sign' />\n )}\n {!isValid && errorMessage && (\n <span className='help-block z-index-max'>\n <span>{errorMessage}</span>\n </span>\n )}\n </div>\n );\n};\n\nexport default SaveableInput;\n"],"names":["DEFAULT_BUTTON_STYLE","useFocus","isEditable","inputRef","useRef","useEffect","SaveableInput","props","placeholder","fixedPreviousValue","previousValue","externalValue","isValid","errorMessage","hideErrorIcon","onValueChanged","noop","onInputChange","onEsc","onEnterEdit","buttonStyle","inputClassName","inputProps","icon","unit","disabled","className","remainingProps","externalOldValue","inputValue","setInputValue","useState","oldInputValue","setOldInputValue","editInput","setEditInput","isFocused","setIsFocused","initialInputValueRef","initialOldInputValueRef","previousExternalValue","setPreviousExternalValue","previousExternalOldValue","setPreviousExternalOldValue","useKey","event","handleToggleInput","useEsc","handleInputChange","nativeEventData","currentInputValue","handleFocus","handleBlur","showOldValue","isEmpty","hasUnit","wrapperClasses","classNames","inputClasses","oldValueClasses","buttonIconClasses","disableButton","jsxs","jsx","Button"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
type SearchHighlightTextProps = {
|
|
2
|
+
/**
|
|
3
|
+
* Full text content to render and highlight.
|
|
4
|
+
*/
|
|
5
|
+
text: string;
|
|
6
|
+
/**
|
|
7
|
+
* Search query used to highlight matches within the text.
|
|
8
|
+
*/
|
|
9
|
+
query: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether to perform a case-sensitive match.
|
|
12
|
+
*
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
caseSensitive?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Optional CSS highlight class name (used by the Highlight API).
|
|
18
|
+
*
|
|
19
|
+
* @default 'search-result-highlight'
|
|
20
|
+
*/
|
|
21
|
+
highlightClassName?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional additional classes applied to the wrapper element.
|
|
24
|
+
*/
|
|
25
|
+
classNames?: string;
|
|
26
|
+
};
|
|
27
|
+
declare const SearchHighlightText: (props: SearchHighlightTextProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export default SearchHighlightText;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import d, { useRef as S, useMemo as m } from "react";
|
|
3
|
+
import h, { SEARCH_HIGHLIGHT_CLASS as x } from "../../hooks/useSearchHighlight.js";
|
|
4
|
+
const H = (r) => r.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), w = (r) => {
|
|
5
|
+
const { text: c, query: o, caseSensitive: a = !1, highlightClassName: p = x, classNames: i = "" } = r, n = S(null), e = m(() => o.trim(), [o]), g = m(() => h.supported(), []);
|
|
6
|
+
if (h({ ref: n, query: e, highlightClassName: p, caseSensitive: a }), !g && e) {
|
|
7
|
+
const u = new RegExp(`(${H(e)})`, a ? "g" : "gi"), f = c.split(u);
|
|
8
|
+
return /* @__PURE__ */ t("span", { className: i, children: f.map((s, l) => (a ? s === e : s.toLowerCase() === e.toLowerCase()) ? /* @__PURE__ */ t("mark", { children: s }, l) : /* @__PURE__ */ t(d.Fragment, { children: s }, l)) });
|
|
9
|
+
}
|
|
10
|
+
return /* @__PURE__ */ t("span", { ref: n, className: i, children: c });
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
w as default
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=SearchHighlightText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchHighlightText.js","sources":["../../../src/components/searchHighlight/SearchHighlightText.tsx"],"sourcesContent":["import React, { useMemo, useRef } from 'react';\nimport useSearchHighlight, { SEARCH_HIGHLIGHT_CLASS } from '../../hooks/useSearchHighlight';\n\ntype SearchHighlightTextProps = {\n /**\n * Full text content to render and highlight.\n */\n text: string;\n\n /**\n * Search query used to highlight matches within the text.\n */\n query: string;\n\n /**\n * Whether to perform a case-sensitive match.\n *\n * @default false\n */\n caseSensitive?: boolean;\n\n /**\n * Optional CSS highlight class name (used by the Highlight API).\n *\n * @default 'search-result-highlight'\n */\n highlightClassName?: string;\n\n /**\n * Optional additional classes applied to the wrapper element.\n */\n classNames?: string;\n};\n\nconst escapeRegExp = (value: string) => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst SearchHighlightText = (props: SearchHighlightTextProps) => {\n const { text, query, caseSensitive = false, highlightClassName = SEARCH_HIGHLIGHT_CLASS, classNames = '' } = props;\n\n const ref = useRef<HTMLSpanElement | null>(null);\n\n // Normalize once to keep comparisons stable across re-renders.\n const normalizedQuery = useMemo(() => query.trim(), [query]);\n\n // Native CSS highlighting is preferred when available.\n const isSupported = useMemo(() => useSearchHighlight.supported(), []);\n\n // always call the hook\n useSearchHighlight({ ref, query: normalizedQuery, highlightClassName, caseSensitive });\n\n if (!isSupported && normalizedQuery) {\n // Fallback: split and wrap matching segments in <mark>.\n const regex = new RegExp(`(${escapeRegExp(normalizedQuery)})`, caseSensitive ? 'g' : 'gi');\n const parts = text.split(regex);\n\n return (\n <span className={classNames}>\n {parts.map((part, index) => {\n const isMatch = caseSensitive\n ? part === normalizedQuery\n : part.toLowerCase() === normalizedQuery.toLowerCase();\n return isMatch ? (\n <mark key={index}>{part}</mark>\n ) : (\n <React.Fragment key={index}>{part}</React.Fragment>\n );\n })}\n </span>\n );\n }\n\n return (\n <span ref={ref} className={classNames}>\n {text}\n </span>\n );\n};\n\nexport default SearchHighlightText;\n"],"names":["escapeRegExp","value","SearchHighlightText","props","text","query","caseSensitive","highlightClassName","SEARCH_HIGHLIGHT_CLASS","classNames","ref","useRef","normalizedQuery","useMemo","isSupported","useSearchHighlight","regex","parts","jsx","part","index","React"],"mappings":";;;AAkCA,MAAMA,IAAe,CAACC,MAAkBA,EAAM,QAAQ,uBAAuB,MAAM,GAE7EC,IAAsB,CAACC,MAAoC;AAC7D,QAAM,EAAE,MAAAC,GAAM,OAAAC,GAAO,eAAAC,IAAgB,IAAO,oBAAAC,IAAqBC,GAAwB,YAAAC,IAAa,GAAA,IAAON,GAEvGO,IAAMC,EAA+B,IAAI,GAGzCC,IAAkBC,EAAQ,MAAMR,EAAM,QAAQ,CAACA,CAAK,CAAC,GAGrDS,IAAcD,EAAQ,MAAME,EAAmB,UAAA,GAAa,CAAA,CAAE;AAKpE,MAFAA,EAAmB,EAAE,KAAAL,GAAK,OAAOE,GAAiB,oBAAAL,GAAoB,eAAAD,GAAe,GAEjF,CAACQ,KAAeF,GAAiB;AAEjC,UAAMI,IAAQ,IAAI,OAAO,IAAIhB,EAAaY,CAAe,CAAC,KAAKN,IAAgB,MAAM,IAAI,GACnFW,IAAQb,EAAK,MAAMY,CAAK;AAE9B,WACI,gBAAAE,EAAC,UAAK,WAAWT,GACZ,YAAM,IAAI,CAACU,GAAMC,OACEd,IACVa,MAASP,IACTO,EAAK,YAAA,MAAkBP,EAAgB,YAAA,KAEzC,gBAAAM,EAAC,QAAA,EAAkB,UAAAC,EAAA,GAARC,CAAa,IAExB,gBAAAF,EAACG,EAAM,UAAN,EAA4B,UAAAF,EAAA,GAARC,CAAa,CAEzC,EAAA,CACL;AAAA,EAER;AAEA,SACI,gBAAAF,EAAC,QAAA,EAAK,KAAAR,GAAU,WAAWD,GACtB,UAAAL,GACL;AAER;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as c, jsxs as x, Fragment as Q } from "react/jsx-runtime";
|
|
2
2
|
import { useState as y, useRef as _, useEffect as b, useLayoutEffect as Y } from "react";
|
|
3
|
-
import C from "classnames";
|
|
4
3
|
import { isEmpty as V } from "es-toolkit/compat";
|
|
5
4
|
import { noop as N } from "es-toolkit/function";
|
|
5
|
+
import C from "../../utils/classNames.js";
|
|
6
6
|
import { useDropDirection as Z } from "../../utils/useDropDirection.js";
|
|
7
7
|
import { DOWN as O, scrollItemIntoView as T, UP as g } from "../../utils/scrollItemIntoView.js";
|
|
8
8
|
import $ from "../../hooks/useEffectOnce.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseSelectDropdown.js","sources":["../../../src/components/selects/BaseSelectDropdown.tsx"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport classNames from 'classnames';\nimport { isEmpty } from 'es-toolkit/compat';\nimport { noop } from 'es-toolkit/function';\n\nimport { useDropDirection } from '../../utils/useDropDirection';\nimport { DOWN, scrollItemIntoView, UP } from '../../utils/scrollItemIntoView';\nimport useEffectOnce from '../../hooks/useEffectOnce';\nimport useKey from '../../useKey';\nimport DropdownHeader from './DropdownHeader';\nimport NoItemMessage from './NoItemMessage';\nimport Spinner from '../spinner/Spinner';\n\nconst DATA_ATTRIBUTE_ID = 'data-item-id';\nconst DEFAULT_FOCUSED_ITEM_INDEX = 0;\nconst HIGHLIGHT_CLASS = 'focus';\nconst DEFAULT_SCROLL_DIRECTION = DOWN;\n\nexport type OptionDOMValue = {\n id: string;\n text: string;\n};\n\nexport type SelectOption = {\n /**\n * Used to identify an option.\n */\n id: string;\n\n /**\n * The option item text.\n */\n label: string | React.ReactNode;\n\n /**\n * Icon to be displayed in front of the label.\n */\n icon?: React.ReactNode;\n\n /**\n * Defines whether the menu item is selected.\n *\n * @default false\n */\n selected?: boolean;\n\n /**\n * Setting \"disabled\" to true will disable the respective item.\n *\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Will treat the given value as a menu header\n */\n header?: boolean;\n};\n\nexport type BaseSelectDropdownProps<T extends SelectOption> = {\n options?: T[];\n isOpen?: boolean;\n isLoading?: boolean;\n updateDOMValues?: (values: OptionDOMValue[] | undefined) => void;\n onOpen?: (hasDropup: boolean) => void;\n onSelect?: (selectedItem: T | undefined) => void;\n onClose?: () => void;\n placeholder?: string | React.ReactNode;\n dropup?: boolean;\n pullRight?: boolean;\n autoDropDirection?: boolean;\n noItemMessage?: string | React.ReactNode;\n focusedItemIndex?: number;\n dropdownClassName?: string;\n keyboardUsed?: boolean;\n useActiveClass?: boolean;\n};\n\nconst BaseSelectDropdown = <T extends SelectOption>(props: BaseSelectDropdownProps<T>) => {\n const {\n isOpen = false,\n isLoading = false,\n updateDOMValues = noop,\n onOpen = noop,\n onSelect = noop,\n onClose = noop,\n options = [],\n autoDropDirection = true,\n dropup = false,\n pullRight = false,\n useActiveClass = false,\n focusedItemIndex: externalFocusedItemIndex,\n keyboardUsed: externalKeyboardUsed,\n noItemMessage,\n dropdownClassName,\n } = props;\n\n const [focusedItemIndex, setFocusedItemIndex] = useState(externalFocusedItemIndex || DEFAULT_FOCUSED_ITEM_INDEX);\n const [keyboardUsed, setKeyboardUsed] = useState(externalKeyboardUsed);\n const lastScrollDirectionRef = useRef<typeof UP | typeof DOWN>(DEFAULT_SCROLL_DIRECTION);\n\n const dropdownMenuRef = useRef<HTMLUListElement>(null);\n\n // Reset scroll position whenever the menu opens to avoid retaining old scroll offsets\n useEffect(() => {\n if (isOpen && dropdownMenuRef.current) {\n dropdownMenuRef.current.scrollTop = 0;\n }\n }, [isOpen]);\n\n // Keep internal focus state in sync when the dropdown opens/closes or when parent-controlled values change\n useEffect(() => {\n if (typeof externalFocusedItemIndex === 'number') {\n setFocusedItemIndex(externalFocusedItemIndex);\n }\n\n if (typeof externalKeyboardUsed === 'boolean') {\n setKeyboardUsed(externalKeyboardUsed);\n }\n\n if (!isOpen) {\n lastScrollDirectionRef.current = DEFAULT_SCROLL_DIRECTION;\n }\n }, [externalFocusedItemIndex, externalKeyboardUsed, isOpen]);\n\n useEffectOnce(() => {\n // all available items need to be rendered in order to know their DOM value\n // which will be used for filtering in the parent component\n const currentItemDOMValues = updateItemDOMValues();\n updateDOMValues(currentItemDOMValues);\n });\n\n // Overwrite position of dropdown menu in case auto drop is enabled\n const dropDirection = useDropDirection({ pullRight, dropup, autoDropDirection, dropdownMenuRef }, [isOpen]);\n\n // Add or remove the \"dropup\" class from the parent Select/Multiselect component to position\n // the dropdown element accordingly via CSS\n useLayoutEffect(() => {\n if (dropdownMenuRef.current) {\n const parent = dropdownMenuRef.current.parentElement;\n if (dropDirection.dropup) {\n parent?.classList.add('dropup');\n } else {\n parent?.classList.remove('dropup');\n }\n }\n }, [dropDirection, dropdownMenuRef]);\n\n useEffect(() => {\n if (dropdownMenuRef.current) {\n updateDOMValues(updateItemDOMValues());\n }\n }, [dropdownMenuRef.current]);\n\n // Scroll the focused item into view whenever focus changes\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n\n scrollItemIntoView(\n lastScrollDirectionRef.current || DEFAULT_SCROLL_DIRECTION,\n dropdownMenuRef.current,\n getFocusedOptionNode()\n );\n }, [focusedItemIndex, isOpen]);\n\n // update internal state for isOpen\n const [previousIsOpen, setPreviousIsOpen] = useState(isOpen);\n if (isOpen && !previousIsOpen) {\n onOpen(dropDirection.dropup);\n setPreviousIsOpen(isOpen);\n } else if (!isOpen && previousIsOpen) {\n onClose();\n setPreviousIsOpen(isOpen);\n }\n\n useKey(event => {\n if (isOpen) {\n switch (event.key) {\n case 'Escape': {\n // close dropdown on esc\n onClose();\n break;\n }\n case 'Tab': {\n // close dropdown on tab\n onClose();\n break;\n }\n case 'Enter': {\n // select item on enter\n selectOptionOnEnter(event);\n break;\n }\n case 'ArrowUp': {\n // prevent scrolling the page when dropdown menu is open\n event.preventDefault();\n\n // select item above on arrow up key\n focusOption(UP);\n scrollItemIntoView(UP, dropdownMenuRef.current, getFocusedOptionNode());\n break;\n }\n case 'ArrowDown': {\n // prevent scrolling the page when dropdown menu is open\n event.preventDefault();\n\n // select item below on arrow down key\n focusOption(DOWN);\n scrollItemIntoView(DOWN, dropdownMenuRef.current, getFocusedOptionNode());\n break;\n }\n default:\n break;\n }\n }\n });\n\n const focusOption = (direction: typeof UP | typeof DOWN) => {\n let nextFocusedItem = 0;\n\n switch (direction) {\n case UP: {\n nextFocusedItem = focusedItemIndex <= 0 ? focusedItemIndex : focusedItemIndex - 1;\n break;\n }\n case DOWN: {\n nextFocusedItem = focusedItemIndex === options.length - 1 ? focusedItemIndex : focusedItemIndex + 1;\n break;\n }\n default:\n break;\n }\n\n lastScrollDirectionRef.current = direction;\n\n // In case the next item index is negative, means outside the bounds of the items,\n // reset it depending on the current direction\n const indexLimit = direction === UP ? options.length - 1 : 0;\n\n setFocusedItemIndex(nextFocusedItem < 0 ? indexLimit : nextFocusedItem);\n setKeyboardUsed(true);\n };\n\n const getOptionNodes = () => {\n const node = dropdownMenuRef.current;\n return node?.getElementsByTagName('a') || [];\n };\n\n const updateItemDOMValues = () => {\n if (dropdownMenuRef.current) {\n const optionNodes = getOptionNodes();\n return [...optionNodes].map(item => {\n return {\n id: item.getAttribute(DATA_ATTRIBUTE_ID),\n text: item.textContent,\n } as OptionDOMValue;\n });\n }\n };\n\n const getFocusedOptionNode = () => {\n const optionNodes = getOptionNodes();\n return [...optionNodes].find(item => item.className.includes(HIGHLIGHT_CLASS));\n };\n\n const selectOptionOnEnter = (event: KeyboardEvent) => {\n event.preventDefault();\n\n // When no filter result was found, avoid selecting anything\n if (isEmpty(options)) {\n return;\n }\n\n const match = getFocusedOptionNode();\n\n if (match) {\n const selectedItem = options.find(option => option.id === match.getAttribute(DATA_ATTRIBUTE_ID));\n onSelect(selectedItem);\n }\n };\n\n const handleOptionChange = (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n\n const optionId = event.currentTarget.getElementsByTagName('input')[0].value;\n const selectedItem = options.find(option => option.id === optionId);\n\n onSelect(selectedItem);\n };\n\n const dropdownMenuClasses = classNames('dropdown-menu', dropDirection.pullRight && 'pull-right', dropdownClassName);\n\n // Don't show the dropdown, when no match are found when filtering unless there is a not found message\n if (isEmpty(options)) {\n return <NoItemMessage noItemMessage={noItemMessage} className={dropdownMenuClasses} />;\n }\n\n return (\n <ul className={dropdownMenuClasses} ref={dropdownMenuRef} role='menu'>\n {isLoading && (\n <div className='display-flex justify-content-center padding-10'>\n <Spinner />\n </div>\n )}\n {!isLoading &&\n options.map((option, index) => {\n if (option.header) {\n return <DropdownHeader key={option.id} icon={option.icon} label={option.label} />;\n }\n\n // Show focused style only when keyboard is in use\n const anchorClassNames = classNames(\n keyboardUsed && focusedItemIndex === index ? HIGHLIGHT_CLASS : '',\n option.disabled && 'pointer-events-none',\n 'display-flex align-items-center gap-3'\n );\n\n const wrapperClassNames = classNames(\n option.disabled && 'disabled',\n useActiveClass && option.selected && 'active'\n );\n\n return (\n <li key={option.id} className={wrapperClassNames} role='listitem'>\n <a\n role='menuitem'\n className={anchorClassNames}\n data-item-id={option.id}\n data-item-index={index}\n // Note, we need to assign the click callback only when it's not disabled\n // otherwise the functions is still triggered\n onClick={option.disabled ? undefined : handleOptionChange}\n >\n <span className='selected-option-dropdown-item'>\n {option.icon && <>{option.icon}</>}\n {option.label}\n </span>\n <input type='hidden' value={option.id} />\n </a>\n </li>\n );\n })}\n </ul>\n );\n};\n\nexport const filterOptions = <T extends SelectOption>(\n itemDOMValues: OptionDOMValue[],\n filterValue: string,\n options: T[]\n) => {\n const filteredDOMValues = itemDOMValues.filter(item => item.text.toLowerCase().includes(filterValue.toLowerCase()));\n\n // Filter the options according to the filtered DOM values and map the IDs since the filter cannot be done\n // on the options itself as they might contain arbitrary components\n return options.filter(option => {\n return filteredDOMValues.find(domValue => domValue.id === option.id);\n });\n};\n\nexport default BaseSelectDropdown;\n"],"names":["DATA_ATTRIBUTE_ID","DEFAULT_FOCUSED_ITEM_INDEX","HIGHLIGHT_CLASS","DEFAULT_SCROLL_DIRECTION","DOWN","BaseSelectDropdown","props","isOpen","isLoading","updateDOMValues","noop","onOpen","onSelect","onClose","options","autoDropDirection","dropup","pullRight","useActiveClass","externalFocusedItemIndex","externalKeyboardUsed","noItemMessage","dropdownClassName","focusedItemIndex","setFocusedItemIndex","useState","keyboardUsed","setKeyboardUsed","lastScrollDirectionRef","useRef","dropdownMenuRef","useEffect","useEffectOnce","currentItemDOMValues","updateItemDOMValues","dropDirection","useDropDirection","useLayoutEffect","parent","scrollItemIntoView","getFocusedOptionNode","previousIsOpen","setPreviousIsOpen","useKey","event","selectOptionOnEnter","focusOption","UP","direction","nextFocusedItem","indexLimit","getOptionNodes","item","isEmpty","match","selectedItem","option","handleOptionChange","optionId","dropdownMenuClasses","classNames","jsx","NoItemMessage","Spinner","index","DropdownHeader","anchorClassNames","wrapperClassNames","jsxs","Fragment","filterOptions","itemDOMValues","filterValue","filteredDOMValues","domValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseSelectDropdown.js","sources":["../../../src/components/selects/BaseSelectDropdown.tsx"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { isEmpty } from 'es-toolkit/compat';\nimport { noop } from 'es-toolkit/function';\n\nimport classNames from '../../utils/classNames';\nimport { useDropDirection } from '../../utils/useDropDirection';\nimport { DOWN, scrollItemIntoView, UP } from '../../utils/scrollItemIntoView';\nimport useEffectOnce from '../../hooks/useEffectOnce';\nimport useKey from '../../useKey';\nimport DropdownHeader from './DropdownHeader';\nimport NoItemMessage from './NoItemMessage';\nimport Spinner from '../spinner/Spinner';\n\nconst DATA_ATTRIBUTE_ID = 'data-item-id';\nconst DEFAULT_FOCUSED_ITEM_INDEX = 0;\nconst HIGHLIGHT_CLASS = 'focus';\nconst DEFAULT_SCROLL_DIRECTION = DOWN;\n\nexport type OptionDOMValue = {\n id: string;\n text: string;\n};\n\nexport type SelectOption = {\n /**\n * Used to identify an option.\n */\n id: string;\n\n /**\n * The option item text.\n */\n label: string | React.ReactNode;\n\n /**\n * Icon to be displayed in front of the label.\n */\n icon?: React.ReactNode;\n\n /**\n * Defines whether the menu item is selected.\n *\n * @default false\n */\n selected?: boolean;\n\n /**\n * Setting \"disabled\" to true will disable the respective item.\n *\n * @default false\n */\n disabled?: boolean;\n\n /**\n * Will treat the given value as a menu header\n */\n header?: boolean;\n};\n\nexport type BaseSelectDropdownProps<T extends SelectOption> = {\n options?: T[];\n isOpen?: boolean;\n isLoading?: boolean;\n updateDOMValues?: (values: OptionDOMValue[] | undefined) => void;\n onOpen?: (hasDropup: boolean) => void;\n onSelect?: (selectedItem: T | undefined) => void;\n onClose?: () => void;\n placeholder?: string | React.ReactNode;\n dropup?: boolean;\n pullRight?: boolean;\n autoDropDirection?: boolean;\n noItemMessage?: string | React.ReactNode;\n focusedItemIndex?: number;\n dropdownClassName?: string;\n keyboardUsed?: boolean;\n useActiveClass?: boolean;\n};\n\nconst BaseSelectDropdown = <T extends SelectOption>(props: BaseSelectDropdownProps<T>) => {\n const {\n isOpen = false,\n isLoading = false,\n updateDOMValues = noop,\n onOpen = noop,\n onSelect = noop,\n onClose = noop,\n options = [],\n autoDropDirection = true,\n dropup = false,\n pullRight = false,\n useActiveClass = false,\n focusedItemIndex: externalFocusedItemIndex,\n keyboardUsed: externalKeyboardUsed,\n noItemMessage,\n dropdownClassName,\n } = props;\n\n const [focusedItemIndex, setFocusedItemIndex] = useState(externalFocusedItemIndex || DEFAULT_FOCUSED_ITEM_INDEX);\n const [keyboardUsed, setKeyboardUsed] = useState(externalKeyboardUsed);\n const lastScrollDirectionRef = useRef<typeof UP | typeof DOWN>(DEFAULT_SCROLL_DIRECTION);\n\n const dropdownMenuRef = useRef<HTMLUListElement>(null);\n\n // Reset scroll position whenever the menu opens to avoid retaining old scroll offsets\n useEffect(() => {\n if (isOpen && dropdownMenuRef.current) {\n dropdownMenuRef.current.scrollTop = 0;\n }\n }, [isOpen]);\n\n // Keep internal focus state in sync when the dropdown opens/closes or when parent-controlled values change\n useEffect(() => {\n if (typeof externalFocusedItemIndex === 'number') {\n setFocusedItemIndex(externalFocusedItemIndex);\n }\n\n if (typeof externalKeyboardUsed === 'boolean') {\n setKeyboardUsed(externalKeyboardUsed);\n }\n\n if (!isOpen) {\n lastScrollDirectionRef.current = DEFAULT_SCROLL_DIRECTION;\n }\n }, [externalFocusedItemIndex, externalKeyboardUsed, isOpen]);\n\n useEffectOnce(() => {\n // all available items need to be rendered in order to know their DOM value\n // which will be used for filtering in the parent component\n const currentItemDOMValues = updateItemDOMValues();\n updateDOMValues(currentItemDOMValues);\n });\n\n // Overwrite position of dropdown menu in case auto drop is enabled\n const dropDirection = useDropDirection({ pullRight, dropup, autoDropDirection, dropdownMenuRef }, [isOpen]);\n\n // Add or remove the \"dropup\" class from the parent Select/Multiselect component to position\n // the dropdown element accordingly via CSS\n useLayoutEffect(() => {\n if (dropdownMenuRef.current) {\n const parent = dropdownMenuRef.current.parentElement;\n if (dropDirection.dropup) {\n parent?.classList.add('dropup');\n } else {\n parent?.classList.remove('dropup');\n }\n }\n }, [dropDirection, dropdownMenuRef]);\n\n useEffect(() => {\n if (dropdownMenuRef.current) {\n updateDOMValues(updateItemDOMValues());\n }\n }, [dropdownMenuRef.current]);\n\n // Scroll the focused item into view whenever focus changes\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n\n scrollItemIntoView(\n lastScrollDirectionRef.current || DEFAULT_SCROLL_DIRECTION,\n dropdownMenuRef.current,\n getFocusedOptionNode()\n );\n }, [focusedItemIndex, isOpen]);\n\n // update internal state for isOpen\n const [previousIsOpen, setPreviousIsOpen] = useState(isOpen);\n if (isOpen && !previousIsOpen) {\n onOpen(dropDirection.dropup);\n setPreviousIsOpen(isOpen);\n } else if (!isOpen && previousIsOpen) {\n onClose();\n setPreviousIsOpen(isOpen);\n }\n\n useKey(event => {\n if (isOpen) {\n switch (event.key) {\n case 'Escape': {\n // close dropdown on esc\n onClose();\n break;\n }\n case 'Tab': {\n // close dropdown on tab\n onClose();\n break;\n }\n case 'Enter': {\n // select item on enter\n selectOptionOnEnter(event);\n break;\n }\n case 'ArrowUp': {\n // prevent scrolling the page when dropdown menu is open\n event.preventDefault();\n\n // select item above on arrow up key\n focusOption(UP);\n scrollItemIntoView(UP, dropdownMenuRef.current, getFocusedOptionNode());\n break;\n }\n case 'ArrowDown': {\n // prevent scrolling the page when dropdown menu is open\n event.preventDefault();\n\n // select item below on arrow down key\n focusOption(DOWN);\n scrollItemIntoView(DOWN, dropdownMenuRef.current, getFocusedOptionNode());\n break;\n }\n default:\n break;\n }\n }\n });\n\n const focusOption = (direction: typeof UP | typeof DOWN) => {\n let nextFocusedItem = 0;\n\n switch (direction) {\n case UP: {\n nextFocusedItem = focusedItemIndex <= 0 ? focusedItemIndex : focusedItemIndex - 1;\n break;\n }\n case DOWN: {\n nextFocusedItem = focusedItemIndex === options.length - 1 ? focusedItemIndex : focusedItemIndex + 1;\n break;\n }\n default:\n break;\n }\n\n lastScrollDirectionRef.current = direction;\n\n // In case the next item index is negative, means outside the bounds of the items,\n // reset it depending on the current direction\n const indexLimit = direction === UP ? options.length - 1 : 0;\n\n setFocusedItemIndex(nextFocusedItem < 0 ? indexLimit : nextFocusedItem);\n setKeyboardUsed(true);\n };\n\n const getOptionNodes = () => {\n const node = dropdownMenuRef.current;\n return node?.getElementsByTagName('a') || [];\n };\n\n const updateItemDOMValues = () => {\n if (dropdownMenuRef.current) {\n const optionNodes = getOptionNodes();\n return [...optionNodes].map(item => {\n return {\n id: item.getAttribute(DATA_ATTRIBUTE_ID),\n text: item.textContent,\n } as OptionDOMValue;\n });\n }\n };\n\n const getFocusedOptionNode = () => {\n const optionNodes = getOptionNodes();\n return [...optionNodes].find(item => item.className.includes(HIGHLIGHT_CLASS));\n };\n\n const selectOptionOnEnter = (event: KeyboardEvent) => {\n event.preventDefault();\n\n // When no filter result was found, avoid selecting anything\n if (isEmpty(options)) {\n return;\n }\n\n const match = getFocusedOptionNode();\n\n if (match) {\n const selectedItem = options.find(option => option.id === match.getAttribute(DATA_ATTRIBUTE_ID));\n onSelect(selectedItem);\n }\n };\n\n const handleOptionChange = (event: React.MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n\n const optionId = event.currentTarget.getElementsByTagName('input')[0].value;\n const selectedItem = options.find(option => option.id === optionId);\n\n onSelect(selectedItem);\n };\n\n const dropdownMenuClasses = classNames('dropdown-menu', dropDirection.pullRight && 'pull-right', dropdownClassName);\n\n // Don't show the dropdown, when no match are found when filtering unless there is a not found message\n if (isEmpty(options)) {\n return <NoItemMessage noItemMessage={noItemMessage} className={dropdownMenuClasses} />;\n }\n\n return (\n <ul className={dropdownMenuClasses} ref={dropdownMenuRef} role='menu'>\n {isLoading && (\n <div className='display-flex justify-content-center padding-10'>\n <Spinner />\n </div>\n )}\n {!isLoading &&\n options.map((option, index) => {\n if (option.header) {\n return <DropdownHeader key={option.id} icon={option.icon} label={option.label} />;\n }\n\n // Show focused style only when keyboard is in use\n const anchorClassNames = classNames(\n keyboardUsed && focusedItemIndex === index ? HIGHLIGHT_CLASS : '',\n option.disabled && 'pointer-events-none',\n 'display-flex align-items-center gap-3'\n );\n\n const wrapperClassNames = classNames(\n option.disabled && 'disabled',\n useActiveClass && option.selected && 'active'\n );\n\n return (\n <li key={option.id} className={wrapperClassNames} role='listitem'>\n <a\n role='menuitem'\n className={anchorClassNames}\n data-item-id={option.id}\n data-item-index={index}\n // Note, we need to assign the click callback only when it's not disabled\n // otherwise the functions is still triggered\n onClick={option.disabled ? undefined : handleOptionChange}\n >\n <span className='selected-option-dropdown-item'>\n {option.icon && <>{option.icon}</>}\n {option.label}\n </span>\n <input type='hidden' value={option.id} />\n </a>\n </li>\n );\n })}\n </ul>\n );\n};\n\nexport const filterOptions = <T extends SelectOption>(\n itemDOMValues: OptionDOMValue[],\n filterValue: string,\n options: T[]\n) => {\n const filteredDOMValues = itemDOMValues.filter(item => item.text.toLowerCase().includes(filterValue.toLowerCase()));\n\n // Filter the options according to the filtered DOM values and map the IDs since the filter cannot be done\n // on the options itself as they might contain arbitrary components\n return options.filter(option => {\n return filteredDOMValues.find(domValue => domValue.id === option.id);\n });\n};\n\nexport default BaseSelectDropdown;\n"],"names":["DATA_ATTRIBUTE_ID","DEFAULT_FOCUSED_ITEM_INDEX","HIGHLIGHT_CLASS","DEFAULT_SCROLL_DIRECTION","DOWN","BaseSelectDropdown","props","isOpen","isLoading","updateDOMValues","noop","onOpen","onSelect","onClose","options","autoDropDirection","dropup","pullRight","useActiveClass","externalFocusedItemIndex","externalKeyboardUsed","noItemMessage","dropdownClassName","focusedItemIndex","setFocusedItemIndex","useState","keyboardUsed","setKeyboardUsed","lastScrollDirectionRef","useRef","dropdownMenuRef","useEffect","useEffectOnce","currentItemDOMValues","updateItemDOMValues","dropDirection","useDropDirection","useLayoutEffect","parent","scrollItemIntoView","getFocusedOptionNode","previousIsOpen","setPreviousIsOpen","useKey","event","selectOptionOnEnter","focusOption","UP","direction","nextFocusedItem","indexLimit","getOptionNodes","item","isEmpty","match","selectedItem","option","handleOptionChange","optionId","dropdownMenuClasses","classNames","jsx","NoItemMessage","Spinner","index","DropdownHeader","anchorClassNames","wrapperClassNames","jsxs","Fragment","filterOptions","itemDOMValues","filterValue","filteredDOMValues","domValue"],"mappings":"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"}
|