@cwellt_software/cwellt-reactjs-lib 1.4.8 → 1.4.10

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 (36) hide show
  1. package/dist/index.cjs.js +193 -384
  2. package/dist/index.css +2 -2
  3. package/dist/index.d.ts +37 -60
  4. package/dist/index.es.js +192 -382
  5. package/dist/src/common/hooks/useDropdownPortal.d.ts +1 -0
  6. package/dist/src/common/hooks/useDropdownPortal.d.ts.map +1 -1
  7. package/dist/src/components/control/action/buttons/CwButtons.d.ts +15 -3
  8. package/dist/src/components/control/action/buttons/CwButtons.d.ts.map +1 -1
  9. package/dist/src/components/control/choice/dropdown/CwPopoverButton.d.ts.map +1 -1
  10. package/dist/src/components/control/choice/select/CwSelect.d.ts +7 -0
  11. package/dist/src/components/control/choice/select/CwSelect.d.ts.map +1 -1
  12. package/dist/src/components/control/input/new-dates/CwDateRangePicker.d.ts.map +1 -1
  13. package/dist/src/components/custom/scheduler-new/presentation/NewScheduler.d.ts +3 -1
  14. package/dist/src/components/custom/scheduler-new/presentation/NewScheduler.d.ts.map +1 -1
  15. package/dist/src/components/custom/scheduler-new/presentation/components/header/HeaderTitle.d.ts +1 -1
  16. package/dist/src/components/custom/scheduler-new/presentation/components/header/HeaderTitle.d.ts.map +1 -1
  17. package/dist/src/components/custom/scheduler-new/presentation/components/header/SchedulerHeaderState.d.ts +1 -1
  18. package/dist/src/components/custom/scheduler-new/presentation/components/header/SchedulerHeaderState.d.ts.map +1 -1
  19. package/dist/src/components/custom/scheduler-new/presentation/components/row/BackgroundEvent.d.ts +1 -1
  20. package/dist/src/components/custom/scheduler-new/presentation/components/row/BackgroundEvent.d.ts.map +1 -1
  21. package/dist/src/components/custom/scheduler-new/presentation/components/row/DefaultRowHeader.d.ts +1 -1
  22. package/dist/src/components/custom/scheduler-new/presentation/components/row/DefaultRowHeader.d.ts.map +1 -1
  23. package/dist/src/components/custom/scheduler-new/presentation/components/row/Event.d.ts +4 -0
  24. package/dist/src/components/custom/scheduler-new/presentation/components/row/Event.d.ts.map +1 -1
  25. package/dist/src/components/custom/scheduler-new/presentation/components/row/SchedulerRow.d.ts +1 -0
  26. package/dist/src/components/custom/scheduler-new/presentation/components/row/SchedulerRow.d.ts.map +1 -1
  27. package/dist/src/components/custom/super-scheduler/PinRowHeader.d.ts.map +1 -1
  28. package/dist/src/components/custom/super-scheduler/SuperScheduler.d.ts +3 -1
  29. package/dist/src/components/custom/super-scheduler/SuperScheduler.d.ts.map +1 -1
  30. package/dist/src/components/layout/modal/legacy/cw_modal.d.ts.map +1 -1
  31. package/dist/src/index.d.ts +1 -4
  32. package/dist/src/index.d.ts.map +1 -1
  33. package/dist/src/playground/PlaygroundApp.d.ts.map +1 -1
  34. package/dist/src/playground/pages/SchedulerPage.d.ts +3 -0
  35. package/dist/src/playground/pages/SchedulerPage.d.ts.map +1 -0
  36. package/package.json +1 -1
package/dist/index.es.js CHANGED
@@ -1621,48 +1621,6 @@ const CwModalHover = ({ children, hovereable, onFirstOpened, ...dialogProps }) =
1621
1621
  }, children: children })] }));
1622
1622
  };
1623
1623
 
1624
- class CwDialogManager {
1625
- static openDialogs = new Map();
1626
- static OpenDialog(id, props) {
1627
- if (!CwDialogManager.openDialogs.has(id)) {
1628
- const container = document.createElement("div");
1629
- document.body.appendChild(container);
1630
- const root = createRoot(container);
1631
- root.render(jsx(CwDialog, { ...props }));
1632
- CwDialogManager.openDialogs.set(id, { props, container });
1633
- }
1634
- }
1635
- static CloseDialog(id) {
1636
- const dialog = CwDialogManager.openDialogs.get(id);
1637
- if (dialog) {
1638
- const root = createRoot(dialog.container);
1639
- root.unmount();
1640
- dialog.container.remove();
1641
- CwDialogManager.openDialogs.delete(id);
1642
- }
1643
- }
1644
- static CloseAllDialogs() {
1645
- CwDialogManager.openDialogs.forEach((_dialog, id) => {
1646
- CwDialogManager.CloseDialog(id);
1647
- });
1648
- }
1649
- static CloseLastDialog() {
1650
- const lastDialogId = Array.from(CwDialogManager.openDialogs.keys()).pop();
1651
- if (lastDialogId) {
1652
- CwDialogManager.CloseDialog(lastDialogId);
1653
- }
1654
- }
1655
- static CloseFirstDialog() {
1656
- const firstDialogId = Array.from(CwDialogManager.openDialogs.keys())[0];
1657
- if (firstDialogId) {
1658
- CwDialogManager.CloseDialog(firstDialogId);
1659
- }
1660
- }
1661
- static GetOpenDialogCount() {
1662
- return CwDialogManager.openDialogs.size;
1663
- }
1664
- }
1665
-
1666
1624
  /**
1667
1625
  * General purpose aligner flex container, useful for column or row view.
1668
1626
  * @remarks
@@ -1818,14 +1776,16 @@ function CwOption(props) {
1818
1776
  * </CwSelect>
1819
1777
  */
1820
1778
  function CwSelect(props) {
1821
- const { alignProps, labelProps, buttonProps, iconProps, placeholder, feedback, children, style, className, ...selectProps } = props;
1779
+ const { alignProps, labelProps, buttonProps, iconProps, placeholder, feedback, handleChange, children, style, className, ...selectProps } = props;
1822
1780
  const feedbackMessages = feedback
1823
1781
  ? Array.isArray(feedback) ? feedback : [feedback]
1824
1782
  : [];
1825
1783
  const flexDirection = alignProps?.flexDirection ?? "row";
1826
1784
  const dataDirection = { 'data-direction': flexDirection };
1827
1785
  const { backgroundColor, color: textColor, ...wrapperStyle } = style ?? {};
1828
- return (jsxs("div", { className: `cw-select${className ? ` ${className}` : ''}`, ...dataDirection, style: wrapperStyle, children: [jsxs(CwAlign, { ...alignProps, itemProp: selectProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: "cw-flex-row cw-gap-small cw-flex-grow", children: [jsxs("select", { ...selectProps, style: backgroundColor ? { backgroundColor, color: textColor } : undefined, children: [placeholder && jsx(CwOption, { value: "", children: placeholder }), children] }), buttonProps && jsx(CwButton, { ...buttonProps })] })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
1786
+ return (jsxs("div", { className: `cw-select${className ? ` ${className}` : ''}`, ...dataDirection, style: wrapperStyle, children: [jsxs(CwAlign, { ...alignProps, itemProp: selectProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsxs("div", { className: "cw-flex-row cw-gap-small cw-flex-grow", children: [jsxs("select", { ...selectProps, style: backgroundColor ? { backgroundColor, color: textColor } : undefined, onChange: handleChange
1787
+ ? (e) => { handleChange(e.currentTarget.value); selectProps.onChange?.(e); }
1788
+ : selectProps.onChange, children: [placeholder && jsx(CwOption, { value: "", children: placeholder }), children] }), buttonProps && jsx(CwButton, { ...buttonProps })] })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
1829
1789
  }
1830
1790
 
1831
1791
  function CwCardList({ items, renderCard, pageSize = 10, layout = 'grid', defaultCardWidth = 320, cardGap = 16, isLoading = false, emptyState, sortOptions = [], defaultSortKey, keyExtractor, ...htmlProps }) {
@@ -3522,237 +3482,6 @@ function CwTextArea(props) {
3522
3482
  return (jsxs("div", { className: "cw-text-area", ...dataDirection, style: style, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsx("textarea", { ...textareaProps, itemProp: textareaProps.required === true ? "required" : "", style: { resize: resize } }), buttonProps && jsx(CwButton, { ...buttonProps })] }), feedbackMessages.map((feedbackItem, index) => (jsx("p", { className: "cw-input-info", "data-color": feedbackItem.type, children: feedbackItem.message }, index)))] }));
3523
3483
  }
3524
3484
 
3525
- /**
3526
- * Input for entering a string of text.
3527
- * @remarks
3528
- * ```txt
3529
- * CwIcon CwLabel input type=date CwButton
3530
- * ↑ ↑ ↑ ↑
3531
- * ╭────────────────────╮╭════╮
3532
- * ⌂ Birthdate │ 0000 / 00 / 00 │║ Ok ║
3533
- * ╰────────────────────╯╰════╯
3534
- * ```
3535
- * @example
3536
- * ```tsx
3537
- * <CwInputDate
3538
- * iconProps={{ iconId: "Birthdate" }}
3539
- * labelProps={{ children: "Name", width: "100px" }}
3540
- * buttonProps={{ children: "Ok", onClick:()=>{alert("happy happy joy joy")} }}
3541
- * />
3542
- * ```
3543
- */
3544
- function CwInputDate(props) {
3545
- const { alignProps, buttonProps, iconProps, labelProps, ...inputProps } = props;
3546
- inputProps.max = inputProps.max ?? "9999-01-01";
3547
- return (jsx("div", { className: "cw-input-date", children: jsxs(CwAlign, { ...alignProps, itemProp: inputProps.required === true ? "required" : "", children: [labelProps && (jsxs(CwLabel, { ...labelProps, children: [iconProps && jsx(CwIcon, { ...iconProps }), labelProps.text] })), jsx("input", { type: "date", ...inputProps }), buttonProps && jsx(CwButton, { ...buttonProps })] }) }));
3548
- }
3549
-
3550
- var classes = {"datePicker":"cw-input-date-picker-module__datePicker__jogOq","input":"cw-input-date-picker-module__input__uQshH","calendar":"cw-input-date-picker-module__calendar__q39ic","calendarHeader":"cw-input-date-picker-module__calendarHeader__1btPK","arrowButton":"cw-input-date-picker-module__arrowButton__23tNc","calendarTitle":"cw-input-date-picker-module__calendarTitle__oOODw","calendarBody":"cw-input-date-picker-module__calendarBody__-711a","calendarDay":"cw-input-date-picker-module__calendarDay__z-Mmv","selected":"cw-input-date-picker-module__selected__XQgR7","todayButton":"cw-input-date-picker-module__todayButton__oYamC","emptyDay":"cw-input-date-picker-module__emptyDay__lbI5B"};
3551
-
3552
- /**
3553
- * Converts a Date or ISO string to a Temporal.PlainDate.
3554
- */
3555
- function toPlainDate$1(dateString) {
3556
- if (dateString instanceof Date) {
3557
- return Temporal.PlainDate.from({
3558
- year: dateString.getFullYear(),
3559
- month: dateString.getMonth() + 1,
3560
- day: dateString.getDate(),
3561
- });
3562
- }
3563
- // ISO "YYYY-MM-DD" → direct parse
3564
- return Temporal.PlainDate.from(dateString);
3565
- }
3566
- /**
3567
- * Formats a date as DD.MM.YYYY (German locale).
3568
- */
3569
- function toGermanDate(dateString) {
3570
- const pd = toPlainDate$1(dateString);
3571
- const day = String(pd.day).padStart(2, "0");
3572
- const month = String(pd.month).padStart(2, "0");
3573
- return `${day}.${month}.${pd.year}`;
3574
- }
3575
- /**
3576
- * Formats a date as YYYY-MM-DD (ISO).
3577
- */
3578
- function toISODate(dateString) {
3579
- return toPlainDate$1(dateString).toString();
3580
- }
3581
- /**
3582
- * Validates whether a string is a valid DD.MM.YYYY date.
3583
- */
3584
- function isValidGermanDate(textDate) {
3585
- return parseGermanDate(textDate) !== null;
3586
- }
3587
- /**
3588
- * Converts a DD.MM.YYYY string to YYYY-MM-DD, or null if invalid.
3589
- */
3590
- function germanDateToISO(textDate) {
3591
- const pd = parseGermanDate(textDate);
3592
- return pd ? pd.toString() : null;
3593
- }
3594
- /**
3595
- * Converts a DD.MM.YYYY string to a Date object, or null if invalid.
3596
- */
3597
- function germanDateToDate(textDate) {
3598
- const pd = parseGermanDate(textDate);
3599
- if (!pd)
3600
- return null;
3601
- return new Date(pd.year, pd.month - 1, pd.day);
3602
- }
3603
- /**
3604
- * Returns the number of days in the month and the Monday-based
3605
- * weekday offset (0 = Monday) for the 1st of the month.
3606
- */
3607
- function computeCalendarGrid(internalDate) {
3608
- const pd = Temporal.PlainDate.from({
3609
- year: internalDate.getFullYear(),
3610
- month: internalDate.getMonth() + 1,
3611
- day: 1,
3612
- });
3613
- const daysInMonth = pd.daysInMonth;
3614
- const startDay = pd.dayOfWeek - 1; // Temporal: 1=Mon … 7=Sun → 0-based Mon
3615
- return { daysInMonth, startDay };
3616
- }
3617
- /**
3618
- * Returns true when the given day in the internalDate's month/year
3619
- * matches the selected ISO value string.
3620
- */
3621
- function isSelectedDay(internalDate, day, value) {
3622
- const pd = Temporal.PlainDate.from({
3623
- year: internalDate.getFullYear(),
3624
- month: internalDate.getMonth() + 1,
3625
- day,
3626
- });
3627
- return pd.toString() === value;
3628
- }
3629
- /**
3630
- * Returns a new Date set to the 1st of the month offset by `direction` months.
3631
- */
3632
- function computeNextMonthDate(currentDate, direction) {
3633
- const pd = Temporal.PlainDate.from({
3634
- year: currentDate.getFullYear(),
3635
- month: currentDate.getMonth() + 1,
3636
- day: 1,
3637
- });
3638
- const moved = pd.add({ months: direction });
3639
- return new Date(moved.year, moved.month - 1, moved.day);
3640
- }
3641
- // ── internal helper ────────────────────────────────────────────────────
3642
- /**
3643
- * Strictly parses a DD.MM.YYYY string into a Temporal.PlainDate, or null.
3644
- */
3645
- function parseGermanDate(text) {
3646
- const match = /^(\d{2})\.(\d{2})\.(\d{4})$/.exec(text);
3647
- if (!match)
3648
- return null;
3649
- const day = Number(match[1]);
3650
- const month = Number(match[2]);
3651
- const year = Number(match[3]);
3652
- try {
3653
- return Temporal.PlainDate.from({ year, month, day }, { overflow: "reject" });
3654
- }
3655
- catch {
3656
- return null;
3657
- }
3658
- }
3659
-
3660
- const CwInputDatePicker = ({ value, onChange }) => {
3661
- const [isCalendarOpen, setIsCalendarOpen] = useState(false);
3662
- const [internalDate, setInternalDate] = useState(new Date(value || new Date().toISOString()));
3663
- const [textDate, setTextDate] = useState(toGermanDate(value));
3664
- const inputRef = useRef(null);
3665
- const calendarRef = useRef(null);
3666
- useEffect(() => {
3667
- const handleClickOutside = (event) => {
3668
- if (calendarRef.current &&
3669
- !calendarRef.current.contains(event.target) &&
3670
- inputRef.current &&
3671
- !inputRef.current.contains(event.target)) {
3672
- setIsCalendarOpen(false);
3673
- }
3674
- };
3675
- document.addEventListener("mousedown", handleClickOutside);
3676
- return () => {
3677
- document.removeEventListener("mousedown", handleClickOutside);
3678
- };
3679
- }, []);
3680
- useEffect(() => {
3681
- setTextDate(toGermanDate(value));
3682
- }, [value]);
3683
- const submitInput = () => {
3684
- if (isValidGermanDate(textDate)) {
3685
- const newDateString = germanDateToISO(textDate);
3686
- const newDate = germanDateToDate(textDate);
3687
- if (newDateString && newDate) {
3688
- if (newDateString !== value) {
3689
- setInternalDate(newDate);
3690
- onChange?.(newDateString);
3691
- }
3692
- setIsCalendarOpen(false);
3693
- return true;
3694
- }
3695
- else {
3696
- console.error("Invalid date format");
3697
- return false;
3698
- }
3699
- }
3700
- else {
3701
- setTextDate(toGermanDate(new Date(value)));
3702
- return false;
3703
- }
3704
- };
3705
- const handleClickToday = () => {
3706
- const today = toISODate(new Date());
3707
- const currentDate = value;
3708
- if (currentDate != today) {
3709
- setTextDate(toGermanDate(today));
3710
- setInternalDate(new Date(today));
3711
- onChange?.(today);
3712
- }
3713
- setIsCalendarOpen(false);
3714
- };
3715
- const handleClickDay = (day) => {
3716
- const newDate = new Date(internalDate.getFullYear(), internalDate.getMonth(), day);
3717
- const newDateString = toISODate(newDate);
3718
- if (newDateString !== value) {
3719
- setTextDate(toGermanDate(newDate));
3720
- setInternalDate(newDate);
3721
- onChange?.(newDateString);
3722
- }
3723
- setIsCalendarOpen(false);
3724
- };
3725
- const handleClickMonthArrow = (direction) => {
3726
- setInternalDate(prevDate => computeNextMonthDate(prevDate, direction));
3727
- };
3728
- const handlePressEnter = (event) => {
3729
- if (event.key === "Enter" && submitInput()) {
3730
- event.currentTarget.blur();
3731
- }
3732
- };
3733
- const handleBlurInput = (event) => {
3734
- if (value != toISODate(internalDate) && submitInput()) {
3735
- event.currentTarget?.blur();
3736
- }
3737
- };
3738
- const generateCalendarDays = () => {
3739
- const { daysInMonth, startDay } = computeCalendarGrid(internalDate);
3740
- const calendarDays = new Array;
3741
- for (let i = 0; i < startDay; i++) {
3742
- calendarDays.push(jsx("div", { className: classes.emptyDay }, `empty-${i}`));
3743
- }
3744
- for (let day = 1; day <= daysInMonth; day++) {
3745
- const selected = isSelectedDay(internalDate, day, value);
3746
- calendarDays.push(jsx("div", { className: `${classes.calendarDay}${selected ? ` ${classes.selected}` : ""}`, onClick: () => handleClickDay(day), children: day }, day));
3747
- }
3748
- return calendarDays;
3749
- };
3750
- return (jsxs("div", { className: classes.datePicker, children: [jsx("input", { type: "text", value: textDate, onChange: e => setTextDate(e.currentTarget.value), onFocus: () => {
3751
- setInternalDate(new Date(value));
3752
- setIsCalendarOpen(true);
3753
- }, onBlur: handleBlurInput, onKeyDown: handlePressEnter, "data-valid": isValidGermanDate(textDate), ref: inputRef, className: classes.input }), isCalendarOpen && (jsxs("div", { className: classes.calendar, ref: calendarRef, children: [jsxs("div", { className: classes.calendarHeader, children: [jsx("button", { className: classes.arrowButton, onClick: () => handleClickMonthArrow(-1), children: "<" }), jsxs("span", { className: classes.calendarTitle, children: [internalDate.toLocaleString("default", { month: "long" }), " ", internalDate.getFullYear()] }), jsx("button", { className: classes.arrowButton, onClick: () => handleClickMonthArrow(1), children: ">" })] }), jsx("div", { className: classes.calendarBody, children: generateCalendarDays() }), jsx("button", { className: classes.todayButton, onClick: handleClickToday, children: "Today" })] }))] }));
3754
- };
3755
-
3756
3485
  /**
3757
3486
  * Input for entering a string of text.
3758
3487
  * @remarks
@@ -4356,8 +4085,9 @@ function useDropdownPortal({ anchorRef, isOpen, onClose, positionStrategy = defa
4356
4085
  zIndex: 1000,
4357
4086
  right: "auto",
4358
4087
  marginLeft: 0,
4088
+ visibility: "hidden",
4359
4089
  });
4360
- const reposition = useCallback(() => {
4090
+ const reposition = useCallback((visibility = "visible") => {
4361
4091
  const anchor = anchorRef.current;
4362
4092
  if (!anchor)
4363
4093
  return;
@@ -4372,15 +4102,18 @@ function useDropdownPortal({ anchorRef, isOpen, onClose, positionStrategy = defa
4372
4102
  zIndex: 1000,
4373
4103
  right: "auto",
4374
4104
  marginLeft: 0,
4105
+ visibility,
4375
4106
  });
4376
4107
  }, [anchorRef, positionStrategy]);
4377
- // Reposition when opened; re-measure after first paint to get real panel size
4108
+ // Reposition when opened. First pass is hidden (panel not yet measured), second
4109
+ // pass fires in a RAF with the real panel size and reveals the panel — preventing
4110
+ // the one-frame flicker at top:0/left:0 or at the wrong position.
4378
4111
  useEffect(() => {
4379
4112
  if (!isOpen)
4380
4113
  return;
4381
- reposition();
4382
- const raf = requestAnimationFrame(reposition);
4383
- const handleUpdate = () => reposition();
4114
+ reposition("hidden");
4115
+ const raf = requestAnimationFrame(() => reposition("visible"));
4116
+ const handleUpdate = () => reposition("visible");
4384
4117
  window.addEventListener("resize", handleUpdate);
4385
4118
  // Capture phase catches scroll on all scrollable ancestors
4386
4119
  window.addEventListener("scroll", handleUpdate, true);
@@ -4574,18 +4307,50 @@ var styles$a = {"container":"cw-popover-button-module__container__YSWQU","panel"
4574
4307
  function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-start", panelClassName, ...buttonProps }) {
4575
4308
  const containerRef = useRef(null);
4576
4309
  const panelRef = useRef(null);
4310
+ const isOpenRef = useRef(false);
4311
+ const lastToggleClosedAtRef = useRef(0);
4312
+ const RECENT_CLOSE_MS = 200;
4577
4313
  const panelCallbackRef = useCallback((node) => {
4578
4314
  panelRef.current = node;
4579
4315
  node?.setAttribute("popover", "auto");
4580
4316
  }, []);
4317
+ // Sync isOpenRef with the native popover toggle event so we know the real
4318
+ // open state at the moment handleClick fires (light-dismiss closes on pointerdown,
4319
+ // before the click event, so we can't rely on a React state for this).
4320
+ useEffect(() => {
4321
+ const panel = panelRef.current;
4322
+ if (!panel)
4323
+ return;
4324
+ const handler = (e) => {
4325
+ const newState = e.newState;
4326
+ isOpenRef.current = newState === "open";
4327
+ if (newState === "closed") {
4328
+ lastToggleClosedAtRef.current = Date.now();
4329
+ }
4330
+ };
4331
+ panel.addEventListener("toggle", handler);
4332
+ return () => panel.removeEventListener("toggle", handler);
4333
+ }, []);
4581
4334
  const handleClick = useCallback(() => {
4582
4335
  const panel = panelRef.current;
4583
4336
  const container = containerRef.current;
4584
4337
  if (!panel || !container)
4585
4338
  return;
4339
+ // Light-dismiss already closed the panel on pointerdown — don't reopen.
4340
+ if (isOpenRef.current)
4341
+ return;
4342
+ if (Date.now() - lastToggleClosedAtRef.current < RECENT_CLOSE_MS)
4343
+ return;
4586
4344
  const rect = container.getBoundingClientRect();
4587
4345
  panel.style.top = `${rect.bottom + 4}px`;
4588
- if (placement === "bottom-start") {
4346
+ // Prefer the requested placement, but flip if the panel would overflow the viewport.
4347
+ const panelWidth = panel.offsetWidth || 240;
4348
+ const spaceOnRight = window.innerWidth - rect.left;
4349
+ const spaceOnLeft = rect.right;
4350
+ const effectivePlacement = placement === "bottom-end" && spaceOnLeft < panelWidth ? "bottom-start" :
4351
+ placement === "bottom-start" && spaceOnRight < panelWidth ? "bottom-end" :
4352
+ placement;
4353
+ if (effectivePlacement === "bottom-start") {
4589
4354
  panel.style.left = `${rect.left}px`;
4590
4355
  panel.style.right = "auto";
4591
4356
  }
@@ -4593,7 +4358,7 @@ function CwPopoverButton({ children, panelWidth = "auto", placement = "bottom-st
4593
4358
  panel.style.right = `${window.innerWidth - rect.right}px`;
4594
4359
  panel.style.left = "auto";
4595
4360
  }
4596
- panel.togglePopover();
4361
+ panel.showPopover();
4597
4362
  }, [placement]);
4598
4363
  return (jsxs("div", { ref: containerRef, className: styles$a.container, children: [jsx(CwButton, { ...buttonProps, onClick: handleClick }), jsx("div", { ref: panelCallbackRef, className: `${styles$a.panel}${panelClassName ? ` ${panelClassName}` : ""}`, style: { width: panelWidth }, children: children })] }));
4599
4364
  }
@@ -5480,25 +5245,41 @@ const CwContextMenu = ({ children, options, offset = DEFAULT_OFFSET, onSelect })
5480
5245
  };
5481
5246
 
5482
5247
  /**
5483
- * Save button wrapper
5248
+ * Save button wrapper (6 uses pending delete)
5484
5249
  * @deprecated Use <CwButton variant="icon" icon="save" onClick={...} /> instead
5485
5250
  */
5486
5251
  function CwBtnSave({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...rest }) {
5487
- return (jsx(CwButton, { ...rest, variant: "icon", icon: "save", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled }));
5252
+ return (jsx(CwButton, { ...rest, variant: "icon", icon: "save", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Save" }));
5488
5253
  }
5489
5254
  /**
5490
- * Edit button wrapper
5255
+ * Edit button wrapper (5 uses pending delete)
5491
5256
  * @deprecated Use <CwButton variant="icon" icon="edit" onClick={...} /> instead
5492
5257
  */
5493
5258
  function CwBtnEdit({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...rest }) {
5494
- return (jsx(CwButton, { ...rest, variant: "icon", icon: "edit", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled }));
5259
+ return (jsx(CwButton, { ...rest, variant: "icon", icon: "edit", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Edit" }));
5495
5260
  }
5496
5261
  /**
5497
- * Delete button wrapper
5262
+ * Delete button wrapper (4 uses pending delete)
5498
5263
  * @deprecated Use <CwButton variant="icon" icon="delete" color="danger" onClick={...} /> instead
5499
5264
  */
5500
5265
  function CwBtnDelete({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...rest }) {
5501
- return (jsx(CwButton, { ...rest, variant: "icon", icon: "delete", color: "danger", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled }));
5266
+ return (jsx(CwButton, { ...rest, variant: "icon", icon: "delete", color: "danger", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Delete" }));
5267
+ }
5268
+ /**
5269
+ * Approve button wrapper.
5270
+ * DO NOT DELETE — used by Operon (lib pinned at ^1.0.9, currently dormant).
5271
+ * @deprecated Use <CwButton variant="icon" icon="check-circle" onClick={...} /> instead
5272
+ */
5273
+ function CwBtnApprove({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...rest }) {
5274
+ return (jsx(CwButton, { ...rest, variant: "icon", icon: "check-circle", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Approve" }));
5275
+ }
5276
+ /**
5277
+ * Cancel button wrapper.
5278
+ * DO NOT DELETE — used by Operon (lib pinned at ^1.0.9, currently dormant).
5279
+ * @deprecated Use <CwButton variant="icon" icon="cancel" color="danger" onClick={...} /> instead
5280
+ */
5281
+ function CwBtnCancel({ cw_btnOnclick, cw_btn_disabled, onClick, disabled, ...rest }) {
5282
+ return (jsx(CwButton, { ...rest, variant: "icon", icon: "cancel", color: "danger", onClick: onClick ?? cw_btnOnclick, disabled: disabled ?? cw_btn_disabled, title: "Cancel" }));
5502
5283
  }
5503
5284
 
5504
5285
  var styles$4 = {"pickerWrapper":"cw-pickers-base-module__pickerWrapper__Fb9Zo","pickerIcons":"cw-pickers-base-module__pickerIcons__dyd2-","pickerPopup":"cw-pickers-base-module__pickerPopup__dkxJo"};
@@ -5745,7 +5526,7 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
5745
5526
  } }), 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)))] }));
5746
5527
  }
5747
5528
 
5748
- var rangeStyles = {"rangeWrapper":"cw-range-picker-module__rangeWrapper__1nIVs","rangePopup":"cw-range-picker-module__rangePopup__E5jd1","presetList":"cw-range-picker-module__presetList__INiLo"};
5529
+ 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"};
5749
5530
 
5750
5531
  const PRESET_LIBRARY = {
5751
5532
  // === PAST DAYS ===
@@ -6020,6 +5801,7 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6020
5801
  const [isOpen, setIsOpen] = useState(false);
6021
5802
  const [inputFromValue, setInputFromValue] = useState("");
6022
5803
  const [inputToValue, setInputToValue] = useState("");
5804
+ const [rangeErrorMessage, setRangeErrorMessage] = useState(null);
6023
5805
  const [focusedInput, setFocusedInput] = useState();
6024
5806
  const containerRef = useRef(null);
6025
5807
  const wrapperRef = useRef(null);
@@ -6144,21 +5926,27 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6144
5926
  }
6145
5927
  }
6146
5928
  }, [value, displayFormat]);
6147
- const handleRangeSelect = useCallback((range, // El rango sugerido por react-day-picker
6148
- selectedDay) => {
5929
+ const handleRangeSelect = useCallback((range, selectedDay) => {
6149
5930
  let newRange;
6150
5931
  if (focusedInput === 'from') {
6151
5932
  newRange = { from: selectedDay, to: value?.to };
6152
5933
  if (newRange.to && selectedDay > newRange.to) {
6153
5934
  newRange.to = undefined;
6154
5935
  setFocusedInput('to');
5936
+ setRangeErrorMessage(null);
6155
5937
  }
6156
5938
  else if (newRange.to) {
5939
+ if (!validateRange(newRange.from, newRange.to)) {
5940
+ setRangeErrorMessage(maxRangeDays ? `Range cannot exceed ${maxRangeDays} days` : "Invalid date range");
5941
+ return;
5942
+ }
5943
+ setRangeErrorMessage(null);
6157
5944
  setIsOpen(false);
6158
5945
  setFocusedInput(undefined);
6159
5946
  }
6160
5947
  else {
6161
5948
  setFocusedInput('to');
5949
+ setRangeErrorMessage(null);
6162
5950
  }
6163
5951
  }
6164
5952
  else if (focusedInput === 'to') {
@@ -6166,13 +5954,20 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6166
5954
  if (newRange.from && selectedDay < newRange.from) {
6167
5955
  newRange.from = undefined;
6168
5956
  setFocusedInput('from');
5957
+ setRangeErrorMessage(null);
6169
5958
  }
6170
5959
  else if (newRange.from) {
5960
+ if (!validateRange(newRange.from, newRange.to)) {
5961
+ setRangeErrorMessage(maxRangeDays ? `Range cannot exceed ${maxRangeDays} days` : "Invalid date range");
5962
+ return;
5963
+ }
5964
+ setRangeErrorMessage(null);
6171
5965
  setIsOpen(false);
6172
5966
  setFocusedInput(undefined);
6173
5967
  }
6174
5968
  else {
6175
5969
  setFocusedInput('from');
5970
+ setRangeErrorMessage(null);
6176
5971
  }
6177
5972
  }
6178
5973
  else {
@@ -6182,20 +5977,23 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6182
5977
  }
6183
5978
  newRange = { from: range.from, to: range.to };
6184
5979
  if (range.from && range.to) {
5980
+ if (!validateRange(newRange.from, newRange.to)) {
5981
+ setRangeErrorMessage(maxRangeDays ? `Range cannot exceed ${maxRangeDays} days` : "Invalid date range");
5982
+ return;
5983
+ }
5984
+ setRangeErrorMessage(null);
6185
5985
  setIsOpen(false);
6186
5986
  setFocusedInput(undefined);
6187
5987
  }
6188
5988
  else if (range.from) {
6189
5989
  setFocusedInput('to');
5990
+ setRangeErrorMessage(null);
6190
5991
  }
6191
5992
  else {
6192
5993
  setFocusedInput('from');
5994
+ setRangeErrorMessage(null);
6193
5995
  }
6194
5996
  }
6195
- // Validate range before sending
6196
- if (newRange.from && newRange.to && !validateRange(newRange.from, newRange.to)) {
6197
- return;
6198
- }
6199
5997
  onChange(newRange);
6200
5998
  }, [onChange, validateRange, value, focusedInput]);
6201
5999
  const handleClearFrom = useCallback((e) => {
@@ -6364,11 +6162,11 @@ function CwDateRangePicker({ value, onChange, minDate, maxDate, disabledDates, d
6364
6162
  }
6365
6163
  return undefined;
6366
6164
  }, [value]);
6367
- 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: [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: {
6368
- today: new Date(),
6369
- }, modifiersClassNames: {
6370
- today: "rdp-day-today",
6371
- } })] }))] })] }) }));
6165
+ 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: {
6166
+ today: new Date(),
6167
+ }, modifiersClassNames: {
6168
+ today: "rdp-day-today",
6169
+ } })] }), jsx("div", { role: "alert", "aria-live": "polite", className: rangeStyles.rangeError, children: rangeErrorMessage })] }))] })] }) }));
6372
6170
  }
6373
6171
 
6374
6172
  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"};
@@ -8601,7 +8399,7 @@ const BackgroundEvent = ({ value, heightRem }) => {
8601
8399
  position: "absolute",
8602
8400
  height: `${heightRem}rem`,
8603
8401
  pointerEvents: "auto",
8604
- }, children: jsx(CwGenericTooltip, { content: value.tooltip, position: "bottom", dissapearsWhenHover: true, showDelay: 200, children: jsx("div", { style: {
8402
+ }, children: jsx(CwTooltipNew, { content: value.tooltip, position: "bottom", dissapearsWhenHover: true, showDelay: 200, children: jsx("div", { style: {
8605
8403
  overflow: "hidden",
8606
8404
  backgroundColor: backColor,
8607
8405
  height: `${heightRem}rem`,
@@ -8761,6 +8559,7 @@ var styles$1 = {"scheduler-row-header":"scheduler-row-module__scheduler-row-head
8761
8559
  const DefaultRowHeader = ({ value, width, onEvent }) => {
8762
8560
  return (jsxs("div", { style: {
8763
8561
  width: width,
8562
+ flexShrink: 0,
8764
8563
  // background: color,
8765
8564
  }, onClick: (_) => {
8766
8565
  onEvent(new OnClickRowHeader(value.rowId));
@@ -8779,10 +8578,10 @@ const EventSideDrag = ({ left = false, heightRem, onStartEvent }) => {
8779
8578
  };
8780
8579
 
8781
8580
  const MAX_EVENT_HEIGHT_REM = 1.5;
8782
- const SchedulerEvent = ({ value, heightRem, onEvent }) => {
8581
+ const SchedulerEvent = ({ value, heightRem, onEvent, maxEventHeightRem }) => {
8783
8582
  const [isOnDrag, setIsOnDrag] = useState(false);
8784
8583
  const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
8785
- const effectiveHeight = Math.min(heightRem, MAX_EVENT_HEIGHT_REM);
8584
+ const effectiveHeight = Math.min(heightRem, maxEventHeightRem ?? MAX_EVENT_HEIGHT_REM);
8786
8585
  const topOffsetRem = (heightRem - effectiveHeight) / 2;
8787
8586
  const topOffsetPx = Math.round(topOffsetRem * 16) + 1;
8788
8587
  // Calculate colors of the event
@@ -8814,78 +8613,86 @@ const SchedulerEvent = ({ value, heightRem, onEvent }) => {
8814
8613
  e.preventDefault();
8815
8614
  onEvent(new OnDoubleClickEvent(value.id));
8816
8615
  });
8817
- return (jsx(CwAnchoredMenu, { open: isContextMenuOpen, onOpenChange: setIsContextMenuOpen, onContextMenu: (e) => {
8818
- e.stopPropagation();
8819
- // onEvent(new OnRightClickEvent(value.id));
8820
- }, placement: "bottom", options: value.contextMenuItems ?? [], onSelect: (key) => {
8821
- onEvent(new OnClickContextMenu(value.id, key));
8822
- }, children: jsx("div", { style: {
8823
- top: `${topOffsetPx}px`,
8824
- left: `${value.left}%`,
8825
- width: `${value.width}%`,
8826
- minWidth: "5px",
8827
- position: "absolute",
8828
- zIndex: isOnDrag ? 999 : undefined,
8829
- contentVisibility: "auto",
8830
- pointerEvents: "auto",
8831
- }, onClick: handleClick, onDoubleClick: handleDoubleClick, draggable: value.isDraggable, onMouseDown: (_) => {
8832
- if (value.isDraggable)
8833
- setIsOnDrag(true);
8834
- }, onMouseLeave: (_) => {
8835
- if (value.isDraggable)
8836
- setIsOnDrag(false);
8837
- }, onDragStart: (_) => {
8838
- if (value.isDraggable)
8839
- onEvent(new OnDragEvent(value.id, value.rowId));
8840
- }, onDragEnd: (_) => {
8841
- if (value.isDraggable)
8842
- setIsOnDrag(false);
8843
- }, children: jsx(CwTooltipNew, { content: value.tooltip, position: "bottom", hide: isOnDrag, showDelay: 200, children: jsxs("div", { style: {
8844
- border: value.selected ? "2px solid black" : "none",
8845
- backgroundColor: backColor,
8846
- height: `calc(${effectiveHeight}rem - 4px)`,
8847
- opacity: eventTransparent ? 0.5 : 1,
8848
- ...value.style,
8849
- }, className: styles$2["scheduler-event"], children: [jsxs("div", { style: {
8850
- display: "flex",
8851
- flexDirection: "row",
8852
- alignItems: "stretch",
8853
- width: "100%",
8854
- padding: "0 2px",
8855
- cursor: value.isDraggable ? "pointer" : "default",
8856
- // height: `calc(${effectiveHeight}rem - 8px)`,
8857
- height: "100%",
8858
- }, children: [value.isResizable && (jsx(EventSideDrag, { left: true, heightRem: effectiveHeight * 0.7, onStartEvent: () => {
8859
- onEvent(new OnLeftDragStart(value.id));
8860
- } })), jsxs("div", { className: styles$2["scheduler-event-container"], children: [jsx("div", { style: {
8861
- display: "flex",
8862
- flexDirection: "row",
8863
- alignItems: "center",
8864
- whiteSpace: "nowrap",
8865
- color: textColor,
8866
- }, children: value.icons }), jsx("span", { style: {
8867
- padding: "0.1rem",
8868
- color: textColor,
8869
- display: "flex",
8870
- flex: 1,
8871
- alignItems: "center",
8872
- width: "100%",
8873
- }, children: value.rectangleColors && value.rectangleColors.length > 0 ? (jsx("div", { style: {
8874
- display: "flex",
8875
- width: "100%",
8876
- }, children: value.rectangleColors.map((item, i) => (jsx("div", { className: "cwellt_rectangle_indicator", style: {
8877
- backgroundColor: item,
8616
+ return (jsxs(Fragment, { children: [value.topLabel && (jsx("div", { style: {
8617
+ position: "absolute",
8618
+ top: 0,
8619
+ left: `${value.left}%`,
8620
+ width: `${value.width}%`,
8621
+ height: `${topOffsetPx}px`,
8622
+ pointerEvents: "none",
8623
+ contentVisibility: "auto",
8624
+ }, children: value.topLabel })), jsx(CwAnchoredMenu, { open: isContextMenuOpen, onOpenChange: setIsContextMenuOpen, onContextMenu: (e) => {
8625
+ e.stopPropagation();
8626
+ // onEvent(new OnRightClickEvent(value.id));
8627
+ }, placement: "bottom", options: value.contextMenuItems ?? [], onSelect: (key) => {
8628
+ onEvent(new OnClickContextMenu(value.id, key));
8629
+ }, children: jsx("div", { style: {
8630
+ top: `${topOffsetPx}px`,
8631
+ left: `${value.left}%`,
8632
+ width: `${value.width}%`,
8633
+ minWidth: "5px",
8634
+ position: "absolute",
8635
+ zIndex: isOnDrag ? 999 : undefined,
8636
+ contentVisibility: "auto",
8637
+ pointerEvents: "auto",
8638
+ }, onClick: handleClick, onDoubleClick: handleDoubleClick, draggable: value.isDraggable, onMouseDown: (_) => {
8639
+ if (value.isDraggable)
8640
+ setIsOnDrag(true);
8641
+ }, onMouseLeave: (_) => {
8642
+ if (value.isDraggable)
8643
+ setIsOnDrag(false);
8644
+ }, onDragStart: (_) => {
8645
+ if (value.isDraggable)
8646
+ onEvent(new OnDragEvent(value.id, value.rowId));
8647
+ }, onDragEnd: (_) => {
8648
+ if (value.isDraggable)
8649
+ setIsOnDrag(false);
8650
+ }, children: jsx(CwTooltipNew, { content: value.tooltip, position: "bottom", hide: isOnDrag, showDelay: 200, children: jsxs("div", { style: {
8651
+ border: value.selected ? "2px solid black" : "none",
8652
+ backgroundColor: backColor,
8653
+ height: `calc(${effectiveHeight}rem - 4px)`,
8654
+ opacity: eventTransparent ? 0.5 : 1,
8655
+ ...value.style,
8656
+ }, className: styles$2["scheduler-event"], children: [jsxs("div", { style: {
8657
+ display: "flex",
8658
+ flexDirection: "row",
8659
+ alignItems: "stretch",
8660
+ width: "100%",
8661
+ padding: "0 2px",
8662
+ cursor: value.isDraggable ? "pointer" : "default",
8663
+ // height: `calc(${effectiveHeight}rem - 8px)`,
8664
+ height: "100%",
8665
+ }, children: [value.isResizable && (jsx(EventSideDrag, { left: true, heightRem: effectiveHeight * 0.7, onStartEvent: () => {
8666
+ onEvent(new OnLeftDragStart(value.id));
8667
+ } })), jsxs("div", { className: styles$2["scheduler-event-container"], children: [jsx("div", { style: {
8668
+ display: "flex",
8669
+ flexDirection: "row",
8670
+ alignItems: "center",
8671
+ whiteSpace: "nowrap",
8672
+ color: textColor,
8673
+ }, children: value.icons }), jsx("span", { style: {
8674
+ padding: "0.1rem",
8675
+ color: textColor,
8676
+ display: "flex",
8878
8677
  flex: 1,
8879
- height: "8px",
8880
- margin: 0,
8881
- padding: 0,
8882
- } }, value.id + "_" + i))) })) : (value.name) })] }), value.isResizable && (jsx(EventSideDrag, { heightRem: effectiveHeight * 0.7, onStartEvent: () => {
8883
- onEvent(new OnRightDragStart(value.id));
8884
- } }))] }), value.primaryTimeMarkerColor && (jsx("div", { className: styles$2["time-marker"], style: {
8885
- backgroundColor: value.primaryTimeMarkerColor,
8886
- } })), value.secondaryTimeMarkerColor && (jsx("div", { className: styles$2["time-marker"], style: {
8887
- backgroundColor: value.secondaryTimeMarkerColor,
8888
- } }))] }) }) }, value.id) }));
8678
+ alignItems: "center",
8679
+ width: "100%",
8680
+ }, children: value.rectangleColors && value.rectangleColors.length > 0 ? (jsx("div", { style: {
8681
+ display: "flex",
8682
+ width: "100%",
8683
+ }, children: value.rectangleColors.map((item, i) => (jsx("div", { className: "cwellt_rectangle_indicator", style: {
8684
+ backgroundColor: item,
8685
+ flex: 1,
8686
+ height: "8px",
8687
+ margin: 0,
8688
+ padding: 0,
8689
+ } }, value.id + "_" + i))) })) : (value.name) })] }), value.isResizable && (jsx(EventSideDrag, { heightRem: effectiveHeight * 0.7, onStartEvent: () => {
8690
+ onEvent(new OnRightDragStart(value.id));
8691
+ } }))] }), value.primaryTimeMarkerColor && (jsx("div", { className: styles$2["time-marker"], style: {
8692
+ backgroundColor: value.primaryTimeMarkerColor,
8693
+ } })), value.secondaryTimeMarkerColor && (jsx("div", { className: styles$2["time-marker"], style: {
8694
+ backgroundColor: value.secondaryTimeMarkerColor,
8695
+ } }))] }) }) }, value.id) })] }));
8889
8696
  };
8890
8697
 
8891
8698
  const SchedulerRow = memo((props) => {
@@ -8947,7 +8754,7 @@ const SchedulerRow = memo((props) => {
8947
8754
  position: "relative",
8948
8755
  height: props.rowHeightInRem + "rem",
8949
8756
  pointerEvents: "none"
8950
- }, children: internalRow.map((event) => (jsx(EventComp, { value: event, heightRem: props.rowHeightInRem, onEvent: onEvent }, event.id))) }, index));
8757
+ }, children: internalRow.map((event) => (jsx(EventComp, { value: event, heightRem: props.rowHeightInRem, onEvent: onEvent, maxEventHeightRem: props.maxEventHeightRem }, event.id))) }, index));
8951
8758
  }), indicatorRows.length > 0 && (jsx(IndicatorRow, { indicators: indicatorRows, selectedDate: selectedDate, visibleDays: visibleDays })), !(timeLinePercentage < 0 || timeLinePercentage > 100) && (jsx(TimeLine, { color: "red", left: `${timeLinePercentage}%`, top: "0px", height: `100%` }))] }) })] }));
8952
8759
  }, (prevProps, nextProps) => {
8953
8760
  // This memo is necessary to prevent re-render all the rows when a user makes drag and drop
@@ -9234,7 +9041,7 @@ const RowContent = React__default.memo(function RowContent(props) {
9234
9041
  return (jsx("div", { style: {
9235
9042
  ...props.style,
9236
9043
  backgroundColor: props.rowColor
9237
- }, children: jsx(SchedulerRow, { events: props.events, backgroundEvents: props.backgroundEvents, indicatorRows: props.indicatorRows, rowHeader: header, EventComp: props.EventComp, BackgroundEventComp: props.BackgroundEventComp, RowTitleComp: props.RowTitleComp, weekendLines: props.weekendLines, divisionLines: props.divisionLines, timeLinePercentage: props.timeLinePercentage, rowHeightInRem: props.rowHeightRem, onEvent: props.onEvent, contextMenuItems: props.contextMenuItems, visibleDays: props.visibleDays, selectedDate: props.selectedDate }) }, props.row.rowId));
9044
+ }, children: jsx(SchedulerRow, { events: props.events, backgroundEvents: props.backgroundEvents, indicatorRows: props.indicatorRows, rowHeader: header, EventComp: props.EventComp, BackgroundEventComp: props.BackgroundEventComp, RowTitleComp: props.RowTitleComp, weekendLines: props.weekendLines, divisionLines: props.divisionLines, timeLinePercentage: props.timeLinePercentage, rowHeightInRem: props.rowHeightRem, maxEventHeightRem: props.maxEventHeightRem, onEvent: props.onEvent, contextMenuItems: props.contextMenuItems, visibleDays: props.visibleDays, selectedDate: props.selectedDate }) }, props.row.rowId));
9238
9045
  });
