@cwellt_software/cwellt-reactjs-lib 1.4.10 → 1.4.12

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.
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import React__default, { useState, useRef, useEffect, useCallback, useLayoutEffect, createContext, useContext, cloneElement, useMemo, forwardRef, useImperativeHandle, createElement, memo, Fragment as Fragment$1, Component } from 'react';
3
+ import React__default, { useState, useRef, useEffect, useCallback, useLayoutEffect, createContext, useContext, cloneElement, useMemo, forwardRef, useImperativeHandle, createElement, useId, memo, Fragment as Fragment$1, Component } from 'react';
4
4
  import { createPortal } from 'react-dom';
5
5
  import { createRoot } from 'react-dom/client';
6
6
  import Draggable from 'react-draggable';
@@ -5017,6 +5017,265 @@ function CwSearchInput(optionsProps) {
5017
5017
  return (jsxs("div", { className: `cw-search-input ${className || ""}`, style: style, id: id, ...otherProps, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { type: "text", value: searchText, onChange: handleInputChange, onFocus: handleInputFocus, onBlur: handleInputBlur, placeholder: placeholder, className: "cw-input-search", disabled: disabled }), isLoading && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: searchText && !disabled && !isLoading ? (jsx(CwButton, { type: "button", onClick: handleClearClick, "aria-label": "Clear search", variant: "icon", icon: "close", color: "neutral" })) : (iconProps ? jsx(CwIcon, { ...iconProps }) : jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, className: dropdownStyles.dropdown, style: panelStyle, children: jsx("ul", { children: filteredOptions.map((option) => (jsx("li", { className: dropdownStyles.option, onClick: () => handleOptionSelect(option), onMouseDown: (e) => e.preventDefault(), children: renderOption ? renderOption(option) : option.description }, option.id))) }) }))] }));
5018
5018
  }
5019
5019
 
5020
+ /**
5021
+ * Generic API-backed search input. Fetches matching options from a caller-supplied `onSearch`
5022
+ * callback as the user types (debounced), renders them in a portal-based dropdown with keyboard
5023
+ * navigation, and commits the selected id via `onChange`.
5024
+ *
5025
+ * All domain logic — API URLs, auth/config, display formatting, provider/secondary lookups — lives
5026
+ * in the caller's callbacks, so this component stays application-agnostic. It is the base for thin
5027
+ * wrappers such as `FindAirport` / `FindCrewmember`.
5028
+ *
5029
+ * Improvements over the legacy `CwFindAirport` / `CwFindCrewmember`: an `AbortController` cancels
5030
+ * superseded in-flight requests (fixes out-of-order results), and `minChars` / `debounceMs` are
5031
+ * configurable.
5032
+ *
5033
+ * @example
5034
+ * <CwSearchAsync
5035
+ * onSearch={(text, signal) => repo.search(text, signal)}
5036
+ * onChange={(id) => setSelectedId(id)}
5037
+ * labelProps={{ text: 'Airport' }}
5038
+ * icon={{ iconId: 'control-tower' }}
5039
+ * />
5040
+ */
5041
+ const CwSearchAsync = ({ onSearch, onChange, value, onResolveInitial, onResolveSelection, icon, placeholder = "Search…", minChars = 2, debounceMs = 300, disabled = false, required = false, initialDisplayText, searchTrigger, labelProps, alignProps, width, className = "", }) => {
5042
+ // State
5043
+ const [inputValue, setInputValue] = useState("");
5044
+ const [options, setOptions] = useState([]);
5045
+ const [isLoading, setIsLoading] = useState(false);
5046
+ const [isInitialLoading, setIsInitialLoading] = useState(false);
5047
+ const [showDropdown, setShowDropdown] = useState(false);
5048
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
5049
+ const [tooltipText, setTooltipText] = useState("");
5050
+ // Refs
5051
+ const inputRef = useRef(null);
5052
+ const wrapperRef = useRef(null);
5053
+ const debounceRef = useRef();
5054
+ const abortRef = useRef(null);
5055
+ const lastQueryRef = useRef("");
5056
+ const didMountRef = useRef(false);
5057
+ const lastResolvedValueRef = useRef(undefined);
5058
+ const initialResolveAbortRef = useRef(null);
5059
+ // Stable ids wiring the combobox input to its listbox popup for assistive tech.
5060
+ const listboxId = useId();
5061
+ const optionId = (index) => `${listboxId}-opt-${index}`;
5062
+ // Cancel a pending initial-value resolve when the user takes over (typing / clearing / reset),
5063
+ // so a slow resolve can't overwrite newer input and the loading flag never sticks.
5064
+ const cancelInitialResolve = useCallback(() => {
5065
+ initialResolveAbortRef.current?.abort();
5066
+ initialResolveAbortRef.current = null;
5067
+ setIsInitialLoading(false);
5068
+ }, []);
5069
+ const { panelRef, panelStyle, renderPanel } = useDropdownPortal({
5070
+ anchorRef: wrapperRef,
5071
+ isOpen: showDropdown && options.length > 0,
5072
+ onClose: () => { setShowDropdown(false); setHighlightedIndex(-1); },
5073
+ });
5074
+ // Core search runner — aborts superseded requests and drops stale responses.
5075
+ const runSearch = useCallback(async (text) => {
5076
+ abortRef.current?.abort();
5077
+ if (text.length < minChars) {
5078
+ setOptions([]);
5079
+ setShowDropdown(false);
5080
+ setHighlightedIndex(-1);
5081
+ return;
5082
+ }
5083
+ const controller = new AbortController();
5084
+ abortRef.current = controller;
5085
+ lastQueryRef.current = text;
5086
+ setIsLoading(true);
5087
+ try {
5088
+ const results = await onSearch(text, controller.signal);
5089
+ if (controller.signal.aborted)
5090
+ return; // superseded → drop
5091
+ setOptions(results);
5092
+ setShowDropdown(results.length > 0); // empty → close silently (dark cockpit)
5093
+ setHighlightedIndex(-1);
5094
+ }
5095
+ catch (error) {
5096
+ if (controller.signal.aborted)
5097
+ return; // aborts reject with AbortError → ignore
5098
+ console.error("CwSearchAsync onSearch failed:", error);
5099
+ setOptions([]);
5100
+ setShowDropdown(false);
5101
+ }
5102
+ finally {
5103
+ if (abortRef.current === controller) {
5104
+ setIsLoading(false);
5105
+ abortRef.current = null;
5106
+ }
5107
+ }
5108
+ }, [minChars, onSearch]);
5109
+ // Keep a stable handle to the latest runSearch for the searchTrigger effect.
5110
+ const runSearchRef = useRef(runSearch);
5111
+ useEffect(() => { runSearchRef.current = runSearch; });
5112
+ const debouncedSearch = useCallback((text) => {
5113
+ if (debounceRef.current)
5114
+ window.clearTimeout(debounceRef.current);
5115
+ // Abort eagerly on every keystroke so a fast typist never has two live fetches.
5116
+ abortRef.current?.abort();
5117
+ debounceRef.current = window.setTimeout(() => runSearch(text), debounceMs);
5118
+ }, [runSearch, debounceMs]);
5119
+ const handleInputChange = (e) => {
5120
+ const newValue = e.target.value;
5121
+ setInputValue(newValue);
5122
+ if (newValue !== inputValue) {
5123
+ cancelInitialResolve();
5124
+ debouncedSearch(newValue);
5125
+ }
5126
+ };
5127
+ const handleOptionSelect = async (optionId) => {
5128
+ const picked = options.find(o => o.id === optionId);
5129
+ if (!picked)
5130
+ return;
5131
+ setShowDropdown(false);
5132
+ let committed = picked;
5133
+ if (onResolveSelection) {
5134
+ abortRef.current?.abort();
5135
+ const controller = new AbortController();
5136
+ abortRef.current = controller;
5137
+ try {
5138
+ const resolved = await onResolveSelection(picked, controller.signal);
5139
+ if (controller.signal.aborted)
5140
+ return;
5141
+ committed = resolved;
5142
+ setOptions([resolved]);
5143
+ }
5144
+ catch (error) {
5145
+ if (controller.signal.aborted)
5146
+ return;
5147
+ console.error("CwSearchAsync onResolveSelection failed:", error);
5148
+ return; // abort the commit, mirroring the legacy provider-airport behaviour
5149
+ }
5150
+ finally {
5151
+ if (abortRef.current === controller)
5152
+ abortRef.current = null;
5153
+ }
5154
+ }
5155
+ setInputValue(committed.inputLabel ?? committed.label);
5156
+ setTooltipText(committed.label);
5157
+ onChange(committed.id);
5158
+ };
5159
+ const handleKeyDown = (e) => {
5160
+ if (!showDropdown || options.length === 0)
5161
+ return;
5162
+ switch (e.key) {
5163
+ case "ArrowDown":
5164
+ e.preventDefault();
5165
+ setHighlightedIndex(prev => (prev < options.length - 1 ? prev + 1 : 0));
5166
+ break;
5167
+ case "ArrowUp":
5168
+ e.preventDefault();
5169
+ setHighlightedIndex(prev => (prev > 0 ? prev - 1 : options.length - 1));
5170
+ break;
5171
+ case "Enter":
5172
+ e.preventDefault();
5173
+ if (highlightedIndex >= 0 && highlightedIndex < options.length) {
5174
+ handleOptionSelect(options[highlightedIndex].id);
5175
+ }
5176
+ break;
5177
+ case "Escape":
5178
+ setShowDropdown(false);
5179
+ setHighlightedIndex(-1);
5180
+ break;
5181
+ }
5182
+ };
5183
+ const handleInputFocus = () => {
5184
+ if (options.length > 0)
5185
+ setShowDropdown(true);
5186
+ };
5187
+ const handleClear = () => {
5188
+ if (debounceRef.current)
5189
+ window.clearTimeout(debounceRef.current);
5190
+ abortRef.current?.abort();
5191
+ cancelInitialResolve();
5192
+ setInputValue("");
5193
+ setTooltipText("");
5194
+ setOptions([]);
5195
+ setShowDropdown(false);
5196
+ lastQueryRef.current = "";
5197
+ onChange(null);
5198
+ inputRef.current?.focus();
5199
+ };
5200
+ // Resolve a preselected value to display text.
5201
+ useEffect(() => {
5202
+ if (value == null)
5203
+ return;
5204
+ if (initialDisplayText) {
5205
+ setInputValue(initialDisplayText);
5206
+ setTooltipText(initialDisplayText);
5207
+ lastResolvedValueRef.current = value;
5208
+ return;
5209
+ }
5210
+ if (!onResolveInitial)
5211
+ return;
5212
+ if (lastResolvedValueRef.current === value)
5213
+ return; // already resolved this value
5214
+ const controller = new AbortController();
5215
+ initialResolveAbortRef.current = controller;
5216
+ setIsInitialLoading(true);
5217
+ onResolveInitial(value, controller.signal)
5218
+ .then(opt => {
5219
+ if (controller.signal.aborted)
5220
+ return;
5221
+ lastResolvedValueRef.current = value; // mark resolved only on success
5222
+ setOptions([opt]);
5223
+ setInputValue(opt.inputLabel ?? opt.label);
5224
+ setTooltipText(opt.label);
5225
+ })
5226
+ .catch(error => {
5227
+ if (!controller.signal.aborted)
5228
+ console.error("CwSearchAsync onResolveInitial failed:", error);
5229
+ })
5230
+ .finally(() => {
5231
+ // Clear the spinner only if this resolve is still the current one (not superseded/cancelled).
5232
+ if (initialResolveAbortRef.current === controller) {
5233
+ setIsInitialLoading(false);
5234
+ initialResolveAbortRef.current = null;
5235
+ }
5236
+ });
5237
+ return () => controller.abort();
5238
+ }, [value, initialDisplayText, onResolveInitial]);
5239
+ // Reset when the controlled value is cleared by the parent.
5240
+ useEffect(() => {
5241
+ if (value == null) {
5242
+ if (debounceRef.current)
5243
+ window.clearTimeout(debounceRef.current);
5244
+ abortRef.current?.abort();
5245
+ cancelInitialResolve();
5246
+ setInputValue("");
5247
+ setTooltipText("");
5248
+ setOptions([]);
5249
+ setShowDropdown(false);
5250
+ setHighlightedIndex(-1);
5251
+ lastQueryRef.current = "";
5252
+ lastResolvedValueRef.current = undefined;
5253
+ }
5254
+ }, [value, cancelInitialResolve]);
5255
+ // Re-run the last query when searchTrigger changes (skip first mount).
5256
+ useEffect(() => {
5257
+ if (!didMountRef.current) {
5258
+ didMountRef.current = true;
5259
+ return;
5260
+ }
5261
+ if (searchTrigger === undefined)
5262
+ return;
5263
+ if (lastQueryRef.current)
5264
+ runSearchRef.current(lastQueryRef.current);
5265
+ }, [searchTrigger]);
5266
+ // Cleanup on unmount.
5267
+ useEffect(() => () => {
5268
+ if (debounceRef.current)
5269
+ window.clearTimeout(debounceRef.current);
5270
+ abortRef.current?.abort();
5271
+ }, []);
5272
+ const direction = alignProps?.flexDirection || "row";
5273
+ return (jsxs("div", { className: `cw-search-input ${className}`, style: {
5274
+ ...(width ? { width } : {}),
5275
+ ...(labelProps?.labelWidth ? { "--label-width": labelProps.labelWidth } : {}),
5276
+ }, "data-direction": direction, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-search-input-wrapper", ref: wrapperRef, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleInputFocus, placeholder: isInitialLoading ? "Loading…" : placeholder, disabled: disabled, required: required, autoComplete: "off", role: "combobox", "aria-haspopup": "listbox", "aria-expanded": showDropdown, "aria-controls": listboxId, "aria-activedescendant": highlightedIndex >= 0 ? optionId(highlightedIndex) : undefined, title: tooltipText }), (isLoading || isInitialLoading) && (jsx("div", { className: "cw-search-input-loading", children: jsx(CwIcon, { iconId: "spinner" }) })), jsx("div", { className: "cw-search-input-icons", children: inputValue && !disabled && !isInitialLoading ? (jsx(CwButton, { type: "button", onClick: handleClear, "aria-label": "Clear selection", variant: "icon", icon: "close", color: "neutral" })) : (icon ? jsx(CwIcon, { ...icon }) : jsx(CwIcon, { iconId: "search" })) })] })] }), renderPanel(jsx("div", { ref: panelRef, id: listboxId, className: dropdownStyles.dropdown, style: panelStyle, role: "listbox", children: jsx("ul", { children: options.map((option, index) => (jsx("li", { id: optionId(index), className: `${dropdownStyles.option}${index === highlightedIndex ? ` ${dropdownStyles.optionFocused}` : ""}`, onClick: () => handleOptionSelect(option.id), onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => setHighlightedIndex(index), role: "option", "aria-selected": index === highlightedIndex, children: option.subLabel ? (jsxs("span", { className: "cw-search-async-option-lines", children: [jsx("span", { children: option.label }), jsx("span", { className: "cw-search-async-option-sub", children: option.subLabel })] })) : (option.label) }, option.id))) }) }))] }));
5277
+ };
5278
+
5020
5279
  var styles$5 = {"menu":"cw-context-menu-module__menu__tXmun","item":"cw-context-menu-module__item__-ko8L","arrow":"cw-context-menu-module__arrow__LHZmQ"};
5021
5280
 
5022
5281
  const ARROW_SIZE = 8;
@@ -6983,7 +7242,7 @@ function formatPlainDate(pd, fmt) {
6983
7242
  .replace("dd", String(pd.day).padStart(2, "0"));
6984
7243
  }
6985
7244
 
6986
- function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates, disabledMatcher, defaultMonth, labelProps, alignProps, placeholder = "Select a date", displayFormat = "dd.MM.yyyy", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showTodayButton = false, todayLabel = "Today", feedback, }) {
7245
+ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates, disabledMatcher, defaultMonth, labelProps, alignProps, placeholder = "Select a date", displayFormat = "dd.MM.yyyy", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showTodayButton = false, locale = enGB, todayLabel = "Today", yearRangeStart, yearRangeEnd, feedback, }) {
6987
7246
  const [isOpen, setIsOpen] = useState(false);
6988
7247
  const [inputValue, setInputValue] = useState();
6989
7248
  const containerRef = useRef(null);
@@ -7072,6 +7331,19 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
7072
7331
  setIsOpen(false);
7073
7332
  }
7074
7333
  }, [minDate, maxDate, onChange]);
7334
+ // Derive start/end months for the year dropdown range, guarding against inverted yearRange props
7335
+ const dropdownStartMonth = useMemo(() => {
7336
+ const inferredStart = minDate ? minDate.year : Temporal.Now.plainDateISO().year - 10;
7337
+ const inferredEnd = yearRangeEnd ?? (maxDate ? maxDate.year : Temporal.Now.plainDateISO().year + 5);
7338
+ const year = Math.min(yearRangeStart ?? inferredStart, inferredEnd);
7339
+ return new Date(year, 0, 1);
7340
+ }, [yearRangeStart, yearRangeEnd, minDate, maxDate]);
7341
+ const dropdownEndMonth = useMemo(() => {
7342
+ const inferredEnd = maxDate ? maxDate.year : Temporal.Now.plainDateISO().year + 5;
7343
+ const inferredStart = yearRangeStart ?? (minDate ? minDate.year : Temporal.Now.plainDateISO().year - 10);
7344
+ const year = Math.max(yearRangeEnd ?? inferredEnd, inferredStart);
7345
+ return new Date(year, 11, 31);
7346
+ }, [yearRangeStart, yearRangeEnd, minDate, maxDate]);
7075
7347
  // Memoize disabled days (convert PlainDate[] to Date[] for DayPicker)
7076
7348
  const disabledDays = useMemo(() => [
7077
7349
  ...(disabledDates?.map(plainDateToJsDate) || []),
@@ -7083,13 +7355,463 @@ function CwDatePickerTemporal({ value, onChange, minDate, maxDate, disabledDates
7083
7355
  const defaultMonthJsDate = defaultMonth
7084
7356
  ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
7085
7357
  : selectedJsDate;
7086
- 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, modifiers: {
7358
+ 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: {
7087
7359
  today: new Date(),
7088
7360
  }, modifiersClassNames: {
7089
7361
  today: "rdp-day-today",
7090
7362
  } }), 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)))] }));
7091
7363
  }
7092
7364
 
7365
+ // dateRangePresetsTemporal.ts
7366
+ // Temporal-typed counterpart of dateRangePresets.ts (used by CwDateRangePickerTemporal).
7367
+ // Each preset is evaluated at click time; a reference date can be injected for testing.
7368
+ const ref = (today) => today ?? Temporal.Now.plainDateISO();
7369
+ /** Monday as first day of the week (ISO dayOfWeek: 1 = Mon … 7 = Sun). */
7370
+ const startOfWeek = (d) => d.subtract({ days: d.dayOfWeek - 1 });
7371
+ const startOfMonth = (d) => d.with({ day: 1 });
7372
+ const endOfMonth = (d) => d.with({ day: d.daysInMonth });
7373
+ /** First day of the quarter that contains `d`. */
7374
+ const startOfQuarter = (d) => Temporal.PlainDate.from({ year: d.year, month: Math.floor((d.month - 1) / 3) * 3 + 1, day: 1 });
7375
+ const PRESET_LIBRARY_TEMPORAL = {
7376
+ // === PAST DAYS ===
7377
+ today: {
7378
+ key: "today",
7379
+ label: "Today",
7380
+ getValue: (t) => { const d = ref(t); return { from: d, to: d }; },
7381
+ },
7382
+ yesterday: {
7383
+ key: "yesterday",
7384
+ label: "Yesterday",
7385
+ getValue: (t) => { const d = ref(t).subtract({ days: 1 }); return { from: d, to: d }; },
7386
+ },
7387
+ past2Days: {
7388
+ key: "past2Days",
7389
+ label: "Past 2 Days",
7390
+ getValue: (t) => { const d = ref(t); return { from: d.subtract({ days: 2 }), to: d }; },
7391
+ },
7392
+ past3Days: {
7393
+ key: "past3Days",
7394
+ label: "Past 3 Days",
7395
+ getValue: (t) => { const d = ref(t); return { from: d.subtract({ days: 3 }), to: d }; },
7396
+ },
7397
+ past7Days: {
7398
+ key: "past7Days",
7399
+ label: "Past 7 days",
7400
+ getValue: (t) => { const d = ref(t); return { from: d.subtract({ days: 7 }), to: d }; },
7401
+ },
7402
+ past14Days: {
7403
+ key: "past14Days",
7404
+ label: "Past 14 days",
7405
+ getValue: (t) => { const d = ref(t); return { from: d.subtract({ days: 14 }), to: d }; },
7406
+ },
7407
+ past30Days: {
7408
+ key: "past30Days",
7409
+ label: "Past 30 days",
7410
+ getValue: (t) => { const d = ref(t); return { from: d.subtract({ days: 30 }), to: d }; },
7411
+ },
7412
+ past90Days: {
7413
+ key: "past90Days",
7414
+ label: "Past 90 days",
7415
+ getValue: (t) => { const d = ref(t); return { from: d.subtract({ days: 90 }), to: d }; },
7416
+ },
7417
+ // === NEXT DAYS ===
7418
+ next7Days: {
7419
+ key: "next7Days",
7420
+ label: "Next 7 days",
7421
+ getValue: (t) => { const d = ref(t); return { from: d, to: d.add({ days: 7 }) }; },
7422
+ },
7423
+ next14Days: {
7424
+ key: "next14Days",
7425
+ label: "Next 14 days",
7426
+ getValue: (t) => { const d = ref(t); return { from: d, to: d.add({ days: 14 }) }; },
7427
+ },
7428
+ next30Days: {
7429
+ key: "next30Days",
7430
+ label: "Next 30 days",
7431
+ getValue: (t) => { const d = ref(t); return { from: d, to: d.add({ days: 30 }) }; },
7432
+ },
7433
+ // === WEEKS (Monday-first) ===
7434
+ thisWeek: {
7435
+ key: "thisWeek",
7436
+ label: "This week",
7437
+ getValue: (t) => { const s = startOfWeek(ref(t)); return { from: s, to: s.add({ days: 6 }) }; },
7438
+ },
7439
+ lastWeek: {
7440
+ key: "lastWeek",
7441
+ label: "Last week",
7442
+ getValue: (t) => { const end = startOfWeek(ref(t)).subtract({ days: 1 }); return { from: end.subtract({ days: 6 }), to: end }; },
7443
+ },
7444
+ nextWeek: {
7445
+ key: "nextWeek",
7446
+ label: "Next week",
7447
+ getValue: (t) => { const s = startOfWeek(ref(t)).add({ days: 7 }); return { from: s, to: s.add({ days: 6 }) }; },
7448
+ },
7449
+ // === MONTHS ===
7450
+ thisMonth: {
7451
+ key: "thisMonth",
7452
+ label: "This month",
7453
+ getValue: (t) => { const d = ref(t); return { from: startOfMonth(d), to: endOfMonth(d) }; },
7454
+ },
7455
+ lastMonth: {
7456
+ key: "lastMonth",
7457
+ label: "Last month",
7458
+ getValue: (t) => { const d = startOfMonth(ref(t)).subtract({ months: 1 }); return { from: d, to: endOfMonth(d) }; },
7459
+ },
7460
+ nextMonth: {
7461
+ key: "nextMonth",
7462
+ label: "Next month",
7463
+ getValue: (t) => { const d = startOfMonth(ref(t)).add({ months: 1 }); return { from: d, to: endOfMonth(d) }; },
7464
+ },
7465
+ // === QUARTERS ===
7466
+ thisQuarter: {
7467
+ key: "thisQuarter",
7468
+ label: "This quarter",
7469
+ getValue: (t) => { const from = startOfQuarter(ref(t)); return { from, to: from.add({ months: 3 }).subtract({ days: 1 }) }; },
7470
+ },
7471
+ lastQuarter: {
7472
+ key: "lastQuarter",
7473
+ label: "Last quarter",
7474
+ getValue: (t) => { const from = startOfQuarter(ref(t)).subtract({ months: 3 }); return { from, to: from.add({ months: 3 }).subtract({ days: 1 }) }; },
7475
+ },
7476
+ nextQuarter: {
7477
+ key: "nextQuarter",
7478
+ label: "Next quarter",
7479
+ getValue: (t) => { const from = startOfQuarter(ref(t)).add({ months: 3 }); return { from, to: from.add({ months: 3 }).subtract({ days: 1 }) }; },
7480
+ },
7481
+ // === YEAR ===
7482
+ thisYear: {
7483
+ key: "thisYear",
7484
+ label: "This year",
7485
+ getValue: (t) => {
7486
+ const y = ref(t).year;
7487
+ return { from: Temporal.PlainDate.from({ year: y, month: 1, day: 1 }), to: Temporal.PlainDate.from({ year: y, month: 12, day: 31 }) };
7488
+ },
7489
+ },
7490
+ lastYear: {
7491
+ key: "lastYear",
7492
+ label: "Last year",
7493
+ getValue: (t) => {
7494
+ const y = ref(t).year - 1;
7495
+ return { from: Temporal.PlainDate.from({ year: y, month: 1, day: 1 }), to: Temporal.PlainDate.from({ year: y, month: 12, day: 31 }) };
7496
+ },
7497
+ },
7498
+ };
7499
+ /**
7500
+ * Helper to get presets by their keys.
7501
+ * @example getPresetsByKeysTemporal(['thisWeek', 'past7Days', 'past30Days'])
7502
+ */
7503
+ const getPresetsByKeysTemporal = (keys) => keys.map((key) => PRESET_LIBRARY_TEMPORAL[key]).filter((preset) => preset !== undefined);
7504
+
7505
+ function CwDateRangePickerTemporal({ value, onChange, minDate, maxDate, disabledDates, disabledMatcher, maxRangeDays, defaultMonth, labelProps, alignProps, placeholderFrom = "From date", placeholderTo = "To date", displayFormat = "dd.MM.yyyy", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 2, locale = enGB, yearRangeStart, yearRangeEnd, showPresets = false, presetKeys, customPresets, }) {
7506
+ const [isOpen, setIsOpen] = useState(false);
7507
+ const [inputFromValue, setInputFromValue] = useState("");
7508
+ const [inputToValue, setInputToValue] = useState("");
7509
+ const [rangeErrorMessage, setRangeErrorMessage] = useState(null);
7510
+ const [focusedInput, setFocusedInput] = useState();
7511
+ const containerRef = useRef(null);
7512
+ const wrapperRef = useRef(null);
7513
+ const inputFromRef = useRef(null);
7514
+ const inputToRef = useRef(null);
7515
+ const prevValueRef = useRef(undefined);
7516
+ const prevDisplayFormatRef = useRef(displayFormat);
7517
+ const rangeError = useCallback(() => (maxRangeDays ? `Range cannot exceed ${maxRangeDays} days` : "Invalid date range"), [maxRangeDays]);
7518
+ const handleClose = useCallback(() => {
7519
+ setIsOpen(false);
7520
+ setFocusedInput(undefined);
7521
+ }, []);
7522
+ const { popupRef, popupStyle, renderPopup } = usePickerPopup({
7523
+ anchorRef: wrapperRef,
7524
+ isOpen,
7525
+ onClose: handleClose,
7526
+ position: popupPosition,
7527
+ });
7528
+ // Calculate presets to render
7529
+ const presetsToRender = useMemo(() => {
7530
+ let presets = [];
7531
+ if (presetKeys && presetKeys.length > 0) {
7532
+ presets = getPresetsByKeysTemporal(presetKeys);
7533
+ }
7534
+ if (customPresets && customPresets.length > 0) {
7535
+ presets = [...presets, ...customPresets];
7536
+ }
7537
+ return presets;
7538
+ }, [presetKeys, customPresets]);
7539
+ // Validate date range
7540
+ const validateRange = useCallback((from, to) => {
7541
+ if (!from || !to)
7542
+ return true; // Partial ranges are OK during selection
7543
+ if (Temporal.PlainDate.compare(from, to) > 0)
7544
+ return false;
7545
+ if (maxRangeDays) {
7546
+ const daysDiff = from.until(to, { largestUnit: "day" }).days;
7547
+ if (daysDiff > maxRangeDays)
7548
+ return false;
7549
+ }
7550
+ return true;
7551
+ }, [maxRangeDays]);
7552
+ // Sync input values with prop value
7553
+ useEffect(() => {
7554
+ const currentFrom = value?.from?.toString();
7555
+ const currentTo = value?.to?.toString();
7556
+ const prevFrom = prevValueRef.current?.from;
7557
+ const prevTo = prevValueRef.current?.to;
7558
+ if (currentFrom !== prevFrom ||
7559
+ currentTo !== prevTo ||
7560
+ prevDisplayFormatRef.current !== displayFormat) {
7561
+ prevValueRef.current = { from: currentFrom, to: currentTo };
7562
+ prevDisplayFormatRef.current = displayFormat;
7563
+ setInputFromValue(value?.from ? formatPlainDate(value.from, displayFormat) : "");
7564
+ setInputToValue(value?.to ? formatPlainDate(value.to, displayFormat) : "");
7565
+ }
7566
+ }, [value, displayFormat]);
7567
+ const handleRangeSelect = useCallback((range, selectedDay) => {
7568
+ const selected = jsDateToPlainDate(selectedDay);
7569
+ let newRange;
7570
+ if (focusedInput === 'from') {
7571
+ newRange = { from: selected, to: value?.to };
7572
+ if (newRange.to && Temporal.PlainDate.compare(selected, newRange.to) > 0) {
7573
+ newRange.to = undefined;
7574
+ setFocusedInput('to');
7575
+ setRangeErrorMessage(null);
7576
+ }
7577
+ else if (newRange.to) {
7578
+ if (!validateRange(newRange.from, newRange.to)) {
7579
+ setRangeErrorMessage(rangeError());
7580
+ return;
7581
+ }
7582
+ setRangeErrorMessage(null);
7583
+ setIsOpen(false);
7584
+ setFocusedInput(undefined);
7585
+ }
7586
+ else {
7587
+ setFocusedInput('to');
7588
+ setRangeErrorMessage(null);
7589
+ }
7590
+ }
7591
+ else if (focusedInput === 'to') {
7592
+ newRange = { from: value?.from, to: selected };
7593
+ if (newRange.from && Temporal.PlainDate.compare(selected, newRange.from) < 0) {
7594
+ newRange.from = undefined;
7595
+ setFocusedInput('from');
7596
+ setRangeErrorMessage(null);
7597
+ }
7598
+ else if (newRange.from) {
7599
+ if (!validateRange(newRange.from, newRange.to)) {
7600
+ setRangeErrorMessage(rangeError());
7601
+ return;
7602
+ }
7603
+ setRangeErrorMessage(null);
7604
+ setIsOpen(false);
7605
+ setFocusedInput(undefined);
7606
+ }
7607
+ else {
7608
+ setFocusedInput('from');
7609
+ setRangeErrorMessage(null);
7610
+ }
7611
+ }
7612
+ else {
7613
+ if (!range) {
7614
+ onChange(undefined);
7615
+ return;
7616
+ }
7617
+ newRange = {
7618
+ from: range.from ? jsDateToPlainDate(range.from) : undefined,
7619
+ to: range.to ? jsDateToPlainDate(range.to) : undefined,
7620
+ };
7621
+ if (range.from && range.to) {
7622
+ if (!validateRange(newRange.from, newRange.to)) {
7623
+ setRangeErrorMessage(rangeError());
7624
+ return;
7625
+ }
7626
+ setRangeErrorMessage(null);
7627
+ setIsOpen(false);
7628
+ setFocusedInput(undefined);
7629
+ }
7630
+ else if (range.from) {
7631
+ setFocusedInput('to');
7632
+ setRangeErrorMessage(null);
7633
+ }
7634
+ else {
7635
+ setFocusedInput('from');
7636
+ setRangeErrorMessage(null);
7637
+ }
7638
+ }
7639
+ onChange(newRange);
7640
+ }, [onChange, validateRange, value, focusedInput, rangeError]);
7641
+ const handleClearFrom = useCallback((e) => {
7642
+ e.stopPropagation();
7643
+ onChange({ from: undefined, to: value?.to });
7644
+ setInputFromValue("");
7645
+ }, [onChange, value]);
7646
+ const handleClearTo = useCallback((e) => {
7647
+ e.stopPropagation();
7648
+ onChange({ from: value?.from, to: undefined });
7649
+ setInputToValue("");
7650
+ }, [onChange, value]);
7651
+ const handleInputFromClick = useCallback(() => {
7652
+ if (!disabled) {
7653
+ setIsOpen(true);
7654
+ setFocusedInput('from');
7655
+ }
7656
+ }, [disabled]);
7657
+ const handleInputToClick = useCallback(() => {
7658
+ if (!disabled) {
7659
+ setIsOpen(true);
7660
+ setFocusedInput('to');
7661
+ }
7662
+ }, [disabled]);
7663
+ const handleInputFromChange = useCallback((e) => {
7664
+ const newValue = e.currentTarget.value;
7665
+ setInputFromValue(newValue);
7666
+ const parsed = parseDate(newValue, displayFormat);
7667
+ if (parsed) {
7668
+ if (validate(parsed, minDate, maxDate) && validateRange(parsed, value?.to)) {
7669
+ onChange({ from: parsed, to: value?.to });
7670
+ }
7671
+ }
7672
+ else if (newValue === "") {
7673
+ onChange({ from: undefined, to: value?.to });
7674
+ }
7675
+ }, [displayFormat, minDate, maxDate, validateRange, onChange, value]);
7676
+ const handleInputToChange = useCallback((e) => {
7677
+ const newValue = e.currentTarget.value;
7678
+ setInputToValue(newValue);
7679
+ const parsed = parseDate(newValue, displayFormat);
7680
+ if (parsed) {
7681
+ if (validate(parsed, minDate, maxDate) && validateRange(value?.from, parsed)) {
7682
+ onChange({ from: value?.from, to: parsed });
7683
+ }
7684
+ }
7685
+ else if (newValue === "") {
7686
+ onChange({ from: value?.from, to: undefined });
7687
+ }
7688
+ }, [displayFormat, minDate, maxDate, validateRange, onChange, value]);
7689
+ const handleInputBlur = useCallback((type) => {
7690
+ const inputValue = type === 'from' ? inputFromValue : inputToValue;
7691
+ const currentValue = type === 'from' ? value?.from : value?.to;
7692
+ const trimmed = inputValue?.trim();
7693
+ if (trimmed) {
7694
+ const parsed = parseDate(trimmed, displayFormat);
7695
+ if (parsed && validate(parsed, minDate, maxDate)) {
7696
+ const newRange = type === 'from'
7697
+ ? { from: parsed, to: value?.to }
7698
+ : { from: value?.from, to: parsed };
7699
+ if (validateRange(newRange.from, newRange.to)) {
7700
+ onChange(newRange);
7701
+ if (type === 'from') {
7702
+ setInputFromValue(formatPlainDate(parsed, displayFormat));
7703
+ }
7704
+ else {
7705
+ setInputToValue(formatPlainDate(parsed, displayFormat));
7706
+ }
7707
+ return;
7708
+ }
7709
+ }
7710
+ }
7711
+ // Reset to current value if invalid
7712
+ if (type === 'from') {
7713
+ setInputFromValue(currentValue ? formatPlainDate(currentValue, displayFormat) : "");
7714
+ }
7715
+ else {
7716
+ setInputToValue(currentValue ? formatPlainDate(currentValue, displayFormat) : "");
7717
+ }
7718
+ }, [inputFromValue, inputToValue, value, displayFormat, minDate, maxDate, validateRange, onChange]);
7719
+ const handleInputKeyDown = useCallback((e, type) => {
7720
+ if (e.key === "Enter") {
7721
+ e.preventDefault();
7722
+ if (type === 'from') {
7723
+ inputFromRef.current?.blur();
7724
+ inputToRef.current?.focus();
7725
+ }
7726
+ else {
7727
+ inputToRef.current?.blur();
7728
+ setIsOpen(false);
7729
+ }
7730
+ }
7731
+ else if (e.key === "Escape") {
7732
+ setIsOpen(false);
7733
+ if (type === 'from') {
7734
+ inputFromRef.current?.blur();
7735
+ }
7736
+ else {
7737
+ inputToRef.current?.blur();
7738
+ }
7739
+ }
7740
+ }, []);
7741
+ // Handle preset click
7742
+ const handlePresetClick = useCallback((preset, e) => {
7743
+ e.preventDefault();
7744
+ e.stopPropagation();
7745
+ const nextRange = preset.getValue();
7746
+ if (!validate(nextRange.from, minDate, maxDate) ||
7747
+ !validate(nextRange.to, minDate, maxDate) ||
7748
+ !validateRange(nextRange.from, nextRange.to)) {
7749
+ setRangeErrorMessage(rangeError());
7750
+ return;
7751
+ }
7752
+ setRangeErrorMessage(null);
7753
+ onChange(nextRange);
7754
+ setIsOpen(false);
7755
+ }, [maxDate, minDate, onChange, rangeError, validateRange]);
7756
+ // Derive start/end months for the year dropdown range, guarding against inverted yearRange props
7757
+ const dropdownStartMonth = useMemo(() => {
7758
+ const inferredStart = minDate ? minDate.year : Temporal.Now.plainDateISO().year - 10;
7759
+ const inferredEnd = yearRangeEnd ?? (maxDate ? maxDate.year : Temporal.Now.plainDateISO().year + 5);
7760
+ const year = Math.min(yearRangeStart ?? inferredStart, inferredEnd);
7761
+ return new Date(year, 0, 1);
7762
+ }, [yearRangeStart, yearRangeEnd, minDate, maxDate]);
7763
+ const dropdownEndMonth = useMemo(() => {
7764
+ const inferredEnd = maxDate ? maxDate.year : Temporal.Now.plainDateISO().year + 5;
7765
+ const inferredStart = yearRangeStart ?? (minDate ? minDate.year : Temporal.Now.plainDateISO().year - 10);
7766
+ const year = Math.max(yearRangeEnd ?? inferredEnd, inferredStart);
7767
+ return new Date(year, 11, 31);
7768
+ }, [yearRangeStart, yearRangeEnd, minDate, maxDate]);
7769
+ // Memoize disabled days (convert Temporal → Date for DayPicker)
7770
+ const disabledDays = useMemo(() => {
7771
+ const baseDisabled = [
7772
+ ...(disabledDates?.map(plainDateToJsDate) || []),
7773
+ ...(minDate ? [{ before: plainDateToJsDate(minDate) }] : []),
7774
+ ...(maxDate ? [{ after: plainDateToJsDate(maxDate) }] : []),
7775
+ ...(disabledMatcher ? [disabledMatcher] : []),
7776
+ ];
7777
+ // If maxRangeDays is set and we have a "from" date, disable dates beyond the range
7778
+ if (maxRangeDays) {
7779
+ if (value?.from) {
7780
+ const maxAllowedDate = value.from.add({ days: maxRangeDays });
7781
+ if (focusedInput !== 'from') {
7782
+ baseDisabled.push({ after: plainDateToJsDate(maxAllowedDate) });
7783
+ }
7784
+ if (focusedInput === 'to' && !value?.to) {
7785
+ const minAllowedDate = value.from.subtract({ days: maxRangeDays });
7786
+ baseDisabled.push({ before: plainDateToJsDate(minAllowedDate) });
7787
+ }
7788
+ }
7789
+ if (value?.to && !value?.from && focusedInput === 'from') {
7790
+ const minAllowedDate = value.to.subtract({ days: maxRangeDays });
7791
+ baseDisabled.push({ before: plainDateToJsDate(minAllowedDate) });
7792
+ }
7793
+ }
7794
+ return baseDisabled;
7795
+ }, [disabledDates, minDate, maxDate, disabledMatcher, maxRangeDays, value, focusedInput]);
7796
+ const selectedRange = useMemo(() => {
7797
+ if (value?.from || value?.to) {
7798
+ return {
7799
+ from: value?.from ? plainDateToJsDate(value.from) : undefined,
7800
+ to: value?.to ? plainDateToJsDate(value.to) : undefined,
7801
+ };
7802
+ }
7803
+ return undefined;
7804
+ }, [value]);
7805
+ const defaultMonthJsDate = defaultMonth
7806
+ ? new Date(defaultMonth.year, defaultMonth.month - 1, 1)
7807
+ : (value?.from ? plainDateToJsDate(value.from) : undefined);
7808
+ 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: {
7809
+ today: new Date(),
7810
+ }, modifiersClassNames: {
7811
+ today: "rdp-day-today",
7812
+ } })] }), jsx("div", { role: "alert", "aria-live": "polite", className: rangeStyles.rangeError, children: rangeErrorMessage })] }))] })] }) }));
7813
+ }
7814
+
7093
7815
  const ResourcesTitleList = ({ resources, canBePinned, includesPinned, onCrewPinning, onClickResourceContextMenu, ResourceTitleComponent, }) => {
7094
7816
  const onClickContextMenu = useCallback((key, resource) => {
7095
7817
  if (onClickResourceContextMenu) {
@@ -9582,13 +10304,13 @@ const PinRowHeader = ({ value, width, onEvent }) => {
9582
10304
  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);
9583
10305
  };
9584
10306
 
9585
- const SuperScheduler = ({ id, state, header, rows, events, headerColumnComp, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, indicatorRows = [], contextMenuItems, onEvent, rowHeightRem = 1.75, rowHeaderWidth, maxEventHeightRem, }) => {
10307
+ const SuperScheduler = ({ id, state, header, rows, events, headerColumnComp, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, indicatorRows = [], contextMenuItems, onEvent, rowHeightRem = 1.75, rowHeaderWidth, maxEventHeightRem, EventComp = SchedulerEvent, }) => {
9586
10308
  const pinnedRows = rows.filter((it) => it.isPinned);
9587
10309
  const notPinnedRows = rows.filter((it) => !it.isPinned);
9588
10310
  const isFirstVisible = pinnedRows.length > 0;
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: () => {
10311
+ 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: EventComp, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem, rowHeaderWidth: rowHeaderWidth, maxEventHeightRem: maxEventHeightRem }), jsx("div", { children: jsx(CwButton, { onClick: () => {
9590
10312
  onEvent(new OnClearPinned());
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 })] }));
10313
+ }, 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: EventComp, RowTitleComp: headerColumnComp, rowHeightRem: rowHeightRem, rowHeaderWidth: rowHeaderWidth, maxEventHeightRem: maxEventHeightRem })] }));
9592
10314
  };
9593
10315
 
9594
10316
  /**
@@ -10025,4 +10747,4 @@ const CwFindCrewmember = ({ handleChange, placeHolder = "Search crew…", requir
10025
10747
  }, "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))) }) }))] }));
10026
10748
  };
10027
10749
 
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 };
10750
+ export { CblDragAndDrop, CwAccordionContainer, CwAlign, CwAnchoredMenu, CwBtnApprove, CwBtnCancel, CwBtnDelete, CwBtnEdit, CwBtnSave, CwButton, CwCard, CwCardList, CwCheck, CwCheckbox, CwCheckboxGroup, CwChip, CwColorPicker, CwConfirmationPopup, CwContextMenu, CwDatePicker, CwDatePickerTemporal, CwDateRangePicker, CwDateRangePickerTemporal, CwDateTimePicker, CwDateTimePickerCompact, CwDialog, CwDigit, CwDisplayMessage, CwDropdown, CwDropdownFilter, CwExpandable, CwFileUpload, CwFileUploadMultiple, CwFindAirport, CwFindCrewmember, CwGenericTooltip, CwHeadingMain, CwHeadingSecond, CwIcon, CwImageArea, CwImageGallery, CwImageZoom, CwInput, CwInputColor, CwInputDateText, CwInputDatetime, CwInputImage, CwInputNumber, CwInputPhone, CwInputText, CwKeyValueList, CwLabel, CwLoading, CwLoadingSmall, CwMasterDetail, CwMessage, CwMessageManager, CwMessageType, CwModal, CwModalHover, CwModalReportFunctional, CwMultiFilter, CwMultiFilterTag, CwNote, CwOption, CwPopoverButton, CwReportModal, CwScheduler, CwSearchAsync, CwSearchInput, CwSelect, CwSelectList, CwSelectListItems, CwSortableList, CwSortableTable, CwSuperScheduler, CwTable, CwTableGrouped, CwTableServerSide, CwTabs, CwTagSelector, CwTextArea, CwTime, CwTimePicker, CwToggle, CwTooltipManager, CwTooltipNew, CwTreeView, CwWeekdaySelector, DefaultRowHeader, OnClearPinned, OnClickContextMenu, OnClickEvent, OnClickRowEvent, OnClickRowHeader, OnClickUtc, OnDoubleClickEvent, OnDoubleClickRowEvent, OnDragEvent, OnDropCtrlEvent, OnDropEvent, OnEndClickHeaderEvent, OnLeftDragStart, OnMultiClickEvent, OnPinRow, OnRangeClickEvent, OnRightClickEvent, OnRightClickRow, OnRightDragStart, OnStartClickHeaderEvent, OnUnpinRow, PRESET_LIBRARY_TEMPORAL, PinRowHeader, Resource, Scheduler, SchedulerEvent, SuperScheduler, TooltipConstraintContext, UiEvent, Weekdays, cblEvent, eventIsVisible, filterVisibleEvents, getDefaultDivisions, getEventSizes, getPresetsByKeysTemporal, itemsToMultiFilterTags, useCwMessage, useSortableList, useSortableTable, useTooltipConstraint };