@cwellt_software/cwellt-reactjs-lib 1.4.15 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/content/fonts/roboto-mono/LICENSE +93 -0
- package/dist/content/fonts/roboto-mono/RobotoMono.css +43 -0
- package/dist/content/fonts/roboto-mono/files/roboto-mono-latin-ext-wght-italic.woff2 +0 -0
- package/dist/content/fonts/roboto-mono/files/roboto-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/content/fonts/roboto-mono/files/roboto-mono-latin-wght-italic.woff2 +0 -0
- package/dist/content/fonts/roboto-mono/files/roboto-mono-latin-wght-normal.woff2 +0 -0
- package/dist/content/icons/new-cw-icons/NewCwIcons.json +1 -1
- package/dist/content/icons/new-cw-icons/css/new-cw-icons.css +260 -824
- package/dist/content/icons/new-cw-icons/fonts/NewCwIcons.woff +0 -0
- package/dist/deprecated/components/MultiSelect_deprecated_.d.ts +24 -0
- package/dist/deprecated/components/MultiSelect_deprecated_.d.ts.map +1 -0
- package/dist/deprecated/components/dropdown/CwDropdownContainer.d.ts +17 -0
- package/dist/deprecated/components/dropdown/CwDropdownContainer.d.ts.map +1 -0
- package/dist/deprecated/components/multiselect/CwHeadFilter.d.ts +17 -0
- package/dist/deprecated/components/multiselect/CwHeadFilter.d.ts.map +1 -0
- package/dist/deprecated/components/multiselect/CwMultiselect.d.ts +13 -0
- package/dist/deprecated/components/multiselect/CwMultiselect.d.ts.map +1 -0
- package/dist/deprecated/components/multiselect/CwOptionList.d.ts +14 -0
- package/dist/deprecated/components/multiselect/CwOptionList.d.ts.map +1 -0
- package/dist/deprecated/components/tag/CwTag.d.ts +15 -0
- package/dist/deprecated/components/tag/CwTag.d.ts.map +1 -0
- package/dist/index.cjs.js +514 -213
- package/dist/index.css +2 -2
- package/dist/index.d.ts +226 -51
- package/dist/index.es.js +508 -212
- package/dist/playground/main.d.ts +4 -0
- package/dist/playground/main.d.ts.map +1 -0
- package/dist/src/components/control/action/button/CwPopoverButton.d.ts +33 -0
- package/dist/src/components/control/action/button/CwPopoverButton.d.ts.map +1 -0
- package/dist/src/components/control/action/contextual-menu/CwContextualMenu.d.ts +29 -0
- package/dist/src/components/control/action/contextual-menu/CwContextualMenu.d.ts.map +1 -0
- package/dist/src/components/control/action/search/CwAsyncSearch.d.ts +102 -0
- package/dist/src/components/control/action/search/CwAsyncSearch.d.ts.map +1 -0
- package/dist/src/components/control/action/search/CwSearch.d.ts +2 -0
- package/dist/src/components/control/action/search/CwSearch.d.ts.map +1 -1
- package/dist/src/components/control/action/search/searchKeyboardNavigation.d.ts +35 -0
- package/dist/src/components/control/action/search/searchKeyboardNavigation.d.ts.map +1 -0
- package/dist/src/components/control/action/tooltip-dialog/CwTooltipDialog.d.ts +19 -0
- package/dist/src/components/control/action/tooltip-dialog/CwTooltipDialog.d.ts.map +1 -0
- package/dist/src/components/control/choice/deprecated/CwDropdown.d.ts +19 -0
- package/dist/src/components/control/choice/deprecated/CwDropdown.d.ts.map +1 -0
- package/dist/src/components/control/choice/deprecated/CwDropdownNavigation.d.ts +21 -0
- package/dist/src/components/control/choice/deprecated/CwDropdownNavigation.d.ts.map +1 -0
- package/dist/src/components/control/choice/deprecated/MultiSelect_deprecated_.d.ts +24 -0
- package/dist/src/components/control/choice/deprecated/MultiSelect_deprecated_.d.ts.map +1 -0
- package/dist/src/components/control/choice/dropdown/CwDropdown.d.ts +19 -0
- package/dist/src/components/control/choice/dropdown/CwDropdown.d.ts.map +1 -0
- package/dist/src/components/control/choice/dropdown/CwDropdownContainer.d.ts +17 -0
- package/dist/src/components/control/choice/dropdown/CwDropdownContainer.d.ts.map +1 -0
- package/dist/src/components/control/choice/dropdown/CwDropdownNavigation.d.ts +21 -0
- package/dist/src/components/control/choice/dropdown/CwDropdownNavigation.d.ts.map +1 -0
- package/dist/src/components/control/choice/multiselect/CwHeadFilter.d.ts +17 -0
- package/dist/src/components/control/choice/multiselect/CwHeadFilter.d.ts.map +1 -0
- package/dist/src/components/control/choice/multiselect/CwMultiselect.d.ts +13 -0
- package/dist/src/components/control/choice/multiselect/CwMultiselect.d.ts.map +1 -0
- package/dist/src/components/control/choice/multiselect/CwOptionList.d.ts +14 -0
- package/dist/src/components/control/choice/multiselect/CwOptionList.d.ts.map +1 -0
- package/dist/src/components/control/choice/nav-menu/CwNavMenu.d.ts +78 -0
- package/dist/src/components/control/choice/nav-menu/CwNavMenu.d.ts.map +1 -0
- package/dist/src/components/control/choice/nav-menu/filterNavItems.d.ts +9 -0
- package/dist/src/components/control/choice/nav-menu/filterNavItems.d.ts.map +1 -0
- package/dist/src/components/control/choice/nav-menu/sortNavItems.d.ts +9 -0
- package/dist/src/components/control/choice/nav-menu/sortNavItems.d.ts.map +1 -0
- package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts +12 -0
- package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts.map +1 -1
- package/dist/src/components/control/input/image/CwInputImage.d.ts +17 -2
- package/dist/src/components/control/input/image/CwInputImage.d.ts.map +1 -1
- package/dist/src/components/control/input/new-dates/CwDateTimePicker2.d.ts +47 -0
- package/dist/src/components/control/input/new-dates/CwDateTimePicker2.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/CwSchedulerComp2.d.ts +24 -0
- package/dist/src/components/custom/scheduler-temporal/CwSchedulerComp2.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/CwSuperSchedulerComp.d.ts +86 -0
- package/dist/src/components/custom/scheduler-temporal/CwSuperSchedulerComp.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/EventRender.d.ts +10 -0
- package/dist/src/components/custom/scheduler-temporal/components/EventRender.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/ResourceListRender.d.ts +20 -0
- package/dist/src/components/custom/scheduler-temporal/components/ResourceListRender.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/ResourceRender.d.ts +14 -0
- package/dist/src/components/custom/scheduler-temporal/components/ResourceRender.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/DayHeader.d.ts +11 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/DayHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/MonthHeader.d.ts +11 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/MonthHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/MyDaysHeader.d.ts +13 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/MyDaysHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/WeekHeader.d.ts +11 -0
- package/dist/src/components/custom/scheduler-temporal/components/day_headers/WeekHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/resources_title_list/ResourcesTitleList.d.ts +14 -0
- package/dist/src/components/custom/scheduler-temporal/components/resources_title_list/ResourcesTitleList.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/scheduler_content_area/SchedulerContentArea.d.ts +23 -0
- package/dist/src/components/custom/scheduler-temporal/components/scheduler_content_area/SchedulerContentArea.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/scheduler_header/SchedulerHeader.d.ts +8 -0
- package/dist/src/components/custom/scheduler-temporal/components/scheduler_header/SchedulerHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/scheduler_timeline/SchedulerTimeLine.d.ts +12 -0
- package/dist/src/components/custom/scheduler-temporal/components/scheduler_timeline/SchedulerTimeLine.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/time_headers/TimeHeader.d.ts +12 -0
- package/dist/src/components/custom/scheduler-temporal/components/time_headers/TimeHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/time_headers/TimeHeaderRow.d.ts +10 -0
- package/dist/src/components/custom/scheduler-temporal/components/time_headers/TimeHeaderRow.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/components/time_line/TimeLine.d.ts +12 -0
- package/dist/src/components/custom/scheduler-temporal/components/time_line/TimeLine.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/addMinutesToDateFromPx.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/addMinutesToDateFromPx.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/daysBetweenTwoDates.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/daysBetweenTwoDates.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/daysBetweenTwoDatesWithoutCeil.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/daysBetweenTwoDatesWithoutCeil.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getFormatedTimeForHeader.d.ts +7 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getFormatedTimeForHeader.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getMonthHeaderData.d.ts +10 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getMonthHeaderData.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getUtcToday.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getUtcToday.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getWeekHeaderDataFromWeekRange.d.ts +7 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/getWeekHeaderDataFromWeekRange.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/listOfDatesToWeeks.d.ts +8 -0
- package/dist/src/components/custom/scheduler-temporal/logic/dates/listOfDatesToWeeks.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/divisions/calculateDivisionType.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/divisions/calculateDivisionType.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/divisions/calculateDivisions.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/divisions/calculateDivisions.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/filterAndProcessResources.d.ts +4 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/filterAndProcessResources.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/filterEvents.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/filterEvents.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/filterResources.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/filterResources.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/hasSameProperties.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/filtering/hasSameProperties.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/onDrop/OnDrop.d.ts +13 -0
- package/dist/src/components/custom/scheduler-temporal/logic/onDrop/OnDrop.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/getHeightLineScheduler.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/getHeightLineScheduler.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/getPixelsForEvent.d.ts +7 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/getPixelsForEvent.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/heightScheduler.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/heightScheduler.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/heightSchedulerPinned.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/pixels/heightSchedulerPinned.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/doubleClickOnResource.d.ts +4 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/doubleClickOnResource.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/handlePropChanges.d.ts +6 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/handlePropChanges.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/handleResourceChange.d.ts +5 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/handleResourceChange.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/onDragOver.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/onDragOver.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/onDropEventToResource.d.ts +5 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/onDropEventToResource.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/onResizeEvent.d.ts +4 -0
- package/dist/src/components/custom/scheduler-temporal/logic/state_handle/onResizeEvent.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/strings/compareStrings.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/strings/compareStrings.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/strings/getGUID.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/strings/getGUID.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/checkIfSlotAvailable.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/checkIfSlotAvailable.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/getEventsOfResource.d.ts +6 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/getEventsOfResource.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/getHasPropsChanged.d.ts +4 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/getHasPropsChanged.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/getTimeHeaders.d.ts +2 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/getTimeHeaders.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/isAllowedToMove.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/isAllowedToMove.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/shouldTriggerScroll.d.ts +4 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/shouldTriggerScroll.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/updateResourceVisibility.d.ts +3 -0
- package/dist/src/components/custom/scheduler-temporal/logic/ui/updateResourceVisibility.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/CblDragAndDrop.d.ts +11 -0
- package/dist/src/components/custom/scheduler-temporal/state/CblDragAndDrop.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/CwSchedulerProps.d.ts +43 -0
- package/dist/src/components/custom/scheduler-temporal/state/CwSchedulerProps.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/Resource.d.ts +14 -0
- package/dist/src/components/custom/scheduler-temporal/state/Resource.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/State.d.ts +25 -0
- package/dist/src/components/custom/scheduler-temporal/state/State.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/cblEvent.d.ts +18 -0
- package/dist/src/components/custom/scheduler-temporal/state/cblEvent.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/cblEventCompProps.d.ts +7 -0
- package/dist/src/components/custom/scheduler-temporal/state/cblEventCompProps.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-temporal/state/resourceCompProps2.d.ts +6 -0
- package/dist/src/components/custom/scheduler-temporal/state/resourceCompProps2.d.ts.map +1 -0
- package/dist/src/components/display/data/table/CwTable.d.ts +4 -1
- package/dist/src/components/display/data/table/CwTable.d.ts.map +1 -1
- package/dist/src/components/display/data/table-serverside/CwTableServerSide.d.ts +4 -1
- package/dist/src/components/display/data/table-serverside/CwTableServerSide.d.ts.map +1 -1
- package/dist/src/components/display/data/table_sortable/CwSortableTable.d.ts +4 -2
- package/dist/src/components/display/data/table_sortable/CwSortableTable.d.ts.map +1 -1
- package/dist/src/components/display/graphics/icon/CwIcon.d.ts +1 -1
- package/dist/src/components/display/graphics/icon/CwIcon.d.ts.map +1 -1
- package/dist/src/components/display/graphics/loading/CwLoading.d.ts +3 -14
- package/dist/src/components/display/graphics/loading/CwLoading.d.ts.map +1 -1
- package/dist/src/components/display/graphics/loading/loadingConfig.d.ts +16 -0
- package/dist/src/components/display/graphics/loading/loadingConfig.d.ts.map +1 -0
- package/dist/src/components/display/graphics/progress/CwProgress.d.ts +36 -0
- package/dist/src/components/display/graphics/progress/CwProgress.d.ts.map +1 -0
- package/dist/src/components/display/graphics/skeleton/CwSkeleton.d.ts +31 -0
- package/dist/src/components/display/graphics/skeleton/CwSkeleton.d.ts.map +1 -0
- package/dist/src/components/display/graphics/skeleton/CwSkeletonCard.d.ts +21 -0
- package/dist/src/components/display/graphics/skeleton/CwSkeletonCard.d.ts.map +1 -0
- package/dist/src/components/display/graphics/skeleton/normalizeSkeletonCount.d.ts +8 -0
- package/dist/src/components/display/graphics/skeleton/normalizeSkeletonCount.d.ts.map +1 -0
- package/dist/src/components/display/graphics/skeleton/skeletonCellWidth.d.ts +8 -0
- package/dist/src/components/display/graphics/skeleton/skeletonCellWidth.d.ts.map +1 -0
- package/dist/src/components/display/text/tag/CwTag.d.ts +15 -0
- package/dist/src/components/display/text/tag/CwTag.d.ts.map +1 -0
- package/dist/src/components/display/text/tooltip/CwTooltip.d.ts +11 -0
- package/dist/src/components/display/text/tooltip/CwTooltip.d.ts.map +1 -0
- package/dist/src/components/layout/card/CwCard.d.ts +3 -1
- package/dist/src/components/layout/card/CwCard.d.ts.map +1 -1
- package/dist/src/components/layout/card/CwCardList.d.ts +4 -2
- package/dist/src/components/layout/card/CwCardList.d.ts.map +1 -1
- package/dist/src/components/layout/list/key-value/CwKeyValueList.d.ts +4 -0
- package/dist/src/components/layout/list/key-value/CwKeyValueList.d.ts.map +1 -1
- package/dist/src/components/layout/master-detail/CwMasterDetail.d.ts +4 -0
- package/dist/src/components/layout/master-detail/CwMasterDetail.d.ts.map +1 -1
- package/dist/src/components/layout/modal/legacy/cw_modal_confirm.d.ts +16 -0
- package/dist/src/components/layout/modal/legacy/cw_modal_confirm.d.ts.map +1 -0
- package/dist/src/components/layout/modal/legacy/cw_modal_iframe.d.ts +21 -0
- package/dist/src/components/layout/modal/legacy/cw_modal_iframe.d.ts.map +1 -0
- package/dist/src/components/layout/tabs/CwTabs.d.ts +7 -0
- package/dist/src/components/layout/tabs/CwTabs.d.ts.map +1 -1
- package/dist/src/index.d.ts +6 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
- package/dist/src/playground/pages/CwFileUploadMultiplePage.d.ts +3 -0
- package/dist/src/playground/pages/CwFileUploadMultiplePage.d.ts.map +1 -0
- package/dist/src/playground/pages/CwInputImagePage.d.ts.map +1 -1
- package/dist/src/playground/pages/CwNavMenuPage.d.ts +3 -0
- package/dist/src/playground/pages/CwNavMenuPage.d.ts.map +1 -0
- package/dist/src/playground/pages/IconLibraryPage.d.ts +3 -0
- package/dist/src/playground/pages/IconLibraryPage.d.ts.map +1 -0
- package/dist/src/playground/pages/LoadingPage.d.ts +3 -0
- package/dist/src/playground/pages/LoadingPage.d.ts.map +1 -0
- package/dist/src/playground/pages/ProgressPage.d.ts +3 -0
- package/dist/src/playground/pages/ProgressPage.d.ts.map +1 -0
- package/dist/src/playground/pages/SelectorsPage.d.ts.map +1 -1
- package/dist/src/playground/pages/SkeletonPage.d.ts +3 -0
- package/dist/src/playground/pages/SkeletonPage.d.ts.map +1 -0
- package/dist/test/components/control/action/search/searchKeyboardNavigation.test.d.ts +2 -0
- package/dist/test/components/control/action/search/searchKeyboardNavigation.test.d.ts.map +1 -0
- package/dist/test/components/control/choice/nav-menu/CwNavMenu.test.d.ts +2 -0
- package/dist/test/components/control/choice/nav-menu/CwNavMenu.test.d.ts.map +1 -0
- package/dist/test/components/control/choice/nav-menu/filterNavItems.test.d.ts +2 -0
- package/dist/test/components/control/choice/nav-menu/filterNavItems.test.d.ts.map +1 -0
- package/dist/test/components/control/choice/nav-menu/sortNavItems.test.d.ts +2 -0
- package/dist/test/components/control/choice/nav-menu/sortNavItems.test.d.ts.map +1 -0
- package/dist/test/components/control/input/file/fileMatchesAccept.test.d.ts +2 -0
- package/dist/test/components/control/input/file/fileMatchesAccept.test.d.ts.map +1 -0
- package/dist/test/components/control/input/image/readImageFileAsDataUrl.test.d.ts +2 -0
- package/dist/test/components/control/input/image/readImageFileAsDataUrl.test.d.ts.map +1 -0
- package/dist/test/components/display/data/table/CwTable.test.d.ts +2 -0
- package/dist/test/components/display/data/table/CwTable.test.d.ts.map +1 -0
- package/dist/test/components/display/data/table-serverside/CwTableServerSide.test.d.ts +2 -0
- package/dist/test/components/display/data/table-serverside/CwTableServerSide.test.d.ts.map +1 -0
- package/dist/test/components/display/data/table_sortable/CwSortableTable.test.d.ts +2 -0
- package/dist/test/components/display/data/table_sortable/CwSortableTable.test.d.ts.map +1 -0
- package/dist/test/components/display/graphics/loading/CwLoading.test.d.ts +2 -0
- package/dist/test/components/display/graphics/loading/CwLoading.test.d.ts.map +1 -0
- package/dist/test/components/display/graphics/progress/CwProgress.test.d.ts +2 -0
- package/dist/test/components/display/graphics/progress/CwProgress.test.d.ts.map +1 -0
- package/dist/test/components/display/graphics/skeleton/CwSkeleton.test.d.ts +2 -0
- package/dist/test/components/display/graphics/skeleton/CwSkeleton.test.d.ts.map +1 -0
- package/dist/test/components/display/graphics/skeleton/CwSkeletonCard.test.d.ts +2 -0
- package/dist/test/components/display/graphics/skeleton/CwSkeletonCard.test.d.ts.map +1 -0
- package/dist/test/components/display/graphics/skeleton/normalizeSkeletonCount.test.d.ts +2 -0
- package/dist/test/components/display/graphics/skeleton/normalizeSkeletonCount.test.d.ts.map +1 -0
- package/dist/test/components/display/graphics/skeleton/skeletonCellWidth.test.d.ts +2 -0
- package/dist/test/components/display/graphics/skeleton/skeletonCellWidth.test.d.ts.map +1 -0
- package/dist/test/components/layout/card/CwCard.test.d.ts +2 -0
- package/dist/test/components/layout/card/CwCard.test.d.ts.map +1 -0
- package/dist/test/components/layout/card/CwCardList.test.d.ts +2 -0
- package/dist/test/components/layout/card/CwCardList.test.d.ts.map +1 -0
- package/dist/test/components/layout/list/key-value/CwKeyValueList.test.d.ts +2 -0
- package/dist/test/components/layout/list/key-value/CwKeyValueList.test.d.ts.map +1 -0
- package/dist/test/components/layout/master-detail/CwMasterDetail.test.d.ts +2 -0
- package/dist/test/components/layout/master-detail/CwMasterDetail.test.d.ts.map +1 -0
- package/dist/test/jest.setup.d.ts +2 -0
- package/dist/test/jest.setup.d.ts.map +1 -0
- package/package.json +1 -2
package/dist/index.es.js
CHANGED
|
@@ -161,12 +161,7 @@ function getContrastColor(color) {
|
|
|
161
161
|
return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
'sortable-asc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "0.3" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "1" })] })),
|
|
166
|
-
'sortable-desc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "1" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "0.3" })] })),
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
var styles$u = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
|
|
164
|
+
var styles$x = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
|
|
170
165
|
|
|
171
166
|
// Constants
|
|
172
167
|
const margin$1 = 16;
|
|
@@ -456,7 +451,7 @@ const CwTooltipManager = () => {
|
|
|
456
451
|
if (!state.isVisible || !state.content) {
|
|
457
452
|
return null;
|
|
458
453
|
}
|
|
459
|
-
return createPortal(jsx("div", { ref: tooltipRef, className: styles$
|
|
454
|
+
return createPortal(jsx("div", { ref: tooltipRef, className: styles$x["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
|
|
460
455
|
top: `${tooltipPosition.top}px`,
|
|
461
456
|
left: `${tooltipPosition.left}px`,
|
|
462
457
|
opacity: (isPositioned && !isMeasuring) ? 1 : 0,
|
|
@@ -537,16 +532,22 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
|
|
|
537
532
|
useEffect(() => {
|
|
538
533
|
ensureTooltipManager();
|
|
539
534
|
}, []);
|
|
540
|
-
return (jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$
|
|
535
|
+
return (jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$x["cw-tooltip"], children: children }));
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
const SVG_ICONS = {
|
|
539
|
+
'sortable-asc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "0.3" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "1" })] })),
|
|
540
|
+
'sortable-desc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "1" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "0.3" })] })),
|
|
541
541
|
};
|
|
542
542
|
|
|
543
543
|
function CwIcon(props) {
|
|
544
|
-
const { iconId, color, size, title, tooltipPosition = 'bottom', ...iconProps } = props;
|
|
544
|
+
const { iconId, color, size, className, title, tooltipPosition = 'bottom', ...iconProps } = props;
|
|
545
545
|
const getClassName = (baseClass) => {
|
|
546
546
|
return [
|
|
547
547
|
baseClass,
|
|
548
548
|
color && `cw-color-${color}`,
|
|
549
|
-
size && `cw-font-size-${size}
|
|
549
|
+
size && `cw-font-size-${size}`,
|
|
550
|
+
className
|
|
550
551
|
].filter(Boolean).join(' ');
|
|
551
552
|
};
|
|
552
553
|
let iconElement;
|
|
@@ -958,49 +959,128 @@ function CwImageZoom(image) {
|
|
|
958
959
|
} }), jsx("div", { style: { color: "#fff", fontSize: "1rem", textAlign: "center" }, children: selectedImage.filename && jsx("div", { children: selectedImage.filename }) })] }))] }));
|
|
959
960
|
}
|
|
960
961
|
|
|
962
|
+
let defaults = {};
|
|
963
|
+
/**
|
|
964
|
+
* Register global CwLoading defaults. Call once at app init, before the first render.
|
|
965
|
+
* Merges into any previously configured defaults.
|
|
966
|
+
*/
|
|
967
|
+
function configureCwLoading(next) {
|
|
968
|
+
defaults = { ...defaults, ...next };
|
|
969
|
+
}
|
|
970
|
+
/** Read the currently configured CwLoading defaults. */
|
|
971
|
+
function getCwLoadingDefaults() {
|
|
972
|
+
return defaults;
|
|
973
|
+
}
|
|
974
|
+
|
|
961
975
|
/**
|
|
962
|
-
* CwLoading
|
|
976
|
+
* CwLoading — a spinner with optional text that dims the wrapped content while loading.
|
|
963
977
|
*
|
|
964
|
-
*
|
|
965
|
-
* and disables the wrapped content while in loading state.
|
|
978
|
+
* Icon resolves as `iconName` prop → `getCwLoadingDefaults().icon` → none (neutral ring).
|
|
966
979
|
*
|
|
967
980
|
* @example
|
|
968
|
-
* // Basic usage
|
|
969
981
|
* <CwLoading isLoading={isSubmitting}>
|
|
970
982
|
* <form>...</form>
|
|
971
983
|
* </CwLoading>
|
|
972
|
-
*
|
|
973
|
-
* // With custom text and size
|
|
974
|
-
* <CwLoading
|
|
975
|
-
* isLoading={isLoading}
|
|
976
|
-
* text="Please wait..."
|
|
977
|
-
* size="large"
|
|
978
|
-
* >
|
|
979
|
-
* <UserProfile />
|
|
980
|
-
* </CwLoading>
|
|
981
984
|
*/
|
|
982
|
-
function CwLoading({ isLoading = false, text = '', size = 'regular', iconPosition = 'outside', iconName
|
|
983
|
-
|
|
984
|
-
|
|
985
|
+
function CwLoading({ isLoading = false, text = '', size = 'regular', iconPosition = 'outside', iconName, animation = 'spin', children }) {
|
|
986
|
+
let overlay = null;
|
|
987
|
+
if (isLoading) {
|
|
988
|
+
const resolvedIcon = iconName ?? getCwLoadingDefaults().icon;
|
|
989
|
+
overlay = (jsxs("div", { className: "cw-loading-content", "data-size": size, "data-animation": animation, role: "status", "aria-label": text || 'Loading', children: [jsx("div", { className: "cw-loading", "data-icon-position": iconPosition, "data-has-icon": !!resolvedIcon, children: resolvedIcon && jsx("span", { className: `cwi-icons ${resolvedIcon}` }) }), text && (jsx("p", { children: text }))] }));
|
|
990
|
+
}
|
|
991
|
+
return (jsxs("div", { "aria-busy": isLoading, className: "cw-loading-container", "data-children": !!children, children: [overlay, jsx("div", { className: "cw-loading-disabled-content", children: children })] }));
|
|
985
992
|
}
|
|
986
993
|
|
|
994
|
+
var styles$w = {"skeleton":"cw-skeleton-module__skeleton__Jvx2x","group":"cw-skeleton-module__group__Cm8AU"};
|
|
995
|
+
|
|
996
|
+
/*
|
|
997
|
+
* Internal helper for skeleton allocations (CwSkeleton, tables, cards).
|
|
998
|
+
* Not exported from the library barrel - not a public API.
|
|
999
|
+
*/
|
|
1000
|
+
/** Upper bound so a pathological count cannot allocate an unbounded number of nodes. */
|
|
1001
|
+
const MAX_SKELETON_COUNT = 100;
|
|
987
1002
|
/**
|
|
988
|
-
*
|
|
1003
|
+
* Normalizes a skeleton count to a finite, floored, non-negative integer capped at
|
|
1004
|
+
* MAX_SKELETON_COUNT. Falls back to `fallback` for undefined, NaN, non-finite or
|
|
1005
|
+
* non-positive input, so valid inputs keep the public default behaviour and only
|
|
1006
|
+
* pathological ones are bounded.
|
|
1007
|
+
*/
|
|
1008
|
+
function normalizeSkeletonCount(value, fallback) {
|
|
1009
|
+
if (value === undefined || !Number.isFinite(value) || value < 1) {
|
|
1010
|
+
return fallback;
|
|
1011
|
+
}
|
|
1012
|
+
return Math.min(Math.floor(value), MAX_SKELETON_COUNT);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
/**
|
|
1016
|
+
* CwSkeleton - a shimmering placeholder that reserves the shape of content while it loads.
|
|
989
1017
|
*
|
|
990
|
-
*
|
|
1018
|
+
* Renders inline <span> elements so it can sit inside text-level contexts. Sizing flows
|
|
1019
|
+
* through component-scoped custom properties; only the props the caller provides are set
|
|
1020
|
+
* inline, so the CSS defaults per variant (and the 60% last-line rule) stay in charge.
|
|
991
1021
|
*
|
|
992
1022
|
* @example
|
|
993
|
-
*
|
|
994
|
-
* <
|
|
995
|
-
*
|
|
996
|
-
* // Use:
|
|
997
|
-
* <CwLoading size="small" />
|
|
1023
|
+
* <CwSkeleton count={3} />
|
|
1024
|
+
* <CwSkeleton variant="circle" />
|
|
1025
|
+
* <CwSkeleton variant="rect" height="10rem" />
|
|
998
1026
|
*/
|
|
999
|
-
function
|
|
1000
|
-
|
|
1027
|
+
function CwSkeleton({ variant = 'text', width, height, count = 1, radius, gap }) {
|
|
1028
|
+
// Only forward the custom properties the caller actually set; CSS declares the defaults.
|
|
1029
|
+
const style = {
|
|
1030
|
+
...(width !== undefined && { '--skeleton-width': width }),
|
|
1031
|
+
...(height !== undefined && { '--skeleton-height': height }),
|
|
1032
|
+
...(radius !== undefined && { '--skeleton-radius': radius })
|
|
1033
|
+
};
|
|
1034
|
+
// The un-hashed cw-skeleton / cw-skeleton-group classes carry no styles in the
|
|
1035
|
+
// library - they are stable public hooks for exceptional external overrides.
|
|
1036
|
+
const skeletonClassName = ['cw-skeleton', styles$w.skeleton].filter(Boolean).join(' ');
|
|
1037
|
+
const groupClassName = ['cw-skeleton-group', styles$w.group].filter(Boolean).join(' ');
|
|
1038
|
+
const lineCount = normalizeSkeletonCount(count, 1);
|
|
1039
|
+
if (lineCount <= 1) {
|
|
1040
|
+
return (jsx("span", { className: skeletonClassName, "data-variant": variant, "aria-hidden": "true", style: style }));
|
|
1041
|
+
}
|
|
1042
|
+
const skeletonElements = Array.from({ length: lineCount }, (_, index) => (jsx("span", { className: skeletonClassName, "data-variant": variant, style: style }, index)));
|
|
1043
|
+
const groupStyle = {
|
|
1044
|
+
...(gap !== undefined && { '--skeleton-gap': gap })
|
|
1045
|
+
};
|
|
1046
|
+
return (jsx("span", { className: groupClassName, "aria-hidden": "true", style: groupStyle, children: skeletonElements }));
|
|
1001
1047
|
}
|
|
1002
1048
|
|
|
1003
|
-
var styles$
|
|
1049
|
+
var styles$v = {"progress":"cw-progress-module__progress__d-g2-","value":"cw-progress-module__value__Q-DrH","header":"cw-progress-module__header__mv5ct","label":"cw-progress-module__label__jwOWp","track":"cw-progress-module__track__572-3","fill":"cw-progress-module__fill__fX1UA"};
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* CwProgress - a determinate or indeterminate progress bar.
|
|
1053
|
+
*
|
|
1054
|
+
* Use it for measurable operations (imports, uploads, batch jobs). For short
|
|
1055
|
+
* unmeasurable waits use CwLoading; for initial layout loads use CwSkeleton.
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* <CwProgress value={62} label="Import" color="success" />
|
|
1059
|
+
* <CwProgress indeterminate label="Uploading" />
|
|
1060
|
+
*/
|
|
1061
|
+
function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'regular', layout = 'row', color = 'primary', monoValue = false, prominent = false }) {
|
|
1062
|
+
const labelId = React__default.useId();
|
|
1063
|
+
// Determinate: a missing or non-finite value is treated as 0 (never NaN), then
|
|
1064
|
+
// clamped to [0,100] for aria-valuenow and the fill width. Indeterminate has no value.
|
|
1065
|
+
const clamped = indeterminate
|
|
1066
|
+
? undefined
|
|
1067
|
+
: Math.min(Math.max(Number.isFinite(value) ? value : 0, 0), 100);
|
|
1068
|
+
const percent = clamped !== undefined ? Math.round(clamped) : undefined;
|
|
1069
|
+
const showValue = rightLabel !== undefined || (!indeterminate && percent !== undefined);
|
|
1070
|
+
const valueText = rightLabel ?? (percent !== undefined ? `${percent}%` : '');
|
|
1071
|
+
// The un-hashed cw-progress class carries no styles in the library - a stable
|
|
1072
|
+
// public hook for exceptional external overrides only.
|
|
1073
|
+
const rootClassName = ['cw-progress', styles$v.progress].filter(Boolean).join(' ');
|
|
1074
|
+
const labelSpan = label ? jsx("span", { className: styles$v.label, id: labelId, children: label }) : null;
|
|
1075
|
+
const valueLabel = showValue ? (jsx("span", { className: styles$v.value, "data-mono": monoValue || undefined, children: valueText })) : null;
|
|
1076
|
+
return (jsxs("div", { className: rootClassName, "data-layout": layout, "data-size": size, "data-color": color, "data-prominent": prominent || undefined, "data-indeterminate": indeterminate || undefined, children: [layout === 'column' && (labelSpan || valueLabel) && (jsxs("header", { className: styles$v.header, children: [labelSpan, valueLabel] })), layout === 'row' && labelSpan, jsx("div", { className: styles$v.track, role: "progressbar", ...(label && { 'aria-labelledby': labelId }), ...(!indeterminate && percent !== undefined && {
|
|
1077
|
+
'aria-valuenow': percent,
|
|
1078
|
+
'aria-valuemin': 0,
|
|
1079
|
+
'aria-valuemax': 100
|
|
1080
|
+
}), children: jsx("div", { className: styles$v.fill, style: !indeterminate && clamped !== undefined ? { width: `${clamped}%` } : undefined }) }), layout === 'row' && valueLabel] }));
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
var styles$u = {"cw-generic-tooltip-content":"cw-generic-tooltip-module__cw-generic-tooltip-content__la-Si","cw-generic-tooltip":"cw-generic-tooltip-module__cw-generic-tooltip__Ij76M"};
|
|
1004
1084
|
|
|
1005
1085
|
// Constants moved outside to prevent recreation
|
|
1006
1086
|
const margin = 16;
|
|
@@ -1123,12 +1203,12 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
|
|
|
1123
1203
|
const { setTooltipTimeout, clearTooltipTimeout } = useTooltipDelay(() => {
|
|
1124
1204
|
setIsVisible(true);
|
|
1125
1205
|
}, showDelay);
|
|
1126
|
-
const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$
|
|
1206
|
+
const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$u["cw-generic-tooltip-content"]);
|
|
1127
1207
|
// Memoize tooltip content creation
|
|
1128
1208
|
const tooltipContent = useMemo(() => {
|
|
1129
1209
|
if (hide || !isVisible || !content)
|
|
1130
1210
|
return null;
|
|
1131
|
-
return createPortal(jsx("div", { className: styles$
|
|
1211
|
+
return createPortal(jsx("div", { className: styles$u["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
|
|
1132
1212
|
position: 'fixed',
|
|
1133
1213
|
top: `${tooltipPosition.top}px`,
|
|
1134
1214
|
left: `${tooltipPosition.left}px`,
|
|
@@ -1143,7 +1223,7 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
|
|
|
1143
1223
|
clearTooltipTimeout();
|
|
1144
1224
|
setIsVisible(false);
|
|
1145
1225
|
}, [clearTooltipTimeout]);
|
|
1146
|
-
return (jsxs("div", { ref: containerRef, className: styles$
|
|
1226
|
+
return (jsxs("div", { ref: containerRef, className: styles$u["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
|
|
1147
1227
|
};
|
|
1148
1228
|
|
|
1149
1229
|
const CwButton = React__default.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }, ref) {
|
|
@@ -1205,7 +1285,7 @@ function CwModal(custModalProps) {
|
|
|
1205
1285
|
return (jsx("div", { children: custModalProps.modalState && (jsxs("div", { className: custModalProps.classNameModalOverlay + " cwelltModalOverlay", children: [jsx("div", { className: "cwelltModalOverlayBg", onClick: custModalProps.onCloseModal }), jsx(Draggable, { disabled: isModalDisabled, axis: "both", nodeRef: draggableRef, children: jsxs("div", { className: custModalProps.classNameModal + " cwelltContainerModal", ref: draggableRef, style: widthModalDef !== "40em" ? modalStyle.widthCustomStyle : modalStyle.widthDefStyle, children: [jsxs("div", { className: "cwelltModalHeader", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: [jsx("div", { className: "cwelltModalTitle", children: custModalProps.titleModal }), jsx("button", { className: "cwelltBtnCloseModal", onClick: custModalProps.onCloseModal, children: jsx("span", { className: "cwelltCloseIcon" }) })] }), jsx("div", { className: "cwelltModalBody", children: jsx("div", { className: "cwelltContainerModalBody", style: { position: "relative" }, children: custModalProps.children }) }), isHide === false ? (jsx("footer", { className: "legacy-modal-footer", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: custModalProps.onSaveModal, form: custModalProps.formSaveModal, hidden: custModalProps.HideBtnModal, type: custModalProps.HtmlSubmitModal }) })) : (jsx("div", { style: { display: "none" } }))] }) })] })) }));
|
|
1206
1286
|
}
|
|
1207
1287
|
|
|
1208
|
-
var styles$
|
|
1288
|
+
var styles$t = {"overlayPositioned":"CwConfirmationPopup-module__overlayPositioned__11qYB","popup":"CwConfirmationPopup-module__popup__ahPjM","message":"CwConfirmationPopup-module__message__MnNL4","buttons":"CwConfirmationPopup-module__buttons__fGYYE","button":"CwConfirmationPopup-module__button__ugYQE","confirmButton":"CwConfirmationPopup-module__confirmButton__rTP4S","cancelButton":"CwConfirmationPopup-module__cancelButton__Ry694"};
|
|
1209
1289
|
|
|
1210
1290
|
function CwConfirmationPopup(props) {
|
|
1211
1291
|
const { isOpen, onConfirm, onCancel, message = "Are you sure you want to proceed?", confirmText = "Confirm", cancelText = "Cancel", placement = 'bottom', children } = props;
|
|
@@ -1269,15 +1349,15 @@ function CwConfirmationPopup(props) {
|
|
|
1269
1349
|
onCancel();
|
|
1270
1350
|
}
|
|
1271
1351
|
};
|
|
1272
|
-
return (jsxs(Fragment, { children: [renderChildren(), isOpen && (jsx("div", { className: styles$
|
|
1352
|
+
return (jsxs(Fragment, { children: [renderChildren(), isOpen && (jsx("div", { className: styles$t.overlayPositioned, onClick: handleOverlayClick, children: jsxs("div", { ref: popupRef, className: styles$t.popup, style: {
|
|
1273
1353
|
position: 'absolute',
|
|
1274
1354
|
top: `${position.top}px`,
|
|
1275
1355
|
left: `${position.left}px`,
|
|
1276
1356
|
transform: 'none'
|
|
1277
|
-
}, children: [jsx("p", { className: styles$
|
|
1357
|
+
}, children: [jsx("p", { className: styles$t.message, children: message }), jsxs("div", { className: styles$t.buttons, children: [jsx("button", { className: `${styles$t.button} ${styles$t.confirmButton}`, onClick: onConfirm, children: confirmText }), jsx("button", { className: `${styles$t.button} ${styles$t.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
|
|
1278
1358
|
}
|
|
1279
1359
|
|
|
1280
|
-
var styles$
|
|
1360
|
+
var styles$s = {"cw-dialog-main":"cw-dialog-module__cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module__cw-dialog-button-close__9GRd8"};
|
|
1281
1361
|
|
|
1282
1362
|
// Helper function to parse size values
|
|
1283
1363
|
const parseSize = (size) => {
|
|
@@ -1550,7 +1630,7 @@ const CwDialog = props => {
|
|
|
1550
1630
|
}
|
|
1551
1631
|
}
|
|
1552
1632
|
}, [open]);
|
|
1553
|
-
const header = useMemo(() => (jsxs("header", { onMouseDown: handleMouseDown, children: [jsx("span", { children: headline }), customHeader || (jsx("button", { className: styles$
|
|
1633
|
+
const header = useMemo(() => (jsxs("header", { onMouseDown: handleMouseDown, children: [jsx("span", { children: headline }), customHeader || (jsx("button", { className: styles$s["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
|
|
1554
1634
|
const content = useMemo(() => (jsx("section", { children: children })), [children]);
|
|
1555
1635
|
const footer = useMemo(() => (jsx("footer", { children: customFooter || (jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: onSave, tooltipPosition: "top", disabled: disableSave, "data-testid": "cw-dialog-save" })) })), [customFooter, onSave, disableSave]);
|
|
1556
1636
|
const resizeHandles = useMemo(() => size.autoHeight
|
|
@@ -1577,7 +1657,7 @@ const CwDialog = props => {
|
|
|
1577
1657
|
: `${convertFromPx(size.height, size.heightUnit)}${size.heightUnit}`;
|
|
1578
1658
|
return { displayWidth, displayHeight };
|
|
1579
1659
|
}, [size.width, size.height, size.widthUnit, size.heightUnit, size.autoHeight]);
|
|
1580
|
-
const dialogContent = (jsx("div", { "data-has-scrim": hasScrim, className: styles$
|
|
1660
|
+
const dialogContent = (jsx("div", { "data-has-scrim": hasScrim, className: styles$s["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxs("dialog", { ...domProps, ref: dialogRef, style: {
|
|
1581
1661
|
left: `${position.x}px`,
|
|
1582
1662
|
top: `${position.y}px`,
|
|
1583
1663
|
width: displayDimensions.displayWidth,
|
|
@@ -1738,7 +1818,7 @@ function CwAlign(props) {
|
|
|
1738
1818
|
}, children: props.children }));
|
|
1739
1819
|
}
|
|
1740
1820
|
|
|
1741
|
-
var styles$
|
|
1821
|
+
var styles$r = {"card":"cw-card-module__card__HJUT0","clickable":"cw-card-module__clickable__Y-V3X","disabled":"cw-card-module__disabled__0wHh1","content":"cw-card-module__content__ma9qy","headerContent":"cw-card-module__headerContent__x4Jfl","footerTags":"cw-card-module__footerTags__80sSW"};
|
|
1742
1822
|
|
|
1743
1823
|
/**
|
|
1744
1824
|
* CwCard - A simple card component for displaying content in a contained format
|
|
@@ -1758,17 +1838,16 @@ var styles$q = {"card":"cw-card-module__card__HJUT0","clickable":"cw-card-module
|
|
|
1758
1838
|
* <p>This is the main content of the card.</p>
|
|
1759
1839
|
* </CwCard>
|
|
1760
1840
|
**/
|
|
1761
|
-
const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, onEdit, onDelete, extraActions, className = '', clickable = false, onClick, isLoading = false, disabled = false, style, chips = [], variant = "border", direction = "column", layout, }) => {
|
|
1841
|
+
const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, onEdit, onDelete, extraActions, className = '', clickable = false, onClick, isLoading = false, skeletonLines = 3, disabled = false, style, chips = [], variant = "border", direction = "column", layout, }) => {
|
|
1762
1842
|
const resolvedDirection = layout?.direction ?? direction;
|
|
1763
1843
|
const resolvedAlign = layout?.align ?? (alignment === 'left' ? 'start' : 'center');
|
|
1764
1844
|
// Construct class names using CSS modules
|
|
1765
1845
|
const cardClassNames = [
|
|
1766
1846
|
'cw-card',
|
|
1767
|
-
styles$
|
|
1847
|
+
styles$r.card,
|
|
1768
1848
|
className,
|
|
1769
|
-
clickable ? styles$
|
|
1770
|
-
disabled ? styles$
|
|
1771
|
-
isLoading ? styles$q.loading : '',
|
|
1849
|
+
clickable ? styles$r.clickable : '',
|
|
1850
|
+
disabled ? styles$r.disabled : '',
|
|
1772
1851
|
].filter(Boolean).join(' ');
|
|
1773
1852
|
// Handle click event when card is clickable
|
|
1774
1853
|
const handleClick = () => {
|
|
@@ -1784,16 +1863,17 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
|
|
|
1784
1863
|
const hasChips = chips.length > 0;
|
|
1785
1864
|
// Determine if footer should be rendered
|
|
1786
1865
|
const hasFooter = hasChips || footer || (hasActions && resolvedDirection === "row");
|
|
1787
|
-
// Actions component to reuse
|
|
1788
|
-
|
|
1789
|
-
|
|
1866
|
+
// Actions component to reuse. While loading, each provided action renders a circular
|
|
1867
|
+
// ghost sized to the CwButton icon footprint (2rem) - no interactive buttons.
|
|
1868
|
+
const ActionsComponent = hasActions && !disabled ? (jsx("div", { className: styles$r.actions, children: isLoading ? (jsxs(Fragment, { children: [extraActions && jsx(CwSkeleton, { variant: "circle", height: "2rem" }), onEdit && jsx(CwSkeleton, { variant: "circle", height: "2rem" }), onDelete && jsx(CwSkeleton, { variant: "circle", height: "2rem" })] })) : (jsxs(Fragment, { children: [extraActions ?? null, onEdit && jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) })) : null;
|
|
1869
|
+
return (jsxs("div", { ...(id && { id }), className: cardClassNames, ...(style && { style }), ...(clickable && !isLoading && {
|
|
1790
1870
|
role: 'button',
|
|
1791
1871
|
tabIndex: 0,
|
|
1792
1872
|
onClick: handleClick,
|
|
1793
|
-
}), "data-variant": variant, "data-direction": resolvedDirection, children: [hasHeader && (jsxs("header", { children: [(title || subtitle) && (jsxs("div", { className: styles$
|
|
1873
|
+
}), "data-variant": variant, "data-direction": resolvedDirection, "aria-busy": isLoading || undefined, children: [isLoading ? (jsxs("header", { children: [jsx("div", { className: styles$r.headerContent, "data-align": resolvedAlign, children: jsx(CwSkeleton, { width: "8rem", height: "1.5em" }) }), resolvedDirection === "column" && ActionsComponent] })) : (hasHeader && (jsxs("header", { children: [(title || subtitle) && (jsxs("div", { className: styles$r.headerContent, "data-align": resolvedAlign, children: [title && jsx("h5", { children: title }), subtitle && jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] }))), jsx("div", { className: styles$r.content, children: isLoading ? jsx(CwSkeleton, { count: normalizeSkeletonCount(skeletonLines, 3) }) : children }), hasFooter && (isLoading ? (jsx("footer", { children: jsx("div", { className: styles$r.footerTags, children: jsx(CwSkeleton, { variant: "rect", width: "4rem", height: "1.5em", radius: "1rem" }) }) })) : (jsxs("footer", { children: [hasChips && (jsx("div", { className: styles$r.footerTags, children: chips.map((chip, index) => (jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$r.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsx("div", { className: styles$r.footerContent, children: footer }))] }))), resolvedDirection === "row" && ActionsComponent] }));
|
|
1794
1874
|
};
|
|
1795
1875
|
|
|
1796
|
-
var styles$
|
|
1876
|
+
var styles$q = {"cardContainer":"cw-card-list-module__cardContainer__l3YEh","pagination":"cw-card-list-module__pagination__5Ay78","pageInfo":"cw-card-list-module__pageInfo__uiMel","emptyState":"cw-card-list-module__emptyState__RlqiS"};
|
|
1797
1877
|
|
|
1798
1878
|
/**
|
|
1799
1879
|
* Option to display in the CwSelect
|
|
@@ -1851,7 +1931,7 @@ function CwSelect(props) {
|
|
|
1851
1931
|
: selectProps.onChange, children: [placeholder && jsx(CwOption, { value: "", children: placeholder }), children] }), buttonProps && jsx(CwButton, { ...buttonProps })] })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
|
|
1852
1932
|
}
|
|
1853
1933
|
|
|
1854
|
-
function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', defaultCardWidth = 320, cardGap = 16, isLoading = false, emptyState, sortOptions = [], defaultSortKey, keyExtractor, ...htmlProps }) {
|
|
1934
|
+
function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', defaultCardWidth = 320, cardGap = 16, isLoading = false, skeletonCards = 6, emptyState, sortOptions = [], defaultSortKey, keyExtractor, ...htmlProps }) {
|
|
1855
1935
|
const [currentPage, setCurrentPage] = useState(1);
|
|
1856
1936
|
const [sortKey, setSortKey] = useState(defaultSortKey || sortOptions[0]?.key || '');
|
|
1857
1937
|
const [sortDirection, setSortDirection] = useState('asc');
|
|
@@ -1888,10 +1968,10 @@ function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', default
|
|
|
1888
1968
|
icon: sortDirection === 'asc' ? 'arrow-up' : 'arrow-down',
|
|
1889
1969
|
onClick: () => setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'),
|
|
1890
1970
|
title: `Sort ${sortDirection === 'asc' ? 'descending' : 'ascending'}`,
|
|
1891
|
-
}, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsx("div", { className: styles$
|
|
1971
|
+
}, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsx("div", { className: `${styles$q.cardContainer}`, "data-layout": layout, style: gridStyle, "aria-busy": true, children: Array.from({ length: normalizeSkeletonCount(skeletonCards, 6) }, (_, index) => (jsx(CwCard, { isLoading: true, children: null }, `skeleton_${index}`))) })) : sortedItems.length === 0 ? (jsx("div", { className: styles$q.emptyState, children: emptyState || jsx("p", { children: "No items to display" }) })) : (jsxs(Fragment, { children: [jsx("div", { className: `${styles$q.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsx(React__default.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxs("div", { className: styles$q.pagination, children: [jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxs("span", { className: styles$q.pageInfo, children: [currentPage, " / ", totalPages] }), jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
|
|
1892
1972
|
}
|
|
1893
1973
|
|
|
1894
|
-
var styles$
|
|
1974
|
+
var styles$p = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
|
|
1895
1975
|
|
|
1896
1976
|
/**
|
|
1897
1977
|
*
|
|
@@ -1908,7 +1988,22 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
|
|
|
1908
1988
|
setVisible_accordionBody(!isVisible_accordionBody);
|
|
1909
1989
|
};
|
|
1910
1990
|
// #endregion
|
|
1911
|
-
return (jsxs("div", { className: styles$
|
|
1991
|
+
return (jsxs("div", { className: styles$p["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxs("header", { onClick: () => showAccordionBody(), children: [jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsx("button", { className: "cw-button-icon" })] }), jsx("div", { className: styles$p["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
/*
|
|
1995
|
+
* Internal helper for table loading ghosts (CwTable, CwSortableTable).
|
|
1996
|
+
* Not exported from the library barrel - not a public API.
|
|
1997
|
+
*/
|
|
1998
|
+
const SKELETON_CELL_WIDTHS = ['85%', '60%', '95%', '70%', '80%', '65%'];
|
|
1999
|
+
/**
|
|
2000
|
+
* Deterministic width for a table ghost cell so skeleton rows look like real,
|
|
2001
|
+
* unevenly sized content. Derived purely from indices - stable across re-renders
|
|
2002
|
+
* (no reshuffling) - and offset by the column count so the pattern does not
|
|
2003
|
+
* repeat identically per row or per column.
|
|
2004
|
+
*/
|
|
2005
|
+
function getSkeletonCellWidth(rowIndex, columnIndex, columnCount) {
|
|
2006
|
+
return SKELETON_CELL_WIDTHS[(rowIndex * columnCount + columnIndex) % SKELETON_CELL_WIDTHS.length];
|
|
1912
2007
|
}
|
|
1913
2008
|
|
|
1914
2009
|
/**
|
|
@@ -1980,7 +2075,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
|
|
|
1980
2075
|
*
|
|
1981
2076
|
* @returns React component
|
|
1982
2077
|
*/
|
|
1983
|
-
function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, testId, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, pageLabel = "page", rowSelection }) {
|
|
2078
|
+
function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, testId, textNoData = "No data available at the moment", rowKey = "key", loading = false, skeletonRows = 5, scrollHeight, stickyHeader = false, pageLabel = "page", rowSelection }) {
|
|
1984
2079
|
const [currentPage, setCurrentPage] = useState(1);
|
|
1985
2080
|
const [expandedRowKey, setExpandedRowKey] = useState(null);
|
|
1986
2081
|
const [sortConfig, setSortConfig] = useState({
|
|
@@ -2118,7 +2213,9 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2118
2213
|
};
|
|
2119
2214
|
const renderTableBody = () => {
|
|
2120
2215
|
if (loading) {
|
|
2121
|
-
|
|
2216
|
+
// Ghost rows: rendered outside the data/selection/expand code paths, so they
|
|
2217
|
+
// cannot trigger row click, selection or expansion.
|
|
2218
|
+
return Array.from({ length: normalizeSkeletonCount(skeletonRows, 5) }, (_, rowIndex) => (jsxs("tr", { children: [expandedRowRender && jsx("td", { className: "cw-table-col-action" }), columns.map((col, columnIndex) => (jsx("td", { className: col.className ?? "", children: jsx(CwSkeleton, { variant: "text", width: getSkeletonCellWidth(rowIndex, columnIndex, columns.length) }) }, col.key)))] }, `skeleton_${rowIndex}`)));
|
|
2122
2219
|
}
|
|
2123
2220
|
if (!paginatedData || paginatedData.length === 0) {
|
|
2124
2221
|
return (jsx("tr", { children: jsx("td", { colSpan: getColSpan(), className: "cw-table-cell-empty", style: { textAlign: "center" }, children: textNoData }) }));
|
|
@@ -2140,7 +2237,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2140
2237
|
: "cwi-chevron-right"}` }) })), columns.map(col => (jsx("td", { className: col.className ?? "", children: col.render ? col.render(item) : col.dataIndex ? String(item[col.dataIndex] ?? "") : "" }, `${itemKey}_${col.key}`)))] }), expandedRowRender && expandedRowKey === itemKey && (jsx("tr", { className: "cw-table-row-expanded", children: jsx("td", { colSpan: getColSpan(), children: expandedRowRender(item) }) }))] }, String(itemKey)));
|
|
2141
2238
|
});
|
|
2142
2239
|
};
|
|
2143
|
-
return (jsxs("div", { id: id, "data-testid": testId, className: `cw-table-container${stickyHeader || scrollHeight ? " cw-table-scroll" : ""} ${classNameContainer ?? ""}`, style: { ...(scrollHeight ? { "--table-height": typeof scrollHeight === "number" ? `${scrollHeight}px` : scrollHeight } : {}), ...style }, children: [jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [expandedRowRender && jsx("th", {}), columns.map(col => (jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${sortConfig.key === col.dataIndex
|
|
2240
|
+
return (jsxs("div", { id: id, "data-testid": testId, className: `cw-table-container${stickyHeader || scrollHeight ? " cw-table-scroll" : ""} ${classNameContainer ?? ""}`, style: { ...(scrollHeight ? { "--table-height": typeof scrollHeight === "number" ? `${scrollHeight}px` : scrollHeight } : {}), ...style }, "aria-busy": loading || undefined, children: [jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [expandedRowRender && jsx("th", {}), columns.map(col => (jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${sortConfig.key === col.dataIndex
|
|
2144
2241
|
? sortConfig.direction
|
|
2145
2242
|
: ""}`.trim(), style: {
|
|
2146
2243
|
cursor: col.sortable ? "pointer" : "default",
|
|
@@ -2166,7 +2263,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2166
2263
|
}, min: 1, max: totalPages }), jsx("span", { children: "/" }), jsx("span", { children: totalPages }), jsx(CwButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
|
|
2167
2264
|
}
|
|
2168
2265
|
|
|
2169
|
-
var styles$
|
|
2266
|
+
var styles$o = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
|
|
2170
2267
|
|
|
2171
2268
|
/**
|
|
2172
2269
|
* Hook that provides state management for CwSortableTable.
|
|
@@ -2229,9 +2326,14 @@ function useSortableTable(initialItems) {
|
|
|
2229
2326
|
}
|
|
2230
2327
|
|
|
2231
2328
|
// ─── Drop indicator row ───────────────────────────────────────────────────────
|
|
2232
|
-
const DropIndicatorRow = ({ colSpan }) => (jsx("tr", { className: styles$
|
|
2329
|
+
const DropIndicatorRow = ({ colSpan }) => (jsx("tr", { className: styles$o.dropIndicator, "aria-hidden": true, children: jsx("td", { colSpan: colSpan, children: jsx("div", {}) }) }));
|
|
2233
2330
|
// ─── Loading skeleton ─────────────────────────────────────────────────────────
|
|
2234
|
-
|
|
2331
|
+
// Plain td cells (no local class): the ghost cells get the same global cw-table
|
|
2332
|
+
// padding as real body cells, so row heights match the loaded rows exactly.
|
|
2333
|
+
// One cell per real column, so column classNames/widths apply to the ghost too.
|
|
2334
|
+
function LoadingRows({ columns, showHandle, skeletonRows }) {
|
|
2335
|
+
return (jsx(Fragment, { children: Array.from({ length: skeletonRows }).map((_, rowIndex) => (jsxs("tr", { children: [showHandle && jsx("td", { className: "cw-table-col-action" }), columns.map((col, columnIndex) => (jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: jsx(CwSkeleton, { variant: "text", width: getSkeletonCellWidth(rowIndex, columnIndex, columns.length) }) }, col.key)))] }, rowIndex))) }));
|
|
2336
|
+
}
|
|
2235
2337
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
2236
2338
|
/**
|
|
2237
2339
|
* CwSortableTable
|
|
@@ -2248,7 +2350,7 @@ const LoadingRows = ({ colSpan }) => (jsx(Fragment, { children: Array.from({ len
|
|
|
2248
2350
|
* - Reorder is calculated in onDragEnd using lastValidDropIndex
|
|
2249
2351
|
* - draggedItem is tracked in state, not via dataTransfer
|
|
2250
2352
|
*/
|
|
2251
|
-
function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = false, textNoData = "No data available", className, tableClassName, maxHeight, showHandle = true, style, saveLabel = "Save order", discardLabel = "Discard", }) {
|
|
2353
|
+
function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = false, skeletonRows = 5, textNoData = "No data available", className, tableClassName, maxHeight, showHandle = true, style, saveLabel = "Save order", discardLabel = "Discard", }) {
|
|
2252
2354
|
const { items, hasChanges, handleReorder, handleSave, handleDiscard, } = useSortableTable(data);
|
|
2253
2355
|
// Drag state lives in the component, same as CwSortableList
|
|
2254
2356
|
const [draggedItem, setDraggedItem] = useState(null);
|
|
@@ -2267,11 +2369,15 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2267
2369
|
setLastValidDropIndex(null);
|
|
2268
2370
|
};
|
|
2269
2371
|
const handleDragStart = (e, item) => {
|
|
2372
|
+
if (loading)
|
|
2373
|
+
return;
|
|
2270
2374
|
setDraggedItem(item);
|
|
2271
2375
|
setLastValidDropIndex(null);
|
|
2272
2376
|
e.dataTransfer.effectAllowed = "move";
|
|
2273
2377
|
};
|
|
2274
2378
|
const handleDragOver = (e, index) => {
|
|
2379
|
+
if (loading)
|
|
2380
|
+
return;
|
|
2275
2381
|
e.preventDefault();
|
|
2276
2382
|
if (!draggedItem)
|
|
2277
2383
|
return;
|
|
@@ -2284,6 +2390,11 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2284
2390
|
}
|
|
2285
2391
|
};
|
|
2286
2392
|
const handleDragEnd = () => {
|
|
2393
|
+
// Never persist a reorder computed against stale/ghost data while loading.
|
|
2394
|
+
if (loading) {
|
|
2395
|
+
cleanupDragState();
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2287
2398
|
if (draggedItem && lastValidDropIndex !== null) {
|
|
2288
2399
|
const dragIndex = items.findIndex(item => item[rowKey] === draggedItem[rowKey]);
|
|
2289
2400
|
if (dragIndex !== lastValidDropIndex && dragIndex !== lastValidDropIndex - 1) {
|
|
@@ -2310,7 +2421,7 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2310
2421
|
};
|
|
2311
2422
|
const renderBody = () => {
|
|
2312
2423
|
if (loading) {
|
|
2313
|
-
return jsx(LoadingRows, {
|
|
2424
|
+
return jsx(LoadingRows, { columns: columns, showHandle: showHandle, skeletonRows: normalizeSkeletonCount(skeletonRows, 5) });
|
|
2314
2425
|
}
|
|
2315
2426
|
if (!items || items.length === 0) {
|
|
2316
2427
|
return (jsx("tr", { children: jsx("td", { colSpan: totalCols, className: "cw-table-cell-empty", style: { textAlign: "center" }, children: textNoData }) }));
|
|
@@ -2318,11 +2429,11 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2318
2429
|
return items.map((item, index) => {
|
|
2319
2430
|
const key = item[rowKey];
|
|
2320
2431
|
const isDragging = draggedItem?.[rowKey] === key;
|
|
2321
|
-
return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && (jsx(DropIndicatorRow, { colSpan: totalCols })), jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$
|
|
2432
|
+
return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && (jsx(DropIndicatorRow, { colSpan: totalCols })), jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$o.dragging : "", children: [showHandle && (jsx("td", { className: "cw-table-col-action", children: jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: renderCell(item, col) }, `${String(key)}_${col.key}`)))] }), index === items.length - 1 && dropIndicatorIndex === items.length && (jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
|
|
2322
2433
|
});
|
|
2323
2434
|
};
|
|
2324
2435
|
// ── Render ──────────────────────────────────────────────────────────────
|
|
2325
|
-
return (jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [showHandle && jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxs("footer", { className: styles$
|
|
2436
|
+
return (jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, "aria-busy": loading || undefined, children: [jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [showHandle && jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsx("tbody", { children: renderBody() })] }), !loading && hasChanges && (jsxs("footer", { className: styles$o.saveBar, children: [jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
|
|
2326
2437
|
}
|
|
2327
2438
|
|
|
2328
2439
|
/**
|
|
@@ -2378,7 +2489,7 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
|
|
|
2378
2489
|
*
|
|
2379
2490
|
* @returns React component
|
|
2380
2491
|
*/
|
|
2381
|
-
function CwTableServerSide({ columns, data, totalItems, pagination = false, pageSizeOptions = [5, 10, 20, 50], pageLabel = "page", expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, testId, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection, onChange, serverState, }) {
|
|
2492
|
+
function CwTableServerSide({ columns, data, totalItems, pagination = false, pageSizeOptions = [5, 10, 20, 50], pageLabel = "page", expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, testId, textNoData = "No data available at the moment", rowKey = "key", loading = false, skeletonRows = 5, scrollHeight, stickyHeader = false, rowSelection, onChange, serverState, }) {
|
|
2382
2493
|
const [internalState, setInternalState] = useState({
|
|
2383
2494
|
page: 1,
|
|
2384
2495
|
pageSize: pageSizeOptions[0],
|
|
@@ -2479,7 +2590,9 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
|
|
|
2479
2590
|
};
|
|
2480
2591
|
const renderTableBody = () => {
|
|
2481
2592
|
if (loading) {
|
|
2482
|
-
|
|
2593
|
+
// Ghost rows: rendered outside the data/selection/expand code paths, so they
|
|
2594
|
+
// cannot trigger row click, selection or expansion.
|
|
2595
|
+
return Array.from({ length: normalizeSkeletonCount(skeletonRows, 5) }, (_, rowIndex) => (jsxs("tr", { children: [expandedRowRender && jsx("td", { className: "cw-table-col-action" }), columns.map((col, columnIndex) => (jsx("td", { className: col.className ?? "", children: jsx(CwSkeleton, { variant: "text", width: getSkeletonCellWidth(rowIndex, columnIndex, columns.length) }) }, col.key)))] }, `skeleton_${rowIndex}`)));
|
|
2483
2596
|
}
|
|
2484
2597
|
if (!data || data.length === 0) {
|
|
2485
2598
|
return (jsx("tr", { children: jsx("td", { colSpan: getColSpan(), className: "cw-table-cell-empty", style: { textAlign: "center" }, children: textNoData }) }));
|
|
@@ -2497,7 +2610,7 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
|
|
|
2497
2610
|
}, children: [expandedRowRender && (jsx("td", { className: "cw-table-col-action cw-table-col-expand", children: jsx("button", { onClick: () => handleRowExpand(item), className: `cw-button-icon ${expandedRowKey === itemKey ? "cwi-chevron-down" : "cwi-chevron-right"}` }) })), columns.map((col) => (jsx("td", { className: col.className ?? "", children: col.render ? col.render(item) : col.dataIndex ? String(item[col.dataIndex] ?? "") : "" }, `${itemKey}_${col.key}`)))] }), expandedRowRender && expandedRowKey === itemKey && (jsx("tr", { className: "cw-table-row-expanded", children: jsx("td", { colSpan: getColSpan(), children: expandedRowRender(item) }) }))] }, String(itemKey)));
|
|
2498
2611
|
});
|
|
2499
2612
|
};
|
|
2500
|
-
return (jsxs("div", { id: id, "data-testid": testId, className: `cw-table-container${stickyHeader || scrollHeight ? " cw-table-scroll" : ""} ${classNameContainer ?? ""}`, style: { ...(scrollHeight ? { "--table-height": typeof scrollHeight === "number" ? `${scrollHeight}px` : scrollHeight } : {}), ...style }, children: [jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [expandedRowRender && jsx("th", {}), columns.map((col) => (jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${state.sortKey === col.dataIndex ? state.sortDirection : ""}`.trim(), style: {
|
|
2613
|
+
return (jsxs("div", { id: id, "data-testid": testId, className: `cw-table-container${stickyHeader || scrollHeight ? " cw-table-scroll" : ""} ${classNameContainer ?? ""}`, style: { ...(scrollHeight ? { "--table-height": typeof scrollHeight === "number" ? `${scrollHeight}px` : scrollHeight } : {}), ...style }, "aria-busy": loading || undefined, children: [jsxs("table", { className: `cw-table ${className ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [expandedRowRender && jsx("th", {}), columns.map((col) => (jsxs("th", { onClick: () => col.sortable && col.dataIndex && handleSort(col.dataIndex), className: `${col.className ?? ""} ${state.sortKey === col.dataIndex ? state.sortDirection : ""}`.trim(), style: {
|
|
2501
2614
|
cursor: col.sortable ? "pointer" : "default",
|
|
2502
2615
|
userSelect: "none",
|
|
2503
2616
|
width: columnWidths[col.key] ?? col.width,
|
|
@@ -2521,7 +2634,7 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
|
|
|
2521
2634
|
}, min: 1, max: totalPages }), jsx("span", { children: "/" }), jsx("span", { children: totalPages }), jsx(CwButton, { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
|
|
2522
2635
|
}
|
|
2523
2636
|
|
|
2524
|
-
var styles$
|
|
2637
|
+
var styles$n = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","badge":"cw-tabs-module__badge__AmVxW","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
|
|
2525
2638
|
|
|
2526
2639
|
const TabIcon = ({ icon }) => {
|
|
2527
2640
|
if (!icon)
|
|
@@ -2571,7 +2684,7 @@ function CwTabs(CwTabsProps) {
|
|
|
2571
2684
|
const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
|
|
2572
2685
|
? { minWidth: CwTabsProps.tabsListWidth }
|
|
2573
2686
|
: undefined;
|
|
2574
|
-
return (jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$
|
|
2687
|
+
return (jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$n['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsx("span", { className: styles$n['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsx("div", { className: styles$n['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, style: CwTabsProps.contentHeight ? { '--tabs-height': CwTabsProps.contentHeight } : undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
|
|
2575
2688
|
}
|
|
2576
2689
|
|
|
2577
2690
|
/**
|
|
@@ -2598,9 +2711,17 @@ const CwExpandable = ({ briefing, onToggle, onOpen, onClose, children, ...detail
|
|
|
2598
2711
|
return (jsxs("details", { ref: myRef, ...detailsProps, className: "cw-expandable", children: [jsx("summary", { children: briefing }), children && jsx("section", { children: children })] }));
|
|
2599
2712
|
};
|
|
2600
2713
|
|
|
2601
|
-
var styles$
|
|
2714
|
+
var styles$m = {"cw-master-detail":"cw-master-detail-module__cw-master-detail__O8-FA","resizer":"cw-master-detail-module__resizer__hvGhL","detail":"cw-master-detail-module__detail__BG4Dm","skeletonRow":"cw-master-detail-module__skeletonRow__6BUgt","detailSkeleton":"cw-master-detail-module__detailSkeleton__GcDS4","detail-empty":"cw-master-detail-module__detail-empty__KFScK"};
|
|
2602
2715
|
|
|
2603
|
-
|
|
2716
|
+
/*
|
|
2717
|
+
* Fixed rem widths for the ghosts: the master rows and detail panel size their
|
|
2718
|
+
* content freely, so a percentage-width skeleton would resolve to 100% of ~0 and
|
|
2719
|
+
* collapse to nothing. Fixed widths render regardless of layout. Cycled so rows do
|
|
2720
|
+
* not all look identical.
|
|
2721
|
+
*/
|
|
2722
|
+
const MASTER_TITLE_WIDTHS = ['9rem', '11rem', '8rem', '10rem'];
|
|
2723
|
+
const MASTER_SUBTITLE_WIDTH = '5rem';
|
|
2724
|
+
const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, detailContent, emptyDetail, searchPlaceholder = 'Search...', onSearch, masterHeader, masterFooter, masterWidth: initialWidth = 320, minMasterWidth = 240, maxMasterWidth = 500, resizable = true, showSearch = true, loading = false, skeletonRows = 5, }) => {
|
|
2604
2725
|
const [masterWidth, setMasterWidth] = useState(initialWidth);
|
|
2605
2726
|
const [isResizing, setIsResizing] = useState(false);
|
|
2606
2727
|
const containerRef = useRef(null);
|
|
@@ -2634,12 +2755,22 @@ const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, de
|
|
|
2634
2755
|
document.body.style.userSelect = '';
|
|
2635
2756
|
};
|
|
2636
2757
|
}, [isResizing, minMasterWidth, maxMasterWidth]);
|
|
2637
|
-
const rootClassName = [styles$
|
|
2638
|
-
return (jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsx("search", { children: jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsx("header", { children: masterHeader })), jsx("ul", { children:
|
|
2758
|
+
const rootClassName = [styles$m['cw-master-detail'], className].filter(Boolean).join(' ');
|
|
2759
|
+
return (jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, "aria-busy": loading || undefined, children: [jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsx("search", { children: jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsx("header", { children: masterHeader })), jsx("ul", { children: loading
|
|
2760
|
+
? Array.from({ length: skeletonRows }, (_unused, rowIndex) => (jsxs("li", { "aria-hidden": "true", children: [jsx(CwSkeleton, { variant: "circle", height: "2rem" }), jsxs("div", { className: styles$m.skeletonRow, children: [jsx(CwSkeleton, { variant: "text", width: MASTER_TITLE_WIDTHS[rowIndex % MASTER_TITLE_WIDTHS.length] }), jsx(CwSkeleton, { variant: "text", width: MASTER_SUBTITLE_WIDTH })] })] }, `skeleton_${rowIndex}`)))
|
|
2761
|
+
: items.map((item) => (jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsx("footer", { children: masterFooter }))] }), resizable && (jsx("div", { className: styles$m.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsx("section", { className: styles$m.detail, children: loading ? (jsxs("div", { className: styles$m.detailSkeleton, "aria-hidden": "true", children: [jsx(CwSkeleton, { variant: "text", width: "14rem", height: "1.5em" }), jsx(CwSkeleton, { variant: "text", width: "22rem" }), jsx(CwSkeleton, { variant: "text", width: "18rem" }), jsx(CwSkeleton, { variant: "text", width: "20rem" })] })) : selectedKey && detailContent
|
|
2639
2762
|
? detailContent
|
|
2640
|
-
: (jsx("div", { className: styles$
|
|
2763
|
+
: (jsx("div", { className: styles$m['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
|
|
2641
2764
|
};
|
|
2642
2765
|
|
|
2766
|
+
/*
|
|
2767
|
+
* Fixed rem widths (not percentages): dt and dd size to their content in the list
|
|
2768
|
+
* item, so a percentage-width skeleton would resolve to 100% of ~0 and collapse to
|
|
2769
|
+
* nothing. Fixed widths are visible in both row (dt beside dd) and column (dt above
|
|
2770
|
+
* dd) item layouts. Cycled by row so keys and values do not all look identical.
|
|
2771
|
+
*/
|
|
2772
|
+
const SKELETON_KEY_WIDTHS = ["5rem", "6.5rem", "4.5rem", "6rem"];
|
|
2773
|
+
const SKELETON_VALUE_WIDTHS = ["8rem", "6rem", "9rem", "7rem"];
|
|
2643
2774
|
/**
|
|
2644
2775
|
* A component for displaying key-value pairs in a definition list format
|
|
2645
2776
|
* Used for read-only display of structured data
|
|
@@ -2653,16 +2784,23 @@ const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, de
|
|
|
2653
2784
|
* emptyValue="N/A"
|
|
2654
2785
|
* />
|
|
2655
2786
|
*/
|
|
2656
|
-
const CwKeyValueList = ({ items, className = "", emptyValue = "-", direction = "row", groupLayout, itemLayout, ...htmlProps }) => {
|
|
2787
|
+
const CwKeyValueList = ({ items, className = "", emptyValue = "-", direction = "row", loading = false, skeletonRows = 4, groupLayout, itemLayout, ...htmlProps }) => {
|
|
2657
2788
|
const itemDirection = itemLayout?.direction ?? direction;
|
|
2658
|
-
|
|
2789
|
+
const renderItems = () => {
|
|
2790
|
+
if (loading) {
|
|
2791
|
+
// The whole list comes from one data load, so both key and value ghost.
|
|
2792
|
+
return Array.from({ length: skeletonRows }, (_unused, rowIndex) => (jsxs("div", { className: `cw-keyvalue-list-item cw-flex-${itemDirection}`, "data-align": itemLayout?.align, "data-justify": itemLayout?.justify, "data-gap": itemLayout?.gap, "aria-hidden": "true", children: [jsx("dt", { children: jsx(CwSkeleton, { variant: "text", width: SKELETON_KEY_WIDTHS[rowIndex % SKELETON_KEY_WIDTHS.length] }) }), jsx("dd", { children: jsx(CwSkeleton, { variant: "text", width: SKELETON_VALUE_WIDTHS[rowIndex % SKELETON_VALUE_WIDTHS.length] }) })] }, `skeleton_${rowIndex}`)));
|
|
2793
|
+
}
|
|
2794
|
+
return items.map(item => (jsxs("div", { className: `cw-keyvalue-list-item cw-flex-${itemDirection}`, "data-align": itemLayout?.align, "data-justify": itemLayout?.justify, "data-gap": itemLayout?.gap, children: [jsx("dt", { children: item.label }), jsx("dd", { children: item.value !== undefined && item.value !== null && item.value !== ""
|
|
2659
2795
|
? (React__default.isValidElement(item.value)
|
|
2660
2796
|
? item.value
|
|
2661
2797
|
: `${item.value}${item.suffix ? ` ${item.suffix}` : ''}`)
|
|
2662
|
-
: emptyValue })] }, item.key)))
|
|
2798
|
+
: emptyValue })] }, item.key)));
|
|
2799
|
+
};
|
|
2800
|
+
return (jsx("dl", { className: `cw-keyvalue-list ${className}`, "data-direction": groupLayout?.direction, "data-align": groupLayout?.align, "data-justify": groupLayout?.justify, "data-gap": groupLayout?.gap, "aria-busy": loading || undefined, ...htmlProps, children: renderItems() }));
|
|
2663
2801
|
};
|
|
2664
2802
|
|
|
2665
|
-
var styles$
|
|
2803
|
+
var styles$l = {"sortableList":"cw-sortable-list-module__sortableList__PyLO-","sortableItem":"cw-sortable-list-module__sortableItem__FAnn2","readOnly":"cw-sortable-list-module__readOnly__r7GcH","dragging":"cw-sortable-list-module__dragging__MD715","moved":"cw-sortable-list-module__moved__sE6-N","expandedContent":"cw-sortable-list-module__expandedContent__Kocna","sortableHandle":"cw-sortable-list-module__sortableHandle__HvYBK","sortableContent":"cw-sortable-list-module__sortableContent__C6JhR","sortableTitle":"cw-sortable-list-module__sortableTitle__EgWXr","sortableExtraContent":"cw-sortable-list-module__sortableExtraContent__s4LSv","sortableActions":"cw-sortable-list-module__sortableActions__gwQOU","dropIndicator":"cw-sortable-list-module__dropIndicator__MNSF-","emptyMessage":"cw-sortable-list-module__emptyMessage__gMpaL"};
|
|
2666
2804
|
|
|
2667
2805
|
function CwSortableList({ items, onReorder, renderItem, className = '', movedItems = new Set(), emptyMessage = "No elements to show", readOnly = false, maxHeight = "300px", }) {
|
|
2668
2806
|
const [draggedItem, setDraggedItem] = useState(null);
|
|
@@ -2725,15 +2863,15 @@ function CwSortableList({ items, onReorder, renderItem, className = '', movedIte
|
|
|
2725
2863
|
}
|
|
2726
2864
|
};
|
|
2727
2865
|
if (items.length === 0) {
|
|
2728
|
-
return (jsx("div", { className: `${styles$
|
|
2866
|
+
return (jsx("div", { className: `${styles$l.sortableList} ${styles$l.emptyState} ${className}`, children: jsx("div", { className: styles$l.emptyMessage, children: emptyMessage }) }));
|
|
2729
2867
|
}
|
|
2730
|
-
return (jsx("div", { className: `${styles$
|
|
2868
|
+
return (jsx("div", { className: `${styles$l.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
|
|
2731
2869
|
const { title, extraContent, actions, showHandle = true, expandedContent } = renderItem(item);
|
|
2732
2870
|
const isDragging = draggedItem?.id === item.id;
|
|
2733
2871
|
const isMoved = movedItems.has(item.id);
|
|
2734
2872
|
const canExpand = Boolean(expandedContent);
|
|
2735
2873
|
const isExpanded = expandedItems.has(item.id);
|
|
2736
|
-
return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && jsx("div", { className: styles$
|
|
2874
|
+
return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && jsx("div", { className: styles$l.dropIndicator }), jsxs("div", { className: `${styles$l.sortableItem} ${isDragging ? styles$l.dragging : ''} ${isMoved ? styles$l.moved : ''} ${readOnly ? styles$l.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxs("header", { children: [canExpand ? (jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsx("div", { className: styles$l.sortableHandle, children: jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxs("div", { className: styles$l.sortableContent, children: [jsx("div", { className: styles$l.sortableTitle, children: title }), extraContent && jsx("div", { className: styles$l.sortableExtraContent, children: extraContent })] }), jsx("div", { className: styles$l.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsx("div", { className: styles$l.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsx("div", { className: styles$l.dropIndicator }))] }, item.id));
|
|
2737
2875
|
}) }));
|
|
2738
2876
|
}
|
|
2739
2877
|
|
|
@@ -2859,60 +2997,9 @@ const CwTableGrouped = props => {
|
|
|
2859
2997
|
group.rows.map((child, j) => (jsx("tr", { "data-row": true, "data-row-last-of-group": j == group.rows.length - 1, children: child.cells.map((cell, k) => (jsx("td", { children: cell.content }, k))) }, j)))] }, i))) }), jsx("tfoot", {})] }) }));
|
|
2860
2998
|
};
|
|
2861
2999
|
|
|
2862
|
-
|
|
2863
|
-
const [previewURL, setPreviewURL] = useState("");
|
|
2864
|
-
const [error, setError] = useState(null);
|
|
2865
|
-
const [_selectedFileName, setSelectedFileName] = useState("");
|
|
2866
|
-
const [_currentHexContent, setCurrentHexContent] = useState("");
|
|
2867
|
-
useEffect(() => {
|
|
2868
|
-
// If there is hexadecimal preview content, set the Preview URL
|
|
2869
|
-
if (fileUploadProps.file?.Bindata) {
|
|
2870
|
-
setPreviewURL(`data:image/png;base64,${fileUploadProps.file.Bindata}`);
|
|
2871
|
-
}
|
|
2872
|
-
}, [fileUploadProps.file?.Bindata]);
|
|
2873
|
-
const handleFileChange = (event) => {
|
|
2874
|
-
const file = event.target.files?.[0];
|
|
2875
|
-
setSelectedFileName(file?.name ?? "");
|
|
2876
|
-
if (file) {
|
|
2877
|
-
const allowedExts = fileUploadProps.accept.split(',').map(ext => ext.trim().replace('.', '').toLowerCase());
|
|
2878
|
-
const fileExt = file.name.split('.').pop()?.toLowerCase() ?? "";
|
|
2879
|
-
if (!allowedExts.includes(fileExt)) {
|
|
2880
|
-
setError(`Invalid file type. Only ${fileUploadProps.acceptString} files are allowed.`);
|
|
2881
|
-
setPreviewURL("");
|
|
2882
|
-
return;
|
|
2883
|
-
}
|
|
2884
|
-
setError(null);
|
|
2885
|
-
const reader = new FileReader();
|
|
2886
|
-
reader.onloadend = () => {
|
|
2887
|
-
if (typeof reader.result === "string") {
|
|
2888
|
-
const hexContent = arrayBufferToHex(reader.result);
|
|
2889
|
-
setCurrentHexContent(hexContent);
|
|
2890
|
-
setPreviewURL(reader.result);
|
|
2891
|
-
setCurrentHexContent(arrayBufferToHex(reader.result));
|
|
2892
|
-
// Call function to store hexadecimal content
|
|
2893
|
-
fileUploadProps.onSaveHexContent(arrayBufferToHex(reader.result));
|
|
2894
|
-
}
|
|
2895
|
-
};
|
|
2896
|
-
reader.readAsDataURL(file);
|
|
2897
|
-
}
|
|
2898
|
-
};
|
|
2899
|
-
// Function to convert the image buffer into hexadecimal content
|
|
2900
|
-
const arrayBufferToHex = (dataUrl) => {
|
|
2901
|
-
// Decodes the base64 of the URL data
|
|
2902
|
-
const base64 = dataUrl.split(",")[1];
|
|
2903
|
-
const binary = atob(base64);
|
|
2904
|
-
let hex = "";
|
|
2905
|
-
for (let i = 0; i < binary.length; i++) {
|
|
2906
|
-
hex += binary.charCodeAt(i).toString(16).padStart(2, "0");
|
|
2907
|
-
}
|
|
2908
|
-
return hex;
|
|
2909
|
-
};
|
|
2910
|
-
return (jsxs("div", { children: [jsxs("div", { className: "row", children: [jsx("input", { className: "cw-button", type: "file", accept: fileUploadProps.accept, readOnly: true, placeholder: "No file selected...", onChange: handleFileChange }), previewURL && (jsx("div", { className: "row", children: jsx("img", { src: previewURL, alt: "Preview", style: { maxWidth: "200px", maxHeight: "200px" } }) }))] }), error && jsx("div", { className: "row error", children: error }), jsx("div", { className: "row", children: jsxs("label", { children: ["Please note: File/image has to be in ", fileUploadProps.acceptString, " format", fileUploadProps.sizeString && `, ${fileUploadProps.sizeString}`] }) })] }));
|
|
2911
|
-
}
|
|
2912
|
-
|
|
2913
|
-
var styles$j = {"fileUploadContainer":"cw-file-upload-multiple-module__fileUploadContainer__liEc1","hiddenInput":"cw-file-upload-multiple-module__hiddenInput__TZBBI","uploadArea":"cw-file-upload-multiple-module__uploadArea__DdOhs","uploadAreaDisabled":"cw-file-upload-multiple-module__uploadAreaDisabled__VWeFX","uploadTitle":"cw-file-upload-multiple-module__uploadTitle__gjRk8","uploadSubtitle":"cw-file-upload-multiple-module__uploadSubtitle__Z0S5t","filesContainer":"cw-file-upload-multiple-module__filesContainer__g44PY","fileItem":"cw-file-upload-multiple-module__fileItem__w27Dg","fileIcon":"cw-file-upload-multiple-module__fileIcon__iJJUX","fileExtension":"cw-file-upload-multiple-module__fileExtension__vOuHv","fileInfo":"cw-file-upload-multiple-module__fileInfo__R5ZTv","fileName":"cw-file-upload-multiple-module__fileName__DjepK","fileSize":"cw-file-upload-multiple-module__fileSize__b8GSm","smallButton":"cw-file-upload-multiple-module__smallButton__siUAh"};
|
|
3000
|
+
var styles$k = {"fileUploadContainer":"cw-file-upload-multiple-module__fileUploadContainer__liEc1","hiddenInput":"cw-file-upload-multiple-module__hiddenInput__TZBBI","uploadArea":"cw-file-upload-multiple-module__uploadArea__DdOhs","uploadAreaDisabled":"cw-file-upload-multiple-module__uploadAreaDisabled__VWeFX","uploadTitle":"cw-file-upload-multiple-module__uploadTitle__gjRk8","uploadSubtitle":"cw-file-upload-multiple-module__uploadSubtitle__Z0S5t","filesContainer":"cw-file-upload-multiple-module__filesContainer__g44PY","fileItem":"cw-file-upload-multiple-module__fileItem__w27Dg","fileIcon":"cw-file-upload-multiple-module__fileIcon__iJJUX","fileExtension":"cw-file-upload-multiple-module__fileExtension__vOuHv","fileInfo":"cw-file-upload-multiple-module__fileInfo__R5ZTv","fileName":"cw-file-upload-multiple-module__fileName__DjepK","fileSize":"cw-file-upload-multiple-module__fileSize__b8GSm","smallButton":"cw-file-upload-multiple-module__smallButton__siUAh"};
|
|
2914
3001
|
|
|
2915
|
-
const DEFAULT_LABELS = {
|
|
3002
|
+
const DEFAULT_LABELS$1 = {
|
|
2916
3003
|
uploadDisabled: 'Upload disabled',
|
|
2917
3004
|
clickToUpload: 'Click to upload or drag and drop',
|
|
2918
3005
|
acceptedFiles: (accept) => `Accepted files: ${accept}`,
|
|
@@ -2920,6 +3007,7 @@ const DEFAULT_LABELS = {
|
|
|
2920
3007
|
allTypesAccepted: 'All file types accepted',
|
|
2921
3008
|
changeFile: 'Change File',
|
|
2922
3009
|
clearAll: 'Clear all',
|
|
3010
|
+
upload: 'Upload',
|
|
2923
3011
|
addMoreFiles: 'Add More Files',
|
|
2924
3012
|
filesSelected: (count) => `${count} file${count !== 1 ? 's' : ''} selected`,
|
|
2925
3013
|
fileTooLarge: (name, maxSize) => `File "${name}" is too large. Maximum size allowed is ${maxSize}MB.`,
|
|
@@ -2927,11 +3015,38 @@ const DEFAULT_LABELS = {
|
|
|
2927
3015
|
invalidMimeType: (name, types) => `File "${name}" has an invalid MIME type. Allowed types: ${types}`,
|
|
2928
3016
|
alreadySelected: (name) => `File "${name}" is already selected.`,
|
|
2929
3017
|
};
|
|
3018
|
+
/**
|
|
3019
|
+
* Checks a file against an `accept` string (comma-separated tokens). A token can be a dotted
|
|
3020
|
+
* extension (".pdf"), an exact MIME type ("application/pdf"), a wildcard MIME ("image" + slash + "star"),
|
|
3021
|
+
* or a bare "star" / "star-slash-star" for anything. Returns true if the file matches ANY token
|
|
3022
|
+
* (or if `accept` is empty).
|
|
3023
|
+
*/
|
|
3024
|
+
function fileMatchesAccept(fileName, fileType, accept) {
|
|
3025
|
+
const tokens = accept.split(',').map(token => token.trim().toLowerCase()).filter(Boolean);
|
|
3026
|
+
if (tokens.length === 0) {
|
|
3027
|
+
return true;
|
|
3028
|
+
}
|
|
3029
|
+
const fileExtension = '.' + (fileName.split('.').pop()?.toLowerCase() ?? '');
|
|
3030
|
+
const mimeType = fileType.toLowerCase();
|
|
3031
|
+
return tokens.some(token => {
|
|
3032
|
+
if (token === '*' || token === '*/*') {
|
|
3033
|
+
return true;
|
|
3034
|
+
}
|
|
3035
|
+
if (token.startsWith('.')) {
|
|
3036
|
+
return token === fileExtension;
|
|
3037
|
+
}
|
|
3038
|
+
if (token.endsWith('/*')) {
|
|
3039
|
+
const prefix = token.slice(0, token.indexOf('/') + 1);
|
|
3040
|
+
return mimeType.startsWith(prefix);
|
|
3041
|
+
}
|
|
3042
|
+
return token === mimeType;
|
|
3043
|
+
});
|
|
3044
|
+
}
|
|
2930
3045
|
function CwFileUploadMultiple(fileUploadProps) {
|
|
2931
3046
|
const fileInputRef = useRef(null);
|
|
2932
3047
|
const [selectedFiles, setSelectedFiles] = useState([]);
|
|
2933
3048
|
const [existingFile, setExistingFile] = useState(fileUploadProps.initialFileName);
|
|
2934
|
-
const labels = { ...DEFAULT_LABELS, ...fileUploadProps.labels };
|
|
3049
|
+
const labels = { ...DEFAULT_LABELS$1, ...fileUploadProps.labels };
|
|
2935
3050
|
React__default.useEffect(() => {
|
|
2936
3051
|
setExistingFile(fileUploadProps.initialFileName);
|
|
2937
3052
|
}, [fileUploadProps.initialFileName]);
|
|
@@ -2949,17 +3064,9 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2949
3064
|
};
|
|
2950
3065
|
}
|
|
2951
3066
|
}
|
|
2952
|
-
// Validate file type
|
|
3067
|
+
// Validate file type against accept (dotted extensions, exact MIME, wildcard MIME, or *)
|
|
2953
3068
|
if (fileUploadProps.accept) {
|
|
2954
|
-
|
|
2955
|
-
const fileExtension = '.' + file.name.split('.').pop()?.toLowerCase();
|
|
2956
|
-
const isExtensionValid = acceptedExtensions.some(ext => {
|
|
2957
|
-
if (ext.startsWith('.')) {
|
|
2958
|
-
return ext === fileExtension;
|
|
2959
|
-
}
|
|
2960
|
-
return false;
|
|
2961
|
-
});
|
|
2962
|
-
if (!isExtensionValid) {
|
|
3069
|
+
if (!fileMatchesAccept(file.name, file.type, fileUploadProps.accept)) {
|
|
2963
3070
|
return {
|
|
2964
3071
|
isValid: false,
|
|
2965
3072
|
error: labels.invalidFormat(file.name, fileUploadProps.accept)
|
|
@@ -2984,7 +3091,7 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2984
3091
|
const errors = [];
|
|
2985
3092
|
for (const file of fileArray) {
|
|
2986
3093
|
// Check if the file already exists (by name and size)
|
|
2987
|
-
const isDuplicate =
|
|
3094
|
+
const isDuplicate = validFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
|
|
2988
3095
|
if (isDuplicate) {
|
|
2989
3096
|
errors.push(labels.alreadySelected(file.name));
|
|
2990
3097
|
continue;
|
|
@@ -3002,8 +3109,7 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
3002
3109
|
fileUploadProps.onError(errors.join('\n'));
|
|
3003
3110
|
}
|
|
3004
3111
|
else {
|
|
3005
|
-
|
|
3006
|
-
alert(errors.join('\n')); // Fallback if there is no onError
|
|
3112
|
+
CwDisplayMessage(errors.join('\n'), CwMessageType.ERROR);
|
|
3007
3113
|
}
|
|
3008
3114
|
}
|
|
3009
3115
|
// If not multiple, only take the first valid file (replace)
|
|
@@ -3077,12 +3183,20 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
3077
3183
|
}
|
|
3078
3184
|
}
|
|
3079
3185
|
};
|
|
3080
|
-
return (jsxs("div", { className: `${styles$
|
|
3186
|
+
return (jsxs("div", { className: `${styles$k.fileUploadContainer} ${fileUploadProps.className}`, children: [jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$k.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxs("div", { className: `${styles$k.uploadArea} ${fileUploadProps.disabled ? styles$k.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsx(CwIcon, { iconId: "upload" }), jsx("p", { className: `${styles$k.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxs("p", { className: `${styles$k.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxs("div", { className: styles$k.filesContainer, children: [jsxs("div", { className: styles$k.fileItem, children: [jsxs("div", { className: styles$k.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$k.fileExtension, children: getFileExtension(existingFile) })] }), jsx("div", { className: styles$k.fileInfo, children: jsx("p", { className: styles$k.fileName, children: existingFile }) }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
|
|
3081
3187
|
setExistingFile(undefined);
|
|
3082
3188
|
if (fileUploadProps.onSelect) {
|
|
3083
3189
|
fileUploadProps.onSelect(null);
|
|
3084
3190
|
}
|
|
3085
|
-
}, disabled: fileUploadProps.disabled, className: styles$
|
|
3191
|
+
}, disabled: fileUploadProps.disabled, className: styles$k.smallButton })] }), jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxs("div", { className: styles$k.filesContainer, children: [jsxs("header", { className: "cw-flex-row cw-align-between-center cw-flex-wrap", children: [jsx("small", { className: styles$k.filesCount, children: fileUploadProps.statusText ?? labels.filesSelected(selectedFiles.length) }), jsxs("div", { className: "cw-flex-row", children: [fileUploadProps.onConfirm && selectedFiles.length > 0 && (jsx(CwButton, { onClick: () => {
|
|
3192
|
+
let files = fileInputRef.current?.files ?? null;
|
|
3193
|
+
if (!files) {
|
|
3194
|
+
const dataTransfer = new DataTransfer();
|
|
3195
|
+
selectedFiles.forEach(file => dataTransfer.items.add(file));
|
|
3196
|
+
files = dataTransfer.files;
|
|
3197
|
+
}
|
|
3198
|
+
fileUploadProps.onConfirm?.(files);
|
|
3199
|
+
}, disabled: fileUploadProps.disabled || fileUploadProps.confirmDisabled, icon: "upload", text: fileUploadProps.confirmLabel ?? labels.upload })), !fileUploadProps.hideClearAll && (jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] })] }), selectedFiles.map((file, index) => (jsxs("div", { className: styles$k.fileItem, children: [jsxs("div", { className: styles$k.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$k.fileExtension, children: getFileExtension(file.name) })] }), jsxs("div", { className: styles$k.fileInfo, children: [jsx("p", { className: styles$k.fileName, children: file.name }), jsxs("p", { className: styles$k.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$k.smallButton })] }, `${file.name}-${file.size}`))), fileUploadProps.multiple && (jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
|
|
3086
3200
|
}
|
|
3087
3201
|
|
|
3088
3202
|
function CwInput(CwInputProps) {
|
|
@@ -3123,7 +3237,7 @@ function CwDigit(props) {
|
|
|
3123
3237
|
return (jsx("div", { className: "cw-input-text", children: jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsx("input", { type: "number", ...inputProps }), buttonProps && jsx(CwButton, { ...buttonProps })] }) }));
|
|
3124
3238
|
}
|
|
3125
3239
|
|
|
3126
|
-
var styles$
|
|
3240
|
+
var styles$j = {"colorPreview":"cw-color-picker-module__colorPreview__ylJcD","hueBar":"cw-color-picker-module__hueBar__bFhyC","hueBarSlider":"cw-color-picker-module__hueBarSlider__D53IV","colorPickerInteractiveArea":"cw-color-picker-module__colorPickerInteractiveArea__KZFR1","colorArea":"cw-color-picker-module__colorArea__xgpSE","colorAreaOverlay":"cw-color-picker-module__colorAreaOverlay__pmgOc","hueBackground":"cw-color-picker-module__hueBackground__Mks78","whiteGradient":"cw-color-picker-module__whiteGradient__Bt-fU","blackGradient":"cw-color-picker-module__blackGradient__VnEKJ","colorAreaCursor":"cw-color-picker-module__colorAreaCursor__lotg3"};
|
|
3127
3241
|
|
|
3128
3242
|
const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }) => {
|
|
3129
3243
|
const [rgb, setRgb] = useState({ r: 255, g: 255, b: 255 });
|
|
@@ -3326,13 +3440,13 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
|
|
|
3326
3440
|
// Calculate background color for the main area based on current hue
|
|
3327
3441
|
const hueColor = hsvToRgb(hsv.h, 100, 100);
|
|
3328
3442
|
const hueHex = rgbToHex(hueColor.r, hueColor.g, hueColor.b);
|
|
3329
|
-
return (jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsx("div", { className: styles$
|
|
3443
|
+
return (jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsx("div", { className: styles$j.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxs("div", { children: [jsx("label", { children: "R:" }), jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxs("div", { children: [jsx("label", { children: "G:" }), jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxs("div", { children: [jsx("label", { children: "B:" }), jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxs("div", { className: styles$j.colorPickerInteractiveArea, children: [jsx("div", { className: styles$j.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsx("div", { className: styles$j.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxs("div", { className: styles$j.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxs("div", { className: styles$j.colorAreaOverlay, children: [jsx("div", { className: styles$j.hueBackground, style: { backgroundColor: hueHex } }), jsx("div", { className: styles$j.whiteGradient }), jsx("div", { className: styles$j.blackGradient })] }), jsx("div", { className: styles$j.colorAreaCursor, style: {
|
|
3330
3444
|
left: `${hsv.s}%`,
|
|
3331
3445
|
top: `${100 - hsv.v}%`
|
|
3332
3446
|
} })] })] })] }));
|
|
3333
3447
|
};
|
|
3334
3448
|
|
|
3335
|
-
var styles$
|
|
3449
|
+
var styles$i = {"container":"cw-input-color-module__container__x7gpk","selectColor":"cw-input-color-module__selectColor__DTo3V","disabled":"cw-input-color-module__disabled__O1fK5","readOnly":"cw-input-color-module__readOnly__HL-Bz","colorDropdown":"cw-input-color-module__colorDropdown__pX2bc"};
|
|
3336
3450
|
|
|
3337
3451
|
const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, }) => {
|
|
3338
3452
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -3465,11 +3579,11 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
|
|
|
3465
3579
|
break;
|
|
3466
3580
|
}
|
|
3467
3581
|
};
|
|
3468
|
-
return (jsxs("div", { className: `cw-input-color ${styles$
|
|
3582
|
+
return (jsxs("div", { className: `cw-input-color ${styles$i.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsx(CwLabel, { ...labelProps })), jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
|
|
3469
3583
|
width,
|
|
3470
3584
|
height,
|
|
3471
3585
|
backgroundColor: value,
|
|
3472
|
-
}, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && createPortal(jsx("div", { ref: dropdownRef, className: styles$
|
|
3586
|
+
}, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && createPortal(jsx("div", { ref: dropdownRef, className: styles$i.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
|
|
3473
3587
|
};
|
|
3474
3588
|
|
|
3475
3589
|
/**
|
|
@@ -3719,31 +3833,63 @@ function CwInputDateText(props) {
|
|
|
3719
3833
|
return (jsx("div", { className: "cw-input-date-text", children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { children: [jsx("input", { type: "text", disabled: disabled, maxLength: 10, onChange: onChangeInputText, pattern: "^$ --|[.0-9\\/\\-]{10}", placeholder: format.toLowerCase(), readOnly: readOnly, ref: textInputRef, required: required, size: width, tabIndex: tabIndex, value: displayedDate }), jsxs("span", { children: [jsx(CwIcon, { iconId: "calendar" }), jsx("input", { type: "date", disabled: disabled, onChange: onChangeInputDate, readOnly: readOnly, ref: dateInputRef, tabIndex: -1, value: date, ...inputProps })] })] }), buttonProps && jsx(CwButton, { ...buttonProps })] }) }));
|
|
3720
3834
|
}
|
|
3721
3835
|
|
|
3722
|
-
var styles$
|
|
3836
|
+
var styles$h = {"hiddenInput":"cw-input-image-module__hiddenInput__pS7hb","dropZone":"cw-input-image-module__dropZone__ygrGu","title":"cw-input-image-module__title__Rji5M","subtitle":"cw-input-image-module__subtitle__djYYu","container":"cw-input-image-module__container__qh7Tm"};
|
|
3723
3837
|
|
|
3838
|
+
const DEFAULT_LABELS = {
|
|
3839
|
+
dropImageHere: "Drop image here",
|
|
3840
|
+
paste: "Paste",
|
|
3841
|
+
browse: "Browse",
|
|
3842
|
+
acceptedFormats: (formats) => `(${formats})`,
|
|
3843
|
+
clipboardError: "Failed to read from clipboard. Ensure the app has permission to access the clipboard.",
|
|
3844
|
+
invalidType: (formats) => `Unsupported file type. Allowed: ${formats}`,
|
|
3845
|
+
readError: "Could not read the image file.",
|
|
3846
|
+
};
|
|
3847
|
+
/** Reads a file/blob into a base64 data URL (persistable, no blob URL to revoke). */
|
|
3848
|
+
function readImageFileAsDataUrl(file) {
|
|
3849
|
+
return new Promise((resolve, reject) => {
|
|
3850
|
+
const reader = new FileReader();
|
|
3851
|
+
reader.onload = () => resolve(reader.result);
|
|
3852
|
+
reader.onerror = () => reject(reader.error ?? new Error("Failed to read file"));
|
|
3853
|
+
reader.readAsDataURL(file);
|
|
3854
|
+
});
|
|
3855
|
+
}
|
|
3724
3856
|
function CwInputImage(props) {
|
|
3725
3857
|
const [_uploadedImage, setUploadedImage] = useState(null);
|
|
3726
3858
|
const inputRef = useRef(null);
|
|
3727
|
-
const { allowedImageFormats, onChange, ...inputProps } = props;
|
|
3859
|
+
const { allowedImageFormats, onChange, onError, labels: labelsProp, size, ...inputProps } = props;
|
|
3728
3860
|
const allowedFormats = allowedImageFormats || ["image/jpeg", "image/png", "image/gif"];
|
|
3861
|
+
const labels = { ...DEFAULT_LABELS, ...labelsProp };
|
|
3729
3862
|
const isValidFileType = (type) => allowedFormats.includes(type);
|
|
3730
|
-
const
|
|
3731
|
-
if (
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3863
|
+
const reportError = (message) => {
|
|
3864
|
+
if (onError)
|
|
3865
|
+
onError(message);
|
|
3866
|
+
else
|
|
3867
|
+
CwDisplayMessage(message, CwMessageType.ERROR);
|
|
3868
|
+
};
|
|
3869
|
+
const handleFile = async (file) => {
|
|
3870
|
+
if (!file) {
|
|
3871
|
+
onChange?.(null);
|
|
3872
|
+
return;
|
|
3736
3873
|
}
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3874
|
+
if (!isValidFileType(file.type)) {
|
|
3875
|
+
reportError(labels.invalidType(allowedFormats.join(", ").replace(/image\//g, "")));
|
|
3876
|
+
onChange?.(null);
|
|
3877
|
+
return;
|
|
3878
|
+
}
|
|
3879
|
+
try {
|
|
3880
|
+
const dataUrl = await readImageFileAsDataUrl(file);
|
|
3881
|
+
setUploadedImage(dataUrl);
|
|
3882
|
+
onChange?.(dataUrl, file);
|
|
3883
|
+
}
|
|
3884
|
+
catch {
|
|
3885
|
+
reportError(labels.readError);
|
|
3886
|
+
onChange?.(null);
|
|
3741
3887
|
}
|
|
3742
3888
|
};
|
|
3743
3889
|
const handleDrop = (e) => {
|
|
3744
3890
|
e.preventDefault();
|
|
3745
3891
|
const file = e.dataTransfer.files[0];
|
|
3746
|
-
handleFile(file);
|
|
3892
|
+
void handleFile(file ?? null);
|
|
3747
3893
|
};
|
|
3748
3894
|
const onPasteButtonClick = async () => {
|
|
3749
3895
|
try {
|
|
@@ -3753,21 +3899,20 @@ function CwInputImage(props) {
|
|
|
3753
3899
|
for (const type of clipboardItem.types) {
|
|
3754
3900
|
if (type.startsWith("image/")) {
|
|
3755
3901
|
const blob = await clipboardItem.getType(type);
|
|
3756
|
-
handleFile(blob);
|
|
3902
|
+
await handleFile(blob);
|
|
3757
3903
|
}
|
|
3758
3904
|
}
|
|
3759
3905
|
}
|
|
3760
3906
|
}
|
|
3761
|
-
catch
|
|
3762
|
-
|
|
3763
|
-
alert("Failed to read from clipboard. Ensure the app has permission to access clipboard.");
|
|
3907
|
+
catch {
|
|
3908
|
+
reportError(labels.clipboardError);
|
|
3764
3909
|
}
|
|
3765
3910
|
};
|
|
3766
3911
|
const handleFileChange = (e) => {
|
|
3767
|
-
const file = e.
|
|
3768
|
-
handleFile(file ?? null);
|
|
3912
|
+
const file = e.currentTarget.files?.[0];
|
|
3913
|
+
void handleFile(file ?? null);
|
|
3769
3914
|
};
|
|
3770
|
-
return (jsxs("div", { className:
|
|
3915
|
+
return (jsxs("div", { className: `cw-input-image ${styles$h.container}`, "data-size": size, children: [jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$h.dropZone, children: [jsx(CwIcon, { iconId: "upload" }), jsxs("div", { className: "cw-flex-column cw-gap-tiny", children: [jsx("p", { className: styles$h.title, children: labels.dropImageHere }), jsx("p", { className: styles$h.subtitle, children: labels.acceptedFormats(allowedFormats.join(", ").replace(/image\//g, "")) })] })] }), jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: labels.paste, size: size }), jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: labels.browse, size: size })] }), jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, className: styles$h.hiddenInput, ...inputProps })] }));
|
|
3771
3916
|
}
|
|
3772
3917
|
|
|
3773
3918
|
/**
|
|
@@ -3899,7 +4044,7 @@ const CwImageArea = forwardRef((props, ref) => {
|
|
|
3899
4044
|
});
|
|
3900
4045
|
CwImageArea.displayName = "CwImageArea";
|
|
3901
4046
|
|
|
3902
|
-
var styles$
|
|
4047
|
+
var styles$g = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
|
|
3903
4048
|
|
|
3904
4049
|
/**
|
|
3905
4050
|
* This class represents a week where days can be selected or unselected
|
|
@@ -4039,16 +4184,16 @@ const CwWeekdaySelector = ({ value = "", onChange, disabled = false }) => {
|
|
|
4039
4184
|
setSelectedDays(newWeekdays);
|
|
4040
4185
|
onChange?.(newWeekdays.toString());
|
|
4041
4186
|
};
|
|
4042
|
-
return (jsx("div", { className: styles$
|
|
4187
|
+
return (jsx("div", { className: styles$g["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
|
|
4043
4188
|
};
|
|
4044
4189
|
|
|
4045
|
-
var styles$
|
|
4190
|
+
var styles$f = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
|
|
4046
4191
|
|
|
4047
4192
|
function CwCheck(props) {
|
|
4048
4193
|
const { labelProps, labelText, direction, alignment, className, ...inputProps } = props;
|
|
4049
4194
|
const resolvedDirection = direction ?? alignment ?? "row";
|
|
4050
4195
|
const displayText = labelProps?.text ?? labelText;
|
|
4051
|
-
return (jsx("div", { className: `cw-check ${styles$
|
|
4196
|
+
return (jsx("div", { className: `cw-check ${styles$f["check-container"]}${className ? ` ${className}` : ''}`, children: jsxs("label", { "data-direction": resolvedDirection, children: [jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsx("span", { className: "cw-icon-text", children: displayText }))] }) }));
|
|
4052
4197
|
}
|
|
4053
4198
|
|
|
4054
4199
|
function CwCheckbox(CwCheckboxProps) {
|
|
@@ -4099,14 +4244,14 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
|
|
|
4099
4244
|
?? (optionsAlignment === "column" ? "row" : "column");
|
|
4100
4245
|
// Each checkbox's box-to-text layout is the opposite of the options flow, mirroring CwRadioGroup.
|
|
4101
4246
|
const checkDirection = itemDirection === "row" ? "column" : "row";
|
|
4102
|
-
return (jsxs("div", { className: `cw-checkbox-group ${styles$
|
|
4247
|
+
return (jsxs("div", { className: `cw-checkbox-group ${styles$f.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$f.options, role: "group", "aria-label": labelProps?.text, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
|
|
4103
4248
|
}
|
|
4104
4249
|
|
|
4105
|
-
var styles$
|
|
4250
|
+
var styles$e = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
|
|
4106
4251
|
|
|
4107
4252
|
/** Single native radio input. Building block for CwRadioGroup. */
|
|
4108
4253
|
function CwRadio({ label, direction = "row", className, ...inputProps }) {
|
|
4109
|
-
return (jsxs("label", { className: `cw-radio ${styles$
|
|
4254
|
+
return (jsxs("label", { className: `cw-radio ${styles$e.radio}${className ? ` ${className}` : ""}`, "data-direction": direction, children: [jsx("input", { type: "radio", ...inputProps }), label && jsx("span", { children: label })] }));
|
|
4110
4255
|
}
|
|
4111
4256
|
|
|
4112
4257
|
/**
|
|
@@ -4130,7 +4275,7 @@ function CwRadioGroup({ options, value, onChange, labelProps, groupLayout, itemL
|
|
|
4130
4275
|
// (itemLayout column) reads best with the circle beside the text; a side-by-side row reads
|
|
4131
4276
|
// best with the circle above the text.
|
|
4132
4277
|
const radioDirection = itemLayout?.direction === "row" ? "column" : "row";
|
|
4133
|
-
return (jsxs("div", { className: `cw-radio-group ${styles$
|
|
4278
|
+
return (jsxs("div", { className: `cw-radio-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$e.options, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : (ariaLabel ?? labelProps?.text), "aria-required": required || undefined, "data-direction": itemLayout?.direction ?? "column", "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
|
|
4134
4279
|
}
|
|
4135
4280
|
|
|
4136
4281
|
function CwToggle(props) {
|
|
@@ -4396,7 +4541,7 @@ function CwDropdownFilter(props) {
|
|
|
4396
4541
|
return (jsxs("div", { id: props.IdContent, className: containerClassName, children: [props.children, isVisible && (jsx("nav", { className: "cw-dropdown-menu", style: inlineStyles, onMouseLeave: props.onMouseLeave, id: props.idDropDownFilter, role: "menu", children: jsx("ul", { role: "none", children: props.DataSourceDropDownItem?.map((item) => (jsx("li", { id: item.IdDropDown_filter, role: "menuitem", children: item.dropDownFilter_desc }, item.IdDropDown_filter))) }) }))] }));
|
|
4397
4542
|
}
|
|
4398
4543
|
|
|
4399
|
-
var styles$
|
|
4544
|
+
var styles$d = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
|
|
4400
4545
|
|
|
4401
4546
|
/**
|
|
4402
4547
|
* Button that toggles a floating panel with arbitrary children.
|
|
@@ -4475,7 +4620,7 @@ function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-st
|
|
|
4475
4620
|
}
|
|
4476
4621
|
panel.showPopover();
|
|
4477
4622
|
}, [placement]);
|
|
4478
|
-
return (jsxs("div", { ref: containerRef, className: styles$
|
|
4623
|
+
return (jsxs("div", { ref: containerRef, className: styles$d.container, children: [jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsx("div", { ref: panelCallbackRef, className: `${styles$d.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
|
|
4479
4624
|
}
|
|
4480
4625
|
|
|
4481
4626
|
function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor, onPrimaryColor) {
|
|
@@ -4493,13 +4638,13 @@ function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor
|
|
|
4493
4638
|
return result;
|
|
4494
4639
|
}
|
|
4495
4640
|
|
|
4496
|
-
var styles$
|
|
4641
|
+
var styles$c = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
|
|
4497
4642
|
|
|
4498
4643
|
const CwMultiFilterTag = props => {
|
|
4499
4644
|
const { ID, Name, Value, Category, Removable, PrimaryColor, Selectable, Selected } = props;
|
|
4500
4645
|
const backgroundColor = `rgb(${PrimaryColor.r},${PrimaryColor.g},${PrimaryColor.b})`;
|
|
4501
4646
|
const isOutlineMode = Selected && !Removable;
|
|
4502
|
-
return (jsx("li", { className: styles$
|
|
4647
|
+
return (jsx("li", { className: styles$c["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
|
|
4503
4648
|
if (Selectable)
|
|
4504
4649
|
props.OnSelect?.(props);
|
|
4505
4650
|
}, children: jsx(CwChip, { label: Name, colorScheme: "custom", customColor: backgroundColor, variant: isOutlineMode ? "outline" : "soft", closable: Removable, onClose: () => props.OnRemove?.(props),
|
|
@@ -4509,7 +4654,7 @@ const CwMultiFilterTag = props => {
|
|
|
4509
4654
|
} : undefined }) }));
|
|
4510
4655
|
};
|
|
4511
4656
|
|
|
4512
|
-
var styles$
|
|
4657
|
+
var styles$b = {"cw-multi-filter-catalog-container":"cw-multi-filter-module__cw-multi-filter-catalog-container__S3nsq","cw-multi-filter":"cw-multi-filter-module__cw-multi-filter__zipBK","category-selected":"cw-multi-filter-module__category-selected__eYbes","cw-multi-filter-search":"cw-multi-filter-module__cw-multi-filter-search__eyHr0 cw-choice-input-box-module__inputBox__gHY9d"};
|
|
4513
4658
|
|
|
4514
4659
|
/**
|
|
4515
4660
|
* A multiple filter selector, a MULTI-SELECT even. Allows users to select and filter items based on tags.
|
|
@@ -4736,9 +4881,9 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4736
4881
|
inputRef.current?.focus();
|
|
4737
4882
|
}
|
|
4738
4883
|
};
|
|
4739
|
-
return (jsxs("form", { ref: componentRef, id: id, className: `${styles$
|
|
4884
|
+
return (jsxs("form", { ref: componentRef, id: id, className: `${styles$b["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
|
|
4740
4885
|
e.preventDefault();
|
|
4741
|
-
}, children: [jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$
|
|
4886
|
+
}, children: [jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$b["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-outline-variant)" } : {}, children: [jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.currentTarget.value), autoComplete: "off", placeholder: selectedTags.size === 0 ? placeholder : "", onKeyDown: e => {
|
|
4742
4887
|
switch (e.key) {
|
|
4743
4888
|
case "Enter":
|
|
4744
4889
|
case "Tab": {
|
|
@@ -4765,7 +4910,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4765
4910
|
break;
|
|
4766
4911
|
}
|
|
4767
4912
|
}
|
|
4768
|
-
} })] }), selectedTags.size > 0 && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxs("section", { ref: panelRef, className: styles$
|
|
4913
|
+
} })] }), selectedTags.size > 0 && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxs("section", { ref: panelRef, className: styles$b["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxs("nav", { children: [jsx("button", { className: selectedCategory === "All" ? styles$b["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsx("button", { className: selectedCategory === category ? styles$b["category-selected"] : undefined, style: {
|
|
4769
4914
|
backgroundColor: getColor(category).primary,
|
|
4770
4915
|
color: getColor(category).onPrimary,
|
|
4771
4916
|
}, onClick: () => handleClickCategory(category), children: category }, category)))] }), jsx("ul", { children: displayTags
|
|
@@ -4791,7 +4936,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
|
|
|
4791
4936
|
} }, props.ID))) })] }))] }));
|
|
4792
4937
|
};
|
|
4793
4938
|
|
|
4794
|
-
var styles$
|
|
4939
|
+
var styles$a = {"container":"cw-tag-selector-module__container__-do8i","inputBox":"cw-tag-selector-module__inputBox__3NGz9 cw-choice-input-box-module__inputBox__gHY9d","disabled":"cw-tag-selector-module__disabled__vbud9 cw-choice-input-box-module__disabled__TFAnC","dropdown":"cw-tag-selector-module__dropdown__X6Dob cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-tag-selector-module__option__2UQ7g cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-tag-selector-module__optionFocused__8-lv8 cw-choice-dropdown-module__optionFocused__BYMxj","optionDot":"cw-tag-selector-module__optionDot__CdFlG cw-choice-dropdown-module__colorCircle__x7mI9","selectAll":"cw-tag-selector-module__selectAll__HyvMA"};
|
|
4795
4940
|
|
|
4796
4941
|
/**
|
|
4797
4942
|
* Multi-select input with chip tags and searchable dropdown.
|
|
@@ -4926,11 +5071,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
|
|
|
4926
5071
|
// Keeping containerRef for any other potential use
|
|
4927
5072
|
const direction = alignProps?.flexDirection ?? "row";
|
|
4928
5073
|
const feedbackMessages = feedback ? (Array.isArray(feedback) ? feedback : [feedback]) : [];
|
|
4929
|
-
return (jsxs("div", { ref: containerRef, className: `${styles$
|
|
4930
|
-
inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxs("div", { ref: panelRef, className: styles$
|
|
5074
|
+
return (jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
|
|
5075
|
+
inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxs("div", { ref: panelRef, className: styles$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxs("li", { className: `${styles$a.option}${idx === focusedIndex ? ` ${styles$a.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
|
|
4931
5076
|
}
|
|
4932
5077
|
|
|
4933
|
-
var styles$
|
|
5078
|
+
var styles$9 = {"tree-container":"cw-tree-view-module__tree-container__NN-HJ","tree-wrapper":"cw-tree-view-module__tree-wrapper__keBZI","tree-item":"cw-tree-view-module__tree-item__prE9N","tree-node":"cw-tree-view-module__tree-node__wfro9","selected":"cw-tree-view-module__selected__XJQ0w","non-selectable":"cw-tree-view-module__non-selectable__YuPSx","tree-children":"cw-tree-view-module__tree-children__ji8CZ","empty-state":"cw-tree-view-module__empty-state__yvRjo","tree-label":"cw-tree-view-module__tree-label__ss3Nf","tree-spacer":"cw-tree-view-module__tree-spacer__E9Ud2"};
|
|
4934
5079
|
|
|
4935
5080
|
function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId: initialSelectedId = null }) {
|
|
4936
5081
|
const [expanded, setExpanded] = useState(new Set());
|
|
@@ -4997,10 +5142,10 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
|
|
|
4997
5142
|
const isLeaf = !hasChildren;
|
|
4998
5143
|
const isSelected = selectedId?.toString().toLowerCase() === node.id.toString().toLowerCase();
|
|
4999
5144
|
const selectable = allowParentSelection || isLeaf;
|
|
5000
|
-
return (jsxs("div", { className: styles$
|
|
5001
|
-
styles$
|
|
5002
|
-
isSelected && styles$
|
|
5003
|
-
!selectable && styles$
|
|
5145
|
+
return (jsxs("div", { className: styles$9["tree-item"], children: [jsxs("div", { className: [
|
|
5146
|
+
styles$9["tree-node"],
|
|
5147
|
+
isSelected && styles$9["selected"],
|
|
5148
|
+
!selectable && styles$9["non-selectable"]
|
|
5004
5149
|
].filter(Boolean).join(' '), style: { paddingLeft: `${depth * 24 + 8}px` }, onClick: () => {
|
|
5005
5150
|
if (selectable) {
|
|
5006
5151
|
setSelectedId(node.id);
|
|
@@ -5009,7 +5154,7 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
|
|
|
5009
5154
|
else {
|
|
5010
5155
|
toggleExpand(node.id);
|
|
5011
5156
|
}
|
|
5012
|
-
}, children: [hasChildren && (jsx(CwIcon, { size: "large", iconId: isExpanded ? "chevron-down" : "chevron-right" })), jsx("div", { className: `${styles$
|
|
5157
|
+
}, children: [hasChildren && (jsx(CwIcon, { size: "large", iconId: isExpanded ? "chevron-down" : "chevron-right" })), jsx("div", { className: `${styles$9["tree-label"]} ${!hasChildren ? styles$9["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsx("div", { className: styles$9["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
|
|
5013
5158
|
};
|
|
5014
5159
|
// Function to search for nodes that match the search term
|
|
5015
5160
|
const searchInTree = (nodes, searchTerm) => {
|
|
@@ -5033,7 +5178,129 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
|
|
|
5033
5178
|
return results;
|
|
5034
5179
|
};
|
|
5035
5180
|
const filteredData = searchInTree(data, search);
|
|
5036
|
-
return (jsxs("div", { className: `cw-tree-view ${styles$
|
|
5181
|
+
return (jsxs("div", { className: `cw-tree-view ${styles$9["tree-container"]}`, children: [jsxs("header", { children: [jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsx("div", { className: styles$9["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxs("div", { className: styles$9["empty-state"], children: [jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
|
|
5182
|
+
}
|
|
5183
|
+
|
|
5184
|
+
const EXACT_PHRASE = /"([^"]+)"/g;
|
|
5185
|
+
/**
|
|
5186
|
+
* Quoted phrases are matched against the label only; loose words against label + description + href.
|
|
5187
|
+
* Parsed once instead of per node.
|
|
5188
|
+
*/
|
|
5189
|
+
function parseSearch(search) {
|
|
5190
|
+
const phrases = Array.from(search.matchAll(EXACT_PHRASE), match => match[1].toLowerCase());
|
|
5191
|
+
const words = search
|
|
5192
|
+
.replace(EXACT_PHRASE, "")
|
|
5193
|
+
.trim()
|
|
5194
|
+
.toLowerCase()
|
|
5195
|
+
.split(/\s+/)
|
|
5196
|
+
.filter(Boolean);
|
|
5197
|
+
return { phrases, words };
|
|
5198
|
+
}
|
|
5199
|
+
/**
|
|
5200
|
+
* Filters a nav tree by a search string, keeping a group whose descendants match.
|
|
5201
|
+
*
|
|
5202
|
+
* Supports `"quoted phrases"` (must appear in the label) alongside loose words (any field) — this is
|
|
5203
|
+
* behaviour users are told about, so don't simplify it.
|
|
5204
|
+
*/
|
|
5205
|
+
function filterNavItems(items, search) {
|
|
5206
|
+
if (!search?.trim())
|
|
5207
|
+
return items;
|
|
5208
|
+
const { phrases, words } = parseSearch(search);
|
|
5209
|
+
if (phrases.length === 0 && words.length === 0)
|
|
5210
|
+
return items;
|
|
5211
|
+
const keep = (item, parentMatchedPhrases) => {
|
|
5212
|
+
const label = item.label.toLowerCase();
|
|
5213
|
+
const haystack = [item.label, item.description, item.href].filter(Boolean).join(" ").toLowerCase();
|
|
5214
|
+
const matchesPhrases = phrases.every(phrase => label.includes(phrase));
|
|
5215
|
+
const matchesWords = words.every(word => haystack.includes(word));
|
|
5216
|
+
const selfMatches = (phrases.length === 0 || matchesPhrases || parentMatchedPhrases) && matchesWords;
|
|
5217
|
+
if (!item.children?.length)
|
|
5218
|
+
return selfMatches ? item : null;
|
|
5219
|
+
let children = item.children
|
|
5220
|
+
.map(child => keep(child, matchesPhrases || parentMatchedPhrases))
|
|
5221
|
+
.filter((child) => child !== null);
|
|
5222
|
+
// A phrase-only search narrows the survivors further: each must carry the phrase itself.
|
|
5223
|
+
if (phrases.length > 0 && words.length === 0 && matchesPhrases) {
|
|
5224
|
+
children = children.filter(child => phrases.every(phrase => child.label.toLowerCase().includes(phrase)));
|
|
5225
|
+
}
|
|
5226
|
+
if (children.length > 0)
|
|
5227
|
+
return { ...item, children };
|
|
5228
|
+
// The group matched but nothing under it did. Returning `children: []` would make it a leaf —
|
|
5229
|
+
// and a leaf with no href — so keep the subtree instead of emptying it.
|
|
5230
|
+
return selfMatches ? item : null;
|
|
5231
|
+
};
|
|
5232
|
+
return items
|
|
5233
|
+
.map(item => keep(item, false))
|
|
5234
|
+
.filter((item) => item !== null);
|
|
5235
|
+
}
|
|
5236
|
+
|
|
5237
|
+
/**
|
|
5238
|
+
* Sorts the top level alphabetically, leaving every nested list in the order the consumer gave.
|
|
5239
|
+
*
|
|
5240
|
+
* Deliberately level 1 only: this exists because a long list of modules is hard to scan, while the
|
|
5241
|
+
* pages inside a module are ordered on purpose. Returns the input untouched when not sorting.
|
|
5242
|
+
*/
|
|
5243
|
+
function sortNavItems(items, alphabetically) {
|
|
5244
|
+
if (!alphabetically)
|
|
5245
|
+
return items;
|
|
5246
|
+
return [...items].sort((first, second) => first.label.localeCompare(second.label));
|
|
5247
|
+
}
|
|
5248
|
+
|
|
5249
|
+
var styles$8 = {"menu":"cw-nav-menu-module__menu__LmeQg","expandIndicator":"cw-nav-menu-module__expandIndicator__TBSdQ","favorites":"cw-nav-menu-module__favorites__Esaqd","favoritesContent":"cw-nav-menu-module__favoritesContent__l5DGG","favoriteStar":"cw-nav-menu-module__favoriteStar__J-jzg","emptyMessage":"cw-nav-menu-module__emptyMessage__-CQNd","skeleton":"cw-nav-menu-module__skeleton__INQqF"};
|
|
5250
|
+
|
|
5251
|
+
const SKELETON_ROW_COUNT = 5;
|
|
5252
|
+
const defaultRenderLink = (item, children) => (jsx("a", { href: item.href, children: children }));
|
|
5253
|
+
/** Sizes only its own icons — content injected via `renderLink` is styled by the consumer. */
|
|
5254
|
+
function CwNavMenu({ items, loading = false, isActive, renderLink = defaultRenderLink, showExpandIndicator = false, search, emptyMessage, sortAlphabetically = false, favoritesSlot, favoritesLabel = "Favorites", favoritesProps, isFavorite, beforeTreeSlot, className, ...navProps }) {
|
|
5255
|
+
const visibleItems = sortNavItems(filterNavItems(items, search), sortAlphabetically);
|
|
5256
|
+
const showEmptyMessage = !loading && Boolean(emptyMessage) && Boolean(search?.trim()) && visibleItems.length === 0;
|
|
5257
|
+
const hasActiveDescendant = (node) => node.children?.some(child => isActive?.(child) || hasActiveDescendant(child)) ?? false;
|
|
5258
|
+
const renderItem = (item, level) => {
|
|
5259
|
+
const children = item.children;
|
|
5260
|
+
if (children && children.length > 0) {
|
|
5261
|
+
return (jsx("li", { children: jsxs("details", { "data-level": level, open: hasActiveDescendant(item) || undefined, children: [jsxs("summary", { children: [item.icon && jsx(CwIcon, { iconId: item.icon, size: level >= 2 ? "small" : "medium" }), item.label, (showExpandIndicator || level >= 2) && (jsx(CwIcon, { iconId: "chevron-down", size: "small", className: styles$8.expandIndicator }))] }), jsx("ul", { children: children.map(child => renderItem(child, level + 1)) })] }) }, item.id));
|
|
5262
|
+
}
|
|
5263
|
+
return (jsx("li", { "data-active": isActive?.(item) ? "true" : undefined, children: renderLink(item, jsxs(Fragment, { children: [item.icon && jsx(CwIcon, { iconId: item.icon, size: "medium" }), item.label, isFavorite?.(item) && jsx(CwIcon, { iconId: "star", size: "small", className: styles$8.favoriteStar })] })) }, item.id));
|
|
5264
|
+
};
|
|
5265
|
+
return (jsxs("nav", { ...navProps, className: [styles$8.menu, className].filter(Boolean).join(" "), "aria-busy": loading || undefined, children: [favoritesSlot && (jsxs("details", { open: true, ...favoritesProps, className: [styles$8.favorites, favoritesProps?.className].filter(Boolean).join(" "), children: [jsxs("summary", { children: [jsx(CwIcon, { iconId: "star", size: "medium" }), favoritesLabel] }), jsx("div", { className: styles$8.favoritesContent, children: favoritesSlot })] })), beforeTreeSlot, jsx("ul", { children: loading
|
|
5266
|
+
? Array.from({ length: SKELETON_ROW_COUNT }, (_unused, index) => (jsx("li", { className: styles$8.skeleton, children: jsx(CwSkeleton, { height: "var(--cw-size-small)", radius: "var(--cw-border-radius-small)" }) }, index)))
|
|
5267
|
+
: visibleItems.map(item => renderItem(item, 1)) }), showEmptyMessage && jsx("p", { className: styles$8.emptyMessage, children: emptyMessage })] }));
|
|
5268
|
+
}
|
|
5269
|
+
|
|
5270
|
+
/**
|
|
5271
|
+
* Pure keyboard-navigation resolver shared by the `CwSearchInput` combobox.
|
|
5272
|
+
* Kept side-effect-free so the arrow/home/end/enter/escape behaviour can be unit
|
|
5273
|
+
* tested without a DOM (the library's vitest runs with `environment: "node"`).
|
|
5274
|
+
*/
|
|
5275
|
+
/**
|
|
5276
|
+
* Resolves a key press against the current highlight into a {@link SearchKeyAction}.
|
|
5277
|
+
* Arrow navigation wraps around; `Enter` selects only when a valid row is highlighted.
|
|
5278
|
+
*
|
|
5279
|
+
* @param key `KeyboardEvent.key` value.
|
|
5280
|
+
* @param currentIndex Currently highlighted option index (`-1` = none).
|
|
5281
|
+
* @param optionsLength Number of options currently in the dropdown.
|
|
5282
|
+
*/
|
|
5283
|
+
function resolveSearchKeyAction(key, currentIndex, optionsLength) {
|
|
5284
|
+
if (optionsLength <= 0)
|
|
5285
|
+
return { type: "none" };
|
|
5286
|
+
switch (key) {
|
|
5287
|
+
case "ArrowDown":
|
|
5288
|
+
return { type: "move", index: currentIndex < optionsLength - 1 ? currentIndex + 1 : 0 };
|
|
5289
|
+
case "ArrowUp":
|
|
5290
|
+
return { type: "move", index: currentIndex > 0 ? currentIndex - 1 : optionsLength - 1 };
|
|
5291
|
+
case "Home":
|
|
5292
|
+
return { type: "move", index: 0 };
|
|
5293
|
+
case "End":
|
|
5294
|
+
return { type: "move", index: optionsLength - 1 };
|
|
5295
|
+
case "Enter":
|
|
5296
|
+
return currentIndex >= 0 && currentIndex < optionsLength
|
|
5297
|
+
? { type: "select", index: currentIndex }
|
|
5298
|
+
: { type: "none" };
|
|
5299
|
+
case "Escape":
|
|
5300
|
+
return { type: "close" };
|
|
5301
|
+
default:
|
|
5302
|
+
return { type: "none" };
|
|
5303
|
+
}
|
|
5037
5304
|
}
|
|
5038
5305
|
|
|
5039
5306
|
/**
|
|
@@ -5054,14 +5321,19 @@ function CwSearchInput(optionsProps) {
|
|
|
5054
5321
|
const [_selectedOption, setSelectedOption] = useState(null);
|
|
5055
5322
|
const [showDropdown, setShowDropdown] = useState(false);
|
|
5056
5323
|
const [isLoading, setIsLoading] = useState(false);
|
|
5324
|
+
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
|
5057
5325
|
const wrapperRef = useRef(null);
|
|
5326
|
+
const inputRef = useRef(null);
|
|
5327
|
+
// Stable ids wiring the combobox input to its listbox popup for assistive tech.
|
|
5328
|
+
const listboxId = useId();
|
|
5329
|
+
const optionId = (index) => `${listboxId}-opt-${index}`;
|
|
5058
5330
|
const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
|
|
5059
5331
|
anchorRef: wrapperRef,
|
|
5060
5332
|
isOpen: showDropdown && filteredOptions.length > 0,
|
|
5061
|
-
onClose: () => setShowDropdown(false),
|
|
5333
|
+
onClose: () => { setShowDropdown(false); setHighlightedIndex(-1); },
|
|
5062
5334
|
});
|
|
5063
5335
|
// Extract props
|
|
5064
|
-
const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, ...otherProps } = optionsProps;
|
|
5336
|
+
const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, autoFocus, ...otherProps } = optionsProps;
|
|
5065
5337
|
// Get direction for data attribute
|
|
5066
5338
|
const direction = alignProps?.flexDirection || "row";
|
|
5067
5339
|
// Make default value selection when loading the component
|
|
@@ -5080,9 +5352,10 @@ function CwSearchInput(optionsProps) {
|
|
|
5080
5352
|
}
|
|
5081
5353
|
}, [defaultValue, selectList]);
|
|
5082
5354
|
const handleInputChange = (event) => {
|
|
5083
|
-
const text = event.
|
|
5355
|
+
const text = event.currentTarget.value;
|
|
5084
5356
|
setSearchText(text);
|
|
5085
5357
|
setShowDropdown(true);
|
|
5358
|
+
setHighlightedIndex(-1);
|
|
5086
5359
|
if (text === "") {
|
|
5087
5360
|
setFilteredOptions(selectList);
|
|
5088
5361
|
setSelectedOption(null);
|
|
@@ -5105,10 +5378,30 @@ function CwSearchInput(optionsProps) {
|
|
|
5105
5378
|
};
|
|
5106
5379
|
const handleInputFocus = () => {
|
|
5107
5380
|
setShowDropdown(true);
|
|
5381
|
+
setHighlightedIndex(-1);
|
|
5108
5382
|
if (searchText === "") {
|
|
5109
5383
|
setFilteredOptions(selectList);
|
|
5110
5384
|
}
|
|
5111
5385
|
};
|
|
5386
|
+
const handleKeyDown = (event) => {
|
|
5387
|
+
if (!(showDropdown && filteredOptions.length > 0))
|
|
5388
|
+
return;
|
|
5389
|
+
const action = resolveSearchKeyAction(event.key, highlightedIndex, filteredOptions.length);
|
|
5390
|
+
switch (action.type) {
|
|
5391
|
+
case "move":
|
|
5392
|
+
event.preventDefault();
|
|
5393
|
+
setHighlightedIndex(action.index);
|
|
5394
|
+
break;
|
|
5395
|
+
case "select":
|
|
5396
|
+
event.preventDefault();
|
|
5397
|
+
handleOptionSelect(filteredOptions[action.index]);
|
|
5398
|
+
break;
|
|
5399
|
+
case "close":
|
|
5400
|
+
setShowDropdown(false);
|
|
5401
|
+
setHighlightedIndex(-1);
|
|
5402
|
+
break;
|
|
5403
|
+
}
|
|
5404
|
+
};
|
|
5112
5405
|
const handleInputBlur = () => {
|
|
5113
5406
|
// Dropdown is closed by useDropdownPortal's outside-click handler.
|
|
5114
5407
|
// Blur alone must not close it — clicking an option would lose focus before the click fires.
|
|
@@ -5120,16 +5413,19 @@ function CwSearchInput(optionsProps) {
|
|
|
5120
5413
|
handleChange(option.id);
|
|
5121
5414
|
}
|
|
5122
5415
|
setFilteredOptions([]);
|
|
5416
|
+
setHighlightedIndex(-1);
|
|
5123
5417
|
};
|
|
5124
5418
|
const handleClearClick = () => {
|
|
5125
5419
|
setSearchText("");
|
|
5126
5420
|
setFilteredOptions([]);
|
|
5127
5421
|
setSelectedOption(null);
|
|
5422
|
+
setHighlightedIndex(-1);
|
|
5128
5423
|
if (handleChange) {
|
|
5129
5424
|
handleChange("");
|
|
5130
5425
|
}
|
|
5426
|
+
inputRef.current?.focus();
|
|
5131
5427
|
};
|
|
5132
|
-
return (jsxs("div", { className: `cw-search-input ${className || ""}`, style: style,
|
|
5428
|
+
return (jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, ...otherProps, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, id: id, type: "text", value: searchText, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled, autoFocus: autoFocus, autoComplete: "off", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": showDropdown && filteredOptions.length > 0, "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 ? optionId(highlightedIndex) : undefined }), isLoading && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsx(CwIcon, { ...iconProps }) : jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: filteredOptions.map((option, index) => (jsx("li", { id: optionId(index), className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
|
|
5133
5429
|
}
|
|
5134
5430
|
|
|
5135
5431
|
/**
|
|
@@ -11292,4 +11588,4 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
|
|
|
11292
11588
|
}, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected crewmember", variant: "icon", icon: "close", color: "neutral" })) : (jsx(CwIcon, { iconId: "person" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: options.map((option, index) => (jsx("li", { className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.value), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.text }, option.value))) }) }))] }));
|
|
11293
11589
|
};
|
|
11294
11590
|
|
|
11295
|
-
export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwButtonSplit, CwButtonSwitch, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDateTimePickerTemporal, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable,
|
|
11591
|
+
export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwButtonSplit, CwButtonSwitch, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDateTimePickerTemporal, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNavMenu, CwNote, CwOption, CwPopoverButton, CwProgress, CwRadioGroup, CwReportModal, CwScheduler, CwSearchAsync, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSkeleton, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PRESET_LIBRARY_TEMPORAL, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, configureCwLoading, eventIsVisible, filterNavItems, filterVisibleEvents, getCwLoadingDefaults, getDefaultDivisions, getEventSizes, getPresetsByKeysTemporal, itemsToMultiFilterTags, sortNavItems, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };
|