@cwellt_software/cwellt-reactjs-lib 1.5.1 → 1.5.3

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 (123) hide show
  1. package/dist/content/fonts/roboto-mono/LICENSE +93 -93
  2. package/dist/content/fonts/roboto-mono/RobotoMono.css +43 -43
  3. package/dist/content/icons/new-cw-icons/css/new-cw-icons.css +6 -0
  4. package/dist/index.cjs.js +268 -1471
  5. package/dist/index.css +2 -2
  6. package/dist/index.d.ts +137 -230
  7. package/dist/index.es.js +269 -1468
  8. package/dist/src/components/control/action/button/CwButton.d.ts +5 -0
  9. package/dist/src/components/control/action/button/CwButton.d.ts.map +1 -1
  10. package/dist/src/components/control/action/button/CwButtonBadge.d.ts +63 -0
  11. package/dist/src/components/control/action/button/CwButtonBadge.d.ts.map +1 -0
  12. package/dist/src/components/control/choice/checkbox/CwCheckboxGroup.d.ts.map +1 -1
  13. package/dist/src/components/control/choice/checkbox/CwRadioGroup.d.ts.map +1 -1
  14. package/dist/src/components/control/choice/select/CwDropdown.d.ts.map +1 -1
  15. package/dist/src/components/control/choice/tag-selector/CwTagSelector.d.ts.map +1 -1
  16. package/dist/src/components/control/input/color/CwInputColor.d.ts +2 -0
  17. package/dist/src/components/control/input/color/CwInputColor.d.ts.map +1 -1
  18. package/dist/src/components/control/input/digit/CwDigit.d.ts +12 -0
  19. package/dist/src/components/control/input/digit/CwDigit.d.ts.map +1 -1
  20. package/dist/src/components/control/input/new-dates/CwDatePicker.d.ts.map +1 -1
  21. package/dist/src/components/control/input/new-dates/CwDatePickerTemporal.d.ts.map +1 -1
  22. package/dist/src/components/control/input/new-dates/CwDateRangePicker.d.ts.map +1 -1
  23. package/dist/src/components/control/input/new-dates/CwDateRangePickerTemporal.d.ts.map +1 -1
  24. package/dist/src/components/control/input/new-dates/CwTimePicker.d.ts.map +1 -1
  25. package/dist/src/components/control/input/weekday/CwWeekdaySelector.d.ts +16 -44
  26. package/dist/src/components/control/input/weekday/CwWeekdaySelector.d.ts.map +1 -1
  27. package/dist/src/components/control/input/weekday/weekdayNames.d.ts +14 -0
  28. package/dist/src/components/control/input/weekday/weekdayNames.d.ts.map +1 -0
  29. package/dist/src/components/control/input/weekday/weekdays.d.ts +65 -0
  30. package/dist/src/components/control/input/weekday/weekdays.d.ts.map +1 -0
  31. package/dist/src/components/display/graphics/progress/CwProgress.d.ts +3 -1
  32. package/dist/src/components/display/graphics/progress/CwProgress.d.ts.map +1 -1
  33. package/dist/src/components/display/text/badge/CwBadge.d.ts +48 -0
  34. package/dist/src/components/display/text/badge/CwBadge.d.ts.map +1 -0
  35. package/dist/src/components/display/text/badge/badgeContent.d.ts +33 -0
  36. package/dist/src/components/display/text/badge/badgeContent.d.ts.map +1 -0
  37. package/dist/src/components/display/text/tag/CwChip.d.ts +16 -8
  38. package/dist/src/components/display/text/tag/CwChip.d.ts.map +1 -1
  39. package/dist/src/components/layout/tabs/CwTabs.d.ts +7 -1
  40. package/dist/src/components/layout/tabs/CwTabs.d.ts.map +1 -1
  41. package/dist/src/index.d.ts +3 -9
  42. package/dist/src/index.d.ts.map +1 -1
  43. package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
  44. package/dist/src/playground/pages/CwBadgePage.d.ts +3 -0
  45. package/dist/src/playground/pages/CwBadgePage.d.ts.map +1 -0
  46. package/dist/src/playground/pages/CwChipPage.d.ts +3 -0
  47. package/dist/src/playground/pages/CwChipPage.d.ts.map +1 -0
  48. package/dist/src/playground/pages/CwDigitPage.d.ts +3 -0
  49. package/dist/src/playground/pages/CwDigitPage.d.ts.map +1 -0
  50. package/dist/src/playground/pages/CwWeekdaySelectorPage.d.ts +3 -0
  51. package/dist/src/playground/pages/CwWeekdaySelectorPage.d.ts.map +1 -0
  52. package/dist/src/playground/pages/FormControlLayoutsPage.d.ts +3 -0
  53. package/dist/src/playground/pages/FormControlLayoutsPage.d.ts.map +1 -0
  54. package/dist/src/playground/pages/ProgressPage.d.ts.map +1 -1
  55. package/dist/src/playground/pages/SelectorsPage.d.ts.map +1 -1
  56. package/dist/test/components/control/input/weekday/weekdayNames.test.d.ts +2 -0
  57. package/dist/test/components/control/input/weekday/weekdayNames.test.d.ts.map +1 -0
  58. package/dist/test/components/control/input/weekday/weekdays.test.d.ts +2 -0
  59. package/dist/test/components/control/input/weekday/weekdays.test.d.ts.map +1 -0
  60. package/dist/test/components/display/text/badge/badgeContent.test.d.ts +2 -0
  61. package/dist/test/components/display/text/badge/badgeContent.test.d.ts.map +1 -0
  62. package/package.json +3 -3
  63. package/dist/content/fonts/roboto/LICENSE.txt +0 -202
  64. package/dist/content/fonts/roboto/Roboto-Black.ttf +0 -0
  65. package/dist/content/fonts/roboto/Roboto-BlackItalic.ttf +0 -0
  66. package/dist/content/fonts/roboto/Roboto-Bold.ttf +0 -0
  67. package/dist/content/fonts/roboto/Roboto-BoldItalic.ttf +0 -0
  68. package/dist/content/fonts/roboto/Roboto-Italic.ttf +0 -0
  69. package/dist/content/fonts/roboto/Roboto-Light.ttf +0 -0
  70. package/dist/content/fonts/roboto/Roboto-LightItalic.ttf +0 -0
  71. package/dist/content/fonts/roboto/Roboto-Medium.ttf +0 -0
  72. package/dist/content/fonts/roboto/Roboto-MediumItalic.ttf +0 -0
  73. package/dist/content/fonts/roboto/Roboto-Regular.ttf +0 -0
  74. package/dist/content/fonts/roboto/Roboto-Thin.ttf +0 -0
  75. package/dist/content/fonts/roboto/Roboto-ThinItalic.ttf +0 -0
  76. package/dist/content/fonts/roboto/RobotoFontFamily.css +0 -109
  77. package/dist/content/fonts/roboto-flex/README.md +0 -24
  78. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-grad-normal.woff2 +0 -0
  79. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-opsz-normal.woff2 +0 -0
  80. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-slnt-normal.woff2 +0 -0
  81. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-standard-normal.woff2 +0 -0
  82. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-wdth-normal.woff2 +0 -0
  83. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-wght-normal.woff2 +0 -0
  84. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-xopq-normal.woff2 +0 -0
  85. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-xtra-normal.woff2 +0 -0
  86. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-yopq-normal.woff2 +0 -0
  87. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-ytas-normal.woff2 +0 -0
  88. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-ytde-normal.woff2 +0 -0
  89. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-ytfi-normal.woff2 +0 -0
  90. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-ytlc-normal.woff2 +0 -0
  91. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ext-ytuc-normal.woff2 +0 -0
  92. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-grad-normal.woff2 +0 -0
  93. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-opsz-normal.woff2 +0 -0
  94. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-slnt-normal.woff2 +0 -0
  95. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-standard-normal.woff2 +0 -0
  96. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-wdth-normal.woff2 +0 -0
  97. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-wght-normal.woff2 +0 -0
  98. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-xopq-normal.woff2 +0 -0
  99. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-xtra-normal.woff2 +0 -0
  100. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-yopq-normal.woff2 +0 -0
  101. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ytas-normal.woff2 +0 -0
  102. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ytde-normal.woff2 +0 -0
  103. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ytfi-normal.woff2 +0 -0
  104. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ytlc-normal.woff2 +0 -0
  105. package/dist/content/fonts/roboto-flex/files/roboto-flex-latin-ytuc-normal.woff2 +0 -0
  106. package/dist/content/fonts/roboto-flex/grad.css +0 -19
  107. package/dist/content/fonts/roboto-flex/index.css +0 -19
  108. package/dist/content/fonts/roboto-flex/metadata.json +0 -33
  109. package/dist/content/fonts/roboto-flex/opsz.css +0 -19
  110. package/dist/content/fonts/roboto-flex/slnt.css +0 -19
  111. package/dist/content/fonts/roboto-flex/standard.css +0 -21
  112. package/dist/content/fonts/roboto-flex/unicode.json +0 -4
  113. package/dist/content/fonts/roboto-flex/wdth.css +0 -21
  114. package/dist/content/fonts/roboto-flex/wght.css +0 -20
  115. package/dist/content/fonts/roboto-flex/xopq.css +0 -20
  116. package/dist/content/fonts/roboto-flex/xtra.css +0 -19
  117. package/dist/content/fonts/roboto-flex/yopq.css +0 -19
  118. package/dist/content/fonts/roboto-flex/ytas.css +0 -19
  119. package/dist/content/fonts/roboto-flex/ytde.css +0 -20
  120. package/dist/content/fonts/roboto-flex/ytfi.css +0 -20
  121. package/dist/content/fonts/roboto-flex/ytlc.css +0 -19
  122. package/dist/content/fonts/roboto-flex/ytuc.css +0 -20
  123. package/dist/content/icons/new-cw-icons/NewCwIcons.html +0 -415
package/dist/index.cjs.js CHANGED
@@ -181,7 +181,7 @@ function getContrastColor(color) {
181
181
  return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
182
182
  }
183
183
 
184
- var styles$x = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
184
+ var styles$y = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
185
185
 
186
186
  // Constants
187
187
  const margin$1 = 16;
@@ -471,7 +471,7 @@ const CwTooltipManager = () => {
471
471
  if (!state.isVisible || !state.content) {
472
472
  return null;
473
473
  }
474
- return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$x["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
474
+ return reactDom.createPortal(jsxRuntime.jsx("div", { ref: tooltipRef, className: styles$y["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
475
475
  top: `${tooltipPosition.top}px`,
476
476
  left: `${tooltipPosition.left}px`,
477
477
  opacity: (isPositioned && !isMeasuring) ? 1 : 0,
@@ -552,7 +552,7 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
552
552
  React.useEffect(() => {
553
553
  ensureTooltipManager();
554
554
  }, []);
555
- return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$x["cw-tooltip"], children: children }));
555
+ return (jsxRuntime.jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$y["cw-tooltip"], children: children }));
556
556
  };
557
557
 
558
558
  const SVG_ICONS = {
@@ -587,25 +587,31 @@ function CwIcon(props) {
587
587
  /**
588
588
  * CwChip - A simple chip/tag component for displaying labels or categories
589
589
  *
590
+ * The colour comes from `color`; the older `colorScheme` spelling is deprecated but still
591
+ * honoured, and `color` wins when both are passed.
592
+ *
590
593
  * @example
591
- * <CwChip label="Active" colorScheme="success" />
592
- * <CwChip label="High Priority" colorScheme="danger" variant="solid" />
593
- * <CwChip label="Custom" colorScheme="custom" customColor="#8a2be2" />
594
- * <CwChip label="Outlined" colorScheme="info" variant="outline" />
594
+ * <CwChip label="Active" color="success" />
595
+ * <CwChip label="High Priority" color="danger" variant="solid" />
596
+ * <CwChip label="Custom" color="custom" customColor="#8a2be2" />
597
+ * <CwChip label="Outlined" color="info" variant="outline" />
595
598
  * <CwChip label="Removable" closable onClose={() => console.log('closed')} />
596
599
  **/
597
- const CwChip = ({ label, colorScheme = 'info', customColor, variant = 'soft', className = '', closable = false, onClose, icon, style = {}, }) => {
600
+ const CwChip = ({ label, color, colorScheme, customColor, variant = 'soft', className = '', closable = false, onClose, icon, style = {}, }) => {
601
+ const resolvedColor = color ?? colorScheme ?? 'info';
598
602
  // Basic validation
599
603
  if (closable && !onClose) {
600
604
  console.warn('CwChip: onClose prop is required when closable is true');
601
605
  }
602
- // Calculate styles based on colorScheme, customColor and variant
606
+ // One arbitrary colour can only fill two of the four roles, so soft and solid look alike here.
603
607
  const chipStyle = React.useMemo(() => {
604
608
  if (customColor) {
605
- // Simply set the CSS custom properties, CSS handles the rest
609
+ const contrast = getContrastColor(customColor);
606
610
  return {
607
- '--chip-accent': customColor,
608
- '--chip-text': getContrastColor(customColor),
611
+ '--accent-light': customColor,
612
+ '--accent-main': customColor,
613
+ '--accent-dark': contrast,
614
+ '--accent-on-main': contrast,
609
615
  ...style
610
616
  };
611
617
  }
@@ -624,7 +630,79 @@ const CwChip = ({ label, colorScheme = 'info', customColor, variant = 'soft', cl
624
630
  className,
625
631
  closable ? 'cw-chip-closable' : '',
626
632
  ].filter(Boolean).join(' ');
627
- return (jsxRuntime.jsxs("span", { className: chipClassNames, "data-color-scheme": colorScheme, "data-variant": variant, style: chipStyle, children: [icon && jsxRuntime.jsx(CwIcon, { iconId: icon }), label && jsxRuntime.jsx("span", { children: label }), closable && (jsxRuntime.jsx("button", { className: "cw-chip-close-button", onClick: handleClose, "aria-label": "Remove", type: "button", children: jsxRuntime.jsx("span", { className: "cwi-icons cwi-close" }) }))] }));
633
+ return (jsxRuntime.jsxs("span", { className: chipClassNames, "data-color": resolvedColor, "data-variant": variant, "data-icon-only": (Boolean(icon) && !label) || undefined, style: chipStyle, children: [icon && jsxRuntime.jsx(CwIcon, { iconId: icon }), label && jsxRuntime.jsx("span", { children: label }), closable && (jsxRuntime.jsx("button", { className: "cw-chip-close-button", onClick: handleClose, "aria-label": "Remove", type: "button", children: jsxRuntime.jsx("span", { className: "cwi-icons cwi-close" }) }))] }));
634
+ };
635
+
636
+ /**
637
+ * Normalises a raw count into the integer the badge represents: a non-negative whole number.
638
+ * Both the display string and the `showZero` decision derive from this.
639
+ */
640
+ function normalizeBadgeCount(count) {
641
+ return Number.isFinite(count) ? Math.max(0, Math.trunc(count)) : 0;
642
+ }
643
+ /**
644
+ * Formats a badge count into its display string. Both arguments are normalised, `max` with a
645
+ * floor of 1 - below that every non-zero count would overflow.
646
+ *
647
+ * @param count Raw count to display.
648
+ * @param max Highest value shown as a number; anything above renders `"{max}+"`.
649
+ *
650
+ * @example
651
+ * formatBadgeCount(7, 99); // "7"
652
+ * formatBadgeCount(100, 99); // "99+"
653
+ * formatBadgeCount(12, 9); // "9+"
654
+ */
655
+ function formatBadgeCount(count, max) {
656
+ const safeCount = normalizeBadgeCount(count);
657
+ const safeMax = Number.isFinite(max) ? Math.max(1, Math.trunc(max)) : 1;
658
+ return safeCount > safeMax ? `${safeMax}+` : `${safeCount}`;
659
+ }
660
+ /**
661
+ * Resolves the badge's accessibility attributes. A text-less badge with no label is hidden rather
662
+ * than announced as an empty element; the button or tab around it usually names the thing.
663
+ *
664
+ * @param label Caller-supplied accessible name.
665
+ * @param loading Whether the badge is showing its spinner.
666
+ * @param hasText Whether the badge renders a count or content.
667
+ */
668
+ function resolveBadgeAria(label, loading, hasText) {
669
+ if (label) {
670
+ return { role: loading ? 'status' : 'img', 'aria-label': label };
671
+ }
672
+ return hasText ? {} : { 'aria-hidden': 'true' };
673
+ }
674
+
675
+ var styles$x = {"badge":"cw-badge-module__badge__PKlak"};
676
+
677
+ /**
678
+ * CwBadge - the small coloured circle with a number, used for alert and notification counts.
679
+ *
680
+ * Always **in flow** (`inline-flex`); it never positions itself, so overlaying it on an icon
681
+ * button is the caller's job. One digit stays a circle, wider content such as `"99+"` grows into
682
+ * a pill. With neither `count` nor `content` it renders as a dot.
683
+ *
684
+ * Precedence: `loading` > `content` > `count` > dot. While loading the badge renders regardless
685
+ * of `showZero`, and the spinner replaces it - circle, background and padding come off.
686
+ *
687
+ * @example
688
+ * <CwBadge count={3} color="danger" />
689
+ * <CwBadge count={0} showZero={false} />
690
+ * <CwBadge count={128} max={99} color="warning" variant="soft" />
691
+ * <CwBadge color="warning" label="Unresolved findings" />
692
+ * <CwBadge count={0} loading />
693
+ */
694
+ const CwBadge = ({ count, content, color = 'info', variant = 'solid', size = 'small', showZero = true, loading = false, max = 99, label, className = '', style, }) => {
695
+ // null counts as absent, so `content={null}` still renders a dot rather than an empty pill.
696
+ const hasContent = content !== undefined && content !== null;
697
+ if (!loading && !hasContent && count !== undefined && !showZero && normalizeBadgeCount(count) === 0) {
698
+ return null;
699
+ }
700
+ const countText = !hasContent && count !== undefined
701
+ ? formatBadgeCount(count, max)
702
+ : undefined;
703
+ const isDot = !loading && !hasContent && count === undefined;
704
+ const badgeClassNames = ['cw-badge', styles$x.badge, className].filter(Boolean).join(' ');
705
+ return (jsxRuntime.jsx("span", { 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 }));
628
706
  };
629
707
 
630
708
  const CW_DEFAULT_MESSAGE_DURATION = 2000;
@@ -1078,7 +1156,7 @@ var styles$v = {"progress":"cw-progress-module__progress__d-g2-","value":"cw-pro
1078
1156
  * <CwProgress value={62} label="Import" color="success" />
1079
1157
  * <CwProgress indeterminate label="Uploading" />
1080
1158
  */
1081
- function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'regular', layout = 'row', color = 'primary', monoValue = false, prominent = false }) {
1159
+ function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'regular', layout = 'row', color = 'primary', monoValue = false, prominent = false, className }) {
1082
1160
  const labelId = React.useId();
1083
1161
  // Determinate: a missing or non-finite value is treated as 0 (never NaN), then
1084
1162
  // clamped to [0,100] for aria-valuenow and the fill width. Indeterminate has no value.
@@ -1090,7 +1168,7 @@ function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'r
1090
1168
  const valueText = rightLabel ?? (percent !== undefined ? `${percent}%` : '');
1091
1169
  // The un-hashed cw-progress class carries no styles in the library - a stable
1092
1170
  // public hook for exceptional external overrides only.
1093
- const rootClassName = ['cw-progress', styles$v.progress].filter(Boolean).join(' ');
1171
+ const rootClassName = ['cw-progress', styles$v.progress, className].filter(Boolean).join(' ');
1094
1172
  const labelSpan = label ? jsxRuntime.jsx("span", { className: styles$v.label, id: labelId, children: label }) : null;
1095
1173
  const valueLabel = showValue ? (jsxRuntime.jsx("span", { className: styles$v.value, "data-mono": monoValue || undefined, children: valueText })) : null;
1096
1174
  return (jsxRuntime.jsxs("div", { className: rootClassName, "data-layout": layout, "data-size": size, "data-color": color, "data-prominent": prominent || undefined, "data-indeterminate": indeterminate || undefined, children: [layout === 'column' && (labelSpan || valueLabel) && (jsxRuntime.jsxs("header", { className: styles$v.header, children: [labelSpan, valueLabel] })), layout === 'row' && labelSpan, jsxRuntime.jsx("div", { className: styles$v.track, role: "progressbar", ...(label && { 'aria-labelledby': labelId }), ...(!indeterminate && percent !== undefined && {
@@ -1246,7 +1324,7 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1246
1324
  return (jsxRuntime.jsxs("div", { ref: containerRef, className: styles$u["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1247
1325
  };
1248
1326
 
1249
- const CwButton = React.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }, ref) {
1327
+ 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) {
1250
1328
  // Build CSS classes based on variant and props
1251
1329
  let buttonClass = `cw-button-${variant}`;
1252
1330
  // Add icon class only for icon variant without children
@@ -1259,13 +1337,19 @@ const CwButton = React.forwardRef(function CwButton({ text, variant = 'solid', c
1259
1337
  const tooltipContent = title || (variant === 'icon' && text ? text : undefined);
1260
1338
  const iconElement = icon ? jsxRuntime.jsx(CwIcon, { iconId: icon }) : null;
1261
1339
  const textElement = text ? jsxRuntime.jsx("strong", { children: text }) : null;
1340
+ // Overlaid, not content: the `cwi-` condition above deliberately ignores it, so a badge
1341
+ // never suppresses the button's own icon. Size defaulted explicitly, not by spread order,
1342
+ // so `size: undefined` in the object cannot clobber it.
1343
+ const badgeElement = badge
1344
+ ? jsxRuntime.jsx(CwBadge, { ...badge, size: badge.size ?? (variant === 'icon' ? 'small' : size) })
1345
+ : null;
1262
1346
  // Only emit toggle attributes when `pressed` is defined; otherwise output stays identical to a normal button.
1263
1347
  const pressedProps = pressed !== undefined
1264
1348
  ? { "aria-pressed": pressed, "data-pressed": pressed ? "true" : undefined }
1265
1349
  : {};
1266
- const buttonElement = (jsxRuntime.jsx("button", { ref: ref, type: "button", className: buttonClass, ...buttonProps, "data-color": color, "data-size": size, ...pressedProps, "aria-label": tooltipContent ?? buttonProps["aria-label"], children: variant === 'icon' ? null : (children ?? (iconPosition === 'right'
1267
- ? jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [textElement, iconElement] })
1268
- : jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [iconElement, textElement] }))) }));
1350
+ const buttonElement = (jsxRuntime.jsx("button", { ref: ref, type: "button", className: buttonClass, ...buttonProps, "data-color": color, "data-size": size, "data-has-badge": badge ? "true" : undefined, ...pressedProps, "aria-label": buttonProps["aria-label"] ?? tooltipContent, children: variant === 'icon' ? badgeElement : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [children ?? (iconPosition === 'right'
1351
+ ? jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [textElement, iconElement] })
1352
+ : jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [iconElement, textElement] })), badgeElement] })) }));
1269
1353
  return tooltipContent ? (jsxRuntime.jsx(CwTooltipNew, { content: tooltipContent, position: tooltipPosition, displayInline: true, children: buttonElement })) : (buttonElement);
1270
1354
  });
1271
1355
  CwButton.displayName = "CwButton";
@@ -2654,8 +2738,12 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
2654
2738
  }, 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" })] })] }))] }));
2655
2739
  }
2656
2740
 
2657
- var styles$n = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","badge":"cw-tabs-module__badge__AmVxW","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2741
+ var styles$n = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2658
2742
 
2743
+ const BADGE_COLOR_SCHEMES = ['primary', 'danger', 'warning', 'success', 'info', 'neutral'];
2744
+ function isBadgeColorScheme(value) {
2745
+ return BADGE_COLOR_SCHEMES.includes(value);
2746
+ }
2659
2747
  const TabIcon = ({ icon }) => {
2660
2748
  if (!icon)
2661
2749
  return null;
@@ -2704,7 +2792,11 @@ function CwTabs(CwTabsProps) {
2704
2792
  const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
2705
2793
  ? { minWidth: CwTabsProps.tabsListWidth }
2706
2794
  : undefined;
2707
- return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$n['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxRuntime.jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsxRuntime.jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsxRuntime.jsx("span", { className: styles$n['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsxRuntime.jsx("div", { className: styles$n['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, style: CwTabsProps.contentHeight ? { '--tabs-height': CwTabsProps.contentHeight } : undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2795
+ return (jsxRuntime.jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$n['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsxRuntime.jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => {
2796
+ const badgeScheme = tab.badgeColor && isBadgeColorScheme(tab.badgeColor) ? tab.badgeColor : undefined;
2797
+ const rawBadgeColor = tab.badgeColor && !badgeScheme ? tab.badgeColor : undefined;
2798
+ 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));
2799
+ }) }), jsxRuntime.jsx("div", { className: styles$n['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, style: CwTabsProps.contentHeight ? { '--tabs-height': CwTabsProps.contentHeight } : undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2708
2800
  }
2709
2801
 
2710
2802
  /**
@@ -3253,8 +3345,16 @@ function CwInput(CwInputProps) {
3253
3345
  * ```
3254
3346
  */
3255
3347
  function CwDigit(props) {
3256
- const { alignProps, buttonProps, iconProps, labelProps, ...inputProps } = props;
3257
- return (jsxRuntime.jsx("div", { className: "cw-input-text", children: jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsx("input", { type: "number", ...inputProps }), buttonProps && jsxRuntime.jsx(CwButton, { ...buttonProps })] }) }));
3348
+ const { alignProps, buttonProps, iconProps, labelProps, feedback, feedbackPosition, ...inputProps } = props;
3349
+ const feedbackMessages = feedback
3350
+ ? Array.isArray(feedback) ? feedback : [feedback]
3351
+ : [];
3352
+ const feedbackId = React.useId();
3353
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
3354
+ const describedBy = [inputProps["aria-describedby"], ...feedbackIds].filter(Boolean).join(" ") || undefined;
3355
+ // data-direction drives the feedback indent, which only makes sense under a label column.
3356
+ const flexDirection = alignProps?.flexDirection ?? "row";
3357
+ 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)))] }));
3258
3358
  }
3259
3359
 
3260
3360
  var styles$j = {"colorPreview":"cw-color-picker-module__colorPreview__ylJcD","hueBar":"cw-color-picker-module__hueBar__bFhyC","hueBarSlider":"cw-color-picker-module__hueBarSlider__D53IV","colorPickerInteractiveArea":"cw-color-picker-module__colorPickerInteractiveArea__KZFR1","colorArea":"cw-color-picker-module__colorArea__xgpSE","colorAreaOverlay":"cw-color-picker-module__colorAreaOverlay__pmgOc","hueBackground":"cw-color-picker-module__hueBackground__Mks78","whiteGradient":"cw-color-picker-module__whiteGradient__Bt-fU","blackGradient":"cw-color-picker-module__blackGradient__VnEKJ","colorAreaCursor":"cw-color-picker-module__colorAreaCursor__lotg3"};
@@ -3468,7 +3568,7 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
3468
3568
 
3469
3569
  var styles$i = {"container":"cw-input-color-module__container__x7gpk","selectColor":"cw-input-color-module__selectColor__DTo3V","disabled":"cw-input-color-module__disabled__O1fK5","readOnly":"cw-input-color-module__readOnly__HL-Bz","colorDropdown":"cw-input-color-module__colorDropdown__pX2bc"};
3470
3570
 
3471
- const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, }) => {
3571
+ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, className, style, }) => {
3472
3572
  const [isOpen, setIsOpen] = React.useState(false);
3473
3573
  const containerRef = React.useRef(null);
3474
3574
  const dropdownRef = React.useRef(null);
@@ -3599,7 +3699,7 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
3599
3699
  break;
3600
3700
  }
3601
3701
  };
3602
- return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$i.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps })), jsxRuntime.jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
3702
+ return (jsxRuntime.jsxs("div", { className: `cw-input-color ${styles$i.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$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
3603
3703
  width,
3604
3704
  height,
3605
3705
  backgroundColor: value,
@@ -4064,15 +4164,37 @@ const CwImageArea = React.forwardRef((props, ref) => {
4064
4164
  });
4065
4165
  CwImageArea.displayName = "CwImageArea";
4066
4166
 
4067
- var styles$g = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
4167
+ var styles$g = {"container":"cw-weekday-selector-module__container__pwcvx","days":"cw-weekday-selector-module__days__Dd3RH"};
4168
+
4169
+ /* 2024-01-01 was a Monday. Formatted in UTC so a negative browser offset cannot shift a day. */
4170
+ const MONDAY_UTC = Date.UTC(2024, 0, 1);
4171
+ const DAY_IN_MS = 86_400_000;
4172
+ const DAY_CODES = ["M", "T", "W", "R", "F", "S", "U"];
4173
+ /**
4174
+ * Day names in the fixed MTWRFSU order the selector renders, resolved through Intl so every
4175
+ * locale gets its own letters (es -> LMXJVSD, de -> MDMDFSS) with no table to maintain.
4176
+ *
4177
+ * @param localeCode BCP-47 tag, e.g. "en-GB" | "es" | "de"
4178
+ */
4179
+ function getWeekdayNames(localeCode) {
4180
+ const narrow = new Intl.DateTimeFormat(localeCode, { weekday: "narrow", timeZone: "UTC" });
4181
+ const full = new Intl.DateTimeFormat(localeCode, { weekday: "long", timeZone: "UTC" });
4182
+ const names = {};
4183
+ DAY_CODES.forEach((code, index) => {
4184
+ const date = new Date(MONDAY_UTC + index * DAY_IN_MS);
4185
+ names[code] = { letter: narrow.format(date), full: full.format(date) };
4186
+ });
4187
+ return names;
4188
+ }
4068
4189
 
4190
+ /* The week model behind CwWeekdaySelector, kept apart from the rendering. */
4069
4191
  /**
4070
4192
  * This class represents a week where days can be selected or unselected
4071
4193
  * @remark Selected days are in UPPERCASE, unselected days are in lowercase
4072
4194
  * ```
4073
4195
  * Monday = "M" | "m"
4074
4196
  * Tuesday = "T" | "t"
4075
- * Wendnesday = "W" | "w"
4197
+ * Wednesday = "W" | "w"
4076
4198
  * thuRsday = "R" | "r"
4077
4199
  * Friday = "F" | "f"
4078
4200
  * Saturday = "S" | "s"
@@ -4084,15 +4206,6 @@ class Weekdays {
4084
4206
  static WEEKDAYS_STANDARD_ARRAY_EMPTY = ["m", "t", "w", "r", "f", "s", "u"];
4085
4207
  static WEEKDAYS_STANDARD_STRING_FULL = "MTWRFSU";
4086
4208
  static WEEKDAYS_STANDARD_STRING_EMPTY = "mtwrfsu";
4087
- static WEEKDAYS_TO_USA_LETTER_FORMAT = new Map([
4088
- ["M", "M"],
4089
- ["T", "T"],
4090
- ["W", "W"],
4091
- ["R", "T"],
4092
- ["F", "F"],
4093
- ["S", "S"],
4094
- ["U", "S"]
4095
- ]);
4096
4209
  static WEEKDAYS_TO_USA_SHORT_FORMAT = new Map([
4097
4210
  ["M", "Mon"],
4098
4211
  ["T", "Tue"],
@@ -4111,6 +4224,7 @@ class Weekdays {
4111
4224
  5: "F",
4112
4225
  6: "S"
4113
4226
  };
4227
+ static DAY_NUMBER_BY_CODE = Object.fromEntries(Object.entries(Weekdays.WEEKDAY_MAP).map(([dayNumber, code]) => [code, Number(dayNumber)]));
4114
4228
  days;
4115
4229
  constructor(days = Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL) {
4116
4230
  if (typeof days === "string")
@@ -4154,11 +4268,11 @@ class Weekdays {
4154
4268
  toString() {
4155
4269
  return this.days.join("").trim();
4156
4270
  }
4157
- toStringFormatted(limiters = { startExistingDay: "{", endExsitingDay: "}", startMissingDay: "(", endMissingDay: ")", separator: " " }, format = Weekdays.WEEKDAYS_TO_USA_SHORT_FORMAT) {
4271
+ toStringFormatted(limiters = { startExistingDay: "{", endExistingDay: "}", startMissingDay: "(", endMissingDay: ")", separator: " " }, format = Weekdays.WEEKDAYS_TO_USA_SHORT_FORMAT) {
4158
4272
  const result = new Array();
4159
4273
  [...this.days].forEach((letter, index) => {
4160
4274
  if (letter === letter.toUpperCase()) {
4161
- result.push(limiters.startExistingDay + format.get(letter) + limiters.endExsitingDay);
4275
+ result.push(limiters.startExistingDay + format.get(letter) + limiters.endExistingDay);
4162
4276
  }
4163
4277
  else if (letter === letter.toLowerCase()) {
4164
4278
  result.push(limiters.startMissingDay +
@@ -4178,33 +4292,77 @@ class Weekdays {
4178
4292
  return this.toString() === Weekdays.WEEKDAYS_STANDARD_STRING_FULL;
4179
4293
  }
4180
4294
  static getFullWeek() {
4181
- return Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL;
4295
+ return [...Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL];
4182
4296
  }
4183
4297
  static getEmptyWeek() {
4184
- return Weekdays.WEEKDAYS_STANDARD_ARRAY_EMPTY;
4298
+ return [...Weekdays.WEEKDAYS_STANDARD_ARRAY_EMPTY];
4185
4299
  }
4186
- }
4187
- const CwWeekdaySelector = ({ value = "", onChange, disabled = false }) => {
4188
- const [selectedDays, setSelectedDays] = React.useState(Weekdays.fromString(value));
4189
- React.useEffect(() => {
4190
- setSelectedDays(Weekdays.fromString(value));
4191
- }, [value]);
4192
- const handleChange = (day, checked) => {
4193
- const currentDays = selectedDays.toArray();
4194
- let updated;
4195
- if (checked) {
4196
- updated = currentDays.filter(d => d !== day.toLowerCase());
4197
- updated.push(day);
4300
+ /** A week with nothing selected. */
4301
+ static empty() {
4302
+ return new Weekdays(Weekdays.WEEKDAYS_STANDARD_ARRAY_EMPTY);
4303
+ }
4304
+ /**
4305
+ * Like {@link fromString}, but yields an empty week instead of throwing on anything invalid.
4306
+ * For UI fed straight from a backend field that can arrive null, empty or partial.
4307
+ */
4308
+ static tryFromString(value) {
4309
+ if (!value)
4310
+ return Weekdays.empty();
4311
+ try {
4312
+ return Weekdays.fromString(value);
4198
4313
  }
4199
- else {
4200
- updated = currentDays.filter(d => d !== day);
4201
- updated.push(day.toLowerCase());
4314
+ catch {
4315
+ return Weekdays.empty();
4202
4316
  }
4203
- const newWeekdays = new Weekdays(updated);
4204
- setSelectedDays(newWeekdays);
4205
- onChange?.(newWeekdays.toString());
4317
+ }
4318
+ /** Selected flags in MTWRFSU order (Monday first). */
4319
+ toBooleans() {
4320
+ return this.days.map(day => day === day.toUpperCase());
4321
+ }
4322
+ /** @param flags selected flags in MTWRFSU order; missing entries count as unselected */
4323
+ static fromBooleans(flags) {
4324
+ return new Weekdays(Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL.map((day, index) => flags[index] ? day : day.toLowerCase()));
4325
+ }
4326
+ /** 7-character mask in MTWRFSU order where "1" means selected, e.g. "1100100". */
4327
+ toMask() {
4328
+ return this.toBooleans().map(selected => (selected ? "1" : "0")).join("");
4329
+ }
4330
+ /** @param mask 7-character mask in MTWRFSU order where "1" means selected; a shorter, empty or
4331
+ * missing mask counts the absent days as unselected */
4332
+ static fromMask(mask) {
4333
+ return Weekdays.fromBooleans(Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL.map((_, index) => mask?.[index] === "1"));
4334
+ }
4335
+ /** Selected days as Date.getDay() numbers (0 = Sunday), in MTWRFSU order. */
4336
+ toDayNumbers() {
4337
+ return this.days
4338
+ .filter(day => day === day.toUpperCase())
4339
+ .map(day => Weekdays.DAY_NUMBER_BY_CODE[day]);
4340
+ }
4341
+ /** @param days Date.getDay() numbers (0 = Sunday) */
4342
+ static fromDayNumbers(days) {
4343
+ const selected = new Set(days);
4344
+ return Weekdays.fromBooleans(Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL.map(day => selected.has(Weekdays.DAY_NUMBER_BY_CODE[day])));
4345
+ }
4346
+ }
4347
+
4348
+ const CwWeekdaySelector = ({ value = "mtwrfsu", onChange, disabled = false, labelProps, layout, feedback, locale = "en-GB", className }) => {
4349
+ const selectedDays = Weekdays.tryFromString(value).toArray();
4350
+ const dayNames = React.useMemo(() => getWeekdayNames(locale), [locale]);
4351
+ const handleChange = (day, checked) => {
4352
+ const updated = selectedDays.filter(d => d !== day && d !== day.toLowerCase());
4353
+ updated.push(checked ? day : day.toLowerCase());
4354
+ onChange?.(new Weekdays(updated).toString());
4206
4355
  };
4207
- return (jsxRuntime.jsx("div", { className: styles$g["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsxRuntime.jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
4356
+ const feedbackMessages = feedback
4357
+ ? Array.isArray(feedback) ? feedback : [feedback]
4358
+ : [];
4359
+ const feedbackId = React.useId();
4360
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4361
+ const describedBy = feedbackIds.join(" ") || undefined;
4362
+ // Points at the label element rather than copying its text, which also covers a labelProps that
4363
+ // carries children instead of `text`.
4364
+ const labelId = labelProps?.id ?? `${feedbackId}-label`;
4365
+ return (jsxRuntime.jsxs("div", { className: `cw-weekday-selector ${styles$g.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$g.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)))] }));
4208
4366
  };
4209
4367
 
4210
4368
  var styles$f = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
@@ -4252,6 +4410,9 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
4252
4410
  const feedbackMessages = feedback
4253
4411
  ? Array.isArray(feedback) ? feedback : [feedback]
4254
4412
  : [];
4413
+ const feedbackId = React.useId();
4414
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4415
+ const describedBy = feedbackIds.join(" ") || undefined;
4255
4416
  // Effective layout — precedence: new `groupLayout`/`itemLayout` > legacy-derived > default.
4256
4417
  // Legacy `alignProps.flexDirection` drove the label-vs-options axis (default "row" = label
4257
4418
  // beside the options); map it to `groupLayout.direction`.
@@ -4264,7 +4425,7 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
4264
4425
  ?? (optionsAlignment === "column" ? "row" : "column");
4265
4426
  // Each checkbox's box-to-text layout is the opposite of the options flow, mirroring CwRadioGroup.
4266
4427
  const checkDirection = itemDirection === "row" ? "column" : "row";
4267
- return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$f.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$f.options, role: "group", "aria-label": labelProps?.text, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4428
+ return (jsxRuntime.jsxs("div", { className: `cw-checkbox-group ${styles$f.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$f.options, role: "group", "aria-label": labelProps?.text, "aria-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)))] }));
4268
4429
  }
4269
4430
 
4270
4431
  var styles$e = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
@@ -4291,11 +4452,14 @@ function CwRadioGroup({ options, value, onChange, labelProps, groupLayout, itemL
4291
4452
  const feedbackMessages = feedback
4292
4453
  ? Array.isArray(feedback) ? feedback : [feedback]
4293
4454
  : [];
4455
+ const feedbackId = React.useId();
4456
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4457
+ const describedBy = feedbackIds.join(" ") || undefined;
4294
4458
  // Each radio's circle-to-text layout is the opposite of the options flow: a stacked list
4295
4459
  // (itemLayout column) reads best with the circle beside the text; a side-by-side row reads
4296
4460
  // best with the circle above the text.
4297
4461
  const radioDirection = itemLayout?.direction === "row" ? "column" : "row";
4298
- return (jsxRuntime.jsxs("div", { className: `cw-radio-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$e.options, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : (ariaLabel ?? labelProps?.text), "aria-required": required || undefined, "data-direction": itemLayout?.direction ?? "column", "data-gap": itemLayout?.gap, children: options.map((option) => (jsxRuntime.jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4462
+ return (jsxRuntime.jsxs("div", { className: `cw-radio-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsxRuntime.jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxRuntime.jsx("div", { className: styles$e.options, role: "radiogroup", "aria-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)))] }));
4299
4463
  }
4300
4464
 
4301
4465
  function CwToggle(props) {
@@ -4475,6 +4639,13 @@ function CwDropdown({ options, value, onChange, labelProps, alignProps, placehol
4475
4639
  const feedbackMessages = feedback
4476
4640
  ? Array.isArray(feedback) ? feedback : [feedback]
4477
4641
  : [];
4642
+ const feedbackId = React.useId();
4643
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4644
+ const describedBy = feedbackIds.join(" ") || undefined;
4645
+ // The trigger is named by reference - the label for the field, the content for the current
4646
+ // value - so neither has to be copied into a string.
4647
+ const labelId = labelProps?.id ?? `${feedbackId}-label`;
4648
+ const valueId = `${feedbackId}-value`;
4478
4649
  // Scroll highlighted item into view
4479
4650
  React.useEffect(() => {
4480
4651
  if (isOpen && highlightedItemRef.current) {
@@ -4543,12 +4714,12 @@ function CwDropdown({ options, value, onChange, labelProps, alignProps, placehol
4543
4714
  }
4544
4715
  }, [isOpen, highlightedIndex, filteredOptions, handleOptionSelect]);
4545
4716
  const flexDirection = alignProps?.flexDirection ?? "row";
4546
- return (jsxRuntime.jsxs("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, { ...labelProps, children: labelProps.text })), jsxRuntime.jsxs("div", { className: "cw-dropdown-wrapper", ref: wrapperRef, children: [jsxRuntime.jsx("button", { type: "button", className: "cw-dropdown-trigger", onClick: handleTriggerClick, onKeyDown: handleKeyDown, disabled: disabled, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-label": selectedOption?.label || placeholder, children: jsxRuntime.jsx("div", { className: "cw-dropdown-trigger-content", children: selectedOption ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [selectedOption.color && (jsxRuntime.jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: selectedOption.color } })), jsxRuntime.jsx("span", { children: selectedOption.label })] })) : (jsxRuntime.jsx("span", { className: "cw-dropdown-placeholder", children: placeholder })) }) }), jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", paddingRight: "0.5rem", flexShrink: 0, cursor: disabled ? "not-allowed" : "pointer" }, onClick: handleTriggerClick, children: jsxRuntime.jsx(CwIcon, { iconId: "chevron-down", size: "small" }) }), renderPanel(jsxRuntime.jsxs("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsxRuntime.jsx("div", { className: dropdownStyles.searchBox, children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: dropdownStyles.searchInput, autoComplete: "off" }) })), jsxRuntime.jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxRuntime.jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
4547
- dropdownStyles.option,
4548
- value === option.value ? dropdownStyles.optionSelected : "",
4549
- highlightedIndex === index ? dropdownStyles.optionFocused : "",
4550
- option.disabled ? dropdownStyles.optionDisabled : "",
4551
- ].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: dropdownStyles.colorCircle, style: { backgroundColor: option.color } })), jsxRuntime.jsx("span", { children: option.label })] }, option.value)))) : (jsxRuntime.jsx("li", { className: dropdownStyles.emptyState, children: "No options available" })) })] }))] })] }), feedbackMessages.map((item, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": item.type, children: item.message }, index)))] }));
4717
+ 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: dropdownStyles.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: dropdownStyles.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: dropdownStyles.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsxRuntime.jsx("div", { className: dropdownStyles.searchBox, children: jsxRuntime.jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: dropdownStyles.searchInput, autoComplete: "off" }) })), jsxRuntime.jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxRuntime.jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
4718
+ dropdownStyles.option,
4719
+ value === option.value ? dropdownStyles.optionSelected : "",
4720
+ highlightedIndex === index ? dropdownStyles.optionFocused : "",
4721
+ option.disabled ? dropdownStyles.optionDisabled : "",
4722
+ ].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: dropdownStyles.colorCircle, style: { backgroundColor: option.color } })), jsxRuntime.jsx("span", { children: option.label })] }, option.value)))) : (jsxRuntime.jsx("li", { className: dropdownStyles.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)))] })] }) }));
4552
4723
  }
4553
4724
 
4554
4725
  function CwDropdownFilter(props) {
@@ -4956,7 +5127,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4956
5127
  } }, props.ID))) })] }))] }));
4957
5128
  };
4958
5129
 
4959
- var styles$a = {"container":"cw-tag-selector-module__container__-do8i","inputBox":"cw-tag-selector-module__inputBox__3NGz9 cw-choice-input-box-module__inputBox__gHY9d","disabled":"cw-tag-selector-module__disabled__vbud9 cw-choice-input-box-module__disabled__TFAnC","dropdown":"cw-tag-selector-module__dropdown__X6Dob cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-tag-selector-module__option__2UQ7g cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-tag-selector-module__optionFocused__8-lv8 cw-choice-dropdown-module__optionFocused__BYMxj","optionDot":"cw-tag-selector-module__optionDot__CdFlG cw-choice-dropdown-module__colorCircle__x7mI9","selectAll":"cw-tag-selector-module__selectAll__HyvMA"};
5130
+ var styles$a = {"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"};
4960
5131
 
4961
5132
  /**
4962
5133
  * Multi-select input with chip tags and searchable dropdown.
@@ -5091,8 +5262,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5091
5262
  // Keeping containerRef for any other potential use
5092
5263
  const direction = alignProps?.flexDirection ?? "row";
5093
5264
  const feedbackMessages = feedback ? (Array.isArray(feedback) ? feedback : [feedback]) : [];
5094
- return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
5095
- inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsxRuntime.jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsxRuntime.jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsxRuntime.jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxRuntime.jsxs("div", { ref: panelRef, className: styles$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.jsxs("li", { className: `${styles$a.option}${idx === focusedIndex ? ` ${styles$a.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsxRuntime.jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
5265
+ const feedbackId = React.useId();
5266
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
5267
+ const describedBy = feedbackIds.join(" ") || undefined;
5268
+ return (jsxRuntime.jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxRuntime.jsxs(CwLabel, { ...labelProps, children: [iconProps && jsxRuntime.jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxRuntime.jsxs("div", { className: styles$a.value, children: [jsxRuntime.jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
5269
+ 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$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxRuntime.jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsxRuntime.jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxRuntime.jsxs("li", { className: `${styles$a.option}${idx === focusedIndex ? ` ${styles$a.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsxRuntime.jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
5096
5270
  }
5097
5271
 
5098
5272
  var styles$9 = {"tree-container":"cw-tree-view-module__tree-container__NN-HJ","tree-wrapper":"cw-tree-view-module__tree-wrapper__keBZI","tree-item":"cw-tree-view-module__tree-item__prE9N","tree-node":"cw-tree-view-module__tree-node__wfro9","selected":"cw-tree-view-module__selected__XJQ0w","non-selectable":"cw-tree-view-module__non-selectable__YuPSx","tree-children":"cw-tree-view-module__tree-children__ji8CZ","empty-state":"cw-tree-view-module__empty-state__yvRjo","tree-label":"cw-tree-view-module__tree-label__ss3Nf","tree-spacer":"cw-tree-view-module__tree-spacer__E9Ud2"};
@@ -6103,7 +6277,7 @@ function CwBtnCancel({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...res
6103
6277
  return (jsxRuntime.jsx(CwButton, { ...rest, variant: "icon", icon: "cancel", color: "danger", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Cancel" }));
6104
6278
  }
6105
6279
 
6106
- var styles$4 = {"pickerWrapper":"cw-pickers-base-module__pickerWrapper__Fb9Zo","pickerIcons":"cw-pickers-base-module__pickerIcons__dyd2-","pickerPopup":"cw-pickers-base-module__pickerPopup__dkxJo"};
6280
+ 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"};
6107
6281
 
6108
6282
  /**
6109
6283
  * Renders a picker popup in a portal so it escapes overflow containers.
@@ -6160,6 +6334,9 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
6160
6334
  const feedbackMessages = feedback
6161
6335
  ? Array.isArray(feedback) ? feedback : [feedback]
6162
6336
  : [];
6337
+ const feedbackId = React.useId();
6338
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
6339
+ const describedBy = feedbackIds.join(" ") || undefined;
6163
6340
  const wrapperRef = React.useRef(null);
6164
6341
  const inputRef = React.useRef(null);
6165
6342
  const prevValueRef = React.useRef(undefined);
@@ -6340,11 +6517,11 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
6340
6517
  ...(maxDate ? [{ after: maxDate }] : []),
6341
6518
  ...(disabledMatcher ? [disabledMatcher] : []),
6342
6519
  ], [disabledDates, minDate, maxDate, disabledMatcher]);
6343
- return (jsxRuntime.jsxs("div", { 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", { 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, required: required }), 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: {
6344
- today: new Date(),
6345
- }, modifiersClassNames: {
6346
- today: "rdp-day-today",
6347
- } }), showTodayButton && (jsxRuntime.jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
6520
+ return (jsxRuntime.jsx("div", { 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: {
6521
+ today: new Date(),
6522
+ }, modifiersClassNames: {
6523
+ today: "rdp-day-today",
6524
+ } }), showTodayButton && (jsxRuntime.jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] }), 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)))] })] }) }));
6348
6525
  }
6349
6526
 
6350
6527
  var rangeStyles = {"rangeWrapper":"cw-range-picker-module__rangeWrapper__1nIVs","rangePopup":"cw-range-picker-module__rangePopup__E5jd1","rangeCalendarRow":"cw-range-picker-module__rangeCalendarRow__VTxi0","presetList":"cw-range-picker-module__presetList__INiLo","rangeError":"cw-range-picker-module__rangeError__qHMdi"};
@@ -6983,14 +7160,14 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6983
7160
  }
6984
7161
  return undefined;
6985
7162
  }, [value]);
6986
- return (jsxRuntime.jsx("div", { 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", { 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, required: required, "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, required: required, "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: {
7163
+ return (jsxRuntime.jsx("div", { 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", { 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, 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, 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: {
6987
7164
  today: new Date(),
6988
7165
  }, modifiersClassNames: {
6989
7166
  today: "rdp-day-today",
6990
7167
  } })] }), jsxRuntime.jsx("div", { role: "alert", "aria-live": "polite", className: rangeStyles.rangeError, children: rangeErrorMessage })] }))] })] }) }));
6991
7168
  }
6992
7169
 
6993
- var timeStyles = {"timePickerPopup":"cw-time-picker-module__timePickerPopup__BN63t","timePickerList":"cw-time-picker-module__timePickerList__E88pr","selected":"cw-time-picker-module__selected__qVnfL","hasIcons":"cw-time-picker-module__hasIcons__ZiGUf","notIcons":"cw-time-picker-module__notIcons__3icu1"};
7170
+ var timeStyles = {"timePickerPopup":"cw-time-picker-module__timePickerPopup__BN63t","timePickerList":"cw-time-picker-module__timePickerList__E88pr","selected":"cw-time-picker-module__selected__qVnfL","field":"cw-time-picker-module__field__kPvGN","narrow":"cw-time-picker-module__narrow__Z7lCI"};
6994
7171
 
6995
7172
  const isMobileDevice = () => {
6996
7173
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
@@ -7152,7 +7329,7 @@ function CwTimePicker({ value, onChange, interval = 15, minTime, maxTime, labelP
7152
7329
  return (jsxRuntime.jsx("div", { 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.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, className: "cw-timepicker-native" }) })] }) }));
7153
7330
  }
7154
7331
  // Custom time picker
7155
- return (jsxRuntime.jsx("div", { 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", { 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, required: required, maxLength: 5, className: showClear ? timeStyles.hasIcons : timeStyles.notIcons }), 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) => {
7332
+ return (jsxRuntime.jsx("div", { 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", { 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, 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) => {
7156
7333
  const isSelected = time === value;
7157
7334
  return (jsxRuntime.jsx("button", { ref: isSelected ? selectedItemRef : null, type: "button", className: isSelected ? timeStyles.selected : "", onClick: () => handleTimeSelect(time), children: time }, time));
7158
7335
  }) }) }))] })] }) }));
@@ -7818,6 +7995,9 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
7818
7995
  const feedbackMessages = feedback
7819
7996
  ? Array.isArray(feedback) ? feedback : [feedback]
7820
7997
  : [];
7998
+ const feedbackId = React.useId();
7999
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
8000
+ const describedBy = feedbackIds.join(" ") || undefined;
7821
8001
  const wrapperRef = React.useRef(null);
7822
8002
  const inputRef = React.useRef(null);
7823
8003
  const prevValueRef = React.useRef(undefined);
@@ -7924,11 +8104,11 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
7924
8104
  const defaultMonthJsDate = defaultMonth
7925
8105
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
7926
8106
  : selectedJsDate;
7927
- return (jsxRuntime.jsxs("div", { 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", { 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, required: required }), 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: {
7928
- today: new Date(),
7929
- }, modifiersClassNames: {
7930
- today: "rdp-day-today",
7931
- } }), showTodayButton && (jsxRuntime.jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] })] }), feedbackMessages.map((feedbackItem, index) => (jsxRuntime.jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
8107
+ return (jsxRuntime.jsx("div", { 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: {
8108
+ today: new Date(),
8109
+ }, modifiersClassNames: {
8110
+ today: "rdp-day-today",
8111
+ } }), showTodayButton && (jsxRuntime.jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsxRuntime.jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] }), 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)))] })] }) }));
7932
8112
  }
7933
8113
 
7934
8114
  // DateTimePickerState - immutable domain model for the Temporal date-time picker.
@@ -8666,1073 +8846,13 @@ function CwDateRangePickerTemporal({ value, onChange, minDate, maxDate, disabled
8666
8846
  const defaultMonthJsDate = defaultMonth
8667
8847
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
8668
8848
  : (value?.from ? plainDateToJsDate(value.from) : undefined);
8669
- return (jsxRuntime.jsx("div", { 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", { 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, required: required, "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, required: required, "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: {
8849
+ return (jsxRuntime.jsx("div", { 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", { 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, 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, 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: {
8670
8850
  today: new Date(),
8671
8851
  }, modifiersClassNames: {
8672
8852
  today: "rdp-day-today",
8673
8853
  } })] }), jsxRuntime.jsx("div", { role: "alert", "aria-live": "polite", className: rangeStyles.rangeError, children: rangeErrorMessage })] }))] })] }) }));
8674
8854
  }
8675
8855
 
8676
- const ResourcesTitleList = ({ resources, canBePinned, includesPinned, onCrewPinning, onClickResourceContextMenu, ResourceTitleComponent, }) => {
8677
- const onClickContextMenu = React.useCallback((key, resource) => {
8678
- if (onClickResourceContextMenu) {
8679
- onClickResourceContextMenu(key, resource);
8680
- }
8681
- }, []);
8682
- return (jsxRuntime.jsx("td", { className: "resourceArea", style: { width: "100px" }, children: resources.map((r, _i) => (jsxRuntime.jsxs("div", { className: "resource CwelltFunctionDescription", style: { height: r.maxTop }, children: [(canBePinned || includesPinned) && (jsxRuntime.jsx(PinButton, { canBePinned: canBePinned, resource: r, onCrewPinning: onCrewPinning })), jsxRuntime.jsx(ResourceTitleComponent, { resource: r, handleOnClickResourceContextMenu: onClickContextMenu })] }, r.id.toString()))) }));
8683
- };
8684
- const PinButton = ({ canBePinned, resource, onCrewPinning }) => {
8685
- const buttonProps = canBePinned
8686
- ? {
8687
- id: "cbl_pinL",
8688
- onClick: () => onCrewPinning(resource, ""),
8689
- children: jsxRuntime.jsx("span", { className: "cwi-pin", style: { visibility: "visible" } }),
8690
- }
8691
- : {
8692
- id: "cbl_pinLess45deg",
8693
- onClick: () => onCrewPinning(resource, "remove"),
8694
- children: jsxRuntime.jsx("span", { className: "cwi-pinned cwi-pin", style: { visibility: "visible" } }),
8695
- };
8696
- return jsxRuntime.jsx("button", { className: "cw-button-icon cw-icon-pin", ...buttonProps });
8697
- };
8698
-
8699
- const addMinutesToDateFromPx = (originalDate, leftPx, minutesPerPx) => {
8700
- const minutes = leftPx / minutesPerPx;
8701
- const datePlusMinutes = new Date(originalDate.getTime() + minutes * 60000);
8702
- return datePlusMinutes;
8703
- };
8704
-
8705
- const doubleClickOnResource = (props, resource) => {
8706
- if (props.scheduler_handleDblClickOnResourceInScheduler) {
8707
- props.scheduler_handleDblClickOnResourceInScheduler(resource);
8708
- }
8709
- };
8710
-
8711
- let CblDragAndDrop$1 = class CblDragAndDrop {
8712
- fromId;
8713
- toId;
8714
- data;
8715
- droppedOnDate;
8716
- resizeFromStart;
8717
- resizeFromEnd;
8718
- isCtrlKey;
8719
- constructor(fromId, toId, data, droppedOnDate = null, resizeFromStart = null, resizeFromEnd = null, isCtrlKey = null) {
8720
- this.fromId = fromId;
8721
- this.toId = toId;
8722
- this.data = data;
8723
- this.droppedOnDate = droppedOnDate;
8724
- this.resizeFromStart = resizeFromStart;
8725
- this.resizeFromEnd = resizeFromEnd;
8726
- this.isCtrlKey = isCtrlKey;
8727
- }
8728
- };
8729
-
8730
- const BIRTHDATE = 15;
8731
- const NOT_WORKING = 16;
8732
- const REST_TIME = 10;
8733
- const MAX_FLIGHT_DUTY_PERIOD = 11;
8734
- const DUTY_REGULATION = 20;
8735
- const unHandleableEvents = [REST_TIME, MAX_FLIGHT_DUTY_PERIOD, NOT_WORKING, DUTY_REGULATION];
8736
- const getEventStyle = (event, reslTime) => {
8737
- const baseStyle = {
8738
- left: event.leftPx,
8739
- width: event.width,
8740
- top: event.top,
8741
- overflow: "hidden",
8742
- zIndex: event.isFullHeight ? 4 : 5,
8743
- };
8744
- if (event.data.eventType === BIRTHDATE) {
8745
- return {
8746
- ...baseStyle,
8747
- height: event.isFullHeight ? "100%" : "auto",
8748
- marginTop: event.isFullHeight ? -1 * event.top : 0,
8749
- pointerEvents: "none",
8750
- borderBottom: "solid 1px rgba(0, 0, 0, 0.4)",
8751
- backgroundColor: event.data.category.color || "orange",
8752
- display: "flex",
8753
- opacity: 0.3,
8754
- alignItems: "flex-end",
8755
- };
8756
- }
8757
- if ([REST_TIME, MAX_FLIGHT_DUTY_PERIOD, DUTY_REGULATION].includes(event.data.eventType)) {
8758
- return {
8759
- ...baseStyle,
8760
- zIndex: event.isFullHeight ? 4 : 6,
8761
- marginTop: event.isFullHeight ? -1 * event.top : 0,
8762
- borderRadius: "0px",
8763
- backgroundColor: event.data.category.color || "grey",
8764
- opacity: 0.3,
8765
- borderBottom: event.data.eventType === DUTY_REGULATION ? "solid 1px rgba(0, 0, 0, 0.4)" : "",
8766
- };
8767
- }
8768
- return {
8769
- ...baseStyle,
8770
- height: event.isFullHeight ? "100%" : "auto",
8771
- marginTop: event.isFullHeight ? -1 * event.top : 0,
8772
- borderRadius: reslTime <= 0.99 ? "3px" : "5px",
8773
- minWidth: reslTime <= 1.5 ? "5px" : "",
8774
- maxWidth: reslTime <= 1.5 ? "25px" : "",
8775
- };
8776
- };
8777
- const EventRender = ({ event, schedulerProps }) => {
8778
- const dateStart = new Date(event.data.start);
8779
- const dateEnd = new Date(event.data.end);
8780
- const reslTime = (dateEnd.getTime() - dateStart.getTime()) / 3600000;
8781
- const eventStyle = getEventStyle(event, reslTime);
8782
- const onClickEvent = (e) => {
8783
- if (!unHandleableEvents.includes(event.data.eventType)) {
8784
- e.stopPropagation();
8785
- const props = schedulerProps;
8786
- props.scheduler_handleCblEventClick.call(props.parent, event, schedulerProps.id);
8787
- }
8788
- };
8789
- const onRightClickEvent = (e) => {
8790
- if (!unHandleableEvents.includes(event.data.eventType)) {
8791
- e.stopPropagation();
8792
- const props = schedulerProps;
8793
- if (props.scheduler_handleCblEventClickRight) {
8794
- props.scheduler_handleCblEventClickRight.call(props.parent, event, schedulerProps.id);
8795
- }
8796
- }
8797
- };
8798
- const safeHandleDragStart = (e, isLeft, isRight) => {
8799
- if (!unHandleableEvents.includes(event.data.eventType)) {
8800
- handleDragStart(e, isLeft, isRight);
8801
- }
8802
- };
8803
- const handleDragStart = (e, isResizeFromStart, isResizeFromEnd) => {
8804
- if (!unHandleableEvents.includes(event.data.eventType)) {
8805
- [].forEach.call(document.querySelectorAll(".ant-tooltip"), function (el) {
8806
- el.style.visibility = "hidden";
8807
- });
8808
- // We don't know in which case is necessary
8809
- if (e.target !== e.currentTarget) {
8810
- // e.preventDefault();
8811
- return;
8812
- }
8813
- const isResize = isResizeFromStart || isResizeFromEnd;
8814
- const isAllowed = !event.isReadOnly && (isResize ? event.isResizable : event.isDraggable);
8815
- if (!isAllowed) {
8816
- e.preventDefault();
8817
- return;
8818
- }
8819
- const cblDragNDrop = new CblDragAndDrop$1(schedulerProps.id, null, [event], null, isResizeFromStart, isResizeFromEnd);
8820
- if (!isResize) {
8821
- e.dataTransfer.dropEffect = e.ctrlKey ? "copy" : "link";
8822
- }
8823
- e.dataTransfer.setData("data", JSON.stringify(cblDragNDrop));
8824
- }
8825
- };
8826
- const handleDoubleClick = (e) => {
8827
- if (!unHandleableEvents.includes(event.data.eventType)) {
8828
- e.preventDefault();
8829
- e.stopPropagation();
8830
- const props = schedulerProps;
8831
- props.scheduler_handleCblEventDoubleClick.call(props.parent, event, schedulerProps.id);
8832
- }
8833
- };
8834
- const onClickContextMenu = (e) => {
8835
- if (!unHandleableEvents.includes(event.data.eventType)) {
8836
- const props = schedulerProps;
8837
- if (props.scheduler_handleOnClickEventContextMenu) {
8838
- props.scheduler_handleOnClickEventContextMenu(e, event);
8839
- }
8840
- }
8841
- };
8842
- const renderBirthdayEvent = () => (jsxRuntime.jsxs("div", { className: `fc-timeline-event cwellt_timeline_event cwellt_event_bday ${event.selected ? "cblEventSelected" : ""}`, style: eventStyle, children: [jsxRuntime.jsx("span", { className: "cwi-icons cwi-birthday", style: { visibility: "visible" } }), event.data.subject && jsxRuntime.jsx("span", { style: { lineHeight: "1em" }, children: event.data.subject })] }, event.id));
8843
- const renderRegularEvent = () => (jsxRuntime.jsxs("div", { draggable: ![10, 11, 16, 20, 21].includes(event.data.eventType), className: "fc-timeline-event cwellt_timeline_event " +
8844
- (event.selected === true ? "cblEventSelected " : "") +
8845
- (event.data.eventType === REST_TIME ||
8846
- event.data.eventType === MAX_FLIGHT_DUTY_PERIOD ||
8847
- event.data.eventType === DUTY_REGULATION
8848
- ? " cwellt_event_bhnd_appt "
8849
- : " "), style: eventStyle, onClick: onClickEvent, onContextMenu: onRightClickEvent, onDragStart: (e) => safeHandleDragStart(e, false, false), onDoubleClick: handleDoubleClick, children: [schedulerProps.scheduler_handleCblEventResize &&
8850
- !event.isReadOnly &&
8851
- !unHandleableEvents.includes(event.data.eventType) && (jsxRuntime.jsx("span", { draggable: true, onDragStart: (e) => handleDragStart(e, true, false), style: {
8852
- position: "absolute",
8853
- cursor: "e-resize",
8854
- zIndex: 10,
8855
- left: "0",
8856
- border: "solid 1px rgba(46,49,49,0.5)",
8857
- }, children: "\u200B" })), jsxRuntime.jsx(schedulerProps.cblEventComp, { cblEvent: event, handleOnClickEventContextMenu: onClickContextMenu }, event.id), schedulerProps.scheduler_handleCblEventResize &&
8858
- !event.isReadOnly &&
8859
- !unHandleableEvents.includes(event.data.eventType) && (jsxRuntime.jsx("span", { draggable: true, onDragStart: (e) => handleDragStart(e, false, true), style: {
8860
- position: "absolute",
8861
- right: "0",
8862
- cursor: "e-resize",
8863
- zIndex: 10,
8864
- border: "solid 1px rgba(46,49,49,0.5)",
8865
- marginTop: "-25px",
8866
- }, children: "\u200B" }))] }, event.id));
8867
- const render = event.data.eventType === BIRTHDATE ? renderBirthdayEvent() : renderRegularEvent();
8868
- return render;
8869
- };
8870
-
8871
- const onDropEventToResource = (props, cblDragNDrop, resource) => {
8872
- props.scheduler_handleOnDropCblEventsOnResource.call(props.parent, cblDragNDrop, resource);
8873
- };
8874
-
8875
- const isAllowedToMove = (data, resData, cblDragNDrop) => {
8876
- if (data?.eventType !== 1) {
8877
- return true;
8878
- }
8879
- const allowedMoves = [
8880
- { from: "acftsScheduler", to: "flightsPairingsScheduler" },
8881
- { from: "flightsScheduler", to: "crewAssignmentsScheduler" },
8882
- { from: "opstoolScheduler", to: "opstoolScheduler" },
8883
- { from: "opstoolScheduler", to: "opstoolSchedulerVirtual" },
8884
- { from: "opstoolSchedulerVirtual", to: "opstoolScheduler" },
8885
- { from: "opstoolSchedulerVirtual", to: "opstoolSchedulerVirtual" },
8886
- { from: "vacationsScheduler", to: "vacationsScheduler" }
8887
- ];
8888
- const crewControllAllowedMove = allowedMoves.some(move => move.from === cblDragNDrop.fromId && move.to === cblDragNDrop.toId);
8889
- if (crewControllAllowedMove) {
8890
- return true;
8891
- }
8892
- return data.Crew !== resData.Crewmember_Id;
8893
- };
8894
-
8895
- const OnDrop = ({ e, resource, id, contentArea, state, schedulerProps }) => {
8896
- e.dataTransfer.dropEffect = "move";
8897
- const cblDragNDrop = JSON.parse(e.dataTransfer.getData("data"));
8898
- if (!cblDragNDrop.data || !cblDragNDrop.data[0]) {
8899
- return;
8900
- }
8901
- cblDragNDrop.toId = id;
8902
- const obj = cblDragNDrop.data[0];
8903
- cblDragNDrop.isCtrlKey = e.ctrlKey;
8904
- const isResizeEvent = cblDragNDrop.resizeFromStart === true || cblDragNDrop.resizeFromEnd === true;
8905
- if (isResizeEvent) {
8906
- // Resize
8907
- if (obj.data === undefined || obj.data.eventType === 1) {
8908
- return;
8909
- }
8910
- const _eventX = e.clientX;
8911
- const _caLeft = contentArea?.getBoundingClientRect()?.left ?? 0;
8912
- const leftPos = _eventX - _caLeft;
8913
- let droppedDate = addMinutesToDateFromPx(schedulerProps.startDate, leftPos, state.minutePx);
8914
- if (cblDragNDrop.resizeFromEnd === true) {
8915
- const eventStart = new Date(Date.parse(obj.start));
8916
- droppedDate = droppedDate < eventStart ? eventStart : droppedDate;
8917
- }
8918
- if (cblDragNDrop.resizeFromStart === true) {
8919
- const eventEnd = new Date(Date.parse(obj.end));
8920
- // 3 hours before is the minimun size in the backend
8921
- eventEnd.setHours(eventEnd.getHours() - 3);
8922
- droppedDate = droppedDate > eventEnd ? eventEnd : droppedDate;
8923
- }
8924
- cblDragNDrop.droppedOnDate = droppedDate;
8925
- schedulerProps.scheduler_handleCblEventResize?.call(schedulerProps.parent, cblDragNDrop);
8926
- return;
8927
- }
8928
- // Drag & Drop
8929
- if (!isAllowedToMove(obj.data, resource.data, cblDragNDrop)) {
8930
- return;
8931
- }
8932
- const d = e.clientX - (contentArea?.getBoundingClientRect()?.left ?? 0);
8933
- const date = new Date(schedulerProps.startDate.getTime() + (d / state.minutePx) * 60000);
8934
- cblDragNDrop.droppedOnDate = date;
8935
- onDropEventToResource(schedulerProps, cblDragNDrop, resource);
8936
- };
8937
-
8938
- const onDragOver = (e) => {
8939
- if (e.ctrlKey === true) {
8940
- e.dataTransfer.dropEffect = "copy";
8941
- }
8942
- else {
8943
- e.dataTransfer.dropEffect = "link";
8944
- }
8945
- e.preventDefault();
8946
- };
8947
-
8948
- const arePropsEqual = (prevProps, nextProps) => {
8949
- return prevProps.res.events === nextProps.res.events && prevProps.isInViewport === nextProps.isInViewport;
8950
- };
8951
- const ResourceRender = React.memo(({ res, schedulerProps, contentArea, state }) => {
8952
- return (jsxRuntime.jsx("div", { style: {
8953
- backgroundColor: "#F9F8F8",
8954
- height: res.maxTop,
8955
- width: "100%",
8956
- position: "relative",
8957
- borderBottom: "1px solid rgb(255,255,255)",
8958
- }, onDragOver: (e) => onDragOver(e), onDrop: (e) => {
8959
- OnDrop({
8960
- e,
8961
- resource: res,
8962
- id: schedulerProps.id,
8963
- contentArea,
8964
- state,
8965
- schedulerProps,
8966
- });
8967
- }, className: "cwellt_divRow_schContent", children: res.events.map((evnt) => (jsxRuntime.jsx(EventRender, { event: evnt, schedulerProps: schedulerProps }, evnt.id))) }, res.id));
8968
- }, arePropsEqual);
8969
-
8970
- const ResourceListRender = ({ resources, schedulerProps, state, contentArea,
8971
- // onClickContextMenu,
8972
- crewAssignmentSchedulerContextMenu, }) => {
8973
- return (jsxRuntime.jsx(React.Fragment, { children: resources.map((r, _i) => (jsxRuntime.jsx(CwAnchoredMenu, { placement: "bottom", onContextMenu: (e) => {
8974
- // Dirty temporal solution to remove ANT design, this can be killed when this scheduler is deprecated
8975
- const leftPos = e.currentTarget.getBoundingClientRect().left -
8976
- (contentArea?.getBoundingClientRect()?.left ?? 0) -
8977
- window.scrollX;
8978
- const calculatedDatetime = addMinutesToDateFromPx(schedulerProps.startDate, leftPos, state.minutePx);
8979
- r.__contextMenuDatetime = calculatedDatetime;
8980
- }, options: crewAssignmentSchedulerContextMenu?.map(m => ({
8981
- key: m.key,
8982
- label: (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: m.icon, style: { color: m.color } }), jsxRuntime.jsx("span", { children: m.text })] }))
8983
- })) ?? [], onSelect: (key) => {
8984
- const datetime = r.__contextMenuDatetime ?? new Date();
8985
- if (schedulerProps.scheduler_handleOnClickContextMenuResource) {
8986
- schedulerProps.scheduler_handleOnClickContextMenuResource(datetime, r, key, schedulerProps.id);
8987
- }
8988
- }, children: jsxRuntime.jsx("span", { onDoubleClick: () => doubleClickOnResource(schedulerProps, r), id: schedulerProps.id + "_" + r.id, children: jsxRuntime.jsx(ResourceRender, { res: r, schedulerProps: schedulerProps, contentArea: contentArea, state: state, isInViewport: r.isInViewport }, r.id) }) }, r.id))) }));
8989
- };
8990
-
8991
- const TimeLine$1 = ({ id, toolTipTitle, marginLeft, color = "rgba(255,0,0,.6)", pixels = 2, height = "100%", zIndex = 1, }) => {
8992
- return (jsxRuntime.jsx(CwTooltipNew, { content: toolTipTitle, position: "top", children: jsxRuntime.jsx("div", { id: id, style: {
8993
- borderLeft: `${pixels}px solid ${color}`,
8994
- marginLeft: marginLeft,
8995
- width: "0px",
8996
- height: height,
8997
- position: "absolute",
8998
- zIndex: zIndex,
8999
- } }) }));
9000
- };
9001
-
9002
- const SchedulerContentArea = ({ now, showTimeline, timeLineLeftPx, timeSeparatorLeftPx, resources, scheduler, contextMenuContents, onEmptyClick, setContentArea, onClickContextMenu, }) => {
9003
- return (jsxRuntime.jsxs("td", { className: "contentArea", style: { width: "100%", overflow: "hidden", position: "relative" }, ref: (reference) => {
9004
- if (reference) {
9005
- setContentArea(reference);
9006
- }
9007
- }, children: [showTimeline && (jsxRuntime.jsx(TimeLine$1, { id: scheduler.props.id + "_timeline", marginLeft: timeLineLeftPx, zIndex: 8, toolTipTitle: Temporal.PlainTime.from({
9008
- hour: now.getHours(),
9009
- minute: now.getMinutes(),
9010
- }).toString({ smallestUnit: "minute" }) })), timeSeparatorLeftPx.map((pixels) => {
9011
- return jsxRuntime.jsx(TimeLine$1, { marginLeft: pixels, color: "rgba(255,255,255,0.7)" });
9012
- }), jsxRuntime.jsx("span", { onClick: () => {
9013
- if (onEmptyClick) {
9014
- onEmptyClick(scheduler.props.id);
9015
- }
9016
- }, children: jsxRuntime.jsx(ResourceListRender, { resources: resources, state: scheduler.state, schedulerProps: scheduler.props, contentArea: scheduler.contentArea, onClickContextMenu: onClickContextMenu, crewAssignmentSchedulerContextMenu: contextMenuContents }) })] }));
9017
- };
9018
-
9019
- const daysBetweenTwoDates = (date1, date2) => {
9020
- const diff = Math.abs(date1.getTime() - date2.getTime());
9021
- let diffDays = 0;
9022
- const startOffset = Math.abs(date1.getTimezoneOffset());
9023
- const endOffset = Math.abs(date2.getTimezoneOffset());
9024
- // Summer: +1 -> +2, true
9025
- // Winter: +2 -> -1, false
9026
- if (startOffset > endOffset) {
9027
- diffDays = Math.floor(diff / (1000 * 3600 * 24));
9028
- }
9029
- else {
9030
- diffDays = Math.ceil(diff / (1000 * 3600 * 24));
9031
- }
9032
- return diffDays;
9033
- };
9034
-
9035
- const calculateDivisionType = (start, end) => {
9036
- const diffDays = daysBetweenTwoDates(start, end);
9037
- if (diffDays <= 15) {
9038
- return "d";
9039
- }
9040
- else if (diffDays <= 30) {
9041
- return "w";
9042
- }
9043
- else {
9044
- return "m";
9045
- }
9046
- };
9047
-
9048
- const getMonthHeaderData = (dates, maxWidth) => {
9049
- if (dates.length === 0)
9050
- return [];
9051
- const dayWidth = maxWidth / dates.length;
9052
- const ranges = getMonthRanges(dates);
9053
- return ranges.map((range) => {
9054
- return {
9055
- monthFormatted: range.start.getMonth() + 1 + "." + range.start.getFullYear(),
9056
- width: dayWidth * range.daysLong,
9057
- };
9058
- });
9059
- };
9060
- const getMonthRanges = (dates) => {
9061
- const firstDay = dates[0];
9062
- const lastDay = dates[dates.length - 1];
9063
- let currentDate = new Date(firstDay);
9064
- const ranges = [];
9065
- while (currentDate <= lastDay) {
9066
- const rangeStart = new Date(currentDate);
9067
- let rangeEnd = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
9068
- if (rangeEnd >= lastDay) {
9069
- rangeEnd = lastDay;
9070
- }
9071
- ranges.push({
9072
- start: rangeStart,
9073
- daysLong: getDaysBetweenDates(rangeStart, rangeEnd),
9074
- });
9075
- currentDate = new Date(rangeEnd.getFullYear(), rangeEnd.getMonth() + 1, 1);
9076
- }
9077
- return ranges;
9078
- };
9079
- const getDaysBetweenDates = (startDate, endDate) => {
9080
- const timeDifference = endDate.getTime() - startDate.getTime();
9081
- return Math.floor(timeDifference / (1000 * 60 * 60 * 24)) + 1;
9082
- };
9083
-
9084
- const getWeekHeaderDataFromWeekRange = (weekRange, maxWidth, dateFormatter) => weekRange.map(week => {
9085
- const numberOfDaysInScheduler = weekRange
9086
- .flatMap(element => {
9087
- return element.days;
9088
- })
9089
- .reduce((el1, el2) => {
9090
- return el1 + el2;
9091
- });
9092
- return {
9093
- formattedString: getStringForWeekRange(week, dateFormatter),
9094
- width: getWidthForWeekRange(maxWidth, week.days, numberOfDaysInScheduler)
9095
- };
9096
- });
9097
- const getStringForWeekRange = (weekRange, dateFormatter) => weekRange.days == 1
9098
- ? dateFormatter(weekRange.start)
9099
- : `${dateFormatter(weekRange.start)} - ${dateFormatter(weekRange.end)}`;
9100
- const getWidthForWeekRange = (maxWidth, weekDays, monthDays) => {
9101
- const dayWidth = maxWidth / monthDays;
9102
- return dayWidth * weekDays;
9103
- };
9104
-
9105
- // stringRange: `${formatter(date)} - ${formatter(end)}`,
9106
- const listOfDatesToWeekRangeList = (dates) => {
9107
- if (dates.length === 0) {
9108
- return [];
9109
- }
9110
- const datesToReturn = [];
9111
- dates.forEach((date, index) => {
9112
- const dayOfWeek = date.getDay();
9113
- const isFirstDay = index === 0;
9114
- const isLastDay = index === dates.length - 1;
9115
- const isSunday = dayOfWeek === 0;
9116
- const isMonday = dayOfWeek === 1;
9117
- if (isFirstDay && !isSunday) {
9118
- datesToReturn.push(createWeekRange(date, 8 - dayOfWeek));
9119
- return;
9120
- }
9121
- if (isLastDay && !isSunday) {
9122
- if (!isMonday) {
9123
- datesToReturn.pop();
9124
- }
9125
- const firstOfWeek = getFirstDayOfWeek(date);
9126
- datesToReturn.push(createWeekRange(firstOfWeek, dayOfWeek));
9127
- return;
9128
- }
9129
- if (isMonday) {
9130
- datesToReturn.push(createWeekRange(date, 7));
9131
- return;
9132
- }
9133
- // this is because sunday is 0
9134
- if (isFirstDay && isSunday) {
9135
- datesToReturn.push(createWeekRange(date, 1));
9136
- return;
9137
- }
9138
- });
9139
- return datesToReturn;
9140
- };
9141
- const createWeekRange = (start, days) => {
9142
- const end = new Date(start);
9143
- end.setDate(end.getDate() + days - 1);
9144
- return {
9145
- days,
9146
- start,
9147
- end,
9148
- isShortWeek: days < 7
9149
- };
9150
- };
9151
- const getFirstDayOfWeek = (date) => {
9152
- const currentDate = new Date(date);
9153
- const dayOfWeek = currentDate.getDay();
9154
- // dayOfWeek 0 == (Sunday)
9155
- const diffToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
9156
- // Set the date to the first day of the week
9157
- currentDate.setDate(currentDate.getDate() - diffToMonday);
9158
- return currentDate;
9159
- };
9160
-
9161
- const DayHeader = ({ index, text, width, headerType }) => {
9162
- const isFirstDay = index == 0;
9163
- return (jsxRuntime.jsx("td", { style: {
9164
- display: "inline-block",
9165
- fontSize: "10px",
9166
- width: width,
9167
- maxWidth: width,
9168
- }, id: headerType + index, children: jsxRuntime.jsx("span", { className: isFirstDay ? "cwelltFirstDate_desc" : "", children: text }) }));
9169
- };
9170
-
9171
- const MonthHeader = ({ index, text, width, headerType }) => {
9172
- return (jsxRuntime.jsx("td", { style: {
9173
- display: "inline-block",
9174
- fontSize: "10px",
9175
- width: width,
9176
- maxWidth: width,
9177
- }, id: headerType + index, children: jsxRuntime.jsx("span", { children: text }) }));
9178
- };
9179
-
9180
- const WeekHeader = ({ index, text, width, headerType }) => {
9181
- const isFirstDay = index == 0;
9182
- return (jsxRuntime.jsx("td", { style: {
9183
- display: "inline-block",
9184
- fontSize: "10px",
9185
- width: width,
9186
- maxWidth: width,
9187
- }, id: headerType + index, children: jsxRuntime.jsx("span", { className: isFirstDay ? "cwelltFirstDate_desc" : "", style: { whiteSpace: "nowrap" }, children: text }) }));
9188
- };
9189
-
9190
- const DaysHeader = ({ days, divisionType, maxWidth, headerType }) => {
9191
- let headerToDraw = [];
9192
- const filteredDays = days.filter((date) => {
9193
- return date.getHours() === 0;
9194
- });
9195
- const dateFormatter = (date) => {
9196
- return `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;
9197
- };
9198
- switch (divisionType) {
9199
- case "d":
9200
- {
9201
- headerToDraw = filteredDays.map((date, index) => {
9202
- return (jsxRuntime.jsx(DayHeader, { text: dateFormatter(date), index: index, width: maxWidth / filteredDays.length, headerType: headerType }, index));
9203
- });
9204
- }
9205
- break;
9206
- case "w":
9207
- {
9208
- const weekRanges = listOfDatesToWeekRangeList(filteredDays);
9209
- headerToDraw = getWeekHeaderDataFromWeekRange(weekRanges, maxWidth, dateFormatter).map((week, index) => {
9210
- return (jsxRuntime.jsx(WeekHeader, { index: index, text: week.formattedString, width: week.width, headerType: headerType }, index));
9211
- });
9212
- }
9213
- break;
9214
- case "m":
9215
- {
9216
- const monthData = getMonthHeaderData(filteredDays, maxWidth);
9217
- headerToDraw = monthData.map(({ monthFormatted, width }, index) => (jsxRuntime.jsx(MonthHeader, { index: index, text: monthFormatted, width: width, headerType: headerType }, index)));
9218
- }
9219
- break;
9220
- }
9221
- return jsxRuntime.jsx("tr", { className: "cwelltSchRowDate", children: headerToDraw });
9222
- };
9223
-
9224
- function formatHHmm(date) {
9225
- const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
9226
- const zdt = Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTimeISO(timeZone);
9227
- return `${zdt.hour.toString().padStart(2, "0")}:${zdt.minute.toString().padStart(2, "0")}`;
9228
- }
9229
- const getFormattedTimeForHeader = (calculatedDivType, calculatedDivision, timeHeader) => {
9230
- let showDate = "";
9231
- switch (calculatedDivType) {
9232
- case "d":
9233
- switch (calculatedDivision) {
9234
- case 8:
9235
- showDate =
9236
- timeHeader.getHours() === 0 ||
9237
- timeHeader.getHours() === 3 ||
9238
- timeHeader.getHours() === 6 ||
9239
- timeHeader.getHours() === 9 ||
9240
- timeHeader.getHours() === 12 ||
9241
- timeHeader.getHours() === 15 ||
9242
- timeHeader.getHours() === 18 ||
9243
- timeHeader.getHours() === 21
9244
- ? formatHHmm(timeHeader)
9245
- : "";
9246
- break;
9247
- case 3:
9248
- showDate =
9249
- timeHeader.getHours() === 0 || timeHeader.getHours() === 8 || timeHeader.getHours() === 16
9250
- ? formatHHmm(timeHeader)
9251
- : "";
9252
- break;
9253
- case 2:
9254
- showDate =
9255
- timeHeader.getHours() === 0 || timeHeader.getHours() === 12 ? formatHHmm(timeHeader) : "";
9256
- break;
9257
- }
9258
- break;
9259
- case "m":
9260
- showDate = timeHeader.getHours() === 0 ? timeHeader.getDate().toString() : "";
9261
- break;
9262
- case "w":
9263
- showDate = timeHeader.getHours() === 0 ? timeHeader.getDate().toString() : "";
9264
- break;
9265
- }
9266
- return {
9267
- text: showDate,
9268
- isWeekend: timeHeader.getDay() === 6 || timeHeader.getDay() === 0,
9269
- };
9270
- };
9271
-
9272
- const calculateDivisions = (start, end) => {
9273
- const diffDays = daysBetweenTwoDates(start, end);
9274
- if (diffDays <= 3) {
9275
- return 8;
9276
- }
9277
- else if (diffDays < 8) {
9278
- return 3;
9279
- }
9280
- else if (diffDays <= 15) {
9281
- return 2;
9282
- }
9283
- else {
9284
- return 1;
9285
- }
9286
- };
9287
-
9288
- const TimeHeader = ({ isWeekend, index, text, width, header }) => {
9289
- if (text === "") {
9290
- return;
9291
- }
9292
- const commonStyles = {
9293
- display: "flex",
9294
- alignItems: "center",
9295
- justifyContent: "left",
9296
- fontSize: "10px",
9297
- width: width,
9298
- maxWidth: width,
9299
- height: "30px",
9300
- borderLeft: "1px solid white",
9301
- background: isWeekend ? "#cbc9c9" : "",
9302
- color: "#000000d9",
9303
- fontWeight: 700,
9304
- };
9305
- return (jsxRuntime.jsx("td", { style: commonStyles, id: `${header}Time${index}`, children: jsxRuntime.jsx("span", { style: { paddingLeft: "8px" }, children: text }) }, `t${index}`));
9306
- };
9307
-
9308
- const TimeHeaderRow = ({ timeHeaders, startDate, endDate, maxWidth, header }) => {
9309
- const calculatedDivision = calculateDivisions(startDate, endDate);
9310
- const calculatedDivType = calculateDivisionType(startDate, endDate);
9311
- const formattedHeaders = timeHeaders.map((th) => {
9312
- return getFormattedTimeForHeader(calculatedDivType, calculatedDivision, th);
9313
- });
9314
- const filteredHeaders = formattedHeaders.filter((element) => element.text !== "");
9315
- return (jsxRuntime.jsx("tr", { className: "cwelltSchRowTime", style: { height: "30px" }, children: filteredHeaders.map(({ text, isWeekend }, index) => {
9316
- return (jsxRuntime.jsx(TimeHeader, { isWeekend: isWeekend, index: index, text: text, width: maxWidth / filteredHeaders.length, header: header }, index));
9317
- }) }));
9318
- };
9319
-
9320
- const SchedulerTimeLine = ({ maxPx, hoursList, startDate, endDate, pxPerHour, headerName, }) => {
9321
- return (jsxRuntime.jsx("table", { className: "content-area cwelltSchTable", style: { width: maxPx }, children: jsxRuntime.jsxs("tbody", { style: { width: "100%", borderSpacing: 0 }, className: "content-area cwelltSchTbody", children: [jsxRuntime.jsx(DaysHeader, { days: hoursList, divisionType: calculateDivisionType(startDate, endDate), maxWidth: pxPerHour * hoursList.length, headerType: headerName ?? "schedulerDateHeader" }), jsxRuntime.jsx(TimeHeaderRow, { timeHeaders: hoursList, startDate: startDate, endDate: endDate, maxWidth: pxPerHour * hoursList.length, header: headerName ?? "schedulerTimeHeader" })] }) }));
9322
- };
9323
-
9324
- const SchedulerHeader$1 = ({ timelineProps, descriptionColumn }) => {
9325
- const { maxPx, hoursList, startDate, endDate, pxPerHour, headerName } = timelineProps;
9326
- return (jsxRuntime.jsx("thead", { className: "cwellt_fc_header_scheduler", style: { position: "sticky", zIndex: 9 }, children: jsxRuntime.jsxs("tr", { className: "cwellt_fc_header_row", children: [jsxRuntime.jsxs("td", { className: "border", style: {
9327
- position: "sticky",
9328
- top: 0,
9329
- backgroundColor: "white",
9330
- width: "100px",
9331
- }, children: [jsxRuntime.jsx("div", { style: {
9332
- display: "flex",
9333
- height: "30px",
9334
- alignItems: "center",
9335
- width: "150px",
9336
- }, children: jsxRuntime.jsx("label", { children: headerName }) }), jsxRuntime.jsx("div", { style: {
9337
- display: "flex",
9338
- height: "30px",
9339
- alignItems: "center",
9340
- background: "rgba(0, 0, 0, 0.04)",
9341
- }, children: jsxRuntime.jsx("span", { children: descriptionColumn }) })] }), jsxRuntime.jsx("td", { style: {
9342
- position: "sticky",
9343
- top: 0,
9344
- zIndex: 6,
9345
- backgroundColor: "white",
9346
- }, children: jsxRuntime.jsx(SchedulerTimeLine, { maxPx: maxPx, hoursList: hoursList, pxPerHour: pxPerHour, startDate: startDate, endDate: endDate, headerName: headerName }) })] }) }));
9347
- };
9348
-
9349
- const daysBetweenTwoDatesIncludingBoth = (date1, date2) => {
9350
- const diff = Math.abs(date1.getTime() - date2.getTime());
9351
- const diffDays = diff / (1000 * 3600 * 24);
9352
- return diffDays;
9353
- };
9354
-
9355
- const getUtcToday = () => {
9356
- const now = new Date();
9357
- const userTimezoneOffset = now.getTimezoneOffset() * 60000;
9358
- const nowUtc = new Date(now.getTime() + userTimezoneOffset);
9359
- return nowUtc;
9360
- };
9361
-
9362
- const filterEvents = (events, start, end, id, module = undefined) => {
9363
- const datesCollide = (event) => event.start <= end && event.end >= start;
9364
- let eventsFiltered = events.filter(event => datesCollide(event));
9365
- if (id !== "flightWatchScheduler") {
9366
- eventsFiltered = sortByDate(eventsFiltered);
9367
- }
9368
- if (id !== "crewAssignmentsScheduler" && id !== "vacationsScheduler") {
9369
- return eventsFiltered;
9370
- }
9371
- eventsFiltered = setNotFullHeightEventsFirst(eventsFiltered);
9372
- if (module === "CrewControl") {
9373
- eventsFiltered = removeDuplicated(eventsFiltered, "Crew_Id");
9374
- }
9375
- if (module === "CrewScheduling") {
9376
- eventsFiltered = removeDuplicated(eventsFiltered, "AssignmentID");
9377
- }
9378
- if (module === "CrewSchedulingVacations") {
9379
- eventsFiltered = removeDuplicated(eventsFiltered, "ID");
9380
- }
9381
- return eventsFiltered;
9382
- };
9383
- const sortByDate = (events) => events.sort((a, b) => +new Date(a.start) - +new Date(b.start));
9384
- const removeDuplicated = (events, key) => {
9385
- return events.filter((obj, index, self) => index === self.findIndex(o => o.data[key] === obj.data[key] && o.data.subject === obj.data.subject));
9386
- };
9387
- const setNotFullHeightEventsFirst = (events) => {
9388
- const notFullHeight = [];
9389
- const isFullHeight = [];
9390
- events.forEach(element => {
9391
- element.isFullHeight ? notFullHeight.push(element) : isFullHeight.push(element);
9392
- });
9393
- return notFullHeight.concat(isFullHeight);
9394
- };
9395
-
9396
- const compareStrings = (str1, str2) => {
9397
- if (str1 > str2)
9398
- return 1;
9399
- if (str1 < str2)
9400
- return -1;
9401
- return 0;
9402
- };
9403
-
9404
- const filterResources = (module, resourceName, resources, groupByFunction, endDate, startDate, scheduleName) => {
9405
- if ((module === "CrewControl" || module === "CrewScheduling" || module === "CrewSchedulingVacations") &&
9406
- resourceName === "Employees") {
9407
- resources = resources.filter(c => (c.data.Eintritt === null || (new Date(c.data.Eintritt) <= endDate)) && (c.data.Austritt === null || (new Date(c.data.Austritt) >= startDate)));
9408
- }
9409
- if (scheduleName === "crewPinnedScheduler" || (module === "CrewControl" || module === "CrewScheduling") && resourceName === "Employees") {
9410
- const sortKey = (groupByFunction || scheduleName === "crewPinnedScheduler") ? "mainFunction" : "C3_LC";
9411
- resources = resources.sort((a, b) => compareStrings(a.data[sortKey], b.data[sortKey]));
9412
- }
9413
- return resources;
9414
- };
9415
-
9416
- const heightScheduler = (resources, visibleRows, isPinnerScheduler) => {
9417
- if (resources.length <= 0) {
9418
- return 100;
9419
- }
9420
- const realVisibleRows = visibleRows > resources.length ? resources.length : visibleRows;
9421
- const rowsHeight = resources.slice(0, realVisibleRows).map((row) => {
9422
- return row.maxTop;
9423
- });
9424
- const height = rowsHeight.reduce((sum, row) => {
9425
- return sum + row;
9426
- }, 0);
9427
- const headerHeight = isPinnerScheduler ? 0 : 60;
9428
- return height + headerHeight;
9429
- };
9430
-
9431
- const getLeftPixels = (eventStart, scheduleStart, dayPx) => {
9432
- if (scheduleStart >= eventStart)
9433
- return 0;
9434
- return daysBetweenTwoDatesIncludingBoth(scheduleStart, eventStart) * dayPx;
9435
- };
9436
- const getEventWithSize = (event, schedulerStart, dayPx) => {
9437
- const eventStartBeforeScheduleStart = event.start.getTime() < schedulerStart.getTime();
9438
- const lengthOfEvent = daysBetweenTwoDatesIncludingBoth(event.start, event.end);
9439
- const daysUntilSchedulerStart = daysBetweenTwoDatesIncludingBoth(event.start, schedulerStart);
9440
- const daysLong = eventStartBeforeScheduleStart ? lengthOfEvent - daysUntilSchedulerStart : lengthOfEvent;
9441
- // we want minimum of 8 px
9442
- const eventMinSize = 8;
9443
- const newEvent = {
9444
- ...event,
9445
- leftPx: getLeftPixels(event.start, schedulerStart, dayPx),
9446
- width: Math.max(daysLong * dayPx, eventMinSize),
9447
- };
9448
- return newEvent;
9449
- };
9450
-
9451
- const checkIfSlotAvailable = (events, event) => {
9452
- if (events.length == 0)
9453
- return true;
9454
- const collide = events.some(existent => {
9455
- return !(existent.end <= event.start || event.end <= existent.start) && !existent.isFullHeight;
9456
- });
9457
- return !collide;
9458
- };
9459
-
9460
- const getEventsInInnerRows = (res, eventHeight, dayPx, start) => {
9461
- let maxTop = 0;
9462
- const tops = [];
9463
- tops[0] = new Array();
9464
- res.events
9465
- .map((e) => {
9466
- return getEventWithSize(e, start, dayPx);
9467
- })
9468
- .forEach((event, i) => {
9469
- if (i === 0 || event.isFullHeight) {
9470
- event.top = 0;
9471
- tops[0].push(event);
9472
- }
9473
- else {
9474
- let found = false;
9475
- for (let j = 0; j < tops.length && found === false; j++) {
9476
- found = checkIfSlotAvailable(tops[j], event);
9477
- if (found === true || event.isFullHeight) {
9478
- event.top = j * eventHeight;
9479
- tops[j].push(event);
9480
- break;
9481
- }
9482
- }
9483
- if (found === false && !event.isFullHeight) {
9484
- maxTop++;
9485
- tops[maxTop] = new Array();
9486
- event.top = maxTop * eventHeight;
9487
- tops[maxTop].push(event);
9488
- }
9489
- else {
9490
- // This is for flightwatch
9491
- if (found === true && event.data.order === 2 && maxTop < 1) {
9492
- maxTop++;
9493
- tops[maxTop] = new Array();
9494
- event.top = maxTop * eventHeight;
9495
- tops[maxTop].push(event);
9496
- maxTop--;
9497
- }
9498
- }
9499
- }
9500
- });
9501
- return tops;
9502
- };
9503
-
9504
- const getTimeHeaders = (startDate, endDate) => {
9505
- const dateArray = new Array();
9506
- const currentDate = new Date(startDate);
9507
- const startOffset = Math.abs(startDate.getTimezoneOffset());
9508
- const endOffset = Math.abs(endDate.getTimezoneOffset());
9509
- // Summer: +1 -> +2, true
9510
- // Winter: +2 -> -1, false
9511
- const offsetSummerWinter = startOffset < endOffset;
9512
- if (offsetSummerWinter === true) {
9513
- while (currentDate < endDate) {
9514
- if (dateArray.length > 0) {
9515
- const lastPosition = dateArray[dateArray.length - 1];
9516
- const differenceHours = currentDate.getHours() - lastPosition.getHours();
9517
- if (differenceHours === 1 || differenceHours < 0) {
9518
- dateArray.push(new Date(currentDate));
9519
- }
9520
- else if (differenceHours > 1) {
9521
- dateArray.push(new Date(currentDate.getHours() - 1));
9522
- dateArray.push(new Date(currentDate));
9523
- }
9524
- }
9525
- else {
9526
- dateArray.push(new Date(currentDate));
9527
- }
9528
- currentDate.setHours(currentDate.getHours() + 1);
9529
- }
9530
- }
9531
- else {
9532
- while (currentDate < endDate) {
9533
- dateArray.push(new Date(currentDate));
9534
- currentDate.setHours(currentDate.getHours() + 1);
9535
- }
9536
- }
9537
- return dateArray;
9538
- };
9539
-
9540
- class CwScheduler extends React.Component {
9541
- contentArea;
9542
- calculateMaxPx = () => {
9543
- const mainElement = document.body;
9544
- const mainRect = mainElement.getBoundingClientRect();
9545
- return Math.floor(mainRect.width - 190);
9546
- };
9547
- constructor(props) {
9548
- super(props);
9549
- const maxPx = this.calculateMaxPx();
9550
- const timeHeaders = getTimeHeaders(props.startDate, props.endDate);
9551
- const dayPx = maxPx / Math.floor(daysBetweenTwoDates(props.startDate, props.endDate));
9552
- const hourPx = dayPx / 24;
9553
- const minutePx = dayPx / 1440;
9554
- window?.addEventListener("resize", this.handleResize);
9555
- const divisions = calculateDivisions(this.props.startDate, this.props.endDate);
9556
- const divisionsLeftPx = timeHeaders
9557
- .filter((_, index) => {
9558
- return index != 0 && index % (24 / divisions) == 0;
9559
- })
9560
- .map((date) => {
9561
- const daysDiff = daysBetweenTwoDatesIncludingBoth(date, props.startDate);
9562
- const pixels = daysDiff * 24 * hourPx;
9563
- return pixels;
9564
- });
9565
- this.state = {
9566
- maxPx: maxPx,
9567
- dayPx: dayPx,
9568
- hourPx: hourPx,
9569
- minutePx: minutePx,
9570
- timeHeaders: timeHeaders,
9571
- divisionsLeftPx: divisionsLeftPx,
9572
- eventHeight: 30,
9573
- resources: props.resources,
9574
- lineStyle: 0,
9575
- nowUtc: getUtcToday(),
9576
- division: divisions,
9577
- divisionType: "",
9578
- pinnedResources: props.pinnedResources ? props.pinnedResources : [],
9579
- selectedEvents: [],
9580
- showConsoleLogs: false, // Change to false to not show the console.log(...)
9581
- };
9582
- }
9583
- handleResize = () => {
9584
- const maxPx = this.calculateMaxPx();
9585
- const days = Math.floor(daysBetweenTwoDates(this.props.startDate, this.props.endDate));
9586
- const dayPx = maxPx / days;
9587
- const hourPx = dayPx / 24;
9588
- const updated = { ...this.state, maxPx: maxPx, hourPx: hourPx, dayPx: dayPx };
9589
- this.setState(updated);
9590
- };
9591
- objectsEqual = (o1, o2) => {
9592
- Object.keys(o1).length === Object.keys(o2).length && Object.keys(o1).every((p) => o1[p] === o2[p]);
9593
- };
9594
- objectsEqualDeep = (o1, o2) => typeof o1 === "object" && Object.keys(o1).length > 0
9595
- ? Object.keys(o1).length === Object.keys(o2).length &&
9596
- Object.keys(o1).every((p) => this.objectsEqual(o1[p], o2[p]))
9597
- : o1 === o2;
9598
- arraysEqual = (a1, a2) => a1.length === a2.length && a1.every((o, idx) => this.objectsEqualDeep(o, a2[idx]));
9599
- componentWillReceiveProps(_nextProps) {
9600
- if (this.state.showConsoleLogs) {
9601
- console.log("Schedule - componentWillReceiveProps, start: ", new Date());
9602
- console.log("Schedule - componentWillReceiveProps - has changes, start: ", new Date());
9603
- }
9604
- const dateChange = _nextProps.startDate.toISOString() !== this.props.startDate.toISOString() ||
9605
- _nextProps.endDate.toISOString() !== this.props.endDate.toISOString();
9606
- if (dateChange) {
9607
- const startDate = _nextProps.startDate;
9608
- const endDate = _nextProps.endDate;
9609
- const maxPx = this.calculateMaxPx();
9610
- const timeHeaders = getTimeHeaders(startDate, endDate);
9611
- const days = Math.floor(daysBetweenTwoDates(startDate, endDate));
9612
- const dayPx = maxPx / days;
9613
- const hourPx = dayPx / 24;
9614
- const minutePx = dayPx / 1440;
9615
- const now = getUtcToday();
9616
- const isInDateRange = now >= startDate && now <= endDate && this.contentArea !== undefined;
9617
- const lineStyle = isInDateRange ? daysBetweenTwoDatesIncludingBoth(startDate, now) * dayPx : 0;
9618
- const divisions = calculateDivisions(startDate, endDate);
9619
- const divisionsLeftPx = timeHeaders
9620
- .filter((_, index) => {
9621
- return index != 0 && index % (24 / divisions) == 0;
9622
- })
9623
- .map((date) => {
9624
- const daysDiff = daysBetweenTwoDatesIncludingBoth(date, startDate);
9625
- const pixels = daysDiff * dayPx;
9626
- return pixels;
9627
- });
9628
- this.setState({
9629
- maxPx: maxPx, // window.screen.width * 0.9,
9630
- dayPx: dayPx,
9631
- hourPx: hourPx,
9632
- minutePx: minutePx,
9633
- timeHeaders: timeHeaders,
9634
- divisionsLeftPx: divisionsLeftPx,
9635
- resources: this.getNewResources(_nextProps, dayPx),
9636
- lineStyle: lineStyle,
9637
- nowUtc: now,
9638
- division: divisions,
9639
- divisionType: "",
9640
- pinnedResources: this.props.pinnedResources ?? [],
9641
- });
9642
- if (this.state.showConsoleLogs) {
9643
- console.log("Schedule - componentWillReceiveProps - print on schedule, end: ", new Date());
9644
- console.log("Schedule - componentWillReceiveProps, end: ", new Date());
9645
- }
9646
- return;
9647
- }
9648
- const areSameEvents = this.arraysEqual(_nextProps.events, this.props.events);
9649
- const areSameRows = this.arraysEqual(_nextProps.resources, this.props.resources);
9650
- if (!areSameEvents || !areSameRows) {
9651
- const startDate = _nextProps.startDate;
9652
- const endDate = _nextProps.endDate;
9653
- const maxPx = this.calculateMaxPx();
9654
- const days = Math.floor(daysBetweenTwoDates(startDate, endDate));
9655
- const dayPx = maxPx / days;
9656
- this.setState({
9657
- resources: this.getNewResources(_nextProps, dayPx),
9658
- });
9659
- return;
9660
- }
9661
- }
9662
- getNewResources = (_nextProps, dayPx) => {
9663
- const mappedEvents = filterEvents(_nextProps.events, _nextProps.startDate, _nextProps.endDate, this.props.id, this.props.module)
9664
- .filter((event) => {
9665
- const outOfRange = event.end <= this.props.startDate || event.start >= this.props.endDate;
9666
- return !outOfRange;
9667
- });
9668
- const resources = filterResources(this.props.module, this.props.resourceName, _nextProps.resources, this.props.groupByFunction, _nextProps.endDate, _nextProps.startDate, this.props.id);
9669
- const newResources = resources
9670
- .map((resource) => {
9671
- return {
9672
- ...resource,
9673
- events: mappedEvents.filter((event) => event.resourceId === resource.id),
9674
- };
9675
- })
9676
- .map((resource) => {
9677
- const tops = getEventsInInnerRows(resource, this.state.eventHeight, dayPx, _nextProps.startDate);
9678
- const height = tops.length === 0 ? this.state.eventHeight : tops.length * this.state.eventHeight;
9679
- let flatMapEvents = [];
9680
- for (let h = 0; h < tops.length; h++) {
9681
- flatMapEvents = flatMapEvents.concat(tops[h]);
9682
- }
9683
- return {
9684
- ...resource,
9685
- maxTop: height,
9686
- events: flatMapEvents,
9687
- };
9688
- });
9689
- return newResources;
9690
- };
9691
- handleOnClickContextMenuResourceScheduler = (_clickEvent, _resource) => {
9692
- let datetime = new Date();
9693
- const _ca = this.contentArea;
9694
- if (_clickEvent.domEvent.currentTarget !== undefined) {
9695
- const leftPos = _clickEvent.domEvent.currentTarget.parentElement.getBoundingClientRect().left -
9696
- (_ca?.getBoundingClientRect()?.left ?? 0) -
9697
- window.scrollX;
9698
- datetime = addMinutesToDateFromPx(this.props.startDate, leftPos, this.state.minutePx);
9699
- }
9700
- if (this.props.scheduler_handleOnClickContextMenuResource) {
9701
- this.props.scheduler_handleOnClickContextMenuResource(datetime, _resource, _clickEvent.key, this.props.id);
9702
- }
9703
- };
9704
- handleCrewPinning = (resource, text) => {
9705
- if (this.props.scheduler_handlePinned) {
9706
- this.props.scheduler_handlePinned.call(this.props.parent, resource.id, text, this.props.id);
9707
- }
9708
- };
9709
- render() {
9710
- const isInDateRange = this.state.nowUtc >= this.props.startDate &&
9711
- this.state.nowUtc <= this.props.endDate &&
9712
- this.contentArea !== undefined;
9713
- const showTimeline = isInDateRange && this.state.lineStyle < this.state.maxPx;
9714
- const isPinnedTable = this.props.id.toLowerCase().includes("pinned");
9715
- const schedulerHeight = heightScheduler(this.state.resources, this.props.height, this.props.id === "crewAssignmentsScheduler");
9716
- return (jsxRuntime.jsx("div", { id: this.props.id, style: {
9717
- maxHeight: isPinnedTable ? "auto" : schedulerHeight,
9718
- }, className: this.state.resources.length > 0 ? "cwellt_tb_con" : "cwellt_tb_con cw_tb_con_emptyValues", children: jsxRuntime.jsxs("table", { id: "cwelltTableScheduler", children: [this.props.id !== "crewAssignmentsScheduler" && (jsxRuntime.jsx(SchedulerHeader$1, { timelineProps: {
9719
- maxPx: this.state.maxPx,
9720
- hoursList: this.state.timeHeaders,
9721
- pxPerHour: this.state.hourPx,
9722
- startDate: this.props.startDate,
9723
- endDate: this.props.endDate,
9724
- headerName: this.props.resourceName,
9725
- }, descriptionColumn: this.props.descriptionColumn })), jsxRuntime.jsx("tbody", { style: {
9726
- width: this.state.maxPx + 150,
9727
- maxHeight: isPinnedTable ? "auto" : schedulerHeight,
9728
- }, className: isPinnedTable ? "fc-body cw-fc-body-pinned" : "fc-body", children: jsxRuntime.jsxs("tr", { className: "fc_body_row", children: [jsxRuntime.jsx(ResourcesTitleList, { resources: this.state.resources, canBePinned: this.props.canBePinned ?? false, includesPinned: this.props.id.toLowerCase().includes("pinned"), onCrewPinning: this.handleCrewPinning, onClickResourceContextMenu: (_e, resource) => {
9729
- if (this.props.scheduler_handleOnClickResourceContextMenu) {
9730
- this.props.scheduler_handleOnClickResourceContextMenu(_e, resource);
9731
- }
9732
- }, ResourceTitleComponent: this.props.resourceComp }), jsxRuntime.jsx("td", { className: "dividerArea" }), jsxRuntime.jsx(SchedulerContentArea, { now: this.state.nowUtc, showTimeline: showTimeline, timeSeparatorLeftPx: this.state.divisionsLeftPx, timeLineLeftPx: this.state.lineStyle, resources: this.state.resources, contextMenuContents: this.props.resourceContextMenuContents, scheduler: this, onEmptyClick: this.props.scheduler_handleEmptyClick, setContentArea: (n) => (this.contentArea = n), onClickContextMenu: this.handleOnClickContextMenuResourceScheduler })] }) })] }) }));
9733
- }
9734
- }
9735
-
9736
8856
  function dateFromPercentage(startDate, visibleDays, percentage) {
9737
8857
  const start = Temporal.Instant.fromEpochMilliseconds(startDate.getTime());
9738
8858
  const spanMs = Math.round(visibleDays) * 24 * 60 * 60 * 1000;
@@ -9873,7 +8993,7 @@ class OnClickContextMenu {
9873
8993
  }
9874
8994
  }
9875
8995
 
9876
- var styles$3 = {"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","scheduler-dates":"scheduler-header-module__scheduler-dates__O7ePQ","current-day":"scheduler-header-module__current-day__FpHiv","scheduler-hours":"scheduler-header-module__scheduler-hours__ZDCVj"};
8996
+ 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","scheduler-dates":"scheduler-header-module__scheduler-dates__O7ePQ","current-day":"scheduler-header-module__current-day__FpHiv","scheduler-hours":"scheduler-header-module__scheduler-hours__ZDCVj"};
9877
8997
 
9878
8998
  const getNow$1 = (isUtc) => {
9879
8999
  let now = new Date();
@@ -9939,7 +9059,7 @@ const HeaderTitle = ({ title, dividerText, width }) => {
9939
9059
  const SchedulerHeader = ({ content, divisions, visibleDays, selectedDate, width, onEvent, timeLinePercentage, isUtc }) => {
9940
9060
  const topWidth = (100 / visibleDays);
9941
9061
  const { title, classification } = content;
9942
- return (jsxRuntime.jsxs("div", { style: { display: "flex" }, 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) => {
9062
+ 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) => {
9943
9063
  e.preventDefault();
9944
9064
  const clickPercentage = getPercentageFromMouseEvent(e);
9945
9065
  const date = dateFromPercentage(selectedDate, visibleDays, clickPercentage);
@@ -10807,325 +9927,6 @@ const Scheduler = (props) => {
10807
9927
  class UiEvent {
10808
9928
  }
10809
9929
 
10810
- let topsCounter = 0;
10811
- class CwSuperScheduler extends React__namespace.Component {
10812
- constructor(Props) {
10813
- super(Props);
10814
- this.state = {
10815
- topsCalculated: 0,
10816
- height: 50,
10817
- dataConfig: this.props.dataConfig ? this.props.dataConfig : undefined,
10818
- pinnedResources: []
10819
- };
10820
- }
10821
- componentDidUpdate(_previousProps, _previousState) {
10822
- if (this.props.pinnedResources !== _previousProps.pinnedResources) {
10823
- let returnedTops = 0;
10824
- let returnedHeight = 50;
10825
- let data;
10826
- if (this.props.pinnedResources) {
10827
- const pinned = [...new Set(this.props.pinnedResources)];
10828
- for (let i = 0; i < pinned.length; i++) {
10829
- data = this.returnDynamicHeight(pinned[i], returnedTops);
10830
- returnedTops = data.topsCalculated;
10831
- returnedHeight = data.height;
10832
- }
10833
- this.setState({
10834
- topsCalculated: returnedTops,
10835
- height: returnedHeight !== 50 ? 80 + returnedHeight : 50,
10836
- pinnedResources: this.props.pinnedResources
10837
- });
10838
- }
10839
- }
10840
- }
10841
- scheduler_handleCblEventClick = (cblEvent, schedulerId) => {
10842
- this.props.scheduler_handleCblEventClick(cblEvent, schedulerId);
10843
- };
10844
- scheduler_handleCblEventClickRight = (cblEvent, schedulerId) => {
10845
- if (this.props.scheduler_handleCblEventClickRight) {
10846
- this.props.scheduler_handleCblEventClickRight(cblEvent, schedulerId);
10847
- }
10848
- };
10849
- scheduler_handleCblEventDoubleClick = (cblEvent, schedulerId) => {
10850
- this.props.scheduler_handleCblEventDoubleClick(cblEvent, schedulerId);
10851
- };
10852
- scheduler_handlePinnedClickMultipleIds = (resIds, schedulerId, requestString) => {
10853
- this.props.scheduler_handlePinningOfResources(resIds, "", schedulerId, requestString);
10854
- };
10855
- scheduler_handlePinnedClick = (resId, text, schedulerId) => {
10856
- const array = new Array();
10857
- array.push(resId);
10858
- this.props.scheduler_handlePinningOfResources(array, text, schedulerId, "resources");
10859
- };
10860
- returnDynamicHeight(pinned, topsCalculated) {
10861
- let height = 100;
10862
- let maxTop = 0;
10863
- const eventHeight = 30;
10864
- const tops = new Array();
10865
- tops[0] = new Array();
10866
- const diffDates = this.props.endDate.getTime() - this.props.startDate.getTime();
10867
- const diffDays = diffDates / (1000 * 3600 * 24);
10868
- const dateToFilter = new Date(this.props.startDate.getTime());
10869
- dateToFilter.setDate(dateToFilter.getDate() + diffDays);
10870
- let events = this.props.pinnedEvents !== undefined ? this.props.pinnedEvents : new Array();
10871
- events = events
10872
- .filter(x => pinned === x.resourceId && x.start >= this.props.startDate && x.start <= dateToFilter)
10873
- .sort((a, b) => {
10874
- return +new Date(a.start) - +new Date(b.start);
10875
- });
10876
- for (let i = 0; i < events.length; i++) {
10877
- const event = events[i];
10878
- if (i === 0 || event.isFullHeight) {
10879
- tops[0].push(event);
10880
- }
10881
- else {
10882
- let found = false;
10883
- for (let j = 0; j < tops.length && found === false; j++) {
10884
- found = this.checkIfSlotAvailable(tops[j], event);
10885
- if (found === true || event.isFullHeight) {
10886
- tops[j].push(event);
10887
- }
10888
- }
10889
- if (found === false) {
10890
- maxTop++;
10891
- tops[maxTop] = new Array();
10892
- tops[maxTop].push(event);
10893
- }
10894
- }
10895
- }
10896
- for (let h = 0; h < tops.length; h++) {
10897
- if (tops.length === 0) {
10898
- height = 100;
10899
- }
10900
- else {
10901
- height = (topsCalculated + tops.length) * eventHeight;
10902
- }
10903
- }
10904
- topsCounter = topsCounter + tops.length;
10905
- return {
10906
- topsCalculated: topsCalculated + tops.length,
10907
- height: height
10908
- };
10909
- }
10910
- checkIfSlotAvailable(array, event) {
10911
- let found = false;
10912
- if (array[array.length - 1].end <= event.start || array[array.length - 1].isFullHeight) {
10913
- found = true;
10914
- }
10915
- return found;
10916
- }
10917
- handleOnClickContextMenuResource = (date, resource, key, schedulerId) => {
10918
- let url = "";
10919
- switch (key) {
10920
- case "showReserves": {
10921
- // CrewControl
10922
- if (this.props.module === "CrewControl") {
10923
- url = "/Winops/CrewControl/CrewControlReact/GetCrewIdsOfReserve";
10924
- }
10925
- // CrewScheduling
10926
- if (this.props.module === "CrewScheduling") {
10927
- url = "/Winops/CrewPlanning/CrewPlanning/GetCrewIdsOfReserve";
10928
- }
10929
- const requestOptions = {
10930
- method: "POST",
10931
- headers: { "Content-Type": "application/json" },
10932
- body: JSON.stringify({
10933
- from: this.dateUTCString(this.props.startDate),
10934
- to: this.dateUTCString(this.props.endDate),
10935
- acftCategories: [],
10936
- functions: [],
10937
- clickedDate: this.dateUTCString(date),
10938
- airportSelected: this.props.airportSelected
10939
- })
10940
- };
10941
- if (this.state.dataConfig) {
10942
- fetch(this.state.dataConfig + url, requestOptions)
10943
- .then(response => response.json())
10944
- .then(res => {
10945
- if (res.length > 0) {
10946
- this.scheduler_handlePinnedClickMultipleIds(res, schedulerId, "Reserves");
10947
- }
10948
- else {
10949
- alert("No Reserves");
10950
- }
10951
- });
10952
- }
10953
- break;
10954
- }
10955
- case "showStandbys": {
10956
- // CrewControl
10957
- if (this.props.module === "CrewControl") {
10958
- url = "/Winops/CrewControl/CrewControlReact/GetCrewIdsOfStandby";
10959
- }
10960
- // CrewScheduling
10961
- if (this.props.module === "CrewScheduling") {
10962
- url = "/Winops/CrewPlanning/CrewPlanning/GetCrewIdsOfStandby";
10963
- }
10964
- const requestOptions2 = {
10965
- method: "POST",
10966
- headers: { "Content-Type": "application/json" },
10967
- body: JSON.stringify({
10968
- from: this.dateUTCString(this.props.startDate),
10969
- to: this.dateUTCString(this.props.startDate),
10970
- acftCategories: [],
10971
- functions: [],
10972
- clickedDate: this.dateUTCString(date),
10973
- airportSelected: this.props.airportSelected
10974
- })
10975
- };
10976
- if (this.state.dataConfig) {
10977
- fetch(this.state.dataConfig + url, requestOptions2)
10978
- .then(response => response.json())
10979
- .then(res => {
10980
- if (res.length > 0) {
10981
- this.scheduler_handlePinnedClickMultipleIds(res, schedulerId, "Standbys");
10982
- }
10983
- else {
10984
- alert("No Standbys");
10985
- }
10986
- });
10987
- }
10988
- break;
10989
- }
10990
- case "showAvailables": {
10991
- // CrewControl
10992
- if (this.props.module === "CrewControl") {
10993
- url = "/Winops/CrewControl/CrewControlReact/GetCrewIdsOfAvailables";
10994
- }
10995
- // CrewScheduling
10996
- if (this.props.module === "CrewScheduling") {
10997
- url = "/Winops/CrewPlanning/CrewPlanning/GetCrewIdsOfAvailables";
10998
- }
10999
- const requestOptions3 = {
11000
- method: "POST",
11001
- headers: { "Content-Type": "application/json" },
11002
- body: JSON.stringify({
11003
- from: this.dateUTCString(this.props.startDate),
11004
- to: this.dateUTCString(this.props.startDate),
11005
- acftCategories: [],
11006
- functions: [],
11007
- clickedDate: this.dateUTCString(date),
11008
- airportSelected: this.props.airportSelected
11009
- })
11010
- };
11011
- if (this.state.dataConfig) {
11012
- fetch(this.state.dataConfig + url, requestOptions3)
11013
- .then(response => response.json())
11014
- .then(res => {
11015
- if (res.length > 0) {
11016
- this.scheduler_handlePinnedClickMultipleIds(res, schedulerId, "Availables");
11017
- }
11018
- else {
11019
- alert("No Availables");
11020
- }
11021
- });
11022
- }
11023
- break;
11024
- }
11025
- default: {
11026
- if (this.props.scheduler_handleOnClickContextMenuResource) {
11027
- this.props.scheduler_handleOnClickContextMenuResource(date, resource, key);
11028
- }
11029
- break;
11030
- }
11031
- }
11032
- };
11033
- dateUTCString(date) {
11034
- if (date instanceof Date) {
11035
- if (date.getFullYear() > 1901)
11036
- return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes())).toISOString();
11037
- }
11038
- return date;
11039
- }
11040
- render() {
11041
- const havePinnedResources = this.state.pinnedResources?.length > 0;
11042
- const firstSchedulerResources = havePinnedResources
11043
- ? this.props.resourcesToPin.filter(x => this.state.pinnedResources.includes(x.id))
11044
- : new Array();
11045
- const secondSchedulerResources = this.props.resources.filter(x => !this.state.pinnedResources.includes(x.id));
11046
- const pinnedEvents = this.props.pinnedEvents !== undefined
11047
- ? this.props.pinnedEvents.filter(x => this.state.pinnedResources.includes(x.resourceId))
11048
- : new Array();
11049
- const notPinnedEvents = this.props.events.filter(x => !this.props.pinnedResources?.includes(x.resourceId));
11050
- return (jsxRuntime.jsxs("div", { className: "cwelltSuperScheduler_content", children: [jsxRuntime.jsx(CwScheduler, { id: "crewPinnedScheduler", events: pinnedEvents, resources: firstSchedulerResources, height: this.state.height, startDate: this.props.startDate, endDate: this.props.endDate, scheduler_handleCblEventClick: this.props.scheduler_handleCblEventClick, scheduler_handleCblEventClickRight: this.props.scheduler_handleCblEventClickRight, scheduler_handleCblEventDoubleClick: this.props.scheduler_handleCblEventDoubleClick, scheduler_handleOnDropCblEventsOnResource: this.props.scheduler_handleOnDropCblEventsOnResource, parent: this.props.parent, cblEventComp: this.props.cblEventComp, scheduler_handleOnClickEventContextMenu: this.props.scheduler_handleOnClickEventContextMenu, resourceComp: this.props.resourceComp, scheduler_handleOnClickContextMenuResource: this.props.scheduler_handleOnClickContextMenuResource, resourceContextMenuContents: this.props.resourceContextMenuContents, scheduler_handleDblClickOnResourceInScheduler: this.props.scheduler_handleDblClickOnResourceInScheduler, scheduler_handleEmptyClick: this.props.scheduler_handleEmptyClick, canBePinned: false, scheduler_handlePinned: this.scheduler_handlePinnedClick, resourceName: this.props.resourceName, descriptionColumn: this.props.descriptionColumn, scheduler_handleOnClickResourceContextMenu: this.props.scheduler_handleOnClickResourceContextMenu, groupByFunction: this.props.groupByFunction }), havePinnedResources && (jsxRuntime.jsx("div", { style: { padding: "0.5rem" }, children: jsxRuntime.jsx(CwButton, { text: "Clear", onClick: () => {
11051
- this.props.scheduler_handleClearPinnedOnParent();
11052
- } }) })), jsxRuntime.jsx(CwScheduler, { id: "crewAssignmentsScheduler", events: notPinnedEvents, resources: secondSchedulerResources, height: this.props.height, startDate: this.props.startDate, endDate: this.props.endDate, scheduler_handleCblEventClick: this.props.scheduler_handleCblEventClick, scheduler_handleCblEventClickRight: this.props.scheduler_handleCblEventClickRight, scheduler_handleCblEventDoubleClick: this.props.scheduler_handleCblEventDoubleClick, scheduler_handleOnDropCblEventsOnResource: this.props.scheduler_handleOnDropCblEventsOnResource, parent: this.props.parent, cblEventComp: this.props.cblEventComp, scheduler_handleOnClickEventContextMenu: this.props.scheduler_handleOnClickEventContextMenu, resourceComp: this.props.resourceComp, scheduler_handleOnClickContextMenuResource: this.handleOnClickContextMenuResource, resourceContextMenuContents: this.props.resourceContextMenuContents, scheduler_handleDblClickOnResourceInScheduler: this.props.scheduler_handleDblClickOnResourceInScheduler, scheduler_handleEmptyClick: this.props.scheduler_handleEmptyClick, canBePinned: true, scheduler_handlePinned: this.scheduler_handlePinnedClick, scheduler_handleCblEventResize: this.props.scheduler_handleCblEventResize, resourceName: this.props.resourceName, descriptionColumn: this.props.descriptionColumn, scheduler_handleOnClickResourceContextMenu: this.props.scheduler_handleOnClickResourceContextMenu, airportSelected: this.props.airportSelected, module: this.props.module, groupByFunction: this.props.groupByFunction })] }));
11053
- }
11054
- }
11055
- class CblDragAndDrop {
11056
- fromId;
11057
- toId;
11058
- data;
11059
- droppedOnDate;
11060
- resizeFromStart;
11061
- resizeFromEnd;
11062
- isCtrlKey;
11063
- constructor(fromId, toId, data, droppedOnDate = null, resizeFromStart = null, resizeFromEnd = null, isCtrlKey = null) {
11064
- this.fromId = fromId;
11065
- this.toId = toId;
11066
- this.data = data;
11067
- this.droppedOnDate = droppedOnDate;
11068
- this.resizeFromStart = resizeFromStart;
11069
- this.resizeFromEnd = resizeFromEnd;
11070
- this.isCtrlKey = isCtrlKey;
11071
- }
11072
- }
11073
-
11074
- const getGUID = () => {
11075
- return generateSegment(false) + generateSegment(true) + generateSegment(true) + generateSegment(false);
11076
- };
11077
- const generateSegment = (includeHyphens) => {
11078
- const p = (Math.random().toString(16) + "000000000").substring(2, 10);
11079
- return includeHyphens ? "-" + p.substring(0, 4) + "-" + p.substring(4, 8) : p;
11080
- };
11081
-
11082
- class cblEvent {
11083
- id = "";
11084
- start;
11085
- end;
11086
- resourceId;
11087
- selected = false;
11088
- top = 0;
11089
- leftPx = 0;
11090
- rightPx = 0;
11091
- width = 0;
11092
- isFullHeight = false;
11093
- isReadOnly = false;
11094
- isResizable = false;
11095
- isDraggable = false;
11096
- data = null;
11097
- constructor(start, end, resourceId, data = null, isFullHeight = false, isReadOnly = false, isResizable = false, isDraggable = false) {
11098
- this.start = start;
11099
- this.end = end;
11100
- this.resourceId = resourceId;
11101
- this.data = data;
11102
- this.isFullHeight = isFullHeight;
11103
- this.isReadOnly = isReadOnly;
11104
- this.isResizable = isResizable;
11105
- this.isDraggable = isDraggable;
11106
- this.id = getGUID();
11107
- }
11108
- }
11109
-
11110
- class Resource {
11111
- uid = "";
11112
- id;
11113
- name;
11114
- maxTop;
11115
- events = [];
11116
- isInViewport = false;
11117
- schedulerResourceDisplay;
11118
- isLoading = false;
11119
- data = null;
11120
- constructor(id, name, eventHeight, data = null, schedulerResourceDisplay = null) {
11121
- this.id = id;
11122
- this.name = name;
11123
- this.maxTop = eventHeight;
11124
- this.data = data;
11125
- this.schedulerResourceDisplay = schedulerResourceDisplay || this.name;
11126
- }
11127
- }
11128
-
11129
9930
  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"};
11130
9931
 
11131
9932
  class OnPinRow {
@@ -11608,10 +10409,10 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
11608
10409
  }, "data-direction": direction, children: [jsxRuntime.jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", 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, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (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 selected crewmember", variant: "icon", icon: "close", color: "neutral" })) : (jsxRuntime.jsx(CwIcon, { iconId: "person" })) })] })] }), renderPanel(jsxRuntime.jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsxRuntime.jsx("ul", { children: options.map((option, index) => (jsxRuntime.jsx("li", { className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.value), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.text }, option.value))) }) }))] }));
11609
10410
  };
11610
10411
 
11611
- exports.CblDragAndDrop = CblDragAndDrop;
11612
10412
  exports.CwAccordionContainer = CwAccordionContainer;
11613
10413
  exports.CwAlign = CwAlign;
11614
10414
  exports.CwAnchoredMenu = CwAnchoredMenu;
10415
+ exports.CwBadge = CwBadge;
11615
10416
  exports.CwBtnApprove = CwBtnApprove;
11616
10417
  exports.CwBtnCancel = CwBtnCancel;
11617
10418
  exports.CwBtnDelete = CwBtnDelete;
@@ -11678,7 +10479,6 @@ exports.CwPopoverButton = CwPopoverButton;
11678
10479
  exports.CwProgress = CwProgress;
11679
10480
  exports.CwRadioGroup = CwRadioGroup;
11680
10481
  exports.CwReportModal = CwReportModal;
11681
- exports.CwScheduler = CwScheduler;
11682
10482
  exports.CwSearchAsync = CwSearchAsync;
11683
10483
  exports.CwSearchInput = CwSearchInput;
11684
10484
  exports.CwSelect = CwSelect;
@@ -11687,7 +10487,6 @@ exports.CwSelectListItems = CwSelectListItems;
11687
10487
  exports.CwSkeleton = CwSkeleton;
11688
10488
  exports.CwSortableList = CwSortableList;
11689
10489
  exports.CwSortableTable = CwSortableTable;
11690
- exports.CwSuperScheduler = CwSuperScheduler;
11691
10490
  exports.CwTable = CwTable;
11692
10491
  exports.CwTableGrouped = CwTableGrouped;
11693
10492
  exports.CwTableServerSide = CwTableServerSide;
@@ -11725,14 +10524,12 @@ exports.OnStartClickHeaderEvent = OnStartClickHeaderEvent;
11725
10524
  exports.OnUnpinRow = OnUnpinRow;
11726
10525
  exports.PRESET_LIBRARY_TEMPORAL = PRESET_LIBRARY_TEMPORAL;
11727
10526
  exports.PinRowHeader = PinRowHeader;
11728
- exports.Resource = Resource;
11729
10527
  exports.Scheduler = Scheduler;
11730
10528
  exports.SchedulerEvent = SchedulerEvent;
11731
10529
  exports.SuperScheduler = SuperScheduler;
11732
10530
  exports.TooltipConstraintContext = TooltipConstraintContext;
11733
10531
  exports.UiEvent = UiEvent;
11734
10532
  exports.Weekdays = Weekdays;
11735
- exports.cblEvent = cblEvent;
11736
10533
  exports.configureCwLoading = configureCwLoading;
11737
10534
  exports.eventIsVisible = eventIsVisible;
11738
10535
  exports.filterNavItems = filterNavItems;