9239
9046
  // Outer (unmemoised) row: looks up per-row buckets from the shared `data`
9240
9047
  // object and forwards them as flat props to `RowContent`. Because the
@@ -9245,7 +9052,7 @@ const Row = ({ index, style, data }) => {
9245
9052
  const rowColor = data.groupRowColors
9246
9053
  ? Math.floor(index / 2) % 2 === 0 ? data.evenColor : data.oddColor
9247
9054
  : index % 2 === 0 ? data.evenColor : data.oddColor;
9248
- return (jsx(RowContent, { style: style, row: row, rowColor: rowColor, events: data.eventsByRow.get(row.rowId) ?? EMPTY_EVENTS, backgroundEvents: data.backgroundEventsByRow.get(row.rowId) ?? EMPTY_BG_EVENTS, indicatorRows: data.indicatorRowsByRow.get(row.rowId) ?? EMPTY_INDICATORS, EventComp: data.EventComp, BackgroundEventComp: data.BackgroundEventComp, RowTitleComp: data.RowTitleComp, rowHeaderWidth: data.rowHeaderWidth, rowHeightRem: row.rowHeightRem ?? data.rowHeightRem, weekendLines: data.weekendLines, divisionLines: data.divisionLines, timeLinePercentage: data.timeLinePercentage, selectedDate: data.selectedDate, visibleDays: data.visibleDays, contextMenuItems: data.contextMenuItems, onEvent: data.onEvent }));
9055
+ return (jsx(RowContent, { style: style, row: row, rowColor: rowColor, events: data.eventsByRow.get(row.rowId) ?? EMPTY_EVENTS, backgroundEvents: data.backgroundEventsByRow.get(row.rowId) ?? EMPTY_BG_EVENTS, indicatorRows: data.indicatorRowsByRow.get(row.rowId) ?? EMPTY_INDICATORS, EventComp: data.EventComp, BackgroundEventComp: data.BackgroundEventComp, RowTitleComp: data.RowTitleComp, rowHeaderWidth: data.rowHeaderWidth, rowHeightRem: row.rowHeightRem ?? data.rowHeightRem, maxEventHeightRem: data.maxEventHeightRem, weekendLines: data.weekendLines, divisionLines: data.divisionLines, timeLinePercentage: data.timeLinePercentage, selectedDate: data.selectedDate, visibleDays: data.visibleDays, contextMenuItems: data.contextMenuItems, onEvent: data.onEvent }));
9249
9056
  };
9250
9057
  // Bucket items by rowId, but reuse previous bucket arrays whenever a row's
9251
9058
  // contents have not changed. Keeping bucket references stable is essential
@@ -9275,7 +9082,7 @@ const groupByRowIdStable = (items, prev) => {
9275
9082
  return next;
9276
9083
  };
9277
9084
  const Scheduler = (props) => {
9278
- const { header: headerContent, id, events: eventsState, backgroundEvents, indicatorRows: allIndicatorRows = [], contextMenuItems, EventComp, RowTitleComp, orderCategories = ["title"], useOrderCategory, onEvent, groupRowColors, rowHeaderWidth = 180, rowHeightRem = 1.75, } = props;
9085
+ const { header: headerContent, id, events: eventsState, backgroundEvents, indicatorRows: allIndicatorRows = [], contextMenuItems, EventComp, RowTitleComp, orderCategories = ["title"], useOrderCategory, onEvent, groupRowColors, rowHeaderWidth = 180, rowHeightRem = 1.75, maxEventHeightRem, } = props;
9279
9086
  const BackgroundEventComp = props.BackgroundEventComp ?? BackgroundEvent;
9280
9087
  const [constraintElement, setConstraintElement] = useState(null);
9281
9088
  const rows = useOrderCategory === false
@@ -9359,6 +9166,7 @@ const Scheduler = (props) => {
9359
9166
  RowTitleComp: RowTitleComp,
9360
9167
  rowHeaderWidth,
9361
9168
  rowHeightRem,
9169
+ maxEventHeightRem,
9362
9170
  weekendLines: weekendsLines,
9363
9171
  divisionLines,
9364
9172
  timeLinePercentage,
@@ -9379,6 +9187,7 @@ const Scheduler = (props) => {
9379
9187
  RowTitleComp,
9380
9188
  rowHeaderWidth,
9381
9189
  rowHeightRem,
9190
+ maxEventHeightRem,
9382
9191
  weekendsLines,
9383
9192
  divisionLines,
9384
9193
  timeLinePercentage,
@@ -9759,6 +9568,7 @@ const PinRowHeader = ({ value, width, onEvent }) => {
9759
9568
  onEvent(new OnClickContextMenu(value.rowId, key));
9760
9569
  }, children: jsx(CwTooltipNew, { content: value.tooltip, position: "right", dissapearsWhenHover: true, children: jsxs("div", { style: {
9761
9570
  width: width,
9571
+ flexShrink: 0,
9762
9572
  height: "100%",
9763
9573
  background: highlightColor
9764
9574
  }, className: styles["super-scheduler-row-header"], children: [jsx("button", { className: "cw-button-icon cwi-pin", "data-pinned": value.isPinned, onClick: (_) => {
@@ -9772,13 +9582,13 @@ const PinRowHeader = ({ value, width, onEvent }) => {
9772
9582
  jsxs("span", { className: styles["scheduler-crewmember-functions"], children: ["(", value.title3, ")"] }), value.subtitle2 && jsxs("span", { children: ["-", value.subtitle2] })] })] }), isLoading ? jsx("span", { className: "cwi-icons cwi-spinner" }) : undefined] }) }, value.rowId) }, value.rowId);
9773
9583
  };
9774
9584
 
9775
- const SuperScheduler = ({ id, state, header, rows, events, headerColumnComp, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, indicatorRows = [], contextMenuItems, onEvent, rowHeightRem = 1.75 }) => {
9585
+ const SuperScheduler = ({ id, state, header, rows, events, headerColumnComp, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, indicatorRows = [], contextMenuItems, onEvent, rowHeightRem = 1.75, rowHeaderWidth, maxEventHeightRem, }) => {
9776
9586
  const pinnedRows = rows.filter((it) => it.isPinned);
9777
9587
  const notPinnedRows = rows.filter((it) => !it.isPinned);
9778
9588
  const isFirstVisible = pinnedRows.length > 0;
9779
- return (jsxs(Fragment, { children: [isFirstVisible && (jsxs(Fragment, { children: [jsx(Scheduler, { id: `${id}-pinned`, state: state, header: header, rows: pinnedRows, events: events, backgroundEvents: backgroundEvents, indicatorRows: indicatorRows, contextMenuItems: contextMenuItems, orderCategories: pinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem }), jsx("div", { children: jsx(CwButton, { onClick: () => {
9589
+ return (jsxs(Fragment, { children: [isFirstVisible && (jsxs(Fragment, { children: [jsx(Scheduler, { id: `${id}-pinned`, state: state, header: header, rows: pinnedRows, events: events, backgroundEvents: backgroundEvents, indicatorRows: indicatorRows, contextMenuItems: contextMenuItems, orderCategories: pinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem, rowHeaderWidth: rowHeaderWidth, maxEventHeightRem: maxEventHeightRem }), jsx("div", { children: jsx(CwButton, { onClick: () => {
9780
9590
  onEvent(new OnClearPinned());
9781
- }, children: "Clear pinned" }) })] })), jsx(Scheduler, { id: `${id}-notPinned`, state: { ...state, isHeaderVisible: !isFirstVisible }, header: header, rows: notPinnedRows, events: events, backgroundEvents: backgroundEvents, indicatorRows: indicatorRows, contextMenuItems: contextMenuItems, orderCategories: unPinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem })] }));
9591
+ }, children: "Clear pinned" }) })] })), jsx(Scheduler, { id: `${id}-notPinned`, state: { ...state, isHeaderVisible: !isFirstVisible }, header: header, rows: notPinnedRows, events: events, backgroundEvents: backgroundEvents, indicatorRows: indicatorRows, contextMenuItems: contextMenuItems, orderCategories: unPinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem, rowHeaderWidth: rowHeaderWidth, maxEventHeightRem: maxEventHeightRem })] }));
9782
9592
  };
9783
9593
 
9784
9594
  /**
@@ -10215,4 +10025,4 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
10215
10025
  }, "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))) }) }))] }));
10216
10026
  };
10217
10027
 
10218
- export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateTimePicker, CwDateTimePickerCompact, CwDialog, CwDialogManager, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUpload, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDate, CwInputDatePicker, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwLoadingSmall, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNote, CwOption, CwPopoverButton, CwReportModal, CwScheduler, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, eventIsVisible, filterVisibleEvents, getDefaultDivisions, getEventSizes, itemsToMultiFilterTags, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };
10028
+ export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateTimePicker, CwDateTimePickerCompact, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUpload, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwLoadingSmall, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNote, CwOption, CwPopoverButton, CwReportModal, CwScheduler, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, eventIsVisible, filterVisibleEvents, getDefaultDivisions, getEventSizes, itemsToMultiFilterTags, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };