@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.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import React__default, { useState, useRef, useEffect, useCallback, useLayoutEffect, createContext, useContext, cloneElement, useMemo, forwardRef, useImperativeHandle, useId, createElement, memo, Fragment as Fragment$1, Component } from 'react';
3
+ import React__default, { useState, useRef, useEffect, useCallback, useLayoutEffect, createContext, useContext, cloneElement, useMemo, forwardRef, useId, useImperativeHandle, createElement, memo } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { createRoot } from 'react-dom/client';
6
6
  import Draggable from 'react-draggable';
@@ -161,7 +161,7 @@ function getContrastColor(color) {
161
161
  return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
162
162
  }
163
163
 
164
- var styles$x = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
164
+ var styles$y = {"cw-tooltip-content":"cw-tooltip-module__cw-tooltip-content__RZczd","cw-tooltip":"cw-tooltip-module__cw-tooltip__1KYig"};
165
165
 
166
166
  // Constants
167
167
  const margin$1 = 16;
@@ -451,7 +451,7 @@ const CwTooltipManager = () => {
451
451
  if (!state.isVisible || !state.content) {
452
452
  return null;
453
453
  }
454
- return createPortal(jsx("div", { ref: tooltipRef, className: styles$x["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
454
+ return createPortal(jsx("div", { ref: tooltipRef, className: styles$y["cw-tooltip-content"], "data-position": actualPosition, "data-visible": state.isVisible, "data-inline": state.displayInline, style: {
455
455
  top: `${tooltipPosition.top}px`,
456
456
  left: `${tooltipPosition.left}px`,
457
457
  opacity: (isPositioned && !isMeasuring) ? 1 : 0,
@@ -532,7 +532,7 @@ const CwTooltipNew = ({ children, content = null, position = "right", dissapears
532
532
  useEffect(() => {
533
533
  ensureTooltipManager();
534
534
  }, []);
535
- return (jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$x["cw-tooltip"], children: children }));
535
+ return (jsx("div", { ref: containerRef, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, className: styles$y["cw-tooltip"], children: children }));
536
536
  };
537
537
 
538
538
  const SVG_ICONS = {
@@ -567,25 +567,31 @@ function CwIcon(props) {
567
567
  /**
568
568
  * CwChip - A simple chip/tag component for displaying labels or categories
569
569
  *
570
+ * The colour comes from `color`; the older `colorScheme` spelling is deprecated but still
571
+ * honoured, and `color` wins when both are passed.
572
+ *
570
573
  * @example
571
- * <CwChip label="Active" colorScheme="success" />
572
- * <CwChip label="High Priority" colorScheme="danger" variant="solid" />
573
- * <CwChip label="Custom" colorScheme="custom" customColor="#8a2be2" />
574
- * <CwChip label="Outlined" colorScheme="info" variant="outline" />
574
+ * <CwChip label="Active" color="success" />
575
+ * <CwChip label="High Priority" color="danger" variant="solid" />
576
+ * <CwChip label="Custom" color="custom" customColor="#8a2be2" />
577
+ * <CwChip label="Outlined" color="info" variant="outline" />
575
578
  * <CwChip label="Removable" closable onClose={() => console.log('closed')} />
576
579
  **/
577
- const CwChip = ({ label, colorScheme = 'info', customColor, variant = 'soft', className = '', closable = false, onClose, icon, style = {}, }) => {
580
+ const CwChip = ({ label, color, colorScheme, customColor, variant = 'soft', className = '', closable = false, onClose, icon, style = {}, }) => {
581
+ const resolvedColor = color ?? colorScheme ?? 'info';
578
582
  // Basic validation
579
583
  if (closable && !onClose) {
580
584
  console.warn('CwChip: onClose prop is required when closable is true');
581
585
  }
582
- // Calculate styles based on colorScheme, customColor and variant
586
+ // One arbitrary colour can only fill two of the four roles, so soft and solid look alike here.
583
587
  const chipStyle = React__default.useMemo(() => {
584
588
  if (customColor) {
585
- // Simply set the CSS custom properties, CSS handles the rest
589
+ const contrast = getContrastColor(customColor);
586
590
  return {
587
- '--chip-accent': customColor,
588
- '--chip-text': getContrastColor(customColor),
591
+ '--accent-light': customColor,
592
+ '--accent-main': customColor,
593
+ '--accent-dark': contrast,
594
+ '--accent-on-main': contrast,
589
595
  ...style
590
596
  };
591
597
  }
@@ -604,7 +610,79 @@ const CwChip = ({ label, colorScheme = 'info', customColor, variant = 'soft', cl
604
610
  className,
605
611
  closable ? 'cw-chip-closable' : '',
606
612
  ].filter(Boolean).join(' ');
607
- return (jsxs("span", { className: chipClassNames, "data-color-scheme": colorScheme, "data-variant": variant, style: chipStyle, children: [icon && jsx(CwIcon, { iconId: icon }), label && jsx("span", { children: label }), closable && (jsx("button", { className: "cw-chip-close-button", onClick: handleClose, "aria-label": "Remove", type: "button", children: jsx("span", { className: "cwi-icons cwi-close" }) }))] }));
613
+ return (jsxs("span", { className: chipClassNames, "data-color": resolvedColor, "data-variant": variant, "data-icon-only": (Boolean(icon) && !label) || undefined, style: chipStyle, children: [icon && jsx(CwIcon, { iconId: icon }), label && jsx("span", { children: label }), closable && (jsx("button", { className: "cw-chip-close-button", onClick: handleClose, "aria-label": "Remove", type: "button", children: jsx("span", { className: "cwi-icons cwi-close" }) }))] }));
614
+ };
615
+
616
+ /**
617
+ * Normalises a raw count into the integer the badge represents: a non-negative whole number.
618
+ * Both the display string and the `showZero` decision derive from this.
619
+ */
620
+ function normalizeBadgeCount(count) {
621
+ return Number.isFinite(count) ? Math.max(0, Math.trunc(count)) : 0;
622
+ }
623
+ /**
624
+ * Formats a badge count into its display string. Both arguments are normalised, `max` with a
625
+ * floor of 1 - below that every non-zero count would overflow.
626
+ *
627
+ * @param count Raw count to display.
628
+ * @param max Highest value shown as a number; anything above renders `"{max}+"`.
629
+ *
630
+ * @example
631
+ * formatBadgeCount(7, 99); // "7"
632
+ * formatBadgeCount(100, 99); // "99+"
633
+ * formatBadgeCount(12, 9); // "9+"
634
+ */
635
+ function formatBadgeCount(count, max) {
636
+ const safeCount = normalizeBadgeCount(count);
637
+ const safeMax = Number.isFinite(max) ? Math.max(1, Math.trunc(max)) : 1;
638
+ return safeCount > safeMax ? `${safeMax}+` : `${safeCount}`;
639
+ }
640
+ /**
641
+ * Resolves the badge's accessibility attributes. A text-less badge with no label is hidden rather
642
+ * than announced as an empty element; the button or tab around it usually names the thing.
643
+ *
644
+ * @param label Caller-supplied accessible name.
645
+ * @param loading Whether the badge is showing its spinner.
646
+ * @param hasText Whether the badge renders a count or content.
647
+ */
648
+ function resolveBadgeAria(label, loading, hasText) {
649
+ if (label) {
650
+ return { role: loading ? 'status' : 'img', 'aria-label': label };
651
+ }
652
+ return hasText ? {} : { 'aria-hidden': 'true' };
653
+ }
654
+
655
+ var styles$x = {"badge":"cw-badge-module__badge__PKlak"};
656
+
657
+ /**
658
+ * CwBadge - the small coloured circle with a number, used for alert and notification counts.
659
+ *
660
+ * Always **in flow** (`inline-flex`); it never positions itself, so overlaying it on an icon
661
+ * button is the caller's job. One digit stays a circle, wider content such as `"99+"` grows into
662
+ * a pill. With neither `count` nor `content` it renders as a dot.
663
+ *
664
+ * Precedence: `loading` > `content` > `count` > dot. While loading the badge renders regardless
665
+ * of `showZero`, and the spinner replaces it - circle, background and padding come off.
666
+ *
667
+ * @example
668
+ * <CwBadge count={3} color="danger" />
669
+ * <CwBadge count={0} showZero={false} />
670
+ * <CwBadge count={128} max={99} color="warning" variant="soft" />
671
+ * <CwBadge color="warning" label="Unresolved findings" />
672
+ * <CwBadge count={0} loading />
673
+ */
674
+ const CwBadge = ({ count, content, color = 'info', variant = 'solid', size = 'small', showZero = true, loading = false, max = 99, label, className = '', style, }) => {
675
+ // null counts as absent, so `content={null}` still renders a dot rather than an empty pill.
676
+ const hasContent = content !== undefined && content !== null;
677
+ if (!loading && !hasContent && count !== undefined && !showZero && normalizeBadgeCount(count) === 0) {
678
+ return null;
679
+ }
680
+ const countText = !hasContent && count !== undefined
681
+ ? formatBadgeCount(count, max)
682
+ : undefined;
683
+ const isDot = !loading && !hasContent && count === undefined;
684
+ const badgeClassNames = ['cw-badge', styles$x.badge, className].filter(Boolean).join(' ');
685
+ return (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 ? jsx(CwIcon, { iconId: "spinner", size: "small" }) : hasContent ? content : countText }));
608
686
  };
609
687
 
610
688
  const CW_DEFAULT_MESSAGE_DURATION = 2000;
@@ -1058,7 +1136,7 @@ var styles$v = {"progress":"cw-progress-module__progress__d-g2-","value":"cw-pro
1058
1136
  * <CwProgress value={62} label="Import" color="success" />
1059
1137
  * <CwProgress indeterminate label="Uploading" />
1060
1138
  */
1061
- function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'regular', layout = 'row', color = 'primary', monoValue = false, prominent = false }) {
1139
+ function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'regular', layout = 'row', color = 'primary', monoValue = false, prominent = false, className }) {
1062
1140
  const labelId = React__default.useId();
1063
1141
  // Determinate: a missing or non-finite value is treated as 0 (never NaN), then
1064
1142
  // clamped to [0,100] for aria-valuenow and the fill width. Indeterminate has no value.
@@ -1070,7 +1148,7 @@ function CwProgress({ value, indeterminate = false, label, rightLabel, size = 'r
1070
1148
  const valueText = rightLabel ?? (percent !== undefined ? `${percent}%` : '');
1071
1149
  // The un-hashed cw-progress class carries no styles in the library - a stable
1072
1150
  // public hook for exceptional external overrides only.
1073
- const rootClassName = ['cw-progress', styles$v.progress].filter(Boolean).join(' ');
1151
+ const rootClassName = ['cw-progress', styles$v.progress, className].filter(Boolean).join(' ');
1074
1152
  const labelSpan = label ? jsx("span", { className: styles$v.label, id: labelId, children: label }) : null;
1075
1153
  const valueLabel = showValue ? (jsx("span", { className: styles$v.value, "data-mono": monoValue || undefined, children: valueText })) : null;
1076
1154
  return (jsxs("div", { className: rootClassName, "data-layout": layout, "data-size": size, "data-color": color, "data-prominent": prominent || undefined, "data-indeterminate": indeterminate || undefined, children: [layout === 'column' && (labelSpan || valueLabel) && (jsxs("header", { className: styles$v.header, children: [labelSpan, valueLabel] })), layout === 'row' && labelSpan, jsx("div", { className: styles$v.track, role: "progressbar", ...(label && { 'aria-labelledby': labelId }), ...(!indeterminate && percent !== undefined && {
@@ -1226,7 +1304,7 @@ const CwGenericTooltip = ({ children, content = null, position = defaultPosition
1226
1304
  return (jsxs("div", { ref: containerRef, className: styles$u["cw-generic-tooltip"], onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, style: overlayStyle, "data-inline": displayInline, children: [tooltipContent, children] }));
1227
1305
  };
1228
1306
 
1229
- const CwButton = React__default.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", children, ...buttonProps }, ref) {
1307
+ const CwButton = React__default.forwardRef(function CwButton({ text, variant = 'solid', color = 'primary', size = 'medium', iconPosition = 'left', pressed, className = '', icon = "", title, tooltipPosition = "bottom", badge, children, ...buttonProps }, ref) {
1230
1308
  // Build CSS classes based on variant and props
1231
1309
  let buttonClass = `cw-button-${variant}`;
1232
1310
  // Add icon class only for icon variant without children
@@ -1239,13 +1317,19 @@ const CwButton = React__default.forwardRef(function CwButton({ text, variant = '
1239
1317
  const tooltipContent = title || (variant === 'icon' && text ? text : undefined);
1240
1318
  const iconElement = icon ? jsx(CwIcon, { iconId: icon }) : null;
1241
1319
  const textElement = text ? jsx("strong", { children: text }) : null;
1320
+ // Overlaid, not content: the `cwi-` condition above deliberately ignores it, so a badge
1321
+ // never suppresses the button's own icon. Size defaulted explicitly, not by spread order,
1322
+ // so `size: undefined` in the object cannot clobber it.
1323
+ const badgeElement = badge
1324
+ ? jsx(CwBadge, { ...badge, size: badge.size ?? (variant === 'icon' ? 'small' : size) })
1325
+ : null;
1242
1326
  // Only emit toggle attributes when `pressed` is defined; otherwise output stays identical to a normal button.
1243
1327
  const pressedProps = pressed !== undefined
1244
1328
  ? { "aria-pressed": pressed, "data-pressed": pressed ? "true" : undefined }
1245
1329
  : {};
1246
- const buttonElement = (jsx("button", { ref: ref, type: "button", className: buttonClass, ...buttonProps, "data-color": color, "data-size": size, ...pressedProps, "aria-label": tooltipContent ?? buttonProps["aria-label"], children: variant === 'icon' ? null : (children ?? (iconPosition === 'right'
1247
- ? jsxs(Fragment, { children: [textElement, iconElement] })
1248
- : jsxs(Fragment, { children: [iconElement, textElement] }))) }));
1330
+ const buttonElement = (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 : (jsxs(Fragment, { children: [children ?? (iconPosition === 'right'
1331
+ ? jsxs(Fragment, { children: [textElement, iconElement] })
1332
+ : jsxs(Fragment, { children: [iconElement, textElement] })), badgeElement] })) }));
1249
1333
  return tooltipContent ? (jsx(CwTooltipNew, { content: tooltipContent, position: tooltipPosition, displayInline: true, children: buttonElement })) : (buttonElement);
1250
1334
  });
1251
1335
  CwButton.displayName = "CwButton";
@@ -2634,8 +2718,12 @@ function CwTableServerSide({ columns, data, totalItems, pagination = false, page
2634
2718
  }, min: 1, max: totalPages }), jsx("span", { children: "/" }), jsx("span", { children: totalPages }), jsx(CwButton, { onClick: () => handlePageChange(state.page + 1), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right" }), jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: state.page === totalPages || totalPages <= 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
2635
2719
  }
2636
2720
 
2637
- var styles$n = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","badge":"cw-tabs-module__badge__AmVxW","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2721
+ var styles$n = {"cw-tabs":"cw-tabs-module__cw-tabs__1pmji","cw-tabs-content":"cw-tabs-module__cw-tabs-content__HTp8d"};
2638
2722
 
2723
+ const BADGE_COLOR_SCHEMES = ['primary', 'danger', 'warning', 'success', 'info', 'neutral'];
2724
+ function isBadgeColorScheme(value) {
2725
+ return BADGE_COLOR_SCHEMES.includes(value);
2726
+ }
2639
2727
  const TabIcon = ({ icon }) => {
2640
2728
  if (!icon)
2641
2729
  return null;
@@ -2684,7 +2772,11 @@ function CwTabs(CwTabsProps) {
2684
2772
  const tabsListStyle = position === 'left' && CwTabsProps.tabsListWidth
2685
2773
  ? { minWidth: CwTabsProps.tabsListWidth }
2686
2774
  : undefined;
2687
- return (jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$n['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => (jsxs("li", { className: `${tab.key === activeTab ? "cw-tab-active" : ""}`, onClick: () => handleTabClick(tab), "data-active": tab.key === activeTab, "data-tab-key": tab.key, children: [jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (jsx("span", { className: styles$n['badge'], style: tab.badgeColor ? { backgroundColor: tab.badgeColor, color: getContrastColor(tab.badgeColor) } : undefined, children: tab.badge }))] }, tab.key))) }), jsx("div", { className: styles$n['cw-tabs-content'], "data-active-tab-key": activeTab ?? undefined, style: CwTabsProps.contentHeight ? { '--tabs-height': CwTabsProps.contentHeight } : undefined, children: activeTab !== null && CwTabsProps.tabs.find(tab => tab.key === activeTab)?.content })] }));
2775
+ return (jsxs("div", { id: CwTabsProps.id, "data-testid": CwTabsProps.testId, className: styles$n['cw-tabs'] + (CwTabsProps.className ? ` ${CwTabsProps.className}` : "") + "", style: CwTabsProps.style, "data-tabs-position": position, children: [jsx("ul", { style: tabsListStyle, children: CwTabsProps.tabs.map(tab => {
2776
+ const badgeScheme = tab.badgeColor && isBadgeColorScheme(tab.badgeColor) ? tab.badgeColor : undefined;
2777
+ const rawBadgeColor = tab.badgeColor && !badgeScheme ? tab.badgeColor : undefined;
2778
+ return (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: [jsx(TabIcon, { icon: tab.icon }), tab.title, (tab.badge !== undefined || tab.badgeColor) && (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));
2779
+ }) }), 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 })] }));
2688
2780
  }
2689
2781
 
2690
2782
  /**
@@ -3233,8 +3325,16 @@ function CwInput(CwInputProps) {
3233
3325
  * ```
3234
3326
  */
3235
3327
  function CwDigit(props) {
3236
- const { alignProps, buttonProps, iconProps, labelProps, ...inputProps } = props;
3237
- return (jsx("div", { className: "cw-input-text", children: jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsx("input", { type: "number", ...inputProps }), buttonProps && jsx(CwButton, { ...buttonProps })] }) }));
3328
+ const { alignProps, buttonProps, iconProps, labelProps, feedback, feedbackPosition, ...inputProps } = props;
3329
+ const feedbackMessages = feedback
3330
+ ? Array.isArray(feedback) ? feedback : [feedback]
3331
+ : [];
3332
+ const feedbackId = useId();
3333
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
3334
+ const describedBy = [inputProps["aria-describedby"], ...feedbackIds].filter(Boolean).join(" ") || undefined;
3335
+ // data-direction drives the feedback indent, which only makes sense under a label column.
3336
+ const flexDirection = alignProps?.flexDirection ?? "row";
3337
+ return (jsxs("div", { className: "cw-input-text", "data-direction": labelProps ? flexDirection : "column", "data-feedback-position": feedbackPosition, children: [jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: "cw-input-button", children: [jsx("input", { type: "number", ...inputProps, "aria-describedby": describedBy }), buttonProps && jsx(CwButton, { ...buttonProps })] })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { id: feedbackIds[index], className: "cw-input-info", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
3238
3338
  }
3239
3339
 
3240
3340
  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"};
@@ -3448,7 +3548,7 @@ const CwColorPicker = ({ initialColor, onChange, previewText = "Color preview" }
3448
3548
 
3449
3549
  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"};
3450
3550
 
3451
- const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, }) => {
3551
+ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled = false, readOnly = false, width = '4rem', height = '2rem', labelProps, layoutProps, className, style, }) => {
3452
3552
  const [isOpen, setIsOpen] = useState(false);
3453
3553
  const containerRef = useRef(null);
3454
3554
  const dropdownRef = useRef(null);
@@ -3579,7 +3679,7 @@ const CwInputColor = ({ value, onChange, previewText = "Color preview", disabled
3579
3679
  break;
3580
3680
  }
3581
3681
  };
3582
- return (jsxs("div", { className: `cw-input-color ${styles$i.container}`, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsx(CwLabel, { ...labelProps })), jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
3682
+ return (jsxs("div", { className: `cw-input-color ${styles$i.container}${className ? ` ${className}` : ''}`, style: style, "data-direction": layoutProps?.direction ?? "row", "data-align": layoutProps?.align, children: [labelProps && (jsx(CwLabel, { ...labelProps })), jsx("div", { ref: containerRef, onClick: handleToggle, className: `${styles$i.selectColor} ${disabled ? styles$i.disabled : ''} ${readOnly ? styles$i.readOnly : ''}`, style: {
3583
3683
  width,
3584
3684
  height,
3585
3685
  backgroundColor: value,
@@ -4044,15 +4144,37 @@ const CwImageArea = forwardRef((props, ref) => {
4044
4144
  });
4045
4145
  CwImageArea.displayName = "CwImageArea";
4046
4146
 
4047
- var styles$g = {"cw-weekday-selector":"cw-weekday-selector-module__cw-weekday-selector__Iz4GZ"};
4147
+ var styles$g = {"container":"cw-weekday-selector-module__container__pwcvx","days":"cw-weekday-selector-module__days__Dd3RH"};
4148
+
4149
+ /* 2024-01-01 was a Monday. Formatted in UTC so a negative browser offset cannot shift a day. */
4150
+ const MONDAY_UTC = Date.UTC(2024, 0, 1);
4151
+ const DAY_IN_MS = 86_400_000;
4152
+ const DAY_CODES = ["M", "T", "W", "R", "F", "S", "U"];
4153
+ /**
4154
+ * Day names in the fixed MTWRFSU order the selector renders, resolved through Intl so every
4155
+ * locale gets its own letters (es -> LMXJVSD, de -> MDMDFSS) with no table to maintain.
4156
+ *
4157
+ * @param localeCode BCP-47 tag, e.g. "en-GB" | "es" | "de"
4158
+ */
4159
+ function getWeekdayNames(localeCode) {
4160
+ const narrow = new Intl.DateTimeFormat(localeCode, { weekday: "narrow", timeZone: "UTC" });
4161
+ const full = new Intl.DateTimeFormat(localeCode, { weekday: "long", timeZone: "UTC" });
4162
+ const names = {};
4163
+ DAY_CODES.forEach((code, index) => {
4164
+ const date = new Date(MONDAY_UTC + index * DAY_IN_MS);
4165
+ names[code] = { letter: narrow.format(date), full: full.format(date) };
4166
+ });
4167
+ return names;
4168
+ }
4048
4169
 
4170
+ /* The week model behind CwWeekdaySelector, kept apart from the rendering. */
4049
4171
  /**
4050
4172
  * This class represents a week where days can be selected or unselected
4051
4173
  * @remark Selected days are in UPPERCASE, unselected days are in lowercase
4052
4174
  * ```
4053
4175
  * Monday = "M" | "m"
4054
4176
  * Tuesday = "T" | "t"
4055
- * Wendnesday = "W" | "w"
4177
+ * Wednesday = "W" | "w"
4056
4178
  * thuRsday = "R" | "r"
4057
4179
  * Friday = "F" | "f"
4058
4180
  * Saturday = "S" | "s"
@@ -4064,15 +4186,6 @@ class Weekdays {
4064
4186
  static WEEKDAYS_STANDARD_ARRAY_EMPTY = ["m", "t", "w", "r", "f", "s", "u"];
4065
4187
  static WEEKDAYS_STANDARD_STRING_FULL = "MTWRFSU";
4066
4188
  static WEEKDAYS_STANDARD_STRING_EMPTY = "mtwrfsu";
4067
- static WEEKDAYS_TO_USA_LETTER_FORMAT = new Map([
4068
- ["M", "M"],
4069
- ["T", "T"],
4070
- ["W", "W"],
4071
- ["R", "T"],
4072
- ["F", "F"],
4073
- ["S", "S"],
4074
- ["U", "S"]
4075
- ]);
4076
4189
  static WEEKDAYS_TO_USA_SHORT_FORMAT = new Map([
4077
4190
  ["M", "Mon"],
4078
4191
  ["T", "Tue"],
@@ -4091,6 +4204,7 @@ class Weekdays {
4091
4204
  5: "F",
4092
4205
  6: "S"
4093
4206
  };
4207
+ static DAY_NUMBER_BY_CODE = Object.fromEntries(Object.entries(Weekdays.WEEKDAY_MAP).map(([dayNumber, code]) => [code, Number(dayNumber)]));
4094
4208
  days;
4095
4209
  constructor(days = Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL) {
4096
4210
  if (typeof days === "string")
@@ -4134,11 +4248,11 @@ class Weekdays {
4134
4248
  toString() {
4135
4249
  return this.days.join("").trim();
4136
4250
  }
4137
- toStringFormatted(limiters = { startExistingDay: "{", endExsitingDay: "}", startMissingDay: "(", endMissingDay: ")", separator: " " }, format = Weekdays.WEEKDAYS_TO_USA_SHORT_FORMAT) {
4251
+ toStringFormatted(limiters = { startExistingDay: "{", endExistingDay: "}", startMissingDay: "(", endMissingDay: ")", separator: " " }, format = Weekdays.WEEKDAYS_TO_USA_SHORT_FORMAT) {
4138
4252
  const result = new Array();
4139
4253
  [...this.days].forEach((letter, index) => {
4140
4254
  if (letter === letter.toUpperCase()) {
4141
- result.push(limiters.startExistingDay + format.get(letter) + limiters.endExsitingDay);
4255
+ result.push(limiters.startExistingDay + format.get(letter) + limiters.endExistingDay);
4142
4256
  }
4143
4257
  else if (letter === letter.toLowerCase()) {
4144
4258
  result.push(limiters.startMissingDay +
@@ -4158,33 +4272,77 @@ class Weekdays {
4158
4272
  return this.toString() === Weekdays.WEEKDAYS_STANDARD_STRING_FULL;
4159
4273
  }
4160
4274
  static getFullWeek() {
4161
- return Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL;
4275
+ return [...Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL];
4162
4276
  }
4163
4277
  static getEmptyWeek() {
4164
- return Weekdays.WEEKDAYS_STANDARD_ARRAY_EMPTY;
4278
+ return [...Weekdays.WEEKDAYS_STANDARD_ARRAY_EMPTY];
4165
4279
  }
4166
- }
4167
- const CwWeekdaySelector = ({ value = "", onChange, disabled = false }) => {
4168
- const [selectedDays, setSelectedDays] = useState(Weekdays.fromString(value));
4169
- useEffect(() => {
4170
- setSelectedDays(Weekdays.fromString(value));
4171
- }, [value]);
4172
- const handleChange = (day, checked) => {
4173
- const currentDays = selectedDays.toArray();
4174
- let updated;
4175
- if (checked) {
4176
- updated = currentDays.filter(d => d !== day.toLowerCase());
4177
- updated.push(day);
4280
+ /** A week with nothing selected. */
4281
+ static empty() {
4282
+ return new Weekdays(Weekdays.WEEKDAYS_STANDARD_ARRAY_EMPTY);
4283
+ }
4284
+ /**
4285
+ * Like {@link fromString}, but yields an empty week instead of throwing on anything invalid.
4286
+ * For UI fed straight from a backend field that can arrive null, empty or partial.
4287
+ */
4288
+ static tryFromString(value) {
4289
+ if (!value)
4290
+ return Weekdays.empty();
4291
+ try {
4292
+ return Weekdays.fromString(value);
4178
4293
  }
4179
- else {
4180
- updated = currentDays.filter(d => d !== day);
4181
- updated.push(day.toLowerCase());
4294
+ catch {
4295
+ return Weekdays.empty();
4182
4296
  }
4183
- const newWeekdays = new Weekdays(updated);
4184
- setSelectedDays(newWeekdays);
4185
- onChange?.(newWeekdays.toString());
4297
+ }
4298
+ /** Selected flags in MTWRFSU order (Monday first). */
4299
+ toBooleans() {
4300
+ return this.days.map(day => day === day.toUpperCase());
4301
+ }
4302
+ /** @param flags selected flags in MTWRFSU order; missing entries count as unselected */
4303
+ static fromBooleans(flags) {
4304
+ return new Weekdays(Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL.map((day, index) => flags[index] ? day : day.toLowerCase()));
4305
+ }
4306
+ /** 7-character mask in MTWRFSU order where "1" means selected, e.g. "1100100". */
4307
+ toMask() {
4308
+ return this.toBooleans().map(selected => (selected ? "1" : "0")).join("");
4309
+ }
4310
+ /** @param mask 7-character mask in MTWRFSU order where "1" means selected; a shorter, empty or
4311
+ * missing mask counts the absent days as unselected */
4312
+ static fromMask(mask) {
4313
+ return Weekdays.fromBooleans(Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL.map((_, index) => mask?.[index] === "1"));
4314
+ }
4315
+ /** Selected days as Date.getDay() numbers (0 = Sunday), in MTWRFSU order. */
4316
+ toDayNumbers() {
4317
+ return this.days
4318
+ .filter(day => day === day.toUpperCase())
4319
+ .map(day => Weekdays.DAY_NUMBER_BY_CODE[day]);
4320
+ }
4321
+ /** @param days Date.getDay() numbers (0 = Sunday) */
4322
+ static fromDayNumbers(days) {
4323
+ const selected = new Set(days);
4324
+ return Weekdays.fromBooleans(Weekdays.WEEKDAYS_STANDARD_ARRAY_FULL.map(day => selected.has(Weekdays.DAY_NUMBER_BY_CODE[day])));
4325
+ }
4326
+ }
4327
+
4328
+ const CwWeekdaySelector = ({ value = "mtwrfsu", onChange, disabled = false, labelProps, layout, feedback, locale = "en-GB", className }) => {
4329
+ const selectedDays = Weekdays.tryFromString(value).toArray();
4330
+ const dayNames = useMemo(() => getWeekdayNames(locale), [locale]);
4331
+ const handleChange = (day, checked) => {
4332
+ const updated = selectedDays.filter(d => d !== day && d !== day.toLowerCase());
4333
+ updated.push(checked ? day : day.toLowerCase());
4334
+ onChange?.(new Weekdays(updated).toString());
4186
4335
  };
4187
- return (jsx("div", { className: styles$g["cw-weekday-selector"], children: Weekdays.getFullWeek().map(day => (jsx("input", { type: "checkbox", "data-day": day, checked: selectedDays.toArray().includes(day), onChange: (e) => handleChange(day, e.target.checked), disabled: disabled }, day))) }));
4336
+ const feedbackMessages = feedback
4337
+ ? Array.isArray(feedback) ? feedback : [feedback]
4338
+ : [];
4339
+ const feedbackId = useId();
4340
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4341
+ const describedBy = feedbackIds.join(" ") || undefined;
4342
+ // Points at the label element rather than copying its text, which also covers a labelProps that
4343
+ // carries children instead of `text`.
4344
+ const labelId = labelProps?.id ?? `${feedbackId}-label`;
4345
+ return (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 && jsx(CwLabel, { id: labelId, ...labelProps }), jsx("div", { role: "group", className: styles$g.days, "aria-labelledby": labelProps ? labelId : undefined, "aria-describedby": describedBy, children: Weekdays.getFullWeek().map(day => (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) => (jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4188
4346
  };
4189
4347
 
4190
4348
  var styles$f = {"check-container":"cw-check-module__check-container__4nscZ","group":"cw-check-module__group__6JCQo","options":"cw-check-module__options__-g9LF"};
@@ -4232,6 +4390,9 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
4232
4390
  const feedbackMessages = feedback
4233
4391
  ? Array.isArray(feedback) ? feedback : [feedback]
4234
4392
  : [];
4393
+ const feedbackId = useId();
4394
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4395
+ const describedBy = feedbackIds.join(" ") || undefined;
4235
4396
  // Effective layout — precedence: new `groupLayout`/`itemLayout` > legacy-derived > default.
4236
4397
  // Legacy `alignProps.flexDirection` drove the label-vs-options axis (default "row" = label
4237
4398
  // beside the options); map it to `groupLayout.direction`.
@@ -4244,7 +4405,7 @@ function CwCheckboxGroup({ options, value = [], onChange, labelProps, groupLayou
4244
4405
  ?? (optionsAlignment === "column" ? "row" : "column");
4245
4406
  // Each checkbox's box-to-text layout is the opposite of the options flow, mirroring CwRadioGroup.
4246
4407
  const checkDirection = itemDirection === "row" ? "column" : "row";
4247
- return (jsxs("div", { className: `cw-checkbox-group ${styles$f.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$f.options, role: "group", "aria-label": labelProps?.text, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4408
+ return (jsxs("div", { className: `cw-checkbox-group ${styles$f.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? groupDirection : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$f.options, role: "group", "aria-label": labelProps?.text, "aria-describedby": describedBy, "aria-required": required || undefined, "data-direction": itemDirection, "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwCheck, { labelProps: { text: option.label }, checked: value.includes(option.value), disabled: disabled || option.disabled, direction: checkDirection, onChange: (e) => handleChange(option.value, e.currentTarget.checked) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4248
4409
  }
4249
4410
 
4250
4411
  var styles$e = {"radio":"cw-radio-module__radio__5sh7a","group":"cw-radio-module__group__br-HM","options":"cw-radio-module__options__LSw7M"};
@@ -4271,11 +4432,14 @@ function CwRadioGroup({ options, value, onChange, labelProps, groupLayout, itemL
4271
4432
  const feedbackMessages = feedback
4272
4433
  ? Array.isArray(feedback) ? feedback : [feedback]
4273
4434
  : [];
4435
+ const feedbackId = useId();
4436
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4437
+ const describedBy = feedbackIds.join(" ") || undefined;
4274
4438
  // Each radio's circle-to-text layout is the opposite of the options flow: a stacked list
4275
4439
  // (itemLayout column) reads best with the circle beside the text; a side-by-side row reads
4276
4440
  // best with the circle above the text.
4277
4441
  const radioDirection = itemLayout?.direction === "row" ? "column" : "row";
4278
- return (jsxs("div", { className: `cw-radio-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$e.options, role: "radiogroup", "aria-labelledby": ariaLabelledby, "aria-label": ariaLabelledby ? undefined : (ariaLabel ?? labelProps?.text), "aria-required": required || undefined, "data-direction": itemLayout?.direction ?? "column", "data-gap": itemLayout?.gap, children: options.map((option) => (jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
4442
+ return (jsxs("div", { className: `cw-radio-group ${styles$e.group}${className ? ` ${className}` : ""}`, "data-testid": dataTestId, "data-direction": labelProps ? (groupLayout?.direction ?? "column") : "column", "data-align": groupLayout?.align, "data-gap": groupLayout?.gap, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$e.options, role: "radiogroup", "aria-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) => (jsx(CwRadio, { name: groupName, label: option.label, direction: radioDirection, checked: value === option.value, required: required, disabled: disabled || option.disabled, onChange: () => onChange(option.value) }, option.value))) }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] }));
4279
4443
  }
4280
4444
 
4281
4445
  function CwToggle(props) {
@@ -4455,6 +4619,13 @@ function CwDropdown({ options, value, onChange, labelProps, alignProps, placehol
4455
4619
  const feedbackMessages = feedback
4456
4620
  ? Array.isArray(feedback) ? feedback : [feedback]
4457
4621
  : [];
4622
+ const feedbackId = useId();
4623
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
4624
+ const describedBy = feedbackIds.join(" ") || undefined;
4625
+ // The trigger is named by reference - the label for the field, the content for the current
4626
+ // value - so neither has to be copied into a string.
4627
+ const labelId = labelProps?.id ?? `${feedbackId}-label`;
4628
+ const valueId = `${feedbackId}-value`;
4458
4629
  // Scroll highlighted item into view
4459
4630
  useEffect(() => {
4460
4631
  if (isOpen && highlightedItemRef.current) {
@@ -4523,12 +4694,12 @@ function CwDropdown({ options, value, onChange, labelProps, alignProps, placehol
4523
4694
  }
4524
4695
  }, [isOpen, highlightedIndex, filteredOptions, handleOptionSelect]);
4525
4696
  const flexDirection = alignProps?.flexDirection ?? "row";
4526
- return (jsxs("div", { ref: containerRef, className: `cw-dropdown${className ? ` ${className}` : ""}`, "data-direction": flexDirection, style: style, ...otherProps, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-dropdown-wrapper", ref: wrapperRef, children: [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: jsx("div", { className: "cw-dropdown-trigger-content", children: selectedOption ? (jsxs(Fragment, { children: [selectedOption.color && (jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: selectedOption.color } })), jsx("span", { children: selectedOption.label })] })) : (jsx("span", { className: "cw-dropdown-placeholder", children: placeholder })) }) }), jsx("div", { style: { display: "flex", alignItems: "center", paddingRight: "0.5rem", flexShrink: 0, cursor: disabled ? "not-allowed" : "pointer" }, onClick: handleTriggerClick, children: jsx(CwIcon, { iconId: "chevron-down", size: "small" }) }), renderPanel(jsxs("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsx("div", { className: dropdownStyles.searchBox, children: jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: dropdownStyles.searchInput, autoComplete: "off" }) })), jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
4527
- dropdownStyles.option,
4528
- value === option.value ? dropdownStyles.optionSelected : "",
4529
- highlightedIndex === index ? dropdownStyles.optionFocused : "",
4530
- option.disabled ? dropdownStyles.optionDisabled : "",
4531
- ].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 && (jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: option.color } })), jsx("span", { children: option.label })] }, option.value)))) : (jsx("li", { className: dropdownStyles.emptyState, children: "No options available" })) })] }))] })] }), feedbackMessages.map((item, index) => (jsx("p", { className: "cw-input-info", "data-color": item.type, children: item.message }, index)))] }));
4697
+ return (jsx("div", { ref: containerRef, className: `cw-dropdown${className ? ` ${className}` : ""}`, "data-direction": flexDirection, style: style, ...otherProps, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && jsx(CwLabel, { id: labelId, ...labelProps }), jsxs("div", { className: dropdownStyles.value, children: [jsxs("div", { className: "cw-dropdown-wrapper", ref: wrapperRef, children: [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: [jsx("div", { className: "cw-dropdown-trigger-content", id: valueId, children: selectedOption ? (jsxs(Fragment, { children: [selectedOption.color && (jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: selectedOption.color } })), jsx("span", { children: selectedOption.label })] })) : (jsx("span", { className: "cw-dropdown-placeholder", children: placeholder })) }), jsx(CwIcon, { iconId: "chevron-down", size: "small" })] }), renderPanel(jsxs("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", onKeyDown: handleKeyDown, children: [allowSearch && (jsx("div", { className: dropdownStyles.searchBox, children: jsx("input", { ref: inputRef, type: "text", placeholder: "Search...", value: searchText, onChange: handleSearchChange, onKeyDown: handleKeyDown, className: dropdownStyles.searchInput, autoComplete: "off" }) })), jsx("ul", { children: filteredOptions.length > 0 ? (filteredOptions.map((option, index) => (jsxs("li", { ref: highlightedIndex === index ? highlightedItemRef : null, className: [
4698
+ dropdownStyles.option,
4699
+ value === option.value ? dropdownStyles.optionSelected : "",
4700
+ highlightedIndex === index ? dropdownStyles.optionFocused : "",
4701
+ option.disabled ? dropdownStyles.optionDisabled : "",
4702
+ ].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 && (jsx("span", { className: dropdownStyles.colorCircle, style: { backgroundColor: option.color } })), jsx("span", { children: option.label })] }, option.value)))) : (jsx("li", { className: dropdownStyles.emptyState, children: "No options available" })) })] }))] }), feedbackMessages.map((item, index) => (jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": item.type, "aria-live": "polite", children: item.message }, index)))] })] }) }));
4532
4703
  }
4533
4704
 
4534
4705
  function CwDropdownFilter(props) {
@@ -4936,7 +5107,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeh
4936
5107
  } }, props.ID))) })] }))] }));
4937
5108
  };
4938
5109
 
4939
- var styles$a = {"container":"cw-tag-selector-module__container__-do8i","inputBox":"cw-tag-selector-module__inputBox__3NGz9 cw-choice-input-box-module__inputBox__gHY9d","disabled":"cw-tag-selector-module__disabled__vbud9 cw-choice-input-box-module__disabled__TFAnC","dropdown":"cw-tag-selector-module__dropdown__X6Dob cw-choice-dropdown-module__dropdown__P0b4j","option":"cw-tag-selector-module__option__2UQ7g cw-choice-dropdown-module__option__uR-ro","optionFocused":"cw-tag-selector-module__optionFocused__8-lv8 cw-choice-dropdown-module__optionFocused__BYMxj","optionDot":"cw-tag-selector-module__optionDot__CdFlG cw-choice-dropdown-module__colorCircle__x7mI9","selectAll":"cw-tag-selector-module__selectAll__HyvMA"};
5110
+ 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"};
4940
5111
 
4941
5112
  /**
4942
5113
  * Multi-select input with chip tags and searchable dropdown.
@@ -5071,8 +5242,11 @@ function CwTagSelector({ id, options, value, onChange, labelProps, iconProps, al
5071
5242
  // Keeping containerRef for any other potential use
5072
5243
  const direction = alignProps?.flexDirection ?? "row";
5073
5244
  const feedbackMessages = feedback ? (Array.isArray(feedback) ? feedback : [feedback]) : [];
5074
- return (jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
5075
- inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off" }), value.length > 0 && !disabled && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] })] }), feedbackMessages.map((fb, i) => (jsx("p", { className: "cw-input-info", "data-color": fb.type, children: fb.message }, i))), renderPanel((showSelectAll || filtered.length > 0) ? (jsxs("div", { ref: panelRef, className: styles$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxs("li", { className: `${styles$a.option}${idx === focusedIndex ? ` ${styles$a.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
5245
+ const feedbackId = useId();
5246
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
5247
+ const describedBy = feedbackIds.join(" ") || undefined;
5248
+ return (jsxs("div", { ref: containerRef, className: `${styles$a.container}${className ? ` ${className}` : ""}`, style: style, id: id, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: styles$a.value, children: [jsxs("div", { className: `${styles$a.inputBox}${disabled ? ` ${styles$a.disabled}` : ""}`, ref: inputBoxRef, onClick: () => { if (!disabled)
5249
+ inputRef.current?.focus(); }, children: [selectedOptions.map(opt => (jsx(CwChip, { label: opt.label, colorScheme: opt.color ? "custom" : "info", customColor: opt.color, closable: !disabled, onClose: () => handleRemove(opt.value) }, opt.value))), jsx("input", { ref: inputRef, type: "text", value: search, onChange: handleInputChange, onFocus: handleInputFocus, onKeyDown: handleKeyDown, placeholder: selectedOptions.length === 0 ? placeholder : "", disabled: disabled, autoComplete: "off", "aria-describedby": describedBy }), value.length > 0 && !disabled && (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onMouseDown: (e) => e.preventDefault(), onClick: (e) => { e.stopPropagation(); onChange([]); setSearch(""); setOpen(false); }, tabIndex: -1, "aria-label": "Clear all" }))] }), feedbackMessages.map((fb, i) => (jsx("p", { id: feedbackIds[i], className: "cw-input-feedback", "data-color": fb.type, "aria-live": "polite", children: fb.message }, i)))] })] }), renderPanel((showSelectAll || filtered.length > 0) ? (jsxs("div", { ref: panelRef, className: styles$a.dropdown, style: panelStyle, children: [showSelectAll && !search && (jsxs("div", { className: styles$a.selectAll, onMouseDown: (e) => e.preventDefault(), onClick: handleToggleAll, children: [jsx("input", { type: "checkbox", checked: allSelected, readOnly: true, tabIndex: -1 }), allSelected ? "Deselect all" : "Select all"] })), jsx("ul", { ref: listRef, children: filtered.map((opt, idx) => (jsxs("li", { className: `${styles$a.option}${idx === focusedIndex ? ` ${styles$a.optionFocused}` : ""}`, onMouseDown: (e) => e.preventDefault(), onClick: () => handleSelect(opt.value), onMouseEnter: () => setFocusedIndex(idx), title: opt.tooltip, children: [opt.color && jsx("span", { className: styles$a.optionDot, style: { backgroundColor: opt.color } }), opt.label] }, opt.value))) })] })) : null)] }));
5076
5250
  }
5077
5251
 
5078
5252
  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"};
@@ -6083,7 +6257,7 @@ function CwBtnCancel({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...res
6083
6257
  return (jsx(CwButton, { ...rest, variant: "icon", icon: "cancel", color: "danger", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Cancel" }));
6084
6258
  }
6085
6259
 
6086
- var styles$4 = {"pickerWrapper":"cw-pickers-base-module__pickerWrapper__Fb9Zo","pickerIcons":"cw-pickers-base-module__pickerIcons__dyd2-","pickerPopup":"cw-pickers-base-module__pickerPopup__dkxJo"};
6260
+ 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"};
6087
6261
 
6088
6262
  /**
6089
6263
  * Renders a picker popup in a portal so it escapes overflow containers.
@@ -6140,6 +6314,9 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
6140
6314
  const feedbackMessages = feedback
6141
6315
  ? Array.isArray(feedback) ? feedback : [feedback]
6142
6316
  : [];
6317
+ const feedbackId = useId();
6318
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
6319
+ const describedBy = feedbackIds.join(" ") || undefined;
6143
6320
  const wrapperRef = useRef(null);
6144
6321
  const inputRef = useRef(null);
6145
6322
  const prevValueRef = useRef(undefined);
@@ -6320,11 +6497,11 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
6320
6497
  ...(maxDate ? [{ after: maxDate }] : []),
6321
6498
  ...(disabledMatcher ? [disabledMatcher] : []),
6322
6499
  ], [disabledDates, minDate, maxDate, disabledMatcher]);
6323
- return (jsxs("div", { ref: containerRef, className: `cw-datepicker ${className || ""}`, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, required: required }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsx(DayPicker, { mode: "single", selected: value || undefined, defaultMonth: defaultMonth || value || undefined, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
6324
- today: new Date(),
6325
- }, modifiersClassNames: {
6326
- today: "rdp-day-today",
6327
- } }), showTodayButton && (jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
6500
+ return (jsx("div", { ref: containerRef, className: `cw-datepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: styles$4.value, children: [jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [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 }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsx(DayPicker, { mode: "single", selected: value || undefined, defaultMonth: defaultMonth || value || undefined, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
6501
+ today: new Date(),
6502
+ }, modifiersClassNames: {
6503
+ today: "rdp-day-today",
6504
+ } }), showTodayButton && (jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }) }));
6328
6505
  }
6329
6506
 
6330
6507
  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"};
@@ -6963,14 +7140,14 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6963
7140
  }
6964
7141
  return undefined;
6965
7142
  }, [value]);
6966
- return (jsx("div", { ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.from && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.to && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsx(DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonth || value?.from || undefined, modifiers: {
7143
+ return (jsx("div", { ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.from && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.to && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsx(DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonth || value?.from || undefined, modifiers: {
6967
7144
  today: new Date(),
6968
7145
  }, modifiersClassNames: {
6969
7146
  today: "rdp-day-today",
6970
7147
  } })] }), jsx("div", { role: "alert", "aria-live": "polite", className: rangeStyles.rangeError, children: rangeErrorMessage })] }))] })] }) }));
6971
7148
  }
6972
7149
 
6973
- 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"};
7150
+ 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"};
6974
7151
 
6975
7152
  const isMobileDevice = () => {
6976
7153
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
@@ -7132,7 +7309,7 @@ function CwTimePicker({ value, onChange, interval = 15, minTime, maxTime, labelP
7132
7309
  return (jsx("div", { className: `cw-timepicker cw-timepicker-native ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsx("div", { className: styles$4.pickerWrapper, children: 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" }) })] }) }));
7133
7310
  }
7134
7311
  // Custom time picker
7135
- return (jsx("div", { ref: containerRef, className: `cw-timepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [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 && (jsx("div", { className: styles$4.pickerIcons, children: value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", icon: "close", color: "neutral", onClick: handleClear, tabIndex: -1, "aria-label": "Clear time" })) : (jsx(CwIcon, { iconId: "clock" })) })), renderPopup(jsx("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${timeStyles.timePickerPopup}`, style: popupStyle, children: jsx("div", { className: timeStyles.timePickerList, children: timeOptions.map((time) => {
7312
+ return (jsx("div", { ref: containerRef, className: `cw-timepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: `${styles$4.pickerWrapper} ${timeStyles.field}${showClear ? "" : ` ${timeStyles.narrow}`}`, children: [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 && (jsx("div", { className: styles$4.pickerIcons, children: value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", icon: "close", color: "neutral", onClick: handleClear, tabIndex: -1, "aria-label": "Clear time" })) : (jsx(CwIcon, { iconId: "clock" })) })), renderPopup(jsx("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${timeStyles.timePickerPopup}`, style: popupStyle, children: jsx("div", { className: timeStyles.timePickerList, children: timeOptions.map((time) => {
7136
7313
  const isSelected = time === value;
7137
7314
  return (jsx("button", { ref: isSelected ? selectedItemRef : null, type: "button", className: isSelected ? timeStyles.selected : "", onClick: () => handleTimeSelect(time), children: time }, time));
7138
7315
  }) }) }))] })] }) }));
@@ -7798,6 +7975,9 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
7798
7975
  const feedbackMessages = feedback
7799
7976
  ? Array.isArray(feedback) ? feedback : [feedback]
7800
7977
  : [];
7978
+ const feedbackId = useId();
7979
+ const feedbackIds = feedbackMessages.map((_, index) => `${feedbackId}-${index}`);
7980
+ const describedBy = feedbackIds.join(" ") || undefined;
7801
7981
  const wrapperRef = useRef(null);
7802
7982
  const inputRef = useRef(null);
7803
7983
  const prevValueRef = useRef(undefined);
@@ -7904,11 +8084,11 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
7904
8084
  const defaultMonthJsDate = defaultMonth
7905
8085
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
7906
8086
  : selectedJsDate;
7907
- return (jsxs("div", { ref: containerRef, className: `cw-datepicker ${className || ""}`, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, required: required }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsx(DayPicker, { mode: "single", selected: selectedJsDate, defaultMonth: defaultMonthJsDate, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
7908
- today: new Date(),
7909
- }, modifiersClassNames: {
7910
- today: "rdp-day-today",
7911
- } }), showTodayButton && (jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
8087
+ return (jsx("div", { ref: containerRef, className: `cw-datepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: styles$4.value, children: [jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [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 }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsx(DayPicker, { mode: "single", selected: selectedJsDate, defaultMonth: defaultMonthJsDate, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8088
+ today: new Date(),
8089
+ }, modifiersClassNames: {
8090
+ today: "rdp-day-today",
8091
+ } }), showTodayButton && (jsx("footer", { className: "cw-flex-row cw-align-right-center", children: jsx(CwButton, { type: "button", variant: "outline", onClick: handleTodayClick, text: todayLabel }) }))] }))] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { id: feedbackIds[index], className: "cw-input-feedback", "data-color": feedbackItem.type, "aria-live": "polite", children: feedbackItem.message }, index)))] })] }) }));
7912
8092
  }
7913
8093
 
7914
8094
  // DateTimePickerState - immutable domain model for the Temporal date-time picker.
@@ -8646,1073 +8826,13 @@ function CwDateRangePickerTemporal({ value, onChange, minDate, maxDate, disabled
8646
8826
  const defaultMonthJsDate = defaultMonth
8647
8827
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
8648
8828
  : (value?.from ? plainDateToJsDate(value.from) : undefined);
8649
- return (jsx("div", { ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.from && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.to && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsx(DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonthJsDate, locale: locale, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8829
+ return (jsx("div", { ref: containerRef, className: `cw-rangepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: rangeStyles.rangeWrapper, children: [jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.from && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearFrom, tabIndex: -1, "aria-label": "Clear from date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), jsx(CwIcon, { iconId: "arrow-right", size: "medium" }), jsxs("div", { className: styles$4.pickerWrapper, children: [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' }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value?.to && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClearTo, tabIndex: -1, "aria-label": "Clear to date" })) : (jsx(CwIcon, { iconId: "calendar" })) })] }), renderPopup(jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${rangeStyles.rangePopup}`, style: popupStyle, children: [jsxs("div", { className: rangeStyles.rangeCalendarRow, children: [showPresets && presetsToRender.length > 0 && (jsx("div", { className: rangeStyles.presetList, children: presetsToRender.map((preset) => (jsx("button", { type: "button", onClick: (e) => handlePresetClick(preset, e), children: preset.label }, preset.key))) })), jsx(DayPicker, { mode: "range", selected: selectedRange, onSelect: handleRangeSelect, disabled: disabledDays, numberOfMonths: numberOfMonths, defaultMonth: defaultMonthJsDate, locale: locale, captionLayout: "dropdown", startMonth: dropdownStartMonth, endMonth: dropdownEndMonth, modifiers: {
8650
8830
  today: new Date(),
8651
8831
  }, modifiersClassNames: {
8652
8832
  today: "rdp-day-today",
8653
8833
  } })] }), jsx("div", { role: "alert", "aria-live": "polite", className: rangeStyles.rangeError, children: rangeErrorMessage })] }))] })] }) }));
8654
8834
  }
8655
8835
 
8656
- const ResourcesTitleList = ({ resources, canBePinned, includesPinned, onCrewPinning, onClickResourceContextMenu, ResourceTitleComponent, }) => {
8657
- const onClickContextMenu = useCallback((key, resource) => {
8658
- if (onClickResourceContextMenu) {
8659
- onClickResourceContextMenu(key, resource);
8660
- }
8661
- }, []);
8662
- return (jsx("td", { className: "resourceArea", style: { width: "100px" }, children: resources.map((r, _i) => (jsxs("div", { className: "resource CwelltFunctionDescription", style: { height: r.maxTop }, children: [(canBePinned || includesPinned) && (jsx(PinButton, { canBePinned: canBePinned, resource: r, onCrewPinning: onCrewPinning })), jsx(ResourceTitleComponent, { resource: r, handleOnClickResourceContextMenu: onClickContextMenu })] }, r.id.toString()))) }));
8663
- };
8664
- const PinButton = ({ canBePinned, resource, onCrewPinning }) => {
8665
- const buttonProps = canBePinned
8666
- ? {
8667
- id: "cbl_pinL",
8668
- onClick: () => onCrewPinning(resource, ""),
8669
- children: jsx("span", { className: "cwi-pin", style: { visibility: "visible" } }),
8670
- }
8671
- : {
8672
- id: "cbl_pinLess45deg",
8673
- onClick: () => onCrewPinning(resource, "remove"),
8674
- children: jsx("span", { className: "cwi-pinned cwi-pin", style: { visibility: "visible" } }),
8675
- };
8676
- return jsx("button", { className: "cw-button-icon cw-icon-pin", ...buttonProps });
8677
- };
8678
-
8679
- const addMinutesToDateFromPx = (originalDate, leftPx, minutesPerPx) => {
8680
- const minutes = leftPx / minutesPerPx;
8681
- const datePlusMinutes = new Date(originalDate.getTime() + minutes * 60000);
8682
- return datePlusMinutes;
8683
- };
8684
-
8685
- const doubleClickOnResource = (props, resource) => {
8686
- if (props.scheduler_handleDblClickOnResourceInScheduler) {
8687
- props.scheduler_handleDblClickOnResourceInScheduler(resource);
8688
- }
8689
- };
8690
-
8691
- let CblDragAndDrop$1 = class CblDragAndDrop {
8692
- fromId;
8693
- toId;
8694
- data;
8695
- droppedOnDate;
8696
- resizeFromStart;
8697
- resizeFromEnd;
8698
- isCtrlKey;
8699
- constructor(fromId, toId, data, droppedOnDate = null, resizeFromStart = null, resizeFromEnd = null, isCtrlKey = null) {
8700
- this.fromId = fromId;
8701
- this.toId = toId;
8702
- this.data = data;
8703
- this.droppedOnDate = droppedOnDate;
8704
- this.resizeFromStart = resizeFromStart;
8705
- this.resizeFromEnd = resizeFromEnd;
8706
- this.isCtrlKey = isCtrlKey;
8707
- }
8708
- };
8709
-
8710
- const BIRTHDATE = 15;
8711
- const NOT_WORKING = 16;
8712
- const REST_TIME = 10;
8713
- const MAX_FLIGHT_DUTY_PERIOD = 11;
8714
- const DUTY_REGULATION = 20;
8715
- const unHandleableEvents = [REST_TIME, MAX_FLIGHT_DUTY_PERIOD, NOT_WORKING, DUTY_REGULATION];
8716
- const getEventStyle = (event, reslTime) => {
8717
- const baseStyle = {
8718
- left: event.leftPx,
8719
- width: event.width,
8720
- top: event.top,
8721
- overflow: "hidden",
8722
- zIndex: event.isFullHeight ? 4 : 5,
8723
- };
8724
- if (event.data.eventType === BIRTHDATE) {
8725
- return {
8726
- ...baseStyle,
8727
- height: event.isFullHeight ? "100%" : "auto",
8728
- marginTop: event.isFullHeight ? -1 * event.top : 0,
8729
- pointerEvents: "none",
8730
- borderBottom: "solid 1px rgba(0, 0, 0, 0.4)",
8731
- backgroundColor: event.data.category.color || "orange",
8732
- display: "flex",
8733
- opacity: 0.3,
8734
- alignItems: "flex-end",
8735
- };
8736
- }
8737
- if ([REST_TIME, MAX_FLIGHT_DUTY_PERIOD, DUTY_REGULATION].includes(event.data.eventType)) {
8738
- return {
8739
- ...baseStyle,
8740
- zIndex: event.isFullHeight ? 4 : 6,
8741
- marginTop: event.isFullHeight ? -1 * event.top : 0,
8742
- borderRadius: "0px",
8743
- backgroundColor: event.data.category.color || "grey",
8744
- opacity: 0.3,
8745
- borderBottom: event.data.eventType === DUTY_REGULATION ? "solid 1px rgba(0, 0, 0, 0.4)" : "",
8746
- };
8747
- }
8748
- return {
8749
- ...baseStyle,
8750
- height: event.isFullHeight ? "100%" : "auto",
8751
- marginTop: event.isFullHeight ? -1 * event.top : 0,
8752
- borderRadius: reslTime <= 0.99 ? "3px" : "5px",
8753
- minWidth: reslTime <= 1.5 ? "5px" : "",
8754
- maxWidth: reslTime <= 1.5 ? "25px" : "",
8755
- };
8756
- };
8757
- const EventRender = ({ event, schedulerProps }) => {
8758
- const dateStart = new Date(event.data.start);
8759
- const dateEnd = new Date(event.data.end);
8760
- const reslTime = (dateEnd.getTime() - dateStart.getTime()) / 3600000;
8761
- const eventStyle = getEventStyle(event, reslTime);
8762
- const onClickEvent = (e) => {
8763
- if (!unHandleableEvents.includes(event.data.eventType)) {
8764
- e.stopPropagation();
8765
- const props = schedulerProps;
8766
- props.scheduler_handleCblEventClick.call(props.parent, event, schedulerProps.id);
8767
- }
8768
- };
8769
- const onRightClickEvent = (e) => {
8770
- if (!unHandleableEvents.includes(event.data.eventType)) {
8771
- e.stopPropagation();
8772
- const props = schedulerProps;
8773
- if (props.scheduler_handleCblEventClickRight) {
8774
- props.scheduler_handleCblEventClickRight.call(props.parent, event, schedulerProps.id);
8775
- }
8776
- }
8777
- };
8778
- const safeHandleDragStart = (e, isLeft, isRight) => {
8779
- if (!unHandleableEvents.includes(event.data.eventType)) {
8780
- handleDragStart(e, isLeft, isRight);
8781
- }
8782
- };
8783
- const handleDragStart = (e, isResizeFromStart, isResizeFromEnd) => {
8784
- if (!unHandleableEvents.includes(event.data.eventType)) {
8785
- [].forEach.call(document.querySelectorAll(".ant-tooltip"), function (el) {
8786
- el.style.visibility = "hidden";
8787
- });
8788
- // We don't know in which case is necessary
8789
- if (e.target !== e.currentTarget) {
8790
- // e.preventDefault();
8791
- return;
8792
- }
8793
- const isResize = isResizeFromStart || isResizeFromEnd;
8794
- const isAllowed = !event.isReadOnly && (isResize ? event.isResizable : event.isDraggable);
8795
- if (!isAllowed) {
8796
- e.preventDefault();
8797
- return;
8798
- }
8799
- const cblDragNDrop = new CblDragAndDrop$1(schedulerProps.id, null, [event], null, isResizeFromStart, isResizeFromEnd);
8800
- if (!isResize) {
8801
- e.dataTransfer.dropEffect = e.ctrlKey ? "copy" : "link";
8802
- }
8803
- e.dataTransfer.setData("data", JSON.stringify(cblDragNDrop));
8804
- }
8805
- };
8806
- const handleDoubleClick = (e) => {
8807
- if (!unHandleableEvents.includes(event.data.eventType)) {
8808
- e.preventDefault();
8809
- e.stopPropagation();
8810
- const props = schedulerProps;
8811
- props.scheduler_handleCblEventDoubleClick.call(props.parent, event, schedulerProps.id);
8812
- }
8813
- };
8814
- const onClickContextMenu = (e) => {
8815
- if (!unHandleableEvents.includes(event.data.eventType)) {
8816
- const props = schedulerProps;
8817
- if (props.scheduler_handleOnClickEventContextMenu) {
8818
- props.scheduler_handleOnClickEventContextMenu(e, event);
8819
- }
8820
- }
8821
- };
8822
- const renderBirthdayEvent = () => (jsxs("div", { className: `fc-timeline-event cwellt_timeline_event cwellt_event_bday ${event.selected ? "cblEventSelected" : ""}`, style: eventStyle, children: [jsx("span", { className: "cwi-icons cwi-birthday", style: { visibility: "visible" } }), event.data.subject && jsx("span", { style: { lineHeight: "1em" }, children: event.data.subject })] }, event.id));
8823
- const renderRegularEvent = () => (jsxs("div", { draggable: ![10, 11, 16, 20, 21].includes(event.data.eventType), className: "fc-timeline-event cwellt_timeline_event " +
8824
- (event.selected === true ? "cblEventSelected " : "") +
8825
- (event.data.eventType === REST_TIME ||
8826
- event.data.eventType === MAX_FLIGHT_DUTY_PERIOD ||
8827
- event.data.eventType === DUTY_REGULATION
8828
- ? " cwellt_event_bhnd_appt "
8829
- : " "), style: eventStyle, onClick: onClickEvent, onContextMenu: onRightClickEvent, onDragStart: (e) => safeHandleDragStart(e, false, false), onDoubleClick: handleDoubleClick, children: [schedulerProps.scheduler_handleCblEventResize &&
8830
- !event.isReadOnly &&
8831
- !unHandleableEvents.includes(event.data.eventType) && (jsx("span", { draggable: true, onDragStart: (e) => handleDragStart(e, true, false), style: {
8832
- position: "absolute",
8833
- cursor: "e-resize",
8834
- zIndex: 10,
8835
- left: "0",
8836
- border: "solid 1px rgba(46,49,49,0.5)",
8837
- }, children: "\u200B" })), jsx(schedulerProps.cblEventComp, { cblEvent: event, handleOnClickEventContextMenu: onClickContextMenu }, event.id), schedulerProps.scheduler_handleCblEventResize &&
8838
- !event.isReadOnly &&
8839
- !unHandleableEvents.includes(event.data.eventType) && (jsx("span", { draggable: true, onDragStart: (e) => handleDragStart(e, false, true), style: {
8840
- position: "absolute",
8841
- right: "0",
8842
- cursor: "e-resize",
8843
- zIndex: 10,
8844
- border: "solid 1px rgba(46,49,49,0.5)",
8845
- marginTop: "-25px",
8846
- }, children: "\u200B" }))] }, event.id));
8847
- const render = event.data.eventType === BIRTHDATE ? renderBirthdayEvent() : renderRegularEvent();
8848
- return render;
8849
- };
8850
-
8851
- const onDropEventToResource = (props, cblDragNDrop, resource) => {
8852
- props.scheduler_handleOnDropCblEventsOnResource.call(props.parent, cblDragNDrop, resource);
8853
- };
8854
-
8855
- const isAllowedToMove = (data, resData, cblDragNDrop) => {
8856
- if (data?.eventType !== 1) {
8857
- return true;
8858
- }
8859
- const allowedMoves = [
8860
- { from: "acftsScheduler", to: "flightsPairingsScheduler" },
8861
- { from: "flightsScheduler", to: "crewAssignmentsScheduler" },
8862
- { from: "opstoolScheduler", to: "opstoolScheduler" },
8863
- { from: "opstoolScheduler", to: "opstoolSchedulerVirtual" },
8864
- { from: "opstoolSchedulerVirtual", to: "opstoolScheduler" },
8865
- { from: "opstoolSchedulerVirtual", to: "opstoolSchedulerVirtual" },
8866
- { from: "vacationsScheduler", to: "vacationsScheduler" }
8867
- ];
8868
- const crewControllAllowedMove = allowedMoves.some(move => move.from === cblDragNDrop.fromId && move.to === cblDragNDrop.toId);
8869
- if (crewControllAllowedMove) {
8870
- return true;
8871
- }
8872
- return data.Crew !== resData.Crewmember_Id;
8873
- };
8874
-
8875
- const OnDrop = ({ e, resource, id, contentArea, state, schedulerProps }) => {
8876
- e.dataTransfer.dropEffect = "move";
8877
- const cblDragNDrop = JSON.parse(e.dataTransfer.getData("data"));
8878
- if (!cblDragNDrop.data || !cblDragNDrop.data[0]) {
8879
- return;
8880
- }
8881
- cblDragNDrop.toId = id;
8882
- const obj = cblDragNDrop.data[0];
8883
- cblDragNDrop.isCtrlKey = e.ctrlKey;
8884
- const isResizeEvent = cblDragNDrop.resizeFromStart === true || cblDragNDrop.resizeFromEnd === true;
8885
- if (isResizeEvent) {
8886
- // Resize
8887
- if (obj.data === undefined || obj.data.eventType === 1) {
8888
- return;
8889
- }
8890
- const _eventX = e.clientX;
8891
- const _caLeft = contentArea?.getBoundingClientRect()?.left ?? 0;
8892
- const leftPos = _eventX - _caLeft;
8893
- let droppedDate = addMinutesToDateFromPx(schedulerProps.startDate, leftPos, state.minutePx);
8894
- if (cblDragNDrop.resizeFromEnd === true) {
8895
- const eventStart = new Date(Date.parse(obj.start));
8896
- droppedDate = droppedDate < eventStart ? eventStart : droppedDate;
8897
- }
8898
- if (cblDragNDrop.resizeFromStart === true) {
8899
- const eventEnd = new Date(Date.parse(obj.end));
8900
- // 3 hours before is the minimun size in the backend
8901
- eventEnd.setHours(eventEnd.getHours() - 3);
8902
- droppedDate = droppedDate > eventEnd ? eventEnd : droppedDate;
8903
- }
8904
- cblDragNDrop.droppedOnDate = droppedDate;
8905
- schedulerProps.scheduler_handleCblEventResize?.call(schedulerProps.parent, cblDragNDrop);
8906
- return;
8907
- }
8908
- // Drag & Drop
8909
- if (!isAllowedToMove(obj.data, resource.data, cblDragNDrop)) {
8910
- return;
8911
- }
8912
- const d = e.clientX - (contentArea?.getBoundingClientRect()?.left ?? 0);
8913
- const date = new Date(schedulerProps.startDate.getTime() + (d / state.minutePx) * 60000);
8914
- cblDragNDrop.droppedOnDate = date;
8915
- onDropEventToResource(schedulerProps, cblDragNDrop, resource);
8916
- };
8917
-
8918
- const onDragOver = (e) => {
8919
- if (e.ctrlKey === true) {
8920
- e.dataTransfer.dropEffect = "copy";
8921
- }
8922
- else {
8923
- e.dataTransfer.dropEffect = "link";
8924
- }
8925
- e.preventDefault();
8926
- };
8927
-
8928
- const arePropsEqual = (prevProps, nextProps) => {
8929
- return prevProps.res.events === nextProps.res.events && prevProps.isInViewport === nextProps.isInViewport;
8930
- };
8931
- const ResourceRender = memo(({ res, schedulerProps, contentArea, state }) => {
8932
- return (jsx("div", { style: {
8933
- backgroundColor: "#F9F8F8",
8934
- height: res.maxTop,
8935
- width: "100%",
8936
- position: "relative",
8937
- borderBottom: "1px solid rgb(255,255,255)",
8938
- }, onDragOver: (e) => onDragOver(e), onDrop: (e) => {
8939
- OnDrop({
8940
- e,
8941
- resource: res,
8942
- id: schedulerProps.id,
8943
- contentArea,
8944
- state,
8945
- schedulerProps,
8946
- });
8947
- }, className: "cwellt_divRow_schContent", children: res.events.map((evnt) => (jsx(EventRender, { event: evnt, schedulerProps: schedulerProps }, evnt.id))) }, res.id));
8948
- }, arePropsEqual);
8949
-
8950
- const ResourceListRender = ({ resources, schedulerProps, state, contentArea,
8951
- // onClickContextMenu,
8952
- crewAssignmentSchedulerContextMenu, }) => {
8953
- return (jsx(Fragment$1, { children: resources.map((r, _i) => (jsx(CwAnchoredMenu, { placement: "bottom", onContextMenu: (e) => {
8954
- // Dirty temporal solution to remove ANT design, this can be killed when this scheduler is deprecated
8955
- const leftPos = e.currentTarget.getBoundingClientRect().left -
8956
- (contentArea?.getBoundingClientRect()?.left ?? 0) -
8957
- window.scrollX;
8958
- const calculatedDatetime = addMinutesToDateFromPx(schedulerProps.startDate, leftPos, state.minutePx);
8959
- r.__contextMenuDatetime = calculatedDatetime;
8960
- }, options: crewAssignmentSchedulerContextMenu?.map(m => ({
8961
- key: m.key,
8962
- label: (jsxs(Fragment, { children: [jsx("span", { className: m.icon, style: { color: m.color } }), jsx("span", { children: m.text })] }))
8963
- })) ?? [], onSelect: (key) => {
8964
- const datetime = r.__contextMenuDatetime ?? new Date();
8965
- if (schedulerProps.scheduler_handleOnClickContextMenuResource) {
8966
- schedulerProps.scheduler_handleOnClickContextMenuResource(datetime, r, key, schedulerProps.id);
8967
- }
8968
- }, children: jsx("span", { onDoubleClick: () => doubleClickOnResource(schedulerProps, r), id: schedulerProps.id + "_" + r.id, children: jsx(ResourceRender, { res: r, schedulerProps: schedulerProps, contentArea: contentArea, state: state, isInViewport: r.isInViewport }, r.id) }) }, r.id))) }));
8969
- };
8970
-
8971
- const TimeLine$1 = ({ id, toolTipTitle, marginLeft, color = "rgba(255,0,0,.6)", pixels = 2, height = "100%", zIndex = 1, }) => {
8972
- return (jsx(CwTooltipNew, { content: toolTipTitle, position: "top", children: jsx("div", { id: id, style: {
8973
- borderLeft: `${pixels}px solid ${color}`,
8974
- marginLeft: marginLeft,
8975
- width: "0px",
8976
- height: height,
8977
- position: "absolute",
8978
- zIndex: zIndex,
8979
- } }) }));
8980
- };
8981
-
8982
- const SchedulerContentArea = ({ now, showTimeline, timeLineLeftPx, timeSeparatorLeftPx, resources, scheduler, contextMenuContents, onEmptyClick, setContentArea, onClickContextMenu, }) => {
8983
- return (jsxs("td", { className: "contentArea", style: { width: "100%", overflow: "hidden", position: "relative" }, ref: (reference) => {
8984
- if (reference) {
8985
- setContentArea(reference);
8986
- }
8987
- }, children: [showTimeline && (jsx(TimeLine$1, { id: scheduler.props.id + "_timeline", marginLeft: timeLineLeftPx, zIndex: 8, toolTipTitle: Temporal.PlainTime.from({
8988
- hour: now.getHours(),
8989
- minute: now.getMinutes(),
8990
- }).toString({ smallestUnit: "minute" }) })), timeSeparatorLeftPx.map((pixels) => {
8991
- return jsx(TimeLine$1, { marginLeft: pixels, color: "rgba(255,255,255,0.7)" });
8992
- }), jsx("span", { onClick: () => {
8993
- if (onEmptyClick) {
8994
- onEmptyClick(scheduler.props.id);
8995
- }
8996
- }, children: jsx(ResourceListRender, { resources: resources, state: scheduler.state, schedulerProps: scheduler.props, contentArea: scheduler.contentArea, onClickContextMenu: onClickContextMenu, crewAssignmentSchedulerContextMenu: contextMenuContents }) })] }));
8997
- };
8998
-
8999
- const daysBetweenTwoDates = (date1, date2) => {
9000
- const diff = Math.abs(date1.getTime() - date2.getTime());
9001
- let diffDays = 0;
9002
- const startOffset = Math.abs(date1.getTimezoneOffset());
9003
- const endOffset = Math.abs(date2.getTimezoneOffset());
9004
- // Summer: +1 -> +2, true
9005
- // Winter: +2 -> -1, false
9006
- if (startOffset > endOffset) {
9007
- diffDays = Math.floor(diff / (1000 * 3600 * 24));
9008
- }
9009
- else {
9010
- diffDays = Math.ceil(diff / (1000 * 3600 * 24));
9011
- }
9012
- return diffDays;
9013
- };
9014
-
9015
- const calculateDivisionType = (start, end) => {
9016
- const diffDays = daysBetweenTwoDates(start, end);
9017
- if (diffDays <= 15) {
9018
- return "d";
9019
- }
9020
- else if (diffDays <= 30) {
9021
- return "w";
9022
- }
9023
- else {
9024
- return "m";
9025
- }
9026
- };
9027
-
9028
- const getMonthHeaderData = (dates, maxWidth) => {
9029
- if (dates.length === 0)
9030
- return [];
9031
- const dayWidth = maxWidth / dates.length;
9032
- const ranges = getMonthRanges(dates);
9033
- return ranges.map((range) => {
9034
- return {
9035
- monthFormatted: range.start.getMonth() + 1 + "." + range.start.getFullYear(),
9036
- width: dayWidth * range.daysLong,
9037
- };
9038
- });
9039
- };
9040
- const getMonthRanges = (dates) => {
9041
- const firstDay = dates[0];
9042
- const lastDay = dates[dates.length - 1];
9043
- let currentDate = new Date(firstDay);
9044
- const ranges = [];
9045
- while (currentDate <= lastDay) {
9046
- const rangeStart = new Date(currentDate);
9047
- let rangeEnd = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
9048
- if (rangeEnd >= lastDay) {
9049
- rangeEnd = lastDay;
9050
- }
9051
- ranges.push({
9052
- start: rangeStart,
9053
- daysLong: getDaysBetweenDates(rangeStart, rangeEnd),
9054
- });
9055
- currentDate = new Date(rangeEnd.getFullYear(), rangeEnd.getMonth() + 1, 1);
9056
- }
9057
- return ranges;
9058
- };
9059
- const getDaysBetweenDates = (startDate, endDate) => {
9060
- const timeDifference = endDate.getTime() - startDate.getTime();
9061
- return Math.floor(timeDifference / (1000 * 60 * 60 * 24)) + 1;
9062
- };
9063
-
9064
- const getWeekHeaderDataFromWeekRange = (weekRange, maxWidth, dateFormatter) => weekRange.map(week => {
9065
- const numberOfDaysInScheduler = weekRange
9066
- .flatMap(element => {
9067
- return element.days;
9068
- })
9069
- .reduce((el1, el2) => {
9070
- return el1 + el2;
9071
- });
9072
- return {
9073
- formattedString: getStringForWeekRange(week, dateFormatter),
9074
- width: getWidthForWeekRange(maxWidth, week.days, numberOfDaysInScheduler)
9075
- };
9076
- });
9077
- const getStringForWeekRange = (weekRange, dateFormatter) => weekRange.days == 1
9078
- ? dateFormatter(weekRange.start)
9079
- : `${dateFormatter(weekRange.start)} - ${dateFormatter(weekRange.end)}`;
9080
- const getWidthForWeekRange = (maxWidth, weekDays, monthDays) => {
9081
- const dayWidth = maxWidth / monthDays;
9082
- return dayWidth * weekDays;
9083
- };
9084
-
9085
- // stringRange: `${formatter(date)} - ${formatter(end)}`,
9086
- const listOfDatesToWeekRangeList = (dates) => {
9087
- if (dates.length === 0) {
9088
- return [];
9089
- }
9090
- const datesToReturn = [];
9091
- dates.forEach((date, index) => {
9092
- const dayOfWeek = date.getDay();
9093
- const isFirstDay = index === 0;
9094
- const isLastDay = index === dates.length - 1;
9095
- const isSunday = dayOfWeek === 0;
9096
- const isMonday = dayOfWeek === 1;
9097
- if (isFirstDay && !isSunday) {
9098
- datesToReturn.push(createWeekRange(date, 8 - dayOfWeek));
9099
- return;
9100
- }
9101
- if (isLastDay && !isSunday) {
9102
- if (!isMonday) {
9103
- datesToReturn.pop();
9104
- }
9105
- const firstOfWeek = getFirstDayOfWeek(date);
9106
- datesToReturn.push(createWeekRange(firstOfWeek, dayOfWeek));
9107
- return;
9108
- }
9109
- if (isMonday) {
9110
- datesToReturn.push(createWeekRange(date, 7));
9111
- return;
9112
- }
9113
- // this is because sunday is 0
9114
- if (isFirstDay && isSunday) {
9115
- datesToReturn.push(createWeekRange(date, 1));
9116
- return;
9117
- }
9118
- });
9119
- return datesToReturn;
9120
- };
9121
- const createWeekRange = (start, days) => {
9122
- const end = new Date(start);
9123
- end.setDate(end.getDate() + days - 1);
9124
- return {
9125
- days,
9126
- start,
9127
- end,
9128
- isShortWeek: days < 7
9129
- };
9130
- };
9131
- const getFirstDayOfWeek = (date) => {
9132
- const currentDate = new Date(date);
9133
- const dayOfWeek = currentDate.getDay();
9134
- // dayOfWeek 0 == (Sunday)
9135
- const diffToMonday = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
9136
- // Set the date to the first day of the week
9137
- currentDate.setDate(currentDate.getDate() - diffToMonday);
9138
- return currentDate;
9139
- };
9140
-
9141
- const DayHeader = ({ index, text, width, headerType }) => {
9142
- const isFirstDay = index == 0;
9143
- return (jsx("td", { style: {
9144
- display: "inline-block",
9145
- fontSize: "10px",
9146
- width: width,
9147
- maxWidth: width,
9148
- }, id: headerType + index, children: jsx("span", { className: isFirstDay ? "cwelltFirstDate_desc" : "", children: text }) }));
9149
- };
9150
-
9151
- const MonthHeader = ({ index, text, width, headerType }) => {
9152
- return (jsx("td", { style: {
9153
- display: "inline-block",
9154
- fontSize: "10px",
9155
- width: width,
9156
- maxWidth: width,
9157
- }, id: headerType + index, children: jsx("span", { children: text }) }));
9158
- };
9159
-
9160
- const WeekHeader = ({ index, text, width, headerType }) => {
9161
- const isFirstDay = index == 0;
9162
- return (jsx("td", { style: {
9163
- display: "inline-block",
9164
- fontSize: "10px",
9165
- width: width,
9166
- maxWidth: width,
9167
- }, id: headerType + index, children: jsx("span", { className: isFirstDay ? "cwelltFirstDate_desc" : "", style: { whiteSpace: "nowrap" }, children: text }) }));
9168
- };
9169
-
9170
- const DaysHeader = ({ days, divisionType, maxWidth, headerType }) => {
9171
- let headerToDraw = [];
9172
- const filteredDays = days.filter((date) => {
9173
- return date.getHours() === 0;
9174
- });
9175
- const dateFormatter = (date) => {
9176
- return `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;
9177
- };
9178
- switch (divisionType) {
9179
- case "d":
9180
- {
9181
- headerToDraw = filteredDays.map((date, index) => {
9182
- return (jsx(DayHeader, { text: dateFormatter(date), index: index, width: maxWidth / filteredDays.length, headerType: headerType }, index));
9183
- });
9184
- }
9185
- break;
9186
- case "w":
9187
- {
9188
- const weekRanges = listOfDatesToWeekRangeList(filteredDays);
9189
- headerToDraw = getWeekHeaderDataFromWeekRange(weekRanges, maxWidth, dateFormatter).map((week, index) => {
9190
- return (jsx(WeekHeader, { index: index, text: week.formattedString, width: week.width, headerType: headerType }, index));
9191
- });
9192
- }
9193
- break;
9194
- case "m":
9195
- {
9196
- const monthData = getMonthHeaderData(filteredDays, maxWidth);
9197
- headerToDraw = monthData.map(({ monthFormatted, width }, index) => (jsx(MonthHeader, { index: index, text: monthFormatted, width: width, headerType: headerType }, index)));
9198
- }
9199
- break;
9200
- }
9201
- return jsx("tr", { className: "cwelltSchRowDate", children: headerToDraw });
9202
- };
9203
-
9204
- function formatHHmm(date) {
9205
- const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
9206
- const zdt = Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTimeISO(timeZone);
9207
- return `${zdt.hour.toString().padStart(2, "0")}:${zdt.minute.toString().padStart(2, "0")}`;
9208
- }
9209
- const getFormattedTimeForHeader = (calculatedDivType, calculatedDivision, timeHeader) => {
9210
- let showDate = "";
9211
- switch (calculatedDivType) {
9212
- case "d":
9213
- switch (calculatedDivision) {
9214
- case 8:
9215
- showDate =
9216
- timeHeader.getHours() === 0 ||
9217
- timeHeader.getHours() === 3 ||
9218
- timeHeader.getHours() === 6 ||
9219
- timeHeader.getHours() === 9 ||
9220
- timeHeader.getHours() === 12 ||
9221
- timeHeader.getHours() === 15 ||
9222
- timeHeader.getHours() === 18 ||
9223
- timeHeader.getHours() === 21
9224
- ? formatHHmm(timeHeader)
9225
- : "";
9226
- break;
9227
- case 3:
9228
- showDate =
9229
- timeHeader.getHours() === 0 || timeHeader.getHours() === 8 || timeHeader.getHours() === 16
9230
- ? formatHHmm(timeHeader)
9231
- : "";
9232
- break;
9233
- case 2:
9234
- showDate =
9235
- timeHeader.getHours() === 0 || timeHeader.getHours() === 12 ? formatHHmm(timeHeader) : "";
9236
- break;
9237
- }
9238
- break;
9239
- case "m":
9240
- showDate = timeHeader.getHours() === 0 ? timeHeader.getDate().toString() : "";
9241
- break;
9242
- case "w":
9243
- showDate = timeHeader.getHours() === 0 ? timeHeader.getDate().toString() : "";
9244
- break;
9245
- }
9246
- return {
9247
- text: showDate,
9248
- isWeekend: timeHeader.getDay() === 6 || timeHeader.getDay() === 0,
9249
- };
9250
- };
9251
-
9252
- const calculateDivisions = (start, end) => {
9253
- const diffDays = daysBetweenTwoDates(start, end);
9254
- if (diffDays <= 3) {
9255
- return 8;
9256
- }
9257
- else if (diffDays < 8) {
9258
- return 3;
9259
- }
9260
- else if (diffDays <= 15) {
9261
- return 2;
9262
- }
9263
- else {
9264
- return 1;
9265
- }
9266
- };
9267
-
9268
- const TimeHeader = ({ isWeekend, index, text, width, header }) => {
9269
- if (text === "") {
9270
- return;
9271
- }
9272
- const commonStyles = {
9273
- display: "flex",
9274
- alignItems: "center",
9275
- justifyContent: "left",
9276
- fontSize: "10px",
9277
- width: width,
9278
- maxWidth: width,
9279
- height: "30px",
9280
- borderLeft: "1px solid white",
9281
- background: isWeekend ? "#cbc9c9" : "",
9282
- color: "#000000d9",
9283
- fontWeight: 700,
9284
- };
9285
- return (jsx("td", { style: commonStyles, id: `${header}Time${index}`, children: jsx("span", { style: { paddingLeft: "8px" }, children: text }) }, `t${index}`));
9286
- };
9287
-
9288
- const TimeHeaderRow = ({ timeHeaders, startDate, endDate, maxWidth, header }) => {
9289
- const calculatedDivision = calculateDivisions(startDate, endDate);
9290
- const calculatedDivType = calculateDivisionType(startDate, endDate);
9291
- const formattedHeaders = timeHeaders.map((th) => {
9292
- return getFormattedTimeForHeader(calculatedDivType, calculatedDivision, th);
9293
- });
9294
- const filteredHeaders = formattedHeaders.filter((element) => element.text !== "");
9295
- return (jsx("tr", { className: "cwelltSchRowTime", style: { height: "30px" }, children: filteredHeaders.map(({ text, isWeekend }, index) => {
9296
- return (jsx(TimeHeader, { isWeekend: isWeekend, index: index, text: text, width: maxWidth / filteredHeaders.length, header: header }, index));
9297
- }) }));
9298
- };
9299
-
9300
- const SchedulerTimeLine = ({ maxPx, hoursList, startDate, endDate, pxPerHour, headerName, }) => {
9301
- return (jsx("table", { className: "content-area cwelltSchTable", style: { width: maxPx }, children: jsxs("tbody", { style: { width: "100%", borderSpacing: 0 }, className: "content-area cwelltSchTbody", children: [jsx(DaysHeader, { days: hoursList, divisionType: calculateDivisionType(startDate, endDate), maxWidth: pxPerHour * hoursList.length, headerType: headerName ?? "schedulerDateHeader" }), jsx(TimeHeaderRow, { timeHeaders: hoursList, startDate: startDate, endDate: endDate, maxWidth: pxPerHour * hoursList.length, header: headerName ?? "schedulerTimeHeader" })] }) }));
9302
- };
9303
-
9304
- const SchedulerHeader$1 = ({ timelineProps, descriptionColumn }) => {
9305
- const { maxPx, hoursList, startDate, endDate, pxPerHour, headerName } = timelineProps;
9306
- return (jsx("thead", { className: "cwellt_fc_header_scheduler", style: { position: "sticky", zIndex: 9 }, children: jsxs("tr", { className: "cwellt_fc_header_row", children: [jsxs("td", { className: "border", style: {
9307
- position: "sticky",
9308
- top: 0,
9309
- backgroundColor: "white",
9310
- width: "100px",
9311
- }, children: [jsx("div", { style: {
9312
- display: "flex",
9313
- height: "30px",
9314
- alignItems: "center",
9315
- width: "150px",
9316
- }, children: jsx("label", { children: headerName }) }), jsx("div", { style: {
9317
- display: "flex",
9318
- height: "30px",
9319
- alignItems: "center",
9320
- background: "rgba(0, 0, 0, 0.04)",
9321
- }, children: jsx("span", { children: descriptionColumn }) })] }), jsx("td", { style: {
9322
- position: "sticky",
9323
- top: 0,
9324
- zIndex: 6,
9325
- backgroundColor: "white",
9326
- }, children: jsx(SchedulerTimeLine, { maxPx: maxPx, hoursList: hoursList, pxPerHour: pxPerHour, startDate: startDate, endDate: endDate, headerName: headerName }) })] }) }));
9327
- };
9328
-
9329
- const daysBetweenTwoDatesIncludingBoth = (date1, date2) => {
9330
- const diff = Math.abs(date1.getTime() - date2.getTime());
9331
- const diffDays = diff / (1000 * 3600 * 24);
9332
- return diffDays;
9333
- };
9334
-
9335
- const getUtcToday = () => {
9336
- const now = new Date();
9337
- const userTimezoneOffset = now.getTimezoneOffset() * 60000;
9338
- const nowUtc = new Date(now.getTime() + userTimezoneOffset);
9339
- return nowUtc;
9340
- };
9341
-
9342
- const filterEvents = (events, start, end, id, module = undefined) => {
9343
- const datesCollide = (event) => event.start <= end && event.end >= start;
9344
- let eventsFiltered = events.filter(event => datesCollide(event));
9345
- if (id !== "flightWatchScheduler") {
9346
- eventsFiltered = sortByDate(eventsFiltered);
9347
- }
9348
- if (id !== "crewAssignmentsScheduler" && id !== "vacationsScheduler") {
9349
- return eventsFiltered;
9350
- }
9351
- eventsFiltered = setNotFullHeightEventsFirst(eventsFiltered);
9352
- if (module === "CrewControl") {
9353
- eventsFiltered = removeDuplicated(eventsFiltered, "Crew_Id");
9354
- }
9355
- if (module === "CrewScheduling") {
9356
- eventsFiltered = removeDuplicated(eventsFiltered, "AssignmentID");
9357
- }
9358
- if (module === "CrewSchedulingVacations") {
9359
- eventsFiltered = removeDuplicated(eventsFiltered, "ID");
9360
- }
9361
- return eventsFiltered;
9362
- };
9363
- const sortByDate = (events) => events.sort((a, b) => +new Date(a.start) - +new Date(b.start));
9364
- const removeDuplicated = (events, key) => {
9365
- return events.filter((obj, index, self) => index === self.findIndex(o => o.data[key] === obj.data[key] && o.data.subject === obj.data.subject));
9366
- };
9367
- const setNotFullHeightEventsFirst = (events) => {
9368
- const notFullHeight = [];
9369
- const isFullHeight = [];
9370
- events.forEach(element => {
9371
- element.isFullHeight ? notFullHeight.push(element) : isFullHeight.push(element);
9372
- });
9373
- return notFullHeight.concat(isFullHeight);
9374
- };
9375
-
9376
- const compareStrings = (str1, str2) => {
9377
- if (str1 > str2)
9378
- return 1;
9379
- if (str1 < str2)
9380
- return -1;
9381
- return 0;
9382
- };
9383
-
9384
- const filterResources = (module, resourceName, resources, groupByFunction, endDate, startDate, scheduleName) => {
9385
- if ((module === "CrewControl" || module === "CrewScheduling" || module === "CrewSchedulingVacations") &&
9386
- resourceName === "Employees") {
9387
- resources = resources.filter(c => (c.data.Eintritt === null || (new Date(c.data.Eintritt) <= endDate)) && (c.data.Austritt === null || (new Date(c.data.Austritt) >= startDate)));
9388
- }
9389
- if (scheduleName === "crewPinnedScheduler" || (module === "CrewControl" || module === "CrewScheduling") && resourceName === "Employees") {
9390
- const sortKey = (groupByFunction || scheduleName === "crewPinnedScheduler") ? "mainFunction" : "C3_LC";
9391
- resources = resources.sort((a, b) => compareStrings(a.data[sortKey], b.data[sortKey]));
9392
- }
9393
- return resources;
9394
- };
9395
-
9396
- const heightScheduler = (resources, visibleRows, isPinnerScheduler) => {
9397
- if (resources.length <= 0) {
9398
- return 100;
9399
- }
9400
- const realVisibleRows = visibleRows > resources.length ? resources.length : visibleRows;
9401
- const rowsHeight = resources.slice(0, realVisibleRows).map((row) => {
9402
- return row.maxTop;
9403
- });
9404
- const height = rowsHeight.reduce((sum, row) => {
9405
- return sum + row;
9406
- }, 0);
9407
- const headerHeight = isPinnerScheduler ? 0 : 60;
9408
- return height + headerHeight;
9409
- };
9410
-
9411
- const getLeftPixels = (eventStart, scheduleStart, dayPx) => {
9412
- if (scheduleStart >= eventStart)
9413
- return 0;
9414
- return daysBetweenTwoDatesIncludingBoth(scheduleStart, eventStart) * dayPx;
9415
- };
9416
- const getEventWithSize = (event, schedulerStart, dayPx) => {
9417
- const eventStartBeforeScheduleStart = event.start.getTime() < schedulerStart.getTime();
9418
- const lengthOfEvent = daysBetweenTwoDatesIncludingBoth(event.start, event.end);
9419
- const daysUntilSchedulerStart = daysBetweenTwoDatesIncludingBoth(event.start, schedulerStart);
9420
- const daysLong = eventStartBeforeScheduleStart ? lengthOfEvent - daysUntilSchedulerStart : lengthOfEvent;
9421
- // we want minimum of 8 px
9422
- const eventMinSize = 8;
9423
- const newEvent = {
9424
- ...event,
9425
- leftPx: getLeftPixels(event.start, schedulerStart, dayPx),
9426
- width: Math.max(daysLong * dayPx, eventMinSize),
9427
- };
9428
- return newEvent;
9429
- };
9430
-
9431
- const checkIfSlotAvailable = (events, event) => {
9432
- if (events.length == 0)
9433
- return true;
9434
- const collide = events.some(existent => {
9435
- return !(existent.end <= event.start || event.end <= existent.start) && !existent.isFullHeight;
9436
- });
9437
- return !collide;
9438
- };
9439
-
9440
- const getEventsInInnerRows = (res, eventHeight, dayPx, start) => {
9441
- let maxTop = 0;
9442
- const tops = [];
9443
- tops[0] = new Array();
9444
- res.events
9445
- .map((e) => {
9446
- return getEventWithSize(e, start, dayPx);
9447
- })
9448
- .forEach((event, i) => {
9449
- if (i === 0 || event.isFullHeight) {
9450
- event.top = 0;
9451
- tops[0].push(event);
9452
- }
9453
- else {
9454
- let found = false;
9455
- for (let j = 0; j < tops.length && found === false; j++) {
9456
- found = checkIfSlotAvailable(tops[j], event);
9457
- if (found === true || event.isFullHeight) {
9458
- event.top = j * eventHeight;
9459
- tops[j].push(event);
9460
- break;
9461
- }
9462
- }
9463
- if (found === false && !event.isFullHeight) {
9464
- maxTop++;
9465
- tops[maxTop] = new Array();
9466
- event.top = maxTop * eventHeight;
9467
- tops[maxTop].push(event);
9468
- }
9469
- else {
9470
- // This is for flightwatch
9471
- if (found === true && event.data.order === 2 && maxTop < 1) {
9472
- maxTop++;
9473
- tops[maxTop] = new Array();
9474
- event.top = maxTop * eventHeight;
9475
- tops[maxTop].push(event);
9476
- maxTop--;
9477
- }
9478
- }
9479
- }
9480
- });
9481
- return tops;
9482
- };
9483
-
9484
- const getTimeHeaders = (startDate, endDate) => {
9485
- const dateArray = new Array();
9486
- const currentDate = new Date(startDate);
9487
- const startOffset = Math.abs(startDate.getTimezoneOffset());
9488
- const endOffset = Math.abs(endDate.getTimezoneOffset());
9489
- // Summer: +1 -> +2, true
9490
- // Winter: +2 -> -1, false
9491
- const offsetSummerWinter = startOffset < endOffset;
9492
- if (offsetSummerWinter === true) {
9493
- while (currentDate < endDate) {
9494
- if (dateArray.length > 0) {
9495
- const lastPosition = dateArray[dateArray.length - 1];
9496
- const differenceHours = currentDate.getHours() - lastPosition.getHours();
9497
- if (differenceHours === 1 || differenceHours < 0) {
9498
- dateArray.push(new Date(currentDate));
9499
- }
9500
- else if (differenceHours > 1) {
9501
- dateArray.push(new Date(currentDate.getHours() - 1));
9502
- dateArray.push(new Date(currentDate));
9503
- }
9504
- }
9505
- else {
9506
- dateArray.push(new Date(currentDate));
9507
- }
9508
- currentDate.setHours(currentDate.getHours() + 1);
9509
- }
9510
- }
9511
- else {
9512
- while (currentDate < endDate) {
9513
- dateArray.push(new Date(currentDate));
9514
- currentDate.setHours(currentDate.getHours() + 1);
9515
- }
9516
- }
9517
- return dateArray;
9518
- };
9519
-
9520
- class CwScheduler extends Component {
9521
- contentArea;
9522
- calculateMaxPx = () => {
9523
- const mainElement = document.body;
9524
- const mainRect = mainElement.getBoundingClientRect();
9525
- return Math.floor(mainRect.width - 190);
9526
- };
9527
- constructor(props) {
9528
- super(props);
9529
- const maxPx = this.calculateMaxPx();
9530
- const timeHeaders = getTimeHeaders(props.startDate, props.endDate);
9531
- const dayPx = maxPx / Math.floor(daysBetweenTwoDates(props.startDate, props.endDate));
9532
- const hourPx = dayPx / 24;
9533
- const minutePx = dayPx / 1440;
9534
- window?.addEventListener("resize", this.handleResize);
9535
- const divisions = calculateDivisions(this.props.startDate, this.props.endDate);
9536
- const divisionsLeftPx = timeHeaders
9537
- .filter((_, index) => {
9538
- return index != 0 && index % (24 / divisions) == 0;
9539
- })
9540
- .map((date) => {
9541
- const daysDiff = daysBetweenTwoDatesIncludingBoth(date, props.startDate);
9542
- const pixels = daysDiff * 24 * hourPx;
9543
- return pixels;
9544
- });
9545
- this.state = {
9546
- maxPx: maxPx,
9547
- dayPx: dayPx,
9548
- hourPx: hourPx,
9549
- minutePx: minutePx,
9550
- timeHeaders: timeHeaders,
9551
- divisionsLeftPx: divisionsLeftPx,
9552
- eventHeight: 30,
9553
- resources: props.resources,
9554
- lineStyle: 0,
9555
- nowUtc: getUtcToday(),
9556
- division: divisions,
9557
- divisionType: "",
9558
- pinnedResources: props.pinnedResources ? props.pinnedResources : [],
9559
- selectedEvents: [],
9560
- showConsoleLogs: false, // Change to false to not show the console.log(...)
9561
- };
9562
- }
9563
- handleResize = () => {
9564
- const maxPx = this.calculateMaxPx();
9565
- const days = Math.floor(daysBetweenTwoDates(this.props.startDate, this.props.endDate));
9566
- const dayPx = maxPx / days;
9567
- const hourPx = dayPx / 24;
9568
- const updated = { ...this.state, maxPx: maxPx, hourPx: hourPx, dayPx: dayPx };
9569
- this.setState(updated);
9570
- };
9571
- objectsEqual = (o1, o2) => {
9572
- Object.keys(o1).length === Object.keys(o2).length && Object.keys(o1).every((p) => o1[p] === o2[p]);
9573
- };
9574
- objectsEqualDeep = (o1, o2) => typeof o1 === "object" && Object.keys(o1).length > 0
9575
- ? Object.keys(o1).length === Object.keys(o2).length &&
9576
- Object.keys(o1).every((p) => this.objectsEqual(o1[p], o2[p]))
9577
- : o1 === o2;
9578
- arraysEqual = (a1, a2) => a1.length === a2.length && a1.every((o, idx) => this.objectsEqualDeep(o, a2[idx]));
9579
- componentWillReceiveProps(_nextProps) {
9580
- if (this.state.showConsoleLogs) {
9581
- console.log("Schedule - componentWillReceiveProps, start: ", new Date());
9582
- console.log("Schedule - componentWillReceiveProps - has changes, start: ", new Date());
9583
- }
9584
- const dateChange = _nextProps.startDate.toISOString() !== this.props.startDate.toISOString() ||
9585
- _nextProps.endDate.toISOString() !== this.props.endDate.toISOString();
9586
- if (dateChange) {
9587
- const startDate = _nextProps.startDate;
9588
- const endDate = _nextProps.endDate;
9589
- const maxPx = this.calculateMaxPx();
9590
- const timeHeaders = getTimeHeaders(startDate, endDate);
9591
- const days = Math.floor(daysBetweenTwoDates(startDate, endDate));
9592
- const dayPx = maxPx / days;
9593
- const hourPx = dayPx / 24;
9594
- const minutePx = dayPx / 1440;
9595
- const now = getUtcToday();
9596
- const isInDateRange = now >= startDate && now <= endDate && this.contentArea !== undefined;
9597
- const lineStyle = isInDateRange ? daysBetweenTwoDatesIncludingBoth(startDate, now) * dayPx : 0;
9598
- const divisions = calculateDivisions(startDate, endDate);
9599
- const divisionsLeftPx = timeHeaders
9600
- .filter((_, index) => {
9601
- return index != 0 && index % (24 / divisions) == 0;
9602
- })
9603
- .map((date) => {
9604
- const daysDiff = daysBetweenTwoDatesIncludingBoth(date, startDate);
9605
- const pixels = daysDiff * dayPx;
9606
- return pixels;
9607
- });
9608
- this.setState({
9609
- maxPx: maxPx, // window.screen.width * 0.9,
9610
- dayPx: dayPx,
9611
- hourPx: hourPx,
9612
- minutePx: minutePx,
9613
- timeHeaders: timeHeaders,
9614
- divisionsLeftPx: divisionsLeftPx,
9615
- resources: this.getNewResources(_nextProps, dayPx),
9616
- lineStyle: lineStyle,
9617
- nowUtc: now,
9618
- division: divisions,
9619
- divisionType: "",
9620
- pinnedResources: this.props.pinnedResources ?? [],
9621
- });
9622
- if (this.state.showConsoleLogs) {
9623
- console.log("Schedule - componentWillReceiveProps - print on schedule, end: ", new Date());
9624
- console.log("Schedule - componentWillReceiveProps, end: ", new Date());
9625
- }
9626
- return;
9627
- }
9628
- const areSameEvents = this.arraysEqual(_nextProps.events, this.props.events);
9629
- const areSameRows = this.arraysEqual(_nextProps.resources, this.props.resources);
9630
- if (!areSameEvents || !areSameRows) {
9631
- const startDate = _nextProps.startDate;
9632
- const endDate = _nextProps.endDate;
9633
- const maxPx = this.calculateMaxPx();
9634
- const days = Math.floor(daysBetweenTwoDates(startDate, endDate));
9635
- const dayPx = maxPx / days;
9636
- this.setState({
9637
- resources: this.getNewResources(_nextProps, dayPx),
9638
- });
9639
- return;
9640
- }
9641
- }
9642
- getNewResources = (_nextProps, dayPx) => {
9643
- const mappedEvents = filterEvents(_nextProps.events, _nextProps.startDate, _nextProps.endDate, this.props.id, this.props.module)
9644
- .filter((event) => {
9645
- const outOfRange = event.end <= this.props.startDate || event.start >= this.props.endDate;
9646
- return !outOfRange;
9647
- });
9648
- const resources = filterResources(this.props.module, this.props.resourceName, _nextProps.resources, this.props.groupByFunction, _nextProps.endDate, _nextProps.startDate, this.props.id);
9649
- const newResources = resources
9650
- .map((resource) => {
9651
- return {
9652
- ...resource,
9653
- events: mappedEvents.filter((event) => event.resourceId === resource.id),
9654
- };
9655
- })
9656
- .map((resource) => {
9657
- const tops = getEventsInInnerRows(resource, this.state.eventHeight, dayPx, _nextProps.startDate);
9658
- const height = tops.length === 0 ? this.state.eventHeight : tops.length * this.state.eventHeight;
9659
- let flatMapEvents = [];
9660
- for (let h = 0; h < tops.length; h++) {
9661
- flatMapEvents = flatMapEvents.concat(tops[h]);
9662
- }
9663
- return {
9664
- ...resource,
9665
- maxTop: height,
9666
- events: flatMapEvents,
9667
- };
9668
- });
9669
- return newResources;
9670
- };
9671
- handleOnClickContextMenuResourceScheduler = (_clickEvent, _resource) => {
9672
- let datetime = new Date();
9673
- const _ca = this.contentArea;
9674
- if (_clickEvent.domEvent.currentTarget !== undefined) {
9675
- const leftPos = _clickEvent.domEvent.currentTarget.parentElement.getBoundingClientRect().left -
9676
- (_ca?.getBoundingClientRect()?.left ?? 0) -
9677
- window.scrollX;
9678
- datetime = addMinutesToDateFromPx(this.props.startDate, leftPos, this.state.minutePx);
9679
- }
9680
- if (this.props.scheduler_handleOnClickContextMenuResource) {
9681
- this.props.scheduler_handleOnClickContextMenuResource(datetime, _resource, _clickEvent.key, this.props.id);
9682
- }
9683
- };
9684
- handleCrewPinning = (resource, text) => {
9685
- if (this.props.scheduler_handlePinned) {
9686
- this.props.scheduler_handlePinned.call(this.props.parent, resource.id, text, this.props.id);
9687
- }
9688
- };
9689
- render() {
9690
- const isInDateRange = this.state.nowUtc >= this.props.startDate &&
9691
- this.state.nowUtc <= this.props.endDate &&
9692
- this.contentArea !== undefined;
9693
- const showTimeline = isInDateRange && this.state.lineStyle < this.state.maxPx;
9694
- const isPinnedTable = this.props.id.toLowerCase().includes("pinned");
9695
- const schedulerHeight = heightScheduler(this.state.resources, this.props.height, this.props.id === "crewAssignmentsScheduler");
9696
- return (jsx("div", { id: this.props.id, style: {
9697
- maxHeight: isPinnedTable ? "auto" : schedulerHeight,
9698
- }, className: this.state.resources.length > 0 ? "cwellt_tb_con" : "cwellt_tb_con cw_tb_con_emptyValues", children: jsxs("table", { id: "cwelltTableScheduler", children: [this.props.id !== "crewAssignmentsScheduler" && (jsx(SchedulerHeader$1, { timelineProps: {
9699
- maxPx: this.state.maxPx,
9700
- hoursList: this.state.timeHeaders,
9701
- pxPerHour: this.state.hourPx,
9702
- startDate: this.props.startDate,
9703
- endDate: this.props.endDate,
9704
- headerName: this.props.resourceName,
9705
- }, descriptionColumn: this.props.descriptionColumn })), jsx("tbody", { style: {
9706
- width: this.state.maxPx + 150,
9707
- maxHeight: isPinnedTable ? "auto" : schedulerHeight,
9708
- }, className: isPinnedTable ? "fc-body cw-fc-body-pinned" : "fc-body", children: jsxs("tr", { className: "fc_body_row", children: [jsx(ResourcesTitleList, { resources: this.state.resources, canBePinned: this.props.canBePinned ?? false, includesPinned: this.props.id.toLowerCase().includes("pinned"), onCrewPinning: this.handleCrewPinning, onClickResourceContextMenu: (_e, resource) => {
9709
- if (this.props.scheduler_handleOnClickResourceContextMenu) {
9710
- this.props.scheduler_handleOnClickResourceContextMenu(_e, resource);
9711
- }
9712
- }, ResourceTitleComponent: this.props.resourceComp }), jsx("td", { className: "dividerArea" }), 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 })] }) })] }) }));
9713
- }
9714
- }
9715
-
9716
8836
  function dateFromPercentage(startDate, visibleDays, percentage) {
9717
8837
  const start = Temporal.Instant.fromEpochMilliseconds(startDate.getTime());
9718
8838
  const spanMs = Math.round(visibleDays) * 24 * 60 * 60 * 1000;
@@ -9853,7 +8973,7 @@ class OnClickContextMenu {
9853
8973
  }
9854
8974
  }
9855
8975
 
9856
- 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"};
8976
+ 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"};
9857
8977
 
9858
8978
  const getNow$1 = (isUtc) => {
9859
8979
  let now = new Date();
@@ -9919,7 +9039,7 @@ const HeaderTitle = ({ title, dividerText, width }) => {
9919
9039
  const SchedulerHeader = ({ content, divisions, visibleDays, selectedDate, width, onEvent, timeLinePercentage, isUtc }) => {
9920
9040
  const topWidth = (100 / visibleDays);
9921
9041
  const { title, classification } = content;
9922
- return (jsxs("div", { style: { display: "flex" }, children: [jsx(HeaderTitle, { title: title, dividerText: classification, width: width }), jsxs("div", { className: styles$3["scheduler-header-divisions"], style: { flex: 1, display: "flex", position: "relative" }, onMouseDown: (e) => {
9042
+ return (jsxs("div", { className: styles$3["scheduler-header"], children: [jsx(HeaderTitle, { title: title, dividerText: classification, width: width }), jsxs("div", { className: styles$3["scheduler-header-divisions"], style: { flex: 1, display: "flex", position: "relative" }, onMouseDown: (e) => {
9923
9043
  e.preventDefault();
9924
9044
  const clickPercentage = getPercentageFromMouseEvent(e);
9925
9045
  const date = dateFromPercentage(selectedDate, visibleDays, clickPercentage);
@@ -10787,325 +9907,6 @@ const Scheduler = (props) => {
10787
9907
  class UiEvent {
10788
9908
  }
10789
9909
 
10790
- let topsCounter = 0;
10791
- class CwSuperScheduler extends React.Component {
10792
- constructor(Props) {
10793
- super(Props);
10794
- this.state = {
10795
- topsCalculated: 0,
10796
- height: 50,
10797
- dataConfig: this.props.dataConfig ? this.props.dataConfig : undefined,
10798
- pinnedResources: []
10799
- };
10800
- }
10801
- componentDidUpdate(_previousProps, _previousState) {
10802
- if (this.props.pinnedResources !== _previousProps.pinnedResources) {
10803
- let returnedTops = 0;
10804
- let returnedHeight = 50;
10805
- let data;
10806
- if (this.props.pinnedResources) {
10807
- const pinned = [...new Set(this.props.pinnedResources)];
10808
- for (let i = 0; i < pinned.length; i++) {
10809
- data = this.returnDynamicHeight(pinned[i], returnedTops);
10810
- returnedTops = data.topsCalculated;
10811
- returnedHeight = data.height;
10812
- }
10813
- this.setState({
10814
- topsCalculated: returnedTops,
10815
- height: returnedHeight !== 50 ? 80 + returnedHeight : 50,
10816
- pinnedResources: this.props.pinnedResources
10817
- });
10818
- }
10819
- }
10820
- }
10821
- scheduler_handleCblEventClick = (cblEvent, schedulerId) => {
10822
- this.props.scheduler_handleCblEventClick(cblEvent, schedulerId);
10823
- };
10824
- scheduler_handleCblEventClickRight = (cblEvent, schedulerId) => {
10825
- if (this.props.scheduler_handleCblEventClickRight) {
10826
- this.props.scheduler_handleCblEventClickRight(cblEvent, schedulerId);
10827
- }
10828
- };
10829
- scheduler_handleCblEventDoubleClick = (cblEvent, schedulerId) => {
10830
- this.props.scheduler_handleCblEventDoubleClick(cblEvent, schedulerId);
10831
- };
10832
- scheduler_handlePinnedClickMultipleIds = (resIds, schedulerId, requestString) => {
10833
- this.props.scheduler_handlePinningOfResources(resIds, "", schedulerId, requestString);
10834
- };
10835
- scheduler_handlePinnedClick = (resId, text, schedulerId) => {
10836
- const array = new Array();
10837
- array.push(resId);
10838
- this.props.scheduler_handlePinningOfResources(array, text, schedulerId, "resources");
10839
- };
10840
- returnDynamicHeight(pinned, topsCalculated) {
10841
- let height = 100;
10842
- let maxTop = 0;
10843
- const eventHeight = 30;
10844
- const tops = new Array();
10845
- tops[0] = new Array();
10846
- const diffDates = this.props.endDate.getTime() - this.props.startDate.getTime();
10847
- const diffDays = diffDates / (1000 * 3600 * 24);
10848
- const dateToFilter = new Date(this.props.startDate.getTime());
10849
- dateToFilter.setDate(dateToFilter.getDate() + diffDays);
10850
- let events = this.props.pinnedEvents !== undefined ? this.props.pinnedEvents : new Array();
10851
- events = events
10852
- .filter(x => pinned === x.resourceId && x.start >= this.props.startDate && x.start <= dateToFilter)
10853
- .sort((a, b) => {
10854
- return +new Date(a.start) - +new Date(b.start);
10855
- });
10856
- for (let i = 0; i < events.length; i++) {
10857
- const event = events[i];
10858
- if (i === 0 || event.isFullHeight) {
10859
- tops[0].push(event);
10860
- }
10861
- else {
10862
- let found = false;
10863
- for (let j = 0; j < tops.length && found === false; j++) {
10864
- found = this.checkIfSlotAvailable(tops[j], event);
10865
- if (found === true || event.isFullHeight) {
10866
- tops[j].push(event);
10867
- }
10868
- }
10869
- if (found === false) {
10870
- maxTop++;
10871
- tops[maxTop] = new Array();
10872
- tops[maxTop].push(event);
10873
- }
10874
- }
10875
- }
10876
- for (let h = 0; h < tops.length; h++) {
10877
- if (tops.length === 0) {
10878
- height = 100;
10879
- }
10880
- else {
10881
- height = (topsCalculated + tops.length) * eventHeight;
10882
- }
10883
- }
10884
- topsCounter = topsCounter + tops.length;
10885
- return {
10886
- topsCalculated: topsCalculated + tops.length,
10887
- height: height
10888
- };
10889
- }
10890
- checkIfSlotAvailable(array, event) {
10891
- let found = false;
10892
- if (array[array.length - 1].end <= event.start || array[array.length - 1].isFullHeight) {
10893
- found = true;
10894
- }
10895
- return found;
10896
- }
10897
- handleOnClickContextMenuResource = (date, resource, key, schedulerId) => {
10898
- let url = "";
10899
- switch (key) {
10900
- case "showReserves": {
10901
- // CrewControl
10902
- if (this.props.module === "CrewControl") {
10903
- url = "/Winops/CrewControl/CrewControlReact/GetCrewIdsOfReserve";
10904
- }
10905
- // CrewScheduling
10906
- if (this.props.module === "CrewScheduling") {
10907
- url = "/Winops/CrewPlanning/CrewPlanning/GetCrewIdsOfReserve";
10908
- }
10909
- const requestOptions = {
10910
- method: "POST",
10911
- headers: { "Content-Type": "application/json" },
10912
- body: JSON.stringify({
10913
- from: this.dateUTCString(this.props.startDate),
10914
- to: this.dateUTCString(this.props.endDate),
10915
- acftCategories: [],
10916
- functions: [],
10917
- clickedDate: this.dateUTCString(date),
10918
- airportSelected: this.props.airportSelected
10919
- })
10920
- };
10921
- if (this.state.dataConfig) {
10922
- fetch(this.state.dataConfig + url, requestOptions)
10923
- .then(response => response.json())
10924
- .then(res => {
10925
- if (res.length > 0) {
10926
- this.scheduler_handlePinnedClickMultipleIds(res, schedulerId, "Reserves");
10927
- }
10928
- else {
10929
- alert("No Reserves");
10930
- }
10931
- });
10932
- }
10933
- break;
10934
- }
10935
- case "showStandbys": {
10936
- // CrewControl
10937
- if (this.props.module === "CrewControl") {
10938
- url = "/Winops/CrewControl/CrewControlReact/GetCrewIdsOfStandby";
10939
- }
10940
- // CrewScheduling
10941
- if (this.props.module === "CrewScheduling") {
10942
- url = "/Winops/CrewPlanning/CrewPlanning/GetCrewIdsOfStandby";
10943
- }
10944
- const requestOptions2 = {
10945
- method: "POST",
10946
- headers: { "Content-Type": "application/json" },
10947
- body: JSON.stringify({
10948
- from: this.dateUTCString(this.props.startDate),
10949
- to: this.dateUTCString(this.props.startDate),
10950
- acftCategories: [],
10951
- functions: [],
10952
- clickedDate: this.dateUTCString(date),
10953
- airportSelected: this.props.airportSelected
10954
- })
10955
- };
10956
- if (this.state.dataConfig) {
10957
- fetch(this.state.dataConfig + url, requestOptions2)
10958
- .then(response => response.json())
10959
- .then(res => {
10960
- if (res.length > 0) {
10961
- this.scheduler_handlePinnedClickMultipleIds(res, schedulerId, "Standbys");
10962
- }
10963
- else {
10964
- alert("No Standbys");
10965
- }
10966
- });
10967
- }
10968
- break;
10969
- }
10970
- case "showAvailables": {
10971
- // CrewControl
10972
- if (this.props.module === "CrewControl") {
10973
- url = "/Winops/CrewControl/CrewControlReact/GetCrewIdsOfAvailables";
10974
- }
10975
- // CrewScheduling
10976
- if (this.props.module === "CrewScheduling") {
10977
- url = "/Winops/CrewPlanning/CrewPlanning/GetCrewIdsOfAvailables";
10978
- }
10979
- const requestOptions3 = {
10980
- method: "POST",
10981
- headers: { "Content-Type": "application/json" },
10982
- body: JSON.stringify({
10983
- from: this.dateUTCString(this.props.startDate),
10984
- to: this.dateUTCString(this.props.startDate),
10985
- acftCategories: [],
10986
- functions: [],
10987
- clickedDate: this.dateUTCString(date),
10988
- airportSelected: this.props.airportSelected
10989
- })
10990
- };
10991
- if (this.state.dataConfig) {
10992
- fetch(this.state.dataConfig + url, requestOptions3)
10993
- .then(response => response.json())
10994
- .then(res => {
10995
- if (res.length > 0) {
10996
- this.scheduler_handlePinnedClickMultipleIds(res, schedulerId, "Availables");
10997
- }
10998
- else {
10999
- alert("No Availables");
11000
- }
11001
- });
11002
- }
11003
- break;
11004
- }
11005
- default: {
11006
- if (this.props.scheduler_handleOnClickContextMenuResource) {
11007
- this.props.scheduler_handleOnClickContextMenuResource(date, resource, key);
11008
- }
11009
- break;
11010
- }
11011
- }
11012
- };
11013
- dateUTCString(date) {
11014
- if (date instanceof Date) {
11015
- if (date.getFullYear() > 1901)
11016
- return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes())).toISOString();
11017
- }
11018
- return date;
11019
- }
11020
- render() {
11021
- const havePinnedResources = this.state.pinnedResources?.length > 0;
11022
- const firstSchedulerResources = havePinnedResources
11023
- ? this.props.resourcesToPin.filter(x => this.state.pinnedResources.includes(x.id))
11024
- : new Array();
11025
- const secondSchedulerResources = this.props.resources.filter(x => !this.state.pinnedResources.includes(x.id));
11026
- const pinnedEvents = this.props.pinnedEvents !== undefined
11027
- ? this.props.pinnedEvents.filter(x => this.state.pinnedResources.includes(x.resourceId))
11028
- : new Array();
11029
- const notPinnedEvents = this.props.events.filter(x => !this.props.pinnedResources?.includes(x.resourceId));
11030
- return (jsxs("div", { className: "cwelltSuperScheduler_content", children: [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 && (jsx("div", { style: { padding: "0.5rem" }, children: jsx(CwButton, { text: "Clear", onClick: () => {
11031
- this.props.scheduler_handleClearPinnedOnParent();
11032
- } }) })), 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 })] }));
11033
- }
11034
- }
11035
- class CblDragAndDrop {
11036
- fromId;
11037
- toId;
11038
- data;
11039
- droppedOnDate;
11040
- resizeFromStart;
11041
- resizeFromEnd;
11042
- isCtrlKey;
11043
- constructor(fromId, toId, data, droppedOnDate = null, resizeFromStart = null, resizeFromEnd = null, isCtrlKey = null) {
11044
- this.fromId = fromId;
11045
- this.toId = toId;
11046
- this.data = data;
11047
- this.droppedOnDate = droppedOnDate;
11048
- this.resizeFromStart = resizeFromStart;
11049
- this.resizeFromEnd = resizeFromEnd;
11050
- this.isCtrlKey = isCtrlKey;
11051
- }
11052
- }
11053
-
11054
- const getGUID = () => {
11055
- return generateSegment(false) + generateSegment(true) + generateSegment(true) + generateSegment(false);
11056
- };
11057
- const generateSegment = (includeHyphens) => {
11058
- const p = (Math.random().toString(16) + "000000000").substring(2, 10);
11059
- return includeHyphens ? "-" + p.substring(0, 4) + "-" + p.substring(4, 8) : p;
11060
- };
11061
-
11062
- class cblEvent {
11063
- id = "";
11064
- start;
11065
- end;
11066
- resourceId;
11067
- selected = false;
11068
- top = 0;
11069
- leftPx = 0;
11070
- rightPx = 0;
11071
- width = 0;
11072
- isFullHeight = false;
11073
- isReadOnly = false;
11074
- isResizable = false;
11075
- isDraggable = false;
11076
- data = null;
11077
- constructor(start, end, resourceId, data = null, isFullHeight = false, isReadOnly = false, isResizable = false, isDraggable = false) {
11078
- this.start = start;
11079
- this.end = end;
11080
- this.resourceId = resourceId;
11081
- this.data = data;
11082
- this.isFullHeight = isFullHeight;
11083
- this.isReadOnly = isReadOnly;
11084
- this.isResizable = isResizable;
11085
- this.isDraggable = isDraggable;
11086
- this.id = getGUID();
11087
- }
11088
- }
11089
-
11090
- class Resource {
11091
- uid = "";
11092
- id;
11093
- name;
11094
- maxTop;
11095
- events = [];
11096
- isInViewport = false;
11097
- schedulerResourceDisplay;
11098
- isLoading = false;
11099
- data = null;
11100
- constructor(id, name, eventHeight, data = null, schedulerResourceDisplay = null) {
11101
- this.id = id;
11102
- this.name = name;
11103
- this.maxTop = eventHeight;
11104
- this.data = data;
11105
- this.schedulerResourceDisplay = schedulerResourceDisplay || this.name;
11106
- }
11107
- }
11108
-
11109
9910
  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"};
11110
9911
 
11111
9912
  class OnPinRow {
@@ -11588,4 +10389,4 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
11588
10389
  }, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeHolder, disabled: disabled, required: required, autoComplete: "off", "aria-expanded": showDropdown, "aria-haspopup": "listbox", role: "combobox", title: tooltipText }), (isLoading || isInitialLoading) && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selected crewmember", variant: "icon", icon: "close", color: "neutral" })) : (jsx(CwIcon, { iconId: "person" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: options.map((option, index) => (jsx("li", { className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.value), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.text }, option.value))) }) }))] }));
11589
10390
  };
11590
10391
 
11591
- export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwButtonSplit, CwButtonSwitch, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDateTimePickerTemporal, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNavMenu, CwNote, CwOption, CwPopoverButton, CwProgress, CwRadioGroup, CwReportModal, CwScheduler, CwSearchAsync, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSkeleton, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PRESET_LIBRARY_TEMPORAL, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, configureCwLoading, eventIsVisible, filterNavItems, filterVisibleEvents, getCwLoadingDefaults, getDefaultDivisions, getEventSizes, getPresetsByKeysTemporal, itemsToMultiFilterTags, sortNavItems, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };
10392
+ export { CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBadge, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwButtonSplit, CwButtonSwitch, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDateTimePickerTemporal, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNavMenu, CwNote, CwOption, CwPopoverButton, CwProgress, CwRadioGroup, CwReportModal, CwSearchAsync, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSkeleton, CwSortableList, CwSortableTable, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PRESET_LIBRARY_TEMPORAL, PinRowHeader, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, configureCwLoading, eventIsVisible, filterNavItems, filterVisibleEvents, getCwLoadingDefaults, getDefaultDivisions, getEventSizes, getPresetsByKeysTemporal, itemsToMultiFilterTags, sortNavItems, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };