@cwellt_software/cwellt-reactjs-lib 1.6.2 → 1.7.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 (120) hide show
  1. package/dist/index.cjs.js +2522 -166
  2. package/dist/index.css +1 -1
  3. package/dist/index.d.ts +697 -5
  4. package/dist/index.es.js +2508 -167
  5. package/dist/src/components/control/choice/tag-selector/CwTagSelector.d.ts.map +1 -1
  6. package/dist/src/components/control/choice/tag-selector/CwTagSelector.stories.d.ts +2 -0
  7. package/dist/src/components/control/choice/tag-selector/CwTagSelector.stories.d.ts.map +1 -1
  8. package/dist/src/components/custom/report-viewer/CwReportGauge.d.ts +19 -0
  9. package/dist/src/components/custom/report-viewer/CwReportGauge.d.ts.map +1 -0
  10. package/dist/src/components/custom/report-viewer/CwReportLineChart.d.ts +21 -0
  11. package/dist/src/components/custom/report-viewer/CwReportLineChart.d.ts.map +1 -0
  12. package/dist/src/components/custom/report-viewer/CwReportPage.d.ts +36 -0
  13. package/dist/src/components/custom/report-viewer/CwReportPage.d.ts.map +1 -0
  14. package/dist/src/components/custom/report-viewer/CwReportParameterForm.d.ts +26 -0
  15. package/dist/src/components/custom/report-viewer/CwReportParameterForm.d.ts.map +1 -0
  16. package/dist/src/components/custom/report-viewer/CwReportPieChart.d.ts +13 -0
  17. package/dist/src/components/custom/report-viewer/CwReportPieChart.d.ts.map +1 -0
  18. package/dist/src/components/custom/report-viewer/CwReportToolbar.d.ts +40 -0
  19. package/dist/src/components/custom/report-viewer/CwReportToolbar.d.ts.map +1 -0
  20. package/dist/src/components/custom/report-viewer/CwReportViewer.d.ts +50 -0
  21. package/dist/src/components/custom/report-viewer/CwReportViewer.d.ts.map +1 -0
  22. package/dist/src/components/custom/report-viewer/ReportItem.d.ts +21 -0
  23. package/dist/src/components/custom/report-viewer/ReportItem.d.ts.map +1 -0
  24. package/dist/src/components/custom/report-viewer/ReportTextbox.d.ts +10 -0
  25. package/dist/src/components/custom/report-viewer/ReportTextbox.d.ts.map +1 -0
  26. package/dist/src/components/custom/report-viewer/logic/rdlChartMarkers.d.ts +26 -0
  27. package/dist/src/components/custom/report-viewer/logic/rdlChartMarkers.d.ts.map +1 -0
  28. package/dist/src/components/custom/report-viewer/logic/rdlChartScale.d.ts +75 -0
  29. package/dist/src/components/custom/report-viewer/logic/rdlChartScale.d.ts.map +1 -0
  30. package/dist/src/components/custom/report-viewer/logic/rdlFind.d.ts +38 -0
  31. package/dist/src/components/custom/report-viewer/logic/rdlFind.d.ts.map +1 -0
  32. package/dist/src/components/custom/report-viewer/logic/rdlGauge.d.ts +40 -0
  33. package/dist/src/components/custom/report-viewer/logic/rdlGauge.d.ts.map +1 -0
  34. package/dist/src/components/custom/report-viewer/logic/rdlListMarkers.d.ts +12 -0
  35. package/dist/src/components/custom/report-viewer/logic/rdlListMarkers.d.ts.map +1 -0
  36. package/dist/src/components/custom/report-viewer/logic/rdlNumberFormat.d.ts +8 -0
  37. package/dist/src/components/custom/report-viewer/logic/rdlNumberFormat.d.ts.map +1 -0
  38. package/dist/src/components/custom/report-viewer/logic/rdlPageGeometry.d.ts +38 -0
  39. package/dist/src/components/custom/report-viewer/logic/rdlPageGeometry.d.ts.map +1 -0
  40. package/dist/src/components/custom/report-viewer/logic/rdlParameterValues.d.ts +42 -0
  41. package/dist/src/components/custom/report-viewer/logic/rdlParameterValues.d.ts.map +1 -0
  42. package/dist/src/components/custom/report-viewer/logic/rdlStyle.d.ts +62 -0
  43. package/dist/src/components/custom/report-viewer/logic/rdlStyle.d.ts.map +1 -0
  44. package/dist/src/components/custom/report-viewer/logic/rdlTableLayout.d.ts +33 -0
  45. package/dist/src/components/custom/report-viewer/logic/rdlTableLayout.d.ts.map +1 -0
  46. package/dist/src/components/custom/report-viewer/logic/rdlToggles.d.ts +20 -0
  47. package/dist/src/components/custom/report-viewer/logic/rdlToggles.d.ts.map +1 -0
  48. package/dist/src/components/custom/report-viewer/logic/rdlUnits.d.ts +9 -0
  49. package/dist/src/components/custom/report-viewer/logic/rdlUnits.d.ts.map +1 -0
  50. package/dist/src/components/custom/report-viewer/logic/reportOutputGuard.d.ts +20 -0
  51. package/dist/src/components/custom/report-viewer/logic/reportOutputGuard.d.ts.map +1 -0
  52. package/dist/src/components/custom/report-viewer/logic/reportViewerLayout.d.ts +17 -0
  53. package/dist/src/components/custom/report-viewer/logic/reportViewerLayout.d.ts.map +1 -0
  54. package/dist/src/components/custom/report-viewer/rdlTypes.d.ts +333 -0
  55. package/dist/src/components/custom/report-viewer/rdlTypes.d.ts.map +1 -0
  56. package/dist/src/components/custom/report-viewer/reportChartShared.d.ts +53 -0
  57. package/dist/src/components/custom/report-viewer/reportChartShared.d.ts.map +1 -0
  58. package/dist/src/components/custom/report-viewer/reportRenderContext.d.ts +25 -0
  59. package/dist/src/components/custom/report-viewer/reportRenderContext.d.ts.map +1 -0
  60. package/dist/src/components/custom/report-viewer/useReportParameterForm.d.ts +30 -0
  61. package/dist/src/components/custom/report-viewer/useReportParameterForm.d.ts.map +1 -0
  62. package/dist/src/components/custom/report-viewer/useReportViewerState.d.ts +74 -0
  63. package/dist/src/components/custom/report-viewer/useReportViewerState.d.ts.map +1 -0
  64. package/dist/src/components/custom/report-viewer/useSidebarResize.d.ts +22 -0
  65. package/dist/src/components/custom/report-viewer/useSidebarResize.d.ts.map +1 -0
  66. package/dist/src/components/custom/scheduler-new/presentation/Scheduler.stories.d.ts +18 -1
  67. package/dist/src/components/custom/scheduler-new/presentation/Scheduler.stories.d.ts.map +1 -1
  68. package/dist/src/components/custom/scheduler-new/presentation/components/row/DefaultRowHeader.d.ts +2 -0
  69. package/dist/src/components/custom/scheduler-new/presentation/components/row/DefaultRowHeader.d.ts.map +1 -1
  70. package/dist/src/components/custom/scheduler-new/presentation/components/row/Event.d.ts +15 -0
  71. package/dist/src/components/custom/scheduler-new/presentation/components/row/Event.d.ts.map +1 -1
  72. package/dist/src/components/custom/super-scheduler/PinRowHeader.d.ts +0 -1
  73. package/dist/src/components/custom/super-scheduler/PinRowHeader.d.ts.map +1 -1
  74. package/dist/src/components/display/data/table/CwTable.d.ts.map +1 -1
  75. package/dist/src/components/display/data/table/CwTable.stories.d.ts +2 -0
  76. package/dist/src/components/display/data/table/CwTable.stories.d.ts.map +1 -1
  77. package/dist/src/components/display/data/tooltip_manager/CwTooltipManager.d.ts +1 -1
  78. package/dist/src/components/display/data/tooltip_manager/CwTooltipManager.d.ts.map +1 -1
  79. package/dist/src/components/layout/card/CwCard.d.ts +2 -2
  80. package/dist/src/components/layout/card/CwCard.d.ts.map +1 -1
  81. package/dist/src/components/layout/card/CwCard.stories.d.ts +4 -2
  82. package/dist/src/components/layout/card/CwCard.stories.d.ts.map +1 -1
  83. package/dist/src/index.d.ts +16 -1
  84. package/dist/src/index.d.ts.map +1 -1
  85. package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
  86. package/dist/src/playground/pages/ReportViewerPage.d.ts +8 -0
  87. package/dist/src/playground/pages/ReportViewerPage.d.ts.map +1 -0
  88. package/dist/src/playground/pages/reportViewerFakeData.d.ts +13 -0
  89. package/dist/src/playground/pages/reportViewerFakeData.d.ts.map +1 -0
  90. package/dist/test/components/custom/report-viewer/rdlChartMarkers.test.d.ts +2 -0
  91. package/dist/test/components/custom/report-viewer/rdlChartMarkers.test.d.ts.map +1 -0
  92. package/dist/test/components/custom/report-viewer/rdlChartScale.test.d.ts +2 -0
  93. package/dist/test/components/custom/report-viewer/rdlChartScale.test.d.ts.map +1 -0
  94. package/dist/test/components/custom/report-viewer/rdlFind.test.d.ts +2 -0
  95. package/dist/test/components/custom/report-viewer/rdlFind.test.d.ts.map +1 -0
  96. package/dist/test/components/custom/report-viewer/rdlGauge.test.d.ts +2 -0
  97. package/dist/test/components/custom/report-viewer/rdlGauge.test.d.ts.map +1 -0
  98. package/dist/test/components/custom/report-viewer/rdlNumberFormat.test.d.ts +2 -0
  99. package/dist/test/components/custom/report-viewer/rdlNumberFormat.test.d.ts.map +1 -0
  100. package/dist/test/components/custom/report-viewer/rdlParameterValues.test.d.ts +2 -0
  101. package/dist/test/components/custom/report-viewer/rdlParameterValues.test.d.ts.map +1 -0
  102. package/dist/test/components/custom/report-viewer/rdlTableLayout.test.d.ts +2 -0
  103. package/dist/test/components/custom/report-viewer/rdlTableLayout.test.d.ts.map +1 -0
  104. package/dist/test/components/custom/report-viewer/rdlText.test.d.ts +2 -0
  105. package/dist/test/components/custom/report-viewer/rdlText.test.d.ts.map +1 -0
  106. package/dist/test/components/custom/report-viewer/rdlToggles.test.d.ts +2 -0
  107. package/dist/test/components/custom/report-viewer/rdlToggles.test.d.ts.map +1 -0
  108. package/dist/test/components/custom/report-viewer/rdlUnits.test.d.ts +2 -0
  109. package/dist/test/components/custom/report-viewer/rdlUnits.test.d.ts.map +1 -0
  110. package/dist/test/components/custom/report-viewer/reportOutputGuard.test.d.ts +2 -0
  111. package/dist/test/components/custom/report-viewer/reportOutputGuard.test.d.ts.map +1 -0
  112. package/dist/test/components/custom/report-viewer/reportViewerLayout.test.d.ts +2 -0
  113. package/dist/test/components/custom/report-viewer/reportViewerLayout.test.d.ts.map +1 -0
  114. package/dist/test/components/custom/report-viewer/useReportParameterForm.test.d.ts +2 -0
  115. package/dist/test/components/custom/report-viewer/useReportParameterForm.test.d.ts.map +1 -0
  116. package/dist/test/components/custom/report-viewer/useReportViewerState.test.d.ts +2 -0
  117. package/dist/test/components/custom/report-viewer/useReportViewerState.test.d.ts.map +1 -0
  118. package/dist/test/helpers/renderHookHeadless.d.ts +8 -0
  119. package/dist/test/helpers/renderHookHeadless.d.ts.map +1 -0
  120. package/package.json +1 -1
package/dist/index.cjs.js CHANGED
@@ -194,7 +194,7 @@ function getContrastColor(color) {
194
194
  return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
195
195
  }
196
196
 
197
- var styles$A = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
197
+ var styles$D = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
198
198
 
199
199
  // Constants
200
200
  const margin$1 = 16;
@@ -484,7 +484,7 @@ const CwTooltipManager = () => {
484
484
  if (!state.isVisible || !state.content) {
485
485
  return null;
486
486
  }
487
- return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$A["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
487
+ return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$D["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
488
488
  top: `${tooltipPosition.top}px`,
489
489
  left: `${tooltipPosition.left}px`,
490
490
  opacity: (isPositioned && !isMeasuring) ? 1 : 0,
@@ -565,7 +565,7 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
565
565
  React.useEffect(() => {
566
566
  ensureTooltipManager();
567
567
  }, []);
568
- return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$A["cw-tooltip"], children: children }));
568
+ return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$D["cw-tooltip"], children: children }));
569
569
  };
570
570
 
571
571
  const SVG_ICONS = {
@@ -685,7 +685,7 @@ function resolveBadgeAria(label, loading, hasText) {
685
685
  return hasText ? {} : { 'aria-hidden': 'true' };
686
686
  }
687
687
 
688
- var styles$z = {"badge":"cw-badge-module__badge__PKlak"};
688
+ var styles$C = {"badge":"cw-badge-module__badge__PKlak"};
689
689
 
690
690
  /**
691
691
  * CwBadge - the small coloured circle with a number, used for alert and notification counts.
@@ -721,7 +721,7 @@ const CwBadge = ({ count, content, color = 'info', variant = 'solid', size = 'sm
721
721
  ? formatBadgeCount(count, max)
722
722
  : undefined;
723
723
  const isDot = !loading && !hasContent && count === undefined;
724
- const badgeClassNames = ['cw-badge', styles$z.badge, className].filter(Boolean).join(' ');
724
+ const badgeClassNames = ['cw-badge', styles$C.badge, className].filter(Boolean).join(' ');
725
725
  return (jsxRuntime.jsx("span", { ...dataAttributes, className: badgeClassNames, "data-color": color, "data-variant": variant, "data-size": size, "data-loading": loading ? 'true' : undefined, "data-dot": isDot ? 'true' : undefined, ...resolveBadgeAria(label, loading, !loading && (hasContent || countText !== undefined)), style: style, children: loading ? jsxRuntime.jsx(CwIcon, { iconId: "spinner", size: "small" }) : hasContent ? content : countText }));
726
726
  };
727
727
 
@@ -1109,7 +1109,7 @@ function CwLoading({ isLoading = false, text = '', size = 'regular', iconPositio
1109
1109
  return (jsxRuntime.jsxs("div", { "aria-busy": isLoading, className: "cw-loading-container", "data-children": !!children, children: [overlay, jsxRuntime.jsx("div", { className: "cw-loading-disabled-content", children: children })] }));
1110
1110
  }
1111
1111
 
1112
- var styles$y = {"skeleton":"cw-skeleton-module__skeleton__Jvx2x","group":"cw-skeleton-module__group__Cm8AU"};
1112
+ var styles$B = {"skeleton":"cw-skeleton-module__skeleton__Jvx2x","group":"cw-skeleton-module__group__Cm8AU"};
1113
1113
 
1114
1114
  /*
1115
1115
  * Internal helper for skeleton allocations (CwSkeleton, tables, cards).
@@ -1151,8 +1151,8 @@ function CwSkeleton({ variant = 'text', width, height, count = 1, radius, gap })
1151
1151
  };
1152
1152
  // The un-hashed cw-skeleton / cw-skeleton-group classes carry no styles in the
1153
1153
  // library - they are stable public hooks for exceptional external overrides.
1154
- const skeletonClassName = ['cw-skeleton', styles$y.skeleton].filter(Boolean).join(' ');
1155
- const groupClassName = ['cw-skeleton-group', styles$y.group].filter(Boolean).join(' ');
1154
+ const skeletonClassName = ['cw-skeleton', styles$B.skeleton].filter(Boolean).join(' ');
1155
+ const groupClassName = ['cw-skeleton-group', styles$B.group].filter(Boolean).join(' ');
1156
1156
  const lineCount = normalizeSkeletonCount(count, 1);
1157
1157
  if (lineCount <= 1) {
1158
1158
  return (jsxRuntime.jsx("span", { className: skeletonClassName, "data-variant": variant, "aria-hidden": "true", style: style }));
@@ -1164,7 +1164,7 @@ function CwSkeleton({ variant = 'text', width, height, count = 1, radius, gap })
1164
1164
  return (jsxRuntime.jsx("span", { className: groupClassName, "aria-hidden": "true", style: groupStyle, children: skeletonElements }));
1165
1165
  }
1166
1166
 
1167
- var styles$x = {"progress":"cw-progress-module__progress__d-g2-","value":"cw-progress-module__value__Q-DrH","label":"cw-progress-module__label__jwOWp","track":"cw-progress-module__track__572-3","footer":"cw-progress-module__footer__0Wo4G","header":"cw-progress-module__header__mv5ct","fill":"cw-progress-module__fill__fX1UA"};
1167
+ var styles$A = {"progress":"cw-progress-module__progress__d-g2-","value":"cw-progress-module__value__Q-DrH","label":"cw-progress-module__label__jwOWp","track":"cw-progress-module__track__572-3","footer":"cw-progress-module__footer__0Wo4G","header":"cw-progress-module__header__mv5ct","fill":"cw-progress-module__fill__fX1UA"};
1168
1168
 
1169
1169
  /**
1170
1170
  * CwProgress - a determinate or indeterminate progress bar.
@@ -1188,17 +1188,17 @@ function CwProgress({ value, indeterminate = false, label, rightLabel, footer, s
1188
1188
  const valueContent = rightLabel ?? (percent !== undefined ? `${percent}%` : '');
1189
1189
  // The un-hashed cw-progress class carries no styles in the library - a stable
1190
1190
  // public hook for exceptional external overrides only.
1191
- const rootClassName = ['cw-progress', styles$x.progress, className].filter(Boolean).join(' ');
1192
- const labelSpan = label ? jsxRuntime.jsx("span", { className: styles$x.label, id: labelId, children: label }) : null;
1193
- const valueLabel = showValue ? (jsxRuntime.jsx("span", { className: styles$x.value, "data-mono": monoValue || undefined, children: valueContent })) : null;
1194
- return (jsxRuntime.jsxs("div", { ...dataAttributes, className: rootClassName, style: style, "data-layout": layout, "data-size": size, "data-color": color, "data-prominent": prominent || undefined, "data-indeterminate": indeterminate || undefined, children: [layout === 'column' && (labelSpan || valueLabel) && (jsxRuntime.jsxs("header", { className: styles$x.header, children: [labelSpan, valueLabel] })), layout === 'row' && labelSpan, jsxRuntime.jsx("div", { className: styles$x.track, role: "progressbar", ...(label && { 'aria-labelledby': labelId }), ...(!indeterminate && percent !== undefined && {
1191
+ const rootClassName = ['cw-progress', styles$A.progress, className].filter(Boolean).join(' ');
1192
+ const labelSpan = label ? jsxRuntime.jsx("span", { className: styles$A.label, id: labelId, children: label }) : null;
1193
+ const valueLabel = showValue ? (jsxRuntime.jsx("span", { className: styles$A.value, "data-mono": monoValue || undefined, children: valueContent })) : null;
1194
+ return (jsxRuntime.jsxs("div", { ...dataAttributes, className: rootClassName, style: style, "data-layout": layout, "data-size": size, "data-color": color, "data-prominent": prominent || undefined, "data-indeterminate": indeterminate || undefined, children: [layout === 'column' && (labelSpan || valueLabel) && (jsxRuntime.jsxs("header", { className: styles$A.header, children: [labelSpan, valueLabel] })), layout === 'row' && labelSpan, jsxRuntime.jsx("div", { className: styles$A.track, role: "progressbar", ...(label && { 'aria-labelledby': labelId }), ...(!indeterminate && percent !== undefined && {
1195
1195
  'aria-valuenow': percent,
1196
1196
  'aria-valuemin': 0,
1197
1197
  'aria-valuemax': 100
1198
- }), children: jsxRuntime.jsx("div", { className: styles$x.fill, style: !indeterminate && clamped !== undefined ? { width: `${clamped}%` } : undefined }) }), layout === 'row' && valueLabel, footer != null && jsxRuntime.jsx("footer", { className: styles$x.footer, children: footer })] }));
1198
+ }), children: jsxRuntime.jsx("div", { className: styles$A.fill, style: !indeterminate && clamped !== undefined ? { width: `${clamped}%` } : undefined }) }), layout === 'row' && valueLabel, footer != null && jsxRuntime.jsx("footer", { className: styles$A.footer, children: footer })] }));
1199
1199
  }
1200
1200
 
1201
- var styles$w = {"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"};
1201
+ var styles$z = {"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"};
1202
1202
 
1203
1203
  // Constants moved outside to prevent recreation
1204
1204
  const margin = 16;
@@ -1325,12 +1325,12 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1325
1325
  const { setTooltipTimeout, clearTooltipTimeout } = useTooltipDelay(() => {
1326
1326
  setIsVisible(true);
1327
1327
  }, showDelay);
1328
- const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$w["cw-generic-tooltip-content"]);
1328
+ const { position: tooltipPosition, actualPosition } = useTooltipPosition(isVisible, containerRef, position, styles$z["cw-generic-tooltip-content"]);
1329
1329
  // Memoize tooltip content creation
1330
1330
  const tooltipContent = React.useMemo(() => {
1331
1331
  if (hide || !isVisible || !content)
1332
1332
  return null;
1333
- return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$w["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
1333
+ return reactDom.createPortal(jsxRuntime.jsx("div", { className: styles$z["cw-generic-tooltip-content"], "data-position": actualPosition, "data-visible": isVisible, "data-inline": displayInline, style: {
1334
1334
  position: 'fixed',
1335
1335
  top: `${tooltipPosition.top}px`,
1336
1336
  left: `${tooltipPosition.left}px`,
@@ -1345,7 +1345,7 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1345
1345
  clearTooltipTimeout();
1346
1346
  setIsVisible(false);
1347
1347
  }, [clearTooltipTimeout]);
1348
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$w["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1348
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$z["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1349
1349
  };
1350
1350
 
1351
1351
  const CwButton = React.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", badge, children, ...buttonProps }, ref) {
@@ -1413,7 +1413,7 @@ function CwModal(custModalProps) {
1413
1413
  return (jsxRuntime.jsx("div", { children: custModalProps.modalState && (jsxRuntime.jsxs("div", { className: custModalProps.classNameModalOverlay + " cwelltModalOverlay", children: [jsxRuntime.jsx("div", { className: "cwelltModalOverlayBg", onClick: custModalProps.onCloseModal }), jsxRuntime.jsx(Draggable, { disabled: isModalDisabled, axis: "both", nodeRef: draggableRef, children: jsxRuntime.jsxs("div", { className: custModalProps.classNameModal + " cwelltContainerModal", ref: draggableRef, style: widthModalDef !== "40em" ? modalStyle.widthCustomStyle : modalStyle.widthDefStyle, children: [jsxRuntime.jsxs("div", { className: "cwelltModalHeader", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: [jsxRuntime.jsx("div", { className: "cwelltModalTitle", children: custModalProps.titleModal }), jsxRuntime.jsx("button", { className: "cwelltBtnCloseModal", onClick: custModalProps.onCloseModal, children: jsxRuntime.jsx("span", { className: "cwelltCloseIcon" }) })] }), jsxRuntime.jsx("div", { className: "cwelltModalBody", children: jsxRuntime.jsx("div", { className: "cwelltContainerModalBody", style: { position: "relative" }, children: custModalProps.children }) }), isHide === false ? (jsxRuntime.jsx("footer", { className: "legacy-modal-footer", onMouseOver: cwelltOnMouseOverModal, onMouseOut: cwelltOnMouseOutModal, children: jsxRuntime.jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: custModalProps.onSaveModal, form: custModalProps.formSaveModal, hidden: custModalProps.HideBtnModal, type: custModalProps.HtmlSubmitModal }) })) : (jsxRuntime.jsx("div", { style: { display: "none" } }))] }) })] })) }));
1414
1414
  }
1415
1415
 
1416
- var styles$v = {"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"};
1416
+ var styles$y = {"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"};
1417
1417
 
1418
1418
  /**
1419
1419
  * Small anchored confirmation for a destructive action.
@@ -1482,15 +1482,15 @@ function CwConfirmationPopup(props) {
1482
1482
  onCancel();
1483
1483
  }
1484
1484
  };
1485
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderChildren(), isOpen && (jsxRuntime.jsx("div", { className: styles$v.overlayPositioned, onClick: handleOverlayClick, children: jsxRuntime.jsxs("div", { ref: popupRef, className: styles$v.popup, style: {
1485
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderChildren(), isOpen && (jsxRuntime.jsx("div", { className: styles$y.overlayPositioned, onClick: handleOverlayClick, children: jsxRuntime.jsxs("div", { ref: popupRef, className: styles$y.popup, style: {
1486
1486
  position: 'absolute',
1487
1487
  top: `${position.top}px`,
1488
1488
  left: `${position.left}px`,
1489
1489
  transform: 'none'
1490
- }, children: [jsxRuntime.jsx("p", { className: styles$v.message, children: message }), jsxRuntime.jsxs("div", { className: styles$v.buttons, children: [jsxRuntime.jsx("button", { className: `${styles$v.button} ${styles$v.confirmButton}`, onClick: onConfirm, children: confirmText }), jsxRuntime.jsx("button", { className: `${styles$v.button} ${styles$v.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
1490
+ }, children: [jsxRuntime.jsx("p", { className: styles$y.message, children: message }), jsxRuntime.jsxs("div", { className: styles$y.buttons, children: [jsxRuntime.jsx("button", { className: `${styles$y.button} ${styles$y.confirmButton}`, onClick: onConfirm, children: confirmText }), jsxRuntime.jsx("button", { className: `${styles$y.button} ${styles$y.cancelButton}`, onClick: onCancel, children: cancelText })] })] }) }))] }));
1491
1491
  }
1492
1492
 
1493
- var styles$u = {"cw-dialog-main":"cw-dialog-module__cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module__cw-dialog-button-close__9GRd8"};
1493
+ var styles$x = {"cw-dialog-main":"cw-dialog-module__cw-dialog-main__cHxHt","cw-dialog-button-close":"cw-dialog-module__cw-dialog-button-close__9GRd8"};
1494
1494
 
1495
1495
  // Helper function to parse size values
1496
1496
  const parseSize = (size) => {
@@ -1763,7 +1763,7 @@ const CwDialog = props => {
1763
1763
  }
1764
1764
  }
1765
1765
  }, [open]);
1766
- const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$u["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
1766
+ const header = React.useMemo(() => (jsxRuntime.jsxs("header", { onMouseDown: handleMouseDown, children: [jsxRuntime.jsx("span", { children: headline }), customHeader || (jsxRuntime.jsx("button", { className: styles$x["cw-dialog-button-close"], onClick: onClose }))] })), [handleMouseDown, headline, customHeader, onClose]);
1767
1767
  const content = React.useMemo(() => (jsxRuntime.jsx("section", { children: children })), [children]);
1768
1768
  const footer = React.useMemo(() => (jsxRuntime.jsx("footer", { children: customFooter || (jsxRuntime.jsx(CwButton, { variant: "icon", icon: "save", title: "Save", onClick: onSave, tooltipPosition: "top", disabled: disableSave, "data-testid": "cw-dialog-save" })) })), [customFooter, onSave, disableSave]);
1769
1769
  const resizeHandles = React.useMemo(() => size.autoHeight
@@ -1790,7 +1790,7 @@ const CwDialog = props => {
1790
1790
  : `${convertFromPx(size.height, size.heightUnit)}${size.heightUnit}`;
1791
1791
  return { displayWidth, displayHeight };
1792
1792
  }, [size.width, size.height, size.widthUnit, size.heightUnit, size.autoHeight]);
1793
- const dialogContent = (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$u["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
1793
+ const dialogContent = (jsxRuntime.jsx("div", { "data-has-scrim": hasScrim, className: styles$x["cw-dialog-main"], onMouseDown: handleScrimMouseDown, onMouseUp: handleScrimMouseUpOrLeave, onMouseLeave: handleScrimMouseUpOrLeave, "data-pressing": isPressingScrim, children: jsxRuntime.jsxs("dialog", { ...domProps, ref: dialogRef, style: {
1794
1794
  left: `${position.x}px`,
1795
1795
  top: `${position.y}px`,
1796
1796
  width: displayDimensions.displayWidth,
@@ -1952,7 +1952,7 @@ function CwAlign(props) {
1952
1952
  }, children: props.children }));
1953
1953
  }
1954
1954
 
1955
- var styles$t = {"card":"cw-card-module__card__HJUT0","clickable":"cw-card-module__clickable__Y-V3X","disabled":"cw-card-module__disabled__0wHh1","content":"cw-card-module__content__ma9qy","headerContent":"cw-card-module__headerContent__x4Jfl","footerTags":"cw-card-module__footerTags__80sSW"};
1955
+ var styles$w = {"card":"cw-card-module__card__HJUT0","content":"cw-card-module__content__ma9qy","clickable":"cw-card-module__clickable__Y-V3X","disabled":"cw-card-module__disabled__0wHh1","headerContent":"cw-card-module__headerContent__x4Jfl","footerTags":"cw-card-module__footerTags__80sSW"};
1956
1956
 
1957
1957
  /**
1958
1958
  * CwCard - A simple card component for displaying content in a contained format
@@ -1965,8 +1965,8 @@ var styles$t = {"card":"cw-card-module__card__HJUT0","clickable":"cw-card-module
1965
1965
  * onDelete={confirmDeletion}
1966
1966
  * footer="Last updated: 2 days ago"
1967
1967
  * chips={[
1968
- * { label: 'Important', colorScheme: 'danger' },
1969
- * { label: 'Custom', colorScheme: 'custom', customColor: '#8a2be2' }
1968
+ * { label: 'Important', color: 'danger' },
1969
+ * { label: 'Custom', color: 'custom', customColor: '#8a2be2' }
1970
1970
  * ]}
1971
1971
  * >
1972
1972
  * <p>This is the main content of the card.</p>
@@ -1978,10 +1978,10 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1978
1978
  // Construct class names using CSS modules
1979
1979
  const cardClassNames = [
1980
1980
  'cw-card',
1981
- styles$t.card,
1981
+ styles$w.card,
1982
1982
  className,
1983
- clickable ? styles$t.clickable : '',
1984
- disabled ? styles$t.disabled : '',
1983
+ clickable ? styles$w.clickable : '',
1984
+ disabled ? styles$w.disabled : '',
1985
1985
  ].filter(Boolean).join(' ');
1986
1986
  // Handle click event when card is clickable
1987
1987
  const handleClick = () => {
@@ -1999,15 +1999,15 @@ const CwCard = ({ id, title, subtitle, alignment = 'center', children, footer, o
1999
1999
  const hasFooter = hasChips || footer || (hasActions && resolvedDirection === "row");
2000
2000
  // Actions component to reuse. While loading, each provided action renders a circular
2001
2001
  // ghost sized to the CwButton icon footprint (2rem) - no interactive buttons.
2002
- const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsx("div", { className: styles$t.actions, children: isLoading ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [extraActions && jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" }), onEdit && jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" }), onDelete && jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [extraActions ?? null, onEdit && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) })) : null;
2002
+ const ActionsComponent = hasActions && !disabled ? (jsxRuntime.jsx("div", { className: styles$w.actions, children: isLoading ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [extraActions && jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" }), onEdit && jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" }), onDelete && jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" })] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [extraActions ?? null, onEdit && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "edit", onClick: onEdit }), onDelete && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "delete", color: "danger", onClick: onDelete })] })) })) : null;
2003
2003
  return (jsxRuntime.jsxs("div", { ...(id && { id }), className: cardClassNames, ...(style && { style }), ...(clickable && !isLoading && {
2004
2004
  role: 'button',
2005
2005
  tabIndex: 0,
2006
2006
  onClick: handleClick,
2007
- }), "data-variant": variant, "data-direction": resolvedDirection, "aria-busy": isLoading || undefined, children: [isLoading ? (jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("div", { className: styles$t.headerContent, "data-align": resolvedAlign, children: jsxRuntime.jsx(CwSkeleton, { width: "8rem", height: "1.5em" }) }), resolvedDirection === "column" && ActionsComponent] })) : (hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$t.headerContent, "data-align": resolvedAlign, children: [title && jsxRuntime.jsx("h5", { children: title }), subtitle && jsxRuntime.jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] }))), jsxRuntime.jsx("div", { className: styles$t.content, children: isLoading ? jsxRuntime.jsx(CwSkeleton, { count: normalizeSkeletonCount(skeletonLines, 3) }) : children }), hasFooter && (isLoading ? (jsxRuntime.jsx("footer", { children: jsxRuntime.jsx("div", { className: styles$t.footerTags, children: jsxRuntime.jsx(CwSkeleton, { variant: "rect", width: "4rem", height: "1.5em", radius: "1rem" }) }) })) : (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$t.footerTags, children: chips.map((chip, index) => (jsxRuntime.jsx(CwChip, { label: chip.label, colorScheme: chip.colorScheme, className: styles$t.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsxRuntime.jsx("div", { className: styles$t.footerContent, children: footer }))] }))), resolvedDirection === "row" && ActionsComponent] }));
2007
+ }), "data-variant": variant, "data-direction": resolvedDirection, "aria-busy": isLoading || undefined, children: [isLoading ? (jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("div", { className: styles$w.headerContent, "data-align": resolvedAlign, children: jsxRuntime.jsx(CwSkeleton, { width: "8rem", height: "1.5em" }) }), resolvedDirection === "column" && ActionsComponent] })) : (hasHeader && (jsxRuntime.jsxs("header", { children: [(title || subtitle) && (jsxRuntime.jsxs("div", { className: styles$w.headerContent, "data-align": resolvedAlign, children: [title && jsxRuntime.jsx("h5", { children: title }), subtitle && jsxRuntime.jsx("strong", { children: subtitle })] })), resolvedDirection === "column" && ActionsComponent] }))), jsxRuntime.jsx("div", { className: styles$w.content, children: isLoading ? jsxRuntime.jsx(CwSkeleton, { count: normalizeSkeletonCount(skeletonLines, 3) }) : children }), hasFooter && (isLoading ? (jsxRuntime.jsx("footer", { children: jsxRuntime.jsx("div", { className: styles$w.footerTags, children: jsxRuntime.jsx(CwSkeleton, { variant: "rect", width: "4rem", height: "1.5em", radius: "1rem" }) }) })) : (jsxRuntime.jsxs("footer", { children: [hasChips && (jsxRuntime.jsx("div", { className: styles$w.footerTags, children: chips.map((chip, index) => (jsxRuntime.jsx(CwChip, { label: chip.label, color: chip.color, colorScheme: chip.colorScheme, className: styles$w.chip, ...(chip.customColor && { customColor: chip.customColor }), ...(chip.variant && { variant: chip.variant }), ...(chip.icon && { icon: chip.icon }) }, index))) })), footer && (jsxRuntime.jsx("div", { className: styles$w.footerContent, children: footer }))] }))), resolvedDirection === "row" && ActionsComponent] }));
2008
2008
  };
2009
2009
 
2010
- var styles$s = {"cardContainer":"cw-card-list-module__cardContainer__l3YEh","pagination":"cw-card-list-module__pagination__5Ay78","pageInfo":"cw-card-list-module__pageInfo__uiMel","emptyState":"cw-card-list-module__emptyState__RlqiS"};
2010
+ var styles$v = {"cardContainer":"cw-card-list-module__cardContainer__l3YEh","pagination":"cw-card-list-module__pagination__5Ay78","pageInfo":"cw-card-list-module__pageInfo__uiMel","emptyState":"cw-card-list-module__emptyState__RlqiS"};
2011
2011
 
2012
2012
  /**
2013
2013
  * Option to display in the CwSelect
@@ -2102,10 +2102,10 @@ function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', default
2102
2102
  icon: sortDirection === 'asc' ? 'arrow-up' : 'arrow-down',
2103
2103
  onClick: () => setSortDirection(prev => prev === 'asc' ? 'desc' : 'asc'),
2104
2104
  title: `Sort ${sortDirection === 'asc' ? 'descending' : 'ascending'}`,
2105
- }, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsxRuntime.jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsxRuntime.jsx("div", { className: `${styles$s.cardContainer}`, "data-layout": layout, style: gridStyle, "aria-busy": true, children: Array.from({ length: normalizeSkeletonCount(skeletonCards, 6) }, (_, index) => (jsxRuntime.jsx(CwCard, { isLoading: true, children: null }, `skeleton_${index}`))) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$s.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$s.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$s.pagination, children: [jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxRuntime.jsxs("span", { className: styles$s.pageInfo, children: [currentPage, " / ", totalPages] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
2105
+ }, value: sortKey, onChange: (e) => handleSortChange(e.target.value), children: sortOptions.map(option => (jsxRuntime.jsx(CwOption, { value: option.key, children: option.label }, option.key))) }) })), isLoading ? (jsxRuntime.jsx("div", { className: `${styles$v.cardContainer}`, "data-layout": layout, style: gridStyle, "aria-busy": true, children: Array.from({ length: normalizeSkeletonCount(skeletonCards, 6) }, (_, index) => (jsxRuntime.jsx(CwCard, { isLoading: true, children: null }, `skeleton_${index}`))) })) : sortedItems.length === 0 ? (jsxRuntime.jsx("div", { className: styles$v.emptyState, children: emptyState || jsxRuntime.jsx("p", { children: "No items to display" }) })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: `${styles$v.cardContainer}`, "data-layout": layout, style: gridStyle, children: visibleItems.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: renderCard(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), totalPages > 1 && (jsxRuntime.jsxs("div", { className: styles$v.pagination, children: [jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-left", disabled: currentPage === 1, onClick: () => setCurrentPage(p => Math.max(1, p - 1)) }), jsxRuntime.jsxs("span", { className: styles$v.pageInfo, children: [currentPage, " / ", totalPages] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-right", disabled: currentPage === totalPages, onClick: () => setCurrentPage(p => Math.min(totalPages, p + 1)) })] }))] }))] }));
2106
2106
  }
2107
2107
 
2108
- var styles$r = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
2108
+ var styles$u = {"cw-accordion":"cw-accordion-module__cw-accordion__ErvlW","cw-accordion-body":"cw-accordion-module__cw-accordion-body__xlI8b"};
2109
2109
 
2110
2110
  /**
2111
2111
  * Legacy collapsible section with its own header markup.
@@ -2120,7 +2120,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
2120
2120
  setVisible_accordionBody(!isVisible_accordionBody);
2121
2121
  };
2122
2122
  // #endregion
2123
- return (jsxRuntime.jsxs("div", { className: styles$r["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxRuntime.jsxs("header", { onClick: () => showAccordionBody(), children: [jsxRuntime.jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsxRuntime.jsx("button", { className: "cw-button-icon" })] }), jsxRuntime.jsx("div", { className: styles$r["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
2123
+ return (jsxRuntime.jsxs("div", { className: styles$u["cw-accordion"], style: CwelltAccordionContainerProps.style, "data-open": isVisible_accordionBody, children: [jsxRuntime.jsxs("header", { onClick: () => showAccordionBody(), children: [jsxRuntime.jsx("div", { children: CwelltAccordionContainerProps.desc_text }), jsxRuntime.jsx("button", { className: "cw-button-icon" })] }), jsxRuntime.jsx("div", { className: styles$u["cw-accordion-body"], children: CwelltAccordionContainerProps.children })] }));
2124
2124
  }
2125
2125
 
2126
2126
  /*
@@ -2221,9 +2221,6 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
2221
2221
  return acc;
2222
2222
  }, {}));
2223
2223
  const [selectedKeys, setSelectedKeys] = React.useState(new Set(rowSelection?.selectedRowKeys || []));
2224
- React.useEffect(() => {
2225
- setCurrentPage(1);
2226
- }, [data]);
2227
2224
  React.useEffect(() => {
2228
2225
  setSelectedKeys(new Set(rowSelection?.selectedRowKeys || []));
2229
2226
  }, [rowSelection?.selectedRowKeys]);
@@ -2309,20 +2306,27 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
2309
2306
  return newSet;
2310
2307
  });
2311
2308
  }, [rowSelection, rowKey, sortedData]);
2309
+ const totalPages = React.useMemo(() => {
2310
+ return pagination ? Math.ceil(sortedData.length / localItemsPerPage) : 1;
2311
+ }, [sortedData, localItemsPerPage, pagination]);
2312
+ // Keep the page when data changes (e.g. a row was edited); only clamp it when it no longer exists.
2313
+ // Derived in render so a shrunk data set never shows an empty page for a frame.
2314
+ const page = Math.min(currentPage, Math.max(1, totalPages));
2315
+ React.useEffect(() => {
2316
+ if (page !== currentPage)
2317
+ setCurrentPage(page);
2318
+ }, [page, currentPage]);
2312
2319
  const paginatedData = React.useMemo(() => {
2313
2320
  if (!sortedData)
2314
2321
  return [];
2315
2322
  if (!pagination)
2316
2323
  return sortedData;
2317
- const start = (currentPage - 1) * localItemsPerPage;
2324
+ const start = (page - 1) * localItemsPerPage;
2318
2325
  return sortedData.slice(start, start + localItemsPerPage);
2319
- }, [sortedData, currentPage, localItemsPerPage, pagination]);
2320
- const totalPages = React.useMemo(() => {
2321
- return pagination ? Math.ceil(sortedData.length / localItemsPerPage) : 1;
2322
- }, [sortedData, localItemsPerPage, pagination]);
2323
- const handlePageChange = (page) => {
2324
- if (page >= 1 && page <= totalPages)
2325
- setCurrentPage(page);
2326
+ }, [sortedData, page, localItemsPerPage, pagination]);
2327
+ const handlePageChange = (target) => {
2328
+ if (target >= 1 && target <= totalPages)
2329
+ setCurrentPage(target);
2326
2330
  };
2327
2331
  const startResize = (e, key) => {
2328
2332
  e.preventDefault();
@@ -2383,7 +2387,7 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
2383
2387
  ? "sortable"
2384
2388
  : sortConfig.direction === "asc"
2385
2389
  ? "sortable-asc"
2386
- : "sortable-desc" }))] }), jsxRuntime.jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderTableBody() })] }), pagination && data.length > pageSizeOptions[0] && (jsxRuntime.jsxs("footer", { className: "cw-table-pagination", children: [jsxRuntime.jsxs("div", { className: "cw-table-pagination-size", children: [jsxRuntime.jsx(CwIcon, { iconId: "list" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map(size => (jsxRuntime.jsx("option", { value: size, children: pageLabel ? `${size} / ${pageLabel}` : size }, size))) })] }), jsxRuntime.jsxs("div", { className: "cw-table-pagination-nav", children: [jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(1), disabled: currentPage === 1 || totalPages <= 1, variant: "icon", icon: "chevron-left-double" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 1 || totalPages <= 1, variant: "icon", icon: "chevron-left" }), jsxRuntime.jsx("input", { type: "text", inputMode: "numeric", value: totalPages === 0 ? 0 : currentPage, disabled: totalPages === 0, onChange: (e) => {
2390
+ : "sortable-desc" }))] }), jsxRuntime.jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderTableBody() })] }), pagination && data.length > pageSizeOptions[0] && (jsxRuntime.jsxs("footer", { className: "cw-table-pagination", children: [jsxRuntime.jsxs("div", { className: "cw-table-pagination-size", children: [jsxRuntime.jsx(CwIcon, { iconId: "list" }), jsxRuntime.jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map(size => (jsxRuntime.jsx("option", { value: size, children: pageLabel ? `${size} / ${pageLabel}` : size }, size))) })] }), jsxRuntime.jsxs("div", { className: "cw-table-pagination-nav", children: [jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(1), disabled: page === 1 || totalPages <= 1, variant: "icon", icon: "chevron-left-double" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(page - 1), disabled: page === 1 || totalPages <= 1, variant: "icon", icon: "chevron-left" }), jsxRuntime.jsx("input", { type: "text", inputMode: "numeric", value: totalPages === 0 ? 0 : page, disabled: totalPages === 0, onChange: (e) => {
2387
2391
  const value = parseInt(e.target.value, 10);
2388
2392
  if (!isNaN(value))
2389
2393
  handlePageChange(value);
@@ -2392,10 +2396,10 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
2392
2396
  if (isNaN(value) || value < 1 || value > totalPages) {
2393
2397
  handlePageChange(1);
2394
2398
  }
2395
- }, min: 1, max: totalPages }), jsxRuntime.jsx("span", { children: "/" }), jsxRuntime.jsx("span", { children: totalPages }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2399
+ }, min: 1, max: totalPages }), jsxRuntime.jsx("span", { children: "/" }), jsxRuntime.jsx("span", { children: totalPages }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(page + 1), disabled: page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2396
2400
  }
2397
2401
 
2398
- var styles$q = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
2402
+ var styles$t = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
2399
2403
 
2400
2404
  /**
2401
2405
  * Hook that provides state management for CwSortableTable.
@@ -2458,7 +2462,7 @@ function useSortableTable(initialItems) {
2458
2462
  }
2459
2463
 
2460
2464
  // ─── Drop indicator row ───────────────────────────────────────────────────────
2461
- const DropIndicatorRow = ({ colSpan }) => (jsxRuntime.jsx("tr", { className: styles$q.dropIndicator, "aria-hidden": true, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", {}) }) }));
2465
+ const DropIndicatorRow = ({ colSpan }) => (jsxRuntime.jsx("tr", { className: styles$t.dropIndicator, "aria-hidden": true, children: jsxRuntime.jsx("td", { colSpan: colSpan, children: jsxRuntime.jsx("div", {}) }) }));
2462
2466
  // ─── Loading skeleton ─────────────────────────────────────────────────────────
2463
2467
  // Plain td cells (no local class): the ghost cells get the same global cw-table
2464
2468
  // padding as real body cells, so row heights match the loaded rows exactly.
@@ -2561,11 +2565,11 @@ function CwSortableTable({ columns, data, rowKey = "key", onReorder, loading = f
2561
2565
  return items.map((item, index) => {
2562
2566
  const key = item[rowKey];
2563
2567
  const isDragging = draggedItem?.[rowKey] === key;
2564
- return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols })), jsxRuntime.jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$q.dragging : "", children: [showHandle && (jsxRuntime.jsx("td", { className: "cw-table-col-action", children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsxRuntime.jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: renderCell(item, col) }, `${String(key)}_${col.key}`)))] }), index === items.length - 1 && dropIndicatorIndex === items.length && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
2568
+ return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols })), jsxRuntime.jsxs("tr", { draggable: true, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, className: isDragging ? styles$t.dragging : "", children: [showHandle && (jsxRuntime.jsx("td", { className: "cw-table-col-action", children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots", color: "neutral", style: { opacity: 0.75 } }) })), columns.map(col => (jsxRuntime.jsx("td", { className: col.className ?? "", style: col.width ? { width: col.width } : undefined, children: renderCell(item, col) }, `${String(key)}_${col.key}`)))] }), index === items.length - 1 && dropIndicatorIndex === items.length && (jsxRuntime.jsx(DropIndicatorRow, { colSpan: totalCols }))] }, String(key)));
2565
2569
  });
2566
2570
  };
2567
2571
  // ── Render ──────────────────────────────────────────────────────────────
2568
- return (jsxRuntime.jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, "aria-busy": loading || undefined, children: [jsxRuntime.jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [showHandle && jsxRuntime.jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsxRuntime.jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderBody() })] }), !loading && hasChanges && (jsxRuntime.jsxs("footer", { className: styles$q.saveBar, children: [jsxRuntime.jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsxRuntime.jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
2572
+ return (jsxRuntime.jsxs("div", { className: `cw-table-container ${className ?? ""}`, style: containerStyle, "aria-busy": loading || undefined, children: [jsxRuntime.jsxs("table", { className: `cw-table cw-sortable-table ${tableClassName ?? ""}`, style: { width: "100%" }, children: [jsxRuntime.jsx("thead", { children: jsxRuntime.jsxs("tr", { children: [showHandle && jsxRuntime.jsx("th", { className: "cw-table-col-action" }), columns.map(col => (jsxRuntime.jsx("th", { className: col.className ?? "", style: col.width ? { width: col.width, minWidth: 50 } : undefined, children: col.title }, col.key)))] }) }), jsxRuntime.jsx("tbody", { children: renderBody() })] }), !loading && hasChanges && (jsxRuntime.jsxs("footer", { className: styles$t.saveBar, children: [jsxRuntime.jsx(CwButton, { variant: "outline", color: "neutral", icon: "undo", text: discardLabel, onClick: handleDiscard }), jsxRuntime.jsx(CwButton, { variant: "solid", color: "primary", icon: "save", text: saveLabel, onClick: () => handleSave(onReorder) })] }))] }));
2569
2573
  }
2570
2574
 
2571
2575
  /**
@@ -2766,7 +2770,7 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
2766
2770
  }, min: 1, max: totalPages }), jsxRuntime.jsx("span", { children: "/" }), jsxRuntime.jsx("span", { children: totalPages }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsxRuntime.jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2767
2771
  }
2768
2772
 
2769
- var styles$p = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2773
+ var styles$s = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2770
2774
 
2771
2775
  const BADGE_COLOR_SCHEMES = ['primary', 'danger', 'warning', 'success', 'info', 'neutral'];
2772
2776
  function isBadgeColorScheme(value) {
@@ -2820,11 +2824,11 @@ function CwTabs(CwTabsProps) {
2820
2824
  const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
2821
2825
  ? { minWidth: CwTabsProps.tabsListWidth }
2822
2826
  : undefined;
2823
- return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$p['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => {
2827
+ return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$s['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => {
2824
2828
  const badgeScheme = tab.badgeColor && isBadgeColorScheme(tab.badgeColor) ? tab.badgeColor : undefined;
2825
2829
  const rawBadgeColor = tab.badgeColor && !badgeScheme ? tab.badgeColor : undefined;
2826
2830
  return (jsxRuntime.jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, "data-badge-themed": tab.badgeColor ? "true" : undefined, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsxRuntime.jsx(CwBadge, { count: typeof tab.badge === 'number' ? tab.badge : undefined, content: typeof tab.badge === 'string' ? tab.badge : undefined, size: "medium", color: badgeScheme ?? 'primary', variant: badgeScheme ? 'solid' : 'soft', style: rawBadgeColor ? { backgroundColor: rawBadgeColor, color: getContrastColor(rawBadgeColor) } : undefined }))] }, tab.key));
2827
- }) }), jsxRuntime.jsx("div", { className: styles$p['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, style: CwTabsProps.contentHeight ? { '--tabs-height': CwTabsProps.contentHeight } : undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2831
+ }) }), jsxRuntime.jsx("div", { className: styles$s['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, style: CwTabsProps.contentHeight ? { '--tabs-height': CwTabsProps.contentHeight } : undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2828
2832
  }
2829
2833
 
2830
2834
  /**
@@ -2852,7 +2856,7 @@ const CwExpandable = ({ briefing, onToggle, onOpen, onClose, children, ...detail
2852
2856
  return (jsxRuntime.jsxs("details", { ref: myRef, ...detailsProps, className: "cw-expandable", children: [jsxRuntime.jsx("summary", { children: briefing }), children && jsxRuntime.jsx("section", { children: children })] }));
2853
2857
  };
2854
2858
 
2855
- var styles$o = {"cw-master-detail":"cw-master-detail-module__cw-master-detail__O8-FA","resizer":"cw-master-detail-module__resizer__hvGhL","detail":"cw-master-detail-module__detail__BG4Dm","skeletonRow":"cw-master-detail-module__skeletonRow__6BUgt","detailSkeleton":"cw-master-detail-module__detailSkeleton__GcDS4","detail-empty":"cw-master-detail-module__detail-empty__KFScK"};
2859
+ var styles$r = {"cw-master-detail":"cw-master-detail-module__cw-master-detail__O8-FA","resizer":"cw-master-detail-module__resizer__hvGhL","detail":"cw-master-detail-module__detail__BG4Dm","skeletonRow":"cw-master-detail-module__skeletonRow__6BUgt","detailSkeleton":"cw-master-detail-module__detailSkeleton__GcDS4","detail-empty":"cw-master-detail-module__detail-empty__KFScK"};
2856
2860
 
2857
2861
  /*
2858
2862
  * Fixed rem widths for the ghosts: the master rows and detail panel size their
@@ -2896,12 +2900,12 @@ const CwMasterDetail = ({ id, className, style, items, selectedKey, onSelect, de
2896
2900
  document.body.style.userSelect = '';
2897
2901
  };
2898
2902
  }, [isResizing, minMasterWidth, maxMasterWidth]);
2899
- const rootClassName = [styles$o['cw-master-detail'], className].filter(Boolean).join(' ');
2903
+ const rootClassName = [styles$r['cw-master-detail'], className].filter(Boolean).join(' ');
2900
2904
  return (jsxRuntime.jsxs("div", { id: id, ref: containerRef, className: rootClassName, style: style, "aria-busy": loading || undefined, children: [jsxRuntime.jsxs("aside", { style: { width: masterWidth, minWidth: masterWidth }, children: [showSearch && (jsxRuntime.jsx("search", { children: jsxRuntime.jsx("input", { type: "text", placeholder: searchPlaceholder, onChange: (e) => onSearch?.(e.target.value) }) })), masterHeader && (jsxRuntime.jsx("header", { children: masterHeader })), jsxRuntime.jsx("ul", { children: loading
2901
- ? Array.from({ length: skeletonRows }, (_unused, rowIndex) => (jsxRuntime.jsxs("li", { "aria-hidden": "true", children: [jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" }), jsxRuntime.jsxs("div", { className: styles$o.skeletonRow, children: [jsxRuntime.jsx(CwSkeleton, { variant: "text", width: MASTER_TITLE_WIDTHS[rowIndex % MASTER_TITLE_WIDTHS.length] }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: MASTER_SUBTITLE_WIDTH })] })] }, `skeleton_${rowIndex}`)))
2902
- : items.map((item) => (jsxRuntime.jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsxRuntime.jsx("footer", { children: masterFooter }))] }), resizable && (jsxRuntime.jsx("div", { className: styles$o.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsxRuntime.jsx("section", { className: styles$o.detail, children: loading ? (jsxRuntime.jsxs("div", { className: styles$o.detailSkeleton, "aria-hidden": "true", children: [jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "14rem", height: "1.5em" }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "22rem" }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "18rem" }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "20rem" })] })) : selectedKey && detailContent
2905
+ ? Array.from({ length: skeletonRows }, (_unused, rowIndex) => (jsxRuntime.jsxs("li", { "aria-hidden": "true", children: [jsxRuntime.jsx(CwSkeleton, { variant: "circle", height: "2rem" }), jsxRuntime.jsxs("div", { className: styles$r.skeletonRow, children: [jsxRuntime.jsx(CwSkeleton, { variant: "text", width: MASTER_TITLE_WIDTHS[rowIndex % MASTER_TITLE_WIDTHS.length] }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: MASTER_SUBTITLE_WIDTH })] })] }, `skeleton_${rowIndex}`)))
2906
+ : items.map((item) => (jsxRuntime.jsx("li", { "data-master-key": item.key, "data-selected": item.key === selectedKey, "data-disabled": item.disabled, onClick: () => onSelect?.(item.key), children: item.content }, item.key))) }), masterFooter && (jsxRuntime.jsx("footer", { children: masterFooter }))] }), resizable && (jsxRuntime.jsx("div", { className: styles$r.resizer, "data-resizing": isResizing, onMouseDown: handleMouseDown })), jsxRuntime.jsx("section", { className: styles$r.detail, children: loading ? (jsxRuntime.jsxs("div", { className: styles$r.detailSkeleton, "aria-hidden": "true", children: [jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "14rem", height: "1.5em" }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "22rem" }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "18rem" }), jsxRuntime.jsx(CwSkeleton, { variant: "text", width: "20rem" })] })) : selectedKey && detailContent
2903
2907
  ? detailContent
2904
- : (jsxRuntime.jsx("div", { className: styles$o['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
2908
+ : (jsxRuntime.jsx("div", { className: styles$r['detail-empty'], children: emptyDetail ?? 'Select an item to view details' })) })] }));
2905
2909
  };
2906
2910
 
2907
2911
  /*
@@ -2941,7 +2945,7 @@ const CwKeyValueList = ({ items, className = "", emptyValue = "-", direction = "
2941
2945
  return (jsxRuntime.jsx("dl", { className: `cw-keyvalue-list ${className}`, "data-direction": groupLayout?.direction, "data-align": groupLayout?.align, "data-justify": groupLayout?.justify, "data-gap": groupLayout?.gap, "aria-busy": loading || undefined, ...htmlProps, children: renderItems() }));
2942
2946
  };
2943
2947
 
2944
- var styles$n = {"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"};
2948
+ var styles$q = {"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"};
2945
2949
 
2946
2950
  function CwSortableList({ items, onReorder, renderItem, className = '', movedItems = new Set(), emptyMessage = "No elements to show", readOnly = false, maxHeight = "300px", }) {
2947
2951
  const [draggedItem, setDraggedItem] = React.useState(null);
@@ -3004,15 +3008,15 @@ function CwSortableList({ items, onReorder, renderItem, className = '', movedIte
3004
3008
  }
3005
3009
  };
3006
3010
  if (items.length === 0) {
3007
- return (jsxRuntime.jsx("div", { className: `${styles$n.sortableList} ${styles$n.emptyState} ${className}`, children: jsxRuntime.jsx("div", { className: styles$n.emptyMessage, children: emptyMessage }) }));
3011
+ return (jsxRuntime.jsx("div", { className: `${styles$q.sortableList} ${styles$q.emptyState} ${className}`, children: jsxRuntime.jsx("div", { className: styles$q.emptyMessage, children: emptyMessage }) }));
3008
3012
  }
3009
- return (jsxRuntime.jsx("div", { className: `${styles$n.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
3013
+ return (jsxRuntime.jsx("div", { className: `${styles$q.sortableList} ${className}`, style: { maxHeight }, children: items.map((item, index) => {
3010
3014
  const { title, extraContent, actions, showHandle = true, expandedContent } = renderItem(item);
3011
3015
  const isDragging = draggedItem?.id === item.id;
3012
3016
  const isMoved = movedItems.has(item.id);
3013
3017
  const canExpand = Boolean(expandedContent);
3014
3018
  const isExpanded = expandedItems.has(item.id);
3015
- return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && jsxRuntime.jsx("div", { className: styles$n.dropIndicator }), jsxRuntime.jsxs("div", { className: `${styles$n.sortableItem} ${isDragging ? styles$n.dragging : ''} ${isMoved ? styles$n.moved : ''} ${readOnly ? styles$n.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxRuntime.jsxs("header", { children: [canExpand ? (jsxRuntime.jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsxRuntime.jsx("div", { className: styles$n.sortableHandle, children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxRuntime.jsxs("div", { className: styles$n.sortableContent, children: [jsxRuntime.jsx("div", { className: styles$n.sortableTitle, children: title }), extraContent && jsxRuntime.jsx("div", { className: styles$n.sortableExtraContent, children: extraContent })] }), jsxRuntime.jsx("div", { className: styles$n.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsxRuntime.jsx("div", { className: styles$n.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsxRuntime.jsx("div", { className: styles$n.dropIndicator }))] }, item.id));
3019
+ return (jsxRuntime.jsxs(React.Fragment, { children: [dropIndicatorIndex === index && jsxRuntime.jsx("div", { className: styles$q.dropIndicator }), jsxRuntime.jsxs("div", { className: `${styles$q.sortableItem} ${isDragging ? styles$q.dragging : ''} ${isMoved ? styles$q.moved : ''} ${readOnly ? styles$q.readOnly : ''}`, draggable: !readOnly, onDragStart: (e) => handleDragStart(e, item), onDragOver: (e) => handleDragOver(e, index), onDragEnd: handleDragEnd, children: [jsxRuntime.jsxs("header", { children: [canExpand ? (jsxRuntime.jsx(CwButton, { variant: "icon", onClick: () => toggleExpanded(item.id), type: "button", title: isExpanded ? "Collapse" : "Expand", icon: isExpanded ? "chevron-up" : "chevron-down" })) : showHandle ? (jsxRuntime.jsx("div", { className: styles$q.sortableHandle, children: jsxRuntime.jsx(CwIcon, { iconId: "grip-dots" }) })) : null, jsxRuntime.jsxs("div", { className: styles$q.sortableContent, children: [jsxRuntime.jsx("div", { className: styles$q.sortableTitle, children: title }), extraContent && jsxRuntime.jsx("div", { className: styles$q.sortableExtraContent, children: extraContent })] }), jsxRuntime.jsx("div", { className: styles$q.sortableActions, children: actions })] }), isExpanded && expandedContent && (jsxRuntime.jsx("div", { className: styles$q.expandedContent, children: expandedContent }))] }), !readOnly && dropIndicatorIndex === items.length && index === items.length - 1 && (jsxRuntime.jsx("div", { className: styles$q.dropIndicator }))] }, item.id));
3016
3020
  }) }));
3017
3021
  }
3018
3022
 
@@ -3139,7 +3143,7 @@ const CwTableGrouped = props => {
3139
3143
  group.rows.map((child, j) => (jsxRuntime.jsx("tr", { "data-row": true, "data-row-last-of-group": j == group.rows.length - 1, children: child.cells.map((cell, k) => (jsxRuntime.jsx("td", { children: cell.content }, k))) }, j)))] }, i))) }), jsxRuntime.jsx("tfoot", {})] }) }));
3140
3144
  };
3141
3145
 
3142
- var styles$m = {"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"};
3146
+ var styles$p = {"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"};
3143
3147
 
3144
3148
  const DEFAULT_LABELS$1 = {
3145
3149
  uploadDisabled: 'Upload disabled',
@@ -3325,12 +3329,12 @@ function CwFileUploadMultiple(fileUploadProps) {
3325
3329
  }
3326
3330
  }
3327
3331
  };
3328
- return (jsxRuntime.jsxs("div", { className: `${styles$m.fileUploadContainer} ${fileUploadProps.className}`, children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$m.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxRuntime.jsxs("div", { className: `${styles$m.uploadArea} ${fileUploadProps.disabled ? styles$m.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsx("p", { className: `${styles$m.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxRuntime.jsxs("p", { className: `${styles$m.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxRuntime.jsxs("div", { className: styles$m.filesContainer, children: [jsxRuntime.jsxs("div", { className: styles$m.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$m.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$m.fileExtension, children: getFileExtension(existingFile) })] }), jsxRuntime.jsx("div", { className: styles$m.fileInfo, children: jsxRuntime.jsx("p", { className: styles$m.fileName, children: existingFile }) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
3332
+ return (jsxRuntime.jsxs("div", { className: `${styles$p.fileUploadContainer} ${fileUploadProps.className}`, children: [jsxRuntime.jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$p.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxRuntime.jsxs("div", { className: `${styles$p.uploadArea} ${fileUploadProps.disabled ? styles$p.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsx("p", { className: `${styles$p.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxRuntime.jsxs("p", { className: `${styles$p.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxRuntime.jsxs("div", { className: styles$p.filesContainer, children: [jsxRuntime.jsxs("div", { className: styles$p.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$p.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$p.fileExtension, children: getFileExtension(existingFile) })] }), jsxRuntime.jsx("div", { className: styles$p.fileInfo, children: jsxRuntime.jsx("p", { className: styles$p.fileName, children: existingFile }) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
3329
3333
  setExistingFile(undefined);
3330
3334
  if (fileUploadProps.onSelect) {
3331
3335
  fileUploadProps.onSelect(null);
3332
3336
  }
3333
- }, disabled: fileUploadProps.disabled, className: styles$m.smallButton })] }), jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxRuntime.jsxs("div", { className: styles$m.filesContainer, children: [jsxRuntime.jsxs("header", { className: "cw-flex-row cw-align-between-center cw-flex-wrap", children: [jsxRuntime.jsx("small", { className: styles$m.filesCount, children: fileUploadProps.statusText ?? labels.filesSelected(selectedFiles.length) }), jsxRuntime.jsxs("div", { className: "cw-flex-row", children: [fileUploadProps.onConfirm && selectedFiles.length > 0 && (jsxRuntime.jsx(CwButton, { onClick: () => {
3337
+ }, disabled: fileUploadProps.disabled, className: styles$p.smallButton })] }), jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxRuntime.jsxs("div", { className: styles$p.filesContainer, children: [jsxRuntime.jsxs("header", { className: "cw-flex-row cw-align-between-center cw-flex-wrap", children: [jsxRuntime.jsx("small", { className: styles$p.filesCount, children: fileUploadProps.statusText ?? labels.filesSelected(selectedFiles.length) }), jsxRuntime.jsxs("div", { className: "cw-flex-row", children: [fileUploadProps.onConfirm && selectedFiles.length > 0 && (jsxRuntime.jsx(CwButton, { onClick: () => {
3334
3338
  let files = fileInputRef.current?.files ?? null;
3335
3339
  if (!files) {
3336
3340
  const dataTransfer = new DataTransfer();
@@ -3338,7 +3342,7 @@ function CwFileUploadMultiple(fileUploadProps) {
3338
3342
  files = dataTransfer.files;
3339
3343
  }
3340
3344
  fileUploadProps.onConfirm?.(files);
3341
- }, disabled: fileUploadProps.disabled || fileUploadProps.confirmDisabled, icon: "upload", text: fileUploadProps.confirmLabel ?? labels.upload })), !fileUploadProps.hideClearAll && (jsxRuntime.jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] })] }), selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: styles$m.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$m.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$m.fileExtension, children: getFileExtension(file.name) })] }), jsxRuntime.jsxs("div", { className: styles$m.fileInfo, children: [jsxRuntime.jsx("p", { className: styles$m.fileName, children: file.name }), jsxRuntime.jsxs("p", { className: styles$m.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$m.smallButton })] }, `${file.name}-${file.size}`))), fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
3345
+ }, disabled: fileUploadProps.disabled || fileUploadProps.confirmDisabled, icon: "upload", text: fileUploadProps.confirmLabel ?? labels.upload })), !fileUploadProps.hideClearAll && (jsxRuntime.jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll }))] })] }), selectedFiles.map((file, index) => (jsxRuntime.jsxs("div", { className: styles$p.fileItem, children: [jsxRuntime.jsxs("div", { className: styles$p.fileIcon, children: [jsxRuntime.jsx(CwIcon, { iconId: "page" }), jsxRuntime.jsx("span", { className: styles$p.fileExtension, children: getFileExtension(file.name) })] }), jsxRuntime.jsxs("div", { className: styles$p.fileInfo, children: [jsxRuntime.jsx("p", { className: styles$p.fileName, children: file.name }), jsxRuntime.jsxs("p", { className: styles$p.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$p.smallButton })] }, `${file.name}-${file.size}`))), fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsxRuntime.jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
3342
3346
  }
3343
3347
 
3344
3348
  /**
@@ -3391,7 +3395,7 @@ function CwDigit(props) {
3391
3395
  return (jsxRuntime.jsxs("div", { className: "cw-input-text", "data-direction": labelProps ? flexDirection : "column", "data-feedback-position": feedbackPosition, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: "cw-input-button", children: [jsxRuntime.jsx("input", { type: "number", ...inputProps, "aria-describedby": describedBy }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-info", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
3392
3396
  }
3393
3397
 
3394
- var styles$l = {"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"};
3398
+ var styles$o = {"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"};
3395
3399
 
3396
3400
  const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }) => {
3397
3401
  const [rgb, setRgb] = React.useState({ r: 255, g: 255, b: 255 });
@@ -3594,13 +3598,13 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
3594
3598
  // Calculate background color for the main area based on current hue
3595
3599
  const hueColor = hsvToRgb(hsv.h, 100, 100);
3596
3600
  const hueHex = rgbToHex(hueColor.r, hueColor.g, hueColor.b);
3597
- return (jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsxRuntime.jsx("div", { className: styles$l.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsxRuntime.jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsxRuntime.jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsxRuntime.jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxRuntime.jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "R:" }), jsxRuntime.jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "G:" }), jsxRuntime.jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "B:" }), jsxRuntime.jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxRuntime.jsxs("div", { className: styles$l.colorPickerInteractiveArea, children: [jsxRuntime.jsx("div", { className: styles$l.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsxRuntime.jsx("div", { className: styles$l.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxRuntime.jsxs("div", { className: styles$l.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxRuntime.jsxs("div", { className: styles$l.colorAreaOverlay, children: [jsxRuntime.jsx("div", { className: styles$l.hueBackground, style: { backgroundColor: hueHex } }), jsxRuntime.jsx("div", { className: styles$l.whiteGradient }), jsxRuntime.jsx("div", { className: styles$l.blackGradient })] }), jsxRuntime.jsx("div", { className: styles$l.colorAreaCursor, style: {
3601
+ return (jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-small", children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-between-center cw-gap-small", children: [jsxRuntime.jsx("div", { className: styles$o.colorPreview, style: { backgroundColor: hexColor, color: getContrastColor(hexColor) }, children: previewText }), jsxRuntime.jsx("button", { type: "button", className: "cw-button", onClick: toggleInputMode, style: { minWidth: "3ch" }, children: inputMode === 'hex' ? 'RGB' : 'HEX' })] }), jsxRuntime.jsx("div", { className: "color-inputs-row", children: inputMode === 'hex' ? (jsxRuntime.jsx("input", { type: "text", value: hexColor, onChange: handleHexChange })) : (jsxRuntime.jsxs("div", { className: "cw-grid-base-3 cw-gap-small", children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "R:" }), jsxRuntime.jsx("input", { type: "number", name: "r", min: "0", max: "255", value: rgb.r, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "G:" }), jsxRuntime.jsx("input", { type: "number", name: "g", min: "0", max: "255", value: rgb.g, onChange: handleRgbChange })] }), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("label", { children: "B:" }), jsxRuntime.jsx("input", { type: "number", name: "b", min: "0", max: "255", value: rgb.b, onChange: handleRgbChange })] })] })) }), jsxRuntime.jsxs("div", { className: styles$o.colorPickerInteractiveArea, children: [jsxRuntime.jsx("div", { className: styles$o.hueBar, ref: hueBarRef, onClick: handleHueBarClick, children: jsxRuntime.jsx("div", { className: styles$o.hueBarSlider, style: { top: `${(360 - hsv.h) / 360 * 100}%` } }) }), jsxRuntime.jsxs("div", { className: styles$o.colorArea, ref: colorAreaRef, onClick: handleColorAreaClick, children: [jsxRuntime.jsxs("div", { className: styles$o.colorAreaOverlay, children: [jsxRuntime.jsx("div", { className: styles$o.hueBackground, style: { backgroundColor: hueHex } }), jsxRuntime.jsx("div", { className: styles$o.whiteGradient }), jsxRuntime.jsx("div", { className: styles$o.blackGradient })] }), jsxRuntime.jsx("div", { className: styles$o.colorAreaCursor, style: {
3598
3602
  left: `${hsv.s}%`,
3599
3603
  top: `${100 - hsv.v}%`
3600
3604
  } })] })] })] }));
3601
3605
  };
3602
3606
 
3603
- var styles$k = {"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"};
3607
+ var styles$n = {"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"};
3604
3608
 
3605
3609
  const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, className, style, }) => {
3606
3610
  const [isOpen, setIsOpen] = React.useState(false);
@@ -3733,11 +3737,11 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
3733
3737
  break;
3734
3738
  }
3735
3739
  };
3736
- return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$k.container}${className ? ` ${className}` : ''}`, style: style, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps })), jsxRuntime.jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$k.selectColor} ${disabled ? styles$k.disabled : ''} ${readOnly ? styles$k.readOnly : ''}`, style: {
3740
+ return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$n.container}${className ? ` ${className}` : ''}`, style: style, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps })), jsxRuntime.jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$n.selectColor} ${disabled ? styles$n.disabled : ''} ${readOnly ? styles$n.readOnly : ''}`, style: {
3737
3741
  width,
3738
3742
  height,
3739
3743
  backgroundColor: value,
3740
- }, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: dropdownRef, className: styles$k.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsxRuntime.jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
3744
+ }, "aria-label": "Open color picker", "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-readonly": readOnly, role: "button", tabIndex: disabled ? -1 : 0, onKeyDown: handleKeyDown }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: dropdownRef, className: styles$n.colorDropdown, style: dropdownStyle, role: "dialog", "aria-modal": "true", "aria-label": "Color picker", children: jsxRuntime.jsx(CwColorPicker, { initialColor: value, onChange: handleColorChange, previewText: previewText }) }), document.body)] }));
3741
3745
  };
3742
3746
 
3743
3747
  /**
@@ -3992,7 +3996,7 @@ function CwInputDateText(props) {
3992
3996
  return (jsxRuntime.jsx("div", { className: "cw-input-date-text", children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("input", { type: "text", disabled: disabled, maxLength: 10, onChange: onChangeInputText, pattern: "^$ --|[.0-9\\/\\-]{10}", placeholder: format.toLowerCase(), readOnly: readOnly, ref: textInputRef, required: required, size: width, tabIndex: tabIndex, value: displayedDate }), jsxRuntime.jsxs("span", { children: [jsxRuntime.jsx(CwIcon, { iconId: "calendar" }), jsxRuntime.jsx("input", { type: "date", disabled: disabled, onChange: onChangeInputDate, readOnly: readOnly, ref: dateInputRef, tabIndex: -1, value: date, ...inputProps })] })] }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] }) }));
3993
3997
  }
3994
3998
 
3995
- var styles$j = {"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"};
3999
+ var styles$m = {"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"};
3996
4000
 
3997
4001
  const DEFAULT_LABELS = {
3998
4002
  dropImageHere: "Drop image here",
@@ -4071,7 +4075,7 @@ function CwInputImage(props) {
4071
4075
  const file = e.currentTarget.files?.[0];
4072
4076
  void handleFile(file ?? null);
4073
4077
  };
4074
- return (jsxRuntime.jsxs("div", { className: `cw-input-image ${styles$j.container}`, "data-size": size, children: [jsxRuntime.jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$j.dropZone, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-tiny", children: [jsxRuntime.jsx("p", { className: styles$j.title, children: labels.dropImageHere }), jsxRuntime.jsx("p", { className: styles$j.subtitle, children: labels.acceptedFormats(allowedFormats.join(", ").replace(/image\//g, "")) })] })] }), jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsxRuntime.jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: labels.paste, size: size }), jsxRuntime.jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: labels.browse, size: size })] }), jsxRuntime.jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, className: styles$j.hiddenInput, ...inputProps })] }));
4078
+ return (jsxRuntime.jsxs("div", { className: `cw-input-image ${styles$m.container}`, "data-size": size, children: [jsxRuntime.jsxs("div", { onDragOver: (e) => e.preventDefault(), onDrop: handleDrop, className: styles$m.dropZone, children: [jsxRuntime.jsx(CwIcon, { iconId: "upload" }), jsxRuntime.jsxs("div", { className: "cw-flex-column cw-gap-tiny", children: [jsxRuntime.jsx("p", { className: styles$m.title, children: labels.dropImageHere }), jsxRuntime.jsx("p", { className: styles$m.subtitle, children: labels.acceptedFormats(allowedFormats.join(", ").replace(/image\//g, "")) })] })] }), jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-center-center cw-gap-small", children: [jsxRuntime.jsx(CwButton, { onClick: onPasteButtonClick, icon: "paste", text: labels.paste, size: size }), jsxRuntime.jsx(CwButton, { onClick: () => inputRef.current?.click(), icon: "folder-open", text: labels.browse, size: size })] }), jsxRuntime.jsx("input", { ref: inputRef, type: "file", accept: allowedFormats.join(","), onChange: handleFileChange, className: styles$m.hiddenInput, ...inputProps })] }));
4075
4079
  }
4076
4080
 
4077
4081
  /**
@@ -4203,7 +4207,7 @@ const CwImageArea = React.forwardRef((props, ref) => {
4203
4207
  });
4204
4208
  CwImageArea.displayName = "CwImageArea";
4205
4209
 
4206
- var styles$i = {"container":"cw-weekday-selector-module__container__pwcvx","days":"cw-weekday-selector-module__days__Dd3RH"};
4210
+ var styles$l = {"container":"cw-weekday-selector-module__container__pwcvx","days":"cw-weekday-selector-module__days__Dd3RH"};
4207
4211
 
4208
4212
  /* 2024-01-01 was a Monday. Formatted in UTC so a negative browser offset cannot shift a day. */
4209
4213
  const MONDAY_UTC = Date.UTC(2024, 0, 1);
@@ -4401,16 +4405,16 @@ const CwWeekdaySelector = ({ value = "mtwrfsu", onChange, disabled = false, labe
4401
4405
  // Points at the label element rather than copying its text, which also covers a labelProps that
4402
4406
  // carries children instead of `text`.
4403
4407
  const labelId = labelProps?.id ?? `${feedbackId}-label`;
4404
- return (jsxRuntime.jsxs("div", { ...dataAttributes, className: `cw-weekday-selector ${styles$i.container}${className ? ` ${className}` : ""}`, "data-direction": labelProps ? layout?.direction ?? "row" : "column", "data-align": layout?.align, "data-gap": layout?.gap, children: [labelProps && jsxRuntime.jsx(CwLabel, { id: labelId, ...labelProps }), jsxRuntime.jsx("div", { role: "group", className: styles$i.days, "aria-labelledby": labelProps ? labelId : undefined, "aria-describedby": describedBy, children: Weekdays.getFullWeek().map(day => (jsxRuntime.jsx("input", { type: "checkbox", "data-day": day, "data-letter": dayNames[day].letter, "aria-label": dayNames[day].full, title: dayNames[day].full, checked: selectedDays.includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4408
+ return (jsxRuntime.jsxs("div", { ...dataAttributes, className: `cw-weekday-selector ${styles$l.container}${className ? ` ${className}` : ""}`, "data-direction": labelProps ? layout?.direction ?? "row" : "column", "data-align": layout?.align, "data-gap": layout?.gap, children: [labelProps && jsxRuntime.jsx(CwLabel, { id: labelId, ...labelProps }), jsxRuntime.jsx("div", { role: "group", className: styles$l.days, "aria-labelledby": labelProps ? labelId : undefined, "aria-describedby": describedBy, children: Weekdays.getFullWeek().map(day => (jsxRuntime.jsx("input", { type: "checkbox", "data-day": day, "data-letter": dayNames[day].letter, "aria-label": dayNames[day].full, title: dayNames[day].full, checked: selectedDays.includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4405
4409
  };
4406
4410
 
4407
- var styles$h = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
4411
+ var styles$k = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
4408
4412
 
4409
4413
  function CwCheck(props) {
4410
4414
  const { labelProps, labelText, direction, alignment, className, ...inputProps } = props;
4411
4415
  const resolvedDirection = direction ?? alignment ?? "row";
4412
4416
  const displayText = labelProps?.text ?? labelText;
4413
- return (jsxRuntime.jsx("div", { className: `cw-check ${styles$h["check-container"]}${className ? ` ${className}` : ''}`, children: jsxRuntime.jsxs("label", { "data-direction": resolvedDirection, children: [jsxRuntime.jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsxRuntime.jsx("span", { className: "cw-icon-text", children: displayText }))] }) }));
4417
+ return (jsxRuntime.jsx("div", { className: `cw-check ${styles$k["check-container"]}${className ? ` ${className}` : ''}`, children: jsxRuntime.jsxs("label", { "data-direction": resolvedDirection, children: [jsxRuntime.jsx("input", { type: "checkbox", ...inputProps }), displayText && (jsxRuntime.jsx("span", { className: "cw-icon-text", children: displayText }))] }) }));
4414
4418
  }
4415
4419
 
4416
4420
  function CwCheckbox(CwCheckboxProps) {
@@ -4464,14 +4468,14 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
4464
4468
  ?? (optionsAlignment === "column" ? "row" : "column");
4465
4469
  // Each checkbox's box-to-text layout is the opposite of the options flow, mirroring CwRadioGroup.
4466
4470
  const checkDirection = itemDirection === "row" ? "column" : "row";
4467
- return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$h.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$h.options, role: "group", "aria-label": labelProps?.text, "aria-describedby": describedBy, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4471
+ return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$k.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$k.options, role: "group", "aria-label": labelProps?.text, "aria-describedby": describedBy, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4468
4472
  }
4469
4473
 
4470
- var styles$g = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
4474
+ var styles$j = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
4471
4475
 
4472
4476
  /** Single native radio input. Building block for CwRadioGroup. */
4473
4477
  function CwRadio({ label, direction = "row", className, ...inputProps }) {
4474
- return (jsxRuntime.jsxs("label", { className: `cw-radio ${styles$g.radio}${className ? ` ${className}` : ""}`, "data-direction": direction, children: [jsxRuntime.jsx("input", { type: "radio", ...inputProps }), label && jsxRuntime.jsx("span", { children: label })] }));
4478
+ return (jsxRuntime.jsxs("label", { className: `cw-radio ${styles$j.radio}${className ? ` ${className}` : ""}`, "data-direction": direction, children: [jsxRuntime.jsx("input", { type: "radio", ...inputProps }), label && jsxRuntime.jsx("span", { children: label })] }));
4475
4479
  }
4476
4480
 
4477
4481
  /**
@@ -4498,7 +4502,7 @@ function CwRadioGroup({ options, value, onChange, labelProps, groupLayout, itemL
4498
4502
  // (itemLayout column) reads best with the circle beside the text; a side-by-side row reads
4499
4503
  // best with the circle above the text.
4500
4504
  const radioDirection = itemLayout?.direction === "row" ? "column" : "row";
4501
- return (jsxRuntime.jsxs("div", { className: `cw-radio-group ${styles$g.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$g.options, role: "radiogroup", "aria-describedby": describedBy, "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : (ariaLabel ?? labelProps?.text), "aria-required": required || undefined, "data-direction": itemLayout?.direction ?? "column", "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4505
+ return (jsxRuntime.jsxs("div", { className: `cw-radio-group ${styles$j.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$j.options, role: "radiogroup", "aria-describedby": describedBy, "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : (ariaLabel ?? labelProps?.text), "aria-required": required || undefined, "data-direction": itemLayout?.direction ?? "column", "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4502
4506
  }
4503
4507
 
4504
4508
  function CwToggle(props) {
@@ -4639,7 +4643,7 @@ function useDropdownPortal({ anchorRef, isOpen, onClose, positionStrategy = defa
4639
4643
  return { panelRef, panelStyle: style, renderPanel };
4640
4644
  }
4641
4645
 
4642
- var styles$f = {"dropdown":"cw-dropdown-module__dropdown__EFZ9M cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-dropdown-module__option__TuMdI cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-dropdown-module__optionFocused__7LGaC cw-choice-dropdown-module__optionFocused__BYMxj","optionSelected":"cw-dropdown-module__optionSelected__OiXIc cw-choice-dropdown-module__optionSelected__Lt8Xg","optionDisabled":"cw-dropdown-module__optionDisabled__lYM6w cw-choice-dropdown-module__optionDisabled__n3scM","emptyState":"cw-dropdown-module__emptyState__gp8KT cw-choice-dropdown-module__emptyState__HO0Y7","searchBox":"cw-dropdown-module__searchBox__Bx0JE cw-choice-dropdown-module__searchBox__0gox7","searchInput":"cw-dropdown-module__searchInput__JrxCK cw-choice-dropdown-module__searchInput__G5oRs","value":"cw-dropdown-module__value__i-7IN","colorCircle":"cw-dropdown-module__colorCircle__5kgiT cw-choice-dropdown-module__colorCircle__x7mI9"};
4646
+ var styles$i = {"dropdown":"cw-dropdown-module__dropdown__EFZ9M cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-dropdown-module__option__TuMdI cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-dropdown-module__optionFocused__7LGaC cw-choice-dropdown-module__optionFocused__BYMxj","optionSelected":"cw-dropdown-module__optionSelected__OiXIc cw-choice-dropdown-module__optionSelected__Lt8Xg","optionDisabled":"cw-dropdown-module__optionDisabled__lYM6w cw-choice-dropdown-module__optionDisabled__n3scM","emptyState":"cw-dropdown-module__emptyState__gp8KT cw-choice-dropdown-module__emptyState__HO0Y7","searchBox":"cw-dropdown-module__searchBox__Bx0JE cw-choice-dropdown-module__searchBox__0gox7","searchInput":"cw-dropdown-module__searchInput__JrxCK cw-choice-dropdown-module__searchInput__G5oRs","value":"cw-dropdown-module__value__i-7IN","colorCircle":"cw-dropdown-module__colorCircle__5kgiT cw-choice-dropdown-module__colorCircle__x7mI9"};
4643
4647
 
4644
4648
  /**
4645
4649
  * Custom dropdown component with colour-coded options, optional search filter, and full
@@ -4753,12 +4757,12 @@ function CwDropdown({ options, value, onChange, labelProps, alignProps, placehol
4753
4757
  }
4754
4758
  }, [isOpen, highlightedIndex, filteredOptions, handleOptionSelect]);
4755
4759
  const flexDirection = alignProps?.flexDirection ?? "row";
4756
- return (jsxRuntime.jsx("div", { ref: containerRef, className: `cw-dropdown${className ? ` ${className}` : ""}`, "data-direction": flexDirection, style: style, ...otherProps, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && jsxRuntime.jsx(CwLabel, { id: labelId, ...labelProps }), jsxRuntime.jsxs("div", { className: styles$f.value, children: [jsxRuntime.jsxs("div", { className: "cw-dropdown-wrapper", ref: wrapperRef, children: [jsxRuntime.jsxs("button", { type: "button", className: "cw-dropdown-trigger", onClick: handleTriggerClick, onKeyDown: handleKeyDown, disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-labelledby": labelProps ? `${labelId} ${valueId}` : undefined, "aria-label": labelProps ? undefined : (selectedOption?.label || placeholder), "aria-describedby": describedBy, children: [jsxRuntime.jsx("div", { className: "cw-dropdown-trigger-content", id: valueId, children: selectedOption ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [selectedOption.color && (jsxRuntime.jsx("span", { className: styles$f.colorCircle, style: { backgroundColor: selectedOption.color } })), jsxRuntime.jsx("span", { children: selectedOption.label })] })) : (jsxRuntime.jsx("span", { className: "cw-dropdown-placeholder", children: placeholder })) }), jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small" })] }), renderPanel(jsxRuntime.jsxs("div", { ref: panelRef, className: styles$f.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsxRuntime.jsx("div", { className: styles$f.searchBox, children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: styles$f.searchInput, autoComplete: "off" }) })), jsxRuntime.jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxRuntime.jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
4757
- styles$f.option,
4758
- value === option.value ? styles$f.optionSelected : "",
4759
- highlightedIndex === index ? styles$f.optionFocused : "",
4760
- option.disabled ? styles$f.optionDisabled : "",
4761
- ].filter(Boolean).join(" "), onClick: () => !option.disabled && handleOptionSelect(option.value), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": value === option.value, "aria-disabled": option.disabled, children: [option.color && (jsxRuntime.jsx("span", { className: styles$f.colorCircle, style: { backgroundColor: option.color } })), jsxRuntime.jsx("span", { children: option.label })] }, option.value)))) : (jsxRuntime.jsx("li", { className: styles$f.emptyState, children: "No options available" })) })] }))] }), feedbackMessages.map((item, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": item.type, "aria-live": "polite", children: item.message }, index)))] })] }) }));
4760
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: `cw-dropdown${className ? ` ${className}` : ""}`, "data-direction": flexDirection, style: style, ...otherProps, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && jsxRuntime.jsx(CwLabel, { id: labelId, ...labelProps }), jsxRuntime.jsxs("div", { className: styles$i.value, children: [jsxRuntime.jsxs("div", { className: "cw-dropdown-wrapper", ref: wrapperRef, children: [jsxRuntime.jsxs("button", { type: "button", className: "cw-dropdown-trigger", onClick: handleTriggerClick, onKeyDown: handleKeyDown, disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-labelledby": labelProps ? `${labelId} ${valueId}` : undefined, "aria-label": labelProps ? undefined : (selectedOption?.label || placeholder), "aria-describedby": describedBy, children: [jsxRuntime.jsx("div", { className: "cw-dropdown-trigger-content", id: valueId, children: selectedOption ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [selectedOption.color && (jsxRuntime.jsx("span", { className: styles$i.colorCircle, style: { backgroundColor: selectedOption.color } })), jsxRuntime.jsx("span", { children: selectedOption.label })] })) : (jsxRuntime.jsx("span", { className: "cw-dropdown-placeholder", children: placeholder })) }), jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small" })] }), renderPanel(jsxRuntime.jsxs("div", { ref: panelRef, className: styles$i.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsxRuntime.jsx("div", { className: styles$i.searchBox, children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: styles$i.searchInput, autoComplete: "off" }) })), jsxRuntime.jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxRuntime.jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
4761
+ styles$i.option,
4762
+ value === option.value ? styles$i.optionSelected : "",
4763
+ highlightedIndex === index ? styles$i.optionFocused : "",
4764
+ option.disabled ? styles$i.optionDisabled : "",
4765
+ ].filter(Boolean).join(" "), onClick: () => !option.disabled && handleOptionSelect(option.value), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": value === option.value, "aria-disabled": option.disabled, children: [option.color && (jsxRuntime.jsx("span", { className: styles$i.colorCircle, style: { backgroundColor: option.color } })), jsxRuntime.jsx("span", { children: option.label })] }, option.value)))) : (jsxRuntime.jsx("li", { className: styles$i.emptyState, children: "No options available" })) })] }))] }), feedbackMessages.map((item, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": item.type, "aria-live": "polite", children: item.message }, index)))] })] }) }));
4762
4766
  }
4763
4767
 
4764
4768
  /**
@@ -4775,7 +4779,7 @@ function CwDropdownFilter(props) {
4775
4779
  return (jsxRuntime.jsxs("div", { id: props.IdContent, className: containerClassName, children: [props.children, isVisible && (jsxRuntime.jsx("nav", { className: "cw-dropdown-menu", style: inlineStyles, onMouseLeave: props.onMouseLeave, id: props.idDropDownFilter, role: "menu", children: jsxRuntime.jsx("ul", { role: "none", children: props.DataSourceDropDownItem?.map((item) => (jsxRuntime.jsx("li", { id: item.IdDropDown_filter, role: "menuitem", children: item.dropDownFilter_desc }, item.IdDropDown_filter))) }) }))] }));
4776
4780
  }
4777
4781
 
4778
- var styles$e = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
4782
+ var styles$h = {"container":"cw-popover-button-module__container__YSWQU","panel":"cw-popover-button-module__panel__C-BTn"};
4779
4783
 
4780
4784
  /**
4781
4785
  * Button that toggles a floating panel with arbitrary children.
@@ -4854,7 +4858,7 @@ function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-st
4854
4858
  }
4855
4859
  panel.showPopover();
4856
4860
  }, [placement]);
4857
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$e.container, children: [jsxRuntime.jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsxRuntime.jsx("div", { ref: panelCallbackRef, className: `${styles$e.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4861
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$h.container, children: [jsxRuntime.jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsxRuntime.jsx("div", { ref: panelCallbackRef, className: `${styles$h.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4858
4862
  }
4859
4863
 
4860
4864
  function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor, onPrimaryColor) {
@@ -4872,13 +4876,13 @@ function itemsToMultiFilterTags(items, nameKey, valueKey, category, primaryColor
4872
4876
  return result;
4873
4877
  }
4874
4878
 
4875
- var styles$d = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
4879
+ var styles$g = {"cw-multifilter-tag":"cw-multi-filter-tag-module__cw-multifilter-tag__Epda-"};
4876
4880
 
4877
4881
  const CwMultiFilterTag = props => {
4878
4882
  const { ID, Name, Value, Category, Removable, PrimaryColor, Selectable, Selected } = props;
4879
4883
  const backgroundColor = `rgb(${PrimaryColor.r},${PrimaryColor.g},${PrimaryColor.b})`;
4880
4884
  const isOutlineMode = Selected && !Removable;
4881
- return (jsxRuntime.jsx("li", { className: styles$d["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
4885
+ return (jsxRuntime.jsx("li", { className: styles$g["cw-multifilter-tag"], id: ID, "data-value": Value, "data-category": Category, "data-selected": !!Selected, title: props.tooltip ?? Name, onClick: () => {
4882
4886
  if (Selectable)
4883
4887
  props.OnSelect?.(props);
4884
4888
  }, children: jsxRuntime.jsx(CwChip, { label: Name, colorScheme: "custom", customColor: backgroundColor, variant: isOutlineMode ? "outline" : "soft", closable: Removable, onClose: () => props.OnRemove?.(props),
@@ -4888,7 +4892,7 @@ const CwMultiFilterTag = props => {
4888
4892
  } : undefined }) }));
4889
4893
  };
4890
4894
 
4891
- var styles$c = {"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"};
4895
+ var styles$f = {"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"};
4892
4896
 
4893
4897
  /**
4894
4898
  * A multiple filter selector, a MULTI-SELECT even. Allows users to select and filter items based on tags.
@@ -5129,9 +5133,9 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
5129
5133
  inputRef.current?.focus();
5130
5134
  }
5131
5135
  };
5132
- return (jsxRuntime.jsxs("form", { ref: componentRef, id: id, "data-testid": testId, className: `${styles$c["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
5136
+ return (jsxRuntime.jsxs("form", { ref: componentRef, id: id, "data-testid": testId, className: `${styles$f["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
5133
5137
  e.preventDefault();
5134
- }, children: [jsxRuntime.jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$c["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-outline-variant)" } : {}, children: [jsxRuntime.jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (React.createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsxRuntime.jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.currentTarget.value), autoComplete: "off", placeholder: selectedTags.size === 0 ? placeholder : "", onKeyDown: e => {
5138
+ }, children: [jsxRuntime.jsxs("div", { onClick: handleDivClick, ref: wrapperRef, className: styles$f["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-outline-variant)" } : {}, children: [jsxRuntime.jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (React.createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsxRuntime.jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.currentTarget.value), autoComplete: "off", placeholder: selectedTags.size === 0 ? placeholder : "", onKeyDown: e => {
5135
5139
  switch (e.key) {
5136
5140
  case "Enter":
5137
5141
  case "Tab": {
@@ -5158,7 +5162,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
5158
5162
  break;
5159
5163
  }
5160
5164
  }
5161
- } })] }), selectedTags.size > 0 && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxRuntime.jsxs("section", { ref: panelRef, className: styles$c["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxRuntime.jsxs("nav", { children: [jsxRuntime.jsx("button", { className: selectedCategory === "All" ? styles$c["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsxRuntime.jsx("button", { className: selectedCategory === category ? styles$c["category-selected"] : undefined, style: {
5165
+ } })] }), selectedTags.size > 0 && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: e => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChangeSelectedTags(new Set()); setIsPanelOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), renderPanel(jsxRuntime.jsxs("section", { ref: panelRef, className: styles$f["cw-multi-filter-catalog-container"], style: panelStyle, children: [jsxRuntime.jsxs("nav", { children: [jsxRuntime.jsx("button", { className: selectedCategory === "All" ? styles$f["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsxRuntime.jsx("button", { className: selectedCategory === category ? styles$f["category-selected"] : undefined, style: {
5162
5166
  backgroundColor: getColor(category).primary,
5163
5167
  color: getColor(category).onPrimary,
5164
5168
  }, onClick: () => handleClickCategory(category), children: category }, category)))] }), jsxRuntime.jsx("ul", { children: displayTags
@@ -5184,7 +5188,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
5184
5188
  } }, props.ID))) })] }))] }));
5185
5189
  };
5186
5190
 
5187
- var styles$b = {"container":"cw-tag-selector-module__container__-do8i","value":"cw-tag-selector-module__value__TDAy3","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"};
5191
+ var styles$e = {"container":"cw-tag-selector-module__container__-do8i","value":"cw-tag-selector-module__value__TDAy3","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"};
5188
5192
 
5189
5193
  /**
5190
5194
  * Multi-select input with chip tags and searchable dropdown.
@@ -5222,6 +5226,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5222
5226
  isOpen: open,
5223
5227
  onClose: () => { setOpen(false); setFocusedIndex(-1); },
5224
5228
  });
5229
+ // Disabling while the panel is open closes it (state adjusted during render, no effect pass).
5230
+ if (disabled && open) {
5231
+ setOpen(false);
5232
+ setFocusedIndex(-1);
5233
+ }
5225
5234
  const selectedSet = React.useMemo(() => new Set(value), [value]);
5226
5235
  const filtered = React.useMemo(() => {
5227
5236
  if (!search)
@@ -5231,17 +5240,23 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5231
5240
  }, [options, selectedSet, search]);
5232
5241
  const selectedOptions = React.useMemo(() => value.map(v => options.find(o => o.value === v)).filter(Boolean), [value, options]);
5233
5242
  const handleSelect = React.useCallback((optionValue) => {
5243
+ if (disabled)
5244
+ return;
5234
5245
  onChange([...value, optionValue]);
5235
5246
  setSearch("");
5236
5247
  setFocusedIndex(-1);
5237
5248
  inputRef.current?.focus();
5238
- }, [value, onChange]);
5249
+ }, [disabled, value, onChange]);
5239
5250
  const handleRemove = React.useCallback((optionValue) => {
5251
+ if (disabled)
5252
+ return;
5240
5253
  onChange(value.filter(v => v !== optionValue));
5241
5254
  inputRef.current?.focus();
5242
- }, [value, onChange]);
5255
+ }, [disabled, value, onChange]);
5243
5256
  const allSelected = options.length > 0 && options.every(o => selectedSet.has(o.value));
5244
5257
  const handleToggleAll = React.useCallback(() => {
5258
+ if (disabled)
5259
+ return;
5245
5260
  if (allSelected) {
5246
5261
  onChange([]);
5247
5262
  }
@@ -5251,7 +5266,7 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5251
5266
  setSearch("");
5252
5267
  setFocusedIndex(-1);
5253
5268
  inputRef.current?.focus();
5254
- }, [allSelected, options, onChange]);
5269
+ }, [disabled, allSelected, options, onChange]);
5255
5270
  const handleInputChange = React.useCallback((e) => {
5256
5271
  setSearch(e.currentTarget.value);
5257
5272
  if (!open)
@@ -5263,6 +5278,8 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5263
5278
  setOpen(true);
5264
5279
  }, [disabled]);
5265
5280
  const handleKeyDown = React.useCallback((e) => {
5281
+ if (disabled)
5282
+ return;
5266
5283
  if (e.key === "Backspace" && !search && value.length > 0) {
5267
5284
  onChange(value.slice(0, -1));
5268
5285
  return;
@@ -5307,7 +5324,7 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5307
5324
  e.preventDefault();
5308
5325
  setFocusedIndex(prev => (prev > 0 ? prev - 1 : 0));
5309
5326
  }
5310
- }, [open, search, value, filtered, focusedIndex, onChange, handleSelect]);
5327
+ }, [disabled, open, search, value, filtered, focusedIndex, onChange, handleSelect]);
5311
5328
  // Scroll focused item into view
5312
5329
  React.useEffect(() => {
5313
5330
  if (focusedIndex >= 0 && listRef.current) {
@@ -5322,11 +5339,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5322
5339
  const feedbackId = React.useId();
5323
5340
  const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
5324
5341
  const describedBy = feedbackIds.join(" ") || undefined;
5325
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$b.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: styles$b.value, children: [jsxRuntime.jsxs("div", { className: `${styles$b.inputBox}${disabled ? ` ${styles$b.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
5326
- inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsxRuntime.jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off", "aria-describedby": describedBy }), value.length > 0 && !disabled && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), feedbackMessages.map((fb, i) => (jsxRuntime.jsx("p", { id: feedbackIds[i], className: "cw-input-feedback", "data-color": fb.type, "aria-live": "polite", children: fb.message }, i)))] })] }), renderPanel((showSelectAll || filtered.length > 0) ? (jsxRuntime.jsxs("div", { ref: panelRef, className: styles$b.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$b.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.jsxs("li", { className: `${styles$b.option}${idx === focusedIndex ? ` ${styles$b.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsxRuntime.jsx("span", { className: styles$b.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
5342
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$e.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: styles$e.value, children: [jsxRuntime.jsxs("div", { className: `${styles$e.inputBox}${disabled ? ` ${styles$e.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
5343
+ inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsxRuntime.jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off", "aria-describedby": describedBy }), value.length > 0 && !disabled && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), feedbackMessages.map((fb, i) => (jsxRuntime.jsx("p", { id: feedbackIds[i], className: "cw-input-feedback", "data-color": fb.type, "aria-live": "polite", children: fb.message }, i)))] })] }), renderPanel((showSelectAll || filtered.length > 0) ? (jsxRuntime.jsxs("div", { ref: panelRef, className: styles$e.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$e.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.jsxs("li", { className: `${styles$e.option}${idx === focusedIndex ? ` ${styles$e.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsxRuntime.jsx("span", { className: styles$e.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
5327
5344
  }
5328
5345
 
5329
- var styles$a = {"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"};
5346
+ var styles$d = {"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"};
5330
5347
 
5331
5348
  function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId: initialSelectedId = null, ...dataAttributes }) {
5332
5349
  const [expanded, setExpanded] = React.useState(new Set());
@@ -5393,10 +5410,10 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
5393
5410
  const isLeaf = !hasChildren;
5394
5411
  const isSelected = selectedId?.toString().toLowerCase() === node.id.toString().toLowerCase();
5395
5412
  const selectable = allowParentSelection || isLeaf;
5396
- return (jsxRuntime.jsxs("div", { className: styles$a["tree-item"], children: [jsxRuntime.jsxs("div", { className: [
5397
- styles$a["tree-node"],
5398
- isSelected && styles$a["selected"],
5399
- !selectable && styles$a["non-selectable"]
5413
+ return (jsxRuntime.jsxs("div", { className: styles$d["tree-item"], children: [jsxRuntime.jsxs("div", { className: [
5414
+ styles$d["tree-node"],
5415
+ isSelected && styles$d["selected"],
5416
+ !selectable && styles$d["non-selectable"]
5400
5417
  ].filter(Boolean).join(' '), style: { paddingLeft: `${depth * 24 + 8}px` }, onClick: () => {
5401
5418
  if (selectable) {
5402
5419
  setSelectedId(node.id);
@@ -5408,7 +5425,7 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
5408
5425
  }, children: [hasChildren && (jsxRuntime.jsx(CwButton, { variant: "icon", color: "neutral", icon: isExpanded ? "chevron-down" : "chevron-right", "aria-expanded": isExpanded, "aria-label": `${isExpanded ? "Collapse" : "Expand"} ${node.label}`, onClick: (event) => {
5409
5426
  event.stopPropagation();
5410
5427
  toggleExpand(node.id);
5411
- } })), jsxRuntime.jsx("div", { className: `${styles$a["tree-label"]} ${!hasChildren ? styles$a["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsxRuntime.jsx("div", { className: styles$a["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
5428
+ } })), jsxRuntime.jsx("div", { className: `${styles$d["tree-label"]} ${!hasChildren ? styles$d["tree-spacer"] : ''}`, children: node.label })] }), hasChildren && isExpanded && (jsxRuntime.jsx("div", { className: styles$d["tree-children"], children: node.children.map((child) => renderNode(child, depth + 1)) }))] }, node.id));
5412
5429
  };
5413
5430
  // Function to search for nodes that match the search term
5414
5431
  const searchInTree = (nodes, searchTerm) => {
@@ -5432,7 +5449,7 @@ function CwTreeView({ data, onSelect, allowParentSelection = false, selectedId:
5432
5449
  return results;
5433
5450
  };
5434
5451
  const filteredData = searchInTree(data, search);
5435
- return (jsxRuntime.jsxs("div", { ...dataAttributes, className: `cw-tree-view ${styles$a["tree-container"]}`, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsxRuntime.jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsxRuntime.jsx("div", { className: styles$a["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxRuntime.jsxs("div", { className: styles$a["empty-state"], children: [jsxRuntime.jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
5452
+ return (jsxRuntime.jsxs("div", { ...dataAttributes, className: `cw-tree-view ${styles$d["tree-container"]}`, children: [jsxRuntime.jsxs("header", { children: [jsxRuntime.jsx("input", { type: "text", placeholder: "Search in tree...", value: search, onChange: (e) => setSearch(e.target.value) }), search && (jsxRuntime.jsx(CwButton, { onClick: () => setSearch(""), type: "button", icon: "close", variant: "icon", color: "neutral" }))] }), jsxRuntime.jsx("div", { className: styles$d["tree-wrapper"], children: filteredData.length > 0 ? (filteredData.map((node) => renderNode(node))) : (jsxRuntime.jsxs("div", { className: styles$d["empty-state"], children: [jsxRuntime.jsx(CwIcon, { iconId: "comment" }), search ? "No results found" : "There are no items"] })) })] }));
5436
5453
  }
5437
5454
 
5438
5455
  const EXACT_PHRASE = /"([^"]+)"/g;
@@ -5500,7 +5517,7 @@ function sortNavItems(items, alphabetically) {
5500
5517
  return [...items].sort((first, second) => first.label.localeCompare(second.label));
5501
5518
  }
5502
5519
 
5503
- var styles$9 = {"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"};
5520
+ var styles$c = {"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"};
5504
5521
 
5505
5522
  const SKELETON_ROW_COUNT = 5;
5506
5523
  const defaultRenderLink = (item, children) => (jsxRuntime.jsx("a", { href: item.href, children: children }));
@@ -5512,13 +5529,13 @@ function CwNavMenu({ items, loading = false, isActive, renderLink = defaultRende
5512
5529
  const renderItem = (item, level) => {
5513
5530
  const children = item.children;
5514
5531
  if (children && children.length > 0) {
5515
- return (jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("details", { "data-level": level, open: hasActiveDescendant(item) || undefined, children: [jsxRuntime.jsxs("summary", { children: [item.icon && jsxRuntime.jsx(CwIcon, { iconId: item.icon, size: level >= 2 ? "small" : "medium" }), item.label, (showExpandIndicator || level >= 2) && (jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small", className: styles$9.expandIndicator }))] }), jsxRuntime.jsx("ul", { children: children.map(child => renderItem(child, level + 1)) })] }) }, item.id));
5532
+ return (jsxRuntime.jsx("li", { children: jsxRuntime.jsxs("details", { "data-level": level, open: hasActiveDescendant(item) || undefined, children: [jsxRuntime.jsxs("summary", { children: [item.icon && jsxRuntime.jsx(CwIcon, { iconId: item.icon, size: level >= 2 ? "small" : "medium" }), item.label, (showExpandIndicator || level >= 2) && (jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small", className: styles$c.expandIndicator }))] }), jsxRuntime.jsx("ul", { children: children.map(child => renderItem(child, level + 1)) })] }) }, item.id));
5516
5533
  }
5517
- return (jsxRuntime.jsx("li", { "data-active": isActive?.(item) ? "true" : undefined, children: renderLink(item, jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [item.icon && jsxRuntime.jsx(CwIcon, { iconId: item.icon, size: "medium" }), item.label, isFavorite?.(item) && jsxRuntime.jsx(CwIcon, { iconId: "star", size: "small", className: styles$9.favoriteStar })] })) }, item.id));
5534
+ return (jsxRuntime.jsx("li", { "data-active": isActive?.(item) ? "true" : undefined, children: renderLink(item, jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [item.icon && jsxRuntime.jsx(CwIcon, { iconId: item.icon, size: "medium" }), item.label, isFavorite?.(item) && jsxRuntime.jsx(CwIcon, { iconId: "star", size: "small", className: styles$c.favoriteStar })] })) }, item.id));
5518
5535
  };
5519
- return (jsxRuntime.jsxs("nav", { ...navProps, className: [styles$9.menu, className].filter(Boolean).join(" "), "aria-busy": loading || undefined, children: [favoritesSlot && (jsxRuntime.jsxs("details", { open: true, ...favoritesProps, className: [styles$9.favorites, favoritesProps?.className].filter(Boolean).join(" "), children: [jsxRuntime.jsxs("summary", { children: [jsxRuntime.jsx(CwIcon, { iconId: "star", size: "medium" }), favoritesLabel] }), jsxRuntime.jsx("div", { className: styles$9.favoritesContent, children: favoritesSlot })] })), beforeTreeSlot, jsxRuntime.jsx("ul", { children: loading
5520
- ? Array.from({ length: SKELETON_ROW_COUNT }, (_unused, index) => (jsxRuntime.jsx("li", { className: styles$9.skeleton, children: jsxRuntime.jsx(CwSkeleton, { height: "var(--cw-size-small)", radius: "var(--cw-border-radius-small)" }) }, index)))
5521
- : visibleItems.map(item => renderItem(item, 1)) }), showEmptyMessage && jsxRuntime.jsx("p", { className: styles$9.emptyMessage, children: emptyMessage })] }));
5536
+ return (jsxRuntime.jsxs("nav", { ...navProps, className: [styles$c.menu, className].filter(Boolean).join(" "), "aria-busy": loading || undefined, children: [favoritesSlot && (jsxRuntime.jsxs("details", { open: true, ...favoritesProps, className: [styles$c.favorites, favoritesProps?.className].filter(Boolean).join(" "), children: [jsxRuntime.jsxs("summary", { children: [jsxRuntime.jsx(CwIcon, { iconId: "star", size: "medium" }), favoritesLabel] }), jsxRuntime.jsx("div", { className: styles$c.favoritesContent, children: favoritesSlot })] })), beforeTreeSlot, jsxRuntime.jsx("ul", { children: loading
5537
+ ? Array.from({ length: SKELETON_ROW_COUNT }, (_unused, index) => (jsxRuntime.jsx("li", { className: styles$c.skeleton, children: jsxRuntime.jsx(CwSkeleton, { height: "var(--cw-size-small)", radius: "var(--cw-border-radius-small)" }) }, index)))
5538
+ : visibleItems.map(item => renderItem(item, 1)) }), showEmptyMessage && jsxRuntime.jsx("p", { className: styles$c.emptyMessage, children: emptyMessage })] }));
5522
5539
  }
5523
5540
 
5524
5541
  var dropdownStyles = {"dropdown":"cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-choice-dropdown-module__optionFocused__BYMxj"};
@@ -5684,7 +5701,7 @@ function CwSearchInput(optionsProps) {
5684
5701
  return (jsxRuntime.jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, ...otherProps, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("input", { ref: inputRef, id: id, type: "text", value: searchText, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled, autoFocus: autoFocus, autoComplete: "off", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": showDropdown && filteredOptions.length > 0, "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 ? optionId(highlightedIndex) : undefined }), isLoading && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsxRuntime.jsx(CwIcon, { ...iconProps }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: filteredOptions.map((option, index) => (jsxRuntime.jsx("li", { id: optionId(index), className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
5685
5702
  }
5686
5703
 
5687
- var styles$8 = {"value":"cw-search-async-module__value__z53xT"};
5704
+ var styles$b = {"value":"cw-search-async-module__value__z53xT"};
5688
5705
 
5689
5706
  /**
5690
5707
  * Generic API-backed search input. Fetches matching options from a caller-supplied `onSearch`
@@ -5948,10 +5965,10 @@ const CwSearchAsync = ({ onSearch, onChange, value, onResolveInitial, onResolveS
5948
5965
  return (jsxRuntime.jsxs("div", { ...dataAttributes, className: `cw-search-input ${className}`, style: {
5949
5966
  ...(width ? { width } : {}),
5950
5967
  ...(labelProps?.labelWidth ? { "--label-width": labelProps.labelWidth } : {}),
5951
- }, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$8.value, children: [jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.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, "aria-describedby": describedBy, title: tooltipText }), (isLoading || isInitialLoading) && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selection", variant: "icon", icon: "close", color: "neutral" })) : (icon ? jsxRuntime.jsx(CwIcon, { ...icon }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: options.map((option, index) => (jsxRuntime.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 ? (jsxRuntime.jsxs("span", { className: "cw-search-async-option-lines", children: [jsxRuntime.jsx("span", { children: option.label }), jsxRuntime.jsx("span", { className: "cw-search-async-option-sub", children: option.subLabel })] })) : (option.label) }, option.id))) }) }))] }));
5968
+ }, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$b.value, children: [jsxRuntime.jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsxRuntime.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, "aria-describedby": describedBy, title: tooltipText }), (isLoading || isInitialLoading) && (jsxRuntime.jsx("div", { className: "cw-search-input-loading", children: jsxRuntime.jsx(CwIcon, { iconId: "spinner" }) })), jsxRuntime.jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsxRuntime.jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selection", variant: "icon", icon: "close", color: "neutral" })) : (icon ? jsxRuntime.jsx(CwIcon, { ...icon }) : jsxRuntime.jsx(CwIcon, { iconId: "search" })) })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: options.map((option, index) => (jsxRuntime.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 ? (jsxRuntime.jsxs("span", { className: "cw-search-async-option-lines", children: [jsxRuntime.jsx("span", { children: option.label }), jsxRuntime.jsx("span", { className: "cw-search-async-option-sub", children: option.subLabel })] })) : (option.label) }, option.id))) }) }))] }));
5952
5969
  };
5953
5970
 
5954
- var styles$7 = {"menu":"cw-context-menu-module__menu__tXmun","item":"cw-context-menu-module__item__-ko8L","arrow":"cw-context-menu-module__arrow__LHZmQ"};
5971
+ var styles$a = {"menu":"cw-context-menu-module__menu__tXmun","item":"cw-context-menu-module__item__-ko8L","arrow":"cw-context-menu-module__arrow__LHZmQ"};
5955
5972
 
5956
5973
  const ARROW_SIZE = 8;
5957
5974
  const SAFETY_MARGIN = 8;
@@ -6092,14 +6109,14 @@ const CwAnchoredMenu = ({ children, options, onSelect, placement = 'bottom', ope
6092
6109
  document.removeEventListener("keydown", handleEscape);
6093
6110
  };
6094
6111
  }, [isOpen]);
6095
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, style: { display: "contents" }, children: children }), isOpen && normalizedOptions.length > 0 && reactDom.createPortal(jsxRuntime.jsxs("div", { ref: menuRef, className: styles$7["menu"], style: {
6112
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, style: { display: "contents" }, children: children }), isOpen && normalizedOptions.length > 0 && reactDom.createPortal(jsxRuntime.jsxs("div", { ref: menuRef, className: styles$a["menu"], style: {
6096
6113
  top: `${position.y}px`,
6097
6114
  left: `${position.x}px`,
6098
- }, "data-has-arrow": "true", children: [jsxRuntime.jsx("div", { ref: arrowRef, className: styles$7["arrow"], "data-placement": placement }), normalizedOptions.map(option => (jsxRuntime.jsxs("div", { onClick: (e) => {
6115
+ }, "data-has-arrow": "true", children: [jsxRuntime.jsx("div", { ref: arrowRef, className: styles$a["arrow"], "data-placement": placement }), normalizedOptions.map(option => (jsxRuntime.jsxs("div", { onClick: (e) => {
6099
6116
  e.stopPropagation();
6100
6117
  e.preventDefault();
6101
6118
  handleOptionClick(option);
6102
- }, className: `${styles$7["item"]} ${option.disabled ? styles$7["disabled"] : ""}`, "data-disabled": option.disabled, children: [option.icon && jsxRuntime.jsx("span", { className: styles$7["icon"], children: option.icon }), option.label] }, option.key)))] }), document.body)] }));
6119
+ }, className: `${styles$a["item"]} ${option.disabled ? styles$a["disabled"] : ""}`, "data-disabled": option.disabled, children: [option.icon && jsxRuntime.jsx("span", { className: styles$a["icon"], children: option.icon }), option.label] }, option.key)))] }), document.body)] }));
6103
6120
  };
6104
6121
 
6105
6122
  /**
@@ -6172,13 +6189,13 @@ const CwContextMenu = ({ children, options, offset = DEFAULT_OFFSET, onSelect })
6172
6189
  document.removeEventListener("keydown", handleEscape);
6173
6190
  };
6174
6191
  }, [isOpen]);
6175
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { onContextMenu: handleContextMenu, children: children }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: menuRef, className: styles$7["menu"], style: {
6192
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { onContextMenu: handleContextMenu, children: children }), isOpen && reactDom.createPortal(jsxRuntime.jsx("div", { ref: menuRef, className: styles$a["menu"], style: {
6176
6193
  top: `${position.y}px`,
6177
6194
  left: `${position.x}px`,
6178
- }, children: options.map(option => (jsxRuntime.jsx("div", { onClick: () => handleOptionClick(option), className: styles$7["item"], children: option }, option))) }), document.body)] }));
6195
+ }, children: options.map(option => (jsxRuntime.jsx("div", { onClick: () => handleOptionClick(option), className: styles$a["item"], children: option }, option))) }), document.body)] }));
6179
6196
  };
6180
6197
 
6181
- var styles$6 = {"split":"cw-button-split-module__split__B2KbU","menu":"cw-button-split-module__menu__mKDlt","item":"cw-button-split-module__item__Aqw6f"};
6198
+ var styles$9 = {"split":"cw-button-split-module__split__B2KbU","menu":"cw-button-split-module__menu__mKDlt","item":"cw-button-split-module__item__Aqw6f"};
6182
6199
 
6183
6200
  /**
6184
6201
  * CwButtonSplit - A primary action joined to a dropdown of alternative actions.
@@ -6204,7 +6221,7 @@ function CwButtonSplit({ text, icon, onClick, actions, onSelect, variant = "soli
6204
6221
  onSelect(action.key);
6205
6222
  event.currentTarget.closest("[popover]")?.hidePopover();
6206
6223
  };
6207
- return (jsxRuntime.jsxs("div", { className: styles$6.split, "data-variant": variant, "data-testid": dataTestId, children: [jsxRuntime.jsx(CwButton, { text: text, icon: icon, variant: variant, color: color, size: size, onClick: onClick, disabled: disabled }), jsxRuntime.jsx(CwPopoverButton, { icon: "chevron-down", title: "More actions", variant: variant, color: color, size: size, disabled: disabled, placement: placement, children: jsxRuntime.jsx("div", { className: styles$6.menu, children: actions.map((action) => (jsxRuntime.jsx(CwButton, { variant: "ghost", color: "neutral", text: action.label, icon: action.icon, disabled: action.disabled, className: styles$6.item, onClick: handleSelect(action) }, action.key))) }) })] }));
6224
+ return (jsxRuntime.jsxs("div", { className: styles$9.split, "data-variant": variant, "data-testid": dataTestId, children: [jsxRuntime.jsx(CwButton, { text: text, icon: icon, variant: variant, color: color, size: size, onClick: onClick, disabled: disabled }), jsxRuntime.jsx(CwPopoverButton, { icon: "chevron-down", title: "More actions", variant: variant, color: color, size: size, disabled: disabled, placement: placement, children: jsxRuntime.jsx("div", { className: styles$9.menu, children: actions.map((action) => (jsxRuntime.jsx(CwButton, { variant: "ghost", color: "neutral", text: action.label, icon: action.icon, disabled: action.disabled, className: styles$9.item, onClick: handleSelect(action) }, action.key))) }) })] }));
6208
6225
  }
6209
6226
 
6210
6227
  /**
@@ -6272,7 +6289,7 @@ function useRovingSingleSelect(options, value, onChange) {
6272
6289
  return { activeIndex, getSegmentProps };
6273
6290
  }
6274
6291
 
6275
- var styles$5 = {"switch":"cw-button-switch-module__switch__vdWV-","segment":"cw-button-switch-module__segment__JmVla","iconOnly":"cw-button-switch-module__iconOnly__-kCwj"};
6292
+ var styles$8 = {"switch":"cw-button-switch-module__switch__vdWV-","segment":"cw-button-switch-module__segment__JmVla","iconOnly":"cw-button-switch-module__iconOnly__-kCwj"};
6276
6293
 
6277
6294
  /**
6278
6295
  * CwButtonSwitch - Segmented single-select control: a strip of joined CwButtons.
@@ -6302,10 +6319,10 @@ var styles$5 = {"switch":"cw-button-switch-module__switch__vdWV-","segment":"cw-
6302
6319
  */
6303
6320
  function CwButtonSwitch({ options, value, onChange, size = "medium", color = "primary", iconOnly = false, direction = "row", disabled = false, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, ...dataAttributes }) {
6304
6321
  const { getSegmentProps } = useRovingSingleSelect(options, value, onChange);
6305
- return (jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-button-switch ${styles$5.switch}`, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : ariaLabel, "data-direction": direction, children: options.map((option, index) => {
6322
+ return (jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-button-switch ${styles$8.switch}`, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : ariaLabel, "data-direction": direction, children: options.map((option, index) => {
6306
6323
  const selected = option.value === value;
6307
6324
  const segmentProps = getSegmentProps(index);
6308
- return (jsxRuntime.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));
6325
+ return (jsxRuntime.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$8.segment}${iconOnly ? ` ${styles$8.iconOnly}` : ""}`, tabIndex: segmentProps.tabIndex, ref: segmentProps.ref, onKeyDown: segmentProps.onKeyDown }, option.value));
6309
6326
  }) }));
6310
6327
  }
6311
6328
 
@@ -6347,7 +6364,7 @@ function CwBtnCancel({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...res
6347
6364
  return (jsxRuntime.jsx(CwButton, { ...rest, variant: "icon", icon: "cancel", color: "danger", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Cancel" }));
6348
6365
  }
6349
6366
 
6350
- var styles$4 = {"value":"cw-pickers-base-module__value__BR67P","pickerWrapper":"cw-pickers-base-module__pickerWrapper__Fb9Zo","pickerIcons":"cw-pickers-base-module__pickerIcons__dyd2-","pickerPopup":"cw-pickers-base-module__pickerPopup__dkxJo"};
6367
+ var styles$7 = {"value":"cw-pickers-base-module__value__BR67P","pickerWrapper":"cw-pickers-base-module__pickerWrapper__Fb9Zo","pickerIcons":"cw-pickers-base-module__pickerIcons__dyd2-","pickerPopup":"cw-pickers-base-module__pickerPopup__dkxJo"};
6351
6368
 
6352
6369
  /**
6353
6370
  * Renders a picker popup in a portal so it escapes overflow containers.
@@ -6587,7 +6604,7 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
6587
6604
  ...(maxDate ? [{ after: maxDate }] : []),
6588
6605
  ...(disabledMatcher ? [disabledMatcher] : []),
6589
6606
  ], [disabledDates, minDate, maxDate, disabledMatcher]);
6590
- return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-datepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "single", selected: value || undefined, defaultMonth: defaultMonth || value || undefined, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
6607
+ return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-datepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: styles$7.pickerPopup, style: popupStyle, children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "single", selected: value || undefined, defaultMonth: defaultMonth || value || undefined, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
6591
6608
  today: new Date(),
6592
6609
  }, modifiersClassNames: {
6593
6610
  today: "rdp-day-today",
@@ -7236,7 +7253,7 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
7236
7253
  }
7237
7254
  return undefined;
7238
7255
  }, [value]);
7239
- return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxRuntime.jsxs("div", { className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputFromRef, type: "text", value: inputFromValue, placeholder: placeholderFrom, onChange: handleInputFromChange, onBlur: () => handleInputBlur('from'), onClick: handleInputFromClick, onKeyDown: (e) => handleInputKeyDown(e, 'from'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'from' }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.from && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), jsxRuntime.jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxRuntime.jsxs("div", { className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputToRef, type: "text", value: inputToValue, placeholder: placeholderTo, onChange: handleInputToChange, onBlur: () => handleInputBlur('to'), onClick: handleInputToClick, onKeyDown: (e) => handleInputKeyDown(e, 'to'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'to' }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.to && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxRuntime.jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsxRuntime.jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsxRuntime.jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonth || value?.from || undefined, modifiers: {
7256
+ return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxRuntime.jsxs("div", { className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputFromRef, type: "text", value: inputFromValue, placeholder: placeholderFrom, onChange: handleInputFromChange, onBlur: () => handleInputBlur('from'), onClick: handleInputFromClick, onKeyDown: (e) => handleInputKeyDown(e, 'from'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'from' }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value?.from && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), jsxRuntime.jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxRuntime.jsxs("div", { className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputToRef, type: "text", value: inputToValue, placeholder: placeholderTo, onChange: handleInputToChange, onBlur: () => handleInputBlur('to'), onClick: handleInputToClick, onKeyDown: (e) => handleInputKeyDown(e, 'to'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'to' }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value?.to && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: `${styles$7.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxRuntime.jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsxRuntime.jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsxRuntime.jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonth || value?.from || undefined, modifiers: {
7240
7257
  today: new Date(),
7241
7258
  }, modifiersClassNames: {
7242
7259
  today: "rdp-day-today",
@@ -7409,10 +7426,10 @@ function CwTimePicker({ value, onChange, interval = 15, minTime, maxTime, labelP
7409
7426
  const displayValue = inputValue;
7410
7427
  // If using native time input
7411
7428
  if (useNative) {
7412
- return (jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-timepicker cw-timepicker-native ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsx("div", { className: styles$4.pickerWrapper, children: jsxRuntime.jsx("input", { type: "time", value: displayValue, onChange: handleNativeChange, min: minTime, max: maxTime, step: interval * 60, disabled: disabled, required: required, placeholder: placeholder, "aria-describedby": describedBy, className: "cw-timepicker-native" }) }), feedbackElements] })] }) }));
7429
+ return (jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-timepicker cw-timepicker-native ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsx("div", { className: styles$7.pickerWrapper, children: jsxRuntime.jsx("input", { type: "time", value: displayValue, onChange: handleNativeChange, min: minTime, max: maxTime, step: interval * 60, disabled: disabled, required: required, placeholder: placeholder, "aria-describedby": describedBy, className: "cw-timepicker-native" }) }), feedbackElements] })] }) }));
7413
7430
  }
7414
7431
  // Custom time picker
7415
- return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-timepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: `${styles$4.pickerWrapper} ${timeStyles.field}${showClear ? "" : ` ${timeStyles.narrow}`}`, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, maxLength: 5 }), showClear && (jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", icon: "close", color: "neutral", onClick: handleClear, tabIndex: -1, "aria-label": "Clear time" })) : (jsxRuntime.jsx(CwIcon, { iconId: "clock" })) })), renderPopup(jsxRuntime.jsx("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${timeStyles.timePickerPopup}`, style: popupStyle, children: jsxRuntime.jsx("div", { className: timeStyles.timePickerList, children: timeOptions.map((time) => {
7432
+ return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-timepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: `${styles$7.pickerWrapper} ${timeStyles.field}${showClear ? "" : ` ${timeStyles.narrow}`}`, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, maxLength: 5 }), showClear && (jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", icon: "close", color: "neutral", onClick: handleClear, tabIndex: -1, "aria-label": "Clear time" })) : (jsxRuntime.jsx(CwIcon, { iconId: "clock" })) })), renderPopup(jsxRuntime.jsx("div", { ref: popupRef, className: `${styles$7.pickerPopup} ${timeStyles.timePickerPopup}`, style: popupStyle, children: jsxRuntime.jsx("div", { className: timeStyles.timePickerList, children: timeOptions.map((time) => {
7416
7433
  const isSelected = time === value;
7417
7434
  return (jsxRuntime.jsx("button", { ref: isSelected ? selectedItemRef : null, type: "button", className: isSelected ? timeStyles.selected : "", onClick: () => handleTimeSelect(time), children: time }, time));
7418
7435
  }) }) }))] }), feedbackElements] })] }) }));
@@ -7720,7 +7737,7 @@ function CwDateTimePicker({ value, onChange, minDateTime, maxDateTime, disabledD
7720
7737
  const displayMaxDate = React.useMemo(() => normalizedMaxDateTime && timezoneOffset !== undefined
7721
7738
  ? getDateInOffset(normalizedMaxDateTime, timezoneOffset)
7722
7739
  : normalizedMaxDateTime, [normalizedMaxDateTime, timezoneOffset]);
7723
- return jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-datetimepicker cw-datetimepicker-separate ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsxRuntime.jsx(CwDatePicker, { value: selectedDate, onChange: handleDateChange, minDate: displayMinDate, maxDate: displayMaxDate, disabledDates: disabledDates, disabledMatcher: disabledMatcher, placeholder: datePlaceholder, disabled: disabled, required: required, showClear: showClear, numberOfMonths: numberOfMonths, popupPosition: popupPosition, locale: locale$1 }), jsxRuntime.jsx(CwTimePicker, { value: selectedTime, onChange: handleTimeChange, interval: timeInterval, minTime: timeRestrictions.minTime, maxTime: timeRestrictions.maxTime, placeholder: timePlaceholder, disabled: disabled, required: required, showClear: showClear, popupPosition: popupPosition }), showNowButton && (jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: handleNowClick, disabled: disabled, text: nowLabel }))] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }) });
7740
+ return jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-datetimepicker cw-datetimepicker-separate ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsxRuntime.jsx(CwDatePicker, { value: selectedDate, onChange: handleDateChange, minDate: displayMinDate, maxDate: displayMaxDate, disabledDates: disabledDates, disabledMatcher: disabledMatcher, placeholder: datePlaceholder, disabled: disabled, required: required, showClear: showClear, numberOfMonths: numberOfMonths, popupPosition: popupPosition, locale: locale$1 }), jsxRuntime.jsx(CwTimePicker, { value: selectedTime, onChange: handleTimeChange, interval: timeInterval, minTime: timeRestrictions.minTime, maxTime: timeRestrictions.maxTime, placeholder: timePlaceholder, disabled: disabled, required: required, showClear: showClear, popupPosition: popupPosition }), showNowButton && (jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: handleNowClick, disabled: disabled, text: nowLabel }))] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }) });
7724
7741
  }
7725
7742
 
7726
7743
  var compactStyles = {"compactPopup":"cw-datetime-compact-module__compactPopup__GiuNY","calendarWrapper":"cw-datetime-compact-module__calendarWrapper__P4Nlq","timeWrapper":"cw-datetime-compact-module__timeWrapper__uMe-A","compactTimeList":"cw-datetime-compact-module__compactTimeList__MzSQT"};
@@ -7976,7 +7993,7 @@ function CwDateTimePickerCompact({ value, onChange, minDateTime, maxDateTime, di
7976
7993
  ...(maxDateTime ? [{ after: maxDateTime }] : []),
7977
7994
  ...(disabledMatcher ? [disabledMatcher] : []),
7978
7995
  ], [disabledDates, minDateTime, maxDateTime, disabledMatcher]);
7979
- return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-datetimepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, maxLength: 16 }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear datetime" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar-time" })) }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${compactStyles.compactPopup}`, style: popupStyle, children: [jsxRuntime.jsxs("div", { className: compactStyles.calendarWrapper, children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "single", selected: selectedDate, onSelect: handleDaySelect, defaultMonth: selectedDate, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
7996
+ return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-datetimepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, maxLength: 16 }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear datetime" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar-time" })) }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: `${styles$7.pickerPopup} ${compactStyles.compactPopup}`, style: popupStyle, children: [jsxRuntime.jsxs("div", { className: compactStyles.calendarWrapper, children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "single", selected: selectedDate, onSelect: handleDaySelect, defaultMonth: selectedDate, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
7980
7997
  today: new Date(),
7981
7998
  }, modifiersClassNames: {
7982
7999
  today: "rdp-day-today",
@@ -8211,7 +8228,7 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
8211
8228
  const defaultMonthJsDate = defaultMonth
8212
8229
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
8213
8230
  : selectedJsDate;
8214
- return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-datepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "single", selected: selectedJsDate, defaultMonth: defaultMonthJsDate, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8231
+ return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-datepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: styles$7.pickerPopup, style: popupStyle, children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "single", selected: selectedJsDate, defaultMonth: defaultMonthJsDate, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8215
8232
  today: new Date(),
8216
8233
  }, modifiersClassNames: {
8217
8234
  today: "rdp-day-today",
@@ -8512,7 +8529,7 @@ function CwDateTimePickerTemporal({ value, onChange, minDateTime, maxDateTime, d
8512
8529
  minTime,
8513
8530
  maxTime,
8514
8531
  });
8515
- return jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-datetimepicker cw-datetimepicker-separate ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsxRuntime.jsx(CwDatePickerTemporal, { value: picker.date, onChange: picker.selectDate, minDate: picker.minDate, maxDate: picker.maxDate, disabledDates: disabledDates, disabledMatcher: disabledMatcher, placeholder: datePlaceholder, disabled: disabled, required: required, showClear: showClear, numberOfMonths: numberOfMonths, popupPosition: popupPosition, locale: locale$1 }), jsxRuntime.jsx(CwTimePicker, { value: picker.time, onChange: picker.selectTime, interval: timeInterval, minTime: picker.effectiveMinTime, maxTime: picker.effectiveMaxTime, placeholder: timePlaceholder, disabled: disabled, required: required, showClear: showClear, popupPosition: popupPosition }), showNowButton && (jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: picker.selectNow, disabled: disabled, text: nowLabel }))] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }) });
8532
+ return jsxRuntime.jsx("div", { ...dataAttributes, className: `cw-datetimepicker cw-datetimepicker-separate ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsxRuntime.jsx(CwDatePickerTemporal, { value: picker.date, onChange: picker.selectDate, minDate: picker.minDate, maxDate: picker.maxDate, disabledDates: disabledDates, disabledMatcher: disabledMatcher, placeholder: datePlaceholder, disabled: disabled, required: required, showClear: showClear, numberOfMonths: numberOfMonths, popupPosition: popupPosition, locale: locale$1 }), jsxRuntime.jsx(CwTimePicker, { value: picker.time, onChange: picker.selectTime, interval: timeInterval, minTime: picker.effectiveMinTime, maxTime: picker.effectiveMaxTime, placeholder: timePlaceholder, disabled: disabled, required: required, showClear: showClear, popupPosition: popupPosition }), showNowButton && (jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: picker.selectNow, disabled: disabled, text: nowLabel }))] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }) });
8516
8533
  }
8517
8534
 
8518
8535
  // dateRangePresetsTemporal.ts
@@ -8964,7 +8981,7 @@ function CwDateRangePickerTemporal({ value, onChange, minDate, maxDate, disabled
8964
8981
  const defaultMonthJsDate = defaultMonth
8965
8982
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
8966
8983
  : (value?.from ? plainDateToJsDate(value.from) : undefined);
8967
- return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$4.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxRuntime.jsxs("div", { className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputFromRef, type: "text", value: inputFromValue, placeholder: placeholderFrom, onChange: handleInputFromChange, onBlur: () => handleInputBlur('from'), onClick: handleInputFromClick, onKeyDown: (e) => handleInputKeyDown(e, 'from'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'from' }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.from && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), jsxRuntime.jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxRuntime.jsxs("div", { className: styles$4.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputToRef, type: "text", value: inputToValue, placeholder: placeholderTo, onChange: handleInputToChange, onBlur: () => handleInputBlur('to'), onClick: handleInputToClick, onKeyDown: (e) => handleInputKeyDown(e, 'to'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'to' }), jsxRuntime.jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.to && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxRuntime.jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsxRuntime.jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsxRuntime.jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonthJsDate, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8984
+ return (jsxRuntime.jsx("div", { ...dataAttributes, ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: styles$7.value, children: [jsxRuntime.jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxRuntime.jsxs("div", { className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputFromRef, type: "text", value: inputFromValue, placeholder: placeholderFrom, onChange: handleInputFromChange, onBlur: () => handleInputBlur('from'), onClick: handleInputFromClick, onKeyDown: (e) => handleInputKeyDown(e, 'from'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'from' }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value?.from && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), jsxRuntime.jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxRuntime.jsxs("div", { className: styles$7.pickerWrapper, children: [jsxRuntime.jsx("input", { ref: inputToRef, type: "text", value: inputToValue, placeholder: placeholderTo, onChange: handleInputToChange, onBlur: () => handleInputBlur('to'), onClick: handleInputToClick, onKeyDown: (e) => handleInputKeyDown(e, 'to'), disabled: disabled, "aria-describedby": describedBy, required: required, size: displayFormat.length, "data-focused": focusedInput === 'to' }), jsxRuntime.jsx("div", { className: styles$7.pickerIcons, children: showClear && value?.to && !disabled ? (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsxRuntime.jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxRuntime.jsxs("div", { ref: popupRef, className: `${styles$7.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxRuntime.jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsxRuntime.jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsxRuntime.jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsxRuntime.jsx(reactDayPicker.DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonthJsDate, locale: locale$1, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8968
8985
  today: new Date(),
8969
8986
  }, modifiersClassNames: {
8970
8987
  today: "rdp-day-today",
@@ -9111,7 +9128,7 @@ class OnClickContextMenu {
9111
9128
  }
9112
9129
  }
9113
9130
 
9114
- var styles$3 = {"scheduler-header":"scheduler-header-module__scheduler-header__Y7SNV","scheduler-header-divisions":"scheduler-header-module__scheduler-header-divisions__1JrNe","scheduler-timeline-now":"scheduler-header-module__scheduler-timeline-now__naREv","scheduler-timeline-label":"scheduler-header-module__scheduler-timeline-label__mLVAp","scheduler-header-title":"scheduler-header-module__scheduler-header-title__Jzy94","title-cell":"scheduler-header-module__title-cell__mz7Ki","title":"scheduler-header-module__title__TuJVn","scheduler-dates":"scheduler-header-module__scheduler-dates__O7ePQ","current-day":"scheduler-header-module__current-day__FpHiv","scheduler-hours":"scheduler-header-module__scheduler-hours__ZDCVj"};
9131
+ var styles$6 = {"scheduler-header":"scheduler-header-module__scheduler-header__Y7SNV","scheduler-header-divisions":"scheduler-header-module__scheduler-header-divisions__1JrNe","scheduler-timeline-now":"scheduler-header-module__scheduler-timeline-now__naREv","scheduler-timeline-label":"scheduler-header-module__scheduler-timeline-label__mLVAp","scheduler-header-title":"scheduler-header-module__scheduler-header-title__Jzy94","title-cell":"scheduler-header-module__title-cell__mz7Ki","title":"scheduler-header-module__title__TuJVn","scheduler-dates":"scheduler-header-module__scheduler-dates__O7ePQ","current-day":"scheduler-header-module__current-day__FpHiv","scheduler-hours":"scheduler-header-module__scheduler-hours__ZDCVj"};
9115
9132
 
9116
9133
  const getNow$1 = (isUtc) => {
9117
9134
  let now = new Date();
@@ -9140,9 +9157,9 @@ const TimeLine = ({ left, top = "0px", height, color, width = "2px", zIndexNumbe
9140
9157
  background: color,
9141
9158
  pointerEvents: "none",
9142
9159
  zIndex: zIndexNumber,
9143
- }, className: styles$3["scheduler-timeline-now"], children: isHeader && (jsxRuntime.jsx("span", { style: {
9160
+ }, className: styles$6["scheduler-timeline-now"], children: isHeader && (jsxRuntime.jsx("span", { style: {
9144
9161
  color: color,
9145
- }, className: styles$3["scheduler-timeline-label"], children: currentTime.toLocaleTimeString([], {
9162
+ }, className: styles$6["scheduler-timeline-label"], children: currentTime.toLocaleTimeString([], {
9146
9163
  hour: '2-digit',
9147
9164
  minute: '2-digit',
9148
9165
  hour12: false
@@ -9169,17 +9186,17 @@ const SchedulerHeaderDivision = ({ topDivisions, bottomDivisions, classification
9169
9186
  return (jsxRuntime.jsxs("div", { style: {
9170
9187
  width: topWidth,
9171
9188
  cursor: "pointer"
9172
- }, children: [jsxRuntime.jsx("div", { className: `${styles$3["scheduler-dates"]} ${isToday(startDate, endDate) ? styles$3["current-day"] : ""}`, children: jsxRuntime.jsx("span", { children: topDivisions }) }), jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "space-between", flex: 1 }, children: bottomDivisions.map((element) => (jsxRuntime.jsx("div", { className: styles$3["scheduler-hours"], children: jsxRuntime.jsx("span", { children: element }) }, classification + element + topDivisions))) })] }));
9189
+ }, children: [jsxRuntime.jsx("div", { className: `${styles$6["scheduler-dates"]} ${isToday(startDate, endDate) ? styles$6["current-day"] : ""}`, children: jsxRuntime.jsx("span", { children: topDivisions }) }), jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "space-between", flex: 1 }, children: bottomDivisions.map((element) => (jsxRuntime.jsx("div", { className: styles$6["scheduler-hours"], children: jsxRuntime.jsx("span", { children: element }) }, classification + element + topDivisions))) })] }));
9173
9190
  };
9174
9191
 
9175
9192
  const HeaderTitle = ({ title, dividerText, width }) => {
9176
- return (jsxRuntime.jsxs("div", { className: styles$3["scheduler-header-title"], style: { width: width }, children: [jsxRuntime.jsx("div", { className: styles$3["title-cell"], children: jsxRuntime.jsx("span", { className: styles$3.title, children: title }) }), jsxRuntime.jsx("div", { children: jsxRuntime.jsx("span", { children: dividerText }) })] }));
9193
+ return (jsxRuntime.jsxs("div", { className: styles$6["scheduler-header-title"], style: { width: width }, children: [jsxRuntime.jsx("div", { className: styles$6["title-cell"], children: jsxRuntime.jsx("span", { className: styles$6.title, children: title }) }), jsxRuntime.jsx("div", { children: jsxRuntime.jsx("span", { children: dividerText }) })] }));
9177
9194
  };
9178
9195
 
9179
9196
  const SchedulerHeader = ({ content, divisions, visibleDays, selectedDate, width, onEvent, timeLinePercentage, isUtc }) => {
9180
9197
  const topWidth = (100 / visibleDays);
9181
9198
  const { title, classification } = content;
9182
- return (jsxRuntime.jsxs("div", { className: styles$3["scheduler-header"], children: [jsxRuntime.jsx(HeaderTitle, { title: title, dividerText: classification, width: width }), jsxRuntime.jsxs("div", { className: styles$3["scheduler-header-divisions"], style: { flex: 1, display: "flex", position: "relative" }, onMouseDown: (e) => {
9199
+ return (jsxRuntime.jsxs("div", { className: styles$6["scheduler-header"], children: [jsxRuntime.jsx(HeaderTitle, { title: title, dividerText: classification, width: width }), jsxRuntime.jsxs("div", { className: styles$6["scheduler-header-divisions"], style: { flex: 1, display: "flex", position: "relative" }, onMouseDown: (e) => {
9183
9200
  e.preventDefault();
9184
9201
  const clickPercentage = getPercentageFromMouseEvent(e);
9185
9202
  const date = dateFromPercentage(selectedDate, visibleDays, clickPercentage);
@@ -9211,7 +9228,7 @@ function getStartEnd(day) {
9211
9228
  };
9212
9229
  }
9213
9230
 
9214
- var styles$2 = {"hide-scrollbar":"new-scheduler-module__hide-scrollbar__33GG9","scheduler-event":"new-scheduler-module__scheduler-event__gphwn","scheduler-event-container":"new-scheduler-module__scheduler-event-container__-h1xm","time-marker":"new-scheduler-module__time-marker__2BejU","color-bars":"new-scheduler-module__color-bars__MhMF7","scheduler-event-text":"new-scheduler-module__scheduler-event-text__zjvd7"};
9231
+ var styles$5 = {"hide-scrollbar":"new-scheduler-module__hide-scrollbar__33GG9","scheduler-event":"new-scheduler-module__scheduler-event__gphwn","scheduler-event-container":"new-scheduler-module__scheduler-event-container__-h1xm","time-marker":"new-scheduler-module__time-marker__2BejU","underlay":"new-scheduler-module__underlay__RVCnV","label-halo":"new-scheduler-module__label-halo__84c7e","corner-marker":"new-scheduler-module__corner-marker__w7o90","color-bars":"new-scheduler-module__color-bars__MhMF7","scheduler-event-text":"new-scheduler-module__scheduler-event-text__zjvd7"};
9215
9232
 
9216
9233
  const BackgroundEvent = ({ value, heightRem }) => {
9217
9234
  const backColor = getHSLColor(value.color, value.alpha ?? 0.5);
@@ -9238,13 +9255,13 @@ const BackgroundEvent = ({ value, heightRem }) => {
9238
9255
  padding: "0.25rem",
9239
9256
  color: textColor,
9240
9257
  alignItems: value.contentAlign ?? "center"
9241
- }, className: styles$2["scheduler-event-container"], children: [value.icons ? jsxRuntime.jsx("div", { style: {
9258
+ }, className: styles$5["scheduler-event-container"], children: [value.icons ? jsxRuntime.jsx("div", { style: {
9242
9259
  display: "flex",
9243
9260
  flexDirection: "row",
9244
9261
  alignItems: "center",
9245
9262
  whiteSpace: "nowrap",
9246
9263
  color: textColor,
9247
- }, children: value.icons }) : null, jsxRuntime.jsx("span", { className: styles$2["scheduler-event-text"], children: value.name })] }) }) }) }) })) : null;
9264
+ }, children: value.icons }) : null, jsxRuntime.jsx("span", { className: styles$5["scheduler-event-text"], children: value.name })] }) }) }) }) })) : null;
9248
9265
  };
9249
9266
 
9250
9267
  const eventIsVisible = (startDate, endDate, selectedDate, visibleDays) => {
@@ -9406,16 +9423,16 @@ const WeekEndLine = ({ left, top = "0px", height, widthPercentage }) => {
9406
9423
  } }));
9407
9424
  };
9408
9425
 
9409
- var styles$1 = {"scheduler-row-header":"scheduler-row-module__scheduler-row-header__S-iv4"};
9426
+ var styles$4 = {"scheduler-row-header":"scheduler-row-module__scheduler-row-header__S-iv4"};
9410
9427
 
9411
9428
  const DefaultRowHeader = ({ value, width, onEvent }) => {
9412
9429
  return (jsxRuntime.jsxs("div", { style: {
9413
9430
  width: width,
9414
9431
  flexShrink: 0,
9415
- // background: color,
9432
+ background: value.highlightColor,
9416
9433
  }, onClick: (_) => {
9417
9434
  onEvent(new OnClickRowHeader(value.rowId));
9418
- }, className: styles$1["scheduler-row-header"], children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: value.title }), value.title2 && jsxRuntime.jsxs("span", { children: ["-", value.title2] }), " ", jsxRuntime.jsx("strong", { children: value.subtitle })] }), value.subtitle && jsxRuntime.jsxs("div", { style: { opacity: 0.5 }, children: [value.title3 && jsxRuntime.jsxs("span", { className: styles$1["scheduler-crewmember-functions"], children: ["(", value.title3, ")"] }), value.subtitle2 && jsxRuntime.jsxs("span", { children: ["-", value.subtitle2] })] })] }));
9435
+ }, className: styles$4["scheduler-row-header"], children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: value.title }), value.title2 && jsxRuntime.jsxs("span", { children: ["-", value.title2] }), " ", jsxRuntime.jsx("strong", { children: value.subtitle })] }), value.subtitle && jsxRuntime.jsxs("div", { style: { opacity: 0.5 }, children: [value.title3 && jsxRuntime.jsxs("span", { className: styles$4["scheduler-crewmember-functions"], children: ["(", value.title3, ")"] }), value.subtitle2 && jsxRuntime.jsxs("span", { children: ["-", value.subtitle2] })] })] }));
9419
9436
  };
9420
9437
 
9421
9438
  const EventSideDrag = ({ left = false, heightRem, onStartEvent }) => {
@@ -9505,7 +9522,7 @@ const SchedulerEvent = ({ value, heightRem, onEvent, maxEventHeightRem }) => {
9505
9522
  height: `calc(${effectiveHeight}rem - 4px)`,
9506
9523
  opacity: eventTransparent ? 0.5 : 1,
9507
9524
  ...value.style,
9508
- }, className: styles$2["scheduler-event"], children: [jsxRuntime.jsxs("div", { style: {
9525
+ }, className: styles$5["scheduler-event"], "data-underlay": value.underlay ? true : undefined, children: [value.underlay && jsxRuntime.jsx("div", { className: styles$5["underlay"], children: value.underlay }), jsxRuntime.jsxs("div", { style: {
9509
9526
  display: "flex",
9510
9527
  flexDirection: "row",
9511
9528
  alignItems: "stretch",
@@ -9516,26 +9533,32 @@ const SchedulerEvent = ({ value, heightRem, onEvent, maxEventHeightRem }) => {
9516
9533
  height: "100%",
9517
9534
  }, children: [value.isResizable && (jsxRuntime.jsx(EventSideDrag, { left: true, heightRem: effectiveHeight * 0.7, onStartEvent: () => {
9518
9535
  onEvent(new OnLeftDragStart(value.id));
9519
- } })), jsxRuntime.jsxs("div", { className: styles$2["scheduler-event-container"], children: [jsxRuntime.jsx("div", { style: {
9536
+ } })), jsxRuntime.jsxs("div", { className: styles$5["scheduler-event-container"], children: [jsxRuntime.jsx("div", { style: {
9520
9537
  display: "flex",
9521
9538
  flexDirection: "row",
9522
9539
  alignItems: "center",
9523
9540
  whiteSpace: "nowrap",
9524
9541
  color: textColor,
9525
- }, children: value.icons }), jsxRuntime.jsx("span", { style: {
9542
+ }, children: value.icons }), jsxRuntime.jsx("span", { className: value.underlay ? styles$5["label-halo"] : undefined, style: {
9526
9543
  padding: "0.1rem",
9527
9544
  color: textColor,
9528
9545
  display: "flex",
9529
9546
  flex: 1,
9530
9547
  alignItems: "center",
9531
9548
  width: "100%",
9532
- }, children: value.rectangleColors && value.rectangleColors.length > 0 ? (jsxRuntime.jsx("div", { className: styles$2["color-bars"], children: value.rectangleColors.map((item, i) => (jsxRuntime.jsx("div", { style: { backgroundColor: item } }, value.id + "_" + i))) })) : (value.name) })] }), value.isResizable && (jsxRuntime.jsx(EventSideDrag, { heightRem: effectiveHeight * 0.7, onStartEvent: () => {
9549
+ ...(value.underlay && { "--label-halo-color": backColor }),
9550
+ }, children: value.rectangleColors && value.rectangleColors.length > 0 ? (jsxRuntime.jsx("div", { className: styles$5["color-bars"], children: value.rectangleColors.map((item, i) => (jsxRuntime.jsx("div", { style: { backgroundColor: item } }, value.id + "_" + i))) })) : (value.label ?? value.name) })] }), value.isResizable && (jsxRuntime.jsx(EventSideDrag, { heightRem: effectiveHeight * 0.7, onStartEvent: () => {
9533
9551
  onEvent(new OnRightDragStart(value.id));
9534
- } }))] }), value.primaryTimeMarkerColor && (jsxRuntime.jsx("div", { className: styles$2["time-marker"], style: {
9552
+ } }))] }), value.primaryTimeMarkerColor && (jsxRuntime.jsx("div", { className: styles$5["time-marker"], style: {
9535
9553
  backgroundColor: value.primaryTimeMarkerColor,
9536
- } })), value.secondaryTimeMarkerColor && (jsxRuntime.jsx("div", { className: styles$2["time-marker"], style: {
9554
+ } })), value.secondaryTimeMarkerColor && (jsxRuntime.jsx("div", { className: styles$5["time-marker"], style: {
9537
9555
  backgroundColor: value.secondaryTimeMarkerColor,
9538
- } }))] }) }) }, value.id) })] }));
9556
+ } }))] }) }) }, value.id) }), value.cornerMarker && (jsxRuntime.jsx("div", { className: styles$5["corner-marker"], style: {
9557
+ top: `${topOffsetPx}px`,
9558
+ left: `${value.left}%`,
9559
+ width: `${value.width}%`,
9560
+ height: `calc(${effectiveHeight}rem - 4px)`,
9561
+ }, children: jsxRuntime.jsx("span", { "data-interactive": value.cornerMarker.tooltip ? true : undefined, "data-pulse": value.cornerMarker.pulse ? true : undefined, children: value.cornerMarker.tooltip ? (jsxRuntime.jsx(CwTooltipNew, { content: value.cornerMarker.tooltip, position: "top", showDelay: 200, hide: isOnDrag, displayInline: true, children: jsxRuntime.jsx(CwBadge, { color: value.cornerMarker.color, size: "medium" }) })) : (jsxRuntime.jsx(CwBadge, { color: value.cornerMarker.color, size: "medium" })) }) }))] }));
9539
9562
  };
9540
9563
 
9541
9564
  const SchedulerRow = React.memo((props) => {
@@ -10064,13 +10087,13 @@ const Scheduler = (props) => {
10064
10087
  position: "sticky",
10065
10088
  top: 0,
10066
10089
  zIndex: 1,
10067
- }, children: jsxRuntime.jsx(SchedulerHeader, { ...header }) })), jsxRuntime.jsx(reactWindow.VariableSizeList, { height: schedulerContentHeight * 16, itemCount: rows.length, itemSize: getItemSize, itemData: itemData, width: "100%", style: { overflowX: "hidden" }, ref: instanceRef, className: styles$2["hide-scrollbar"], children: Row })] }) }));
10090
+ }, children: jsxRuntime.jsx(SchedulerHeader, { ...header }) })), jsxRuntime.jsx(reactWindow.VariableSizeList, { height: schedulerContentHeight * 16, itemCount: rows.length, itemSize: getItemSize, itemData: itemData, width: "100%", style: { overflowX: "hidden" }, ref: instanceRef, className: styles$5["hide-scrollbar"], children: Row })] }) }));
10068
10091
  };
10069
10092
 
10070
10093
  class UiEvent {
10071
10094
  }
10072
10095
 
10073
- var styles = {"super-scheduler-row-header":"super-scheduler-module__super-scheduler-row-header__TTs4e","indicators":"super-scheduler-module__indicators__f4lIT","scheduler-crewmember-functions":"super-scheduler-module__scheduler-crewmember-functions__BS2hs"};
10096
+ var styles$3 = {"super-scheduler-row-header":"super-scheduler-module__super-scheduler-row-header__TTs4e","indicators":"super-scheduler-module__indicators__f4lIT","scheduler-crewmember-functions":"super-scheduler-module__scheduler-crewmember-functions__BS2hs"};
10074
10097
 
10075
10098
  class OnPinRow {
10076
10099
  id;
@@ -10098,15 +10121,15 @@ const PinRowHeader = ({ value, width, onEvent }) => {
10098
10121
  flexShrink: 0,
10099
10122
  height: "100%",
10100
10123
  background: highlightColor
10101
- }, className: styles["super-scheduler-row-header"], children: [jsxRuntime.jsx("button", { className: "cw-button-icon cwi-pin", "data-pinned": value.isPinned, onClick: (_) => {
10124
+ }, className: styles$3["super-scheduler-row-header"], children: [jsxRuntime.jsx("button", { className: "cw-button-icon cwi-pin", "data-pinned": value.isPinned, onClick: (_) => {
10102
10125
  onEvent(value.isPinned ? new OnUnpinRow(value.rowId) : new OnPinRow(value.rowId));
10103
- } }), jsxRuntime.jsx("div", { className: styles["indicators"], children: value.indicators ?? undefined }), jsxRuntime.jsxs("div", { style: {
10126
+ } }), jsxRuntime.jsx("div", { className: styles$3["indicators"], children: value.indicators ?? undefined }), jsxRuntime.jsxs("div", { style: {
10104
10127
  display: "flex",
10105
10128
  flexDirection: "column",
10106
10129
  justifyContent: "center",
10107
10130
  alignItems: "flex-start",
10108
10131
  }, children: [jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx("strong", { children: value.title }), value.title2 && jsxRuntime.jsxs("span", { children: ["-", value.title2] }), " ", jsxRuntime.jsx("strong", { children: value.subtitle })] }), value.subtitle && jsxRuntime.jsxs("div", { style: { opacity: 0.5 }, children: [value.title3 &&
10109
- jsxRuntime.jsxs("span", { className: styles["scheduler-crewmember-functions"], children: ["(", value.title3, ")"] }), value.subtitle2 && jsxRuntime.jsxs("span", { children: ["-", value.subtitle2] })] })] }), isLoading ? jsxRuntime.jsx("span", { className: "cwi-icons cwi-spinner" }) : undefined] }) }, value.rowId) }, value.rowId);
10132
+ jsxRuntime.jsxs("span", { className: styles$3["scheduler-crewmember-functions"], children: ["(", value.title3, ")"] }), value.subtitle2 && jsxRuntime.jsxs("span", { children: ["-", value.subtitle2] })] })] }), isLoading ? jsxRuntime.jsx("span", { className: "cwi-icons cwi-spinner" }) : undefined] }) }, value.rowId) }, value.rowId);
10110
10133
  };
10111
10134
 
10112
10135
  const SuperScheduler = ({ id, state, header, rows, events, headerColumnComp, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, indicatorRows = [], contextMenuItems, onEvent, rowHeightRem = 1.75, rowHeaderWidth, maxEventHeightRem, EventComp = SchedulerEvent, }) => {
@@ -10118,6 +10141,2324 @@ const SuperScheduler = ({ id, state, header, rows, events, headerColumnComp, pin
10118
10141
  }, children: "Clear pinned" }) })] })), jsxRuntime.jsx(Scheduler, { id: `${id}-notPinned`, state: { ...state, isHeaderVisible: !isFirstVisible }, header: header, rows: notPinnedRows, events: events, backgroundEvents: backgroundEvents, indicatorRows: indicatorRows, contextMenuItems: contextMenuItems, orderCategories: unPinnedOrderCategory, onEvent: onEvent, EventComp: EventComp, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem, rowHeaderWidth: rowHeaderWidth, maxEventHeightRem: maxEventHeightRem })] }));
10119
10142
  };
10120
10143
 
10144
+ /** A toggle ref hides its item while `InitiallyHidden` XOR "flipped" is true. */
10145
+ function isToggleRefHidden(ref, flipped) {
10146
+ return ref.InitiallyHidden !== flipped.has(ref.Id);
10147
+ }
10148
+ /** An item, row or cell is visible only when every toggle it depends on is in its visible state. */
10149
+ function isRdlVisible(toggles, flipped) {
10150
+ if (!toggles || toggles.length === 0)
10151
+ return true;
10152
+ return toggles.every(ref => !isToggleRefHidden(ref, flipped));
10153
+ }
10154
+ /** The +/- state of a toggle textbox: the initial state inverted when its id was flipped. */
10155
+ function isToggleExpanded(textbox, flipped) {
10156
+ const initial = textbox.ToggleExpanded ?? false;
10157
+ return textbox.ToggleId ? initial !== flipped.has(textbox.ToggleId) : initial;
10158
+ }
10159
+ /**
10160
+ * The toggle ids an export or print sends so the file shows the drilldown state of the screen: the
10161
+ * ids flipped relative to the render's initial state (a toggle clicked twice is back to its initial
10162
+ * state and not sent), sorted for a stable request.
10163
+ */
10164
+ function flippedToggleIds(flipped) {
10165
+ return [...flipped].sort();
10166
+ }
10167
+ /** The toggle ids to ask the server for after a click on toggle `id`: the flipped ids with `id` flipped once more. */
10168
+ function toggledIds(flipped, id) {
10169
+ return flippedToggleIds(flipToggle(flipped, id));
10170
+ }
10171
+ /** Returns a new set with `id` flipped (added when absent, removed when present). */
10172
+ function flipToggle(flipped, id) {
10173
+ const next = new Set(flipped);
10174
+ if (next.has(id)) {
10175
+ next.delete(id);
10176
+ }
10177
+ else {
10178
+ next.add(id);
10179
+ }
10180
+ return next;
10181
+ }
10182
+
10183
+ /** Number of visible rows among `span` rows starting at `start`, at least 1. */
10184
+ function visibleRowSpan(rowVisible, start, span) {
10185
+ const end = Math.min(rowVisible.length, start + Math.max(1, span));
10186
+ let count = 0;
10187
+ for (let i = start; i < end; i++) {
10188
+ if (rowVisible[i])
10189
+ count++;
10190
+ }
10191
+ return Math.max(1, count);
10192
+ }
10193
+ function sum(values, from, to) {
10194
+ let total = 0;
10195
+ for (let i = Math.max(0, from); i < Math.min(values.length, to); i++)
10196
+ total += values[i];
10197
+ return total;
10198
+ }
10199
+ function visibleHeight(rows, rowVisible, start, span) {
10200
+ const end = Math.min(rows.length, start + Math.max(1, span));
10201
+ let height = 0;
10202
+ for (let i = start; i < end; i++) {
10203
+ if (rowVisible[i])
10204
+ height += rows[i].Height;
10205
+ }
10206
+ return height;
10207
+ }
10208
+ /**
10209
+ * Lays a table out for the current toggle state: hidden rows take no space, cells are placed at
10210
+ * their column with ColSpan/RowSpan and a header cell's RowSpan is recounted over the visible rows.
10211
+ * Cells that start in a hidden row are not drawn.
10212
+ */
10213
+ function layoutRdlTable(table, flipped) {
10214
+ const rows = table.Rows;
10215
+ const widths = table.ColumnWidths;
10216
+ const rowVisible = rows.map(row => isRdlVisible(row.Toggles, flipped));
10217
+ const rowTops = [];
10218
+ let top = 0;
10219
+ rows.forEach((row, index) => {
10220
+ rowTops.push(top);
10221
+ if (rowVisible[index])
10222
+ top += row.Height;
10223
+ });
10224
+ const cells = [];
10225
+ rows.forEach((row, rowIndex) => {
10226
+ if (!rowVisible[rowIndex])
10227
+ return;
10228
+ row.Cells.forEach((cell, cellIndex) => {
10229
+ const colSpan = Math.max(1, cell.ColSpan);
10230
+ cells.push({
10231
+ cell,
10232
+ rowIndex,
10233
+ cellIndex,
10234
+ left: sum(widths, 0, cell.Column),
10235
+ top: rowTops[rowIndex],
10236
+ width: sum(widths, cell.Column, cell.Column + colSpan),
10237
+ height: visibleHeight(rows, rowVisible, rowIndex, cell.RowSpan),
10238
+ rowSpan: visibleRowSpan(rowVisible, rowIndex, cell.RowSpan),
10239
+ hidden: !isRdlVisible(cell.Toggles, flipped)
10240
+ });
10241
+ });
10242
+ });
10243
+ return {
10244
+ width: sum(widths, 0, widths.length),
10245
+ height: top,
10246
+ rowTops,
10247
+ rowVisible,
10248
+ cells
10249
+ };
10250
+ }
10251
+
10252
+ /*
10253
+ * Find over the text of one page. Every run gets a key from its position in the render tree; the
10254
+ * renderer builds the same keys, so a match can be highlighted where the run is drawn.
10255
+ */
10256
+ /** Key prefixes of the three page sections. */
10257
+ const RDL_SECTION_KEYS = { header: "h", body: "b", footer: "f" };
10258
+ function rdlItemKey(parentKey, index) {
10259
+ return `${parentKey}.${index}`;
10260
+ }
10261
+ function rdlCellKey(tableKey, rowIndex, cellIndex) {
10262
+ return `${tableKey}.r${rowIndex}c${cellIndex}`;
10263
+ }
10264
+ function rdlRunKey(textboxKey, paragraphIndex, runIndex) {
10265
+ return `${textboxKey}.p${paragraphIndex}r${runIndex}`;
10266
+ }
10267
+ function collectTextbox(textbox, key, out) {
10268
+ textbox.Paragraphs.forEach((paragraph, p) => {
10269
+ paragraph.Runs.forEach((run, r) => {
10270
+ if (run.Text)
10271
+ out.push({ key: rdlRunKey(key, p, r), text: run.Text });
10272
+ });
10273
+ });
10274
+ }
10275
+ function collectItem(item, key, flipped, out) {
10276
+ if (!isRdlVisible(item.Toggles, flipped))
10277
+ return;
10278
+ switch (item.Kind) {
10279
+ case "textbox":
10280
+ collectTextbox(item, key, out);
10281
+ break;
10282
+ case "rectangle":
10283
+ collectItems(item.Items, key, flipped, out);
10284
+ break;
10285
+ case "table": {
10286
+ const layout = layoutRdlTable(item, flipped);
10287
+ for (const box of layout.cells) {
10288
+ if (box.hidden || !box.cell.Content)
10289
+ continue;
10290
+ collectItem(box.cell.Content, rdlCellKey(key, box.rowIndex, box.cellIndex), flipped, out);
10291
+ }
10292
+ break;
10293
+ }
10294
+ }
10295
+ }
10296
+ function collectItems(items, parentKey, flipped, out) {
10297
+ items.forEach((item, index) => collectItem(item, rdlItemKey(parentKey, index), flipped, out));
10298
+ }
10299
+ /** Every visible text run of a page in document order: header, body, footer. */
10300
+ function collectPageText(page, flipped) {
10301
+ const out = [];
10302
+ if (page.Header)
10303
+ collectItems(page.Header.Items, RDL_SECTION_KEYS.header, flipped, out);
10304
+ collectItems(page.Items, RDL_SECTION_KEYS.body, flipped, out);
10305
+ if (page.Footer)
10306
+ collectItems(page.Footer.Items, RDL_SECTION_KEYS.footer, flipped, out);
10307
+ return out;
10308
+ }
10309
+ /**
10310
+ * The text lower-cased one character at a time, with each code unit of the result pointing back to the
10311
+ * original character it came from: lower-casing can change the length ("İ" becomes two code units outside
10312
+ * Turkish), and the highlights slice the original text.
10313
+ */
10314
+ function lowerWithOffsets(text, locale) {
10315
+ let lower = "";
10316
+ const starts = [];
10317
+ const ends = [];
10318
+ let index = 0;
10319
+ for (const character of text) {
10320
+ const lowered = character.toLocaleLowerCase(locale);
10321
+ for (let unit = 0; unit < lowered.length; unit++) {
10322
+ starts.push(index);
10323
+ ends.push(index + character.length);
10324
+ }
10325
+ lower += lowered;
10326
+ index += character.length;
10327
+ }
10328
+ return { lower, starts, ends };
10329
+ }
10330
+ /**
10331
+ * Case-insensitive, non-overlapping matches of `query` in the runs, in run order, with the casing rules of
10332
+ * `locale` (default: the browser's, so "istanbul" finds "İSTANBUL" in Turkish). A match does not span two runs.
10333
+ */
10334
+ function findInRuns(runs, query, locale) {
10335
+ const needle = query.trim().toLocaleLowerCase(locale);
10336
+ if (needle === "")
10337
+ return [];
10338
+ const matches = [];
10339
+ for (const run of runs) {
10340
+ const { lower, starts, ends } = lowerWithOffsets(run.text, locale);
10341
+ let from = 0;
10342
+ for (;;) {
10343
+ const at = lower.indexOf(needle, from);
10344
+ if (at < 0)
10345
+ break;
10346
+ const start = starts[at];
10347
+ matches.push({ key: run.key, start, length: ends[at + needle.length - 1] - start });
10348
+ from = at + needle.length;
10349
+ }
10350
+ }
10351
+ return matches;
10352
+ }
10353
+ /** Find over the visible text of one page. */
10354
+ function findInPage(page, query, flipped) {
10355
+ return findInRuns(collectPageText(page, flipped), query);
10356
+ }
10357
+ /**
10358
+ * The active match index: -1 without matches; the stored index clamped into the matches when it belongs to the
10359
+ * current page and query (a stored -1 from an empty search becomes 0 once a drilldown reveals matches); else 0.
10360
+ */
10361
+ function activeMatchIndex(storedIndex, storedForCurrentSearch, count) {
10362
+ if (count <= 0)
10363
+ return -1;
10364
+ return storedForCurrentSearch ? Math.min(Math.max(0, storedIndex), count - 1) : 0;
10365
+ }
10366
+ /** The next match index after `current`, cycling; -1 when there are no matches. */
10367
+ function nextMatchIndex(current, count) {
10368
+ if (count <= 0)
10369
+ return -1;
10370
+ return current < 0 ? 0 : (current + 1) % count;
10371
+ }
10372
+
10373
+ /** CSS pixels per point: 96 px per inch, 72 pt per inch. */
10374
+ const PX_PER_PT = 96 / 72;
10375
+ /** Converts points to CSS pixels at a zoom factor (1 = 100%). */
10376
+ function ptToPx(pt, zoom = 1) {
10377
+ return pt * PX_PER_PT * zoom;
10378
+ }
10379
+ const POINTS_PER_UNIT = {
10380
+ pt: 1,
10381
+ px: 72 / 96,
10382
+ in: 72,
10383
+ cm: 72 / 2.54,
10384
+ mm: 72 / 25.4,
10385
+ pc: 12
10386
+ };
10387
+ // Linear: one digit run either side of the point, so a long non-matching value cannot backtrack quadratically.
10388
+ const SIZE_PATTERN = /^\s*(-?(?:\d+(?:\.\d*)?|\.\d+))\s*(pt|px|in|cm|mm|pc)?\s*$/i;
10389
+ /** No real RDL size comes near this; longer report-supplied strings are rejected before matching. */
10390
+ const MAX_SIZE_LENGTH = 32;
10391
+ /** Parses an RDL size ("10pt", "2.5mm", "1in", ...) into points; a bare number is points. Null when unparsable. */
10392
+ function parseRdlSize(value) {
10393
+ if (!value || value.length > MAX_SIZE_LENGTH)
10394
+ return null;
10395
+ const match = SIZE_PATTERN.exec(value);
10396
+ if (!match)
10397
+ return null;
10398
+ const unit = (match[2] ?? "pt").toLowerCase();
10399
+ return parseFloat(match[1]) * POINTS_PER_UNIT[unit];
10400
+ }
10401
+ /** An RDL size as CSS pixels at a zoom factor, or undefined when the size is missing or unparsable. */
10402
+ function rdlSizeToPx(value, zoom) {
10403
+ const pt = parseRdlSize(value);
10404
+ return pt === null ? undefined : ptToPx(pt, zoom);
10405
+ }
10406
+
10407
+ /** The zoom steps of the toolbar, 50% to 200%. */
10408
+ const REPORT_ZOOM_STEPS = [0.5, 0.75, 1, 1.25, 1.5, 2];
10409
+ const MIN_ZOOM = 0.1;
10410
+ const MAX_ZOOM = 4;
10411
+ /** Default margins of a standalone CwReportPage: a quarter inch, so content never touches the paper edge. */
10412
+ const DEFAULT_PAGE_MARGIN_PT = 18;
10413
+ /**
10414
+ * Margins of the sheet in the viewer: none. Like the old ReportViewer, the screen shows the content
10415
+ * (header, body, footer) without the RDL page margins; PDF and print come from the server with them.
10416
+ */
10417
+ const SCREEN_PAGE_MARGINS = { top: 0, right: 0, bottom: 0, left: 0 };
10418
+ /** Width of the page content in points: the page's own `Width` (body plus items reaching past it) when the server sends it, else the body width. */
10419
+ function pageContentWidthPt(page, bodyWidth) {
10420
+ return page.Width && Number.isFinite(page.Width) && page.Width > 0 ? Math.max(page.Width, bodyWidth) : bodyWidth;
10421
+ }
10422
+ /** Size of the drawn sheet in points: margins + header + body + footer, as wide as the content so every item lies on it. */
10423
+ function pageSheetSizePt(page, bodyWidth, margins) {
10424
+ return {
10425
+ width: margins.left + pageContentWidthPt(page, bodyWidth) + margins.right,
10426
+ height: margins.top + (page.Header?.Height ?? 0) + page.Height + (page.Footer?.Height ?? 0) + margins.bottom
10427
+ };
10428
+ }
10429
+ /**
10430
+ * The zoom factor to draw with. "pageWidth" fits the sheet width into the available width,
10431
+ * "wholePage" fits the whole sheet; available sizes are CSS pixels. Clamped to 10%..400%.
10432
+ */
10433
+ function resolveZoomFactor(zoom, sheetPt, available) {
10434
+ if (typeof zoom === "number")
10435
+ return clamp(zoom);
10436
+ const widthPx = ptToPx(sheetPt.width);
10437
+ const heightPx = ptToPx(sheetPt.height);
10438
+ if (widthPx <= 0 || available.width <= 0)
10439
+ return 1;
10440
+ const byWidth = available.width / widthPx;
10441
+ if (zoom === "pageWidth" || heightPx <= 0 || available.height <= 0)
10442
+ return clamp(byWidth);
10443
+ return clamp(Math.min(byWidth, available.height / heightPx));
10444
+ }
10445
+ function clamp(value) {
10446
+ return Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, value));
10447
+ }
10448
+
10449
+ /*
10450
+ * Maps the RDL style vocabulary to CSS. Everything here is report CONTENT: colors, fonts and borders
10451
+ * come from the report definition and are applied as given, not from the design system.
10452
+ */
10453
+ const RDL_DEFAULT_FONT_FAMILY = "Arial";
10454
+ const RDL_DEFAULT_FONT_SIZE = "10pt";
10455
+ const RDL_DEFAULT_COLOR = "black";
10456
+ const FONT_WEIGHTS = {
10457
+ thin: 100,
10458
+ extralight: 200,
10459
+ light: 300,
10460
+ normal: 400,
10461
+ medium: 500,
10462
+ semibold: 600,
10463
+ bold: 700,
10464
+ extrabold: 800,
10465
+ heavy: 900
10466
+ };
10467
+ const BORDER_STYLES = {
10468
+ solid: "solid",
10469
+ dotted: "dotted",
10470
+ dashed: "dashed",
10471
+ double: "double",
10472
+ none: "none"
10473
+ };
10474
+ /** An RDL color as CSS: "Transparent" = transparent, names and #RRGGBB pass through, empty = undefined. */
10475
+ function rdlColor(value) {
10476
+ if (!value)
10477
+ return undefined;
10478
+ const trimmed = value.trim();
10479
+ if (trimmed === "")
10480
+ return undefined;
10481
+ return trimmed.toLowerCase() === "transparent" ? "transparent" : trimmed;
10482
+ }
10483
+ /** Thin..Heavy to 100..900; unknown values fall back to normal. */
10484
+ function rdlFontWeight(value) {
10485
+ if (!value)
10486
+ return 400;
10487
+ return FONT_WEIGHTS[value.toLowerCase()] ?? (/^\d{3}$/.test(value) ? parseInt(value, 10) : 400);
10488
+ }
10489
+ /** A border side as a CSS shorthand; Style None or missing = none. Width defaults to 1pt, color to black. */
10490
+ function rdlBorder(border, zoom) {
10491
+ if (!border)
10492
+ return undefined;
10493
+ const style = BORDER_STYLES[(border.Style ?? "none").toLowerCase()] ?? "solid";
10494
+ if (style === "none")
10495
+ return "none";
10496
+ const widthPt = parseRdlSize(border.Width) ?? 1;
10497
+ const widthPx = Math.max(1, ptToPx(widthPt, zoom));
10498
+ return `${widthPx}px ${style} ${rdlColor(border.Color) ?? RDL_DEFAULT_COLOR}`;
10499
+ }
10500
+ /**
10501
+ * The four borders of an item box as the custom properties its border overlay draws
10502
+ * (`--rdl-border-top` ... in cw-report-page.module.css). Like the report server, borders sit on
10503
+ * the box edge and take no space from the content, so text laid out by the server to just fit
10504
+ * still fits. Always all four sides, "none" when unset: custom properties inherit, and a nested
10505
+ * item must not draw its container's borders.
10506
+ */
10507
+ function rdlBorderVars(style, zoom) {
10508
+ return {
10509
+ "--rdl-border-top": rdlBorder(style?.BorderTop, zoom) ?? "none",
10510
+ "--rdl-border-right": rdlBorder(style?.BorderRight, zoom) ?? "none",
10511
+ "--rdl-border-bottom": rdlBorder(style?.BorderBottom, zoom) ?? "none",
10512
+ "--rdl-border-left": rdlBorder(style?.BorderLeft, zoom) ?? "none"
10513
+ };
10514
+ }
10515
+ /** Background, borders (as overlay custom properties, see `rdlBorderVars`) and padding of an item box. */
10516
+ function rdlBoxStyle(style, zoom) {
10517
+ if (!style)
10518
+ return rdlBorderVars(null, zoom);
10519
+ return {
10520
+ ...rdlBorderVars(style, zoom),
10521
+ backgroundColor: rdlColor(style.BackgroundColor),
10522
+ paddingTop: rdlSizeToPx(style.PaddingTop, zoom),
10523
+ paddingRight: rdlSizeToPx(style.PaddingRight, zoom),
10524
+ paddingBottom: rdlSizeToPx(style.PaddingBottom, zoom),
10525
+ paddingLeft: rdlSizeToPx(style.PaddingLeft, zoom)
10526
+ };
10527
+ }
10528
+ function pick(key, styles) {
10529
+ for (const style of styles) {
10530
+ const value = style?.[key];
10531
+ if (value)
10532
+ return value;
10533
+ }
10534
+ return null;
10535
+ }
10536
+ function resolveRdlTextStyle(run, paragraph, textbox) {
10537
+ const chain = [run, paragraph, textbox];
10538
+ return {
10539
+ color: pick("Color", chain) ?? RDL_DEFAULT_COLOR,
10540
+ fontFamily: pick("FontFamily", chain) ?? RDL_DEFAULT_FONT_FAMILY,
10541
+ fontSize: pick("FontSize", chain) ?? RDL_DEFAULT_FONT_SIZE,
10542
+ fontStyle: pick("FontStyle", chain),
10543
+ fontWeight: pick("FontWeight", chain),
10544
+ textDecoration: pick("TextDecoration", chain),
10545
+ lineHeight: pick("LineHeight", chain)
10546
+ };
10547
+ }
10548
+ /**
10549
+ * The text style of a paragraph element. Its font sets the strut every line box gets, so it takes
10550
+ * the font of its runs (they usually share one; when they differ, the first run's): a paragraph
10551
+ * left at the textbox default (Arial 10pt) around Segoe UI 8pt runs would make every line taller
10552
+ * than the server measured and the text would overflow its box. An RDL LineHeight on the paragraph
10553
+ * or textbox still wins; otherwise the run's LineHeight, if any, applies.
10554
+ */
10555
+ function resolveParagraphTextStyle(runStyles, paragraph, textbox) {
10556
+ const own = resolveRdlTextStyle(null, paragraph, textbox);
10557
+ if (runStyles.length === 0)
10558
+ return own;
10559
+ const run = resolveRdlTextStyle(runStyles[0], paragraph, textbox);
10560
+ return {
10561
+ ...own,
10562
+ fontFamily: run.fontFamily,
10563
+ fontSize: run.fontSize,
10564
+ fontStyle: run.fontStyle,
10565
+ fontWeight: run.fontWeight,
10566
+ lineHeight: own.lineHeight ?? run.lineHeight
10567
+ };
10568
+ }
10569
+ function textDecoration(value) {
10570
+ switch ((value ?? "").toLowerCase()) {
10571
+ case "underline": return "underline";
10572
+ case "linethrough": return "line-through";
10573
+ case "overline": return "overline";
10574
+ default: return undefined;
10575
+ }
10576
+ }
10577
+ /** An RDL LineHeight in pixels, else "normal"; an unparsable value also falls back to normal. */
10578
+ function rdlLineHeight(value, zoom) {
10579
+ const px = rdlSizeToPx(value, zoom);
10580
+ return px === undefined ? "normal" : `${px}px`;
10581
+ }
10582
+ /**
10583
+ * CSS of a resolved text style at a zoom factor. Without an RDL LineHeight the line height is the
10584
+ * font's natural one ("normal"), the spacing the server measures text with; set inline so no app
10585
+ * or base rule on p / span (125%, 1.15) can shrink the line box and clip large glyphs.
10586
+ */
10587
+ function rdlTextCss(text, zoom) {
10588
+ return {
10589
+ // Transparent text is invisible, as in Reporting Services (reports use it to hide values).
10590
+ color: rdlColor(text.color),
10591
+ fontFamily: text.fontFamily,
10592
+ fontSize: rdlSizeToPx(text.fontSize, zoom) ?? ptToPx(10, zoom),
10593
+ fontStyle: (text.fontStyle ?? "").toLowerCase() === "italic" ? "italic" : undefined,
10594
+ fontWeight: text.fontWeight ? rdlFontWeight(text.fontWeight) : undefined,
10595
+ textDecoration: textDecoration(text.textDecoration),
10596
+ lineHeight: rdlLineHeight(text.lineHeight, zoom)
10597
+ };
10598
+ }
10599
+ /** TextAlign Left/Center/Right/General (General = left). */
10600
+ function rdlTextAlign(value) {
10601
+ switch ((value ?? "").toLowerCase()) {
10602
+ case "center": return "center";
10603
+ case "right": return "right";
10604
+ case "justify": return "justify";
10605
+ default: return "left";
10606
+ }
10607
+ }
10608
+ /**
10609
+ * VerticalAlign Top/Middle/Bottom as the justify-content of a column flex box. "safe": when the
10610
+ * text is taller than its box it falls back to the top, so the first line is never cut off.
10611
+ */
10612
+ function rdlVerticalAlign(value) {
10613
+ switch ((value ?? "").toLowerCase()) {
10614
+ case "middle": return "safe center";
10615
+ case "bottom": return "safe flex-end";
10616
+ default: return "flex-start";
10617
+ }
10618
+ }
10619
+ /** The stroke of a line item: BorderTop, else BorderLeft, default 1pt solid black. */
10620
+ function rdlLineStroke(style, zoom) {
10621
+ const border = style?.BorderTop ?? style?.BorderLeft ?? null;
10622
+ const width = Math.max(1, ptToPx(parseRdlSize(border?.Width) ?? 1, zoom));
10623
+ const kind = (border?.Style ?? "solid").toLowerCase();
10624
+ const color = rdlColor(border?.Color) ?? RDL_DEFAULT_COLOR;
10625
+ if (kind === "none")
10626
+ return { color: "transparent", width };
10627
+ if (kind === "dotted")
10628
+ return { color, width, dash: `${width} ${width * 2}` };
10629
+ if (kind === "dashed")
10630
+ return { color, width, dash: `${width * 4} ${width * 2}` };
10631
+ return { color, width };
10632
+ }
10633
+
10634
+ /*
10635
+ * Pure chart math for the report charts. The hex values below are the report's chart palettes:
10636
+ * content colors (like the colors a report carries), not UI chrome, so no design tokens.
10637
+ */
10638
+ /**
10639
+ * The Microsoft chart palettes by name, with the exact colors of the old ReportViewer engine.
10640
+ * The engine's semi-transparent palettes are #AARRGGBB; here they are CSS #RRGGBBAA.
10641
+ */
10642
+ const PALETTES = {
10643
+ Default: [
10644
+ "#008000", "#0000FF", "#800080", "#00FF00", "#FF00FF", "#008080", "#FFFF00", "#808080",
10645
+ "#00FFFF", "#000080", "#800000", "#FF0000", "#808000", "#C0C0C0", "#FF6347", "#FFE4B5"
10646
+ ],
10647
+ Grayscale: [
10648
+ "#C8C8C8", "#BDBDBD", "#B2B2B2", "#A7A7A7", "#9C9C9C", "#919191", "#868686", "#7B7B7B",
10649
+ "#707070", "#656565", "#5A5A5A", "#4F4F4F", "#444444", "#393939", "#2E2E2E", "#232323"
10650
+ ],
10651
+ Excel: [
10652
+ "#9999FF", "#993366", "#FFFFCC", "#CCFFFF", "#660066", "#FF8080", "#0066CC", "#CCCCFF",
10653
+ "#000080", "#FF00FF", "#FFFF00", "#00FFFF", "#800080", "#800000", "#008080", "#0000FF"
10654
+ ],
10655
+ Light: ["#E6E6FA", "#FFF0F5", "#FFDAB9", "#FFFACD", "#FFE4E1", "#F0FFF0", "#F0F8FF", "#F5F5F5", "#FAEBD7", "#E0FFFF"],
10656
+ Pastel: [
10657
+ "#87CEEB", "#32CD32", "#BA55D3", "#F08080", "#4682B4", "#9ACD32", "#40E0D0", "#FF69B4",
10658
+ "#F0E68C", "#D2B48C", "#8FBC8B", "#6495ED", "#DDA0DD", "#5F9EA0", "#FFDAB9", "#FFA07A"
10659
+ ],
10660
+ EarthTones: [
10661
+ "#FF8000", "#B8860B", "#C04000", "#6B8E23", "#CD853F", "#C0C000", "#228B22", "#D2691E",
10662
+ "#808000", "#20B2AA", "#F4A460", "#00C000", "#8FBC8B", "#B22222", "#8B4513", "#C00000"
10663
+ ],
10664
+ SemiTransparent: [
10665
+ "#FF000096", "#00FF0096", "#0000FF96", "#FFFF0096", "#00FFFF96", "#FF00FF96", "#AA781496", "#FF000050",
10666
+ "#00FF0050", "#0000FF50", "#FFFF0050", "#00FFFF50", "#FF00FF50", "#AA781450", "#64783296", "#285A9696"
10667
+ ],
10668
+ Berry: ["#8A2BE2", "#BA55D3", "#4169E1", "#C71585", "#0000FF", "#8A2BE2", "#DA70D6", "#7B68EE", "#C000C0", "#0000CD", "#800080"],
10669
+ Chocolate: ["#A0522D", "#D2691E", "#8B0000", "#CD853F", "#A52A2A", "#F4A460", "#8B4513", "#C04000", "#B22222", "#B65C3A"],
10670
+ Fire: ["#FFD700", "#FF0000", "#FF1493", "#DC143C", "#FF8C00", "#FF00FF", "#FFFF00", "#FF4500", "#C71585", "#DDE221"],
10671
+ SeaGreen: ["#2E8B57", "#66CDAA", "#4682B4", "#008B8B", "#5F9EA0", "#3CB371", "#48D1CC", "#B0C4DE", "#8FBC8B", "#87CEEB"],
10672
+ BrightPastel: [
10673
+ "#418CF0", "#FCB441", "#E0400A", "#056492", "#BFBFBF", "#1A3B69", "#FFE382", "#129CDD",
10674
+ "#CA6B4B", "#005CDB", "#F3D288", "#506381", "#F1B9A8", "#E0830A", "#7893BE"
10675
+ ],
10676
+ Pacific: [
10677
+ "#01B8AA", "#374649", "#FD625E", "#F2C80F", "#5F6B6D", "#8AD4EB", "#FE9666", "#A66999", "#3599B8", "#DFBFBF",
10678
+ "#4AC5BB", "#5F6B6D", "#FB8281", "#F4D25A", "#7F898A", "#A4DDEE", "#FDAB89", "#B687AC", "#28738A", "#A78F8F"
10679
+ ],
10680
+ PacificLight: ["#4AC5BB", "#5F6B6D", "#FB8281", "#F4D25A", "#7F898A", "#A4DDEE", "#FDAB89", "#B687AC", "#28738A", "#A78F8F"],
10681
+ PacificSemiTransparent: [
10682
+ "#01B8AA99", "#37464999", "#FD625E99", "#F2C80F99", "#5F6B6D99", "#8AD4EB99", "#FE966699", "#A6699999", "#3599B899", "#DFBFBF99",
10683
+ "#4AC5BB99", "#5F6B6D99", "#FB828199", "#F4D25A99", "#7F898A99", "#A4DDEE99", "#FDAB8999", "#B687AC99", "#28738A99", "#A78F8F99"
10684
+ ]
10685
+ };
10686
+ const PALETTES_BY_NAME = new Map(Object.entries(PALETTES).map(([name, colors]) => [name.toLowerCase(), colors]));
10687
+ /** The palette for an RDL palette name (any case); a missing or unknown name is "Default", the RDL default. */
10688
+ function chartPalette(name) {
10689
+ return PALETTES_BY_NAME.get((name ?? "").trim().toLowerCase()) ?? PALETTES.Default;
10690
+ }
10691
+ /** The color of series `index`: its own color, else the palette entry. */
10692
+ function seriesColor(series, index, palette) {
10693
+ return series.Color && series.Color.toLowerCase() !== "automatic" ? series.Color : palette[index % palette.length];
10694
+ }
10695
+ /** Steps of a value axis: about five, rounded to 1, 2, 5 or 10 times a power of ten. */
10696
+ const VALUE_AXIS_STEPS = 5;
10697
+ /** Drops the binary noise of step multiples (0.6000000000000001 -> 0.6). */
10698
+ function tidy$1(value) {
10699
+ return Number(value.toPrecision(12));
10700
+ }
10701
+ /**
10702
+ * bound / step, snapped to the nearest integer only when it is within a few ulps of it: 0.07 / 0.01 is
10703
+ * 7.000000000000001 in binary floating point and would otherwise add an axis step. Genuine non-multiples
10704
+ * (0.37 / 0.05) keep their fraction so the bounds still round outwards.
10705
+ */
10706
+ function axisQuotient(bound, step) {
10707
+ const quotient = bound / step;
10708
+ const nearest = Math.round(quotient);
10709
+ const reconstructed = nearest * step;
10710
+ const tolerance = Number.EPSILON * 4 * Math.max(1, Math.abs(bound), Math.abs(reconstructed));
10711
+ return Math.abs(reconstructed - bound) <= tolerance ? nearest : quotient;
10712
+ }
10713
+ /** The nice step for a value range (> 0): range / 5 rounded to 1, 2, 5 or 10 times its magnitude. */
10714
+ function niceAxisStep(range) {
10715
+ const raw = range / VALUE_AXIS_STEPS;
10716
+ const magnitude = Math.pow(10, Math.floor(Math.log10(raw)));
10717
+ const residual = raw / magnitude;
10718
+ const nice = residual < 1.5 ? 1 : residual < 3.5 ? 2 : residual < 7.5 ? 5 : 10;
10719
+ return tidy$1(nice * magnitude);
10720
+ }
10721
+ /**
10722
+ * A value axis over the given values, the same rule as the server's PDF: the range always includes
10723
+ * 0, nulls are ignored, the step is `niceAxisStep(range)` and the bounds are rounded out to whole
10724
+ * steps (data max 113 gives 0..120 in steps of 20). All-null or all-zero data gives 0..1.
10725
+ */
10726
+ function computeValueScale(values) {
10727
+ let min = 0;
10728
+ let max = 0;
10729
+ for (const value of values) {
10730
+ if (value === null || value === undefined || !Number.isFinite(value))
10731
+ continue;
10732
+ if (value < min)
10733
+ min = value;
10734
+ if (value > max)
10735
+ max = value;
10736
+ }
10737
+ if (min === max)
10738
+ max = min + 1;
10739
+ const step = niceAxisStep(max - min);
10740
+ const first = Math.floor(axisQuotient(min, step));
10741
+ const last = Math.ceil(axisQuotient(max, step));
10742
+ const ticks = [];
10743
+ for (let index = first; index <= last; index++)
10744
+ ticks.push(tidy$1(index * step));
10745
+ return { min: tidy$1(first * step), max: tidy$1(last * step), ticks };
10746
+ }
10747
+ /**
10748
+ * The server's category axis labels (`RdlRenderChart.CategoryAxisLabels`) along an axis that starts
10749
+ * at `start` with `band` pixels per category: position 0 is the first category's point (the middle
10750
+ * of its band), fractions fall between two categories. Labels outside the categories are dropped.
10751
+ */
10752
+ function categoryAxisLabels(labels, categoryCount, start, band) {
10753
+ return labels
10754
+ .filter(label => Number.isFinite(label.Position) && label.Position >= -0.5 && label.Position <= categoryCount - 0.5)
10755
+ .map(label => ({ at: start + band * (label.Position + 0.5), text: label.Text }));
10756
+ }
10757
+ /**
10758
+ * Centers a label of `width` on `center`, moved inside [min, max] when it would cross an end: a
10759
+ * category label never runs past the value axis (and its origin label) or the plot's right edge.
10760
+ */
10761
+ function placeAxisLabel(center, width, min, max) {
10762
+ if (center - width / 2 < min)
10763
+ return { x: min, anchor: "start" };
10764
+ if (center + width / 2 > max)
10765
+ return { x: max, anchor: "end" };
10766
+ return { x: center, anchor: "middle" };
10767
+ }
10768
+ /** Maps a value of the scale to a pixel coordinate between `from` (scale min) and `to` (scale max). */
10769
+ function scaleValue(value, scale, from, to) {
10770
+ const span = scale.max - scale.min;
10771
+ if (span === 0)
10772
+ return from;
10773
+ return from + ((value - scale.min) / span) * (to - from);
10774
+ }
10775
+ /** Splits a series into runs of consecutive non-null points: a null value leaves a gap in the line. */
10776
+ function lineSegments(values, x, y) {
10777
+ const segments = [];
10778
+ let current = [];
10779
+ values.forEach((value, index) => {
10780
+ if (value === null || value === undefined || !Number.isFinite(value)) {
10781
+ if (current.length > 0)
10782
+ segments.push(current);
10783
+ current = [];
10784
+ return;
10785
+ }
10786
+ current.push({ index, value, x: x(index), y: y(value) });
10787
+ });
10788
+ if (current.length > 0)
10789
+ segments.push(current);
10790
+ return segments;
10791
+ }
10792
+ /** SVG path of one segment: straight, stepped (horizontal then vertical) or smooth (Catmull-Rom as cubic Beziers). */
10793
+ function segmentPath(points, subtype) {
10794
+ if (points.length === 0)
10795
+ return "";
10796
+ const kind = (subtype ?? "").toLowerCase();
10797
+ let path = `M${points[0].x},${points[0].y}`;
10798
+ for (let i = 1; i < points.length; i++) {
10799
+ const prev = points[i - 1];
10800
+ const point = points[i];
10801
+ if (kind === "stepped") {
10802
+ path += ` H${point.x} V${point.y}`;
10803
+ }
10804
+ else if (kind === "smooth") {
10805
+ const before = points[i - 2] ?? prev;
10806
+ const after = points[i + 1] ?? point;
10807
+ const c1x = prev.x + (point.x - before.x) / 6;
10808
+ const c1y = prev.y + (point.y - before.y) / 6;
10809
+ const c2x = point.x - (after.x - prev.x) / 6;
10810
+ const c2y = point.y - (after.y - prev.y) / 6;
10811
+ path += ` C${c1x},${c1y} ${c2x},${c2y} ${point.x},${point.y}`;
10812
+ }
10813
+ else {
10814
+ path += ` L${point.x},${point.y}`;
10815
+ }
10816
+ }
10817
+ return path;
10818
+ }
10819
+ /** Pie slices of positive values (null, zero and negative values get no slice); angles in radians from 12 o'clock, clockwise. */
10820
+ function pieSlices(values) {
10821
+ const total = values.reduce((acc, value) => acc + (value !== null && value > 0 ? value : 0), 0);
10822
+ if (total <= 0)
10823
+ return [];
10824
+ const slices = [];
10825
+ let angle = 0;
10826
+ values.forEach((value, index) => {
10827
+ if (value === null || value <= 0)
10828
+ return;
10829
+ const fraction = value / total;
10830
+ const end = angle + fraction * Math.PI * 2;
10831
+ slices.push({ index, value, fraction, startAngle: angle, endAngle: end });
10832
+ angle = end;
10833
+ });
10834
+ return slices;
10835
+ }
10836
+ /** A point on a circle; angle in radians from 12 o'clock, clockwise. */
10837
+ function polar(cx, cy, radius, angle) {
10838
+ return { x: cx + radius * Math.sin(angle), y: cy - radius * Math.cos(angle) };
10839
+ }
10840
+ /** SVG path of an arc band (or a pie wedge when innerRadius is 0) between two angles. */
10841
+ function arcPath(cx, cy, outerRadius, innerRadius, start, end) {
10842
+ const sweep = end - start;
10843
+ if (sweep >= Math.PI * 2 - 1e-9) {
10844
+ const mid = start + Math.PI;
10845
+ return arcPath(cx, cy, outerRadius, innerRadius, start, mid) + " " + arcPath(cx, cy, outerRadius, innerRadius, mid, end);
10846
+ }
10847
+ const large = sweep > Math.PI ? 1 : 0;
10848
+ const o1 = polar(cx, cy, outerRadius, start);
10849
+ const o2 = polar(cx, cy, outerRadius, end);
10850
+ if (innerRadius <= 0) {
10851
+ return `M${cx},${cy} L${o1.x},${o1.y} A${outerRadius},${outerRadius} 0 ${large} 1 ${o2.x},${o2.y} Z`;
10852
+ }
10853
+ const i2 = polar(cx, cy, innerRadius, end);
10854
+ const i1 = polar(cx, cy, innerRadius, start);
10855
+ return `M${o1.x},${o1.y} A${outerRadius},${outerRadius} 0 ${large} 1 ${o2.x},${o2.y} L${i2.x},${i2.y} A${innerRadius},${innerRadius} 0 ${large} 0 ${i1.x},${i1.y} Z`;
10856
+ }
10857
+ /** Clamps a gauge value into the scale; null stays at the minimum. */
10858
+ function clampGaugeValue(value, minimum, maximum) {
10859
+ if (value === null || value === undefined || !Number.isFinite(value))
10860
+ return minimum;
10861
+ const low = Math.min(minimum, maximum);
10862
+ const high = Math.max(minimum, maximum);
10863
+ return Math.min(high, Math.max(low, value));
10864
+ }
10865
+ /** Formats an axis or data value compactly: integers without decimals, else up to 2 decimals. */
10866
+ function formatChartValue(value) {
10867
+ if (Number.isInteger(value))
10868
+ return value.toString();
10869
+ return (Math.round(value * 100) / 100).toString();
10870
+ }
10871
+
10872
+ /** More ticks than this on one scale is a broken interval, not a scale anyone can read. */
10873
+ const MAX_GAUGE_TICKS = 200;
10874
+ /**
10875
+ * The ellipse a state indicator fills: its percent box of the panel, stretched to an oval in a box
10876
+ * that is not square, like the old viewer. Null when the active state has no color or the box is empty.
10877
+ */
10878
+ function stateIndicatorEllipse(indicator, panelWidth, panelHeight) {
10879
+ if (!indicator.Color)
10880
+ return null;
10881
+ const width = (Math.max(0, indicator.Width) / 100) * panelWidth;
10882
+ const height = (Math.max(0, indicator.Height) / 100) * panelHeight;
10883
+ if (width <= 0 || height <= 0)
10884
+ return null;
10885
+ const left = (indicator.Left / 100) * panelWidth;
10886
+ const top = (indicator.Top / 100) * panelHeight;
10887
+ return { cx: left + width / 2, cy: top + height / 2, rx: width / 2, ry: height / 2 };
10888
+ }
10889
+ /** The value span a Bar pointer covers: from the scale minimum to the value clamped into the scale. */
10890
+ function gaugeBarSpan(value, minimum, maximum) {
10891
+ return { from: minimum, to: clampGaugeValue(value, minimum, maximum) };
10892
+ }
10893
+ function tidy(value) {
10894
+ return Number(value.toPrecision(12));
10895
+ }
10896
+ /**
10897
+ * The major tick values of a gauge scale: every `interval` from the minimum up to the maximum (the
10898
+ * server computes it); without a usable interval the chart axis' nice step of the range is used.
10899
+ */
10900
+ function gaugeTicks(minimum, maximum, interval) {
10901
+ const low = Math.min(minimum, maximum);
10902
+ const high = Math.max(minimum, maximum);
10903
+ if (!Number.isFinite(low) || !Number.isFinite(high))
10904
+ return [];
10905
+ if (high === low)
10906
+ return [tidy(low)];
10907
+ const step = interval !== null && interval !== undefined && Number.isFinite(interval) && interval > 0
10908
+ ? interval
10909
+ : niceAxisStep(high - low);
10910
+ const count = Math.floor(tidy((high - low) / step));
10911
+ if (count > MAX_GAUGE_TICKS)
10912
+ return [tidy(low), tidy(high)];
10913
+ const ticks = [];
10914
+ for (let index = 0; index <= count; index++)
10915
+ ticks.push(tidy(low + index * step));
10916
+ return ticks;
10917
+ }
10918
+ /**
10919
+ * A thickness given in percent of the gauge's own size (for a horizontal linear gauge its height, as
10920
+ * the chart engine measures range and pointer widths), or the default fraction when it is missing.
10921
+ */
10922
+ function gaugeThickness(percent, gaugeSize, defaultFraction) {
10923
+ const fraction = percent !== null && percent !== undefined && Number.isFinite(percent) && percent > 0 ? percent / 100 : defaultFraction;
10924
+ return gaugeSize * Math.min(1, fraction);
10925
+ }
10926
+ /** Cross (or none) is centred on the scale line, Inside lies above it, Outside below it. */
10927
+ function gaugeBandExtent(placement, thickness) {
10928
+ switch ((placement ?? "").toLowerCase()) {
10929
+ case "inside": return { up: thickness, down: 0 };
10930
+ case "outside": return { up: 0, down: thickness };
10931
+ default: return { up: thickness / 2, down: thickness / 2 };
10932
+ }
10933
+ }
10934
+ /**
10935
+ * The y of the scale line of a horizontal linear gauge `height` tall: the bands (ranges and pointers)
10936
+ * and the tick labels below them (`labelSpace`) are centred as one block.
10937
+ */
10938
+ function linearGaugeScaleY(height, bands, labelSpace) {
10939
+ const up = Math.max(0, ...bands.map(band => band.up));
10940
+ const down = Math.max(0, ...bands.map(band => band.down));
10941
+ return Math.max(up, (height - (up + down + labelSpace)) / 2 + up);
10942
+ }
10943
+
10944
+ /** The order an "Auto" marker takes per series, as the chart engine cycles it. */
10945
+ const AUTO_SHAPES = ["square", "circle", "diamond", "triangle", "cross", "star4", "star5", "star6", "star10"];
10946
+ const SHAPES = {
10947
+ square: "square",
10948
+ circle: "circle",
10949
+ diamond: "diamond",
10950
+ triangle: "triangle",
10951
+ cross: "cross",
10952
+ star4: "star4",
10953
+ star5: "star5",
10954
+ star6: "star6",
10955
+ star10: "star10"
10956
+ };
10957
+ /** The marker size when the series sets none, as the server uses it. */
10958
+ const RDL_DEFAULT_MARKER_SIZE_PT = 5;
10959
+ /**
10960
+ * The marker a series draws, or null for none. The server resolves Auto to a shape, so a missing type
10961
+ * or None means no marker. Should an Auto (or an unknown name) still arrive, a scatter series cycles
10962
+ * the shapes per series, so its points stay visible; a line series then draws none.
10963
+ */
10964
+ function seriesMarker(markerType, scatter, seriesIndex) {
10965
+ if (!markerType)
10966
+ return null;
10967
+ const name = markerType.trim().toLowerCase();
10968
+ if (name === "none" || name === "")
10969
+ return null;
10970
+ const shape = SHAPES[name];
10971
+ if (shape)
10972
+ return shape;
10973
+ return scatter ? AUTO_SHAPES[seriesIndex % AUTO_SHAPES.length] : null;
10974
+ }
10975
+ /** The marker size in pixels at a zoom (RDL size, default 5pt), at least 3 px so it stays visible. */
10976
+ function markerSizePx(markerSize, zoom) {
10977
+ return Math.max(3, ptToPx(parseRdlSize(markerSize) ?? RDL_DEFAULT_MARKER_SIZE_PT, zoom));
10978
+ }
10979
+ function round(value) {
10980
+ return Math.round(value * 100) / 100;
10981
+ }
10982
+ function polygon(points) {
10983
+ return `M${points.map(([x, y]) => `${round(x)},${round(y)}`).join(" L")} Z`;
10984
+ }
10985
+ function star(cx, cy, outer, points) {
10986
+ const inner = outer * (points <= 4 ? 0.35 : 0.45);
10987
+ const corners = [];
10988
+ for (let index = 0; index < points * 2; index++) {
10989
+ const radius = index % 2 === 0 ? outer : inner;
10990
+ const angle = -Math.PI / 2 + (index * Math.PI) / points;
10991
+ corners.push([cx + radius * Math.cos(angle), cy + radius * Math.sin(angle)]);
10992
+ }
10993
+ return polygon(corners);
10994
+ }
10995
+ /** SVG path of a marker of `size` (its width; an X has arms of that length along its diagonals) centered on (cx, cy); every shape is filled. */
10996
+ function markerPath(shape, cx, cy, size) {
10997
+ const r = size / 2;
10998
+ switch (shape) {
10999
+ case "square":
11000
+ return polygon([[cx - r, cy - r], [cx + r, cy - r], [cx + r, cy + r], [cx - r, cy + r]]);
11001
+ case "circle":
11002
+ return `M${round(cx - r)},${round(cy)} A${round(r)},${round(r)} 0 1 0 ${round(cx + r)},${round(cy)} A${round(r)},${round(r)} 0 1 0 ${round(cx - r)},${round(cy)} Z`;
11003
+ case "diamond":
11004
+ return polygon([[cx, cy - r], [cx + r, cy], [cx, cy + r], [cx - r, cy]]);
11005
+ case "triangle":
11006
+ return polygon([[cx, cy - r], [cx + r, cy + r], [cx - r, cy + r]]);
11007
+ case "cross": {
11008
+ // The chart engine's Cross is an X: a filled plus sign, its arms a third of the size thick, turned by 45 degrees.
11009
+ const t = size / 6;
11010
+ const plus = [
11011
+ [-t, -r], [t, -r], [t, -t], [r, -t], [r, t], [t, t],
11012
+ [t, r], [-t, r], [-t, t], [-r, t], [-r, -t], [-t, -t]
11013
+ ];
11014
+ const turn = Math.SQRT1_2;
11015
+ return polygon(plus.map(([dx, dy]) => [cx + (dx - dy) * turn, cy + (dx + dy) * turn]));
11016
+ }
11017
+ case "star4": return star(cx, cy, r, 4);
11018
+ case "star5": return star(cx, cy, r, 5);
11019
+ case "star6": return star(cx, cy, r, 6);
11020
+ case "star10": return star(cx, cy, r, 10);
11021
+ }
11022
+ }
11023
+ const ALIGN = {
11024
+ left: "start",
11025
+ top: "start",
11026
+ center: "center",
11027
+ right: "end",
11028
+ bottom: "end"
11029
+ };
11030
+ /** The RDL default legend position: a column on the right, vertically centered (RightCenter). */
11031
+ const DEFAULT_LEGEND = { edge: "right", align: "center" };
11032
+ /**
11033
+ * The RDL ChartLegend Position as an edge and an alignment: the first word is the edge, the second
11034
+ * the alignment along it (TopLeft = top edge, left aligned; LeftTop = left edge, top aligned).
11035
+ * Missing or unknown = RightCenter, the RDL default.
11036
+ */
11037
+ function legendPlacement(position) {
11038
+ const match = /^(top|bottom|left|right)(left|right|top|bottom|center)$/i.exec((position ?? "").trim());
11039
+ if (!match)
11040
+ return DEFAULT_LEGEND;
11041
+ const edge = match[1].toLowerCase();
11042
+ const along = match[2].toLowerCase();
11043
+ const horizontalEdge = edge === "top" || edge === "bottom";
11044
+ // "TopTop" or "LeftLeft" make no sense: the alignment must run along the edge.
11045
+ const valid = horizontalEdge ? ["left", "center", "right"].includes(along) : ["top", "center", "bottom"].includes(along);
11046
+ return { edge, align: valid ? ALIGN[along] : "center" };
11047
+ }
11048
+
11049
+ var styles$2 = {"chart":"cw-report-chart-module__chart__HEwvf","title":"cw-report-chart-module__title__zvCfx","axis":"cw-report-chart-module__axis__qwHaL","grid":"cw-report-chart-module__grid__xJMG8","tick":"cw-report-chart-module__tick__uQJeQ","muted":"cw-report-chart-module__muted__Nj1-j","hit":"cw-report-chart-module__hit__-u6vf","point":"cw-report-chart-module__point__M-GuI","slice":"cw-report-chart-module__slice__DEbOB","track":"cw-report-chart-module__track__NAVBX","needle":"cw-report-chart-module__needle__m5fJK","cap":"cw-report-chart-module__cap__zL7KT"};
11050
+
11051
+ /** Chart text size in points (scaled with the zoom). */
11052
+ const CHART_FONT_PT = 8;
11053
+ /** Rough width of one character of the chart font, as a share of the font size. */
11054
+ const CHAR_WIDTH = 0.6;
11055
+ function chartFontPx(zoom) {
11056
+ return ptToPx(CHART_FONT_PT, zoom);
11057
+ }
11058
+ function estimateTextWidth(text, fontPx) {
11059
+ return text.length * fontPx * CHAR_WIDTH;
11060
+ }
11061
+ /** Hover handlers that show the shared CwTooltipManager tooltip over an SVG element. */
11062
+ function useChartTooltip() {
11063
+ React.useEffect(() => {
11064
+ ensureTooltipManager();
11065
+ }, []);
11066
+ const show = React.useCallback((content) => (event) => {
11067
+ showTooltip(content, event.currentTarget, "top");
11068
+ }, []);
11069
+ const hide = React.useCallback(() => hideTooltip(), []);
11070
+ return { show, hide };
11071
+ }
11072
+ function tooltipContent(title, label, value) {
11073
+ return (jsxRuntime.jsxs("span", { children: [jsxRuntime.jsx("strong", { children: title }), jsxRuntime.jsx("br", {}), label, ": ", value] }));
11074
+ }
11075
+ /** Lays legend entries out in rows that wrap at `width`, each row aligned within `width` (centered by default). */
11076
+ function layoutLegend(entries, width, fontPx, align = "center") {
11077
+ if (entries.length === 0)
11078
+ return { height: 0, width: 0, items: [] };
11079
+ const swatch = fontPx;
11080
+ const gap = fontPx;
11081
+ const lineHeight = fontPx * 1.6;
11082
+ const rows = [[]];
11083
+ let rowWidth = 0;
11084
+ for (const entry of entries) {
11085
+ const itemWidth = swatch + fontPx * 0.4 + estimateTextWidth(entry.label, fontPx);
11086
+ if (rowWidth > 0 && rowWidth + gap + itemWidth > width) {
11087
+ rows.push([]);
11088
+ rowWidth = 0;
11089
+ }
11090
+ rowWidth += (rowWidth > 0 ? gap : 0) + itemWidth;
11091
+ rows[rows.length - 1].push({ entry, width: itemWidth });
11092
+ }
11093
+ const items = [];
11094
+ let widest = 0;
11095
+ rows.forEach((row, rowIndex) => {
11096
+ const total = row.reduce((acc, item) => acc + item.width, 0) + gap * (row.length - 1);
11097
+ widest = Math.max(widest, total);
11098
+ const free = Math.max(0, width - total);
11099
+ let x = align === "start" ? 0 : align === "end" ? free : free / 2;
11100
+ for (const item of row) {
11101
+ items.push({ entry: item.entry, x, y: rowIndex * lineHeight + lineHeight / 2 });
11102
+ x += item.width + gap;
11103
+ }
11104
+ });
11105
+ return { height: rows.length * lineHeight, width: widest, items };
11106
+ }
11107
+ function ChartLegend({ layout, top, left = 0, fontPx }) {
11108
+ return (jsxRuntime.jsx("g", { transform: `translate(${left}, ${top})`, children: layout.items.map((item, index) => (jsxRuntime.jsxs("g", { transform: `translate(${item.x}, ${item.y})`, children: [item.entry.marker
11109
+ ? jsxRuntime.jsx("path", { d: markerPath(item.entry.marker, fontPx / 2, 0, fontPx), fill: item.entry.color })
11110
+ : jsxRuntime.jsx("rect", { x: 0, y: -fontPx / 2, width: fontPx, height: fontPx, fill: item.entry.color }), jsxRuntime.jsx("text", { x: fontPx * 1.4, dominantBaseline: "central", fontSize: fontPx, children: item.entry.label })] }, index))) }));
11111
+ }
11112
+ /** The chart titles, one line each, centered. Returns the height they take. */
11113
+ function ChartTitles({ titles, width, fontPx }) {
11114
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: titles.map((title, index) => (jsxRuntime.jsx("text", { className: styles$2.title, x: width / 2, y: fontPx * 1.5 * (index + 1), textAnchor: "middle", fontSize: fontPx * 1.25, children: title }, index))) }));
11115
+ }
11116
+ function titlesHeight(titles, fontPx) {
11117
+ return titles.length === 0 ? 0 : fontPx * 1.5 * titles.length + fontPx * 0.5;
11118
+ }
11119
+ /** A centered message instead of the plot (dataset error or no rows). */
11120
+ function ChartMessage({ text, width, height, fontPx }) {
11121
+ return (jsxRuntime.jsx("text", { className: styles$2.muted, x: width / 2, y: height / 2, textAnchor: "middle", dominantBaseline: "central", fontSize: fontPx * 1.2, children: text }));
11122
+ }
11123
+
11124
+ /** 270 degree dial: from 7:30 to 4:30 on a clock face, in radians from 12 o'clock. */
11125
+ const DIAL_START = -Math.PI * 0.75;
11126
+ const DIAL_END = Math.PI * 0.75;
11127
+ /** Report content defaults, as the old viewer drew them: black pointers, the Default palette for ranges. */
11128
+ const POINTER_FALLBACK = "black";
11129
+ const RANGE_PALETTE = chartPalette(null);
11130
+ /** Thickness of a range / pointer without a Width, as a fraction of the gauge height (the chart engine defaults). */
11131
+ const RANGE_DEFAULT_WIDTH = 0.3;
11132
+ const POINTER_DEFAULT_WIDTH = 0.1;
11133
+ const EMPTY_SCALE = { Minimum: 0, Maximum: 100, Pointers: [], Ranges: [] };
11134
+ function isBarPointer(type) {
11135
+ return (type ?? "").toLowerCase() === "bar";
11136
+ }
11137
+ function rangeColor(range, index) {
11138
+ return range.Color || RANGE_PALETTE[index % RANGE_PALETTE.length];
11139
+ }
11140
+ function pointerColor(pointer) {
11141
+ return pointer.Color || POINTER_FALLBACK;
11142
+ }
11143
+ function RadialGauge({ gauge, width, height, fontPx, zoom }) {
11144
+ const scale = gauge.Scales[0] ?? EMPTY_SCALE;
11145
+ const { Minimum: min, Maximum: max } = scale;
11146
+ const radius = Math.max(0, Math.min(width / 2, height / 1.75) - fontPx * 0.5);
11147
+ const cx = width / 2;
11148
+ const cy = fontPx * 0.5 + radius;
11149
+ const band = radius * 0.15;
11150
+ const angle = (value) => scaleValue(clampGaugeValue(value, min, max), { min, max }, DIAL_START, DIAL_END);
11151
+ const minLabel = polar(cx, cy, radius - band * 2.5, DIAL_START);
11152
+ const maxLabel = polar(cx, cy, radius - band * 2.5, DIAL_END);
11153
+ const showLabels = scale.ShowLabels !== false;
11154
+ return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("path", { className: styles$2.track, d: arcPath(cx, cy, radius, radius - band, DIAL_START, DIAL_END) }), scale.Ranges.map((range, index) => (jsxRuntime.jsx("path", { d: arcPath(cx, cy, radius, radius - band, angle(range.Start ?? min), angle(range.End ?? max)), fill: rangeColor(range, index) }, `r${index}`))), scale.Pointers.map((pointer, index) => {
11155
+ if (isBarPointer(pointer.Type)) {
11156
+ const span = gaugeBarSpan(pointer.Value, min, max);
11157
+ return (jsxRuntime.jsx("path", { d: arcPath(cx, cy, radius - band * 1.2, radius - band * 1.9, angle(span.from), angle(span.to)), fill: pointerColor(pointer) }, `p${index}`));
11158
+ }
11159
+ const tip = polar(cx, cy, radius * 0.8, angle(pointer.Value ?? min));
11160
+ return (jsxRuntime.jsx("line", { className: styles$2.needle, x1: cx, y1: cy, x2: tip.x, y2: tip.y, style: pointer.Color ? { stroke: pointer.Color } : undefined, strokeWidth: Math.max(1.5, 2.5 * zoom) }, `p${index}`));
11161
+ }), jsxRuntime.jsx("circle", { className: styles$2.cap, cx: cx, cy: cy, r: Math.max(2, radius * 0.06) }), showLabels && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("text", { className: styles$2.tick, x: minLabel.x, y: minLabel.y, textAnchor: "middle", fontSize: fontPx, children: formatChartValue(min) }), jsxRuntime.jsx("text", { className: styles$2.tick, x: maxLabel.x, y: maxLabel.y, textAnchor: "middle", fontSize: fontPx, children: formatChartValue(max) })] }))] }));
11162
+ }
11163
+ /**
11164
+ * A horizontal linear gauge as the chart engine draws it: range bands and pointers are as thick as
11165
+ * their Width percent of the gauge height (ranges 30%, pointers 10% by default) around the scale line
11166
+ * (Cross centred, Inside above, Outside below), the ranges in their own colour at full opacity, a Bar
11167
+ * pointer on top of them from the minimum to the value, and the major ticks with labels below.
11168
+ */
11169
+ function LinearGauge({ gauge, width, height, fontPx }) {
11170
+ const scale = gauge.Scales[0] ?? EMPTY_SCALE;
11171
+ const { Minimum: min, Maximum: max } = scale;
11172
+ const showLabels = scale.ShowLabels !== false;
11173
+ const left = fontPx;
11174
+ const right = width - fontPx;
11175
+ const labelSpace = showLabels ? fontPx * 2 : 0;
11176
+ const x = (value) => scaleValue(clampGaugeValue(value, min, max), { min, max }, left, right);
11177
+ const ticks = showLabels ? gaugeTicks(min, max, scale.Interval) : [];
11178
+ const ranges = scale.Ranges.map(range => {
11179
+ const thickness = gaugeThickness(range.Width, height, RANGE_DEFAULT_WIDTH);
11180
+ return { range, thickness, extent: gaugeBandExtent(range.Placement, thickness) };
11181
+ });
11182
+ const pointers = scale.Pointers.map(pointer => {
11183
+ const thickness = gaugeThickness(pointer.Width, height, POINTER_DEFAULT_WIDTH);
11184
+ return { pointer, thickness, extent: gaugeBandExtent(pointer.Placement, thickness) };
11185
+ });
11186
+ const extents = [...ranges, ...pointers].map(band => band.extent);
11187
+ const scaleY = linearGaugeScaleY(height, extents, labelSpace);
11188
+ const bandsBottom = scaleY + Math.max(0, ...extents.map(extent => extent.down));
11189
+ return (jsxRuntime.jsxs("g", { children: [ranges.map(({ range, thickness, extent }, index) => {
11190
+ const from = x(range.Start ?? min);
11191
+ const to = x(range.End ?? max);
11192
+ return (jsxRuntime.jsx("rect", { x: Math.min(from, to), y: scaleY - extent.up, width: Math.abs(to - from), height: thickness, fill: rangeColor(range, index) }, `r${index}`));
11193
+ }), jsxRuntime.jsx("line", { className: styles$2.axis, x1: left, x2: right, y1: scaleY, y2: scaleY }), pointers.map(({ pointer, thickness, extent }, index) => {
11194
+ if (isBarPointer(pointer.Type)) {
11195
+ const span = gaugeBarSpan(pointer.Value, min, max);
11196
+ const from = x(span.from);
11197
+ const to = x(span.to);
11198
+ return (jsxRuntime.jsx("rect", { x: Math.min(from, to), y: scaleY - extent.up, width: Math.abs(to - from), height: thickness, fill: pointerColor(pointer) }, `p${index}`));
11199
+ }
11200
+ // A marker: a triangle pointing at the scale line from below.
11201
+ const at = x(pointer.Value ?? min);
11202
+ const size = Math.max(thickness, fontPx * 0.6);
11203
+ return (jsxRuntime.jsx("path", { d: `M${at},${scaleY} l${-size / 2},${size} h${size} Z`, fill: pointerColor(pointer) }, `p${index}`));
11204
+ }), ticks.map(tick => (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("line", { className: styles$2.axis, x1: x(tick), x2: x(tick), y1: bandsBottom, y2: bandsBottom + fontPx * 0.4 }), jsxRuntime.jsx("text", { className: styles$2.tick, x: x(tick), y: bandsBottom + fontPx * 1.5, textAnchor: "middle", fontSize: fontPx, children: formatChartValue(tick) })] }, tick)))] }));
11205
+ }
11206
+ /**
11207
+ * A gauge panel: its gauges side by side (RadialGauge = 270 degree dial with colored ranges and a
11208
+ * needle or bar per pointer, LinearGauge = horizontal track with range bands, a bar or marker per
11209
+ * pointer and the major ticks), the state indicators at their percent boxes and the panel labels
11210
+ * below. The pointer value is not printed; only the report's own labels are. Only the first scale of
11211
+ * a gauge is drawn.
11212
+ */
11213
+ function CwReportGauge({ panel, width, height, zoom = 1 }) {
11214
+ const fontPx = chartFontPx(zoom);
11215
+ const lineHeight = fontPx * 1.5;
11216
+ const labelsHeight = panel.Labels.length * lineHeight;
11217
+ const gaugeHeight = Math.max(0, height - labelsHeight);
11218
+ const cellWidth = panel.Gauges.length > 0 ? width / panel.Gauges.length : width;
11219
+ return (jsxRuntime.jsxs("svg", { className: styles$2.chart, width: width, height: height, role: "img", "aria-label": panel.Name, children: [panel.Error ? (jsxRuntime.jsx(ChartMessage, { text: panel.Error, width: width, height: height, fontPx: fontPx })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [panel.Gauges.map((gauge, index) => {
11220
+ const drawProps = { gauge, width: cellWidth, height: gaugeHeight, fontPx, zoom };
11221
+ return (jsxRuntime.jsx("g", { transform: `translate(${cellWidth * index}, 0)`, children: gauge.Kind.toLowerCase() === "lineargauge" ? jsxRuntime.jsx(LinearGauge, { ...drawProps }) : jsxRuntime.jsx(RadialGauge, { ...drawProps }) }, index));
11222
+ }), (panel.StateIndicators ?? []).map((indicator, index) => {
11223
+ const ellipse = stateIndicatorEllipse(indicator, width, height);
11224
+ return ellipse && jsxRuntime.jsx("ellipse", { ...ellipse, fill: indicator.Color ?? undefined }, `s${index}`);
11225
+ })] })), panel.Labels.map((label, index) => (jsxRuntime.jsx("text", { x: width / 2, y: gaugeHeight + lineHeight * (index + 0.7), textAnchor: "middle", fontSize: fontPx, children: label }, index)))] }));
11226
+ }
11227
+
11228
+ /*
11229
+ * The .NET numeric format strings a report puts on a chart's value axis (<Format>), applied with the
11230
+ * report culture so the screen shows the same tick text as the server's PDF. Only the formats reports
11231
+ * actually use are covered; anything else returns null and the caller keeps its own formatting.
11232
+ */
11233
+ /** .NET's default decimals of the N, F and P standard formats without a precision. */
11234
+ const STANDARD_DEFAULT_DECIMALS = 2;
11235
+ const STANDARD_FORMAT = /^([NnFfPp])(\d{1,2})?$/;
11236
+ /** 0, 0.00, 0.0#, #,##0, #,0.00, 0%, 0.0% ... (integer part of 0, # and one optional grouping comma). */
11237
+ const CUSTOM_FORMAT = /^(#*,?#*0+)(?:\.(0*)(#*))?(%?)$/;
11238
+ /**
11239
+ * Formats longer than this are not matched (the custom pattern backtracks quadratically on a long
11240
+ * non-matching string), and more decimals than this are left to the caller: Intl.NumberFormat throws
11241
+ * above 100 fraction digits (above 20 on older browsers), which would break the chart render.
11242
+ */
11243
+ const MAX_FORMAT_LENGTH = 64;
11244
+ const MAX_FRACTION_DIGITS = 20;
11245
+ function parseFormat(format) {
11246
+ if (format.length > MAX_FORMAT_LENGTH)
11247
+ return null;
11248
+ const standard = STANDARD_FORMAT.exec(format);
11249
+ if (standard) {
11250
+ const kind = standard[1].toUpperCase();
11251
+ const digits = standard[2] === undefined ? STANDARD_DEFAULT_DECIMALS : parseInt(standard[2], 10);
11252
+ return {
11253
+ minimumFractionDigits: digits,
11254
+ maximumFractionDigits: digits,
11255
+ grouping: kind !== "F",
11256
+ percent: kind === "P" ? "standard" : null
11257
+ };
11258
+ }
11259
+ const custom = CUSTOM_FORMAT.exec(format);
11260
+ if (custom) {
11261
+ const required = custom[2]?.length ?? 0;
11262
+ const optional = custom[3]?.length ?? 0;
11263
+ return {
11264
+ minimumFractionDigits: required,
11265
+ maximumFractionDigits: required + optional,
11266
+ grouping: custom[1].includes(","),
11267
+ percent: custom[4] === "%" ? "custom" : null
11268
+ };
11269
+ }
11270
+ return null;
11271
+ }
11272
+ function numberFormat(locale, options) {
11273
+ try {
11274
+ return new Intl.NumberFormat(locale || "en-US", options);
11275
+ }
11276
+ catch {
11277
+ return new Intl.NumberFormat("en-US", options);
11278
+ }
11279
+ }
11280
+ /**
11281
+ * A value in a .NET numeric format ("N0", "F1", "P0", "0", "0.0", "#,##0.00", "0%", ...) and a culture
11282
+ * ("de-CH"; missing or unknown = invariant-like en-US). Null for a missing or unsupported format.
11283
+ * The standard "P" uses the culture's percent pattern (e.g. "12 %" in de-DE); a custom "%" appends the
11284
+ * sign directly, as .NET does.
11285
+ */
11286
+ function formatRdlNumber(value, format, culture) {
11287
+ if (!format || !Number.isFinite(value))
11288
+ return null;
11289
+ const spec = parseFormat(format.trim());
11290
+ if (!spec || spec.maximumFractionDigits > MAX_FRACTION_DIGITS)
11291
+ return null;
11292
+ const digits = {
11293
+ minimumFractionDigits: spec.minimumFractionDigits,
11294
+ maximumFractionDigits: spec.maximumFractionDigits,
11295
+ useGrouping: spec.grouping
11296
+ };
11297
+ const locale = culture ?? undefined;
11298
+ if (spec.percent === "standard")
11299
+ return numberFormat(locale, { ...digits, style: "percent" }).format(value);
11300
+ if (spec.percent === "custom") {
11301
+ // The percent style scales by 100 without float noise (0.145 -> 14.5, not 14.499...); its own
11302
+ // sign and spacing are dropped for the plain "%" a custom format appends.
11303
+ const parts = numberFormat(locale, { ...digits, style: "percent" }).formatToParts(value);
11304
+ return `${parts.filter(part => part.type !== "percentSign" && part.type !== "literal").map(part => part.value).join("")}%`;
11305
+ }
11306
+ return numberFormat(locale, digits).format(value);
11307
+ }
11308
+
11309
+ function seriesKind(series) {
11310
+ switch (series.Type.toLowerCase()) {
11311
+ case "column": return "column";
11312
+ case "bar": return "bar";
11313
+ case "area": return "area";
11314
+ case "scatter": return "scatter";
11315
+ default: return "line";
11316
+ }
11317
+ }
11318
+ function truncate(text, maxWidth, fontPx) {
11319
+ if (estimateTextWidth(text, fontPx) <= maxWidth)
11320
+ return text;
11321
+ const chars = Math.max(1, Math.floor(maxWidth / (fontPx * 0.6)) - 1);
11322
+ return text.slice(0, chars) + "…";
11323
+ }
11324
+ /** Categories along the x axis, values up: lines, areas, columns and scatter points. */
11325
+ function VerticalPlot({ chart, colors, scale, fontPx, left, top, right, bottom, strokeWidth, zoom, tickLabel }) {
11326
+ const tooltip = useChartTooltip();
11327
+ const count = Math.max(1, chart.Categories.length);
11328
+ const band = (right - left) / count;
11329
+ const x = (index) => left + band * (index + 0.5);
11330
+ const y = (value) => scaleValue(value, scale, bottom, top);
11331
+ const baseline = y(Math.min(scale.max, Math.max(scale.min, 0)));
11332
+ const columns = chart.Series.map((series, index) => ({ series, index })).filter(({ series }) => {
11333
+ const kind = seriesKind(series);
11334
+ return kind === "column" || kind === "bar";
11335
+ });
11336
+ const groupWidth = band * 0.75;
11337
+ const columnWidth = columns.length > 0 ? groupWidth / columns.length : 0;
11338
+ const labelWidth = Math.max(...chart.Categories.map(label => estimateTextWidth(label, fontPx)), 0) + fontPx;
11339
+ const labelStep = Math.max(1, Math.ceil(Math.min(labelWidth, fontPx * 12) / band));
11340
+ const marks = [];
11341
+ const hits = [];
11342
+ columns.forEach(({ series, index }, columnIndex) => {
11343
+ series.Values.forEach((value, category) => {
11344
+ if (value === null || !Number.isFinite(value))
11345
+ return;
11346
+ const columnX = left + band * category + (band - groupWidth) / 2 + columnWidth * columnIndex;
11347
+ const valueY = y(value);
11348
+ const content = tooltipContent(series.Name, chart.Categories[category] ?? "", formatChartValue(value));
11349
+ marks.push(jsxRuntime.jsx("rect", { x: columnX, y: Math.min(valueY, baseline), width: Math.max(1, columnWidth - 1), height: Math.max(0, Math.abs(baseline - valueY)), fill: colors[index], onMouseEnter: tooltip.show(content), onMouseLeave: tooltip.hide }, `c${index}-${category}`));
11350
+ if (series.ShowDataLabels) {
11351
+ marks.push(jsxRuntime.jsx("text", { x: columnX + columnWidth / 2, y: valueY - fontPx * 0.4, textAnchor: "middle", fontSize: fontPx, children: formatChartValue(value) }, `cl${index}-${category}`));
11352
+ }
11353
+ });
11354
+ });
11355
+ chart.Series.forEach((series, index) => {
11356
+ const kind = seriesKind(series);
11357
+ if (kind !== "line" && kind !== "area" && kind !== "scatter")
11358
+ return;
11359
+ const marker = seriesMarker(series.MarkerType, kind === "scatter", index);
11360
+ const markerSize = markerSizePx(series.MarkerSize, zoom);
11361
+ const segments = lineSegments(series.Values, x, y);
11362
+ segments.forEach((segment, segmentIndex) => {
11363
+ if (kind !== "scatter")
11364
+ drawLine(segment, segmentIndex);
11365
+ for (const point of segment) {
11366
+ if (marker) {
11367
+ marks.push(jsxRuntime.jsx("path", { d: markerPath(marker, point.x, point.y, markerSize), fill: colors[index] }, `m${index}-${point.index}`));
11368
+ }
11369
+ if (series.ShowDataLabels) {
11370
+ marks.push(jsxRuntime.jsx("text", { x: point.x, y: point.y - Math.max(fontPx * 0.6, markerSize), textAnchor: "middle", fontSize: fontPx, children: formatChartValue(point.value) }, `ll${index}-${point.index}`));
11371
+ }
11372
+ const content = tooltipContent(series.Name, chart.Categories[point.index] ?? "", formatChartValue(point.value));
11373
+ hits.push(jsxRuntime.jsx("circle", { className: styles$2.hit, cx: point.x, cy: point.y, r: Math.max(4, Math.min(8, band / 3), markerSize / 2), onMouseEnter: tooltip.show(content), onMouseLeave: tooltip.hide }, `h${index}-${point.index}`));
11374
+ }
11375
+ });
11376
+ function drawLine(segment, segmentIndex) {
11377
+ const path = segmentPath(segment, series.Subtype);
11378
+ if (kind === "area") {
11379
+ const first = segment[0];
11380
+ const last = segment[segment.length - 1];
11381
+ marks.push(jsxRuntime.jsx("path", { d: `${path} L${last.x},${baseline} L${first.x},${baseline} Z`, fill: colors[index], fillOpacity: 0.45, stroke: "none" }, `a${index}-${segmentIndex}`));
11382
+ }
11383
+ marks.push(jsxRuntime.jsx("path", { d: path, fill: "none", stroke: colors[index], strokeWidth: strokeWidth }, `l${index}-${segmentIndex}`));
11384
+ // A lone point between gaps has no line to show it: a dot, unless the series draws markers.
11385
+ if (segment.length === 1 && !marker) {
11386
+ marks.push(jsxRuntime.jsx("circle", { className: styles$2.point, cx: segment[0].x, cy: segment[0].y, r: strokeWidth * 1.5, fill: colors[index] }, `p${index}-${segmentIndex}`));
11387
+ }
11388
+ }
11389
+ });
11390
+ const serverLabels = chart.CategoryAxisLabels ? categoryAxisLabels(chart.CategoryAxisLabels, count, left, band) : null;
11391
+ // Category gridlines run through the labelled categories: the server's labels, else every labelStep-th category.
11392
+ const categoryGrid = chart.CategoryAxisGridLines === false
11393
+ ? []
11394
+ : serverLabels?.map(label => label.at) ?? chart.Categories.map((_label, index) => index).filter(index => index % labelStep === 0).map(x);
11395
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [categoryGrid.map((at, index) => jsxRuntime.jsx("line", { className: styles$2.grid, x1: at, x2: at, y1: top, y2: bottom }, `cg${index}`)), scale.ticks.map(tick => (jsxRuntime.jsxs("g", { children: [chart.ValueAxisGridLines !== false && jsxRuntime.jsx("line", { className: styles$2.grid, x1: left, x2: right, y1: y(tick), y2: y(tick) }), jsxRuntime.jsx("text", { className: styles$2.tick, x: left - fontPx * 0.4, y: y(tick), textAnchor: "end", dominantBaseline: "central", fontSize: fontPx, children: tickLabel(tick) })] }, tick))), jsxRuntime.jsx("line", { className: styles$2.axis, x1: left, x2: left, y1: top, y2: bottom }), jsxRuntime.jsx("line", { className: styles$2.axis, x1: left, x2: right, y1: baseline, y2: baseline }), serverLabels
11396
+ ? serverLabels.map((label, index) => {
11397
+ const placement = placeAxisLabel(label.at, estimateTextWidth(label.text, fontPx), left, right);
11398
+ return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("line", { className: styles$2.axis, x1: label.at, x2: label.at, y1: bottom, y2: bottom + fontPx * 0.3 }), jsxRuntime.jsx("text", { className: styles$2.tick, x: placement.x, y: bottom + fontPx * 1.3, textAnchor: placement.anchor, fontSize: fontPx, children: label.text })] }, `c${index}`));
11399
+ })
11400
+ : chart.Categories.map((label, index) => {
11401
+ if (index % labelStep !== 0)
11402
+ return null;
11403
+ const text = truncate(label, band * labelStep - fontPx * 0.4, fontPx);
11404
+ const placement = placeAxisLabel(x(index), estimateTextWidth(text, fontPx), left, right);
11405
+ return (jsxRuntime.jsx("text", { className: styles$2.tick, x: placement.x, y: bottom + fontPx * 1.1, textAnchor: placement.anchor, fontSize: fontPx, children: text }, index));
11406
+ }), marks, hits] }));
11407
+ }
11408
+ /** Categories down the y axis, values to the right: horizontal bars. */
11409
+ function HorizontalPlot({ chart, colors, scale, fontPx, left, top, right, bottom, tickLabel }) {
11410
+ const tooltip = useChartTooltip();
11411
+ const count = Math.max(1, chart.Categories.length);
11412
+ const band = (bottom - top) / count;
11413
+ const x = (value) => scaleValue(value, scale, left, right);
11414
+ const baseline = x(Math.min(scale.max, Math.max(scale.min, 0)));
11415
+ const groupHeight = band * 0.75;
11416
+ const barHeight = chart.Series.length > 0 ? groupHeight / chart.Series.length : 0;
11417
+ const serverLabels = chart.CategoryAxisLabels ? categoryAxisLabels(chart.CategoryAxisLabels, count, top, band) : null;
11418
+ const categoryGrid = chart.CategoryAxisGridLines === false
11419
+ ? []
11420
+ : serverLabels?.map(label => label.at) ?? chart.Categories.map((_label, index) => top + band * (index + 0.5));
11421
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [categoryGrid.map((at, index) => jsxRuntime.jsx("line", { className: styles$2.grid, x1: left, x2: right, y1: at, y2: at }, `cg${index}`)), scale.ticks.map(tick => (jsxRuntime.jsxs("g", { children: [chart.ValueAxisGridLines !== false && jsxRuntime.jsx("line", { className: styles$2.grid, x1: x(tick), x2: x(tick), y1: top, y2: bottom }), jsxRuntime.jsx("text", { className: styles$2.tick, x: x(tick), y: bottom + fontPx * 1.1, textAnchor: "middle", fontSize: fontPx, children: tickLabel(tick) })] }, tick))), jsxRuntime.jsx("line", { className: styles$2.axis, x1: baseline, x2: baseline, y1: top, y2: bottom }), jsxRuntime.jsx("line", { className: styles$2.axis, x1: left, x2: right, y1: bottom, y2: bottom }), serverLabels
11422
+ ? serverLabels.map((label, index) => (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("line", { className: styles$2.axis, x1: left - fontPx * 0.3, x2: left, y1: label.at, y2: label.at }), jsxRuntime.jsx("text", { className: styles$2.tick, x: left - fontPx * 0.4, y: label.at, textAnchor: "end", dominantBaseline: "central", fontSize: fontPx, children: truncate(label.text, left - fontPx, fontPx) })] }, `c${index}`)))
11423
+ : chart.Categories.map((label, index) => (jsxRuntime.jsx("text", { className: styles$2.tick, x: left - fontPx * 0.4, y: top + band * (index + 0.5), textAnchor: "end", dominantBaseline: "central", fontSize: fontPx, children: truncate(label, left - fontPx, fontPx) }, index))), chart.Series.map((series, index) => series.Values.map((value, category) => {
11424
+ if (value === null || !Number.isFinite(value))
11425
+ return null;
11426
+ const barY = top + band * category + (band - groupHeight) / 2 + barHeight * index;
11427
+ const valueX = x(value);
11428
+ const content = tooltipContent(series.Name, chart.Categories[category] ?? "", formatChartValue(value));
11429
+ return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("rect", { x: Math.min(valueX, baseline), y: barY, width: Math.max(0, Math.abs(valueX - baseline)), height: Math.max(1, barHeight - 1), fill: colors[index], onMouseEnter: tooltip.show(content), onMouseLeave: tooltip.hide }), series.ShowDataLabels && (jsxRuntime.jsx("text", { x: Math.max(valueX, baseline) + fontPx * 0.3, y: barY + barHeight / 2, dominantBaseline: "central", fontSize: fontPx, children: formatChartValue(value) }))] }, `${index}-${category}`));
11430
+ }))] }));
11431
+ }
11432
+ /**
11433
+ * A report chart over categories: Line (Smooth / Stepped), Area, Column and Scatter series share one
11434
+ * value axis; a chart made only of Bar series is drawn horizontally. Scatter series draw only their
11435
+ * markers, line series draw markers too when the report sets a marker type. Null values leave gaps.
11436
+ * The legend sits where the RDL legend Position says. Own SVG, no chart library; hover shows
11437
+ * category, series and value.
11438
+ */
11439
+ function CwReportLineChart({ chart, width, height, zoom = 1, culture }) {
11440
+ const fontPx = chartFontPx(zoom);
11441
+ const palette = chartPalette(chart.Palette);
11442
+ const colors = chart.Series.map((series, index) => seriesColor(series, index, palette));
11443
+ const titleHeight = titlesHeight(chart.Titles, fontPx);
11444
+ // The legend on the side its RDL Position names: a side legend is a column at most 30% wide.
11445
+ const placement = legendPlacement(chart.LegendPosition);
11446
+ const sideLegend = placement.edge === "left" || placement.edge === "right";
11447
+ const legend = layoutLegend(chart.LegendHidden ? [] : chart.Series.map((series, index) => ({
11448
+ label: series.Name,
11449
+ color: colors[index],
11450
+ marker: seriesMarker(series.MarkerType, seriesKind(series) === "scatter", index)
11451
+ })), sideLegend ? width * 0.3 : width, fontPx, sideLegend ? "start" : placement.align);
11452
+ const legendHeight = legend.height > 0 ? legend.height + fontPx * 0.5 : 0;
11453
+ const legendWidth = legend.width > 0 ? legend.width + fontPx : 0;
11454
+ const legendSpace = {
11455
+ top: placement.edge === "top" ? legendHeight : 0,
11456
+ bottom: placement.edge === "bottom" ? legendHeight : 0,
11457
+ left: placement.edge === "left" ? legendWidth : 0,
11458
+ right: placement.edge === "right" ? legendWidth : 0
11459
+ };
11460
+ const message = chart.Error
11461
+ ?? (chart.Categories.length === 0 || chart.Series.length === 0 ? (chart.NoRowsMessage ?? "No data") : null);
11462
+ if (message) {
11463
+ return (jsxRuntime.jsxs("svg", { className: styles$2.chart, width: width, height: height, role: "img", "aria-label": chart.Titles.join(" ") || chart.Name, children: [jsxRuntime.jsx(ChartTitles, { titles: chart.Titles, width: width, fontPx: fontPx }), jsxRuntime.jsx(ChartMessage, { text: message, width: width, height: height, fontPx: fontPx })] }));
11464
+ }
11465
+ const horizontal = chart.Series.every(series => seriesKind(series) === "bar");
11466
+ const scale = computeValueScale(chart.Series.flatMap(series => series.Values));
11467
+ // The axis <Format> with the report culture, as the server's PDF prints it; an unsupported format keeps the compact default.
11468
+ const tickLabel = (tick) => formatRdlNumber(tick, chart.ValueAxisFormat, culture) ?? formatChartValue(tick);
11469
+ const tickWidth = Math.max(...scale.ticks.map(tick => estimateTextWidth(tickLabel(tick), fontPx)));
11470
+ const categoryWidth = Math.min(width * 0.35, Math.max(...chart.Categories.map(label => estimateTextWidth(label, fontPx)), 0));
11471
+ const lineHeight = fontPx * 1.6;
11472
+ const valueTitleSpace = chart.ValueAxisTitle ? lineHeight : 0;
11473
+ const categoryTitleSpace = chart.CategoryAxisTitle ? lineHeight : 0;
11474
+ const left = legendSpace.left + (horizontal ? categoryTitleSpace + categoryWidth : valueTitleSpace + tickWidth) + fontPx * 0.8;
11475
+ const right = width - fontPx - legendSpace.right;
11476
+ const top = titleHeight + legendSpace.top + fontPx * 0.8;
11477
+ const bottom = height - legendSpace.bottom - lineHeight - (horizontal ? valueTitleSpace : categoryTitleSpace);
11478
+ const strokeWidth = Math.max(1, 1.5 * zoom);
11479
+ const plotProps = { chart, colors, scale, fontPx, left, top, right, bottom, strokeWidth, zoom, tickLabel };
11480
+ const verticalTitle = horizontal ? chart.CategoryAxisTitle : chart.ValueAxisTitle;
11481
+ const horizontalTitle = horizontal ? chart.ValueAxisTitle : chart.CategoryAxisTitle;
11482
+ const titleX = legendSpace.left + fontPx;
11483
+ const legendLeft = placement.edge === "left" ? fontPx * 0.4 : placement.edge === "right" ? width - legendWidth + fontPx * 0.4 : 0;
11484
+ const legendTop = (() => {
11485
+ switch (placement.edge) {
11486
+ case "top": return titleHeight;
11487
+ case "bottom": return height - legend.height;
11488
+ default:
11489
+ if (placement.align === "start")
11490
+ return top;
11491
+ if (placement.align === "end")
11492
+ return Math.max(top, bottom - legend.height);
11493
+ return Math.max(top, (top + bottom - legend.height) / 2);
11494
+ }
11495
+ })();
11496
+ return (jsxRuntime.jsxs("svg", { className: styles$2.chart, width: width, height: height, role: "img", "aria-label": chart.Titles.join(" ") || chart.Name, children: [jsxRuntime.jsx(ChartTitles, { titles: chart.Titles, width: width, fontPx: fontPx }), right - left > 10 && bottom - top > 10 && (horizontal ? jsxRuntime.jsx(HorizontalPlot, { ...plotProps }) : jsxRuntime.jsx(VerticalPlot, { ...plotProps })), verticalTitle && (jsxRuntime.jsx("text", { x: titleX, y: (top + bottom) / 2, textAnchor: "middle", dominantBaseline: "central", fontSize: fontPx, transform: `rotate(-90 ${titleX} ${(top + bottom) / 2})`, children: verticalTitle })), horizontalTitle && (jsxRuntime.jsx("text", { x: (left + right) / 2, y: bottom + lineHeight * 1.6, textAnchor: "middle", fontSize: fontPx, children: horizontalTitle })), jsxRuntime.jsx(ChartLegend, { layout: legend, top: legendTop, left: legendLeft, fontPx: fontPx })] }));
11497
+ }
11498
+
11499
+ /** A pie of the chart's first series over its categories (RDL series Type "Shape"). Own SVG. */
11500
+ function CwReportPieChart({ chart, width, height, zoom = 1 }) {
11501
+ const tooltip = useChartTooltip();
11502
+ const fontPx = chartFontPx(zoom);
11503
+ const palette = chartPalette(chart.Palette);
11504
+ const series = chart.Series[0];
11505
+ const colorOf = (index) => palette[index % palette.length];
11506
+ const titleHeight = titlesHeight(chart.Titles, fontPx);
11507
+ const legend = layoutLegend(chart.LegendHidden ? [] : chart.Categories.map((label, index) => ({ label, color: colorOf(index) })), width, fontPx);
11508
+ const legendHeight = legend.height > 0 ? legend.height + fontPx * 0.5 : 0;
11509
+ const slices = series ? pieSlices(series.Values) : [];
11510
+ const message = chart.Error ?? (slices.length === 0 ? (chart.NoRowsMessage ?? "No data") : null);
11511
+ const plotTop = titleHeight + fontPx * 0.5;
11512
+ const plotHeight = height - plotTop - legendHeight;
11513
+ const radius = Math.max(0, Math.min(width, plotHeight) / 2 - fontPx * 0.5);
11514
+ const cx = width / 2;
11515
+ const cy = plotTop + plotHeight / 2;
11516
+ return (jsxRuntime.jsxs("svg", { className: styles$2.chart, width: width, height: height, role: "img", "aria-label": chart.Titles.join(" ") || chart.Name, children: [jsxRuntime.jsx(ChartTitles, { titles: chart.Titles, width: width, fontPx: fontPx }), message ? (jsxRuntime.jsx(ChartMessage, { text: message, width: width, height: height, fontPx: fontPx })) : (slices.map(slice => {
11517
+ const category = chart.Categories[slice.index] ?? "";
11518
+ const percent = `${formatChartValue(slice.fraction * 100)}%`;
11519
+ const labelAt = polar(cx, cy, radius * 0.65, (slice.startAngle + slice.endAngle) / 2);
11520
+ return (jsxRuntime.jsxs("g", { children: [jsxRuntime.jsx("path", { className: styles$2.slice, d: arcPath(cx, cy, radius, 0, slice.startAngle, slice.endAngle), fill: colorOf(slice.index), onMouseEnter: tooltip.show(tooltipContent(series.Name, category, `${formatChartValue(slice.value)} (${percent})`)), onMouseLeave: tooltip.hide }), series.ShowDataLabels && slice.fraction >= 0.03 && (jsxRuntime.jsx("text", { x: labelAt.x, y: labelAt.y, textAnchor: "middle", dominantBaseline: "central", fontSize: fontPx, pointerEvents: "none", children: formatChartValue(slice.value) }))] }, slice.index));
11521
+ })), jsxRuntime.jsx(ChartLegend, { layout: legend, top: height - legend.height, fontPx: fontPx })] }));
11522
+ }
11523
+
11524
+ /** Indent of one list level, in points. */
11525
+ const RDL_LIST_INDENT_PT = 18;
11526
+ const BULLETS = ["•", "◦", "▪"];
11527
+ function listKind(paragraph) {
11528
+ switch ((paragraph.ListStyle ?? "").toLowerCase()) {
11529
+ case "bulleted": return "bulleted";
11530
+ case "numbered": return "numbered";
11531
+ default: return null;
11532
+ }
11533
+ }
11534
+ /**
11535
+ * The list marker of every paragraph (null = no list). Numbering counts consecutive numbered
11536
+ * paragraphs of the same level: a non-list paragraph resets every level, a paragraph at a level
11537
+ * resets the levels below it, and a bulleted paragraph resets the numbering of its own level.
11538
+ */
11539
+ function computeListMarkers(paragraphs) {
11540
+ const counters = [];
11541
+ return paragraphs.map(paragraph => {
11542
+ const kind = listKind(paragraph);
11543
+ if (!kind) {
11544
+ counters.length = 0;
11545
+ return null;
11546
+ }
11547
+ const level = Math.max(1, paragraph.ListLevel);
11548
+ counters.length = Math.min(counters.length, level);
11549
+ if (kind === "bulleted") {
11550
+ counters[level - 1] = 0;
11551
+ return BULLETS[(level - 1) % BULLETS.length];
11552
+ }
11553
+ counters[level - 1] = (counters[level - 1] ?? 0) + 1;
11554
+ return `${counters[level - 1]}.`;
11555
+ });
11556
+ }
11557
+ /** Left indent of a paragraph in points: one list indent per level (a list paragraph has at least level 1). */
11558
+ function paragraphIndentPt(paragraph) {
11559
+ const level = listKind(paragraph) ? Math.max(1, paragraph.ListLevel) : Math.max(0, paragraph.ListLevel);
11560
+ return level * RDL_LIST_INDENT_PT;
11561
+ }
11562
+
11563
+ const EMPTY_FLIPPED = new Set();
11564
+ const EMPTY_HIGHLIGHTS = new Map();
11565
+ const ReportRenderContext = React.createContext({
11566
+ zoom: 1,
11567
+ flipped: EMPTY_FLIPPED,
11568
+ highlights: EMPTY_HIGHLIGHTS,
11569
+ activeMatchIndex: -1
11570
+ });
11571
+ function useReportRender() {
11572
+ return React.useContext(ReportRenderContext);
11573
+ }
11574
+ /** Groups the page's matches by run key. */
11575
+ function highlightsByRun(matches) {
11576
+ const map = new Map();
11577
+ matches.forEach((match, matchIndex) => {
11578
+ const list = map.get(match.key) ?? [];
11579
+ list.push({ start: match.start, length: match.length, matchIndex });
11580
+ map.set(match.key, list);
11581
+ });
11582
+ return map;
11583
+ }
11584
+
11585
+ var styles$1 = {"sheet":"cw-report-page-module__sheet__MAL8a","section":"cw-report-page-module__section__rN7A3","item":"cw-report-page-module__item__VZFw8","table":"cw-report-page-module__table__SAZVC","textbox":"cw-report-page-module__textbox__iwVwk cw-report-page-module__item__VZFw8","textRow":"cw-report-page-module__textRow__3WIRX","textBody":"cw-report-page-module__textBody__Jp1-1","paragraph":"cw-report-page-module__paragraph__d6dYI","marker":"cw-report-page-module__marker__geRQt","link":"cw-report-page-module__link__YFX1h","match":"cw-report-page-module__match__sWdSD","inlineButton":"cw-report-page-module__inlineButton__m05OC","rectangle":"cw-report-page-module__rectangle__2PYyK cw-report-page-module__item__VZFw8","line":"cw-report-page-module__line__Vfus-","image":"cw-report-page-module__image__VEp5H cw-report-page-module__item__VZFw8","tableMessage":"cw-report-page-module__tableMessage__kWsAj","chart":"cw-report-page-module__chart__PP9oM cw-report-page-module__item__VZFw8","placeholder":"cw-report-page-module__placeholder__FK8kO cw-report-page-module__item__VZFw8"};
11586
+
11587
+ /** Size of the drilldown / sort icons, in points: a little below the default 10pt text. */
11588
+ const INLINE_ICON_PT = 9;
11589
+ const SAFE_LINK = /^(https?:|mailto:)/i;
11590
+ function highlightedText(text, highlights, activeMatchIndex) {
11591
+ if (!highlights || highlights.length === 0)
11592
+ return text;
11593
+ const parts = [];
11594
+ let cursor = 0;
11595
+ for (const highlight of highlights) {
11596
+ if (highlight.start > cursor)
11597
+ parts.push(text.slice(cursor, highlight.start));
11598
+ const active = highlight.matchIndex === activeMatchIndex;
11599
+ parts.push(jsxRuntime.jsx("mark", { className: styles$1.match, "data-active": active ? "true" : undefined, "data-active-match": active ? "true" : undefined, children: text.slice(highlight.start, highlight.start + highlight.length) }, highlight.matchIndex));
11600
+ cursor = highlight.start + highlight.length;
11601
+ }
11602
+ if (cursor < text.length)
11603
+ parts.push(text.slice(cursor));
11604
+ return parts;
11605
+ }
11606
+ function ReportRun({ run, runKey, paragraphStyle, textboxStyle }) {
11607
+ const { zoom, highlights, activeMatchIndex } = useReportRender();
11608
+ const css = rdlTextCss(resolveRdlTextStyle(run.Style, paragraphStyle, textboxStyle), zoom);
11609
+ const content = highlightedText(run.Text, highlights.get(runKey), activeMatchIndex);
11610
+ if (run.Href && SAFE_LINK.test(run.Href)) {
11611
+ return (jsxRuntime.jsx("a", { className: styles$1.link, href: run.Href, target: "_blank", rel: "noopener noreferrer", style: css, children: content }));
11612
+ }
11613
+ return jsxRuntime.jsx("span", { style: css, children: content });
11614
+ }
11615
+ function iconSizeStyle(zoom) {
11616
+ return { "--btn-size": `${ptToPx(INLINE_ICON_PT, zoom)}px` };
11617
+ }
11618
+ function sortIcon(direction) {
11619
+ switch ((direction ?? "").toLowerCase()) {
11620
+ case "ascending": return "sort-asc";
11621
+ case "descending": return "sort-desc";
11622
+ default: return "sortable";
11623
+ }
11624
+ }
11625
+ /** A textbox: paragraphs as blocks, runs as inline spans, plain text only (never HTML). */
11626
+ function ReportTextbox({ textbox, itemKey, frameStyle }) {
11627
+ const { zoom, flipped, onToggle, onSort } = useReportRender();
11628
+ const markers = computeListMarkers(textbox.Paragraphs);
11629
+ const paragraphs = textbox.Paragraphs.map((paragraph, p) => {
11630
+ const indent = ptToPx(paragraphIndentPt(paragraph), zoom);
11631
+ const marker = markers[p];
11632
+ const firstRun = paragraph.Runs[0];
11633
+ const paragraphCss = {
11634
+ ...rdlTextCss(resolveParagraphTextStyle(paragraph.Runs.map(run => run.Style), paragraph.Style, textbox.Style), zoom),
11635
+ textAlign: rdlTextAlign(paragraph.Style?.TextAlign ?? textbox.Style?.TextAlign),
11636
+ paddingLeft: indent || undefined
11637
+ };
11638
+ return (jsxRuntime.jsxs("p", { className: styles$1.paragraph, style: paragraphCss, children: [marker !== null && (jsxRuntime.jsx("span", { className: styles$1.marker, style: {
11639
+ ...rdlTextCss(resolveRdlTextStyle(firstRun?.Style, paragraph.Style, textbox.Style), zoom),
11640
+ left: indent - ptToPx(RDL_LIST_INDENT_PT, zoom),
11641
+ width: ptToPx(RDL_LIST_INDENT_PT, zoom)
11642
+ }, children: marker })), paragraph.Runs.map((run, r) => (jsxRuntime.jsx(ReportRun, { run: run, runKey: rdlRunKey(itemKey, p, r), paragraphStyle: paragraph.Style, textboxStyle: textbox.Style }, r)))] }, p));
11643
+ });
11644
+ const boxCss = {
11645
+ ...frameStyle,
11646
+ ...rdlBoxStyle(textbox.Style, zoom),
11647
+ color: rdlColor(textbox.Style?.Color),
11648
+ justifyContent: rdlVerticalAlign(textbox.Style?.VerticalAlign)
11649
+ };
11650
+ const toggleId = textbox.ToggleId;
11651
+ const sortId = textbox.SortId;
11652
+ if (!toggleId && !sortId) {
11653
+ return jsxRuntime.jsx("div", { className: styles$1.textbox, style: boxCss, children: paragraphs });
11654
+ }
11655
+ const expanded = isToggleExpanded(textbox, flipped);
11656
+ return (jsxRuntime.jsx("div", { className: styles$1.textbox, style: boxCss, children: jsxRuntime.jsxs("div", { className: styles$1.textRow, children: [toggleId && (jsxRuntime.jsx(CwButton, { variant: "icon", size: "small", icon: expanded ? "minus" : "plus", className: styles$1.inlineButton, style: iconSizeStyle(zoom), "aria-label": expanded ? "Collapse" : "Expand", "aria-expanded": expanded, "data-toggle-id": toggleId, onClick: () => onToggle?.(toggleId) })), jsxRuntime.jsx("div", { className: styles$1.textBody, children: paragraphs }), sortId && (jsxRuntime.jsx(CwButton, { variant: "icon", size: "small", icon: sortIcon(textbox.SortDirection), className: styles$1.inlineButton, style: iconSizeStyle(zoom), "aria-label": "Sort", onClick: () => onSort?.(sortId) }))] }) }));
11657
+ }
11658
+
11659
+ function frameOf(item) {
11660
+ return { top: item.Top, left: item.Left, width: item.Width, height: item.Height };
11661
+ }
11662
+ function frameCss(frame, zoom) {
11663
+ return {
11664
+ top: ptToPx(frame.top, zoom),
11665
+ left: ptToPx(frame.left, zoom),
11666
+ width: ptToPx(frame.width, zoom),
11667
+ height: ptToPx(frame.height, zoom)
11668
+ };
11669
+ }
11670
+ const SAFE_IMAGE_URL = /^https?:/i;
11671
+ function ReportRectangle({ item, itemKey, frame }) {
11672
+ const { zoom } = useReportRender();
11673
+ return (jsxRuntime.jsx("div", { className: styles$1.rectangle, style: { ...frameCss(frame, zoom), ...rdlBoxStyle(item.Style, zoom) }, children: jsxRuntime.jsx(ReportItems, { items: item.Items, parentKey: itemKey }) }));
11674
+ }
11675
+ function ReportLine({ item, frame }) {
11676
+ const { zoom } = useReportRender();
11677
+ const stroke = rdlLineStroke(item.Style, zoom);
11678
+ const x1 = ptToPx(frame.left, zoom);
11679
+ const y1 = ptToPx(frame.top, zoom);
11680
+ const x2 = ptToPx(frame.left + frame.width, zoom);
11681
+ const y2 = ptToPx(frame.top + frame.height, zoom);
11682
+ const pad = stroke.width;
11683
+ const left = Math.min(x1, x2) - pad;
11684
+ const top = Math.min(y1, y2) - pad;
11685
+ const width = Math.abs(x2 - x1) + pad * 2;
11686
+ const height = Math.abs(y2 - y1) + pad * 2;
11687
+ return (jsxRuntime.jsx("svg", { className: styles$1.line, style: { left, top, width, height }, width: width, height: height, "aria-hidden": "true", children: jsxRuntime.jsx("line", { x1: x1 - left, y1: y1 - top, x2: x2 - left, y2: y2 - top, stroke: stroke.color, strokeWidth: stroke.width, strokeDasharray: stroke.dash }) }));
11688
+ }
11689
+ function imageSizing(sizing) {
11690
+ switch (sizing.toLowerCase()) {
11691
+ case "fit": return "fit";
11692
+ case "fitproportional": return "proportional";
11693
+ default: return "natural";
11694
+ }
11695
+ }
11696
+ function ReportImage({ item, frame }) {
11697
+ const { zoom, getImageUrl } = useReportRender();
11698
+ const src = item.Url && SAFE_IMAGE_URL.test(item.Url)
11699
+ ? item.Url
11700
+ : item.ImageId && getImageUrl ? getImageUrl(item.ImageId) : null;
11701
+ const sizing = imageSizing(item.Sizing);
11702
+ return (jsxRuntime.jsx("div", { className: styles$1.image, style: { ...frameCss(frame, zoom), ...rdlBoxStyle(item.Style, zoom) }, children: src && (jsxRuntime.jsx("img", { src: src, alt: item.Name, referrerPolicy: "no-referrer", "data-sizing": sizing, style: sizing === "natural" ? { transform: `scale(${zoom})` } : undefined })) }));
11703
+ }
11704
+ function ReportTable({ item, itemKey, frame }) {
11705
+ const { zoom, flipped } = useReportRender();
11706
+ const message = item.Error ?? (item.Rows.length === 0 ? item.NoRowsMessage : null);
11707
+ if (message) {
11708
+ const textCss = rdlTextCss(resolveRdlTextStyle(null, null, item.Style), zoom);
11709
+ return (jsxRuntime.jsx("div", { className: styles$1.table, style: { ...frameCss(frame, zoom), height: undefined, ...rdlBoxStyle(item.Style, zoom) }, children: item.Error
11710
+ ? jsxRuntime.jsx(CwNote, { color: "danger", variant: "soft", fontSize: "small", content: item.Error })
11711
+ : jsxRuntime.jsx("p", { className: `${styles$1.tableMessage} cw-margin-none`, style: textCss, children: message }) }));
11712
+ }
11713
+ const layout = layoutRdlTable(item, flipped);
11714
+ return (jsxRuntime.jsx("div", { className: styles$1.table, style: { ...frameCss({ ...frame, width: layout.width, height: layout.height }, zoom), ...rdlBoxStyle(item.Style, zoom) }, children: layout.cells.map(box => {
11715
+ const content = box.cell.Content;
11716
+ if (!content)
11717
+ return null;
11718
+ const cellFrame = { top: box.top, left: box.left, width: box.width, height: box.height };
11719
+ const key = `${box.rowIndex}-${box.cellIndex}`;
11720
+ if (box.hidden) {
11721
+ // Drawn empty: the cell keeps its borders and background so the grid stays closed.
11722
+ return jsxRuntime.jsx("div", { className: styles$1.item, style: { ...frameCss(cellFrame, zoom), ...rdlBoxStyle(content.Style, zoom) } }, key);
11723
+ }
11724
+ return jsxRuntime.jsx(ReportItem, { item: content, itemKey: rdlCellKey(itemKey, box.rowIndex, box.cellIndex), frame: cellFrame }, key);
11725
+ }) }));
11726
+ }
11727
+ function ReportChart({ item, frame }) {
11728
+ const { zoom, culture } = useReportRender();
11729
+ const width = ptToPx(frame.width, zoom);
11730
+ const height = ptToPx(frame.height, zoom);
11731
+ const pie = item.Series[0]?.Type.toLowerCase() === "shape";
11732
+ return (jsxRuntime.jsx("div", { className: styles$1.chart, style: { ...frameCss(frame, zoom), ...rdlBoxStyle(item.Style, zoom) }, children: pie
11733
+ ? jsxRuntime.jsx(CwReportPieChart, { chart: item, width: width, height: height, zoom: zoom })
11734
+ : jsxRuntime.jsx(CwReportLineChart, { chart: item, width: width, height: height, zoom: zoom, culture: culture }) }));
11735
+ }
11736
+ function ReportGauge({ item, frame }) {
11737
+ const { zoom } = useReportRender();
11738
+ return (jsxRuntime.jsx("div", { className: styles$1.chart, style: { ...frameCss(frame, zoom), ...rdlBoxStyle(item.Style, zoom) }, children: jsxRuntime.jsx(CwReportGauge, { panel: item, width: ptToPx(frame.width, zoom), height: ptToPx(frame.height, zoom), zoom: zoom }) }));
11739
+ }
11740
+ function ReportPlaceholder({ item, frame }) {
11741
+ const { zoom } = useReportRender();
11742
+ return (jsxRuntime.jsx(CwTooltipNew, { content: `${item.Element}: ${item.Reason}`, position: "top", children: jsxRuntime.jsx("div", { className: styles$1.placeholder, style: frameCss(frame, zoom), "aria-label": `${item.Element}: ${item.Reason}`, children: item.Element }) }));
11743
+ }
11744
+ /** One render-tree item, absolutely positioned in its container; nothing when its toggles hide it. */
11745
+ function ReportItem({ item, itemKey, frame }) {
11746
+ const { zoom, flipped } = useReportRender();
11747
+ if (!isRdlVisible(item.Toggles, flipped))
11748
+ return null;
11749
+ const box = frame ?? frameOf(item);
11750
+ switch (item.Kind) {
11751
+ case "textbox": return jsxRuntime.jsx(ReportTextbox, { textbox: item, itemKey: itemKey, frameStyle: frameCss(box, zoom) });
11752
+ case "rectangle": return jsxRuntime.jsx(ReportRectangle, { item: item, itemKey: itemKey, frame: box });
11753
+ case "line": return jsxRuntime.jsx(ReportLine, { item: item, frame: box });
11754
+ case "image": return jsxRuntime.jsx(ReportImage, { item: item, frame: box });
11755
+ case "table": return jsxRuntime.jsx(ReportTable, { item: item, itemKey: itemKey, frame: box });
11756
+ case "chart": return jsxRuntime.jsx(ReportChart, { item: item, frame: box });
11757
+ case "gauge": return jsxRuntime.jsx(ReportGauge, { item: item, frame: box });
11758
+ case "placeholder": return jsxRuntime.jsx(ReportPlaceholder, { item: item, frame: box });
11759
+ default: return null;
11760
+ }
11761
+ }
11762
+ function ReportItems({ items, parentKey }) {
11763
+ return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((item, index) => (jsxRuntime.jsx(ReportItem, { item: item, itemKey: rdlItemKey(parentKey, index) }, index))) }));
11764
+ }
11765
+
11766
+ const NO_FLIPS$1 = new Set();
11767
+ const NO_MATCHES = [];
11768
+ const DEFAULT_MARGINS = {
11769
+ top: DEFAULT_PAGE_MARGIN_PT,
11770
+ right: DEFAULT_PAGE_MARGIN_PT,
11771
+ bottom: DEFAULT_PAGE_MARGIN_PT,
11772
+ left: DEFAULT_PAGE_MARGIN_PT
11773
+ };
11774
+ function Band({ section, sectionKey, zoom, bodyWidth, as: Element }) {
11775
+ return (jsxRuntime.jsx(Element, { className: styles$1.section, style: { ...rdlBoxStyle(section.Style, zoom), width: ptToPx(bodyWidth, zoom), height: ptToPx(section.Height, zoom) }, children: jsxRuntime.jsx(ReportItems, { items: section.Items, parentKey: sectionKey }) }));
11776
+ }
11777
+ /**
11778
+ * One page of a rendered RDL report drawn as a sheet of paper: page header, body and page footer,
11779
+ * every item absolutely positioned in points scaled by the zoom. Presentational: toggle state,
11780
+ * sorting, images and find matches come from the host.
11781
+ */
11782
+ function CwReportPage({ page, bodyWidth, zoom = 1, culture, margins = DEFAULT_MARGINS, flippedToggles = NO_FLIPS$1, onToggle, onSort, getImageUrl, findMatches = NO_MATCHES, activeMatchIndex = -1, className }) {
11783
+ const sheetRef = React.useRef(null);
11784
+ const highlights = React.useMemo(() => highlightsByRun(findMatches), [findMatches]);
11785
+ const context = React.useMemo(() => ({
11786
+ zoom,
11787
+ culture,
11788
+ flipped: flippedToggles,
11789
+ onToggle,
11790
+ onSort,
11791
+ getImageUrl,
11792
+ highlights,
11793
+ activeMatchIndex
11794
+ }), [zoom, culture, flippedToggles, onToggle, onSort, getImageUrl, highlights, activeMatchIndex]);
11795
+ React.useEffect(() => {
11796
+ if (activeMatchIndex < 0)
11797
+ return;
11798
+ const active = sheetRef.current?.querySelector("[data-active-match='true']");
11799
+ active?.scrollIntoView?.({ block: "center", inline: "nearest" });
11800
+ }, [activeMatchIndex, findMatches]);
11801
+ const sheet = pageSheetSizePt(page, bodyWidth, margins);
11802
+ return (jsxRuntime.jsx(ReportRenderContext.Provider, { value: context, children: jsxRuntime.jsxs("div", { ref: sheetRef, className: `${styles$1.sheet}${className ? ` ${className}` : ""}`, style: {
11803
+ width: ptToPx(sheet.width, zoom),
11804
+ height: ptToPx(sheet.height, zoom),
11805
+ padding: `${ptToPx(margins.top, zoom)}px ${ptToPx(margins.right, zoom)}px ${ptToPx(margins.bottom, zoom)}px ${ptToPx(margins.left, zoom)}px`
11806
+ }, "data-page": page.Number, children: [page.Header && jsxRuntime.jsx(Band, { section: page.Header, sectionKey: RDL_SECTION_KEYS.header, zoom: zoom, bodyWidth: bodyWidth, as: "header" }), jsxRuntime.jsx("div", { className: styles$1.section, style: { width: ptToPx(bodyWidth, zoom), height: ptToPx(page.Height, zoom) }, children: jsxRuntime.jsx(ReportItems, { items: page.Items, parentKey: RDL_SECTION_KEYS.body }) }), page.Footer && jsxRuntime.jsx(Band, { section: page.Footer, sectionKey: RDL_SECTION_KEYS.footer, zoom: zoom, bodyWidth: bodyWidth, as: "footer" })] }) }));
11807
+ }
11808
+
11809
+ const DATE_PREFIX = /^(\d{4}-\d{2}-\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?/;
11810
+ /** Reads the date and time of an ISO 8601 text (any offset is ignored, the wall clock is kept). Null when it is not a date. */
11811
+ function parseRdlDateTime(text) {
11812
+ const match = DATE_PREFIX.exec(text.trim());
11813
+ if (!match)
11814
+ return null;
11815
+ try {
11816
+ return Temporal.PlainDateTime.from(`${match[1]}T${match[2] ?? "00"}:${match[3] ?? "00"}:${match[4] ?? "00"}`);
11817
+ }
11818
+ catch {
11819
+ return null;
11820
+ }
11821
+ }
11822
+ /** A date-time as invariant text "YYYY-MM-DDTHH:mm:ss". */
11823
+ function formatRdlDateTime(value) {
11824
+ return value.toString({ smallestUnit: "second", calendarName: "never" });
11825
+ }
11826
+ /** A typed API value as the text of an option or an editor (null stays null). */
11827
+ function rdlValueToText(value) {
11828
+ if (value === null || value === undefined)
11829
+ return null;
11830
+ if (typeof value === "boolean")
11831
+ return value ? "true" : "false";
11832
+ if (typeof value === "number")
11833
+ return numberToInvariant(value);
11834
+ return value;
11835
+ }
11836
+ function numberToInvariant(value) {
11837
+ return Number.isFinite(value) ? value.toString() : "";
11838
+ }
11839
+ function isDateTime(parameter) {
11840
+ return parameter.DataType.toLowerCase() === "datetime" || parameter.InputType.toLowerCase() === "datetime";
11841
+ }
11842
+ function isBoolean(parameter) {
11843
+ return parameter.DataType.toLowerCase() === "boolean" || parameter.InputType.toLowerCase() === "boolean";
11844
+ }
11845
+ function isTextInput(parameter) {
11846
+ return parameter.InputType.toLowerCase() === "textbox";
11847
+ }
11848
+ function isNumeric(parameter) {
11849
+ const type = parameter.DataType.toLowerCase();
11850
+ return type === "integer" || type === "float";
11851
+ }
11852
+ function toEditorScalar(parameter, value) {
11853
+ if (isDateTime(parameter) && parameter.InputType.toLowerCase() !== "dropdownlist") {
11854
+ const text = String(value);
11855
+ return parseRdlDateTime(text) ?? text;
11856
+ }
11857
+ if (isBoolean(parameter) && parameter.InputType.toLowerCase() !== "dropdownlist") {
11858
+ return typeof value === "boolean" ? value : String(value).toLowerCase() === "true";
11859
+ }
11860
+ return rdlValueToText(value) ?? "";
11861
+ }
11862
+ /** The editor state of one parameter from the values the server sent; a NULL value is an empty field. */
11863
+ function initialParameterEdit(parameter) {
11864
+ const scalars = (parameter.Values ?? [])
11865
+ .filter((value) => value !== null && value !== undefined)
11866
+ .map(value => toEditorScalar(parameter, value));
11867
+ return { values: parameter.MultiValue ? scalars : scalars.slice(0, 1) };
11868
+ }
11869
+ /** The values that count: a multi-value text drops its empty lines, a single value keeps only the first. */
11870
+ function enteredValues(parameter, edit) {
11871
+ const values = edit.values.filter(value => value !== "");
11872
+ return parameter.MultiValue ? values : values.slice(0, 1);
11873
+ }
11874
+ /** The editor state of a whole form. */
11875
+ function initialParameterEdits(parameters) {
11876
+ const edits = {};
11877
+ for (const parameter of parameters)
11878
+ edits[parameter.Name] = initialParameterEdit(parameter);
11879
+ return edits;
11880
+ }
11881
+ /** One editor value as invariant text. */
11882
+ function editorScalarToInvariant(parameter, value) {
11883
+ if (typeof value === "boolean")
11884
+ return value ? "true" : "false";
11885
+ if (typeof value !== "string")
11886
+ return formatRdlDateTime(value);
11887
+ if (isNumeric(parameter))
11888
+ return value.trim().replace(",", ".");
11889
+ return value;
11890
+ }
11891
+ /**
11892
+ * The values the API takes (RdlParameterValuesRequest.Values): every parameter, each as an array of
11893
+ * invariant text. An empty field is [null] when the parameter is nullable, [""] for a single text,
11894
+ * else []. A parameter without an edit sends the values the server gave it.
11895
+ *
11896
+ * A nullable boolean whose value is NULL shows neither True nor False and keeps sending NULL until
11897
+ * the user picks one; from then on it sends "true" / "false" (a radio group cannot be emptied again).
11898
+ */
11899
+ function toRdlParameterValues(parameters, edits) {
11900
+ const result = {};
11901
+ for (const parameter of parameters) {
11902
+ const edit = edits[parameter.Name] ?? initialParameterEdit(parameter);
11903
+ const texts = enteredValues(parameter, edit).map(value => editorScalarToInvariant(parameter, value));
11904
+ if (texts.length > 0) {
11905
+ result[parameter.Name] = texts;
11906
+ }
11907
+ else if (parameter.Nullable) {
11908
+ result[parameter.Name] = [null];
11909
+ }
11910
+ else {
11911
+ result[parameter.Name] = !parameter.MultiValue && isTextInput(parameter) ? [""] : [];
11912
+ }
11913
+ }
11914
+ return result;
11915
+ }
11916
+ /** True when any other parameter lists `name` in its DependsOn: a change must re-resolve the form. */
11917
+ function hasDependentParameters(parameters, name) {
11918
+ return parameters.some(parameter => parameter.Name !== name && parameter.DependsOn.includes(name));
11919
+ }
11920
+ /** Whether the user edits the parameter (hidden and server-filled parameters are not editable). */
11921
+ function isEditableParameter(parameter) {
11922
+ return !parameter.Hidden && !parameter.ServerValue;
11923
+ }
11924
+ /** Whether the form has anything for the user to fill in (some parameter is neither hidden nor server-filled). */
11925
+ function hasEditableParameters(parameters) {
11926
+ return parameters.some(isEditableParameter);
11927
+ }
11928
+ /**
11929
+ * Client-side checks before "View report": a value is required unless the parameter is nullable
11930
+ * (empty = NULL) or allows blank text (AllowBlank), and numbers / dates must parse. Hidden and
11931
+ * server-filled parameters are the server's business. Returns parameter name to message.
11932
+ */
11933
+ function validateParameterEdits(parameters, edits) {
11934
+ const errors = {};
11935
+ for (const parameter of parameters) {
11936
+ if (!isEditableParameter(parameter))
11937
+ continue;
11938
+ const edit = edits[parameter.Name] ?? initialParameterEdit(parameter);
11939
+ const values = enteredValues(parameter, edit);
11940
+ if (values.length === 0) {
11941
+ const blankAllowed = parameter.Nullable
11942
+ || (parameter.AllowBlank && !parameter.MultiValue && isTextInput(parameter) && !isNumeric(parameter));
11943
+ if (!blankAllowed)
11944
+ errors[parameter.Name] = parameter.MultiValue ? "Select at least one value." : "A value is required.";
11945
+ continue;
11946
+ }
11947
+ if (isNumeric(parameter) && parameter.InputType.toLowerCase() !== "dropdownlist") {
11948
+ const integer = parameter.DataType.toLowerCase() === "integer";
11949
+ const invalid = values.some(value => {
11950
+ const text = editorScalarToInvariant(parameter, value);
11951
+ return integer ? !/^-?\d+$/.test(text) : !/^-?(\d+\.?\d*|\.\d+)$/.test(text);
11952
+ });
11953
+ if (invalid)
11954
+ errors[parameter.Name] = integer ? "Enter a whole number." : "Enter a number.";
11955
+ continue;
11956
+ }
11957
+ if (isDateTime(parameter) && parameter.InputType.toLowerCase() !== "dropdownlist"
11958
+ && values.some(value => typeof value === "string")) {
11959
+ errors[parameter.Name] = "Enter a valid date.";
11960
+ }
11961
+ }
11962
+ return errors;
11963
+ }
11964
+
11965
+ var styles = {"viewer":"cw-report-viewer-module__viewer__SYHSE","sidebar":"cw-report-viewer-module__sidebar__1ZSM2","resizer":"cw-report-viewer-module__resizer__JdnQI","main":"cw-report-viewer-module__main__qsPXX","parameterForm":"cw-report-viewer-module__parameterForm__H01sS","parameterFields":"cw-report-viewer-module__parameterFields__D2BuK","parameterActions":"cw-report-viewer-module__parameterActions__01RD4","viewButton":"cw-report-viewer-module__viewButton__1CMHL","parameterGrid":"cw-report-viewer-module__parameterGrid__Jyn0M","toolbar":"cw-report-viewer-module__toolbar__9gKXV","reportName":"cw-report-viewer-module__reportName__g5nsm","findStatus":"cw-report-viewer-module__findStatus__4gLGb","warningsButton":"cw-report-viewer-module__warningsButton__GIKjH","warningsPanel":"cw-report-viewer-module__warningsPanel__rFHBP","warningList":"cw-report-viewer-module__warningList__Ouk7x","menu":"cw-report-viewer-module__menu__ufxUU","menuItem":"cw-report-viewer-module__menuItem__hBmdD","canvas":"cw-report-viewer-module__canvas__9KuUT","canvasNote":"cw-report-viewer-module__canvasNote__K9XP0","sheetSkeleton":"cw-report-viewer-module__sheetSkeleton__DsSaA","emptyState":"cw-report-viewer-module__emptyState__pJyQ1"};
11966
+
11967
+ /** Above this many options a single-select dropdown gets a search box. */
11968
+ const SEARCH_THRESHOLD = 10;
11969
+ const LABEL_LAYOUT = { flexDirection: "column" };
11970
+ const BOOLEAN_OPTIONS = [
11971
+ { value: "true", label: "True" },
11972
+ { value: "false", label: "False" }
11973
+ ];
11974
+ function scalarText(value) {
11975
+ if (value === undefined)
11976
+ return "";
11977
+ if (typeof value === "boolean")
11978
+ return value ? "true" : "false";
11979
+ return typeof value === "string" ? value : value.toString();
11980
+ }
11981
+ function feedbackFor(parameter, clientError) {
11982
+ const messages = [];
11983
+ if (parameter.ValidValuesError)
11984
+ messages.push({ type: "danger", message: parameter.ValidValuesError });
11985
+ if (parameter.ValueError)
11986
+ messages.push({ type: "danger", message: parameter.ValueError });
11987
+ if (clientError)
11988
+ messages.push({ type: "danger", message: clientError });
11989
+ return messages.length > 0 ? messages : undefined;
11990
+ }
11991
+ function ParameterField({ parameter, edit, error, disabled, setEdit, commit }) {
11992
+ const label = { text: parameter.Prompt || parameter.Name };
11993
+ const feedback = feedbackFor(parameter, error);
11994
+ const testId = `report-parameter-${parameter.Name}`;
11995
+ // A NULL valid value is no option of its own: leaving the field empty is NULL.
11996
+ const options = parameter.ValidValues
11997
+ .filter(option => option.Value !== null && option.Value !== undefined)
11998
+ .map(option => ({ value: rdlValueToText(option.Value) ?? "", label: option.Label }));
11999
+ switch (parameter.InputType.toLowerCase()) {
12000
+ case "dropdownlist":
12001
+ if (parameter.MultiValue) {
12002
+ return (jsxRuntime.jsx(CwTagSelector, { id: testId, labelProps: label, alignProps: LABEL_LAYOUT, options: options, value: edit.values.map(scalarText), onChange: values => setEdit({ values }, true), showSelectAll: true, disabled: disabled, feedback: feedback }));
12003
+ }
12004
+ return (jsxRuntime.jsx(CwDropdown, { "data-testid": testId, labelProps: label, alignProps: LABEL_LAYOUT, options: options, value: scalarText(edit.values[0]), onChange: value => setEdit({ values: value === undefined ? [] : [String(value)] }, true), allowSearch: options.length > SEARCH_THRESHOLD, disabled: disabled, feedback: feedback }));
12005
+ case "datetime": {
12006
+ const value = edit.values[0];
12007
+ return (jsxRuntime.jsx(CwDateTimePickerTemporal, { "data-testid": testId, labelProps: label, alignProps: LABEL_LAYOUT, value: value instanceof Temporal.PlainDateTime ? value : undefined, onChange: dateTime => setEdit({ values: dateTime ? [dateTime] : [] }, true), disabled: disabled, feedback: feedback }));
12008
+ }
12009
+ case "boolean":
12010
+ return (jsxRuntime.jsx(CwRadioGroup, { "data-testid": testId, labelProps: label, groupLayout: { direction: "row" }, options: BOOLEAN_OPTIONS, value: edit.values.length > 0 ? scalarText(edit.values[0]) : undefined, onChange: value => setEdit({ values: [value === "true"] }, true), disabled: disabled, feedback: feedback }));
12011
+ case "integer":
12012
+ case "float":
12013
+ return (jsxRuntime.jsx(CwDigit, { "data-testid": testId, labelProps: label, alignProps: LABEL_LAYOUT, step: parameter.InputType.toLowerCase() === "integer" ? 1 : "any", value: scalarText(edit.values[0]), onChange: e => {
12014
+ const text = e.currentTarget.value;
12015
+ setEdit({ values: text === "" ? [] : [text] }, false);
12016
+ }, onBlur: commit, disabled: disabled, feedback: feedback }));
12017
+ default:
12018
+ if (parameter.MultiValue) {
12019
+ return (jsxRuntime.jsx(CwTextArea, { "data-testid": testId, labelProps: label, alignProps: LABEL_LAYOUT, value: edit.values.map(scalarText).join("\n"), onChange: e => {
12020
+ // Keep empty lines while typing (Enter must survive the re-render); they are dropped on serialization.
12021
+ setEdit({ values: e.currentTarget.value.split("\n") }, false);
12022
+ }, onBlur: commit, disabled: disabled, feedback: feedback ?? { type: "neutral", message: "One value per line." } }));
12023
+ }
12024
+ return (jsxRuntime.jsx(CwInputText, { "data-testid": testId, labelProps: label, alignProps: LABEL_LAYOUT, value: scalarText(edit.values[0]), onChange: e => {
12025
+ const text = e.currentTarget.value;
12026
+ setEdit({ values: [text] }, false);
12027
+ }, onBlur: commit, disabled: disabled, feedback: feedback }));
12028
+ }
12029
+ }
12030
+ /**
12031
+ * The report parameter form in the server's order: dropdowns (multi-value as tag selector with
12032
+ * select-all), date-time pickers, True/False, numbers and text. There is no NULL control: an empty
12033
+ * field of a nullable parameter is sent as NULL (see rdlParameterValues), as in the old WinOps
12034
+ * report page. Hidden parameters are not drawn; server-filled ones are read-only. Presentational:
12035
+ * the host owns the editor state (`useReportParameterForm`); a change to a parameter others depend
12036
+ * on calls its `onResolve`, "View report" its `onRender` with the values as invariant text
12037
+ * (`toRdlParameterValues`).
12038
+ *
12039
+ * The form fills its parent's height when the parent gives it one: the fields scroll and the
12040
+ * "View report" footer stays pinned at the bottom. In an unbounded parent it simply grows.
12041
+ */
12042
+ function CwReportParameterForm({ controller, loading = false, rendering = false }) {
12043
+ const { form } = controller;
12044
+ const visible = form?.Parameters.filter(parameter => !parameter.Hidden) ?? [];
12045
+ return (jsxRuntime.jsxs("form", { className: styles.parameterForm, "data-testid": "report-parameter-form", onSubmit: e => {
12046
+ e.preventDefault();
12047
+ controller.submit();
12048
+ }, children: [jsxRuntime.jsx("div", { className: styles.parameterFields, children: form ? (jsxRuntime.jsx(CwLoading, { isLoading: loading, size: "small", children: visible.length > 0 && (jsxRuntime.jsx("div", { className: `${styles.parameterGrid} cw-grid-base-auto`, children: visible.map(parameter => (jsxRuntime.jsx(ParameterField, { parameter: parameter, edit: controller.edits[parameter.Name] ?? { values: [] }, error: controller.errors[parameter.Name], disabled: loading || !!parameter.ServerValue, setEdit: (edit, commit) => controller.setEdit(parameter.Name, edit, commit), commit: () => controller.commit(parameter.Name) }, parameter.Name))) })) })) : (jsxRuntime.jsxs("div", { className: `${styles.parameterGrid} cw-grid-base-auto`, "aria-busy": "true", children: [jsxRuntime.jsx(CwSkeleton, { variant: "rect", height: "3.5rem" }), jsxRuntime.jsx(CwSkeleton, { variant: "rect", height: "3.5rem" }), jsxRuntime.jsx(CwSkeleton, { variant: "rect", height: "3.5rem" })] })) }), jsxRuntime.jsx("footer", { className: styles.parameterActions, children: jsxRuntime.jsx(CwButton, { type: "submit", text: "View report", icon: "file-view", className: styles.viewButton, disabled: !form || loading || rendering, "data-testid": "report-view-button" }) })] }));
12049
+ }
12050
+
12051
+ const REPORT_EXPORT_LABELS = {
12052
+ pdf: "PDF",
12053
+ xlsx: "Excel",
12054
+ docx: "Word"
12055
+ };
12056
+ /** A render with warnings asks before exporting or printing; without warnings the action runs at once. */
12057
+ function needsOutputConfirmation(warnings) {
12058
+ return (warnings?.length ?? 0) > 0;
12059
+ }
12060
+ /** Texts of the confirmation shown before an export or print of a render with warnings. */
12061
+ function outputConfirmation(action, warningCount) {
12062
+ const count = `${warningCount} warning${warningCount === 1 ? "" : "s"}`;
12063
+ if (action.kind === "print") {
12064
+ return {
12065
+ headline: "Print report",
12066
+ message: `This report has ${count}. The printout may not match the report exactly.`,
12067
+ confirmText: "Print anyway"
12068
+ };
12069
+ }
12070
+ const label = REPORT_EXPORT_LABELS[action.format];
12071
+ return {
12072
+ headline: `Export as ${label}`,
12073
+ message: `This report has ${count}. The ${label} export may not match the report exactly.`,
12074
+ confirmText: "Export anyway"
12075
+ };
12076
+ }
12077
+
12078
+ const EXPORTS = [
12079
+ { format: "pdf", label: REPORT_EXPORT_LABELS.pdf, icon: "file-pdf" },
12080
+ { format: "xlsx", label: REPORT_EXPORT_LABELS.xlsx, icon: "table" },
12081
+ { format: "docx", label: REPORT_EXPORT_LABELS.docx, icon: "document" }
12082
+ ];
12083
+ function zoomToValue(zoom) {
12084
+ return typeof zoom === "number" ? String(zoom) : zoom;
12085
+ }
12086
+ function valueToZoom(value) {
12087
+ if (value === "pageWidth" || value === "wholePage")
12088
+ return value;
12089
+ const factor = parseFloat(value);
12090
+ return Number.isFinite(factor) && factor > 0 ? factor : 1;
12091
+ }
12092
+ function closePopover(element) {
12093
+ element.closest("[popover]")?.hidePopover();
12094
+ }
12095
+ function PageInput({ pageNumber, pageCount, onPage, disabled }) {
12096
+ const [draft, setDraft] = React.useState({ page: pageNumber, text: String(pageNumber) });
12097
+ const text = draft.page === pageNumber ? draft.text : String(pageNumber);
12098
+ const commit = () => {
12099
+ const parsed = parseInt(text, 10);
12100
+ const target = Number.isFinite(parsed) ? Math.min(Math.max(1, parsed), Math.max(1, pageCount)) : pageNumber;
12101
+ setDraft({ page: pageNumber, text: String(target) });
12102
+ if (target !== pageNumber)
12103
+ onPage(target);
12104
+ };
12105
+ return (jsxRuntime.jsx(CwDigit, { "data-size": "tiny", "aria-label": "Page", min: 1, max: Math.max(1, pageCount), value: text, disabled: disabled, onChange: e => {
12106
+ const value = e.currentTarget.value;
12107
+ setDraft({ page: pageNumber, text: value });
12108
+ }, onKeyDown: (e) => {
12109
+ if (e.key === "Enter")
12110
+ commit();
12111
+ }, onBlur: commit }));
12112
+ }
12113
+ /**
12114
+ * The report viewer toolbar, like the old ReportViewer: page navigation, refresh, back, zoom,
12115
+ * find on the current page, export (PDF / Excel / Word) and print. Warnings stay invisible until
12116
+ * there are some (Dark Cockpit). Presentational: every action is a callback.
12117
+ */
12118
+ function CwReportToolbar({ pageNumber, pageCount, onPage, onRefresh, onBack, zoom, onZoomChange, findText, onFindTextChange, onFindNext, findMatchCount, findMatchIndex, onExport, onPrint, warnings = [], onToggleParameters, parametersVisible = true, disabled = false, reportName }) {
12119
+ const firstPage = disabled || pageNumber <= 1;
12120
+ const lastPage = disabled || pageNumber >= pageCount;
12121
+ const findStatus = findText.trim() === ""
12122
+ ? ""
12123
+ : findMatchCount === 0 ? "No matches" : `${Math.max(0, findMatchIndex) + 1} of ${findMatchCount}`;
12124
+ return (jsxRuntime.jsxs("header", { className: `${styles.toolbar} cw-flex-row cw-align-left-center cw-flex-wrap cw-gap-small`, "data-testid": "report-toolbar", children: [onBack && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "arrow-left", title: "Back", onClick: onBack }), onToggleParameters && (jsxRuntime.jsx(CwButton, { variant: "icon", icon: "filter-list", title: parametersVisible ? "Hide parameters" : "Show parameters", pressed: parametersVisible, onClick: onToggleParameters })), jsxRuntime.jsxs("nav", { className: "cw-flex-row cw-align-left-center cw-gap-tiny", "aria-label": "Pages", children: [jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-left-double", title: "First page", disabled: firstPage, onClick: () => onPage(1) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-left", title: "Previous page", disabled: firstPage, onClick: () => onPage(pageNumber - 1) }), jsxRuntime.jsx(PageInput, { pageNumber: pageNumber, pageCount: pageCount, onPage: onPage, disabled: disabled }), jsxRuntime.jsxs("span", { className: "cw-font-size-small", children: ["of ", disabled ? "-" : pageCount] }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-right", title: "Next page", disabled: lastPage, onClick: () => onPage(pageNumber + 1) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "chevron-right-double", title: "Last page", disabled: lastPage, onClick: () => onPage(pageCount) })] }), onRefresh && jsxRuntime.jsx(CwButton, { variant: "icon", icon: "refresh", title: "Refresh", disabled: disabled, onClick: onRefresh }), jsxRuntime.jsxs(CwSelect, { "aria-label": "Zoom", value: zoomToValue(zoom), handleChange: value => onZoomChange(valueToZoom(value)), children: [REPORT_ZOOM_STEPS.map(step => (jsxRuntime.jsx(CwOption, { value: String(step), text: `${Math.round(step * 100)}%` }, step))), jsxRuntime.jsx(CwOption, { value: "pageWidth", text: "Page width" }), jsxRuntime.jsx(CwOption, { value: "wholePage", text: "Whole page" })] }), jsxRuntime.jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsxRuntime.jsx(CwInputText, { "aria-label": "Find text", placeholder: "Find", value: findText, disabled: disabled, onChange: e => onFindTextChange(e.currentTarget.value), onKeyDown: (e) => {
12125
+ if (e.key === "Enter")
12126
+ onFindNext();
12127
+ }, buttonProps: {
12128
+ text: "Next",
12129
+ variant: "outline",
12130
+ disabled: disabled || findMatchCount === 0,
12131
+ onClick: onFindNext
12132
+ } }), jsxRuntime.jsx("span", { className: `${styles.findStatus} cw-font-size-small`, "aria-live": "polite", children: findStatus })] }), jsxRuntime.jsx("div", { className: styles.reportName, children: reportName && (jsxRuntime.jsx(CwTooltipNew, { content: reportName, position: "bottom", children: jsxRuntime.jsx("strong", { className: "cw-text-ellipsis", "data-testid": "report-name", children: reportName }) })) }), warnings.length > 0 && (jsxRuntime.jsx(CwPopoverButton, { variant: "icon", icon: "warning", title: "Warnings", badge: { count: warnings.length, color: "warning" }, className: styles.warningsButton, placement: "bottom-end", panelClassName: styles.warningsPanel, children: jsxRuntime.jsx("ul", { className: styles.warningList, children: warnings.map((warning, index) => jsxRuntime.jsx("li", { children: warning }, index)) }) })), jsxRuntime.jsx(CwPopoverButton, { icon: "download", title: "Export", variant: "icon", disabled: disabled, placement: "bottom-end", children: jsxRuntime.jsx("div", { className: styles.menu, children: EXPORTS.map(item => (jsxRuntime.jsx(CwButton, { variant: "ghost", color: "neutral", text: item.label, icon: item.icon, className: styles.menuItem, onClick: e => {
12133
+ closePopover(e.currentTarget);
12134
+ onExport(item.format);
12135
+ } }, item.format))) }) }), jsxRuntime.jsx(CwButton, { variant: "icon", icon: "print", title: "Print", disabled: disabled, onClick: onPrint })] }));
12136
+ }
12137
+
12138
+ /** Width change of one arrow key press on the sidebar resize handle, in CSS pixels. */
12139
+ const SIDEBAR_KEY_STEP = 16;
12140
+ /** Keeps a sidebar width inside [min, max]; a max below min collapses to min. */
12141
+ function clampSidebarWidth(width, min, max) {
12142
+ const upper = Math.max(min, max);
12143
+ if (!Number.isFinite(width))
12144
+ return min;
12145
+ return Math.min(Math.max(width, min), upper);
12146
+ }
12147
+ /**
12148
+ * The sidebar width after a key press on the resize handle: arrows step, Home / End jump to the
12149
+ * bounds. Null for keys the handle does not use, so they keep their default behaviour.
12150
+ */
12151
+ function sidebarWidthForKey(key, current, min, max, step = SIDEBAR_KEY_STEP) {
12152
+ switch (key) {
12153
+ case "ArrowLeft":
12154
+ return clampSidebarWidth(current - step, min, max);
12155
+ case "ArrowRight":
12156
+ return clampSidebarWidth(current + step, min, max);
12157
+ case "Home":
12158
+ return clampSidebarWidth(min, min, max);
12159
+ case "End":
12160
+ return clampSidebarWidth(max, min, max);
12161
+ default:
12162
+ return null;
12163
+ }
12164
+ }
12165
+ /**
12166
+ * Whether the viewer shows the parameter sidebar. While the form loads for the first time it shows
12167
+ * the skeleton; once loaded only when the user has something to fill in. A report whose parameters
12168
+ * are all hidden or server-filled (or that has none) gets no sidebar.
12169
+ */
12170
+ function showsParameterSidebar(parameters, loadingParameters) {
12171
+ return parameters ? hasEditableParameters(parameters.Parameters) : loadingParameters;
12172
+ }
12173
+
12174
+ /**
12175
+ * Width of a left sidebar resized by dragging the handle on its right edge, like the master panel
12176
+ * of CwMasterDetail. The handle captures the pointer, so the drag keeps going outside it; the
12177
+ * keyboard steps the width for users who cannot drag.
12178
+ */
12179
+ function useSidebarResize(initialWidth, minWidth, maxWidth) {
12180
+ const [storedWidth, setStoredWidth] = React.useState(initialWidth);
12181
+ const [resizing, setResizing] = React.useState(false);
12182
+ const drag = React.useRef(null);
12183
+ const width = clampSidebarWidth(storedWidth, minWidth, maxWidth);
12184
+ const onPointerDown = React.useCallback((e) => {
12185
+ if (e.button !== 0)
12186
+ return;
12187
+ e.preventDefault();
12188
+ e.currentTarget.setPointerCapture(e.pointerId);
12189
+ drag.current = { startX: e.clientX, startWidth: width };
12190
+ setResizing(true);
12191
+ }, [width]);
12192
+ const onPointerMove = React.useCallback((e) => {
12193
+ const start = drag.current;
12194
+ if (!start)
12195
+ return;
12196
+ setStoredWidth(clampSidebarWidth(start.startWidth + e.clientX - start.startX, minWidth, maxWidth));
12197
+ }, [minWidth, maxWidth]);
12198
+ const endDrag = React.useCallback((e) => {
12199
+ if (!drag.current)
12200
+ return;
12201
+ drag.current = null;
12202
+ if (e.currentTarget.hasPointerCapture(e.pointerId))
12203
+ e.currentTarget.releasePointerCapture(e.pointerId);
12204
+ setResizing(false);
12205
+ }, []);
12206
+ const onKeyDown = React.useCallback((e) => {
12207
+ const next = sidebarWidthForKey(e.key, width, minWidth, maxWidth);
12208
+ if (next === null)
12209
+ return;
12210
+ e.preventDefault();
12211
+ setStoredWidth(next);
12212
+ }, [width, minWidth, maxWidth]);
12213
+ return {
12214
+ width,
12215
+ resizing,
12216
+ handleProps: { onPointerDown, onPointerMove, onPointerUp: endDrag, onPointerCancel: endDrag, onKeyDown }
12217
+ };
12218
+ }
12219
+
12220
+ /** Space the canvas keeps around the sheet when fitting it (its padding on both sides), in CSS pixels. */
12221
+ const CANVAS_GUTTER = 32;
12222
+ function useElementSize(ref) {
12223
+ const [size, setSize] = React.useState({ width: 0, height: 0 });
12224
+ React.useEffect(() => {
12225
+ const element = ref.current;
12226
+ if (!element || typeof ResizeObserver === "undefined")
12227
+ return;
12228
+ const observer = new ResizeObserver(() => {
12229
+ setSize({ width: element.clientWidth, height: element.clientHeight });
12230
+ });
12231
+ observer.observe(element);
12232
+ return () => observer.disconnect();
12233
+ }, [ref]);
12234
+ return size;
12235
+ }
12236
+ /**
12237
+ * The RDL report viewer: a resizable, collapsible parameter sidebar on the left, the toolbar and
12238
+ * the page on a neutral canvas on the right, like the old ReportViewer. The sidebar only exists
12239
+ * when the user has a parameter to fill in. Presentational: it fetches nothing and owns no report
12240
+ * state. The host calls `useReportViewerState` and `useReportParameterForm` and passes their results
12241
+ * as `state` and `parameterForm`; every request goes out through the callbacks given to those hooks
12242
+ * (or `onSort` / `onRefresh` / `onBack`) and comes back as their arguments.
12243
+ */
12244
+ function CwReportViewer({ definition, state, parameterForm, loadingParameters = false, loadingRender = false, error, onSort, onRefresh, onBack, getImageUrl, sidebarWidth = 320, minSidebarWidth = 240, maxSidebarWidth = 600, resizable = true, className }) {
12245
+ const { result } = state;
12246
+ const parameters = parameterForm.form;
12247
+ const sidebar = useSidebarResize(sidebarWidth, minSidebarWidth, maxSidebarWidth);
12248
+ const canvasRef = React.useRef(null);
12249
+ const canvasSize = useElementSize(canvasRef);
12250
+ const hasSidebar = showsParameterSidebar(parameters, loadingParameters);
12251
+ const sidebarOpen = hasSidebar && state.parametersVisible;
12252
+ const warnings = result?.Warnings ?? [];
12253
+ const reportName = result?.Name || definition?.Name || null;
12254
+ const confirmation = state.pendingOutput ? outputConfirmation(state.pendingOutput, warnings.length) : null;
12255
+ /** Where the clicked toggle sat in the canvas, so the re-rendered page keeps it in the same place. */
12256
+ const toggleAnchorRef = React.useRef(null);
12257
+ const handleToggle = (toggleId) => {
12258
+ if (state.serverToggles) {
12259
+ const canvas = canvasRef.current;
12260
+ const button = canvas?.querySelector(`[data-toggle-id="${CSS.escape(toggleId)}"]`);
12261
+ toggleAnchorRef.current = canvas && button
12262
+ ? { toggleId, offset: button.getBoundingClientRect().top - canvas.getBoundingClientRect().top }
12263
+ : null;
12264
+ }
12265
+ state.toggle(toggleId);
12266
+ };
12267
+ React.useLayoutEffect(() => {
12268
+ const anchor = toggleAnchorRef.current;
12269
+ const canvas = canvasRef.current;
12270
+ if (!anchor || !canvas || !result)
12271
+ return;
12272
+ toggleAnchorRef.current = null;
12273
+ const button = canvas.querySelector(`[data-toggle-id="${CSS.escape(anchor.toggleId)}"]`);
12274
+ if (button)
12275
+ canvas.scrollTop += button.getBoundingClientRect().top - canvas.getBoundingClientRect().top - anchor.offset;
12276
+ }, [result]);
12277
+ // Without a sidebar (nothing to fill in) the form's "View report" lives on the canvas instead.
12278
+ const runButton = !hasSidebar && parameters && !result ? (jsxRuntime.jsx(CwButton, { text: "View report", icon: "file-view", disabled: loadingParameters || loadingRender, onClick: parameterForm.submit, "data-testid": "report-view-button" })) : null;
12279
+ const zoomFactor = result
12280
+ ? resolveZoomFactor(state.zoom, pageSheetSizePt(result.Page, result.BodyWidth, SCREEN_PAGE_MARGINS), { width: canvasSize.width - CANVAS_GUTTER, height: canvasSize.height - CANVAS_GUTTER })
12281
+ : 1;
12282
+ const renderCanvas = () => {
12283
+ if (error) {
12284
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(CwNote, { color: "danger", variant: "soft", icon: "warning", content: error, className: styles.canvasNote }), runButton] }));
12285
+ }
12286
+ if (!result) {
12287
+ if (loadingRender) {
12288
+ return (jsxRuntime.jsx("div", { className: styles.sheetSkeleton, "aria-busy": "true", children: jsxRuntime.jsx(CwSkeleton, { variant: "text", count: 14 }) }));
12289
+ }
12290
+ return (jsxRuntime.jsxs("div", { className: `${styles.emptyState} cw-flex-column cw-align-center-center cw-gap-small`, children: [jsxRuntime.jsx(CwIcon, { iconId: "file-report", size: "huge", color: "neutral" }), jsxRuntime.jsx("p", { className: "cw-margin-none", children: hasSidebar ? "Set the parameters and select View report." : "Select View report to run the report." }), runButton] }));
12291
+ }
12292
+ return (jsxRuntime.jsx(CwLoading, { isLoading: loadingRender, children: jsxRuntime.jsx(CwReportPage, { page: result.Page, bodyWidth: result.BodyWidth, zoom: zoomFactor, culture: result.Culture, margins: SCREEN_PAGE_MARGINS, flippedToggles: state.drawnFlips, onToggle: handleToggle, onSort: onSort, getImageUrl: getImageUrl, findMatches: state.findMatches, activeMatchIndex: state.findIndex }) }));
12293
+ };
12294
+ return (jsxRuntime.jsxs("section", { className: `${styles.viewer}${className ? ` ${className}` : ""}`, "aria-label": result?.Name ?? definition?.Name ?? "Report", "data-resizing": sidebar.resizing || undefined, "data-testid": "report-viewer", children: [sidebarOpen && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("aside", { className: styles.sidebar, style: { width: sidebar.width }, "aria-label": "Report parameters", "data-testid": "report-parameter-sidebar", children: jsxRuntime.jsx(CwReportParameterForm, { controller: parameterForm, loading: loadingParameters, rendering: loadingRender }) }), resizable && (jsxRuntime.jsx("div", { className: styles.resizer, role: "separator", "aria-orientation": "vertical", "aria-label": "Resize parameters", "aria-valuenow": sidebar.width, "aria-valuemin": minSidebarWidth, "aria-valuemax": Math.max(minSidebarWidth, maxSidebarWidth), tabIndex: 0, "data-resizing": sidebar.resizing, ...sidebar.handleProps }))] })), jsxRuntime.jsxs("div", { className: styles.main, children: [jsxRuntime.jsx(CwReportToolbar, { pageNumber: result?.Page.Number ?? 1, pageCount: result?.PageCount ?? 1, onPage: state.goToPage, onRefresh: onRefresh, onBack: onBack, zoom: state.zoom, onZoomChange: state.setZoom, findText: state.findText, onFindTextChange: state.setFindText, onFindNext: state.findNext, findMatchCount: state.findMatches.length, findMatchIndex: state.findIndex, onExport: format => state.requestOutput({ kind: "export", format }), onPrint: () => state.requestOutput({ kind: "print" }), warnings: warnings, reportName: reportName, onToggleParameters: hasSidebar ? state.toggleParameters : undefined, parametersVisible: state.parametersVisible, disabled: !result || loadingRender || !!error }), jsxRuntime.jsx("div", { ref: canvasRef, className: styles.canvas, "data-testid": "report-canvas", children: renderCanvas() })] }), confirmation && (jsxRuntime.jsx(CwDialog, { open: true, headline: confirmation.headline, width: "28rem", onClose: state.cancelOutput, customFooter: [
12295
+ jsxRuntime.jsx(CwButton, { text: "Cancel", variant: "outline", onClick: state.cancelOutput }, "cancel"),
12296
+ jsxRuntime.jsx(CwButton, { text: confirmation.confirmText, onClick: state.confirmOutput, "data-testid": "report-output-confirm" }, "confirm")
12297
+ ], "data-testid": "report-output-dialog", children: jsxRuntime.jsx("p", { className: "cw-margin-none", children: confirmation.message }) })), state.permissionDialogOpen && (jsxRuntime.jsx(CwDialog, { open: true, headline: "SQL ERROR", width: "30rem", onClose: state.closePermissionDialog, customFooter: [jsxRuntime.jsx(CwButton, { text: "OK", onClick: state.closePermissionDialog }, "ok")], "data-testid": "report-permission-dialog", children: jsxRuntime.jsx("p", { className: "cw-margin-none", children: "You do not have the database permission this report needs, so some of its data could not be read. Ask an administrator to grant access to the report data." }) }))] }));
12298
+ }
12299
+
12300
+ const NO_FLIPS = new Set();
12301
+ /**
12302
+ * Client-side state of the report viewer around one render result, owned by the host and handed to
12303
+ * `CwReportViewer` as `state`. The drilldown toggles belong to a render: a new RenderId (new render,
12304
+ * sort) starts with none flipped, paging and server views of the same render keep them. With
12305
+ * `onView` the host re-renders the page for the flipped toggles, so the page and find use it as drawn
12306
+ * (`drawnFlips` = none). The find position belongs to the query and the page shown. The permission
12307
+ * dialog is dismissed per render, and a pending export / print question is dropped by a new render.
12308
+ */
12309
+ function useReportViewerState(result, options) {
12310
+ const { onPage, onView, onExport, onPrint, initialZoom = 1 } = options;
12311
+ const renderId = result?.RenderId ?? null;
12312
+ const page = result?.Page ?? null;
12313
+ const pageNumber = page?.Number ?? 1;
12314
+ const warnings = result?.Warnings;
12315
+ const serverToggles = !!onView;
12316
+ const [zoom, setZoom] = React.useState(initialZoom);
12317
+ const [toggles, setToggles] = React.useState({ renderId: null, flipped: NO_FLIPS });
12318
+ const [findText, setFindText] = React.useState("");
12319
+ const [find, setFind] = React.useState({ key: "", index: 0 });
12320
+ const [parametersVisible, setParametersVisible] = React.useState(true);
12321
+ const [dismissedRenderId, setDismissedRenderId] = React.useState(null);
12322
+ const [output, setOutput] = React.useState(null);
12323
+ const flipped = toggles.renderId === renderId ? toggles.flipped : NO_FLIPS;
12324
+ const toggle = React.useCallback((toggleId) => {
12325
+ setToggles(previous => ({
12326
+ renderId,
12327
+ flipped: flipToggle(previous.renderId === renderId ? previous.flipped : NO_FLIPS, toggleId)
12328
+ }));
12329
+ if (onView)
12330
+ onView(toggledIds(flipped, toggleId), pageNumber);
12331
+ }, [renderId, onView, flipped, pageNumber]);
12332
+ const setFlipped = React.useCallback((toggleIds) => {
12333
+ setToggles({ renderId, flipped: new Set(toggleIds) });
12334
+ }, [renderId]);
12335
+ const goToPage = React.useCallback((target) => {
12336
+ if (onView && flipped.size > 0) {
12337
+ onView(flippedToggleIds(flipped), target);
12338
+ }
12339
+ else {
12340
+ onPage(target);
12341
+ }
12342
+ }, [onView, onPage, flipped]);
12343
+ // With server toggles the page arrives already drawn for the flipped toggles, so nothing is flipped again here.
12344
+ const drawnFlips = serverToggles ? NO_FLIPS : flipped;
12345
+ const findMatches = React.useMemo(() => (page ? findInPage(page, findText, drawnFlips) : []), [page, findText, drawnFlips]);
12346
+ const findKey = `${renderId ?? ""}|${page?.Number ?? 0}|${findText}`;
12347
+ const findIndex = activeMatchIndex(find.index, find.key === findKey, findMatches.length);
12348
+ const findNext = React.useCallback(() => {
12349
+ setFind({ key: findKey, index: nextMatchIndex(findIndex, findMatches.length) });
12350
+ }, [findKey, findIndex, findMatches.length]);
12351
+ const toggleParameters = React.useCallback(() => setParametersVisible(visible => !visible), []);
12352
+ const closePermissionDialog = React.useCallback(() => setDismissedRenderId(renderId), [renderId]);
12353
+ // A new render (refresh, sort) drops a question asked about the previous one.
12354
+ const pendingOutput = output && output.renderId === renderId ? output.action : null;
12355
+ const runOutput = React.useCallback((action) => {
12356
+ const toggleIds = flippedToggleIds(flipped);
12357
+ if (action.kind === "print") {
12358
+ onPrint(toggleIds);
12359
+ }
12360
+ else {
12361
+ onExport(action.format, toggleIds);
12362
+ }
12363
+ }, [flipped, onPrint, onExport]);
12364
+ const requestOutput = React.useCallback((action) => {
12365
+ if (needsOutputConfirmation(warnings)) {
12366
+ setOutput({ renderId, action });
12367
+ }
12368
+ else {
12369
+ runOutput(action);
12370
+ }
12371
+ }, [warnings, renderId, runOutput]);
12372
+ const confirmOutput = React.useCallback(() => {
12373
+ setOutput(null);
12374
+ if (pendingOutput)
12375
+ runOutput(pendingOutput);
12376
+ }, [pendingOutput, runOutput]);
12377
+ const cancelOutput = React.useCallback(() => setOutput(null), []);
12378
+ return {
12379
+ result,
12380
+ serverToggles,
12381
+ zoom,
12382
+ setZoom,
12383
+ flipped,
12384
+ drawnFlips,
12385
+ toggle,
12386
+ setFlipped,
12387
+ goToPage,
12388
+ findText,
12389
+ setFindText,
12390
+ findMatches,
12391
+ findIndex,
12392
+ findNext,
12393
+ parametersVisible,
12394
+ toggleParameters,
12395
+ permissionDialogOpen: !!result?.PermissionDenied && dismissedRenderId !== renderId,
12396
+ closePermissionDialog,
12397
+ pendingOutput,
12398
+ requestOutput,
12399
+ confirmOutput,
12400
+ cancelOutput
12401
+ };
12402
+ }
12403
+
12404
+ function stateFor(form) {
12405
+ return { source: form, edits: initialParameterEdits(form?.Parameters ?? []), pending: new Set(), showErrors: false };
12406
+ }
12407
+ /**
12408
+ * Editor state of the report parameter form, owned by the host and handed to `CwReportParameterForm`
12409
+ * as `controller`. A new form object from the host (after a resolve) resets the editors to the values
12410
+ * it carries; the server echoes the submitted values, so nothing is lost.
12411
+ */
12412
+ function useReportParameterForm(form, options) {
12413
+ const { onResolve, onRender } = options;
12414
+ const [state, setState] = React.useState(() => stateFor(form));
12415
+ const current = state.source === form ? state : stateFor(form);
12416
+ if (current !== state)
12417
+ setState(current);
12418
+ const parameters = form?.Parameters ?? [];
12419
+ const setEdit = React.useCallback((name, edit, commit) => {
12420
+ const params = form?.Parameters ?? [];
12421
+ const edits = { ...current.edits, [name]: edit };
12422
+ const pending = new Set(current.pending);
12423
+ if (commit) {
12424
+ pending.delete(name);
12425
+ }
12426
+ else {
12427
+ pending.add(name);
12428
+ }
12429
+ setState({ ...current, edits, pending });
12430
+ if (commit && hasDependentParameters(params, name))
12431
+ onResolve(toRdlParameterValues(params, edits));
12432
+ }, [current, form, onResolve]);
12433
+ const commit = React.useCallback((name) => {
12434
+ if (!current.pending.has(name))
12435
+ return;
12436
+ const params = form?.Parameters ?? [];
12437
+ const pending = new Set(current.pending);
12438
+ pending.delete(name);
12439
+ setState({ ...current, pending });
12440
+ if (hasDependentParameters(params, name))
12441
+ onResolve(toRdlParameterValues(params, current.edits));
12442
+ }, [current, form, onResolve]);
12443
+ const submit = React.useCallback(() => {
12444
+ const params = form?.Parameters ?? [];
12445
+ const errors = validateParameterEdits(params, current.edits);
12446
+ if (Object.keys(errors).length > 0) {
12447
+ setState({ ...current, showErrors: true });
12448
+ return;
12449
+ }
12450
+ onRender(toRdlParameterValues(params, current.edits));
12451
+ }, [current, form, onRender]);
12452
+ return {
12453
+ form,
12454
+ edits: current.edits,
12455
+ errors: current.showErrors ? validateParameterEdits(parameters, current.edits) : {},
12456
+ setEdit,
12457
+ commit,
12458
+ submit
12459
+ };
12460
+ }
12461
+
10121
12462
  /**
10122
12463
  * API-backed airport search input for WinOps.
10123
12464
  *
@@ -10621,7 +12962,14 @@ exports.CwOption = CwOption;
10621
12962
  exports.CwPopoverButton = CwPopoverButton;
10622
12963
  exports.CwProgress = CwProgress;
10623
12964
  exports.CwRadioGroup = CwRadioGroup;
12965
+ exports.CwReportGauge = CwReportGauge;
12966
+ exports.CwReportLineChart = CwReportLineChart;
10624
12967
  exports.CwReportModal = CwReportModal;
12968
+ exports.CwReportPage = CwReportPage;
12969
+ exports.CwReportParameterForm = CwReportParameterForm;
12970
+ exports.CwReportPieChart = CwReportPieChart;
12971
+ exports.CwReportToolbar = CwReportToolbar;
12972
+ exports.CwReportViewer = CwReportViewer;
10625
12973
  exports.CwSearchAsync = CwSearchAsync;
10626
12974
  exports.CwSearchInput = CwSearchInput;
10627
12975
  exports.CwSelect = CwSelect;
@@ -10667,6 +13015,7 @@ exports.OnStartClickHeaderEvent = OnStartClickHeaderEvent;
10667
13015
  exports.OnUnpinRow = OnUnpinRow;
10668
13016
  exports.PRESET_LIBRARY_TEMPORAL = PRESET_LIBRARY_TEMPORAL;
10669
13017
  exports.PinRowHeader = PinRowHeader;
13018
+ exports.REPORT_ZOOM_STEPS = REPORT_ZOOM_STEPS;
10670
13019
  exports.Scheduler = Scheduler;
10671
13020
  exports.SchedulerEvent = SchedulerEvent;
10672
13021
  exports.SuperScheduler = SuperScheduler;
@@ -10677,13 +13026,20 @@ exports.configureCwLoading = configureCwLoading;
10677
13026
  exports.eventIsVisible = eventIsVisible;
10678
13027
  exports.filterNavItems = filterNavItems;
10679
13028
  exports.filterVisibleEvents = filterVisibleEvents;
13029
+ exports.findInPage = findInPage;
13030
+ exports.flipToggle = flipToggle;
10680
13031
  exports.getCwLoadingDefaults = getCwLoadingDefaults;
10681
13032
  exports.getDefaultDivisions = getDefaultDivisions;
10682
13033
  exports.getEventSizes = getEventSizes;
10683
13034
  exports.getPresetsByKeysTemporal = getPresetsByKeysTemporal;
13035
+ exports.initialParameterEdits = initialParameterEdits;
13036
+ exports.isRdlVisible = isRdlVisible;
10684
13037
  exports.itemsToMultiFilterTags = itemsToMultiFilterTags;
10685
13038
  exports.sortNavItems = sortNavItems;
13039
+ exports.toRdlParameterValues = toRdlParameterValues;
10686
13040
  exports.useCwMessage = useCwMessage;
13041
+ exports.useReportParameterForm = useReportParameterForm;
13042
+ exports.useReportViewerState = useReportViewerState;
10687
13043
  exports.useSortableList = useSortableList;
10688
13044
  exports.useSortableTable = useSortableTable;
10689
13045
  exports.useTooltipConstraint = useTooltipConstraint;