@cwellt_software/cwellt-reactjs-lib 1.4.14 → 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 (85) 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 +564 -217
  5. package/dist/index.css +2 -2
  6. package/dist/index.d.ts +358 -66
  7. package/dist/index.es.js +558 -217
  8. package/dist/src/common/hooks/useRovingSingleSelect.d.ts +28 -0
  9. package/dist/src/common/hooks/useRovingSingleSelect.d.ts.map +1 -0
  10. package/dist/src/components/control/action/button/CwButton.d.ts +14 -4
  11. package/dist/src/components/control/action/button/CwButton.d.ts.map +1 -1
  12. package/dist/src/components/control/action/button/CwButtonSplit.d.ts +52 -0
  13. package/dist/src/components/control/action/button/CwButtonSplit.d.ts.map +1 -0
  14. package/dist/src/components/control/action/button/CwButtonSwitch.d.ts +65 -0
  15. package/dist/src/components/control/action/button/CwButtonSwitch.d.ts.map +1 -0
  16. package/dist/src/components/control/action/search/CwSearch.d.ts +2 -0
  17. package/dist/src/components/control/action/search/CwSearch.d.ts.map +1 -1
  18. package/dist/src/components/control/action/search/searchKeyboardNavigation.d.ts +35 -0
  19. package/dist/src/components/control/action/search/searchKeyboardNavigation.d.ts.map +1 -0
  20. package/dist/src/components/control/choice/checkbox/CwCheck.d.ts +6 -5
  21. package/dist/src/components/control/choice/checkbox/CwCheck.d.ts.map +1 -1
  22. package/dist/src/components/control/choice/checkbox/CwCheckboxGroup.d.ts +30 -7
  23. package/dist/src/components/control/choice/checkbox/CwCheckboxGroup.d.ts.map +1 -1
  24. package/dist/src/components/control/choice/checkbox/CwRadio.d.ts +10 -0
  25. package/dist/src/components/control/choice/checkbox/CwRadio.d.ts.map +1 -0
  26. package/dist/src/components/control/choice/checkbox/CwRadioGroup.d.ts +58 -0
  27. package/dist/src/components/control/choice/checkbox/CwRadioGroup.d.ts.map +1 -0
  28. package/dist/src/components/control/choice/nav-menu/CwNavMenu.d.ts +78 -0
  29. package/dist/src/components/control/choice/nav-menu/CwNavMenu.d.ts.map +1 -0
  30. package/dist/src/components/control/choice/nav-menu/filterNavItems.d.ts +9 -0
  31. package/dist/src/components/control/choice/nav-menu/filterNavItems.d.ts.map +1 -0
  32. package/dist/src/components/control/choice/nav-menu/sortNavItems.d.ts +9 -0
  33. package/dist/src/components/control/choice/nav-menu/sortNavItems.d.ts.map +1 -0
  34. package/dist/src/components/control/choice/toggle/CwToggle.d.ts +6 -5
  35. package/dist/src/components/control/choice/toggle/CwToggle.d.ts.map +1 -1
  36. package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts +12 -0
  37. package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts.map +1 -1
  38. package/dist/src/components/control/input/image/CwInputImage.d.ts +17 -2
  39. package/dist/src/components/control/input/image/CwInputImage.d.ts.map +1 -1
  40. package/dist/src/components/display/graphics/icon/CwIcon.d.ts +1 -1
  41. package/dist/src/components/display/graphics/icon/CwIcon.d.ts.map +1 -1
  42. package/dist/src/components/display/graphics/loading/CwLoading.d.ts +3 -14
  43. package/dist/src/components/display/graphics/loading/CwLoading.d.ts.map +1 -1
  44. package/dist/src/components/display/graphics/loading/loadingConfig.d.ts +16 -0
  45. package/dist/src/components/display/graphics/loading/loadingConfig.d.ts.map +1 -0
  46. package/dist/src/index.d.ts +7 -2
  47. package/dist/src/index.d.ts.map +1 -1
  48. package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
  49. package/dist/src/playground/PlaygroundSection.d.ts +13 -0
  50. package/dist/src/playground/PlaygroundSection.d.ts.map +1 -0
  51. package/dist/src/playground/pages/CwButtonPage.d.ts +3 -0
  52. package/dist/src/playground/pages/CwButtonPage.d.ts.map +1 -0
  53. package/dist/src/playground/pages/CwButtonSplitPage.d.ts +3 -0
  54. package/dist/src/playground/pages/CwButtonSplitPage.d.ts.map +1 -0
  55. package/dist/src/playground/pages/CwButtonSwitchPage.d.ts +3 -0
  56. package/dist/src/playground/pages/CwButtonSwitchPage.d.ts.map +1 -0
  57. package/dist/src/playground/pages/CwCheckboxGroupPage.d.ts +3 -0
  58. package/dist/src/playground/pages/CwCheckboxGroupPage.d.ts.map +1 -0
  59. package/dist/src/playground/pages/CwFileUploadMultiplePage.d.ts +3 -0
  60. package/dist/src/playground/pages/CwFileUploadMultiplePage.d.ts.map +1 -0
  61. package/dist/src/playground/pages/CwInputImagePage.d.ts.map +1 -1
  62. package/dist/src/playground/pages/CwNavMenuPage.d.ts +3 -0
  63. package/dist/src/playground/pages/CwNavMenuPage.d.ts.map +1 -0
  64. package/dist/src/playground/pages/CwRadioGroupPage.d.ts +3 -0
  65. package/dist/src/playground/pages/CwRadioGroupPage.d.ts.map +1 -0
  66. package/dist/src/playground/pages/IconLibraryPage.d.ts +3 -0
  67. package/dist/src/playground/pages/IconLibraryPage.d.ts.map +1 -0
  68. package/dist/src/playground/pages/LoadingPage.d.ts +3 -0
  69. package/dist/src/playground/pages/LoadingPage.d.ts.map +1 -0
  70. package/dist/src/playground/pages/SelectorsPage.d.ts.map +1 -1
  71. package/dist/test/common/hooks/useRovingSingleSelect.test.d.ts +2 -0
  72. package/dist/test/common/hooks/useRovingSingleSelect.test.d.ts.map +1 -0
  73. package/dist/test/components/control/action/search/searchKeyboardNavigation.test.d.ts +2 -0
  74. package/dist/test/components/control/action/search/searchKeyboardNavigation.test.d.ts.map +1 -0
  75. package/dist/test/components/control/choice/nav-menu/filterNavItems.test.d.ts +2 -0
  76. package/dist/test/components/control/choice/nav-menu/filterNavItems.test.d.ts.map +1 -0
  77. package/dist/test/components/control/choice/nav-menu/sortNavItems.test.d.ts +2 -0
  78. package/dist/test/components/control/choice/nav-menu/sortNavItems.test.d.ts.map +1 -0
  79. package/dist/test/components/control/input/file/fileMatchesAccept.test.d.ts +2 -0
  80. package/dist/test/components/control/input/file/fileMatchesAccept.test.d.ts.map +1 -0
  81. package/dist/test/components/control/input/image/readImageFileAsDataUrl.test.d.ts +2 -0
  82. package/dist/test/components/control/input/image/readImageFileAsDataUrl.test.d.ts.map +1 -0
  83. package/dist/test/components/display/graphics/loading/CwLoading.test.d.ts +2 -0
  84. package/dist/test/components/display/graphics/loading/CwLoading.test.d.ts.map +1 -0
  85. package/package.json +1 -2
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import React__default, { useState, useRef, useEffect, useCallback, useLayoutEffect, createContext, useContext, cloneElement, useMemo, forwardRef, useImperativeHandle, createElement, useId, memo, Fragment as Fragment$1, Component } from 'react';
3
+ import React__default, { useState, useRef, useEffect, useCallback, useLayoutEffect, createContext, useContext, cloneElement, useMemo, forwardRef, useImperativeHandle, useId, createElement, memo, Fragment as Fragment$1, Component } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { createRoot } from 'react-dom/client';
6
6
  import Draggable from 'react-draggable';
@@ -161,12 +161,7 @@ function getContrastColor(color) {
161
161
  return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
162
162
  }
163
163
 
164
- const SVG_ICONS = {
165
- 'sortable-asc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "0.3" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "1" })] })),
166
- 'sortable-desc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "1" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "0.3" })] })),
167
- };
168
-
169
- var styles$r = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
164
+ var styles$v = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
170
165
 
171
166
  // Constants
172
167
  const margin$1 = 16;
@@ -456,7 +451,7 @@ const CwTooltipManager = () => {
456
451
  if (!state.isVisible || !state.content) {
457
452
  return null;
458
453
  }
459
- return createPortal(jsx("div", { ref: tooltipRef, className: styles$r["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
454
+ return createPortal(jsx("div", { ref: tooltipRef, className: styles$v["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
460
455
  top: `${tooltipPosition.top}px`,
461
456
  left: `${tooltipPosition.left}px`,
462
457
  opacity: (isPositioned && !isMeasuring) ? 1 : 0,
@@ -537,16 +532,22 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
537
532
  useEffect(() => {
538
533
  ensureTooltipManager();
539
534
  }, []);
540
- return (jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$r["cw-tooltip"], children: children }));
535
+ return (jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$v["cw-tooltip"], children: children }));
536
+ };
537
+
538
+ const SVG_ICONS = {
539
+ 'sortable-asc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "0.3" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "1" })] })),
540
+ 'sortable-desc': (jsxs("svg", { width: "16", height: "16", viewBox: "0 0 128 128", fill: "currentColor", children: [jsx("path", { d: "M93.1675 73.1739C94.5691 74.5758 94.7323 76.7924 93.5515 78.3846L93.1675 78.8326L63.6741 108.326L34.1755 78.8326C32.6908 77.3518 32.6014 74.9761 33.9708 73.3881C35.3401 71.8001 37.7033 71.5391 39.3861 72.7899L39.8341 73.1739L63.6741 97.0137L87.5088 73.1739C88.9104 71.7726 91.1274 71.6092 92.7194 72.7899L93.1674 73.1739H93.1675Z", opacity: "1" }), jsx("path", { d: "M34.1714 55.1518C32.7697 53.7499 32.6066 51.5333 33.7874 49.9411L34.1714 49.4931L63.6647 20L93.1634 49.4931C94.6481 50.9739 94.7375 53.3496 93.3681 54.9376C91.9987 56.5256 89.6356 56.7866 87.9527 55.5358L87.5047 55.1517L63.6647 31.312L39.8301 55.1518C38.4285 56.5531 36.2115 56.7165 34.6195 55.5358L34.1715 55.1518L34.1714 55.1518Z", opacity: "0.3" })] })),
541
541
  };
542
542
 
543
543
  function CwIcon(props) {
544
- const { iconId, color, size, title, tooltipPosition = 'bottom', ...iconProps } = props;
544
+ const { iconId, color, size, className, title, tooltipPosition = 'bottom', ...iconProps } = props;
545
545
  const getClassName = (baseClass) => {
546
546
  return [
547
547
  baseClass,
548
548
  color && `cw-color-${color}`,
549
- size && `cw-font-size-${size}`
549
+ size && `cw-font-size-${size}`,
550
+ className
550
551
  ].filter(Boolean).join(' ');
551
552
  };
552
553
  let iconElement;
@@ -958,49 +959,39 @@ function CwImageZoom(image) {
958
959
  } }), jsx("div", { style: { color: "#fff", fontSize: "1rem", textAlign: "center" }, children: selectedImage.filename && jsx("div", { children: selectedImage.filename }) })] }))] }));
959
960
  }
960
961
 
962
+ let defaults = {};
961
963
  /**
962
- * CwLoading
963
- *
964
- * A versatile loading component that shows a spinner with optional text
965
- * and disables the wrapped content while in loading state.
966
- *
967
- * @example
968
- * // Basic usage
969
- * <CwLoading isLoading={isSubmitting}>
970
- * <form>...</form>
971
- * </CwLoading>
972
- *
973
- * // With custom text and size
974
- * <CwLoading
975
- * isLoading={isLoading}
976
- * text="Please wait..."
977
- * size="large"
978
- * >
979
- * <UserProfile />
980
- * </CwLoading>
964
+ * Register global CwLoading defaults. Call once at app init, before the first render.
965
+ * Merges into any previously configured defaults.
981
966
  */
982
- function CwLoading({ isLoading = false, text = '', size = 'regular', iconPosition = 'outside', iconName = 'cwi-plane-solid', animation = 'spin', children }) {
983
- const iconClasses = `cwi-icons ${iconName || ''}`;
984
- return (jsxs("div", { "aria-busy": isLoading, className: isLoading ? 'cw-loading-container' : '', "data-children": !!children, children: [isLoading && (jsxs("div", { className: "cw-loading-content", "data-size": size, "data-animation": animation, children: [jsx("div", { className: "cw-loading", "data-icon-position": iconPosition, children: jsx("span", { className: iconClasses }) }), text && (jsx("p", { children: text }))] })), jsx("div", { className: isLoading ? 'cw-loading-disabled-content' : '', children: children })] }));
967
+ function configureCwLoading(next) {
968
+ defaults = { ...defaults, ...next };
969
+ }
970
+ /** Read the currently configured CwLoading defaults. */
971
+ function getCwLoadingDefaults() {
972
+ return defaults;
985
973
  }
986
974
 
987
975
  /**
988
- * @deprecated since may 2025. Use <CwLoading size="small"> instead.
976
+ * CwLoading — a spinner with optional text that dims the wrapped content while loading.
989
977
  *
990
- * This component will be removed in a future release.
978
+ * Icon resolves as `iconName` prop → `getCwLoadingDefaults().icon` → none (neutral ring).
991
979
  *
992
980
  * @example
993
- * // Instead of:
994
- * <CwLoadingSmall />
995
- *
996
- * // Use:
997
- * <CwLoading size="small" />
981
+ * <CwLoading isLoading={isSubmitting}>
982
+ * <form>...</form>
983
+ * </CwLoading>
998
984
  */
999
- function CwLoadingSmall(CwelltLoadingAppointements) {
1000
- return (jsx("div", { children: CwelltLoadingAppointements.isLoading === true ? (jsx("div", { className: "cw-loading-container", children: jsx("div", { className: "cw-loading" }) })) : (jsx("div", {})) }));
985
+ function CwLoading({ isLoading = false, text = '', size = 'regular', iconPosition = 'outside', iconName, animation = 'spin', children }) {
986
+ let overlay = null;
987
+ if (isLoading) {
988
+ const resolvedIcon = iconName ?? getCwLoadingDefaults().icon;
989
+ overlay = (jsxs("div", { className: "cw-loading-content", "data-size": size, "data-animation": animation, role: "status", "aria-label": text || 'Loading', children: [jsx("div", { className: "cw-loading", "data-icon-position": iconPosition, "data-has-icon": !!resolvedIcon, children: resolvedIcon && jsx("span", { className: `cwi-icons ${resolvedIcon}` }) }), text && (jsx("p", { children: text }))] }));
990
+ }
991
+ return (jsxs("div", { "aria-busy": isLoading, className: "cw-loading-container", "data-children": !!children, children: [overlay, jsx("div", { className: "cw-loading-disabled-content", children: children })] }));
1001
992
  }
1002
993
 
1003
- var styles$q = {"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"};
994
+ var styles$u = {"cw-generic-tooltip-content":"cw-generic-tooltip-module__cw-generic-tooltip-content__la-Si","cw-generic-tooltip":"cw-generic-tooltip-module__cw-generic-tooltip__Ij76M"};
1004
995
 
1005
996
  // Constants moved outside to prevent recreation
1006
997
  const margin = 16;
@@ -1123,12 +1114,12 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1123
1114
  const { setTooltipTimeout, clearTooltipTimeout } = useTooltipDelay(() => {
1124
1115
  setIsVisible(true);
1125
1116
  }, showDelay);
1126
- const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$q["cw-generic-tooltip-content"]);
1117
+ const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$u["cw-generic-tooltip-content"]);
1127
1118
  // Memoize tooltip content creation
1128
1119
  const tooltipContent = useMemo(() => {
1129
1120
  if (hide || !isVisible || !content)
1130
1121
  return null;
1131
- return createPortal(jsx("div", { className: styles$q["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
1122
+ return createPortal(jsx("div", { className: styles$u["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
1132
1123
  position: 'fixed',
1133
1124
  top: `${tooltipPosition.top}px`,
1134
1125
  left: `${tooltipPosition.left}px`,
@@ -1143,10 +1134,10 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1143
1134
  clearTooltipTimeout();
1144
1135
  setIsVisible(false);
1145
1136
  }, [clearTooltipTimeout]);
1146
- return (jsxs("div", { ref: containerRef, className: styles$q["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1137
+ return (jsxs("div", { ref: containerRef, className: styles$u["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1147
1138
  };
1148
1139
 
1149
- function CwButton({ text, variant = 'solid', color = 'primary', className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }) {
1140
+ const CwButton = React__default.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }, ref) {
1150
1141
  // Build CSS classes based on variant and props
1151
1142
  let buttonClass = `cw-button-${variant}`;
1152
1143
  // Add icon class only for icon variant without children
@@ -1157,9 +1148,18 @@ function CwButton({ text, variant = 'solid', color = 'primary', className = '',
1157
1148
  buttonClass += ` ${className}`;
1158
1149
  }
1159
1150
  const tooltipContent = title || (variant === 'icon' && text ? text : undefined);
1160
- const buttonElement = (jsx("button", { type: "button", className: buttonClass, ...buttonProps, "data-color": color, "aria-label": tooltipContent, children: variant === 'icon' ? null : (children ?? (jsxs(Fragment, { children: [icon && jsx(CwIcon, { iconId: icon }), text && jsx("strong", { children: text })] }))) }));
1151
+ const iconElement = icon ? jsx(CwIcon, { iconId: icon }) : null;
1152
+ const textElement = text ? jsx("strong", { children: text }) : null;
1153
+ // Only emit toggle attributes when `pressed` is defined; otherwise output stays identical to a normal button.
1154
+ const pressedProps = pressed !== undefined
1155
+ ? { "aria-pressed": pressed, "data-pressed": pressed ? "true" : undefined }
1156
+ : {};
1157
+ const buttonElement = (jsx("button", { ref: ref, type: "button", className: buttonClass, ...buttonProps, "data-color": color, "data-size": size, ...pressedProps, "aria-label": tooltipContent ?? buttonProps["aria-label"], children: variant === 'icon' ? null : (children ?? (iconPosition === 'right'
1158
+ ? jsxs(Fragment, { children: [textElement, iconElement] })
1159
+ : jsxs(Fragment, { children: [iconElement, textElement] }))) }));
1161
1160
  return tooltipContent ? (jsx(CwTooltipNew, { content: tooltipContent, position: tooltipPosition, displayInline: true, children: buttonElement })) : (buttonElement);
1162
- }
1161
+ });
1162
+ CwButton.displayName = "CwButton";
1163
1163
 
1164
1164
  // Reference for draggable modal
1165
1165
  /**
@@ -1196,7 +1196,7 @@ function CwModal(custModalProps) {
1196
1196
  return (jsx("div", { children: custModalProps.modalState && (jsxs("div", { className: custModalProps.classNameModalOverlay + " cwelltModalOverlay", children: [jsx("div", { className: "cwelltModalOverlayBg", onClick: custModalProps.onCloseModal }), jsx(Draggable, { disabled: isModalDisabled, axis: "both", nodeRef: draggableRef, children: jsxs("div", { className: custModalProps.classNameModal + " cwelltContainerModal", ref: draggableRef, style: widthModalDef !== "40em" ? modalStyle.widthCustomStyle : modalStyle.widthDefStyle, children: [jsxs("div", { className: "cwelltModalHeader", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: [jsx("div", { className: "cwelltModalTitle", children: custModalProps.titleModal }), jsx("button", { className: "cwelltBtnCloseModal", onClick: custModalProps.onCloseModal, children: jsx("span", { className: "cwelltCloseIcon" }) })] }), jsx("div", { className: "cwelltModalBody", children: jsx("div", { className: "cwelltContainerModalBody", style: { position: "relative" }, children: custModalProps.children }) }), isHide === false ? (jsx("footer", { className: "legacy-modal-footer", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: custModalProps.onSaveModal, form: custModalProps.formSaveModal, hidden: custModalProps.HideBtnModal, type: custModalProps.HtmlSubmitModal }) })) : (jsx("div", { style: { display: "none" } }))] }) })] })) }));
1197
1197
  }
1198
1198
 
1199
- var styles$p = {"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"};
1199
+ 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"};
1200
1200
 
1201
1201
  function CwConfirmationPopup(props) {
1202
1202
  const { isOpen, onConfirm, onCancel, message = "Are you sure you want to proceed?", confirmText = "Confirm", cancelText = "Cancel", placement = 'bottom', children } = props;
@@ -1260,15 +1260,15 @@ function CwConfirmationPopup(props) {
1260
1260
  onCancel();
1261
1261
  }
1262
1262
  };
1263
- return (jsxs(Fragment, { children: [renderChildren(), isOpen && (jsx("div", { className: styles$p.overlayPositioned, onClick: handleOverlayClick, children: jsxs("div", { ref: popupRef, className: styles$p.popup, style: {
1263
+ return (jsxs(Fragment, { children: [renderChildren(), isOpen && (jsx("div", { className: styles$t.overlayPositioned, onClick: handleOverlayClick, children: jsxs("div", { ref: popupRef, className: styles$t.popup, style: {
1264
1264
  position: 'absolute',
1265
1265
  top: `${position.top}px`,
1266
1266
  left: `${position.left}px`,
1267
1267
  transform: 'none'
1268
- }, children: [jsx("p", { className: styles$p.message, children: message }), jsxs("div", { className: styles$p.buttons, children: [jsx("button", { className: `${styles$p.button} ${styles$p.confirmButton}`, onClick: onConfirm, children: confirmText }), jsx("button", { className: `${styles$p.button} ${styles$p.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
1268
+ }, children: [jsx("p", { className: styles$t.message, children: message }), jsxs("div", { className: styles$t.buttons, children: [jsx("button", { className: `${styles$t.button} ${styles$t.confirmButton}`, onClick: onConfirm, children: confirmText }), jsx("button", { className: `${styles$t.button} ${styles$t.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
1269
1269
  }
1270
1270
 
1271
- var styles$o = {"cw-dialog-main":"cw-dialog-module__cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module__cw-dialog-button-close__9GRd8"};
1271
+ 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"};
1272
1272
 
1273
1273
  // Helper function to parse size values
1274
1274
  const parseSize = (size) => {
@@ -1541,7 +1541,7 @@ const CwDialog = props => {
1541
1541
  }
1542
1542
  }
1543
1543
  }, [open]);
1544
- const header = useMemo(() => (jsxs("header", { onMouseDown: handleMouseDown, children: [jsx("span", { children: headline }), customHeader || (jsx("button", { className: styles$o["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
1544
+ const header = useMemo(() => (jsxs("header", { onMouseDown: handleMouseDown, children: [jsx("span", { children: headline }), customHeader || (jsx("button", { className: styles$s["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
1545
1545
  const content = useMemo(() => (jsx("section", { children: children })), [children]);
1546
1546
  const footer = useMemo(() => (jsx("footer", { children: customFooter || (jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: onSave, tooltipPosition: "top", disabled: disableSave, "data-testid": "cw-dialog-save" })) })), [customFooter, onSave, disableSave]);
1547
1547
  const resizeHandles = useMemo(() => size.autoHeight
@@ -1568,7 +1568,7 @@ const CwDialog = props => {
1568
1568
  : `${convertFromPx(size.height, size.heightUnit)}${size.heightUnit}`;
1569
1569
  return { displayWidth, displayHeight };
1570
1570
  }, [size.width, size.height, size.widthUnit, size.heightUnit, size.autoHeight]);
1571
- const dialogContent = (jsx("div", { "data-has-scrim": hasScrim, className: styles$o["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxs("dialog", { ...domProps, ref: dialogRef, style: {
1571
+ const dialogContent = (jsx("div", { "data-has-scrim": hasScrim, className: styles$s["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxs("dialog", { ...domProps, ref: dialogRef, style: {
1572
1572
  left: `${position.x}px`,
1573
1573
  top: `${position.y}px`,
1574
1574
  width: displayDimensions.displayWidth,
@@ -1729,7 +1729,7 @@ function CwAlign(props) {
1729
1729
  }, children: props.children }));
1730
1730
  }
1731
1731
 
1732
- var styles$n = {"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"};
1732
+ 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"};
1733
1733
 
1734
1734
  /**
1735
1735
  * CwCard - A simple card component for displaying content in a contained format
@@ -1755,11 +1755,11 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1755
1755
  // Construct class names using CSS modules
1756
1756
  const cardClassNames = [
1757
1757
  'cw-card',
1758
- styles$n.card,
1758
+ styles$r.card,
1759
1759
  className,
1760
- clickable ? styles$n.clickable : '',
1761
- disabled ? styles$n.disabled : '',
1762
- isLoading ? styles$n.loading : '',
1760
+ clickable ? styles$r.clickable : '',
1761
+ disabled ? styles$r.disabled : '',
1762
+ isLoading ? styles$r.loading : '',
1763
1763
  ].filter(Boolean).join(' ');
1764
1764
  // Handle click event when card is clickable
1765
1765
  const handleClick = () => {
@@ -1776,15 +1776,15 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1776
1776
  // Determine if footer should be rendered
1777
1777
  const hasFooter = hasChips || footer || (hasActions && resolvedDirection === "row");
1778
1778
  // Actions component to reuse
1779
- const ActionsComponent = hasActions && !disabled ? (jsxs("div", { className: styles$n.actions, children: [extraActions ?? null, onEdit && jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) : null;
1779
+ const ActionsComponent = hasActions && !disabled ? (jsxs("div", { className: styles$r.actions, children: [extraActions ?? null, onEdit && jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) : null;
1780
1780
  return (jsxs("div", { ...(id && { id }), className: cardClassNames, ...(style && { style }), ...(clickable && {
1781
1781
  role: 'button',
1782
1782
  tabIndex: 0,
1783
1783
  onClick: handleClick,
1784
- }), "data-variant": variant, "data-direction": resolvedDirection, children: [hasHeader && (jsxs("header", { children: [(title || subtitle) && (jsxs("div", { className: styles$n.headerContent, "data-align": resolvedAlign, children: [title && jsx("h5", { children: title }), subtitle && jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] })), jsx("div", { className: styles$n.content, children: children }), hasFooter && (jsxs("footer", { children: [hasChips && (jsx("div", { className: styles$n.footerTags, children: chips.map((chip, index) => (jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$n.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsx("div", { className: styles$n.footerContent, children: footer }))] })), resolvedDirection === "row" && ActionsComponent, isLoading && (jsx("div", { className: styles$n.loadingOverlay, children: jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
1784
+ }), "data-variant": variant, "data-direction": resolvedDirection, children: [hasHeader && (jsxs("header", { children: [(title || subtitle) && (jsxs("div", { className: styles$r.headerContent, "data-align": resolvedAlign, children: [title && jsx("h5", { children: title }), subtitle && jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] })), jsx("div", { className: styles$r.content, children: children }), hasFooter && (jsxs("footer", { children: [hasChips && (jsx("div", { className: styles$r.footerTags, children: chips.map((chip, index) => (jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$r.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsx("div", { className: styles$r.footerContent, children: footer }))] })), resolvedDirection === "row" && ActionsComponent, isLoading && (jsx("div", { className: styles$r.loadingOverlay, children: jsx(CwLoading, { isLoading: isLoading, size: "small" }) }))] }));
1785
1785
  };
1786
1786
 
1787
- var styles$m = {"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"};
1787
+ 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"};
1788
1788
 
1789
1789
  /**
1790
1790
  * Option to display in the CwSelect
@@ -1879,10 +1879,10 @@ function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', default
1879
1879
  icon: sortDirection === 'asc' ? 'arrow-up' : 'arrow-down',
1880
1880
  onClick: () => setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'),
1881
1881
  title: `Sort ${sortDirection === 'asc' ? 'descending' : 'ascending'}`,
1882
- }, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsx("div", { className: styles$m.loading, children: jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsx("div", { className: styles$m.emptyState, children: emptyState || jsx("p", { children: "No items to display" }) })) : (jsxs(Fragment, { children: [jsx("div", { className: `${styles$m.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsx(React__default.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxs("div", { className: styles$m.pagination, children: [jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxs("span", { className: styles$m.pageInfo, children: [currentPage, " / ", totalPages] }), jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
1882
+ }, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsx("div", { className: styles$q.loading, children: jsx(CwLoading, { isLoading: isLoading }) })) : sortedItems.length === 0 ? (jsx("div", { className: styles$q.emptyState, children: emptyState || jsx("p", { children: "No items to display" }) })) : (jsxs(Fragment, { children: [jsx("div", { className: `${styles$q.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsx(React__default.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxs("div", { className: styles$q.pagination, children: [jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxs("span", { className: styles$q.pageInfo, children: [currentPage, " / ", totalPages] }), jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
1883
1883
  }
1884
1884
 
1885
- var styles$l = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
1885
+ var styles$p = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
1886
1886
 
1887
1887
  /**
1888
1888
  *
@@ -1899,7 +1899,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
1899
1899
  setVisible_accordionBody(!isVisible_accordionBody);
1900
1900
  };
1901
1901
  // #endregion
1902
- return (jsxs("div", { className: styles$l["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxs("header", { onClick: () => showAccordionBody(), children: [jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsx("button", { className: "cw-button-icon" })] }), jsx("div", { className: styles$l["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
1902
+ return (jsxs("div", { className: styles$p["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxs("header", { onClick: () => showAccordionBody(), children: [jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsx("button", { className: "cw-button-icon" })] }), jsx("div", { className: styles$p["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
1903
1903
  }
1904
1904
 
1905
1905
  /**
@@ -2157,7 +2157,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
2157
2157
  }, min: 1, max: totalPages }), jsx("span", { children: "/" }), jsx("span", { children: totalPages }), jsx(CwButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2158
2158
  }
2159
2159
 
2160
- var styles$k = {"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"};
2160
+ 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"};
2161
2161
 
2162
2162
  /**
2163
2163
  * Hook that provides state management for CwSortableTable.
@@ -2220,9 +2220,9 @@ function useSortableTable(initialItems) {
2220
2220
  }
2221
2221
 
2222
2222
  // ─── Drop indicator row ───────────────────────────────────────────────────────
2223
- const DropIndicatorRow = ({ colSpan }) => (jsx("tr", { className: styles$k.dropIndicator, "aria-hidden": true, children: jsx("td", { colSpan: colSpan, children: jsx("div", {}) }) }));
2223
+ const DropIndicatorRow = ({ colSpan }) => (jsx("tr", { className: styles$o.dropIndicator, "aria-hidden": true, children: jsx("td", { colSpan: colSpan, children: jsx("div", {}) }) }));
2224
2224
  // ─── Loading skeleton ─────────────────────────────────────────────────────────
2225
- const LoadingRows = ({ colSpan }) => (jsx(Fragment, { children: Array.from({ length: 4 }).map((_, i) => (jsx("tr", { className: styles$k.skeletonRow, children: jsx("td", { colSpan: colSpan, children: jsx("div", { className: styles$k.skeleton }) }) }, i))) }));
2225
+ const LoadingRows = ({ colSpan }) => (jsx(Fragment, { children: Array.from({ length: 4 }).map((_, i) => (jsx("tr", { className: styles$o.skeletonRow, children: jsx("td", { colSpan: colSpan, children: jsx("div", { className: styles$o.skeleton }) }) }, i))) }));
2226
2226
  // ─── Component ────────────────────────────────────────────────────────────────
2227
2227
  /**
2228
2228
  * CwSortableTable
@@ -2309,11 +2309,11 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
2309
2309
  return items.map((item, index) => {
2310
2310
  const key = item[rowKey];
2311
2311
  const isDragging = draggedItem?.[rowKey] === key;
2312
- return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && (jsx(DropIndicatorRow, { colSpan: totalCols })), jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$k.dragging : "", children: [showHandle && (jsx("td", { className: "cw-table-col-action", children: jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: renderCell(item, col) }, `${String(key)}_${col.key}`)))] }), index === items.length - 1 && dropIndicatorIndex === items.length && (jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
2312
+ return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && (jsx(DropIndicatorRow, { colSpan: totalCols })), jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$o.dragging : "", children: [showHandle && (jsx("td", { className: "cw-table-col-action", children: jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: renderCell(item, col) }, `${String(key)}_${col.key}`)))] }), index === items.length - 1 && dropIndicatorIndex === items.length && (jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
2313
2313
  });
2314
2314
  };
2315
2315
  // ── Render ──────────────────────────────────────────────────────────────
2316
- return (jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [showHandle && jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxs("footer", { className: styles$k.saveBar, children: [jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
2316
+ return (jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, children: [jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsx("thead", { children: jsxs("tr", { children: [showHandle && jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsx("tbody", { children: renderBody() })] }), hasChanges && (jsxs("footer", { className: styles$o.saveBar, children: [jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
2317
2317
  }
2318
2318
 
2319
2319
  /**
@@ -2512,7 +2512,7 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
2512
2512
  }, min: 1, max: totalPages }), jsx("span", { children: "/" }), jsx("span", { children: totalPages }), jsx(CwButton, { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2513
2513
  }
2514
2514
 
2515
- var styles$j = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","badge":"cw-tabs-module__badge__AmVxW","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2515
+ 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"};
2516
2516
 
2517
2517
  const TabIcon = ({ icon }) => {
2518
2518
  if (!icon)
@@ -2562,7 +2562,7 @@ function CwTabs(CwTabsProps) {
2562
2562
  const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
2563
2563
  ? { minWidth: CwTabsProps.tabsListWidth }
2564
2564
  : undefined;
2565
- return (jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$j['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsx("span", { className: styles$j['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsx("div", { className: styles$j['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2565
+ return (jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$n['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsx("span", { className: styles$n['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsx("div", { className: styles$n['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2566
2566
  }
2567
2567
 
2568
2568
  /**
@@ -2589,7 +2589,7 @@ const CwExpandable = ({ briefing, onToggle, onOpen, onClose, children, ...detail
2589
2589
  return (jsxs("details", { ref: myRef, ...detailsProps, className: "cw-expandable", children: [jsx("summary", { children: briefing }), children && jsx("section", { children: children })] }));
2590
2590
  };
2591
2591
 
2592
- var styles$i = {"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"};
2592
+ 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"};
2593
2593
 
2594
2594
  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, }) => {
2595
2595
  const [masterWidth, setMasterWidth] = useState(initialWidth);
@@ -2625,10 +2625,10 @@ const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, de
2625
2625
  document.body.style.userSelect = '';
2626
2626
  };
2627
2627
  }, [isResizing, minMasterWidth, maxMasterWidth]);
2628
- const rootClassName = [styles$i['cw-master-detail'], className].filter(Boolean).join(' ');
2629
- return (jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsx("search", { children: jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsx("header", { children: masterHeader })), jsx("ul", { children: items.map((item) => (jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsx("footer", { children: masterFooter }))] }), resizable && (jsx("div", { className: styles$i.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsx("section", { className: styles$i.detail, children: selectedKey && detailContent
2628
+ const rootClassName = [styles$m['cw-master-detail'], className].filter(Boolean).join(' ');
2629
+ return (jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, children: [jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsx("search", { children: jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsx("header", { children: masterHeader })), jsx("ul", { children: items.map((item) => (jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsx("footer", { children: masterFooter }))] }), resizable && (jsx("div", { className: styles$m.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsx("section", { className: styles$m.detail, children: selectedKey && detailContent
2630
2630
  ? detailContent
2631
- : (jsx("div", { className: styles$i['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
2631
+ : (jsx("div", { className: styles$m['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
2632
2632
  };
2633
2633
 
2634
2634
  /**
@@ -2653,7 +2653,7 @@ const CwKeyValueList = ({ items, className = "", emptyValue = "-", direction = "
2653
2653
  : emptyValue })] }, item.key))) }));
2654
2654
  };
2655
2655
 
2656
- var styles$h = {"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"};
2656
+ 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"};
2657
2657
 
2658
2658
  function CwSortableList({ items, onReorder, renderItem, className = '', movedItems = new Set(), emptyMessage = "No elements to show", readOnly = false, maxHeight = "300px", }) {
2659
2659
  const [draggedItem, setDraggedItem] = useState(null);
@@ -2716,15 +2716,15 @@ function CwSortableList({ items, onReorder, renderItem, className = '', movedIte
2716
2716
  }
2717
2717
  };
2718
2718
  if (items.length === 0) {
2719
- return (jsx("div", { className: `${styles$h.sortableList} ${styles$h.emptyState} ${className}`, children: jsx("div", { className: styles$h.emptyMessage, children: emptyMessage }) }));
2719
+ return (jsx("div", { className: `${styles$l.sortableList} ${styles$l.emptyState} ${className}`, children: jsx("div", { className: styles$l.emptyMessage, children: emptyMessage }) }));
2720
2720
  }
2721
- return (jsx("div", { className: `${styles$h.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
2721
+ return (jsx("div", { className: `${styles$l.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
2722
2722
  const { title, extraContent, actions, showHandle = true, expandedContent } = renderItem(item);
2723
2723
  const isDragging = draggedItem?.id === item.id;
2724
2724
  const isMoved = movedItems.has(item.id);
2725
2725
  const canExpand = Boolean(expandedContent);
2726
2726
  const isExpanded = expandedItems.has(item.id);
2727
- return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && jsx("div", { className: styles$h.dropIndicator }), jsxs("div", { className: `${styles$h.sortableItem} ${isDragging ? styles$h.dragging : ''} ${isMoved ? styles$h.moved : ''} ${readOnly ? styles$h.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxs("header", { children: [canExpand ? (jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsx("div", { className: styles$h.sortableHandle, children: jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxs("div", { className: styles$h.sortableContent, children: [jsx("div", { className: styles$h.sortableTitle, children: title }), extraContent && jsx("div", { className: styles$h.sortableExtraContent, children: extraContent })] }), jsx("div", { className: styles$h.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsx("div", { className: styles$h.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsx("div", { className: styles$h.dropIndicator }))] }, item.id));
2727
+ return (jsxs(React__default.Fragment, { children: [dropIndicatorIndex === index && jsx("div", { className: styles$l.dropIndicator }), jsxs("div", { className: `${styles$l.sortableItem} ${isDragging ? styles$l.dragging : ''} ${isMoved ? styles$l.moved : ''} ${readOnly ? styles$l.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxs("header", { children: [canExpand ? (jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsx("div", { className: styles$l.sortableHandle, children: jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxs("div", { className: styles$l.sortableContent, children: [jsx("div", { className: styles$l.sortableTitle, children: title }), extraContent && jsx("div", { className: styles$l.sortableExtraContent, children: extraContent })] }), jsx("div", { className: styles$l.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsx("div", { className: styles$l.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsx("div", { className: styles$l.dropIndicator }))] }, item.id));
2728
2728
  }) }));
2729
2729
  }
2730
2730
 
@@ -2850,60 +2850,9 @@ const CwTableGrouped = props => {
2850
2850
  group.rows.map((child, j) => (jsx("tr", { "data-row": true, "data-row-last-of-group": j == group.rows.length - 1, children: child.cells.map((cell, k) => (jsx("td", { children: cell.content }, k))) }, j)))] }, i))) }), jsx("tfoot", {})] }) }));
2851
2851
  };
2852
2852
 
2853
- function CwFileUpload(fileUploadProps) {
2854
- const [previewURL, setPreviewURL] = useState("");
2855
- const [error, setError] = useState(null);
2856
- const [_selectedFileName, setSelectedFileName] = useState("");
2857
- const [_currentHexContent, setCurrentHexContent] = useState("");
2858
- useEffect(() => {
2859
- // If there is hexadecimal preview content, set the Preview URL
2860
- if (fileUploadProps.file?.Bindata) {
2861
- setPreviewURL(`data:image/png;base64,${fileUploadProps.file.Bindata}`);
2862
- }
2863
- }, [fileUploadProps.file?.Bindata]);
2864
- const handleFileChange = (event) => {
2865
- const file = event.target.files?.[0];
2866
- setSelectedFileName(file?.name ?? "");
2867
- if (file) {
2868
- const allowedExts = fileUploadProps.accept.split(',').map(ext => ext.trim().replace('.', '').toLowerCase());
2869
- const fileExt = file.name.split('.').pop()?.toLowerCase() ?? "";
2870
- if (!allowedExts.includes(fileExt)) {
2871
- setError(`Invalid file type. Only ${fileUploadProps.acceptString} files are allowed.`);
2872
- setPreviewURL("");
2873
- return;
2874
- }
2875
- setError(null);
2876
- const reader = new FileReader();
2877
- reader.onloadend = () => {
2878
- if (typeof reader.result === "string") {
2879
- const hexContent = arrayBufferToHex(reader.result);
2880
- setCurrentHexContent(hexContent);
2881
- setPreviewURL(reader.result);
2882
- setCurrentHexContent(arrayBufferToHex(reader.result));
2883
- // Call function to store hexadecimal content
2884
- fileUploadProps.onSaveHexContent(arrayBufferToHex(reader.result));
2885
- }
2886
- };
2887
- reader.readAsDataURL(file);
2888
- }
2889
- };
2890
- // Function to convert the image buffer into hexadecimal content
2891
- const arrayBufferToHex = (dataUrl) => {
2892
- // Decodes the base64 of the URL data
2893
- const base64 = dataUrl.split(",")[1];
2894
- const binary = atob(base64);
2895
- let hex = "";
2896
- for (let i = 0; i < binary.length; i++) {
2897
- hex += binary.charCodeAt(i).toString(16).padStart(2, "0");
2898
- }
2899
- return hex;
2900
- };
2901
- return (jsxs("div", { children: [jsxs("div", { className: "row", children: [jsx("input", { className: "cw-button", type: "file", accept: fileUploadProps.accept, readOnly: true, placeholder: "No file selected...", onChange: handleFileChange }), previewURL && (jsx("div", { className: "row", children: jsx("img", { src: previewURL, alt: "Preview", style: { maxWidth: "200px", maxHeight: "200px" } }) }))] }), error && jsx("div", { className: "row error", children: error }), jsx("div", { className: "row", children: jsxs("label", { children: ["Please note: File/image has to be in ", fileUploadProps.acceptString, " format", fileUploadProps.sizeString && `, ${fileUploadProps.sizeString}`] }) })] }));
2902
- }
2903
-
2904
- var styles$g = {"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"};
2853
+ 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"};
2905
2854
 
2906
- const DEFAULT_LABELS = {
2855
+ const DEFAULT_LABELS$1 = {
2907
2856
  uploadDisabled: 'Upload disabled',
2908
2857
  clickToUpload: 'Click to upload or drag and drop',
2909
2858
  acceptedFiles: (accept) => `Accepted files: ${accept}`,
@@ -2911,6 +2860,7 @@ const DEFAULT_LABELS = {
2911
2860
  allTypesAccepted: 'All file types accepted',
2912
2861
  changeFile: 'Change File',
2913
2862
  clearAll: 'Clear all',
2863
+ upload: 'Upload',
2914
2864
  addMoreFiles: 'Add More Files',
2915
2865
  filesSelected: (count) => `${count} file${count !== 1 ? 's' : ''} selected`,
2916
2866
  fileTooLarge: (name, maxSize) => `File "${name}" is too large. Maximum size allowed is ${maxSize}MB.`,
@@ -2918,11 +2868,38 @@ const DEFAULT_LABELS = {
2918
2868
  invalidMimeType: (name, types) => `File "${name}" has an invalid MIME type. Allowed types: ${types}`,
2919
2869
  alreadySelected: (name) => `File "${name}" is already selected.`,
2920
2870
  };
2871
+ /**
2872
+ * Checks a file against an `accept` string (comma-separated tokens). A token can be a dotted
2873
+ * extension (".pdf"), an exact MIME type ("application/pdf"), a wildcard MIME ("image" + slash + "star"),
2874
+ * or a bare "star" / "star-slash-star" for anything. Returns true if the file matches ANY token
2875
+ * (or if `accept` is empty).
2876
+ */
2877
+ function fileMatchesAccept(fileName, fileType, accept) {
2878
+ const tokens = accept.split(',').map(token => token.trim().toLowerCase()).filter(Boolean);
2879
+ if (tokens.length === 0) {
2880
+ return true;
2881
+ }
2882
+ const fileExtension = '.' + (fileName.split('.').pop()?.toLowerCase() ?? '');
2883
+ const mimeType = fileType.toLowerCase();
2884
+ return tokens.some(token => {
2885
+ if (token === '*' || token === '*/*') {
2886
+ return true;
2887
+ }
2888
+ if (token.startsWith('.')) {
2889
+ return token === fileExtension;
2890
+ }
2891
+ if (token.endsWith('/*')) {
2892
+ const prefix = token.slice(0, token.indexOf('/') + 1);
2893
+ return mimeType.startsWith(prefix);
2894
+ }
2895
+ return token === mimeType;
2896
+ });
2897
+ }
2921
2898
  function CwFileUploadMultiple(fileUploadProps) {
2922
2899
  const fileInputRef = useRef(null);
2923
2900
  const [selectedFiles, setSelectedFiles] = useState([]);
2924
2901
  const [existingFile, setExistingFile] = useState(fileUploadProps.initialFileName);
2925
- const labels = { ...DEFAULT_LABELS, ...fileUploadProps.labels };
2902
+ const labels = { ...DEFAULT_LABELS$1, ...fileUploadProps.labels };
2926
2903
  React__default.useEffect(() => {
2927
2904
  setExistingFile(fileUploadProps.initialFileName);
2928
2905
  }, [fileUploadProps.initialFileName]);
@@ -2940,17 +2917,9 @@ function CwFileUploadMultiple(fileUploadProps) {
2940
2917
  };
2941
2918
  }
2942
2919
  }
2943
- // Validate file type by extension (based in accept)
2920
+ // Validate file type against accept (dotted extensions, exact MIME, wildcard MIME, or *)
2944
2921
  if (fileUploadProps.accept) {
2945
- const acceptedExtensions = fileUploadProps.accept.split(',').map(ext => ext.trim().toLowerCase());
2946
- const fileExtension = '.' + file.name.split('.').pop()?.toLowerCase();
2947
- const isExtensionValid = acceptedExtensions.some(ext => {
2948
- if (ext.startsWith('.')) {
2949
- return ext === fileExtension;
2950
- }
2951
- return false;
2952
- });
2953
- if (!isExtensionValid) {
2922
+ if (!fileMatchesAccept(file.name, file.type, fileUploadProps.accept)) {
2954
2923
  return {
2955
2924
  isValid: false,
2956
2925
  error: labels.invalidFormat(file.name, fileUploadProps.accept)
@@ -2975,7 +2944,7 @@ function CwFileUploadMultiple(fileUploadProps) {
2975
2944
  const errors = [];
2976
2945
  for (const file of fileArray) {
2977
2946
  // Check if the file already exists (by name and size)
2978
- const isDuplicate = existingFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
2947
+ const isDuplicate = validFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
2979
2948
  if (isDuplicate) {
2980
2949
  errors.push(labels.alreadySelected(file.name));
2981
2950
  continue;
@@ -2993,8 +2962,7 @@ function CwFileUploadMultiple(fileUploadProps) {
2993
2962
  fileUploadProps.onError(errors.join('\n'));
2994
2963
  }
2995
2964
  else {
2996
- console.error(errors.join('\n'));
2997
- alert(errors.join('\n')); // Fallback if there is no onError
2965
+ CwDisplayMessage(errors.join('\n'), CwMessageType.ERROR);
2998
2966
  }
2999
2967
  }
3000
2968
  // If not multiple, only take the first valid file (replace)
@@ -3068,12 +3036,20 @@ function CwFileUploadMultiple(fileUploadProps) {
3068
3036
  }
3069
3037
  }
3070
3038
  };
3071
- return (jsxs("div", { className: `${styles$g.fileUploadContainer} ${fileUploadProps.className}`, children: [jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$g.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxs("div", { className: `${styles$g.uploadArea} ${fileUploadProps.disabled ? styles$g.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsx(CwIcon, { iconId: "upload" }), jsx("p", { className: `${styles$g.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxs("p", { className: `${styles$g.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxs("div", { className: styles$g.filesContainer, children: [jsxs("div", { className: styles$g.fileItem, children: [jsxs("div", { className: styles$g.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$g.fileExtension, children: getFileExtension(existingFile) })] }), jsx("div", { className: styles$g.fileInfo, children: jsx("p", { className: styles$g.fileName, children: existingFile }) }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
3039
+ return (jsxs("div", { className: `${styles$k.fileUploadContainer} ${fileUploadProps.className}`, children: [jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$k.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxs("div", { className: `${styles$k.uploadArea} ${fileUploadProps.disabled ? styles$k.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsx(CwIcon, { iconId: "upload" }), jsx("p", { className: `${styles$k.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxs("p", { className: `${styles$k.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxs("div", { className: styles$k.filesContainer, children: [jsxs("div", { className: styles$k.fileItem, children: [jsxs("div", { className: styles$k.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$k.fileExtension, children: getFileExtension(existingFile) })] }), jsx("div", { className: styles$k.fileInfo, children: jsx("p", { className: styles$k.fileName, children: existingFile }) }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
3072
3040
  setExistingFile(undefined);
3073
3041
  if (fileUploadProps.onSelect) {
3074
3042
  fileUploadProps.onSelect(null);
3075
3043
  }
3076
- }, disabled: fileUploadProps.disabled, className: styles$g.smallButton })] }), jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxs("div", { className: styles$g.filesContainer, children: [jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsx("small", { className: styles$g.filesCount, children: labels.filesSelected(selectedFiles.length) }), !fileUploadProps.hideClearAll && (jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] }), selectedFiles.map((file, index) => (jsxs("div", { className: styles$g.fileItem, children: [jsxs("div", { className: styles$g.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$g.fileExtension, children: getFileExtension(file.name) })] }), jsxs("div", { className: styles$g.fileInfo, children: [jsx("p", { className: styles$g.fileName, children: file.name }), jsxs("p", { className: styles$g.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$g.smallButton })] }, index))), fileUploadProps.multiple && (jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
3044
+ }, disabled: fileUploadProps.disabled, className: styles$k.smallButton })] }), jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxs("div", { className: styles$k.filesContainer, children: [jsxs("header", { className: "cw-flex-row cw-align-between-center cw-flex-wrap", children: [jsx("small", { className: styles$k.filesCount, children: fileUploadProps.statusText ?? labels.filesSelected(selectedFiles.length) }), jsxs("div", { className: "cw-flex-row", children: [fileUploadProps.onConfirm && selectedFiles.length > 0 && (jsx(CwButton, { onClick: () => {
3045
+ let files = fileInputRef.current?.files ?? null;
3046
+ if (!files) {
3047
+ const dataTransfer = new DataTransfer();
3048
+ selectedFiles.forEach(file => dataTransfer.items.add(file));
3049
+ files = dataTransfer.files;
3050
+ }
3051
+ fileUploadProps.onConfirm?.(files);
3052
+ }, disabled: fileUploadProps.disabled || fileUploadProps.confirmDisabled, icon: "upload", text: fileUploadProps.confirmLabel ?? labels.upload })), !fileUploadProps.hideClearAll && (jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] })] }), selectedFiles.map((file, index) => (jsxs("div", { className: styles$k.fileItem, children: [jsxs("div", { className: styles$k.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$k.fileExtension, children: getFileExtension(file.name) })] }), jsxs("div", { className: styles$k.fileInfo, children: [jsx("p", { className: styles$k.fileName, children: file.name }), jsxs("p", { className: styles$k.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$k.smallButton })] }, `${file.name}-${file.size}`))), fileUploadProps.multiple && (jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
3077
3053
  }
3078
3054
 
3079
3055
  function CwInput(CwInputProps) {
@@ -3114,7 +3090,7 @@ function CwDigit(props) {
3114
3090
  return (jsx("div", { className: "cw-input-text", children: jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsx("input", { type: "number", ...inputProps }), buttonProps && jsx(CwButton, { ...buttonProps })] }) }));
3115
3091
  }
3116
3092
 
3117
- var styles$f = {"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"};
3093
+ 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"};
3118
3094
 
3119
3095
  const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }) => {
3120
3096
  const [rgb, setRgb] = useState({ r: 255, g: 255, b: 255 });
@@ -3317,13 +3293,13 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
3317
3293
  // Calculate background color for the main area based on current hue
3318
3294
  const hueColor = hsvToRgb(hsv.h, 100, 100);
3319
3295
  const hueHex = rgbToHex(hueColor.r, hueColor.g, hueColor.b);
3320
- return (jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsx("div", { className: styles$f.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxs("div", { children: [jsx("label", { children: "R:" }), jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxs("div", { children: [jsx("label", { children: "G:" }), jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxs("div", { children: [jsx("label", { children: "B:" }), jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxs("div", { className: styles$f.colorPickerInteractiveArea, children: [jsx("div", { className: styles$f.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsx("div", { className: styles$f.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxs("div", { className: styles$f.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxs("div", { className: styles$f.colorAreaOverlay, children: [jsx("div", { className: styles$f.hueBackground, style: { backgroundColor: hueHex } }), jsx("div", { className: styles$f.whiteGradient }), jsx("div", { className: styles$f.blackGradient })] }), jsx("div", { className: styles$f.colorAreaCursor, style: {
3296
+ return (jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsx("div", { className: styles$j.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxs("div", { children: [jsx("label", { children: "R:" }), jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxs("div", { children: [jsx("label", { children: "G:" }), jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxs("div", { children: [jsx("label", { children: "B:" }), jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxs("div", { className: styles$j.colorPickerInteractiveArea, children: [jsx("div", { className: styles$j.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsx("div", { className: styles$j.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxs("div", { className: styles$j.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxs("div", { className: styles$j.colorAreaOverlay, children: [jsx("div", { className: styles$j.hueBackground, style: { backgroundColor: hueHex } }), jsx("div", { className: styles$j.whiteGradient }), jsx("div", { className: styles$j.blackGradient })] }), jsx("div", { className: styles$j.colorAreaCursor, style: {
3321
3297
  left: `${hsv.s}%`,
3322
3298
  top: `${100 - hsv.v}%`
3323
3299
  } })] })] })] }));
3324
3300
  };
3325
3301
 
3326
- var styles$e = {"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"};
3302
+ 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"};
3327
3303
 
3328
3304
  const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, }) => {
3329
3305
  const [isOpen, setIsOpen] = useState(false);
@@ -3456,11 +3432,11 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
3456
3432
  break;
3457
3433
  }
3458
3434
  };
3459
- return (jsxs("div", { className: `cw-input-color ${styles$e.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsx(CwLabel, { ...labelProps })), jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$e.selectColor} ${disabled ? styles$e.disabled : ''} ${readOnly ? styles$e.readOnly : ''}`, style: {
3435
+ return (jsxs("div", { className: `cw-input-color ${styles$i.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsx(CwLabel, { ...labelProps })), jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
3460
3436
  width,
3461
3437
  height,
3462
3438
  backgroundColor: value,
3463
- }, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && createPortal(jsx("div", { ref: dropdownRef, className: styles$e.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
3439
+ }, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && createPortal(jsx("div", { ref: dropdownRef, className: styles$i.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
3464
3440
  };
3465
3441
 
3466
3442
  /**
@@ -3710,31 +3686,63 @@ function CwInputDateText(props) {
3710
3686
  return (jsx("div", { className: "cw-input-date-text", children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { children: [jsx("input", { type: "text", disabled: disabled, maxLength: 10, onChange: onChangeInputText, pattern: "^$ --|[.0-9\\/\\-]{10}", placeholder: format.toLowerCase(), readOnly: readOnly, ref: textInputRef, required: required, size: width, tabIndex: tabIndex, value: displayedDate }), jsxs("span", { children: [jsx(CwIcon, { iconId: "calendar" }), jsx("input", { type: "date", disabled: disabled, onChange: onChangeInputDate, readOnly: readOnly, ref: dateInputRef, tabIndex: -1, value: date, ...inputProps })] })] }), buttonProps && jsx(CwButton, { ...buttonProps })] }) }));
3711
3687
  }
3712
3688
 
3713
- var styles$d = {"dropZone":"cw-input-image-module__dropZone__ygrGu"};
3689
+ 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"};
3714
3690
 
3691
+ const DEFAULT_LABELS = {
3692
+ dropImageHere: "Drop image here",
3693
+ paste: "Paste",
3694
+ browse: "Browse",
3695
+ acceptedFormats: (formats) => `(${formats})`,
3696
+ clipboardError: "Failed to read from clipboard. Ensure the app has permission to access the clipboard.",
3697
+ invalidType: (formats) => `Unsupported file type. Allowed: ${formats}`,
3698
+ readError: "Could not read the image file.",
3699
+ };
3700
+ /** Reads a file/blob into a base64 data URL (persistable, no blob URL to revoke). */
3701
+ function readImageFileAsDataUrl(file) {
3702
+ return new Promise((resolve, reject) => {
3703
+ const reader = new FileReader();
3704
+ reader.onload = () => resolve(reader.result);
3705
+ reader.onerror = () => reject(reader.error ?? new Error("Failed to read file"));
3706
+ reader.readAsDataURL(file);
3707
+ });
3708
+ }
3715
3709
  function CwInputImage(props) {
3716
3710
  const [_uploadedImage, setUploadedImage] = useState(null);
3717
3711
  const inputRef = useRef(null);
3718
- const { allowedImageFormats, onChange, ...inputProps } = props;
3712
+ const { allowedImageFormats, onChange, onError, labels: labelsProp, size, ...inputProps } = props;
3719
3713
  const allowedFormats = allowedImageFormats || ["image/jpeg", "image/png", "image/gif"];
3714
+ const labels = { ...DEFAULT_LABELS, ...labelsProp };
3720
3715
  const isValidFileType = (type) => allowedFormats.includes(type);
3721
- const handleFile = (file) => {
3722
- if (file && isValidFileType(file.type)) {
3723
- const imgURL = URL.createObjectURL(file);
3724
- setUploadedImage(imgURL);
3725
- if (onChange)
3726
- onChange(imgURL);
3716
+ const reportError = (message) => {
3717
+ if (onError)
3718
+ onError(message);
3719
+ else
3720
+ CwDisplayMessage(message, CwMessageType.ERROR);
3721
+ };
3722
+ const handleFile = async (file) => {
3723
+ if (!file) {
3724
+ onChange?.(null);
3725
+ return;
3727
3726
  }
3728
- else {
3729
- // Optionally handle unsupported file types
3730
- if (onChange)
3731
- onChange(null);
3727
+ if (!isValidFileType(file.type)) {
3728
+ reportError(labels.invalidType(allowedFormats.join(", ").replace(/image\//g, "")));
3729
+ onChange?.(null);
3730
+ return;
3731
+ }
3732
+ try {
3733
+ const dataUrl = await readImageFileAsDataUrl(file);
3734
+ setUploadedImage(dataUrl);
3735
+ onChange?.(dataUrl, file);
3736
+ }
3737
+ catch {
3738
+ reportError(labels.readError);
3739
+ onChange?.(null);
3732
3740
  }
3733
3741
  };
3734
3742
  const handleDrop = (e) => {
3735
3743
  e.preventDefault();
3736
3744
  const file = e.dataTransfer.files[0];
3737
- handleFile(file);
3745
+ void handleFile(file ?? null);
3738
3746
  };
3739
3747
  const onPasteButtonClick = async () => {
3740
3748
  try {
@@ -3744,21 +3752,20 @@ function CwInputImage(props) {
3744
3752
  for (const type of clipboardItem.types) {
3745
3753
  if (type.startsWith("image/")) {
3746
3754
  const blob = await clipboardItem.getType(type);
3747
- handleFile(blob);
3755
+ await handleFile(blob);
3748
3756
  }
3749
3757
  }
3750
3758
  }
3751
3759
  }
3752
- catch (err) {
3753
- console.error("Failed to read clipboard:", err);
3754
- alert("Failed to read from clipboard. Ensure the app has permission to access clipboard.");
3760
+ catch {
3761
+ reportError(labels.clipboardError);
3755
3762
  }
3756
3763
  };
3757
3764
  const handleFileChange = (e) => {
3758
- const file = e.target.files?.[0];
3759
- handleFile(file ?? null);
3765
+ const file = e.currentTarget.files?.[0];
3766
+ void handleFile(file ?? null);
3760
3767
  };
3761
- return (jsxs("div", { className: "cw-input-image", children: [jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$d.dropZone, children: [jsx("p", { children: "Drop image here" }), jsxs("small", { children: ["(", allowedFormats.join(", ").replace(/image\//g, ""), ")"] })] }), jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: "Paste" }), jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: "Browse" })] }), jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, style: { display: "none" }, ...inputProps })] }));
3768
+ return (jsxs("div", { className: `cw-input-image ${styles$h.container}`, "data-size": size, children: [jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$h.dropZone, children: [jsx(CwIcon, { iconId: "upload" }), jsxs("div", { className: "cw-flex-column cw-gap-tiny", children: [jsx("p", { className: styles$h.title, children: labels.dropImageHere }), jsx("p", { className: styles$h.subtitle, children: labels.acceptedFormats(allowedFormats.join(", ").replace(/image\//g, "")) })] })] }), jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: labels.paste, size: size }), jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: labels.browse, size: size })] }), jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, className: styles$h.hiddenInput, ...inputProps })] }));
3762
3769
  }
3763
3770
 
3764
3771
  /**
@@ -3890,7 +3897,7 @@ const CwImageArea = forwardRef((props, ref) => {
3890
3897
  });
3891
3898
  CwImageArea.displayName = "CwImageArea";
3892
3899
 
3893
- var styles$c = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
3900
+ var styles$g = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
3894
3901
 
3895
3902
  /**
3896
3903
  * This class represents a week where days can be selected or unselected
@@ -4030,15 +4037,16 @@ const CwWeekdaySelector = ({ value = "", onChange, disabled = false }) => {
4030
4037
  setSelectedDays(newWeekdays);
4031
4038
  onChange?.(newWeekdays.toString());
4032
4039
  };
4033
- return (jsx("div", { className: styles$c["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
4040
+ return (jsx("div", { className: styles$g["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
4034
4041
  };
4035
4042
 
4036
- var styles$b = {"check-container":"cw-check-module__check-container__4nscZ","checkbox-group-container":"cw-check-module__checkbox-group-container__WMNbG"};
4043
+ var styles$f = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
4037
4044
 
4038
4045
  function CwCheck(props) {
4039
- const { labelProps, labelText, iconProps, alignment = "row", className, ...inputProps } = props;
4040
- const displayText = labelText || labelProps?.text;
4041
- return (jsx("div", { className: `cw-check ${styles$b["check-container"]}${className ? ` ${className}` : ''}`, children: jsxs("label", { "data-direction": alignment, children: [jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsxs("span", { className: "cw-icon-text", children: [iconProps && jsx(CwIcon, { ...iconProps }), displayText] }))] }) }));
4046
+ const { labelProps, labelText, direction, alignment, className, ...inputProps } = props;
4047
+ const resolvedDirection = direction ?? alignment ?? "row";
4048
+ const displayText = labelProps?.text ?? labelText;
4049
+ return (jsx("div", { className: `cw-check ${styles$f["check-container"]}${className ? ` ${className}` : ''}`, children: jsxs("label", { "data-direction": resolvedDirection, children: [jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsx("span", { className: "cw-icon-text", children: displayText }))] }) }));
4042
4050
  }
4043
4051
 
4044
4052
  function CwCheckbox(CwCheckboxProps) {
@@ -4056,7 +4064,16 @@ function CwCheckbox(CwCheckboxProps) {
4056
4064
  : "cw_checkboxContent cwellt_flex_row" + " " + CwCheckboxProps.classNameContainer, style: CwCheckboxProps.styleContainer, children: [inputElement, CwCheckboxProps.labelName ? (jsx("label", { htmlFor: CwCheckboxProps.id, className: CwCheckboxProps.labelClassName, children: CwCheckboxProps.labelName })) : null] }));
4057
4065
  }
4058
4066
 
4059
- function CwCheckboxGroup({ options, value = [], onChange, labelProps, alignProps, required, disabled, optionsAlignment = "row", className, feedback, }) {
4067
+ /**
4068
+ * CwCheckboxGroup - Multi-select group of native checkbox inputs.
4069
+ *
4070
+ * Use for selecting any number of values from a list of options. Layout follows the
4071
+ * CwKeyValueList / CwRadioGroup convention with two nested {@link CwLayoutProps} axes applied as
4072
+ * `data-*` attributes: `groupLayout` positions the label relative to the group block (root grid),
4073
+ * `itemLayout` controls how the checkboxes flow among themselves (options container) and, on the
4074
+ * opposite axis, each checkbox's own box-to-text layout.
4075
+ */
4076
+ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayout, itemLayout, required, disabled, className, feedback, alignProps, optionsAlignment, "data-testid": dataTestId, }) {
4060
4077
  const handleChange = (optionValue, checked) => {
4061
4078
  if (checked) {
4062
4079
  onChange([...value, optionValue]);
@@ -4068,15 +4085,57 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, alignProps
4068
4085
  const feedbackMessages = feedback
4069
4086
  ? Array.isArray(feedback) ? feedback : [feedback]
4070
4087
  : [];
4071
- const flexDirection = alignProps?.flexDirection ?? "row";
4072
- const dataDirection = { 'data-direction': flexDirection };
4073
- return (jsxs("div", { className: `cw-checkbox-group ${styles$b["checkbox-group-container"]}${className ? ` ${className}` : ''}`, ...dataDirection, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: `${optionsAlignment === "row" ? "cw-flex-column cw-gap-small" : "cw-flex-row cw-flex-wrap"}`, children: options.map((option) => (jsx(CwCheck, { labelText: option.label, checked: value.includes(option.value), disabled: disabled || option.disabled, alignment: optionsAlignment, onChange: (e) => handleChange(option.value, e.target.checked) }, option.value))) })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4088
+ // Effective layout — precedence: new `groupLayout`/`itemLayout` > legacy-derived > default.
4089
+ // Legacy `alignProps.flexDirection` drove the label-vs-options axis (default "row" = label
4090
+ // beside the options); map it to `groupLayout.direction`.
4091
+ const groupDirection = groupLayout?.direction
4092
+ ?? (alignProps?.flexDirection === "column" ? "column" : "row");
4093
+ // Legacy `optionsAlignment` is inverted relative to the options flow: "row" stacked the options
4094
+ // (column flow) with each check internally row; "column" laid them inline (row flow) with each
4095
+ // check internally column. Default reproduces the legacy `optionsAlignment="row"` case.
4096
+ const itemDirection = itemLayout?.direction
4097
+ ?? (optionsAlignment === "column" ? "row" : "column");
4098
+ // Each checkbox's box-to-text layout is the opposite of the options flow, mirroring CwRadioGroup.
4099
+ const checkDirection = itemDirection === "row" ? "column" : "row";
4100
+ return (jsxs("div", { className: `cw-checkbox-group ${styles$f.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$f.options, role: "group", "aria-label": labelProps?.text, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4101
+ }
4102
+
4103
+ var styles$e = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
4104
+
4105
+ /** Single native radio input. Building block for CwRadioGroup. */
4106
+ function CwRadio({ label, direction = "row", className, ...inputProps }) {
4107
+ return (jsxs("label", { className: `cw-radio ${styles$e.radio}${className ? ` ${className}` : ""}`, "data-direction": direction, children: [jsx("input", { type: "radio", ...inputProps }), label && jsx("span", { children: label })] }));
4108
+ }
4109
+
4110
+ /**
4111
+ * CwRadioGroup - Single-select group of native radio inputs.
4112
+ *
4113
+ * Built on `<input type="radio">` sharing one `name`, so the browser provides radio-group
4114
+ * semantics (roving tabindex, arrow-key navigation) natively. Use for a single choice from a
4115
+ * list of options; for 2–3 options shown as a strip use CwButtonSwitch.
4116
+ *
4117
+ * Layout follows the CwKeyValueList convention with two nested {@link CwLayoutProps} axes
4118
+ * applied as `data-*` attributes: `groupLayout` positions the label relative to the radiogroup
4119
+ * block (root grid), `itemLayout` controls how the radios flow among themselves (options
4120
+ * container) and, on the opposite axis, each radio's own circle-to-text layout.
4121
+ */
4122
+ function CwRadioGroup({ options, value, onChange, labelProps, groupLayout, itemLayout, required, disabled, className, feedback, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "data-testid": dataTestId, }) {
4123
+ const groupName = useId();
4124
+ const feedbackMessages = feedback
4125
+ ? Array.isArray(feedback) ? feedback : [feedback]
4126
+ : [];
4127
+ // Each radio's circle-to-text layout is the opposite of the options flow: a stacked list
4128
+ // (itemLayout column) reads best with the circle beside the text; a side-by-side row reads
4129
+ // best with the circle above the text.
4130
+ const radioDirection = itemLayout?.direction === "row" ? "column" : "row";
4131
+ return (jsxs("div", { className: `cw-radio-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$e.options, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : (ariaLabel ?? labelProps?.text), "aria-required": required || undefined, "data-direction": itemLayout?.direction ?? "column", "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4074
4132
  }
4075
4133
 
4076
4134
  function CwToggle(props) {
4077
- const { labelProps, labelText, iconProps, alignment = "row", className, style, ...inputProps } = props;
4078
- const displayText = labelText || labelProps?.text;
4079
- return (jsx("div", { className: `cw-toggle ${className ? ` ${className}` : ''}`, style: style, children: jsxs("label", { className: "cw-toggle-label", "data-direction": alignment, children: [displayText && (jsxs("span", { className: "cw-icon-text", children: [iconProps && jsx(CwIcon, { ...iconProps }), displayText] })), jsx("input", {
4135
+ const { labelProps, labelText, direction, alignment, className, style, ...inputProps } = props;
4136
+ const resolvedDirection = direction ?? alignment ?? "row";
4137
+ const displayText = labelProps?.text ?? labelText;
4138
+ return (jsx("div", { className: `cw-toggle ${className ? ` ${className}` : ''}`, style: style, children: jsxs("label", { className: "cw-toggle-label", "data-direction": resolvedDirection, children: [displayText && (jsx("span", { className: "cw-icon-text", children: displayText })), jsx("input", {
4080
4139
  //data-color={color}
4081
4140
  type: "checkbox", ...inputProps })] }) }));
4082
4141
  }
@@ -4335,7 +4394,7 @@ function CwDropdownFilter(props) {
4335
4394
  return (jsxs("div", { id: props.IdContent, className: containerClassName, children: [props.children, isVisible && (jsx("nav", { className: "cw-dropdown-menu", style: inlineStyles, onMouseLeave: props.onMouseLeave, id: props.idDropDownFilter, role: "menu", children: jsx("ul", { role: "none", children: props.DataSourceDropDownItem?.map((item) => (jsx("li", { id: item.IdDropDown_filter, role: "menuitem", children: item.dropDownFilter_desc }, item.IdDropDown_filter))) }) }))] }));
4336
4395
  }
4337
4396
 
4338
- var styles$a = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
4397
+ var styles$d = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
4339
4398
 
4340
4399
  /**
4341
4400
  * Button that toggles a floating panel with arbitrary children.
@@ -4414,7 +4473,7 @@ function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-st
4414
4473
  }
4415
4474
  panel.showPopover();
4416
4475
  }, [placement]);
4417
- return (jsxs("div", { ref: containerRef, className: styles$a.container, children: [jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsx("div", { ref: panelCallbackRef, className: `${styles$a.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4476
+ return (jsxs("div", { ref: containerRef, className: styles$d.container, children: [jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsx("div", { ref: panelCallbackRef, className: `${styles$d.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4418
4477
  }
4419
4478
 
4420
4479
  function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor, onPrimaryColor) {
@@ -4432,13 +4491,13 @@ function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor
4432
4491
  return result;
4433
4492
  }
4434
4493
 
4435
- var styles$9 = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
4494
+ var styles$c = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
4436
4495
 
4437
4496
  const CwMultiFilterTag = props => {
4438
4497
  const { ID, Name, Value, Category, Removable, PrimaryColor, Selectable, Selected } = props;
4439
4498
  const backgroundColor = `rgb(${PrimaryColor.r},${PrimaryColor.g},${PrimaryColor.b})`;
4440
4499
  const isOutlineMode = Selected && !Removable;
4441
- return (jsx("li", { className: styles$9["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
4500
+ return (jsx("li", { className: styles$c["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
4442
4501
  if (Selectable)
4443
4502
  props.OnSelect?.(props);
4444
4503
  }, children: jsx(CwChip, { label: Name, colorScheme: "custom", customColor: backgroundColor, variant: isOutlineMode ? "outline" : "soft", closable: Removable, onClose: () => props.OnRemove?.(props),
@@ -4448,7 +4507,7 @@ const CwMultiFilterTag = props => {
4448
4507
  } : undefined }) }));
4449
4508
  };
4450
4509
 
4451
- var styles$8 = {"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"};
4510
+ 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"};
4452
4511
 
4453
4512
  /**
4454
4513
  * A multiple filter selector, a MULTI-SELECT even. Allows users to select and filter items based on tags.
@@ -4675,9 +4734,9 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4675
4734
  inputRef.current?.focus();
4676
4735
  }
4677
4736
  };
4678
- return (jsxs("form", { ref: componentRef, id: id, className: `${styles$8["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
4737
+ return (jsxs("form", { ref: componentRef, id: id, className: `${styles$b["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
4679
4738
  e.preventDefault();
4680
- }, children: [jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$8["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-outline-variant)" } : {}, children: [jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.currentTarget.value), autoComplete: "off", placeholder: selectedTags.size === 0 ? placeholder : "", onKeyDown: e => {
4739
+ }, children: [jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$b["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-outline-variant)" } : {}, children: [jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.currentTarget.value), autoComplete: "off", placeholder: selectedTags.size === 0 ? placeholder : "", onKeyDown: e => {
4681
4740
  switch (e.key) {
4682
4741
  case "Enter":
4683
4742
  case "Tab": {
@@ -4704,7 +4763,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4704
4763
  break;
4705
4764
  }
4706
4765
  }
4707
- } })] }), selectedTags.size > 0 && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxs("section", { ref: panelRef, className: styles$8["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxs("nav", { children: [jsx("button", { className: selectedCategory === "All" ? styles$8["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsx("button", { className: selectedCategory === category ? styles$8["category-selected"] : undefined, style: {
4766
+ } })] }), selectedTags.size > 0 && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxs("section", { ref: panelRef, className: styles$b["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxs("nav", { children: [jsx("button", { className: selectedCategory === "All" ? styles$b["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsx("button", { className: selectedCategory === category ? styles$b["category-selected"] : undefined, style: {
4708
4767
  backgroundColor: getColor(category).primary,
4709
4768
  color: getColor(category).onPrimary,
4710
4769
  }, onClick: () => handleClickCategory(category), children: category }, category)))] }), jsx("ul", { children: displayTags
@@ -4730,7 +4789,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4730
4789
  } }, props.ID))) })] }))] }));
4731
4790
  };
4732
4791
 
4733
- var styles$7 = {"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"};
4792
+ 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"};
4734
4793
 
4735
4794
  /**
4736
4795
  * Multi-select input with chip tags and searchable dropdown.
@@ -4865,11 +4924,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
4865
4924
  // Keeping containerRef for any other potential use
4866
4925
  const direction = alignProps?.flexDirection ?? "row";
4867
4926
  const feedbackMessages = feedback ? (Array.isArray(feedback) ? feedback : [feedback]) : [];
4868
- return (jsxs("div", { ref: containerRef, className: `${styles$7.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: `${styles$7.inputBox}${disabled ? ` ${styles$7.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
4869
- inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxs("div", { ref: panelRef, className: styles$7.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxs("div", { className: styles$7.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxs("li", { className: `${styles$7.option}${idx === focusedIndex ? ` ${styles$7.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsx("span", { className: styles$7.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
4927
+ return (jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
4928
+ inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxs("div", { ref: panelRef, className: styles$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxs("li", { className: `${styles$a.option}${idx === focusedIndex ? ` ${styles$a.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
4870
4929
  }
4871
4930
 
4872
- var styles$6 = {"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"};
4931
+ 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"};
4873
4932
 
4874
4933
  function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId: initialSelectedId = null }) {
4875
4934
  const [expanded, setExpanded] = useState(new Set());
@@ -4936,10 +4995,10 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
4936
4995
  const isLeaf = !hasChildren;
4937
4996
  const isSelected = selectedId?.toString().toLowerCase() === node.id.toString().toLowerCase();
4938
4997
  const selectable = allowParentSelection || isLeaf;
4939
- return (jsxs("div", { className: styles$6["tree-item"], children: [jsxs("div", { className: [
4940
- styles$6["tree-node"],
4941
- isSelected && styles$6["selected"],
4942
- !selectable && styles$6["non-selectable"]
4998
+ return (jsxs("div", { className: styles$9["tree-item"], children: [jsxs("div", { className: [
4999
+ styles$9["tree-node"],
5000
+ isSelected && styles$9["selected"],
5001
+ !selectable && styles$9["non-selectable"]
4943
5002
  ].filter(Boolean).join(' '), style: { paddingLeft: `${depth * 24 + 8}px` }, onClick: () => {
4944
5003
  if (selectable) {
4945
5004
  setSelectedId(node.id);
@@ -4948,7 +5007,7 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
4948
5007
  else {
4949
5008
  toggleExpand(node.id);
4950
5009
  }
4951
- }, children: [hasChildren && (jsx(CwIcon, { size: "large", iconId: isExpanded ? "chevron-down" : "chevron-right" })), jsx("div", { className: `${styles$6["tree-label"]} ${!hasChildren ? styles$6["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsx("div", { className: styles$6["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
5010
+ }, children: [hasChildren && (jsx(CwIcon, { size: "large", iconId: isExpanded ? "chevron-down" : "chevron-right" })), jsx("div", { className: `${styles$9["tree-label"]} ${!hasChildren ? styles$9["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsx("div", { className: styles$9["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
4952
5011
  };
4953
5012
  // Function to search for nodes that match the search term
4954
5013
  const searchInTree = (nodes, searchTerm) => {
@@ -4972,7 +5031,129 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
4972
5031
  return results;
4973
5032
  };
4974
5033
  const filteredData = searchInTree(data, search);
4975
- return (jsxs("div", { className: `cw-tree-view ${styles$6["tree-container"]}`, children: [jsxs("header", { children: [jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsx("div", { className: styles$6["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxs("div", { className: styles$6["empty-state"], children: [jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
5034
+ return (jsxs("div", { className: `cw-tree-view ${styles$9["tree-container"]}`, children: [jsxs("header", { children: [jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsx("div", { className: styles$9["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxs("div", { className: styles$9["empty-state"], children: [jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
5035
+ }
5036
+
5037
+ const EXACT_PHRASE = /"([^"]+)"/g;
5038
+ /**
5039
+ * Quoted phrases are matched against the label only; loose words against label + description + href.
5040
+ * Parsed once instead of per node.
5041
+ */
5042
+ function parseSearch(search) {
5043
+ const phrases = Array.from(search.matchAll(EXACT_PHRASE), match => match[1].toLowerCase());
5044
+ const words = search
5045
+ .replace(EXACT_PHRASE, "")
5046
+ .trim()
5047
+ .toLowerCase()
5048
+ .split(/\s+/)
5049
+ .filter(Boolean);
5050
+ return { phrases, words };
5051
+ }
5052
+ /**
5053
+ * Filters a nav tree by a search string, keeping a group whose descendants match.
5054
+ *
5055
+ * Supports `"quoted phrases"` (must appear in the label) alongside loose words (any field) — this is
5056
+ * behaviour users are told about, so don't simplify it.
5057
+ */
5058
+ function filterNavItems(items, search) {
5059
+ if (!search?.trim())
5060
+ return items;
5061
+ const { phrases, words } = parseSearch(search);
5062
+ if (phrases.length === 0 && words.length === 0)
5063
+ return items;
5064
+ const keep = (item, parentMatchedPhrases) => {
5065
+ const label = item.label.toLowerCase();
5066
+ const haystack = [item.label, item.description, item.href].filter(Boolean).join(" ").toLowerCase();
5067
+ const matchesPhrases = phrases.every(phrase => label.includes(phrase));
5068
+ const matchesWords = words.every(word => haystack.includes(word));
5069
+ const selfMatches = (phrases.length === 0 || matchesPhrases || parentMatchedPhrases) && matchesWords;
5070
+ if (!item.children?.length)
5071
+ return selfMatches ? item : null;
5072
+ let children = item.children
5073
+ .map(child => keep(child, matchesPhrases || parentMatchedPhrases))
5074
+ .filter((child) => child !== null);
5075
+ // A phrase-only search narrows the survivors further: each must carry the phrase itself.
5076
+ if (phrases.length > 0 && words.length === 0 && matchesPhrases) {
5077
+ children = children.filter(child => phrases.every(phrase => child.label.toLowerCase().includes(phrase)));
5078
+ }
5079
+ if (children.length > 0)
5080
+ return { ...item, children };
5081
+ // The group matched but nothing under it did. Returning `children: []` would make it a leaf —
5082
+ // and a leaf with no href — so keep the subtree instead of emptying it.
5083
+ return selfMatches ? item : null;
5084
+ };
5085
+ return items
5086
+ .map(item => keep(item, false))
5087
+ .filter((item) => item !== null);
5088
+ }
5089
+
5090
+ /**
5091
+ * Sorts the top level alphabetically, leaving every nested list in the order the consumer gave.
5092
+ *
5093
+ * Deliberately level 1 only: this exists because a long list of modules is hard to scan, while the
5094
+ * pages inside a module are ordered on purpose. Returns the input untouched when not sorting.
5095
+ */
5096
+ function sortNavItems(items, alphabetically) {
5097
+ if (!alphabetically)
5098
+ return items;
5099
+ return [...items].sort((first, second) => first.label.localeCompare(second.label));
5100
+ }
5101
+
5102
+ 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"};
5103
+
5104
+ const SKELETON_ROW_COUNT = 5;
5105
+ const defaultRenderLink = (item, children) => (jsx("a", { href: item.href, children: children }));
5106
+ /** Sizes only its own icons — content injected via `renderLink` is styled by the consumer. */
5107
+ function CwNavMenu({ items, loading = false, isActive, renderLink = defaultRenderLink, showExpandIndicator = false, search, emptyMessage, sortAlphabetically = false, favoritesSlot, favoritesLabel = "Favorites", favoritesProps, isFavorite, beforeTreeSlot, className, ...navProps }) {
5108
+ const visibleItems = sortNavItems(filterNavItems(items, search), sortAlphabetically);
5109
+ const showEmptyMessage = !loading && Boolean(emptyMessage) && Boolean(search?.trim()) && visibleItems.length === 0;
5110
+ const hasActiveDescendant = (node) => node.children?.some(child => isActive?.(child) || hasActiveDescendant(child)) ?? false;
5111
+ const renderItem = (item, level) => {
5112
+ const children = item.children;
5113
+ if (children && children.length > 0) {
5114
+ return (jsx("li", { children: jsxs("details", { "data-level": level, open: hasActiveDescendant(item) || undefined, children: [jsxs("summary", { children: [item.icon && jsx(CwIcon, { iconId: item.icon, size: level >= 2 ? "small" : "medium" }), item.label, (showExpandIndicator || level >= 2) && (jsx(CwIcon, { iconId: "chevron-down", size: "small", className: styles$8.expandIndicator }))] }), jsx("ul", { children: children.map(child => renderItem(child, level + 1)) })] }) }, item.id));
5115
+ }
5116
+ return (jsx("li", { "data-active": isActive?.(item) ? "true" : undefined, children: renderLink(item, jsxs(Fragment, { children: [item.icon && jsx(CwIcon, { iconId: item.icon, size: "medium" }), item.label, isFavorite?.(item) && jsx(CwIcon, { iconId: "star", size: "small", className: styles$8.favoriteStar })] })) }, item.id));
5117
+ };
5118
+ return (jsxs("nav", { ...navProps, className: [styles$8.menu, className].filter(Boolean).join(" "), children: [favoritesSlot && (jsxs("details", { open: true, ...favoritesProps, className: [styles$8.favorites, favoritesProps?.className].filter(Boolean).join(" "), children: [jsxs("summary", { children: [jsx(CwIcon, { iconId: "star", size: "medium" }), favoritesLabel] }), jsx("div", { className: styles$8.favoritesContent, children: favoritesSlot })] })), beforeTreeSlot, jsx("ul", { children: loading
5119
+ ? Array.from({ length: SKELETON_ROW_COUNT }, (_unused, index) => (jsx("li", { className: styles$8.skeleton }, index)))
5120
+ : visibleItems.map(item => renderItem(item, 1)) }), showEmptyMessage && jsx("p", { className: styles$8.emptyMessage, children: emptyMessage })] }));
5121
+ }
5122
+
5123
+ /**
5124
+ * Pure keyboard-navigation resolver shared by the `CwSearchInput` combobox.
5125
+ * Kept side-effect-free so the arrow/home/end/enter/escape behaviour can be unit
5126
+ * tested without a DOM (the library's vitest runs with `environment: "node"`).
5127
+ */
5128
+ /**
5129
+ * Resolves a key press against the current highlight into a {@link SearchKeyAction}.
5130
+ * Arrow navigation wraps around; `Enter` selects only when a valid row is highlighted.
5131
+ *
5132
+ * @param key `KeyboardEvent.key` value.
5133
+ * @param currentIndex Currently highlighted option index (`-1` = none).
5134
+ * @param optionsLength Number of options currently in the dropdown.
5135
+ */
5136
+ function resolveSearchKeyAction(key, currentIndex, optionsLength) {
5137
+ if (optionsLength <= 0)
5138
+ return { type: "none" };
5139
+ switch (key) {
5140
+ case "ArrowDown":
5141
+ return { type: "move", index: currentIndex < optionsLength - 1 ? currentIndex + 1 : 0 };
5142
+ case "ArrowUp":
5143
+ return { type: "move", index: currentIndex > 0 ? currentIndex - 1 : optionsLength - 1 };
5144
+ case "Home":
5145
+ return { type: "move", index: 0 };
5146
+ case "End":
5147
+ return { type: "move", index: optionsLength - 1 };
5148
+ case "Enter":
5149
+ return currentIndex >= 0 && currentIndex < optionsLength
5150
+ ? { type: "select", index: currentIndex }
5151
+ : { type: "none" };
5152
+ case "Escape":
5153
+ return { type: "close" };
5154
+ default:
5155
+ return { type: "none" };
5156
+ }
4976
5157
  }
4977
5158
 
4978
5159
  /**
@@ -4993,14 +5174,19 @@ function CwSearchInput(optionsProps) {
4993
5174
  const [_selectedOption, setSelectedOption] = useState(null);
4994
5175
  const [showDropdown, setShowDropdown] = useState(false);
4995
5176
  const [isLoading, setIsLoading] = useState(false);
5177
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
4996
5178
  const wrapperRef = useRef(null);
5179
+ const inputRef = useRef(null);
5180
+ // Stable ids wiring the combobox input to its listbox popup for assistive tech.
5181
+ const listboxId = useId();
5182
+ const optionId = (index) => `${listboxId}-opt-${index}`;
4997
5183
  const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
4998
5184
  anchorRef: wrapperRef,
4999
5185
  isOpen: showDropdown && filteredOptions.length > 0,
5000
- onClose: () => setShowDropdown(false),
5186
+ onClose: () => { setShowDropdown(false); setHighlightedIndex(-1); },
5001
5187
  });
5002
5188
  // Extract props
5003
- const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, ...otherProps } = optionsProps;
5189
+ const { labelProps, iconProps, alignProps, selectList, handleChange, placeholder = "Search…", disabled, renderOption, style, id, className, defaultValue, autoFocus, ...otherProps } = optionsProps;
5004
5190
  // Get direction for data attribute
5005
5191
  const direction = alignProps?.flexDirection || "row";
5006
5192
  // Make default value selection when loading the component
@@ -5019,9 +5205,10 @@ function CwSearchInput(optionsProps) {
5019
5205
  }
5020
5206
  }, [defaultValue, selectList]);
5021
5207
  const handleInputChange = (event) => {
5022
- const text = event.target.value;
5208
+ const text = event.currentTarget.value;
5023
5209
  setSearchText(text);
5024
5210
  setShowDropdown(true);
5211
+ setHighlightedIndex(-1);
5025
5212
  if (text === "") {
5026
5213
  setFilteredOptions(selectList);
5027
5214
  setSelectedOption(null);
@@ -5044,10 +5231,30 @@ function CwSearchInput(optionsProps) {
5044
5231
  };
5045
5232
  const handleInputFocus = () => {
5046
5233
  setShowDropdown(true);
5234
+ setHighlightedIndex(-1);
5047
5235
  if (searchText === "") {
5048
5236
  setFilteredOptions(selectList);
5049
5237
  }
5050
5238
  };
5239
+ const handleKeyDown = (event) => {
5240
+ if (!(showDropdown && filteredOptions.length > 0))
5241
+ return;
5242
+ const action = resolveSearchKeyAction(event.key, highlightedIndex, filteredOptions.length);
5243
+ switch (action.type) {
5244
+ case "move":
5245
+ event.preventDefault();
5246
+ setHighlightedIndex(action.index);
5247
+ break;
5248
+ case "select":
5249
+ event.preventDefault();
5250
+ handleOptionSelect(filteredOptions[action.index]);
5251
+ break;
5252
+ case "close":
5253
+ setShowDropdown(false);
5254
+ setHighlightedIndex(-1);
5255
+ break;
5256
+ }
5257
+ };
5051
5258
  const handleInputBlur = () => {
5052
5259
  // Dropdown is closed by useDropdownPortal's outside-click handler.
5053
5260
  // Blur alone must not close it — clicking an option would lose focus before the click fires.
@@ -5059,16 +5266,19 @@ function CwSearchInput(optionsProps) {
5059
5266
  handleChange(option.id);
5060
5267
  }
5061
5268
  setFilteredOptions([]);
5269
+ setHighlightedIndex(-1);
5062
5270
  };
5063
5271
  const handleClearClick = () => {
5064
5272
  setSearchText("");
5065
5273
  setFilteredOptions([]);
5066
5274
  setSelectedOption(null);
5275
+ setHighlightedIndex(-1);
5067
5276
  if (handleChange) {
5068
5277
  handleChange("");
5069
5278
  }
5279
+ inputRef.current?.focus();
5070
5280
  };
5071
- return (jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, id: id, ...otherProps, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { type: "text", value: searchText, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled }), isLoading && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsx(CwIcon, { ...iconProps }) : jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, children: jsx("ul", { children: filteredOptions.map((option) => (jsx("li", { className: dropdownStyles.option, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
5281
+ return (jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, ...otherProps, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, id: id, type: "text", value: searchText, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled, autoFocus: autoFocus, autoComplete: "off", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": showDropdown && filteredOptions.length > 0, "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 ? optionId(highlightedIndex) : undefined }), isLoading && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsx(CwIcon, { ...iconProps }) : jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: filteredOptions.map((option, index) => (jsx("li", { id: optionId(index), className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
5072
5282
  }
5073
5283
 
5074
5284
  /**
@@ -5330,7 +5540,7 @@ const CwSearchAsync = ({ onSearch, onChange, value, onResolveInitial, onResolveS
5330
5540
  }, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeholder, disabled: disabled, required: required, autoComplete: "off", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": showDropdown, "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 ? optionId(highlightedIndex) : undefined, title: tooltipText }), (isLoading || isInitialLoading) && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selection", variant: "icon", icon: "close", color: "neutral" })) : (icon ? jsx(CwIcon, { ...icon }) : jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: options.map((option, index) => (jsx("li", { id: optionId(index), className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.id), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.subLabel ? (jsxs("span", { className: "cw-search-async-option-lines", children: [jsx("span", { children: option.label }), jsx("span", { className: "cw-search-async-option-sub", children: option.subLabel })] })) : (option.label) }, option.id))) }) }))] }));
5331
5541
  };
5332
5542
 
5333
- var styles$5 = {"menu":"cw-context-menu-module__menu__tXmun","item":"cw-context-menu-module__item__-ko8L","arrow":"cw-context-menu-module__arrow__LHZmQ"};
5543
+ var styles$7 = {"menu":"cw-context-menu-module__menu__tXmun","item":"cw-context-menu-module__item__-ko8L","arrow":"cw-context-menu-module__arrow__LHZmQ"};
5334
5544
 
5335
5545
  const ARROW_SIZE = 8;
5336
5546
  const SAFETY_MARGIN = 8;
@@ -5471,14 +5681,14 @@ const CwAnchoredMenu = ({ children, options, onSelect, placement = 'bottom', ope
5471
5681
  document.removeEventListener("keydown", handleEscape);
5472
5682
  };
5473
5683
  }, [isOpen]);
5474
- return (jsxs(Fragment, { children: [jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, style: { display: "contents" }, children: children }), isOpen && normalizedOptions.length > 0 && createPortal(jsxs("div", { ref: menuRef, className: styles$5["menu"], style: {
5684
+ return (jsxs(Fragment, { children: [jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, style: { display: "contents" }, children: children }), isOpen && normalizedOptions.length > 0 && createPortal(jsxs("div", { ref: menuRef, className: styles$7["menu"], style: {
5475
5685
  top: `${position.y}px`,
5476
5686
  left: `${position.x}px`,
5477
- }, "data-has-arrow": "true", children: [jsx("div", { ref: arrowRef, className: styles$5["arrow"], "data-placement": placement }), normalizedOptions.map(option => (jsxs("div", { onClick: (e) => {
5687
+ }, "data-has-arrow": "true", children: [jsx("div", { ref: arrowRef, className: styles$7["arrow"], "data-placement": placement }), normalizedOptions.map(option => (jsxs("div", { onClick: (e) => {
5478
5688
  e.stopPropagation();
5479
5689
  e.preventDefault();
5480
5690
  handleOptionClick(option);
5481
- }, className: `${styles$5["item"]} ${option.disabled ? styles$5["disabled"] : ""}`, "data-disabled": option.disabled, children: [option.icon && jsx("span", { className: styles$5["icon"], children: option.icon }), option.label] }, option.key)))] }), document.body)] }));
5691
+ }, className: `${styles$7["item"]} ${option.disabled ? styles$7["disabled"] : ""}`, "data-disabled": option.disabled, children: [option.icon && jsx("span", { className: styles$7["icon"], children: option.icon }), option.label] }, option.key)))] }), document.body)] }));
5482
5692
  };
5483
5693
 
5484
5694
  /**
@@ -5551,12 +5761,143 @@ const CwContextMenu = ({ children, options, offset = DEFAULT_OFFSET, onSelect })
5551
5761
  document.removeEventListener("keydown", handleEscape);
5552
5762
  };
5553
5763
  }, [isOpen]);
5554
- return (jsxs(Fragment, { children: [jsx("div", { onContextMenu: handleContextMenu, children: children }), isOpen && createPortal(jsx("div", { ref: menuRef, className: styles$5["menu"], style: {
5764
+ return (jsxs(Fragment, { children: [jsx("div", { onContextMenu: handleContextMenu, children: children }), isOpen && createPortal(jsx("div", { ref: menuRef, className: styles$7["menu"], style: {
5555
5765
  top: `${position.y}px`,
5556
5766
  left: `${position.x}px`,
5557
- }, children: options.map(option => (jsx("div", { onClick: () => handleOptionClick(option), className: styles$5["item"], children: option }, option))) }), document.body)] }));
5767
+ }, children: options.map(option => (jsx("div", { onClick: () => handleOptionClick(option), className: styles$7["item"], children: option }, option))) }), document.body)] }));
5558
5768
  };
5559
5769
 
5770
+ var styles$6 = {"split":"cw-button-split-module__split__B2KbU","menu":"cw-button-split-module__menu__mKDlt","item":"cw-button-split-module__item__Aqw6f"};
5771
+
5772
+ /**
5773
+ * CwButtonSplit - A primary action joined to a dropdown of alternative actions.
5774
+ *
5775
+ * Composes a main {@link CwButton} with a {@link CwPopoverButton} chevron whose
5776
+ * panel holds a vertical menu of alternatives (rendered as `variant="ghost"` rows).
5777
+ * Both parts share variant, color and size and read as one joined control.
5778
+ *
5779
+ * @example
5780
+ * <CwButtonSplit
5781
+ * text="Save"
5782
+ * icon="save"
5783
+ * onClick={handleSave}
5784
+ * actions={[
5785
+ * { key: "saveAs", label: "Save as…", icon: "copy" },
5786
+ * { key: "saveAndClose", label: "Save and close" },
5787
+ * ]}
5788
+ * onSelect={handleSelect}
5789
+ * />
5790
+ */
5791
+ function CwButtonSplit({ text, icon, onClick, actions, onSelect, variant = "solid", color = "primary", size = "medium", disabled = false, placement = "bottom-end", "data-testid": dataTestId, }) {
5792
+ const handleSelect = (action) => (event) => {
5793
+ onSelect(action.key);
5794
+ event.currentTarget.closest("[popover]")?.hidePopover();
5795
+ };
5796
+ return (jsxs("div", { className: styles$6.split, "data-variant": variant, "data-testid": dataTestId, children: [jsx(CwButton, { text: text, icon: icon, variant: variant, color: color, size: size, onClick: onClick, disabled: disabled }), jsx(CwPopoverButton, { icon: "chevron-down", title: "More actions", variant: variant, color: color, size: size, disabled: disabled, placement: placement, children: jsx("div", { className: styles$6.menu, children: actions.map((action) => (jsx(CwButton, { variant: "ghost", color: "neutral", text: action.label, icon: action.icon, disabled: action.disabled, className: styles$6.item, onClick: handleSelect(action) }, action.key))) }) })] }));
5797
+ }
5798
+
5799
+ /**
5800
+ * Roving-tabindex single-select behaviour for a custom radio group (e.g. a segmented
5801
+ * button strip that has no native grouping). The active segment is the selected one,
5802
+ * or the first enabled option when nothing is selected. Arrow keys (Right/Down = next,
5803
+ * Left/Up = previous) move focus and select, wrapping around and skipping disabled
5804
+ * options; Space/Enter selects the focused segment.
5805
+ *
5806
+ * Native form controls (e.g. `<input type="radio">` sharing a name) already get this
5807
+ * behaviour from the browser — use this hook only for non-native custom groups.
5808
+ */
5809
+ function useRovingSingleSelect(options, value, onChange) {
5810
+ const elementRefs = useRef([]);
5811
+ const selectedIndex = options.findIndex((option) => option.value === value);
5812
+ const firstEnabledIndex = options.findIndex((option) => !option.disabled);
5813
+ // If the selected option is disabled it cannot hold the tab stop (disabled elements are out of
5814
+ // the tab order), so fall back to the first enabled option to keep the group reachable by Tab.
5815
+ const activeIndex = selectedIndex >= 0 && !options[selectedIndex]?.disabled ? selectedIndex : firstEnabledIndex;
5816
+ const focusAndSelect = useCallback((index) => {
5817
+ const option = options[index];
5818
+ if (!option || option.disabled)
5819
+ return;
5820
+ onChange(option.value);
5821
+ elementRefs.current[index]?.focus();
5822
+ }, [options, onChange]);
5823
+ const moveFocus = useCallback((fromIndex, direction) => {
5824
+ const count = options.length;
5825
+ if (count === 0)
5826
+ return;
5827
+ let nextIndex = fromIndex;
5828
+ for (let step = 0; step < count; step++) {
5829
+ nextIndex = (nextIndex + direction + count) % count;
5830
+ if (!options[nextIndex]?.disabled) {
5831
+ focusAndSelect(nextIndex);
5832
+ return;
5833
+ }
5834
+ }
5835
+ }, [options, focusAndSelect]);
5836
+ const getSegmentProps = useCallback((index) => ({
5837
+ tabIndex: index === activeIndex ? 0 : -1,
5838
+ ref: (element) => {
5839
+ elementRefs.current[index] = element;
5840
+ },
5841
+ onKeyDown: (event) => {
5842
+ switch (event.key) {
5843
+ case "ArrowRight":
5844
+ case "ArrowDown":
5845
+ event.preventDefault();
5846
+ moveFocus(index, 1);
5847
+ break;
5848
+ case "ArrowLeft":
5849
+ case "ArrowUp":
5850
+ event.preventDefault();
5851
+ moveFocus(index, -1);
5852
+ break;
5853
+ case " ":
5854
+ case "Enter":
5855
+ event.preventDefault();
5856
+ focusAndSelect(index);
5857
+ break;
5858
+ }
5859
+ },
5860
+ }), [activeIndex, moveFocus, focusAndSelect]);
5861
+ return { activeIndex, getSegmentProps };
5862
+ }
5863
+
5864
+ var styles$5 = {"switch":"cw-button-switch-module__switch__vdWV-","segment":"cw-button-switch-module__segment__JmVla","iconOnly":"cw-button-switch-module__iconOnly__-kCwj"};
5865
+
5866
+ /**
5867
+ * CwButtonSwitch - Segmented single-select control: a strip of joined CwButtons.
5868
+ *
5869
+ * The selected segment renders `solid`, the others `outline`, both sharing the `color`
5870
+ * theme (`primary` default, `danger`, or `neutral`). It is a proper ARIA radiogroup with
5871
+ * roving tabindex (one tab stop) and arrow-key navigation, provided by
5872
+ * {@link useRovingSingleSelect}. Use for 2–3 mutually-exclusive options that benefit from
5873
+ * being shown side by side; for a longer list use CwRadioGroup.
5874
+ *
5875
+ * `direction="column"` renders the strip vertically (stacked, full-width segments) instead of
5876
+ * the default horizontal `row`; arrow-key navigation handles both orientations.
5877
+ *
5878
+ * Set `iconOnly` to render just each option's icon; the option's `label` is still required
5879
+ * and is passed as the segment title, so it becomes the tooltip and the accessible name.
5880
+ *
5881
+ * It is an inline control with no form label — if a caption is needed, place it next to the
5882
+ * control at the call site, and pass `aria-label` (or `aria-labelledby`) to name the radiogroup
5883
+ * for screen readers.
5884
+ *
5885
+ * @example
5886
+ * <CwButtonSwitch
5887
+ * options={[{ value: "list", label: "List", icon: "list" }, { value: "grid", label: "Grid", icon: "grid" }]}
5888
+ * value={view}
5889
+ * onChange={setView}
5890
+ * />
5891
+ */
5892
+ function CwButtonSwitch({ options, value, onChange, size = "medium", color = "primary", iconOnly = false, direction = "row", disabled = false, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "data-testid": dataTestId, }) {
5893
+ const { getSegmentProps } = useRovingSingleSelect(options, value, onChange);
5894
+ return (jsx("div", { className: `cw-button-switch ${styles$5.switch}`, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : ariaLabel, "data-direction": direction, "data-testid": dataTestId, children: options.map((option, index) => {
5895
+ const selected = option.value === value;
5896
+ const segmentProps = getSegmentProps(index);
5897
+ return (jsx(CwButton, { text: iconOnly ? undefined : option.label, title: iconOnly ? option.label : undefined, icon: option.icon, size: size, color: color, variant: selected ? "solid" : "outline", role: "radio", "aria-checked": selected, disabled: disabled || option.disabled, onClick: () => onChange(option.value), className: `${styles$5.segment}${iconOnly ? ` ${styles$5.iconOnly}` : ""}`, tabIndex: segmentProps.tabIndex, ref: segmentProps.ref, onKeyDown: segmentProps.onKeyDown }, option.value));
5898
+ }) }));
5899
+ }
5900
+
5560
5901
  /**
5561
5902
  * Save button wrapper (6 uses pending delete)
5562
5903
  * @deprecated Use <CwButton variant="icon" icon="save" onClick={...} /> instead
@@ -11100,4 +11441,4 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
11100
11441
  }, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected crewmember", variant: "icon", icon: "close", color: "neutral" })) : (jsx(CwIcon, { iconId: "person" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: options.map((option, index) => (jsx("li", { className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.value), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.text }, option.value))) }) }))] }));
11101
11442
  };
11102
11443
 
11103
- export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDateTimePickerTemporal, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUpload, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwLoadingSmall, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNote, CwOption, CwPopoverButton, CwReportModal, CwScheduler, CwSearchAsync, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PRESET_LIBRARY_TEMPORAL, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, eventIsVisible, filterVisibleEvents, getDefaultDivisions, getEventSizes, getPresetsByKeysTemporal, itemsToMultiFilterTags, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };
11444
+ export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwButtonSplit, CwButtonSwitch, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDateTimePickerTemporal, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNavMenu, CwNote, CwOption, CwPopoverButton, CwRadioGroup, CwReportModal, CwScheduler, CwSearchAsync, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PRESET_LIBRARY_TEMPORAL, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, configureCwLoading, eventIsVisible, filterNavItems, filterVisibleEvents, getCwLoadingDefaults, getDefaultDivisions, getEventSizes, getPresetsByKeysTemporal, itemsToMultiFilterTags, sortNavItems, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };