@cwellt_software/cwellt-reactjs-lib 1.4.15 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/content/icons/new-cw-icons/NewCwIcons.json +1 -1
  2. package/dist/content/icons/new-cw-icons/css/new-cw-icons.css +260 -824
  3. package/dist/content/icons/new-cw-icons/fonts/NewCwIcons.woff +0 -0
  4. package/dist/index.cjs.js +355 -203
  5. package/dist/index.css +2 -2
  6. package/dist/index.d.ts +133 -48
  7. package/dist/index.es.js +351 -202
  8. package/dist/src/components/control/action/search/CwSearch.d.ts +2 -0
  9. package/dist/src/components/control/action/search/CwSearch.d.ts.map +1 -1
  10. package/dist/src/components/control/action/search/searchKeyboardNavigation.d.ts +35 -0
  11. package/dist/src/components/control/action/search/searchKeyboardNavigation.d.ts.map +1 -0
  12. package/dist/src/components/control/choice/nav-menu/CwNavMenu.d.ts +78 -0
  13. package/dist/src/components/control/choice/nav-menu/CwNavMenu.d.ts.map +1 -0
  14. package/dist/src/components/control/choice/nav-menu/filterNavItems.d.ts +9 -0
  15. package/dist/src/components/control/choice/nav-menu/filterNavItems.d.ts.map +1 -0
  16. package/dist/src/components/control/choice/nav-menu/sortNavItems.d.ts +9 -0
  17. package/dist/src/components/control/choice/nav-menu/sortNavItems.d.ts.map +1 -0
  18. package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts +12 -0
  19. package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts.map +1 -1
  20. package/dist/src/components/control/input/image/CwInputImage.d.ts +17 -2
  21. package/dist/src/components/control/input/image/CwInputImage.d.ts.map +1 -1
  22. package/dist/src/components/display/graphics/icon/CwIcon.d.ts +1 -1
  23. package/dist/src/components/display/graphics/icon/CwIcon.d.ts.map +1 -1
  24. package/dist/src/components/display/graphics/loading/CwLoading.d.ts +3 -14
  25. package/dist/src/components/display/graphics/loading/CwLoading.d.ts.map +1 -1
  26. package/dist/src/components/display/graphics/loading/loadingConfig.d.ts +16 -0
  27. package/dist/src/components/display/graphics/loading/loadingConfig.d.ts.map +1 -0
  28. package/dist/src/index.d.ts +4 -2
  29. package/dist/src/index.d.ts.map +1 -1
  30. package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
  31. package/dist/src/playground/pages/CwFileUploadMultiplePage.d.ts +3 -0
  32. package/dist/src/playground/pages/CwFileUploadMultiplePage.d.ts.map +1 -0
  33. package/dist/src/playground/pages/CwInputImagePage.d.ts.map +1 -1
  34. package/dist/src/playground/pages/CwNavMenuPage.d.ts +3 -0
  35. package/dist/src/playground/pages/CwNavMenuPage.d.ts.map +1 -0
  36. package/dist/src/playground/pages/IconLibraryPage.d.ts +3 -0
  37. package/dist/src/playground/pages/IconLibraryPage.d.ts.map +1 -0
  38. package/dist/src/playground/pages/LoadingPage.d.ts +3 -0
  39. package/dist/src/playground/pages/LoadingPage.d.ts.map +1 -0
  40. package/dist/src/playground/pages/SelectorsPage.d.ts.map +1 -1
  41. package/dist/test/components/control/action/search/searchKeyboardNavigation.test.d.ts +2 -0
  42. package/dist/test/components/control/action/search/searchKeyboardNavigation.test.d.ts.map +1 -0
  43. package/dist/test/components/control/choice/nav-menu/filterNavItems.test.d.ts +2 -0
  44. package/dist/test/components/control/choice/nav-menu/filterNavItems.test.d.ts.map +1 -0
  45. package/dist/test/components/control/choice/nav-menu/sortNavItems.test.d.ts +2 -0
  46. package/dist/test/components/control/choice/nav-menu/sortNavItems.test.d.ts.map +1 -0
  47. package/dist/test/components/control/input/file/fileMatchesAccept.test.d.ts +2 -0
  48. package/dist/test/components/control/input/file/fileMatchesAccept.test.d.ts.map +1 -0
  49. package/dist/test/components/control/input/image/readImageFileAsDataUrl.test.d.ts +2 -0
  50. package/dist/test/components/control/input/image/readImageFileAsDataUrl.test.d.ts.map +1 -0
  51. package/dist/test/components/display/graphics/loading/CwLoading.test.d.ts +2 -0
  52. package/dist/test/components/display/graphics/loading/CwLoading.test.d.ts.map +1 -0
  53. package/package.json +1 -2
package/dist/index.cjs.js CHANGED
@@ -181,12 +181,7 @@ function getContrastColor(color) {
181
181
  return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
182
182
  }
183
183
 
184
- const SVG_ICONS = {
185
- 'sortable-asc': (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsxRuntime.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" }), jsxRuntime.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" })] })),
186
- 'sortable-desc': (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsxRuntime.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" }), jsxRuntime.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" })] })),
187
- };
188
-
189
- var styles$u = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
184
+ var styles$v = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
190
185
 
191
186
  // Constants
192
187
  const margin$1 = 16;
@@ -476,7 +471,7 @@ const CwTooltipManager = () => {
476
471
  if (!state.isVisible || !state.content) {
477
472
  return null;
478
473
  }
479
- return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$u["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
474
+ return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$v["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
480
475
  top: `${tooltipPosition.top}px`,
481
476
  left: `${tooltipPosition.left}px`,
482
477
  opacity: (isPositioned && !isMeasuring) ? 1 : 0,
@@ -557,16 +552,22 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
557
552
  React.useEffect(() => {
558
553
  ensureTooltipManager();
559
554
  }, []);
560
- return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$u["cw-tooltip"], children: children }));
555
+ return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$v["cw-tooltip"], children: children }));
556
+ };
557
+
558
+ const SVG_ICONS = {
559
+ 'sortable-asc': (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsxRuntime.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" }), jsxRuntime.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" })] })),
560
+ 'sortable-desc': (jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsxRuntime.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" }), jsxRuntime.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" })] })),
561
561
  };
562
562
 
563
563
  function CwIcon(props) {
564
- const { iconId, color, size, title, tooltipPosition = 'bottom', ...iconProps } = props;
564
+ const { iconId, color, size, className, title, tooltipPosition = 'bottom', ...iconProps } = props;
565
565
  const getClassName = (baseClass) => {
566
566
  return [
567
567
  baseClass,
568
568
  color && `cw-color-${color}`,
569
- size && `cw-font-size-${size}`
569
+ size && `cw-font-size-${size}`,
570
+ className
570
571
  ].filter(Boolean).join(' ');
571
572
  };
572
573
  let iconElement;
@@ -978,49 +979,39 @@ function CwImageZoom(image) {
978
979
  } }), jsxRuntime.jsx("div", { style: { color: "#fff", fontSize: "1rem", textAlign: "center" }, children: selectedImage.filename && jsxRuntime.jsx("div", { children: selectedImage.filename }) })] }))] }));
979
980
  }
980
981
 
982
+ let defaults = {};
981
983
  /**
982
- * CwLoading
983
- *
984
- * A versatile loading component that shows a spinner with optional text
985
- * and disables the wrapped content while in loading state.
986
- *
987
- * @example
988
- * // Basic usage
989
- * <CwLoading isLoading={isSubmitting}>
990
- * <form>...</form>
991
- * </CwLoading>
992
- *
993
- * // With custom text and size
994
- * <CwLoading
995
- * isLoading={isLoading}
996
- * text="Please wait..."
997
- * size="large"
998
- * >
999
- * <UserProfile />
1000
- * </CwLoading>
984
+ * Register global CwLoading defaults. Call once at app init, before the first render.
985
+ * Merges into any previously configured defaults.
1001
986
  */
1002
- function CwLoading({ isLoading = false, text = '', size = 'regular', iconPosition = 'outside', iconName = 'cwi-plane-solid', animation = 'spin', children }) {
1003
- const iconClasses = `cwi-icons ${iconName || ''}`;
1004
- return (jsxRuntime.jsxs("div", { "aria-busy": isLoading, className: isLoading ? 'cw-loading-container' : '', "data-children": !!children, children: [isLoading && (jsxRuntime.jsxs("div", { className: "cw-loading-content", "data-size": size, "data-animation": animation, children: [jsxRuntime.jsx("div", { className: "cw-loading", "data-icon-position": iconPosition, children: jsxRuntime.jsx("span", { className: iconClasses }) }), text && (jsxRuntime.jsx("p", { children: text }))] })), jsxRuntime.jsx("div", { className: isLoading ? 'cw-loading-disabled-content' : '', children: children })] }));
987
+ function configureCwLoading(next) {
988
+ defaults = { ...defaults, ...next };
989
+ }
990
+ /** Read the currently configured CwLoading defaults. */
991
+ function getCwLoadingDefaults() {
992
+ return defaults;
1005
993
  }
1006
994
 
1007
995
  /**
1008
- * @deprecated since may 2025. Use <CwLoading size="small"> instead.
996
+ * CwLoading — a spinner with optional text that dims the wrapped content while loading.
1009
997
  *
1010
- * This component will be removed in a future release.
998
+ * Icon resolves as `iconName` prop → `getCwLoadingDefaults().icon` → none (neutral ring).
1011
999
  *
1012
1000
  * @example
1013
- * // Instead of:
1014
- * <CwLoadingSmall />
1015
- *
1016
- * // Use:
1017
- * <CwLoading size="small" />
1001
+ * <CwLoading isLoading={isSubmitting}>
1002
+ * <form>...</form>
1003
+ * </CwLoading>
1018
1004
  */
1019
- function CwLoadingSmall(CwelltLoadingAppointements) {
1020
- return (jsxRuntime.jsx("div", { children: CwelltLoadingAppointements.isLoading === true ? (jsxRuntime.jsx("div", { className: "cw-loading-container", children: jsxRuntime.jsx("div", { className: "cw-loading" }) })) : (jsxRuntime.jsx("div", {})) }));
1005
+ function CwLoading({ isLoading = false, text = '', size = 'regular', iconPosition = 'outside', iconName, animation = 'spin', children }) {
1006
+ let overlay = null;
1007
+ if (isLoading) {
1008
+ const resolvedIcon = iconName ?? getCwLoadingDefaults().icon;
1009
+ overlay = (jsxRuntime.jsxs("div", { className: "cw-loading-content", "data-size": size, "data-animation": animation, role: "status", "aria-label": text || 'Loading', children: [jsxRuntime.jsx("div", { className: "cw-loading", "data-icon-position": iconPosition, "data-has-icon": !!resolvedIcon, children: resolvedIcon && jsxRuntime.jsx("span", { className: `cwi-icons ${resolvedIcon}` }) }), text && (jsxRuntime.jsx("p", { children: text }))] }));
1010
+ }
1011
+ return (jsxRuntime.jsxs("div", { "aria-busy": isLoading, className: "cw-loading-container", "data-children": !!children, children: [overlay, jsxRuntime.jsx("div", { className: "cw-loading-disabled-content", children: children })] }));
1021
1012
  }
1022
1013
 
1023
- var styles$t = {"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"};
1014
+ 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"};
1024
1015
 
1025
1016
  // Constants moved outside to prevent recreation
1026
1017
  const margin = 16;
@@ -1143,12 +1134,12 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1143
1134
  const { setTooltipTimeout, clearTooltipTimeout } = useTooltipDelay(() => {
1144
1135
  setIsVisible(true);
1145
1136
  }, showDelay);
1146
- const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$t["cw-generic-tooltip-content"]);
1137
+ const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$u["cw-generic-tooltip-content"]);
1147
1138
  // Memoize tooltip content creation
1148
1139
  const tooltipContent = React.useMemo(() => {
1149
1140
  if (hide || !isVisible || !content)
1150
1141
  return null;
1151
- return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$t["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
1142
+ return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$u["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
1152
1143
  position: 'fixed',
1153
1144
  top: `${tooltipPosition.top}px`,
1154
1145
  left: `${tooltipPosition.left}px`,
@@ -1163,7 +1154,7 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1163
1154
  clearTooltipTimeout();
1164
1155
  setIsVisible(false);
1165
1156
  }, [clearTooltipTimeout]);
1166
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$t["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1157
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$u["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1167
1158
  };
1168
1159
 
1169
1160
  const CwButton = React.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }, ref) {
@@ -1225,7 +1216,7 @@ function CwModal(custModalProps) {
1225
1216
  return (jsxRuntime.jsx("div", { children: custModalProps.modalState && (jsxRuntime.jsxs("div", { className: custModalProps.classNameModalOverlay + " cwelltModalOverlay", children: [jsxRuntime.jsx("div", { className: "cwelltModalOverlayBg", onClick: custModalProps.onCloseModal }), jsxRuntime.jsx(Draggable, { disabled: isModalDisabled, axis: "both", nodeRef: draggableRef, children: jsxRuntime.jsxs("div", { className: custModalProps.classNameModal + " cwelltContainerModal", ref: draggableRef, style: widthModalDef !== "40em" ? modalStyle.widthCustomStyle : modalStyle.widthDefStyle, children: [jsxRuntime.jsxs("div", { className: "cwelltModalHeader", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: [jsxRuntime.jsx("div", { className: "cwelltModalTitle", children: custModalProps.titleModal }), jsxRuntime.jsx("button", { className: "cwelltBtnCloseModal", onClick: custModalProps.onCloseModal, children: jsxRuntime.jsx("span", { className: "cwelltCloseIcon" }) })] }), jsxRuntime.jsx("div", { className: "cwelltModalBody", children: jsxRuntime.jsx("div", { className: "cwelltContainerModalBody", style: { position: "relative" }, children: custModalProps.children }) }), isHide === false ? (jsxRuntime.jsx("footer", { className: "legacy-modal-footer", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: jsxRuntime.jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: custModalProps.onSaveModal, form: custModalProps.formSaveModal, hidden: custModalProps.HideBtnModal, type: custModalProps.HtmlSubmitModal }) })) : (jsxRuntime.jsx("div", { style: { display: "none" } }))] }) })] })) }));
1226
1217
  }
1227
1218
 
1228
- var styles$s = {"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"};
1219
+ 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"};
1229
1220
 
1230
1221
  function CwConfirmationPopup(props) {
1231
1222
  const { isOpen, onConfirm, onCancel, message = "Are you sure you want to proceed?", confirmText = "Confirm", cancelText = "Cancel", placement = 'bottom', children } = props;
@@ -1289,15 +1280,15 @@ function CwConfirmationPopup(props) {
1289
1280
  onCancel();
1290
1281
  }
1291
1282
  };
1292
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderChildren(), isOpen && (jsxRuntime.jsx("div", { className: styles$s.overlayPositioned, onClick: handleOverlayClick, children: jsxRuntime.jsxs("div", { ref: popupRef, className: styles$s.popup, style: {
1283
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderChildren(), isOpen && (jsxRuntime.jsx("div", { className: styles$t.overlayPositioned, onClick: handleOverlayClick, children: jsxRuntime.jsxs("div", { ref: popupRef, className: styles$t.popup, style: {
1293
1284
  position: 'absolute',
1294
1285
  top: `${position.top}px`,
1295
1286
  left: `${position.left}px`,
1296
1287
  transform: 'none'
1297
- }, children: [jsxRuntime.jsx("p", { className: styles$s.message, children: message }), jsxRuntime.jsxs("div", { className: styles$s.buttons, children: [jsxRuntime.jsx("button", { className: `${styles$s.button} ${styles$s.confirmButton}`, onClick: onConfirm, children: confirmText }), jsxRuntime.jsx("button", { className: `${styles$s.button} ${styles$s.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
1288
+ }, children: [jsxRuntime.jsx("p", { className: styles$t.message, children: message }), jsxRuntime.jsxs("div", { className: styles$t.buttons, children: [jsxRuntime.jsx("button", { className: `${styles$t.button} ${styles$t.confirmButton}`, onClick: onConfirm, children: confirmText }), jsxRuntime.jsx("button", { className: `${styles$t.button} ${styles$t.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
1298
1289
  }
1299
1290
 
1300
- var styles$r = {"cw-dialog-main":"cw-dialog-module__cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module__cw-dialog-button-close__9GRd8"};
1291
+ 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"};
1301
1292
 
1302
1293
  // Helper function to parse size values
1303
1294
  const parseSize = (size) => {
@@ -1570,7 +1561,7 @@ const CwDialog = props => {
1570
1561
  }
1571
1562
  }
1572
1563
  }, [open]);
1573
- const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$r["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
1564
+ const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$s["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
1574
1565
  const content = React.useMemo(() => (jsxRuntime.jsx("section", { children: children })), [children]);
1575
1566
  const footer = React.useMemo(() => (jsxRuntime.jsx("footer", { children: customFooter || (jsxRuntime.jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: onSave, tooltipPosition: "top", disabled: disableSave, "data-testid": "cw-dialog-save" })) })), [customFooter, onSave, disableSave]);
1576
1567
  const resizeHandles = React.useMemo(() => size.autoHeight
@@ -1597,7 +1588,7 @@ const CwDialog = props => {
1597
1588
  : `${convertFromPx(size.height, size.heightUnit)}${size.heightUnit}`;
1598
1589
  return { displayWidth, displayHeight };
1599
1590
  }, [size.width, size.height, size.widthUnit, size.heightUnit, size.autoHeight]);
1600
- const dialogContent = (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$r["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
1591
+ const dialogContent = (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$s["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
1601
1592
  left: `${position.x}px`,
1602
1593
  top: `${position.y}px`,
1603
1594
  width: displayDimensions.displayWidth,
@@ -1758,7 +1749,7 @@ function CwAlign(props) {
1758
1749
  }, children: props.children }));
1759
1750
  }
1760
1751
 
1761
- var styles$q = {"card":"cw-card-module__card__HJUT0","clickable":"cw-card-module__clickable__Y-V3X","disabled":"cw-card-module__disabled__0wHh1","loading":"cw-card-module__loading__-fzlx","content":"cw-card-module__content__ma9qy","headerContent":"cw-card-module__headerContent__x4Jfl","footerTags":"cw-card-module__footerTags__80sSW","loadingOverlay":"cw-card-module__loadingOverlay__8-zVV"};
1752
+ var styles$r = {"card":"cw-card-module__card__HJUT0","clickable":"cw-card-module__clickable__Y-V3X","disabled":"cw-card-module__disabled__0wHh1","loading":"cw-card-module__loading__-fzlx","content":"cw-card-module__content__ma9qy","headerContent":"cw-card-module__headerContent__x4Jfl","footerTags":"cw-card-module__footerTags__80sSW","loadingOverlay":"cw-card-module__loadingOverlay__8-zVV"};
1762
1753
 
1763
1754
  /**
1764
1755
  * CwCard - A simple card component for displaying content in a contained format
@@ -1784,11 +1775,11 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1784
1775
  // Construct class names using CSS modules
1785
1776
  const cardClassNames = [
1786
1777
  'cw-card',
1787
- styles$q.card,
1778
+ styles$r.card,
1788
1779
  className,
1789
- clickable ? styles$q.clickable : '',
1790
- disabled ? styles$q.disabled : '',
1791
- isLoading ? styles$q.loading : '',
1780
+ clickable ? styles$r.clickable : '',
1781
+ disabled ? styles$r.disabled : '',
1782
+ isLoading ? styles$r.loading : '',
1792
1783
  ].filter(Boolean).join(' ');
1793
1784
  // Handle click event when card is clickable
1794
1785
  const handleClick = () => {
@@ -1805,15 +1796,15 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1805
1796
  // Determine if footer should be rendered
1806
1797
  const hasFooter = hasChips || footer || (hasActions && resolvedDirection === "row");
1807
1798
  // Actions component to reuse
1808
- const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsxs("div", { className: styles$q.actions, children: [extraActions ?? null, onEdit && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) : null;
1799
+ const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsxs("div", { className: styles$r.actions, children: [extraActions ?? null, onEdit && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) : null;
1809
1800
  return (jsxRuntime.jsxs("div", { ...(id && { id }), className: cardClassNames, ...(style && { style }), ...(clickable && {
1810
1801
  role: 'button',
1811
1802
  tabIndex: 0,
1812
1803
  onClick: handleClick,
1813
- }), "data-variant": variant, "data-direction": resolvedDirection, children: [hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$q.headerContent, "data-align": resolvedAlign, children: [title && jsxRuntime.jsx("h5", { children: title }), subtitle && jsxRuntime.jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] })), jsxRuntime.jsx("div", { className: styles$q.content, children: children }), hasFooter && (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$q.footerTags, children: chips.map((chip, index) => (jsxRuntime.jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$q.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsxRuntime.jsx("div", { className: styles$q.footerContent, children: footer }))] })), resolvedDirection === "row" && ActionsComponent, isLoading && (jsxRuntime.jsx("div", { className: styles$q.loadingOverlay, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
1804
+ }), "data-variant": variant, "data-direction": resolvedDirection, children: [hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$r.headerContent, "data-align": resolvedAlign, children: [title && jsxRuntime.jsx("h5", { children: title }), subtitle && jsxRuntime.jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] })), jsxRuntime.jsx("div", { className: styles$r.content, children: children }), hasFooter && (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$r.footerTags, children: chips.map((chip, index) => (jsxRuntime.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 && (jsxRuntime.jsx("div", { className: styles$r.footerContent, children: footer }))] })), resolvedDirection === "row" && ActionsComponent, isLoading && (jsxRuntime.jsx("div", { className: styles$r.loadingOverlay, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
1814
1805
  };
1815
1806
 
1816
- var styles$p = {"cardContainer":"cw-card-list-module__cardContainer__l3YEh","pagination":"cw-card-list-module__pagination__5Ay78","pageInfo":"cw-card-list-module__pageInfo__uiMel","loading":"cw-card-list-module__loading__cYpND","emptyState":"cw-card-list-module__emptyState__RlqiS"};
1807
+ var styles$q = {"cardContainer":"cw-card-list-module__cardContainer__l3YEh","pagination":"cw-card-list-module__pagination__5Ay78","pageInfo":"cw-card-list-module__pageInfo__uiMel","loading":"cw-card-list-module__loading__cYpND","emptyState":"cw-card-list-module__emptyState__RlqiS"};
1817
1808
 
1818
1809
  /**
1819
1810
  * Option to display in the CwSelect
@@ -1908,10 +1899,10 @@ function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', default
1908
1899
  icon: sortDirection === 'asc' ? 'arrow-up' : 'arrow-down',
1909
1900
  onClick: () => setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'),
1910
1901
  title: `Sort ${sortDirection === 'asc' ? 'descending' : 'ascending'}`,
1911
- }, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsxRuntime.jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsxRuntime.jsx("div", { className: styles$p.loading, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$p.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$p.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$p.pagination, children: [jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxRuntime.jsxs("span", { className: styles$p.pageInfo, children: [currentPage, " / ", totalPages] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
1902
+ }, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsxRuntime.jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsxRuntime.jsx("div", { className: styles$q.loading, children: jsxRuntime.jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$q.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$q.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$q.pagination, children: [jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxRuntime.jsxs("span", { className: styles$q.pageInfo, children: [currentPage, " / ", totalPages] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
1912
1903
  }
1913
1904
 
1914
- var styles$o = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
1905
+ var styles$p = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
1915
1906
 
1916
1907
  /**
1917
1908
  *
@@ -1928,7 +1919,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
1928
1919
  setVisible_accordionBody(!isVisible_accordionBody);
1929
1920
  };
1930
1921
  // #endregion
1931
- return (jsxRuntime.jsxs("div", { className: styles$o["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxRuntime.jsxs("header", { onClick: () => showAccordionBody(), children: [jsxRuntime.jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsxRuntime.jsx("button", { className: "cw-button-icon" })] }), jsxRuntime.jsx("div", { className: styles$o["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
1922
+ return (jsxRuntime.jsxs("div", { className: styles$p["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxRuntime.jsxs("header", { onClick: () => showAccordionBody(), children: [jsxRuntime.jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsxRuntime.jsx("button", { className: "cw-button-icon" })] }), jsxRuntime.jsx("div", { className: styles$p["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
1932
1923
  }
1933
1924
 
1934
1925
  /**
@@ -2186,7 +2177,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
2186
2177
  }, min: 1, max: totalPages }), jsxRuntime.jsx("span", { children: "/" }), jsxRuntime.jsx("span", { children: totalPages }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2187
2178
  }
2188
2179
 
2189
- var styles$n = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","skeletonRow":"cw-sortable-table-module__skeletonRow__vyD0M","skeleton":"cw-sortable-table-module__skeleton__QGXAD","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
2180
+ var styles$o = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","skeletonRow":"cw-sortable-table-module__skeletonRow__vyD0M","skeleton":"cw-sortable-table-module__skeleton__QGXAD","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
2190
2181
 
2191
2182
  /**
2192
2183
  * Hook that provides state management for CwSortableTable.
@@ -2249,9 +2240,9 @@ function useSortableTable(initialItems) {
2249
2240
  }
2250
2241
 
2251
2242
  // ─── Drop indicator row ───────────────────────────────────────────────────────
2252
- const DropIndicatorRow = ({ colSpan }) => (jsxRuntime.jsx("tr", { className: styles$n.dropIndicator, "aria-hidden": true, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", {}) }) }));
2243
+ const DropIndicatorRow = ({ colSpan }) => (jsxRuntime.jsx("tr", { className: styles$o.dropIndicator, "aria-hidden": true, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", {}) }) }));
2253
2244
  // ─── Loading skeleton ─────────────────────────────────────────────────────────
2254
- const LoadingRows = ({ colSpan }) => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 4 }).map((_, i) => (jsxRuntime.jsx("tr", { className: styles$n.skeletonRow, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", { className: styles$n.skeleton }) }) }, i))) }));
2245
+ const LoadingRows = ({ colSpan }) => (jsxRuntime.jsx(jsxRuntime.Fragment, { children: Array.from({ length: 4 }).map((_, i) => (jsxRuntime.jsx("tr", { className: styles$o.skeletonRow, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", { className: styles$o.skeleton }) }) }, i))) }));
2255
2246
  // ─── Component ────────────────────────────────────────────────────────────────
2256
2247
  /**
2257
2248
  * CwSortableTable
@@ -2338,11 +2329,11 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
2338
2329
  return items.map((item, index) => {
2339
2330
  const key = item[rowKey];
2340
2331
  const isDragging = draggedItem?.[rowKey] === key;
2341
- return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols })), jsxRuntime.jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$n.dragging : "", children: [showHandle && (jsxRuntime.jsx("td", { className: "cw-table-col-action", children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsxRuntime.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 && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
2332
+ return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols })), jsxRuntime.jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$o.dragging : "", children: [showHandle && (jsxRuntime.jsx("td", { className: "cw-table-col-action", children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsxRuntime.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 && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
2342
2333
  });
2343
2334
  };
2344
2335
  // ── Render ──────────────────────────────────────────────────────────────
2345
- return (jsxRuntime.jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxRuntime.jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [showHandle && jsxRuntime.jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsxRuntime.jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxRuntime.jsxs("footer", { className: styles$n.saveBar, children: [jsxRuntime.jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsxRuntime.jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
2336
+ return (jsxRuntime.jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxRuntime.jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [showHandle && jsxRuntime.jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsxRuntime.jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxRuntime.jsxs("footer", { className: styles$o.saveBar, children: [jsxRuntime.jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsxRuntime.jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
2346
2337
  }
2347
2338
 
2348
2339
  /**
@@ -2541,7 +2532,7 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
2541
2532
  }, min: 1, max: totalPages }), jsxRuntime.jsx("span", { children: "/" }), jsxRuntime.jsx("span", { children: totalPages }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2542
2533
  }
2543
2534
 
2544
- var styles$m = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","badge":"cw-tabs-module__badge__AmVxW","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2535
+ 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"};
2545
2536
 
2546
2537
  const TabIcon = ({ icon }) => {
2547
2538
  if (!icon)
@@ -2591,7 +2582,7 @@ function CwTabs(CwTabsProps) {
2591
2582
  const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
2592
2583
  ? { minWidth: CwTabsProps.tabsListWidth }
2593
2584
  : undefined;
2594
- return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$m['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxRuntime.jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsxRuntime.jsx("span", { className: styles$m['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsxRuntime.jsx("div", { className: styles$m['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2585
+ return (jsxRuntime.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: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxRuntime.jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsxRuntime.jsx("span", { className: styles$n['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsxRuntime.jsx("div", { className: styles$n['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2595
2586
  }
2596
2587
 
2597
2588
  /**
@@ -2618,7 +2609,7 @@ const CwExpandable = ({ briefing, onToggle, onOpen, onClose, children, ...detail
2618
2609
  return (jsxRuntime.jsxs("details", { ref: myRef, ...detailsProps, className: "cw-expandable", children: [jsxRuntime.jsx("summary", { children: briefing }), children && jsxRuntime.jsx("section", { children: children })] }));
2619
2610
  };
2620
2611
 
2621
- var styles$l = {"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","detail-empty":"cw-master-detail-module__detail-empty__KFScK"};
2612
+ 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","detail-empty":"cw-master-detail-module__detail-empty__KFScK"};
2622
2613
 
2623
2614
  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, }) => {
2624
2615
  const [masterWidth, setMasterWidth] = React.useState(initialWidth);
@@ -2654,10 +2645,10 @@ const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, de
2654
2645
  document.body.style.userSelect = '';
2655
2646
  };
2656
2647
  }, [isResizing, minMasterWidth, maxMasterWidth]);
2657
- const rootClassName = [styles$l['cw-master-detail'], className].filter(Boolean).join(' ');
2658
- return (jsxRuntime.jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxRuntime.jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsxRuntime.jsx("search", { children: jsxRuntime.jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsxRuntime.jsx("header", { children: masterHeader })), jsxRuntime.jsx("ul", { children: items.map((item) => (jsxRuntime.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 && (jsxRuntime.jsx("footer", { children: masterFooter }))] }), resizable && (jsxRuntime.jsx("div", { className: styles$l.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsxRuntime.jsx("section", { className: styles$l.detail, children: selectedKey && detailContent
2648
+ const rootClassName = [styles$m['cw-master-detail'], className].filter(Boolean).join(' ');
2649
+ return (jsxRuntime.jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxRuntime.jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsxRuntime.jsx("search", { children: jsxRuntime.jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsxRuntime.jsx("header", { children: masterHeader })), jsxRuntime.jsx("ul", { children: items.map((item) => (jsxRuntime.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 && (jsxRuntime.jsx("footer", { children: masterFooter }))] }), resizable && (jsxRuntime.jsx("div", { className: styles$m.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsxRuntime.jsx("section", { className: styles$m.detail, children: selectedKey && detailContent
2659
2650
  ? detailContent
2660
- : (jsxRuntime.jsx("div", { className: styles$l['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
2651
+ : (jsxRuntime.jsx("div", { className: styles$m['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
2661
2652
  };
2662
2653
 
2663
2654
  /**
@@ -2682,7 +2673,7 @@ const CwKeyValueList = ({ items, className = "", emptyValue = "-", direction = "
2682
2673
  : emptyValue })] }, item.key))) }));
2683
2674
  };
2684
2675
 
2685
- var styles$k = {"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"};
2676
+ 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"};
2686
2677
 
2687
2678
  function CwSortableList({ items, onReorder, renderItem, className = '', movedItems = new Set(), emptyMessage = "No elements to show", readOnly = false, maxHeight = "300px", }) {
2688
2679
  const [draggedItem, setDraggedItem] = React.useState(null);
@@ -2745,15 +2736,15 @@ function CwSortableList({ items, onReorder, renderItem, className = '', movedIte
2745
2736
  }
2746
2737
  };
2747
2738
  if (items.length === 0) {
2748
- return (jsxRuntime.jsx("div", { className: `${styles$k.sortableList} ${styles$k.emptyState} ${className}`, children: jsxRuntime.jsx("div", { className: styles$k.emptyMessage, children: emptyMessage }) }));
2739
+ return (jsxRuntime.jsx("div", { className: `${styles$l.sortableList} ${styles$l.emptyState} ${className}`, children: jsxRuntime.jsx("div", { className: styles$l.emptyMessage, children: emptyMessage }) }));
2749
2740
  }
2750
- return (jsxRuntime.jsx("div", { className: `${styles$k.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
2741
+ return (jsxRuntime.jsx("div", { className: `${styles$l.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
2751
2742
  const { title, extraContent, actions, showHandle = true, expandedContent } = renderItem(item);
2752
2743
  const isDragging = draggedItem?.id === item.id;
2753
2744
  const isMoved = movedItems.has(item.id);
2754
2745
  const canExpand = Boolean(expandedContent);
2755
2746
  const isExpanded = expandedItems.has(item.id);
2756
- return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && jsxRuntime.jsx("div", { className: styles$k.dropIndicator }), jsxRuntime.jsxs("div", { className: `${styles$k.sortableItem} ${isDragging ? styles$k.dragging : ''} ${isMoved ? styles$k.moved : ''} ${readOnly ? styles$k.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxRuntime.jsxs("header", { children: [canExpand ? (jsxRuntime.jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsxRuntime.jsx("div", { className: styles$k.sortableHandle, children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxRuntime.jsxs("div", { className: styles$k.sortableContent, children: [jsxRuntime.jsx("div", { className: styles$k.sortableTitle, children: title }), extraContent && jsxRuntime.jsx("div", { className: styles$k.sortableExtraContent, children: extraContent })] }), jsxRuntime.jsx("div", { className: styles$k.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsxRuntime.jsx("div", { className: styles$k.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsxRuntime.jsx("div", { className: styles$k.dropIndicator }))] }, item.id));
2747
+ return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && jsxRuntime.jsx("div", { className: styles$l.dropIndicator }), jsxRuntime.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: [jsxRuntime.jsxs("header", { children: [canExpand ? (jsxRuntime.jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsxRuntime.jsx("div", { className: styles$l.sortableHandle, children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxRuntime.jsxs("div", { className: styles$l.sortableContent, children: [jsxRuntime.jsx("div", { className: styles$l.sortableTitle, children: title }), extraContent && jsxRuntime.jsx("div", { className: styles$l.sortableExtraContent, children: extraContent })] }), jsxRuntime.jsx("div", { className: styles$l.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsxRuntime.jsx("div", { className: styles$l.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsxRuntime.jsx("div", { className: styles$l.dropIndicator }))] }, item.id));
2757
2748
  }) }));
2758
2749
  }
2759
2750
 
@@ -2879,60 +2870,9 @@ const CwTableGrouped = props => {
2879
2870
  group.rows.map((child, j) => (jsxRuntime.jsx("tr", { "data-row": true, "data-row-last-of-group": j == group.rows.length - 1, children: child.cells.map((cell, k) => (jsxRuntime.jsx("td", { children: cell.content }, k))) }, j)))] }, i))) }), jsxRuntime.jsx("tfoot", {})] }) }));
2880
2871
  };
2881
2872
 
2882
- function CwFileUpload(fileUploadProps) {
2883
- const [previewURL, setPreviewURL] = React.useState("");
2884
- const [error, setError] = React.useState(null);
2885
- const [_selectedFileName, setSelectedFileName] = React.useState("");
2886
- const [_currentHexContent, setCurrentHexContent] = React.useState("");
2887
- React.useEffect(() => {
2888
- // If there is hexadecimal preview content, set the Preview URL
2889
- if (fileUploadProps.file?.Bindata) {
2890
- setPreviewURL(`data:image/png;base64,${fileUploadProps.file.Bindata}`);
2891
- }
2892
- }, [fileUploadProps.file?.Bindata]);
2893
- const handleFileChange = (event) => {
2894
- const file = event.target.files?.[0];
2895
- setSelectedFileName(file?.name ?? "");
2896
- if (file) {
2897
- const allowedExts = fileUploadProps.accept.split(',').map(ext => ext.trim().replace('.', '').toLowerCase());
2898
- const fileExt = file.name.split('.').pop()?.toLowerCase() ?? "";
2899
- if (!allowedExts.includes(fileExt)) {
2900
- setError(`Invalid file type. Only ${fileUploadProps.acceptString} files are allowed.`);
2901
- setPreviewURL("");
2902
- return;
2903
- }
2904
- setError(null);
2905
- const reader = new FileReader();
2906
- reader.onloadend = () => {
2907
- if (typeof reader.result === "string") {
2908
- const hexContent = arrayBufferToHex(reader.result);
2909
- setCurrentHexContent(hexContent);
2910
- setPreviewURL(reader.result);
2911
- setCurrentHexContent(arrayBufferToHex(reader.result));
2912
- // Call function to store hexadecimal content
2913
- fileUploadProps.onSaveHexContent(arrayBufferToHex(reader.result));
2914
- }
2915
- };
2916
- reader.readAsDataURL(file);
2917
- }
2918
- };
2919
- // Function to convert the image buffer into hexadecimal content
2920
- const arrayBufferToHex = (dataUrl) => {
2921
- // Decodes the base64 of the URL data
2922
- const base64 = dataUrl.split(",")[1];
2923
- const binary = atob(base64);
2924
- let hex = "";
2925
- for (let i = 0; i < binary.length; i++) {
2926
- hex += binary.charCodeAt(i).toString(16).padStart(2, "0");
2927
- }
2928
- return hex;
2929
- };
2930
- return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: "row", children: [jsxRuntime.jsx("input", { className: "cw-button", type: "file", accept: fileUploadProps.accept, readOnly: true, placeholder: "No file selected...", onChange: handleFileChange }), previewURL && (jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsx("img", { src: previewURL, alt: "Preview", style: { maxWidth: "200px", maxHeight: "200px" } }) }))] }), error && jsxRuntime.jsx("div", { className: "row error", children: error }), jsxRuntime.jsx("div", { className: "row", children: jsxRuntime.jsxs("label", { children: ["Please note: File/image has to be in ", fileUploadProps.acceptString, " format", fileUploadProps.sizeString && `, ${fileUploadProps.sizeString}`] }) })] }));
2931
- }
2932
-
2933
- 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"};
2873
+ 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"};
2934
2874
 
2935
- const DEFAULT_LABELS = {
2875
+ const DEFAULT_LABELS$1 = {
2936
2876
  uploadDisabled: 'Upload disabled',
2937
2877
  clickToUpload: 'Click to upload or drag and drop',
2938
2878
  acceptedFiles: (accept) => `Accepted files: ${accept}`,
@@ -2940,6 +2880,7 @@ const DEFAULT_LABELS = {
2940
2880
  allTypesAccepted: 'All file types accepted',
2941
2881
  changeFile: 'Change File',
2942
2882
  clearAll: 'Clear all',
2883
+ upload: 'Upload',
2943
2884
  addMoreFiles: 'Add More Files',
2944
2885
  filesSelected: (count) => `${count} file${count !== 1 ? 's' : ''} selected`,
2945
2886
  fileTooLarge: (name, maxSize) => `File "${name}" is too large. Maximum size allowed is ${maxSize}MB.`,
@@ -2947,11 +2888,38 @@ const DEFAULT_LABELS = {
2947
2888
  invalidMimeType: (name, types) => `File "${name}" has an invalid MIME type. Allowed types: ${types}`,
2948
2889
  alreadySelected: (name) => `File "${name}" is already selected.`,
2949
2890
  };
2891
+ /**
2892
+ * Checks a file against an `accept` string (comma-separated tokens). A token can be a dotted
2893
+ * extension (".pdf"), an exact MIME type ("application/pdf"), a wildcard MIME ("image" + slash + "star"),
2894
+ * or a bare "star" / "star-slash-star" for anything. Returns true if the file matches ANY token
2895
+ * (or if `accept` is empty).
2896
+ */
2897
+ function fileMatchesAccept(fileName, fileType, accept) {
2898
+ const tokens = accept.split(',').map(token => token.trim().toLowerCase()).filter(Boolean);
2899
+ if (tokens.length === 0) {
2900
+ return true;
2901
+ }
2902
+ const fileExtension = '.' + (fileName.split('.').pop()?.toLowerCase() ?? '');
2903
+ const mimeType = fileType.toLowerCase();
2904
+ return tokens.some(token => {
2905
+ if (token === '*' || token === '*/*') {
2906
+ return true;
2907
+ }
2908
+ if (token.startsWith('.')) {
2909
+ return token === fileExtension;
2910
+ }
2911
+ if (token.endsWith('/*')) {
2912
+ const prefix = token.slice(0, token.indexOf('/') + 1);
2913
+ return mimeType.startsWith(prefix);
2914
+ }
2915
+ return token === mimeType;
2916
+ });
2917
+ }
2950
2918
  function CwFileUploadMultiple(fileUploadProps) {
2951
2919
  const fileInputRef = React.useRef(null);
2952
2920
  const [selectedFiles, setSelectedFiles] = React.useState([]);
2953
2921
  const [existingFile, setExistingFile] = React.useState(fileUploadProps.initialFileName);
2954
- const labels = { ...DEFAULT_LABELS, ...fileUploadProps.labels };
2922
+ const labels = { ...DEFAULT_LABELS$1, ...fileUploadProps.labels };
2955
2923
  React.useEffect(() => {
2956
2924
  setExistingFile(fileUploadProps.initialFileName);
2957
2925
  }, [fileUploadProps.initialFileName]);
@@ -2969,17 +2937,9 @@ function CwFileUploadMultiple(fileUploadProps) {
2969
2937
  };
2970
2938
  }
2971
2939
  }
2972
- // Validate file type by extension (based in accept)
2940
+ // Validate file type against accept (dotted extensions, exact MIME, wildcard MIME, or *)
2973
2941
  if (fileUploadProps.accept) {
2974
- const acceptedExtensions = fileUploadProps.accept.split(',').map(ext => ext.trim().toLowerCase());
2975
- const fileExtension = '.' + file.name.split('.').pop()?.toLowerCase();
2976
- const isExtensionValid = acceptedExtensions.some(ext => {
2977
- if (ext.startsWith('.')) {
2978
- return ext === fileExtension;
2979
- }
2980
- return false;
2981
- });
2982
- if (!isExtensionValid) {
2942
+ if (!fileMatchesAccept(file.name, file.type, fileUploadProps.accept)) {
2983
2943
  return {
2984
2944
  isValid: false,
2985
2945
  error: labels.invalidFormat(file.name, fileUploadProps.accept)
@@ -3004,7 +2964,7 @@ function CwFileUploadMultiple(fileUploadProps) {
3004
2964
  const errors = [];
3005
2965
  for (const file of fileArray) {
3006
2966
  // Check if the file already exists (by name and size)
3007
- const isDuplicate = existingFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
2967
+ const isDuplicate = validFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
3008
2968
  if (isDuplicate) {
3009
2969
  errors.push(labels.alreadySelected(file.name));
3010
2970
  continue;
@@ -3022,8 +2982,7 @@ function CwFileUploadMultiple(fileUploadProps) {
3022
2982
  fileUploadProps.onError(errors.join('\n'));
3023
2983
  }
3024
2984
  else {
3025
- console.error(errors.join('\n'));
3026
- alert(errors.join('\n')); // Fallback if there is no onError
2985
+ CwDisplayMessage(errors.join('\n'), exports.CwMessageType.ERROR);
3027
2986
  }
3028
2987
  }
3029
2988
  // If not multiple, only take the first valid file (replace)
@@ -3097,12 +3056,20 @@ function CwFileUploadMultiple(fileUploadProps) {
3097
3056
  }
3098
3057
  }
3099
3058
  };
3100
- return (jsxRuntime.jsxs("div", { className: `${styles$j.fileUploadContainer} ${fileUploadProps.className}`, children: [jsxRuntime.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$j.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxRuntime.jsxs("div", { className: `${styles$j.uploadArea} ${fileUploadProps.disabled ? styles$j.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsx("p", { className: `${styles$j.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxRuntime.jsxs("p", { className: `${styles$j.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxRuntime.jsxs("div", { className: styles$j.filesContainer, children: [jsxRuntime.jsxs("div", { className: styles$j.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$j.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$j.fileExtension, children: getFileExtension(existingFile) })] }), jsxRuntime.jsx("div", { className: styles$j.fileInfo, children: jsxRuntime.jsx("p", { className: styles$j.fileName, children: existingFile }) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
3059
+ return (jsxRuntime.jsxs("div", { className: `${styles$k.fileUploadContainer} ${fileUploadProps.className}`, children: [jsxRuntime.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 ? (jsxRuntime.jsxs("div", { className: `${styles$k.uploadArea} ${fileUploadProps.disabled ? styles$k.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsx("p", { className: `${styles$k.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxRuntime.jsxs("p", { className: `${styles$k.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxRuntime.jsxs("div", { className: styles$k.filesContainer, children: [jsxRuntime.jsxs("div", { className: styles$k.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$k.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$k.fileExtension, children: getFileExtension(existingFile) })] }), jsxRuntime.jsx("div", { className: styles$k.fileInfo, children: jsxRuntime.jsx("p", { className: styles$k.fileName, children: existingFile }) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
3101
3060
  setExistingFile(undefined);
3102
3061
  if (fileUploadProps.onSelect) {
3103
3062
  fileUploadProps.onSelect(null);
3104
3063
  }
3105
- }, disabled: fileUploadProps.disabled, className: styles$j.smallButton })] }), jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxRuntime.jsxs("div", { className: styles$j.filesContainer, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsxRuntime.jsx("small", { className: styles$j.filesCount, children: labels.filesSelected(selectedFiles.length) }), !fileUploadProps.hideClearAll && (jsxRuntime.jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] }), selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: styles$j.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$j.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$j.fileExtension, children: getFileExtension(file.name) })] }), jsxRuntime.jsxs("div", { className: styles$j.fileInfo, children: [jsxRuntime.jsx("p", { className: styles$j.fileName, children: file.name }), jsxRuntime.jsxs("p", { className: styles$j.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$j.smallButton })] }, index))), fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
3064
+ }, disabled: fileUploadProps.disabled, className: styles$k.smallButton })] }), jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxRuntime.jsxs("div", { className: styles$k.filesContainer, children: [jsxRuntime.jsxs("header", { className: "cw-flex-row cw-align-between-center cw-flex-wrap", children: [jsxRuntime.jsx("small", { className: styles$k.filesCount, children: fileUploadProps.statusText ?? labels.filesSelected(selectedFiles.length) }), jsxRuntime.jsxs("div", { className: "cw-flex-row", children: [fileUploadProps.onConfirm && selectedFiles.length > 0 && (jsxRuntime.jsx(CwButton, { onClick: () => {
3065
+ let files = fileInputRef.current?.files ?? null;
3066
+ if (!files) {
3067
+ const dataTransfer = new DataTransfer();
3068
+ selectedFiles.forEach(file => dataTransfer.items.add(file));
3069
+ files = dataTransfer.files;
3070
+ }
3071
+ fileUploadProps.onConfirm?.(files);
3072
+ }, disabled: fileUploadProps.disabled || fileUploadProps.confirmDisabled, icon: "upload", text: fileUploadProps.confirmLabel ?? labels.upload })), !fileUploadProps.hideClearAll && (jsxRuntime.jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] })] }), selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: styles$k.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$k.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$k.fileExtension, children: getFileExtension(file.name) })] }), jsxRuntime.jsxs("div", { className: styles$k.fileInfo, children: [jsxRuntime.jsx("p", { className: styles$k.fileName, children: file.name }), jsxRuntime.jsxs("p", { className: styles$k.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$k.smallButton })] }, `${file.name}-${file.size}`))), fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
3106
3073
  }
3107
3074
 
3108
3075
  function CwInput(CwInputProps) {
@@ -3143,7 +3110,7 @@ function CwDigit(props) {
3143
3110
  return (jsxRuntime.jsx("div", { className: "cw-input-text", children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsx("input", { type: "number", ...inputProps }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] }) }));
3144
3111
  }
3145
3112
 
3146
- var styles$i = {"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"};
3113
+ 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"};
3147
3114
 
3148
3115
  const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }) => {
3149
3116
  const [rgb, setRgb] = React.useState({ r: 255, g: 255, b: 255 });
@@ -3346,13 +3313,13 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
3346
3313
  // Calculate background color for the main area based on current hue
3347
3314
  const hueColor = hsvToRgb(hsv.h, 100, 100);
3348
3315
  const hueHex = rgbToHex(hueColor.r, hueColor.g, hueColor.b);
3349
- return (jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsxRuntime.jsx("div", { className: styles$i.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsxRuntime.jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsxRuntime.jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsxRuntime.jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxRuntime.jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "R:" }), jsxRuntime.jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "G:" }), jsxRuntime.jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "B:" }), jsxRuntime.jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxRuntime.jsxs("div", { className: styles$i.colorPickerInteractiveArea, children: [jsxRuntime.jsx("div", { className: styles$i.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsxRuntime.jsx("div", { className: styles$i.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxRuntime.jsxs("div", { className: styles$i.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxRuntime.jsxs("div", { className: styles$i.colorAreaOverlay, children: [jsxRuntime.jsx("div", { className: styles$i.hueBackground, style: { backgroundColor: hueHex } }), jsxRuntime.jsx("div", { className: styles$i.whiteGradient }), jsxRuntime.jsx("div", { className: styles$i.blackGradient })] }), jsxRuntime.jsx("div", { className: styles$i.colorAreaCursor, style: {
3316
+ return (jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsxRuntime.jsx("div", { className: styles$j.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsxRuntime.jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsxRuntime.jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsxRuntime.jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxRuntime.jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "R:" }), jsxRuntime.jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "G:" }), jsxRuntime.jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "B:" }), jsxRuntime.jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxRuntime.jsxs("div", { className: styles$j.colorPickerInteractiveArea, children: [jsxRuntime.jsx("div", { className: styles$j.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsxRuntime.jsx("div", { className: styles$j.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxRuntime.jsxs("div", { className: styles$j.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxRuntime.jsxs("div", { className: styles$j.colorAreaOverlay, children: [jsxRuntime.jsx("div", { className: styles$j.hueBackground, style: { backgroundColor: hueHex } }), jsxRuntime.jsx("div", { className: styles$j.whiteGradient }), jsxRuntime.jsx("div", { className: styles$j.blackGradient })] }), jsxRuntime.jsx("div", { className: styles$j.colorAreaCursor, style: {
3350
3317
  left: `${hsv.s}%`,
3351
3318
  top: `${100 - hsv.v}%`
3352
3319
  } })] })] })] }));
3353
3320
  };
3354
3321
 
3355
- var styles$h = {"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"};
3322
+ 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"};
3356
3323
 
3357
3324
  const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, }) => {
3358
3325
  const [isOpen, setIsOpen] = React.useState(false);
@@ -3485,11 +3452,11 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
3485
3452
  break;
3486
3453
  }
3487
3454
  };
3488
- return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$h.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps })), jsxRuntime.jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$h.selectColor} ${disabled ? styles$h.disabled : ''} ${readOnly ? styles$h.readOnly : ''}`, style: {
3455
+ return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$i.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps })), jsxRuntime.jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
3489
3456
  width,
3490
3457
  height,
3491
3458
  backgroundColor: value,
3492
- }, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: dropdownRef, className: styles$h.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsxRuntime.jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
3459
+ }, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: dropdownRef, className: styles$i.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsxRuntime.jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
3493
3460
  };
3494
3461
 
3495
3462
  /**
@@ -3739,31 +3706,63 @@ function CwInputDateText(props) {
3739
3706
  return (jsxRuntime.jsx("div", { className: "cw-input-date-text", children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { children: [jsxRuntime.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 }), jsxRuntime.jsxs("span", { children: [jsxRuntime.jsx(CwIcon, { iconId: "calendar" }), jsxRuntime.jsx("input", { type: "date", disabled: disabled, onChange: onChangeInputDate, readOnly: readOnly, ref: dateInputRef, tabIndex: -1, value: date, ...inputProps })] })] }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] }) }));
3740
3707
  }
3741
3708
 
3742
- var styles$g = {"dropZone":"cw-input-image-module__dropZone__ygrGu"};
3709
+ 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"};
3743
3710
 
3711
+ const DEFAULT_LABELS = {
3712
+ dropImageHere: "Drop image here",
3713
+ paste: "Paste",
3714
+ browse: "Browse",
3715
+ acceptedFormats: (formats) => `(${formats})`,
3716
+ clipboardError: "Failed to read from clipboard. Ensure the app has permission to access the clipboard.",
3717
+ invalidType: (formats) => `Unsupported file type. Allowed: ${formats}`,
3718
+ readError: "Could not read the image file.",
3719
+ };
3720
+ /** Reads a file/blob into a base64 data URL (persistable, no blob URL to revoke). */
3721
+ function readImageFileAsDataUrl(file) {
3722
+ return new Promise((resolve, reject) => {
3723
+ const reader = new FileReader();
3724
+ reader.onload = () => resolve(reader.result);
3725
+ reader.onerror = () => reject(reader.error ?? new Error("Failed to read file"));
3726
+ reader.readAsDataURL(file);
3727
+ });
3728
+ }
3744
3729
  function CwInputImage(props) {
3745
3730
  const [_uploadedImage, setUploadedImage] = React.useState(null);
3746
3731
  const inputRef = React.useRef(null);
3747
- const { allowedImageFormats, onChange, ...inputProps } = props;
3732
+ const { allowedImageFormats, onChange, onError, labels: labelsProp, size, ...inputProps } = props;
3748
3733
  const allowedFormats = allowedImageFormats || ["image/jpeg", "image/png", "image/gif"];
3734
+ const labels = { ...DEFAULT_LABELS, ...labelsProp };
3749
3735
  const isValidFileType = (type) => allowedFormats.includes(type);
3750
- const handleFile = (file) => {
3751
- if (file && isValidFileType(file.type)) {
3752
- const imgURL = URL.createObjectURL(file);
3753
- setUploadedImage(imgURL);
3754
- if (onChange)
3755
- onChange(imgURL);
3736
+ const reportError = (message) => {
3737
+ if (onError)
3738
+ onError(message);
3739
+ else
3740
+ CwDisplayMessage(message, exports.CwMessageType.ERROR);
3741
+ };
3742
+ const handleFile = async (file) => {
3743
+ if (!file) {
3744
+ onChange?.(null);
3745
+ return;
3756
3746
  }
3757
- else {
3758
- // Optionally handle unsupported file types
3759
- if (onChange)
3760
- onChange(null);
3747
+ if (!isValidFileType(file.type)) {
3748
+ reportError(labels.invalidType(allowedFormats.join(", ").replace(/image\//g, "")));
3749
+ onChange?.(null);
3750
+ return;
3751
+ }
3752
+ try {
3753
+ const dataUrl = await readImageFileAsDataUrl(file);
3754
+ setUploadedImage(dataUrl);
3755
+ onChange?.(dataUrl, file);
3756
+ }
3757
+ catch {
3758
+ reportError(labels.readError);
3759
+ onChange?.(null);
3761
3760
  }
3762
3761
  };
3763
3762
  const handleDrop = (e) => {
3764
3763
  e.preventDefault();
3765
3764
  const file = e.dataTransfer.files[0];
3766
- handleFile(file);
3765
+ void handleFile(file ?? null);
3767
3766
  };
3768
3767
  const onPasteButtonClick = async () => {
3769
3768
  try {
@@ -3773,21 +3772,20 @@ function CwInputImage(props) {
3773
3772
  for (const type of clipboardItem.types) {
3774
3773
  if (type.startsWith("image/")) {
3775
3774
  const blob = await clipboardItem.getType(type);
3776
- handleFile(blob);
3775
+ await handleFile(blob);
3777
3776
  }
3778
3777
  }
3779
3778
  }
3780
3779
  }
3781
- catch (err) {
3782
- console.error("Failed to read clipboard:", err);
3783
- alert("Failed to read from clipboard. Ensure the app has permission to access clipboard.");
3780
+ catch {
3781
+ reportError(labels.clipboardError);
3784
3782
  }
3785
3783
  };
3786
3784
  const handleFileChange = (e) => {
3787
- const file = e.target.files?.[0];
3788
- handleFile(file ?? null);
3785
+ const file = e.currentTarget.files?.[0];
3786
+ void handleFile(file ?? null);
3789
3787
  };
3790
- return (jsxRuntime.jsxs("div", { className: "cw-input-image", children: [jsxRuntime.jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$g.dropZone, children: [jsxRuntime.jsx("p", { children: "Drop image here" }), jsxRuntime.jsxs("small", { children: ["(", allowedFormats.join(", ").replace(/image\//g, ""), ")"] })] }), jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsxRuntime.jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: "Paste" }), jsxRuntime.jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: "Browse" })] }), jsxRuntime.jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, style: { display: "none" }, ...inputProps })] }));
3788
+ return (jsxRuntime.jsxs("div", { className: `cw-input-image ${styles$h.container}`, "data-size": size, children: [jsxRuntime.jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$h.dropZone, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-tiny", children: [jsxRuntime.jsx("p", { className: styles$h.title, children: labels.dropImageHere }), jsxRuntime.jsx("p", { className: styles$h.subtitle, children: labels.acceptedFormats(allowedFormats.join(", ").replace(/image\//g, "")) })] })] }), jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsxRuntime.jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: labels.paste, size: size }), jsxRuntime.jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: labels.browse, size: size })] }), jsxRuntime.jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, className: styles$h.hiddenInput, ...inputProps })] }));
3791
3789
  }
3792
3790
 
3793
3791
  /**
@@ -3919,7 +3917,7 @@ const CwImageArea = React.forwardRef((props, ref) => {
3919
3917
  });
3920
3918
  CwImageArea.displayName = "CwImageArea";
3921
3919
 
3922
- var styles$f = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
3920
+ var styles$g = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
3923
3921
 
3924
3922
  /**
3925
3923
  * This class represents a week where days can be selected or unselected
@@ -4059,16 +4057,16 @@ const CwWeekdaySelector = ({ value = "", onChange, disabled = false }) => {
4059
4057
  setSelectedDays(newWeekdays);
4060
4058
  onChange?.(newWeekdays.toString());
4061
4059
  };
4062
- return (jsxRuntime.jsx("div", { className: styles$f["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsxRuntime.jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
4060
+ return (jsxRuntime.jsx("div", { className: styles$g["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsxRuntime.jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
4063
4061
  };
4064
4062
 
4065
- var styles$e = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
4063
+ var styles$f = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
4066
4064
 
4067
4065
  function CwCheck(props) {
4068
4066
  const { labelProps, labelText, direction, alignment, className, ...inputProps } = props;
4069
4067
  const resolvedDirection = direction ?? alignment ?? "row";
4070
4068
  const displayText = labelProps?.text ?? labelText;
4071
- return (jsxRuntime.jsx("div", { className: `cw-check ${styles$e["check-container"]}${className ? ` ${className}` : ''}`, children: jsxRuntime.jsxs("label", { "data-direction": resolvedDirection, children: [jsxRuntime.jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsxRuntime.jsx("span", { className: "cw-icon-text", children: displayText }))] }) }));
4069
+ return (jsxRuntime.jsx("div", { className: `cw-check ${styles$f["check-container"]}${className ? ` ${className}` : ''}`, children: jsxRuntime.jsxs("label", { "data-direction": resolvedDirection, children: [jsxRuntime.jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsxRuntime.jsx("span", { className: "cw-icon-text", children: displayText }))] }) }));
4072
4070
  }
4073
4071
 
4074
4072
  function CwCheckbox(CwCheckboxProps) {
@@ -4119,14 +4117,14 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
4119
4117
  ?? (optionsAlignment === "column" ? "row" : "column");
4120
4118
  // Each checkbox's box-to-text layout is the opposite of the options flow, mirroring CwRadioGroup.
4121
4119
  const checkDirection = itemDirection === "row" ? "column" : "row";
4122
- return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$e.options, role: "group", "aria-label": labelProps?.text, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.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) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4120
+ return (jsxRuntime.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 && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.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) => (jsxRuntime.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) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4123
4121
  }
4124
4122
 
4125
- var styles$d = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
4123
+ var styles$e = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
4126
4124
 
4127
4125
  /** Single native radio input. Building block for CwRadioGroup. */
4128
4126
  function CwRadio({ label, direction = "row", className, ...inputProps }) {
4129
- return (jsxRuntime.jsxs("label", { className: `cw-radio ${styles$d.radio}${className ? ` ${className}` : ""}`, "data-direction": direction, children: [jsxRuntime.jsx("input", { type: "radio", ...inputProps }), label && jsxRuntime.jsx("span", { children: label })] }));
4127
+ return (jsxRuntime.jsxs("label", { className: `cw-radio ${styles$e.radio}${className ? ` ${className}` : ""}`, "data-direction": direction, children: [jsxRuntime.jsx("input", { type: "radio", ...inputProps }), label && jsxRuntime.jsx("span", { children: label })] }));
4130
4128
  }
4131
4129
 
4132
4130
  /**
@@ -4150,7 +4148,7 @@ function CwRadioGroup({ options, value, onChange, labelProps, groupLayout, itemL
4150
4148
  // (itemLayout column) reads best with the circle beside the text; a side-by-side row reads
4151
4149
  // best with the circle above the text.
4152
4150
  const radioDirection = itemLayout?.direction === "row" ? "column" : "row";
4153
- return (jsxRuntime.jsxs("div", { className: `cw-radio-group ${styles$d.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$d.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) => (jsxRuntime.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) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4151
+ return (jsxRuntime.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 && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.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) => (jsxRuntime.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) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4154
4152
  }
4155
4153
 
4156
4154
  function CwToggle(props) {
@@ -4416,7 +4414,7 @@ function CwDropdownFilter(props) {
4416
4414
  return (jsxRuntime.jsxs("div", { id: props.IdContent, className: containerClassName, children: [props.children, isVisible && (jsxRuntime.jsx("nav", { className: "cw-dropdown-menu", style: inlineStyles, onMouseLeave: props.onMouseLeave, id: props.idDropDownFilter, role: "menu", children: jsxRuntime.jsx("ul", { role: "none", children: props.DataSourceDropDownItem?.map((item) => (jsxRuntime.jsx("li", { id: item.IdDropDown_filter, role: "menuitem", children: item.dropDownFilter_desc }, item.IdDropDown_filter))) }) }))] }));
4417
4415
  }
4418
4416
 
4419
- var styles$c = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
4417
+ var styles$d = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
4420
4418
 
4421
4419
  /**
4422
4420
  * Button that toggles a floating panel with arbitrary children.
@@ -4495,7 +4493,7 @@ function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-st
4495
4493
  }
4496
4494
  panel.showPopover();
4497
4495
  }, [placement]);
4498
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$c.container, children: [jsxRuntime.jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsxRuntime.jsx("div", { ref: panelCallbackRef, className: `${styles$c.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4496
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$d.container, children: [jsxRuntime.jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsxRuntime.jsx("div", { ref: panelCallbackRef, className: `${styles$d.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4499
4497
  }
4500
4498
 
4501
4499
  function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor, onPrimaryColor) {
@@ -4513,13 +4511,13 @@ function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor
4513
4511
  return result;
4514
4512
  }
4515
4513
 
4516
- var styles$b = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
4514
+ var styles$c = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
4517
4515
 
4518
4516
  const CwMultiFilterTag = props => {
4519
4517
  const { ID, Name, Value, Category, Removable, PrimaryColor, Selectable, Selected } = props;
4520
4518
  const backgroundColor = `rgb(${PrimaryColor.r},${PrimaryColor.g},${PrimaryColor.b})`;
4521
4519
  const isOutlineMode = Selected && !Removable;
4522
- return (jsxRuntime.jsx("li", { className: styles$b["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
4520
+ return (jsxRuntime.jsx("li", { className: styles$c["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
4523
4521
  if (Selectable)
4524
4522
  props.OnSelect?.(props);
4525
4523
  }, children: jsxRuntime.jsx(CwChip, { label: Name, colorScheme: "custom", customColor: backgroundColor, variant: isOutlineMode ? "outline" : "soft", closable: Removable, onClose: () => props.OnRemove?.(props),
@@ -4529,7 +4527,7 @@ const CwMultiFilterTag = props => {
4529
4527
  } : undefined }) }));
4530
4528
  };
4531
4529
 
4532
- var styles$a = {"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"};
4530
+ 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"};
4533
4531
 
4534
4532
  /**
4535
4533
  * A multiple filter selector, a MULTI-SELECT even. Allows users to select and filter items based on tags.
@@ -4756,9 +4754,9 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4756
4754
  inputRef.current?.focus();
4757
4755
  }
4758
4756
  };
4759
- return (jsxRuntime.jsxs("form", { ref: componentRef, id: id, className: `${styles$a["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
4757
+ return (jsxRuntime.jsxs("form", { ref: componentRef, id: id, className: `${styles$b["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
4760
4758
  e.preventDefault();
4761
- }, children: [jsxRuntime.jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$a["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-outline-variant)" } : {}, children: [jsxRuntime.jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (React.createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsxRuntime.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 => {
4759
+ }, children: [jsxRuntime.jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$b["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-outline-variant)" } : {}, children: [jsxRuntime.jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (React.createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsxRuntime.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 => {
4762
4760
  switch (e.key) {
4763
4761
  case "Enter":
4764
4762
  case "Tab": {
@@ -4785,7 +4783,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4785
4783
  break;
4786
4784
  }
4787
4785
  }
4788
- } })] }), selectedTags.size > 0 && (jsxRuntime.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(jsxRuntime.jsxs("section", { ref: panelRef, className: styles$a["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxRuntime.jsxs("nav", { children: [jsxRuntime.jsx("button", { className: selectedCategory === "All" ? styles$a["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsxRuntime.jsx("button", { className: selectedCategory === category ? styles$a["category-selected"] : undefined, style: {
4786
+ } })] }), selectedTags.size > 0 && (jsxRuntime.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(jsxRuntime.jsxs("section", { ref: panelRef, className: styles$b["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxRuntime.jsxs("nav", { children: [jsxRuntime.jsx("button", { className: selectedCategory === "All" ? styles$b["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsxRuntime.jsx("button", { className: selectedCategory === category ? styles$b["category-selected"] : undefined, style: {
4789
4787
  backgroundColor: getColor(category).primary,
4790
4788
  color: getColor(category).onPrimary,
4791
4789
  }, onClick: () => handleClickCategory(category), children: category }, category)))] }), jsxRuntime.jsx("ul", { children: displayTags
@@ -4811,7 +4809,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4811
4809
  } }, props.ID))) })] }))] }));
4812
4810
  };
4813
4811
 
4814
- var styles$9 = {"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"};
4812
+ 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"};
4815
4813
 
4816
4814
  /**
4817
4815
  * Multi-select input with chip tags and searchable dropdown.
@@ -4946,11 +4944,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
4946
4944
  // Keeping containerRef for any other potential use
4947
4945
  const direction = alignProps?.flexDirection ?? "row";
4948
4946
  const feedbackMessages = feedback ? (Array.isArray(feedback) ? feedback : [feedback]) : [];
4949
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$9.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: `${styles$9.inputBox}${disabled ? ` ${styles$9.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
4950
- inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsxRuntime.jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsxRuntime.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 && (jsxRuntime.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) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxRuntime.jsxs("div", { ref: panelRef, className: styles$9.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$9.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.jsxs("li", { className: `${styles$9.option}${idx === focusedIndex ? ` ${styles$9.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsxRuntime.jsx("span", { className: styles$9.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
4947
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
4948
+ inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsxRuntime.jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsxRuntime.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 && (jsxRuntime.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) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxRuntime.jsxs("div", { ref: panelRef, className: styles$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.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 && jsxRuntime.jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
4951
4949
  }
4952
4950
 
4953
- var styles$8 = {"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"};
4951
+ 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"};
4954
4952
 
4955
4953
  function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId: initialSelectedId = null }) {
4956
4954
  const [expanded, setExpanded] = React.useState(new Set());
@@ -5017,10 +5015,10 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
5017
5015
  const isLeaf = !hasChildren;
5018
5016
  const isSelected = selectedId?.toString().toLowerCase() === node.id.toString().toLowerCase();
5019
5017
  const selectable = allowParentSelection || isLeaf;
5020
- return (jsxRuntime.jsxs("div", { className: styles$8["tree-item"], children: [jsxRuntime.jsxs("div", { className: [
5021
- styles$8["tree-node"],
5022
- isSelected && styles$8["selected"],
5023
- !selectable && styles$8["non-selectable"]
5018
+ return (jsxRuntime.jsxs("div", { className: styles$9["tree-item"], children: [jsxRuntime.jsxs("div", { className: [
5019
+ styles$9["tree-node"],
5020
+ isSelected && styles$9["selected"],
5021
+ !selectable && styles$9["non-selectable"]
5024
5022
  ].filter(Boolean).join(' '), style: { paddingLeft: `${depth * 24 + 8}px` }, onClick: () => {
5025
5023
  if (selectable) {
5026
5024
  setSelectedId(node.id);
@@ -5029,7 +5027,7 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
5029
5027
  else {
5030
5028
  toggleExpand(node.id);
5031
5029
  }
5032
- }, children: [hasChildren && (jsxRuntime.jsx(CwIcon, { size: "large", iconId: isExpanded ? "chevron-down" : "chevron-right" })), jsxRuntime.jsx("div", { className: `${styles$8["tree-label"]} ${!hasChildren ? styles$8["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsxRuntime.jsx("div", { className: styles$8["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
5030
+ }, children: [hasChildren && (jsxRuntime.jsx(CwIcon, { size: "large", iconId: isExpanded ? "chevron-down" : "chevron-right" })), jsxRuntime.jsx("div", { className: `${styles$9["tree-label"]} ${!hasChildren ? styles$9["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsxRuntime.jsx("div", { className: styles$9["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
5033
5031
  };
5034
5032
  // Function to search for nodes that match the search term
5035
5033
  const searchInTree = (nodes, searchTerm) => {
@@ -5053,7 +5051,129 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
5053
5051
  return results;
5054
5052
  };
5055
5053
  const filteredData = searchInTree(data, search);
5056
- return (jsxRuntime.jsxs("div", { className: `cw-tree-view ${styles$8["tree-container"]}`, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsxRuntime.jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsxRuntime.jsx("div", { className: styles$8["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxRuntime.jsxs("div", { className: styles$8["empty-state"], children: [jsxRuntime.jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
5054
+ return (jsxRuntime.jsxs("div", { className: `cw-tree-view ${styles$9["tree-container"]}`, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsxRuntime.jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsxRuntime.jsx("div", { className: styles$9["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxRuntime.jsxs("div", { className: styles$9["empty-state"], children: [jsxRuntime.jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
5055
+ }
5056
+
5057
+ const EXACT_PHRASE = /"([^"]+)"/g;
5058
+ /**
5059
+ * Quoted phrases are matched against the label only; loose words against label + description + href.
5060
+ * Parsed once instead of per node.
5061
+ */
5062
+ function parseSearch(search) {
5063
+ const phrases = Array.from(search.matchAll(EXACT_PHRASE), match => match[1].toLowerCase());
5064
+ const words = search
5065
+ .replace(EXACT_PHRASE, "")
5066
+ .trim()
5067
+ .toLowerCase()
5068
+ .split(/\s+/)
5069
+ .filter(Boolean);
5070
+ return { phrases, words };
5071
+ }
5072
+ /**
5073
+ * Filters a nav tree by a search string, keeping a group whose descendants match.
5074
+ *
5075
+ * Supports `"quoted phrases"` (must appear in the label) alongside loose words (any field) — this is
5076
+ * behaviour users are told about, so don't simplify it.
5077
+ */
5078
+ function filterNavItems(items, search) {
5079
+ if (!search?.trim())
5080
+ return items;
5081
+ const { phrases, words } = parseSearch(search);
5082
+ if (phrases.length === 0 && words.length === 0)
5083
+ return items;
5084
+ const keep = (item, parentMatchedPhrases) => {
5085
+ const label = item.label.toLowerCase();
5086
+ const haystack = [item.label, item.description, item.href].filter(Boolean).join(" ").toLowerCase();
5087
+ const matchesPhrases = phrases.every(phrase => label.includes(phrase));
5088
+ const matchesWords = words.every(word => haystack.includes(word));
5089
+ const selfMatches = (phrases.length === 0 || matchesPhrases || parentMatchedPhrases) && matchesWords;
5090
+ if (!item.children?.length)
5091
+ return selfMatches ? item : null;
5092
+ let children = item.children
5093
+ .map(child => keep(child, matchesPhrases || parentMatchedPhrases))
5094
+ .filter((child) => child !== null);
5095
+ // A phrase-only search narrows the survivors further: each must carry the phrase itself.
5096
+ if (phrases.length > 0 && words.length === 0 && matchesPhrases) {
5097
+ children = children.filter(child => phrases.every(phrase => child.label.toLowerCase().includes(phrase)));
5098
+ }
5099
+ if (children.length > 0)
5100
+ return { ...item, children };
5101
+ // The group matched but nothing under it did. Returning `children: []` would make it a leaf —
5102
+ // and a leaf with no href — so keep the subtree instead of emptying it.
5103
+ return selfMatches ? item : null;
5104
+ };
5105
+ return items
5106
+ .map(item => keep(item, false))
5107
+ .filter((item) => item !== null);
5108
+ }
5109
+
5110
+ /**
5111
+ * Sorts the top level alphabetically, leaving every nested list in the order the consumer gave.
5112
+ *
5113
+ * Deliberately level 1 only: this exists because a long list of modules is hard to scan, while the
5114
+ * pages inside a module are ordered on purpose. Returns the input untouched when not sorting.
5115
+ */
5116
+ function sortNavItems(items, alphabetically) {
5117
+ if (!alphabetically)
5118
+ return items;
5119
+ return [...items].sort((first, second) => first.label.localeCompare(second.label));
5120
+ }
5121
+
5122
+ 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"};
5123
+
5124
+ const SKELETON_ROW_COUNT = 5;
5125
+ const defaultRenderLink = (item, children) => (jsxRuntime.jsx("a", { href: item.href, children: children }));
5126
+ /** Sizes only its own icons — content injected via `renderLink` is styled by the consumer. */
5127
+ function CwNavMenu({ items, loading = false, isActive, renderLink = defaultRenderLink, showExpandIndicator = false, search, emptyMessage, sortAlphabetically = false, favoritesSlot, favoritesLabel = "Favorites", favoritesProps, isFavorite, beforeTreeSlot, className, ...navProps }) {
5128
+ const visibleItems = sortNavItems(filterNavItems(items, search), sortAlphabetically);
5129
+ const showEmptyMessage = !loading && Boolean(emptyMessage) && Boolean(search?.trim()) && visibleItems.length === 0;
5130
+ const hasActiveDescendant = (node) => node.children?.some(child => isActive?.(child) || hasActiveDescendant(child)) ?? false;
5131
+ const renderItem = (item, level) => {
5132
+ const children = item.children;
5133
+ if (children && children.length > 0) {
5134
+ return (jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("details", { "data-level": level, open: hasActiveDescendant(item) || undefined, children: [jsxRuntime.jsxs("summary", { children: [item.icon && jsxRuntime.jsx(CwIcon, { iconId: item.icon, size: level >= 2 ? "small" : "medium" }), item.label, (showExpandIndicator || level >= 2) && (jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small", className: styles$8.expandIndicator }))] }), jsxRuntime.jsx("ul", { children: children.map(child => renderItem(child, level + 1)) })] }) }, item.id));
5135
+ }
5136
+ return (jsxRuntime.jsx("li", { "data-active": isActive?.(item) ? "true" : undefined, children: renderLink(item, jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [item.icon && jsxRuntime.jsx(CwIcon, { iconId: item.icon, size: "medium" }), item.label, isFavorite?.(item) && jsxRuntime.jsx(CwIcon, { iconId: "star", size: "small", className: styles$8.favoriteStar })] })) }, item.id));
5137
+ };
5138
+ return (jsxRuntime.jsxs("nav", { ...navProps, className: [styles$8.menu, className].filter(Boolean).join(" "), children: [favoritesSlot && (jsxRuntime.jsxs("details", { open: true, ...favoritesProps, className: [styles$8.favorites, favoritesProps?.className].filter(Boolean).join(" "), children: [jsxRuntime.jsxs("summary", { children: [jsxRuntime.jsx(CwIcon, { iconId: "star", size: "medium" }), favoritesLabel] }), jsxRuntime.jsx("div", { className: styles$8.favoritesContent, children: favoritesSlot })] })), beforeTreeSlot, jsxRuntime.jsx("ul", { children: loading
5139
+ ? Array.from({ length: SKELETON_ROW_COUNT }, (_unused, index) => (jsxRuntime.jsx("li", { className: styles$8.skeleton }, index)))
5140
+ : visibleItems.map(item => renderItem(item, 1)) }), showEmptyMessage && jsxRuntime.jsx("p", { className: styles$8.emptyMessage, children: emptyMessage })] }));
5141
+ }
5142
+
5143
+ /**
5144
+ * Pure keyboard-navigation resolver shared by the `CwSearchInput` combobox.
5145
+ * Kept side-effect-free so the arrow/home/end/enter/escape behaviour can be unit
5146
+ * tested without a DOM (the library's vitest runs with `environment: "node"`).
5147
+ */
5148
+ /**
5149
+ * Resolves a key press against the current highlight into a {@link SearchKeyAction}.
5150
+ * Arrow navigation wraps around; `Enter` selects only when a valid row is highlighted.
5151
+ *
5152
+ * @param key `KeyboardEvent.key` value.
5153
+ * @param currentIndex Currently highlighted option index (`-1` = none).
5154
+ * @param optionsLength Number of options currently in the dropdown.
5155
+ */
5156
+ function resolveSearchKeyAction(key, currentIndex, optionsLength) {
5157
+ if (optionsLength <= 0)
5158
+ return { type: "none" };
5159
+ switch (key) {
5160
+ case "ArrowDown":
5161
+ return { type: "move", index: currentIndex < optionsLength - 1 ? currentIndex + 1 : 0 };
5162
+ case "ArrowUp":
5163
+ return { type: "move", index: currentIndex > 0 ? currentIndex - 1 : optionsLength - 1 };
5164
+ case "Home":
5165
+ return { type: "move", index: 0 };
5166
+ case "End":
5167
+ return { type: "move", index: optionsLength - 1 };
5168
+ case "Enter":
5169
+ return currentIndex >= 0 && currentIndex < optionsLength
5170
+ ? { type: "select", index: currentIndex }
5171
+ : { type: "none" };
5172
+ case "Escape":
5173
+ return { type: "close" };
5174
+ default:
5175
+ return { type: "none" };
5176
+ }
5057
5177
  }
5058
5178
 
5059
5179
  /**
@@ -5074,14 +5194,19 @@ function CwSearchInput(optionsProps) {
5074
5194
  const [_selectedOption, setSelectedOption] = React.useState(null);
5075
5195
  const [showDropdown, setShowDropdown] = React.useState(false);
5076
5196
  const [isLoading, setIsLoading] = React.useState(false);
5197
+ const [highlightedIndex, setHighlightedIndex] = React.useState(-1);
5077
5198
  const wrapperRef = React.useRef(null);
5199
+ const inputRef = React.useRef(null);
5200
+ // Stable ids wiring the combobox input to its listbox popup for assistive tech.
5201
+ const listboxId = React.useId();
5202
+ const optionId = (index) => `${listboxId}-opt-${index}`;
5078
5203
  const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
5079
5204
  anchorRef: wrapperRef,
5080
5205
  isOpen: showDropdown && filteredOptions.length > 0,
5081
- onClose: () => setShowDropdown(false),
5206
+ onClose: () => { setShowDropdown(false); setHighlightedIndex(-1); },
5082
5207
  });
5083
5208
  // Extract props
5084
- const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, ...otherProps } = optionsProps;
5209
+ const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, autoFocus, ...otherProps } = optionsProps;
5085
5210
  // Get direction for data attribute
5086
5211
  const direction = alignProps?.flexDirection || "row";
5087
5212
  // Make default value selection when loading the component
@@ -5100,9 +5225,10 @@ function CwSearchInput(optionsProps) {
5100
5225
  }
5101
5226
  }, [defaultValue, selectList]);
5102
5227
  const handleInputChange = (event) => {
5103
- const text = event.target.value;
5228
+ const text = event.currentTarget.value;
5104
5229
  setSearchText(text);
5105
5230
  setShowDropdown(true);
5231
+ setHighlightedIndex(-1);
5106
5232
  if (text === "") {
5107
5233
  setFilteredOptions(selectList);
5108
5234
  setSelectedOption(null);
@@ -5125,10 +5251,30 @@ function CwSearchInput(optionsProps) {
5125
5251
  };
5126
5252
  const handleInputFocus = () => {
5127
5253
  setShowDropdown(true);
5254
+ setHighlightedIndex(-1);
5128
5255
  if (searchText === "") {
5129
5256
  setFilteredOptions(selectList);
5130
5257
  }
5131
5258
  };
5259
+ const handleKeyDown = (event) => {
5260
+ if (!(showDropdown && filteredOptions.length > 0))
5261
+ return;
5262
+ const action = resolveSearchKeyAction(event.key, highlightedIndex, filteredOptions.length);
5263
+ switch (action.type) {
5264
+ case "move":
5265
+ event.preventDefault();
5266
+ setHighlightedIndex(action.index);
5267
+ break;
5268
+ case "select":
5269
+ event.preventDefault();
5270
+ handleOptionSelect(filteredOptions[action.index]);
5271
+ break;
5272
+ case "close":
5273
+ setShowDropdown(false);
5274
+ setHighlightedIndex(-1);
5275
+ break;
5276
+ }
5277
+ };
5132
5278
  const handleInputBlur = () => {
5133
5279
  // Dropdown is closed by useDropdownPortal's outside-click handler.
5134
5280
  // Blur alone must not close it — clicking an option would lose focus before the click fires.
@@ -5140,16 +5286,19 @@ function CwSearchInput(optionsProps) {
5140
5286
  handleChange(option.id);
5141
5287
  }
5142
5288
  setFilteredOptions([]);
5289
+ setHighlightedIndex(-1);
5143
5290
  };
5144
5291
  const handleClearClick = () => {
5145
5292
  setSearchText("");
5146
5293
  setFilteredOptions([]);
5147
5294
  setSelectedOption(null);
5295
+ setHighlightedIndex(-1);
5148
5296
  if (handleChange) {
5149
5297
  handleChange("");
5150
5298
  }
5299
+ inputRef.current?.focus();
5151
5300
  };
5152
- return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, id: id, ...otherProps, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("input", { type: "text", value: searchText, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled }), isLoading && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsxRuntime.jsx(CwIcon, { ...iconProps }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, children: jsxRuntime.jsx("ul", { children: filteredOptions.map((option) => (jsxRuntime.jsx("li", { className: dropdownStyles.option, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
5301
+ return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, ...otherProps, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.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 && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsxRuntime.jsx(CwIcon, { ...iconProps }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: filteredOptions.map((option, index) => (jsxRuntime.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))) }) }))] }));
5153
5302
  }
5154
5303
 
5155
5304
  /**
@@ -11346,7 +11495,6 @@ exports.CwDisplayMessage = CwDisplayMessage;
11346
11495
  exports.CwDropdown = CwDropdown;
11347
11496
  exports.CwDropdownFilter = CwDropdownFilter;
11348
11497
  exports.CwExpandable = CwExpandable;
11349
- exports.CwFileUpload = CwFileUpload;
11350
11498
  exports.CwFileUploadMultiple = CwFileUploadMultiple;
11351
11499
  exports.CwFindAirport = CwFindAirport;
11352
11500
  exports.CwFindCrewmember = CwFindCrewmember;
@@ -11368,7 +11516,6 @@ exports.CwInputText = CwInputText;
11368
11516
  exports.CwKeyValueList = CwKeyValueList;
11369
11517
  exports.CwLabel = CwLabel;
11370
11518
  exports.CwLoading = CwLoading;
11371
- exports.CwLoadingSmall = CwLoadingSmall;
11372
11519
  exports.CwMasterDetail = CwMasterDetail;
11373
11520
  exports.CwMessage = CwMessage;
11374
11521
  exports.CwMessageManager = CwMessageManager;
@@ -11377,6 +11524,7 @@ exports.CwModalHover = CwModalHover;
11377
11524
  exports.CwModalReportFunctional = CwModalReportFunctional;
11378
11525
  exports.CwMultiFilter = CwMultiFilter;
11379
11526
  exports.CwMultiFilterTag = CwMultiFilterTag;
11527
+ exports.CwNavMenu = CwNavMenu;
11380
11528
  exports.CwNote = CwNote;
11381
11529
  exports.CwOption = CwOption;
11382
11530
  exports.CwPopoverButton = CwPopoverButton;
@@ -11436,12 +11584,16 @@ exports.TooltipConstraintContext = TooltipConstraintContext;
11436
11584
  exports.UiEvent = UiEvent;
11437
11585
  exports.Weekdays = Weekdays;
11438
11586
  exports.cblEvent = cblEvent;
11587
+ exports.configureCwLoading = configureCwLoading;
11439
11588
  exports.eventIsVisible = eventIsVisible;
11589
+ exports.filterNavItems = filterNavItems;
11440
11590
  exports.filterVisibleEvents = filterVisibleEvents;
11591
+ exports.getCwLoadingDefaults = getCwLoadingDefaults;
11441
11592
  exports.getDefaultDivisions = getDefaultDivisions;
11442
11593
  exports.getEventSizes = getEventSizes;
11443
11594
  exports.getPresetsByKeysTemporal = getPresetsByKeysTemporal;
11444
11595
  exports.itemsToMultiFilterTags = itemsToMultiFilterTags;
11596
+ exports.sortNavItems = sortNavItems;
11445
11597
  exports.useCwMessage = useCwMessage;
11446
11598
  exports.useSortableList = useSortableList;
11447
11599
  exports.useSortableTable = useSortableTable;