@cwellt_software/cwellt-reactjs-lib 1.3.2 → 1.3.5
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.cjs.js +336 -169
- package/dist/index.css +2 -2
- package/dist/index.d.ts +61 -7
- package/dist/index.es.js +336 -169
- package/dist/src/common/functions/colorManipulation.d.ts.map +1 -1
- package/dist/src/common/functions/useSingleAndDoubleClicks.d.ts.map +1 -1
- package/dist/src/components/control/choice/multi-filter/CwMultiFilter.d.ts +6 -0
- package/dist/src/components/control/choice/multi-filter/CwMultiFilter.d.ts.map +1 -1
- package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts +16 -0
- package/dist/src/components/control/input/file/CwFileUploadMultiple.d.ts.map +1 -1
- package/dist/src/components/control/input/new-dates/CwDatePicker.d.ts +10 -1
- package/dist/src/components/control/input/new-dates/CwDatePicker.d.ts.map +1 -1
- package/dist/src/components/control/input/new-dates/CwDateTimePicker.d.ts +6 -1
- package/dist/src/components/control/input/new-dates/CwDateTimePicker.d.ts.map +1 -1
- package/dist/src/components/control/input/new-dates/CwDateTimePickerCompact.d.ts +8 -1
- package/dist/src/components/control/input/new-dates/CwDateTimePickerCompact.d.ts.map +1 -1
- package/dist/src/components/custom/scheduler-new/presentation/NewScheduler.d.ts +2 -0
- package/dist/src/components/custom/scheduler-new/presentation/NewScheduler.d.ts.map +1 -1
- package/dist/src/components/custom/scheduler-new/presentation/components/row/IndicatorRow.d.ts +18 -0
- package/dist/src/components/custom/scheduler-new/presentation/components/row/IndicatorRow.d.ts.map +1 -0
- package/dist/src/components/custom/scheduler-new/presentation/components/row/SchedulerRow.d.ts +2 -0
- package/dist/src/components/custom/scheduler-new/presentation/components/row/SchedulerRow.d.ts.map +1 -1
- package/dist/src/components/custom/super-scheduler/SuperScheduler.d.ts +2 -0
- package/dist/src/components/custom/super-scheduler/SuperScheduler.d.ts.map +1 -1
- package/dist/src/components/display/data/table/CwTable.d.ts +2 -1
- package/dist/src/components/display/data/table/CwTable.d.ts.map +1 -1
- package/dist/src/components/display/text/message/CwMessage.d.ts +3 -2
- package/dist/src/components/display/text/message/CwMessage.d.ts.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/main.d.ts +0 -1
- package/dist/src/main.d.ts.map +1 -1
- package/dist/src/playground/PlaygroundApp.d.ts +4 -0
- package/dist/src/playground/PlaygroundApp.d.ts.map +1 -0
- package/dist/src/playground/pages/ColorContrastPage.d.ts +3 -0
- package/dist/src/playground/pages/ColorContrastPage.d.ts.map +1 -0
- package/dist/src/playground/pages/DatePickerLocalePage.d.ts +3 -0
- package/dist/src/playground/pages/DatePickerLocalePage.d.ts.map +1 -0
- package/dist/src/playground/pages/TablePaginationPage.d.ts +3 -0
- package/dist/src/playground/pages/TablePaginationPage.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/index.es.js
CHANGED
|
@@ -105,36 +105,60 @@ function getHSLColor(color, alpha = 1) {
|
|
|
105
105
|
const hsl = colorToHSL(color);
|
|
106
106
|
return `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${alpha})`;
|
|
107
107
|
}
|
|
108
|
+
function hslToLinearRgb(h, s, l) {
|
|
109
|
+
const sNorm = s / 100;
|
|
110
|
+
const lNorm = l / 100;
|
|
111
|
+
const a = sNorm * Math.min(lNorm, 1 - lNorm);
|
|
112
|
+
const f = (n) => {
|
|
113
|
+
const k = (n + h / 30) % 12;
|
|
114
|
+
return lNorm - a * Math.max(-1, Math.min(k - 3, Math.min(9 - k, 1)));
|
|
115
|
+
};
|
|
116
|
+
return [f(0), f(8), f(4)];
|
|
117
|
+
}
|
|
118
|
+
function srgbLuminance(r, g, b) {
|
|
119
|
+
const lin = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
120
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
121
|
+
}
|
|
122
|
+
function wcagContrastRatio(lum1, lum2) {
|
|
123
|
+
const lighter = Math.max(lum1, lum2);
|
|
124
|
+
const darker = Math.min(lum1, lum2);
|
|
125
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
126
|
+
}
|
|
108
127
|
function getContrastColor(color) {
|
|
109
|
-
if (color === null)
|
|
128
|
+
if (color === null)
|
|
110
129
|
return '#000000';
|
|
111
|
-
}
|
|
112
130
|
const hsl = colorToHSL(color);
|
|
113
|
-
// Saturated greenyellow and cyan tones need lower luminance threshold (40-35)
|
|
114
|
-
// Saturated mediumblue and blueviolet tones need higher luminance threshold (55-60)
|
|
115
|
-
// Saturated orangered tones need lower luminance threshold (45)
|
|
116
|
-
const isYellowGreen = (hsl.h >= 45 && hsl.h <= 180);
|
|
117
|
-
const isBlueViolet = (hsl.h >= 210 && hsl.h <= 300);
|
|
118
|
-
const isRedOrange = (hsl.h >= 0 && hsl.h <= 30) || (hsl.h >= 330 && hsl.h <= 360);
|
|
119
|
-
let threshold = 50;
|
|
120
|
-
if (isYellowGreen) {
|
|
121
|
-
threshold = 40;
|
|
122
|
-
if (hsl.s >= 70) {
|
|
123
|
-
threshold = 35;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
else if (isBlueViolet) {
|
|
127
|
-
threshold = 55;
|
|
128
|
-
if (hsl.s >= 70) {
|
|
129
|
-
threshold = 60;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
else if (isRedOrange && hsl.s >= 80) {
|
|
133
|
-
threshold = 45;
|
|
134
|
-
}
|
|
135
|
-
const contrastL = hsl.l >= threshold ? 20 : 90;
|
|
136
131
|
const contrastS = Math.min(hsl.s, 90);
|
|
137
|
-
|
|
132
|
+
const bgRgb = hslToLinearRgb(hsl.h, hsl.s, hsl.l);
|
|
133
|
+
const bgLum = srgbLuminance(...bgRgb);
|
|
134
|
+
const darkL = 15;
|
|
135
|
+
const lightL = 90;
|
|
136
|
+
const darkLum = srgbLuminance(...hslToLinearRgb(hsl.h, contrastS, darkL));
|
|
137
|
+
const lightLum = srgbLuminance(...hslToLinearRgb(hsl.h, contrastS, lightL));
|
|
138
|
+
const darkRatio = wcagContrastRatio(bgLum, darkLum);
|
|
139
|
+
const lightRatio = wcagContrastRatio(bgLum, lightLum);
|
|
140
|
+
// On saturated backgrounds, dark-tinted text blends visually with the
|
|
141
|
+
// vibrant color even when math says it has better contrast.
|
|
142
|
+
// Prefer light text unless dark has an overwhelmingly higher ratio.
|
|
143
|
+
const saturatedBias = hsl.s >= 30 && bgLum < 0.4;
|
|
144
|
+
// Mid-grays (#777–#999): dark text "sinks" into the background while
|
|
145
|
+
// white text pops, even though dark wins on WCAG ratio.
|
|
146
|
+
const midGrayBias = hsl.s < 15 && bgLum >= 0.18 && bgLum <= 0.35;
|
|
147
|
+
const goLight = saturatedBias
|
|
148
|
+
? darkRatio < lightRatio * 3
|
|
149
|
+
: midGrayBias || lightRatio >= darkRatio;
|
|
150
|
+
let targetL = goLight ? lightL : darkL;
|
|
151
|
+
let bestRatio = goLight ? lightRatio : darkRatio;
|
|
152
|
+
if (bestRatio < 4.5) {
|
|
153
|
+
const step = goLight ? 5 : -5;
|
|
154
|
+
const limit = goLight ? 95 : 0;
|
|
155
|
+
while (bestRatio < 4.5 && targetL !== limit) {
|
|
156
|
+
targetL = goLight ? Math.min(targetL + step, limit) : Math.max(targetL + step, limit);
|
|
157
|
+
const candidateLum = srgbLuminance(...hslToLinearRgb(hsl.h, contrastS, targetL));
|
|
158
|
+
bestRatio = wcagContrastRatio(bgLum, candidateLum);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return `hsl(${hsl.h}, ${contrastS}%, ${targetL}%)`;
|
|
138
162
|
}
|
|
139
163
|
|
|
140
164
|
const SVG_ICONS = {
|
|
@@ -229,7 +253,7 @@ const CwMessage = props => {
|
|
|
229
253
|
}, props.duration ?? CW_DEFAULT_MESSAGE_DURATION);
|
|
230
254
|
return () => clearTimeout(timer);
|
|
231
255
|
}, [props]);
|
|
232
|
-
return (jsxs("div", { className: "cw-message", "data-message-type": Object.keys(CwMessageType).find(key => CwMessageType[key] === props.messageType), children: [props.messageType && jsx(CwIcon, { iconId: props.messageType.toString(), size: "large" }), props.message] }));
|
|
256
|
+
return (jsxs("div", { className: "cw-message", "data-message-type": Object.keys(CwMessageType).find(key => CwMessageType[key] === props.messageType), onClick: props.onClick, style: props.onClick ? { cursor: "pointer" } : undefined, children: [props.messageType && jsx(CwIcon, { iconId: props.messageType.toString(), size: "large" }), props.message] }));
|
|
233
257
|
};
|
|
234
258
|
/**
|
|
235
259
|
* Hook for displaying inline messages within specific components.
|
|
@@ -292,11 +316,11 @@ class CwMessageManager {
|
|
|
292
316
|
document.body.prepend(this.messageWrapper);
|
|
293
317
|
this.root = createRoot(this.messageWrapper); // Create a root at the messageWrapper
|
|
294
318
|
}
|
|
295
|
-
showMessage(message, type, duration) {
|
|
319
|
+
showMessage(message, type, duration, onClick) {
|
|
296
320
|
const msg = document.createElement("div");
|
|
297
321
|
this.messageWrapper?.prepend(msg);
|
|
298
322
|
const msgRoot = createRoot(msg); // Create a root for the new message
|
|
299
|
-
msgRoot.render(jsx(CwMessage, { message: message, messageType: type, duration: duration, onClose: () => this.closeMessage(msgRoot) }));
|
|
323
|
+
msgRoot.render(jsx(CwMessage, { message: message, messageType: type, duration: duration, onClick: onClick, onClose: () => this.closeMessage(msgRoot) }));
|
|
300
324
|
}
|
|
301
325
|
closeMessage(msgRoot) {
|
|
302
326
|
msgRoot.unmount(); // Unmount the message root
|
|
@@ -318,8 +342,8 @@ class CwMessageManager {
|
|
|
318
342
|
*
|
|
319
343
|
* @note For inline messages within components, use `CwNote` or `useCwMessage` hook instead
|
|
320
344
|
*/
|
|
321
|
-
function CwDisplayMessage(message, type, duration) {
|
|
322
|
-
CwMessageManager.getInstance().showMessage(message, type, duration);
|
|
345
|
+
function CwDisplayMessage(message, type, duration, onClick) {
|
|
346
|
+
CwMessageManager.getInstance().showMessage(message, type, duration, onClick);
|
|
323
347
|
}
|
|
324
348
|
|
|
325
349
|
/**
|
|
@@ -1844,7 +1868,7 @@ function CwAccordionContainer(CwelltAccordionContainerProps) {
|
|
|
1844
1868
|
*
|
|
1845
1869
|
* @returns React component
|
|
1846
1870
|
*/
|
|
1847
|
-
function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, rowSelection }) {
|
|
1871
|
+
function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10, 20, 50], expandedRowRender, onExpand, className, classNameRow, style, classNameContainer, id, textNoData = "No data available at the moment", rowKey = "key", loading = false, scrollHeight, stickyHeader = false, pageLabel = "page", rowSelection }) {
|
|
1848
1872
|
const [currentPage, setCurrentPage] = useState(1);
|
|
1849
1873
|
const [expandedRowKey, setExpandedRowKey] = useState(null);
|
|
1850
1874
|
const [sortConfig, setSortConfig] = useState({
|
|
@@ -2029,16 +2053,16 @@ function CwTable({ columns, data, pagination = false, pageSizeOptions = [5, 10,
|
|
|
2029
2053
|
? "sortable"
|
|
2030
2054
|
: sortConfig.direction === "asc"
|
|
2031
2055
|
? "sortable-asc"
|
|
2032
|
-
: "sortable-desc" }))] }), jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsx("tbody", { children: renderTableBody() })] }) }), pagination && data.length > pageSizeOptions[0] && (jsxs("footer", { className: "cw-table-pagination", children: [jsx("
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2056
|
+
: "sortable-desc" }))] }), jsx("span", { onMouseDown: (e) => startResize(e, col.key), className: "th-column-resizer" })] }, col.key)))] }) }), jsx("tbody", { children: renderTableBody() })] }) }), pagination && data.length > pageSizeOptions[0] && (jsxs("footer", { className: "cw-table-pagination", children: [jsxs("div", { className: "cw-table-pagination-size", children: [jsx(CwIcon, { iconId: "list" }), jsx("select", { value: localItemsPerPage, onChange: handleItemsPerPageChange, children: pageSizeOptions.map(size => (jsx("option", { value: size, children: pageLabel ? `${size} / ${pageLabel}` : size }, size))) })] }), jsxs("div", { className: "cw-table-pagination-nav", children: [jsx(CwButton, { onClick: () => handlePageChange(1), disabled: currentPage === 1 || totalPages === 1, variant: "icon", icon: "chevron-left-double" }), jsx(CwButton, { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 1 || totalPages === 1, variant: "icon", icon: "chevron-left" }), jsx("input", { type: "text", inputMode: "numeric", value: currentPage, onChange: (e) => {
|
|
2057
|
+
const value = parseInt(e.target.value, 10);
|
|
2058
|
+
if (!isNaN(value))
|
|
2059
|
+
handlePageChange(value);
|
|
2060
|
+
}, onBlur: (e) => {
|
|
2061
|
+
const value = parseInt(e.target.value, 10);
|
|
2062
|
+
if (isNaN(value) || value < 1 || value > totalPages) {
|
|
2063
|
+
handlePageChange(1);
|
|
2064
|
+
}
|
|
2065
|
+
}, min: 1, max: totalPages }), jsx("span", { children: "/" }), jsx("span", { children: totalPages }), jsx(CwButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages || totalPages === 1, variant: "icon", icon: "chevron-right" }), jsx(CwButton, { onClick: () => handlePageChange(totalPages), disabled: currentPage === totalPages || totalPages === 1, variant: "icon", icon: "chevron-right-double" })] })] }))] }));
|
|
2042
2066
|
}
|
|
2043
2067
|
|
|
2044
2068
|
var styles$i = {"dropIndicator":"cw-sortable-table-module__dropIndicator__ov-Jz","dragging":"cw-sortable-table-module__dragging__MrLrz","skeletonRow":"cw-sortable-table-module__skeletonRow__vyD0M","skeleton":"cw-sortable-table-module__skeleton__QGXAD","saveBar":"cw-sortable-table-module__saveBar__3OdoZ cw-flex-row cw-align-center-center cw-gap-small"};
|
|
@@ -2795,10 +2819,26 @@ function CwFileUpload(fileUploadProps) {
|
|
|
2795
2819
|
|
|
2796
2820
|
var styles$e = {"fileUploadContainer":"cw-file-upload-multiple-module__fileUploadContainer__liEc1","hiddenInput":"cw-file-upload-multiple-module__hiddenInput__TZBBI","uploadArea":"cw-file-upload-multiple-module__uploadArea__DdOhs","uploadAreaDisabled":"cw-file-upload-multiple-module__uploadAreaDisabled__VWeFX","uploadTitle":"cw-file-upload-multiple-module__uploadTitle__gjRk8","uploadSubtitle":"cw-file-upload-multiple-module__uploadSubtitle__Z0S5t","filesContainer":"cw-file-upload-multiple-module__filesContainer__g44PY","fileItem":"cw-file-upload-multiple-module__fileItem__w27Dg","fileIcon":"cw-file-upload-multiple-module__fileIcon__iJJUX","fileExtension":"cw-file-upload-multiple-module__fileExtension__vOuHv","fileInfo":"cw-file-upload-multiple-module__fileInfo__R5ZTv","fileName":"cw-file-upload-multiple-module__fileName__DjepK","fileSize":"cw-file-upload-multiple-module__fileSize__b8GSm","smallButton":"cw-file-upload-multiple-module__smallButton__siUAh"};
|
|
2797
2821
|
|
|
2822
|
+
const DEFAULT_LABELS = {
|
|
2823
|
+
uploadDisabled: 'Upload disabled',
|
|
2824
|
+
clickToUpload: 'Click to upload or drag and drop',
|
|
2825
|
+
acceptedFiles: (accept) => `Accepted files: ${accept}`,
|
|
2826
|
+
singleFileOnly: '(Single file only)',
|
|
2827
|
+
allTypesAccepted: 'All file types accepted',
|
|
2828
|
+
changeFile: 'Change File',
|
|
2829
|
+
clearAll: 'Clear all',
|
|
2830
|
+
addMoreFiles: 'Add More Files',
|
|
2831
|
+
filesSelected: (count) => `${count} file${count !== 1 ? 's' : ''} selected`,
|
|
2832
|
+
fileTooLarge: (name, maxSize) => `File "${name}" is too large. Maximum size allowed is ${maxSize}MB.`,
|
|
2833
|
+
invalidFormat: (name, accepted) => `File "${name}" has an invalid format. Allowed formats: ${accepted}`,
|
|
2834
|
+
invalidMimeType: (name, types) => `File "${name}" has an invalid MIME type. Allowed types: ${types}`,
|
|
2835
|
+
alreadySelected: (name) => `File "${name}" is already selected.`,
|
|
2836
|
+
};
|
|
2798
2837
|
function CwFileUploadMultiple(fileUploadProps) {
|
|
2799
2838
|
const fileInputRef = useRef(null);
|
|
2800
2839
|
const [selectedFiles, setSelectedFiles] = useState([]);
|
|
2801
2840
|
const [existingFile, setExistingFile] = useState(fileUploadProps.initialFileName);
|
|
2841
|
+
const labels = { ...DEFAULT_LABELS, ...fileUploadProps.labels };
|
|
2802
2842
|
React__default.useEffect(() => {
|
|
2803
2843
|
setExistingFile(fileUploadProps.initialFileName);
|
|
2804
2844
|
}, [fileUploadProps.initialFileName]);
|
|
@@ -2812,7 +2852,7 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2812
2852
|
if (fileSizeInMB > fileUploadProps.maxFileSize) {
|
|
2813
2853
|
return {
|
|
2814
2854
|
isValid: false,
|
|
2815
|
-
error:
|
|
2855
|
+
error: labels.fileTooLarge(file.name, fileUploadProps.maxFileSize)
|
|
2816
2856
|
};
|
|
2817
2857
|
}
|
|
2818
2858
|
}
|
|
@@ -2829,7 +2869,7 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2829
2869
|
if (!isExtensionValid) {
|
|
2830
2870
|
return {
|
|
2831
2871
|
isValid: false,
|
|
2832
|
-
error:
|
|
2872
|
+
error: labels.invalidFormat(file.name, fileUploadProps.accept)
|
|
2833
2873
|
};
|
|
2834
2874
|
}
|
|
2835
2875
|
}
|
|
@@ -2839,7 +2879,7 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2839
2879
|
if (!isMimeTypeValid) {
|
|
2840
2880
|
return {
|
|
2841
2881
|
isValid: false,
|
|
2842
|
-
error:
|
|
2882
|
+
error: labels.invalidMimeType(file.name, fileUploadProps.allowedTypes.join(', '))
|
|
2843
2883
|
};
|
|
2844
2884
|
}
|
|
2845
2885
|
}
|
|
@@ -2853,7 +2893,7 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2853
2893
|
// Check if the file already exists (by name and size)
|
|
2854
2894
|
const isDuplicate = existingFiles.some(existingFile => existingFile.name === file.name && existingFile.size === file.size);
|
|
2855
2895
|
if (isDuplicate) {
|
|
2856
|
-
errors.push(
|
|
2896
|
+
errors.push(labels.alreadySelected(file.name));
|
|
2857
2897
|
continue;
|
|
2858
2898
|
}
|
|
2859
2899
|
const validation = validateFile(file);
|
|
@@ -2944,12 +2984,12 @@ function CwFileUploadMultiple(fileUploadProps) {
|
|
|
2944
2984
|
}
|
|
2945
2985
|
}
|
|
2946
2986
|
};
|
|
2947
|
-
return (jsxs("div", { className: `${styles$e.fileUploadContainer} ${fileUploadProps.className}`, children: [jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$e.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxs("div", { className: `${styles$e.uploadArea} ${fileUploadProps.disabled ? styles$e.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsx(CwIcon, { iconId: "upload" }), jsx("p", { className: `${styles$e.uploadTitle}`, children: fileUploadProps.disabled ?
|
|
2987
|
+
return (jsxs("div", { className: `${styles$e.fileUploadContainer} ${fileUploadProps.className}`, children: [jsx("input", { ref: fileInputRef, type: "file", name: fileUploadProps.name, accept: fileUploadProps.accept, multiple: fileUploadProps.multiple, onChange: handleFileSelectInternal, disabled: fileUploadProps.disabled, "aria-label": "files", className: styles$e.hiddenInput }), selectedFiles.length === 0 && !existingFile ? (jsxs("div", { className: `${styles$e.uploadArea} ${fileUploadProps.disabled ? styles$e.uploadAreaDisabled : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onClick: !fileUploadProps.disabled ? handleButtonClick : undefined, children: [jsx(CwIcon, { iconId: "upload" }), jsx("p", { className: `${styles$e.uploadTitle}`, children: fileUploadProps.disabled ? labels.uploadDisabled : labels.clickToUpload }), jsxs("p", { className: `${styles$e.uploadSubtitle}`, children: [fileUploadProps.accept ? labels.acceptedFiles(fileUploadProps.accept) : labels.allTypesAccepted, !fileUploadProps.multiple && ` ${labels.singleFileOnly}`] })] })) : selectedFiles.length === 0 && existingFile ? (jsxs("div", { className: styles$e.filesContainer, children: [jsxs("div", { className: styles$e.fileItem, children: [jsxs("div", { className: styles$e.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$e.fileExtension, children: getFileExtension(existingFile) })] }), jsx("div", { className: styles$e.fileInfo, children: jsx("p", { className: styles$e.fileName, children: existingFile }) }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => {
|
|
2948
2988
|
setExistingFile(undefined);
|
|
2949
2989
|
if (fileUploadProps.onSelect) {
|
|
2950
2990
|
fileUploadProps.onSelect(null);
|
|
2951
2991
|
}
|
|
2952
|
-
}, disabled: fileUploadProps.disabled, className: styles$e.smallButton })] }), jsx(CwButton, { text:
|
|
2992
|
+
}, disabled: fileUploadProps.disabled, className: styles$e.smallButton })] }), jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled })] })) : (jsxs("div", { className: styles$e.filesContainer, children: [jsxs("div", { className: "cw-flex-row cw-align-between-center", children: [jsx("small", { className: styles$e.filesCount, children: labels.filesSelected(selectedFiles.length) }), jsx(CwButton, { onClick: removeAllFiles, disabled: fileUploadProps.disabled, color: "danger", variant: "outline", icon: "delete", text: labels.clearAll })] }), selectedFiles.map((file, index) => (jsxs("div", { className: styles$e.fileItem, children: [jsxs("div", { className: styles$e.fileIcon, children: [jsx(CwIcon, { iconId: "page" }), jsx("span", { className: styles$e.fileExtension, children: getFileExtension(file.name) })] }), jsxs("div", { className: styles$e.fileInfo, children: [jsx("p", { className: styles$e.fileName, children: file.name }), jsxs("p", { className: styles$e.fileSize, children: [(file.size / 1024).toFixed(1), " KB"] })] }), jsx(CwButton, { variant: "icon", icon: "close", color: "neutral", onClick: () => removeFile(index), className: styles$e.smallButton })] }, index))), fileUploadProps.multiple && (jsx(CwButton, { text: labels.addMoreFiles, icon: "plus", variant: "outline", onClick: handleButtonClick, disabled: fileUploadProps.disabled })), !fileUploadProps.multiple && (jsx(CwButton, { text: labels.changeFile, icon: "refresh", onClick: handleButtonClick, disabled: fileUploadProps.disabled }))] }))] }));
|
|
2953
2993
|
}
|
|
2954
2994
|
|
|
2955
2995
|
function CwInput(CwInputProps) {
|
|
@@ -4309,7 +4349,7 @@ const CwMultiFilterTag = props => {
|
|
|
4309
4349
|
} : undefined }) }));
|
|
4310
4350
|
};
|
|
4311
4351
|
|
|
4312
|
-
var styles$7 = {"cw-multi-filter-catalog-container":"cw-multi-filter-module__cw-multi-filter-catalog-container__S3nsq","cw-multi-filter":"cw-multi-filter-module__cw-multi-filter__zipBK","cw-multi-filter-search":"cw-multi-filter-module__cw-multi-filter-search__eyHr0"};
|
|
4352
|
+
var styles$7 = {"cw-multi-filter-catalog-container":"cw-multi-filter-module__cw-multi-filter-catalog-container__S3nsq","cw-multi-filter":"cw-multi-filter-module__cw-multi-filter__zipBK","category-selected":"cw-multi-filter-module__category-selected__eYbes","cw-multi-filter-search":"cw-multi-filter-module__cw-multi-filter-search__eyHr0"};
|
|
4313
4353
|
|
|
4314
4354
|
/**
|
|
4315
4355
|
* A multiple filter selector, a MULTI-SELECT even. Allows users to select and filter items based on tags.
|
|
@@ -4450,7 +4490,7 @@ var styles$7 = {"cw-multi-filter-catalog-container":"cw-multi-filter-module__cw-
|
|
|
4450
4490
|
* @param {CwMultiFilterProps} props
|
|
4451
4491
|
* @returns Set the `onChange` callback to a function to check for changes in the selected filters
|
|
4452
4492
|
*/
|
|
4453
|
-
const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, style }) => {
|
|
4493
|
+
const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, placeholder = "Write to filter", allCategoriesLabel = "ALL CATEGORIES", className, style }) => {
|
|
4454
4494
|
const [filteredTags, setFilteredTags] = useState(new Set());
|
|
4455
4495
|
const [inputTextValue, setInputTextValue] = useState("");
|
|
4456
4496
|
const [isPanelOpen, setIsPanelOpen] = useState(false);
|
|
@@ -4552,9 +4592,9 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, style
|
|
|
4552
4592
|
inputRef.current?.focus();
|
|
4553
4593
|
}
|
|
4554
4594
|
};
|
|
4555
|
-
return (jsxs("form", { ref: componentRef, id: id, className: styles$7["cw-multi-filter"]
|
|
4595
|
+
return (jsxs("form", { ref: componentRef, id: id, className: `${styles$7["cw-multi-filter"]}${className ? ` ${className}` : ""}`, style: style, onSubmit: (e) => {
|
|
4556
4596
|
e.preventDefault();
|
|
4557
|
-
}, children: [jsxs("div", { onClick: handleDivClick, className: styles$7["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-primary)", outlineOffset: "-2px" } : {}, children: [jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.target.value), autoComplete: "off", placeholder:
|
|
4597
|
+
}, children: [jsxs("div", { onClick: handleDivClick, className: styles$7["cw-multi-filter-search"], style: isPanelOpen ? { outline: "1px solid var(--cw-color-primary)", outlineOffset: "-2px" } : {}, children: [jsxs("ul", { id: id + "_selected_filters", children: [Array.from(selectedTags).map(tag => (createElement(CwMultiFilterTag, { ...tag, key: tag.ID, Selectable: false, Removable: true, OnRemove: () => removeTag(tag.ID) }))), jsx("input", { type: "text", id: id + "_input", ref: inputRef, value: inputTextValue, spellCheck: false, onFocus: () => setIsPanelOpen(true), onChange: e => handleInputText(e.target.value), autoComplete: "off", placeholder: placeholder, onKeyDown: e => {
|
|
4558
4598
|
switch (e.key) {
|
|
4559
4599
|
case "Enter":
|
|
4560
4600
|
case "Tab": {
|
|
@@ -4584,15 +4624,7 @@ const CwMultiFilter = ({ allTags, id, onChangeSelectedTags, selectedTags, style
|
|
|
4584
4624
|
} })] }), selectedTags.size > 0 ? (jsx("input", { type: "reset", value: "\u00D7", onClick: e => {
|
|
4585
4625
|
e.preventDefault();
|
|
4586
4626
|
onChangeSelectedTags(new Set());
|
|
4587
|
-
} })) : null] }), jsxs("section", { className: styles$7["cw-multi-filter-catalog-container"], "data-display-none": !isPanelOpen, children: [jsxs("nav", { children: [jsx("button", {
|
|
4588
|
-
? {
|
|
4589
|
-
backgroundColor: "var(--cw-color-primary-container)",
|
|
4590
|
-
color: "var(--cw-color-primary)",
|
|
4591
|
-
outline: "2px solid var(--cw-color-primary)",
|
|
4592
|
-
outlineOffset: "-2px",
|
|
4593
|
-
fontWeight: 400
|
|
4594
|
-
}
|
|
4595
|
-
: {}, onClick: () => handleClickCategory("All"), children: "SEARCH IN ALL CATEGORIES" }), Array.from(categoriesMappedToTags().keys()).map(category => (jsx("button", { style: selectedCategory === category
|
|
4627
|
+
} })) : null] }), jsxs("section", { className: styles$7["cw-multi-filter-catalog-container"], "data-display-none": !isPanelOpen, children: [jsxs("nav", { children: [jsx("button", { className: selectedCategory === "All" ? styles$7["category-selected"] : undefined, onClick: () => handleClickCategory("All"), children: allCategoriesLabel }), Array.from(categoriesMappedToTags().keys()).map(category => (jsx("button", { style: selectedCategory === category
|
|
4596
4628
|
? {
|
|
4597
4629
|
backgroundColor: getColor(category).primary,
|
|
4598
4630
|
color: getColor(category).onPrimary,
|
|
@@ -5142,10 +5174,13 @@ function usePickerPopup({ anchorRef, isOpen, onClose, position = "left-bottom" }
|
|
|
5142
5174
|
return { popupRef, popupStyle: style, renderPopup };
|
|
5143
5175
|
}
|
|
5144
5176
|
|
|
5145
|
-
function CwDatePicker({ 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, }) {
|
|
5177
|
+
function CwDatePicker({ 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", feedback, }) {
|
|
5146
5178
|
const [isOpen, setIsOpen] = useState(false);
|
|
5147
5179
|
const [inputValue, setInputValue] = useState("");
|
|
5148
5180
|
const containerRef = useRef(null);
|
|
5181
|
+
const feedbackMessages = feedback
|
|
5182
|
+
? Array.isArray(feedback) ? feedback : [feedback]
|
|
5183
|
+
: [];
|
|
5149
5184
|
const wrapperRef = useRef(null);
|
|
5150
5185
|
const inputRef = useRef(null);
|
|
5151
5186
|
const prevValueRef = useRef(undefined);
|
|
@@ -5313,11 +5348,11 @@ function CwDatePicker({ value, onChange, minDate, maxDate, disabledDates, disabl
|
|
|
5313
5348
|
...(maxDate ? [{ after: maxDate }] : []),
|
|
5314
5349
|
...(disabledMatcher ? [disabledMatcher] : []),
|
|
5315
5350
|
], [disabledDates, minDate, maxDate, disabledMatcher]);
|
|
5316
|
-
return (
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5351
|
+
return (jsxs("div", { ref: containerRef, className: `cw-datepicker ${className || ""}`, children: [jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, required: required }), jsx("div", { className: styles$4.pickerIcons, children: showClear && value && !disabled ? (jsx(CwButton, { type: "button", variant: "icon", color: "neutral", icon: "close", onClick: handleClear, tabIndex: -1, "aria-label": "Clear date" })) : (jsx(CwIcon, { iconId: "calendar" })) }), renderPopup(jsxs("div", { ref: popupRef, className: styles$4.pickerPopup, style: popupStyle, children: [jsx(DayPicker, { mode: "single", selected: value || undefined, defaultMonth: defaultMonth || value || undefined, onSelect: handleDaySelect, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale, modifiers: {
|
|
5352
|
+
today: new Date(),
|
|
5353
|
+
}, modifiersClassNames: {
|
|
5354
|
+
today: "rdp-day-today",
|
|
5355
|
+
} }), 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)))] }));
|
|
5321
5356
|
}
|
|
5322
5357
|
|
|
5323
5358
|
var rangeStyles = {"rangeWrapper":"cw-range-picker-module__rangeWrapper__1nIVs","rangePopup":"cw-range-picker-module__rangePopup__E5jd1","presetList":"cw-range-picker-module__presetList__INiLo"};
|
|
@@ -6165,7 +6200,7 @@ function combineDateTimeInOffset(date, hours, minutes, timezoneOffset) {
|
|
|
6165
6200
|
return new Date(zdt.epochMilliseconds);
|
|
6166
6201
|
}
|
|
6167
6202
|
|
|
6168
|
-
function CwDateTimePicker({ value, onChange, minDateTime, maxDateTime, disabledDates, disabledMatcher, timeInterval = 15, minTime, maxTime, labelProps, alignProps, datePlaceholder = "dd.MM.yyyy", timePlaceholder = "HH:mm", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showNowButton = false, timezoneOffset, }) {
|
|
6203
|
+
function CwDateTimePicker({ value, onChange, minDateTime, maxDateTime, disabledDates, disabledMatcher, timeInterval = 15, minTime, maxTime, labelProps, alignProps, datePlaceholder = "dd.MM.yyyy", timePlaceholder = "HH:mm", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showNowButton = false, nowLabel = "Now", locale = enGB, timezoneOffset, }) {
|
|
6169
6204
|
// ========================================
|
|
6170
6205
|
// PROPS NORMALIZATION
|
|
6171
6206
|
// ========================================
|
|
@@ -6405,12 +6440,12 @@ function CwDateTimePicker({ value, onChange, minDateTime, maxDateTime, disabledD
|
|
|
6405
6440
|
const displayMaxDate = useMemo(() => normalizedMaxDateTime && timezoneOffset !== undefined
|
|
6406
6441
|
? getDateInOffset(normalizedMaxDateTime, timezoneOffset)
|
|
6407
6442
|
: normalizedMaxDateTime, [normalizedMaxDateTime, timezoneOffset]);
|
|
6408
|
-
return jsx("div", { className: `cw-datetimepicker cw-datetimepicker-separate ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsx(CwDatePicker, { value: selectedDate, onChange: handleDateChange, minDate: displayMinDate, maxDate: displayMaxDate, disabledDates: disabledDates, disabledMatcher: disabledMatcher, placeholder: datePlaceholder, disabled: disabled, required: required, showClear: showClear, numberOfMonths: numberOfMonths, popupPosition: popupPosition }), jsx(CwTimePicker, { value: selectedTime, onChange: handleTimeChange, interval: timeInterval, minTime: timeRestrictions.minTime, maxTime: timeRestrictions.maxTime, placeholder: timePlaceholder, disabled: disabled, required: required, showClear: showClear, popupPosition: popupPosition }), showNowButton && (jsx(CwButton, { type: "button", variant: "outline", onClick: handleNowClick, disabled: disabled,
|
|
6443
|
+
return jsx("div", { className: `cw-datetimepicker cw-datetimepicker-separate ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { className: "cw-flex-row cw-align-left-center cw-gap-small", children: [jsx(CwDatePicker, { value: selectedDate, onChange: handleDateChange, minDate: displayMinDate, maxDate: displayMaxDate, disabledDates: disabledDates, disabledMatcher: disabledMatcher, placeholder: datePlaceholder, disabled: disabled, required: required, showClear: showClear, numberOfMonths: numberOfMonths, popupPosition: popupPosition, locale: locale }), jsx(CwTimePicker, { value: selectedTime, onChange: handleTimeChange, interval: timeInterval, minTime: timeRestrictions.minTime, maxTime: timeRestrictions.maxTime, placeholder: timePlaceholder, disabled: disabled, required: required, showClear: showClear, popupPosition: popupPosition }), showNowButton && (jsx(CwButton, { type: "button", variant: "outline", onClick: handleNowClick, disabled: disabled, text: nowLabel }))] })] }) });
|
|
6409
6444
|
}
|
|
6410
6445
|
|
|
6411
6446
|
var compactStyles = {"compactPopup":"cw-datetime-compact-module__compactPopup__GiuNY","calendarWrapper":"cw-datetime-compact-module__calendarWrapper__P4Nlq","timeWrapper":"cw-datetime-compact-module__timeWrapper__uMe-A","compactTimeList":"cw-datetime-compact-module__compactTimeList__MzSQT"};
|
|
6412
6447
|
|
|
6413
|
-
function CwDateTimePickerCompact({ value, onChange, minDateTime, maxDateTime, disabledDates, disabledMatcher, timeInterval = 15, minTime, maxTime, labelProps, alignProps, placeholder = "dd.mm.yyyy HH:mm", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showTodayButton = false, }) {
|
|
6448
|
+
function CwDateTimePickerCompact({ value, onChange, minDateTime, maxDateTime, disabledDates, disabledMatcher, timeInterval = 15, minTime, maxTime, labelProps, alignProps, placeholder = "dd.mm.yyyy HH:mm", disabled, required, className, showClear = true, popupPosition = "left-bottom", numberOfMonths = 1, showTodayButton = false, nowLabel = "Now", timeLabel = "Time", locale = enGB, }) {
|
|
6414
6449
|
const [isOpen, setIsOpen] = useState(false);
|
|
6415
6450
|
const [inputValue, setInputValue] = useState("");
|
|
6416
6451
|
const [selectedDate, setSelectedDate] = useState(value);
|
|
@@ -6641,11 +6676,11 @@ function CwDateTimePickerCompact({ value, onChange, minDateTime, maxDateTime, di
|
|
|
6641
6676
|
...(maxDateTime ? [{ after: maxDateTime }] : []),
|
|
6642
6677
|
...(disabledMatcher ? [disabledMatcher] : []),
|
|
6643
6678
|
], [disabledDates, minDateTime, maxDateTime, disabledMatcher]);
|
|
6644
|
-
return (jsx("div", { ref: containerRef, className: `cw-datetimepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, required: required, maxLength: 16
|
|
6679
|
+
return (jsx("div", { ref: containerRef, className: `cw-datetimepicker ${className || ""}`, children: jsxs(CwAlign, { ...alignProps, itemProp: required ? "required" : "", children: [labelProps && (jsx(CwLabel, { ...labelProps, children: labelProps.text })), jsxs("div", { ref: wrapperRef, className: styles$4.pickerWrapper, children: [jsx("input", { ref: inputRef, type: "text", value: inputValue, placeholder: placeholder, onChange: handleInputChange, onBlur: handleInputBlur, onClick: handleInputClick, onKeyDown: handleInputKeyDown, disabled: disabled, required: required, maxLength: 16 }), 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 datetime" })) : (jsx(CwIcon, { iconId: "calendar-time" })) }), renderPopup(jsxs("div", { ref: popupRef, className: `${styles$4.pickerPopup} ${compactStyles.compactPopup}`, style: popupStyle, children: [jsxs("div", { className: compactStyles.calendarWrapper, children: [jsx(DayPicker, { mode: "single", selected: selectedDate, onSelect: handleDaySelect, defaultMonth: selectedDate, disabled: disabledDays, numberOfMonths: numberOfMonths, locale: locale, modifiers: {
|
|
6645
6680
|
today: new Date(),
|
|
6646
6681
|
}, modifiersClassNames: {
|
|
6647
6682
|
today: "rdp-day-today",
|
|
6648
|
-
} }), showTodayButton && (jsx("footer", { className: "cw-flex-row cw-align-center-center", children: jsx(CwButton, { type: "button", variant: "outline", icon: "check-big", onClick: handleNowClick, text:
|
|
6683
|
+
} }), showTodayButton && (jsx("footer", { className: "cw-flex-row cw-align-center-center", children: jsx(CwButton, { type: "button", variant: "outline", icon: "check-big", onClick: handleNowClick, text: nowLabel }) }))] }), jsxs("div", { className: compactStyles.timeWrapper, children: [jsxs("header", { children: [jsx(CwIcon, { iconId: "clock", size: "medium" }), jsx("span", { children: timeLabel })] }), jsx("div", { ref: timeListRef, className: `${timeStyles.timePickerList} ${compactStyles.compactTimeList}`, children: timeOptions.map((time) => {
|
|
6649
6684
|
const isSelected = time === selectedTime;
|
|
6650
6685
|
return (jsx("button", { type: "button", className: isSelected ? timeStyles.selected : "", onClick: () => handleTimeSelect(time), children: time }, time));
|
|
6651
6686
|
}) })] })] }))] })] }) }));
|
|
@@ -7985,30 +8020,95 @@ const BackgroundEvent = ({ value, heightRem }) => {
|
|
|
7985
8020
|
}, children: value.icons }) : null, jsx("span", { className: styles$2["scheduler-event-text"], children: value.name })] }) }) }) }) })) : null;
|
|
7986
8021
|
};
|
|
7987
8022
|
|
|
8023
|
+
const eventIsVisible = (startDate, endDate, selectedDate, visibleDays) => {
|
|
8024
|
+
const schedulerEnd = Temporal.PlainDate.from({
|
|
8025
|
+
year: selectedDate.getFullYear(),
|
|
8026
|
+
month: selectedDate.getMonth() + 1,
|
|
8027
|
+
day: selectedDate.getDate(),
|
|
8028
|
+
}).add({ days: visibleDays });
|
|
8029
|
+
const schedulerEndDate = new Date(schedulerEnd.year, schedulerEnd.month - 1, schedulerEnd.day);
|
|
8030
|
+
const isBefore = selectedDate > startDate && selectedDate > endDate;
|
|
8031
|
+
const isAfter = schedulerEndDate < startDate && schedulerEndDate < endDate;
|
|
8032
|
+
return !isBefore && !isAfter;
|
|
8033
|
+
};
|
|
8034
|
+
|
|
8035
|
+
const hoursBetween = (date1, date2) => {
|
|
8036
|
+
const oneHourInMillis = 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
|
|
8037
|
+
const timeDiff = date2.getTime() - date1.getTime();
|
|
8038
|
+
return timeDiff / oneHourInMillis;
|
|
8039
|
+
};
|
|
8040
|
+
const getEventSizes = (schedulerDate, totalDays, startDate, endDate) => {
|
|
8041
|
+
if (!eventIsVisible(startDate, endDate, schedulerDate, totalDays)) {
|
|
8042
|
+
return {
|
|
8043
|
+
left: 0,
|
|
8044
|
+
width: 0,
|
|
8045
|
+
};
|
|
8046
|
+
}
|
|
8047
|
+
const totalHours = totalDays * 24;
|
|
8048
|
+
// const dateString = schedulerDate.toISOString().split('T')[0];
|
|
8049
|
+
//const schedulerDateAtZero = new Date(dateString)
|
|
8050
|
+
let startHours = hoursBetween(schedulerDate, startDate);
|
|
8051
|
+
let durationHours = hoursBetween(startDate, endDate);
|
|
8052
|
+
const startOutOfScheduler = startHours < 0;
|
|
8053
|
+
if (startOutOfScheduler) {
|
|
8054
|
+
durationHours += startHours;
|
|
8055
|
+
startHours = 0;
|
|
8056
|
+
}
|
|
8057
|
+
const left = (startHours / totalHours) * 100;
|
|
8058
|
+
// Minimum width equivalent to 15 minutes so zero/near-zero duration events stay visible
|
|
8059
|
+
const MIN_WIDTH_HOURS = 0.25;
|
|
8060
|
+
const minWidth = (MIN_WIDTH_HOURS * 100) / totalHours;
|
|
8061
|
+
const width = Math.max((durationHours * 100) / totalHours, minWidth);
|
|
8062
|
+
return {
|
|
8063
|
+
left,
|
|
8064
|
+
width,
|
|
8065
|
+
};
|
|
8066
|
+
};
|
|
8067
|
+
|
|
8068
|
+
const INDICATOR_HEIGHT_REM = 0.25;
|
|
8069
|
+
const IndicatorRow = ({ indicators, selectedDate, visibleDays }) => {
|
|
8070
|
+
return (jsx("div", { style: {
|
|
8071
|
+
position: "relative",
|
|
8072
|
+
height: `${INDICATOR_HEIGHT_REM}rem`,
|
|
8073
|
+
pointerEvents: "none",
|
|
8074
|
+
}, "data-name": "indicator-row", children: indicators.map((indicator) => {
|
|
8075
|
+
const { left, width } = getEventSizes(selectedDate, visibleDays, indicator.start, indicator.end);
|
|
8076
|
+
if (width <= 0)
|
|
8077
|
+
return null;
|
|
8078
|
+
const bar = (jsx("div", { style: {
|
|
8079
|
+
position: "absolute",
|
|
8080
|
+
left: `${left}%`,
|
|
8081
|
+
width: `${width}%`,
|
|
8082
|
+
height: `${INDICATOR_HEIGHT_REM}rem`,
|
|
8083
|
+
backgroundColor: indicator.color,
|
|
8084
|
+
borderRadius: "1px",
|
|
8085
|
+
pointerEvents: "auto",
|
|
8086
|
+
} }, indicator.id));
|
|
8087
|
+
if (indicator.tooltip) {
|
|
8088
|
+
return (jsx(CwTooltipNew, { content: indicator.tooltip, position: "bottom", dissapearsWhenHover: true, showDelay: 200, children: bar }, indicator.id));
|
|
8089
|
+
}
|
|
8090
|
+
return bar;
|
|
8091
|
+
}) }));
|
|
8092
|
+
};
|
|
8093
|
+
|
|
8094
|
+
// Fires onClick on the first click of a sequence (detail === 1) and
|
|
8095
|
+
// onDoubleClick on the native dblclick event. Subsequent clicks of a
|
|
8096
|
+
// double-click sequence (detail > 1) are suppressed so the same logical
|
|
8097
|
+
// interaction does not fire onClick twice. Selection therefore appears
|
|
8098
|
+
// within one paint frame instead of being delayed by an artificial timer.
|
|
7988
8099
|
function useSingleAndDoubleClicks(onClick, onDoubleClick) {
|
|
7989
|
-
const timer = useRef(null);
|
|
7990
|
-
const cancelPendingClick = useCallback(() => {
|
|
7991
|
-
if (timer.current) {
|
|
7992
|
-
clearTimeout(timer.current);
|
|
7993
|
-
timer.current = null;
|
|
7994
|
-
}
|
|
7995
|
-
}, [timer]);
|
|
7996
8100
|
const handleClick = useCallback((e) => {
|
|
7997
|
-
// We only cache the most recent click event, so cancel any pending clicks
|
|
7998
8101
|
e.stopPropagation();
|
|
7999
8102
|
e.preventDefault();
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
}, 500);
|
|
8005
|
-
}, [timer, cancelPendingClick, onClick]);
|
|
8103
|
+
if (e.detail > 1)
|
|
8104
|
+
return;
|
|
8105
|
+
onClick(e);
|
|
8106
|
+
}, [onClick]);
|
|
8006
8107
|
const handleDoubleClick = useCallback((e) => {
|
|
8007
8108
|
e.stopPropagation();
|
|
8008
8109
|
e.preventDefault();
|
|
8009
|
-
cancelPendingClick();
|
|
8010
8110
|
onDoubleClick(e);
|
|
8011
|
-
}, [
|
|
8111
|
+
}, [onDoubleClick]);
|
|
8012
8112
|
return { handleClick, handleDoubleClick };
|
|
8013
8113
|
}
|
|
8014
8114
|
|
|
@@ -8182,7 +8282,7 @@ const SchedulerEvent = ({ value, heightRem, onEvent }) => {
|
|
|
8182
8282
|
|
|
8183
8283
|
const SchedulerRow = memo((props) => {
|
|
8184
8284
|
const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
|
|
8185
|
-
const { events, backgroundEvents, rowHeader, contextMenuItems, RowTitleComp, EventComp, BackgroundEventComp, weekendLines, divisionLines, timeLinePercentage, selectedDate, visibleDays, onEvent, } = props;
|
|
8285
|
+
const { events, backgroundEvents, indicatorRows, rowHeader, contextMenuItems, RowTitleComp, EventComp, BackgroundEventComp, weekendLines, divisionLines, timeLinePercentage, selectedDate, visibleDays, onEvent, } = props;
|
|
8186
8286
|
const internalRows = separateEventsToInnerRows(events);
|
|
8187
8287
|
const schedulerDivRef = useRef(null);
|
|
8188
8288
|
const { handleClick, handleDoubleClick } = useSingleAndDoubleClicks((e) => {
|
|
@@ -8239,7 +8339,7 @@ const SchedulerRow = memo((props) => {
|
|
|
8239
8339
|
height: props.rowHeightInRem + "rem",
|
|
8240
8340
|
pointerEvents: "none"
|
|
8241
8341
|
}, children: internalRow.map((event) => (jsx(EventComp, { value: event, heightRem: props.rowHeightInRem, onEvent: onEvent }, event.id))) }, index));
|
|
8242
|
-
}), !(timeLinePercentage < 0 || timeLinePercentage > 100) && (jsx(TimeLine, { color: "red", left: `${timeLinePercentage}%`, top: "0px", height: `100%` }))] }) })] }));
|
|
8342
|
+
}), 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%` }))] }) })] }));
|
|
8243
8343
|
}, (prevProps, nextProps) => {
|
|
8244
8344
|
// This memo is necessary to prevent re-render all the rows when a user makes drag and drop
|
|
8245
8345
|
const getEventKey = (event) => {
|
|
@@ -8265,6 +8365,9 @@ const SchedulerRow = memo((props) => {
|
|
|
8265
8365
|
return false;
|
|
8266
8366
|
}
|
|
8267
8367
|
}
|
|
8368
|
+
if (prevProps.indicatorRows.length !== nextProps.indicatorRows.length) {
|
|
8369
|
+
return false;
|
|
8370
|
+
}
|
|
8268
8371
|
// If we got here, the events are the same
|
|
8269
8372
|
return true;
|
|
8270
8373
|
});
|
|
@@ -8455,51 +8558,6 @@ const getWeeksByDays = (visibleDays, selectedDate) => {
|
|
|
8455
8558
|
return weeks;
|
|
8456
8559
|
};
|
|
8457
8560
|
|
|
8458
|
-
const eventIsVisible = (startDate, endDate, selectedDate, visibleDays) => {
|
|
8459
|
-
const schedulerEnd = Temporal.PlainDate.from({
|
|
8460
|
-
year: selectedDate.getFullYear(),
|
|
8461
|
-
month: selectedDate.getMonth() + 1,
|
|
8462
|
-
day: selectedDate.getDate(),
|
|
8463
|
-
}).add({ days: visibleDays });
|
|
8464
|
-
const schedulerEndDate = new Date(schedulerEnd.year, schedulerEnd.month - 1, schedulerEnd.day);
|
|
8465
|
-
const isBefore = selectedDate > startDate && selectedDate > endDate;
|
|
8466
|
-
const isAfter = schedulerEndDate < startDate && schedulerEndDate < endDate;
|
|
8467
|
-
return !isBefore && !isAfter;
|
|
8468
|
-
};
|
|
8469
|
-
|
|
8470
|
-
const hoursBetween = (date1, date2) => {
|
|
8471
|
-
const oneHourInMillis = 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
|
|
8472
|
-
const timeDiff = date2.getTime() - date1.getTime();
|
|
8473
|
-
return timeDiff / oneHourInMillis;
|
|
8474
|
-
};
|
|
8475
|
-
const getEventSizes = (schedulerDate, totalDays, startDate, endDate) => {
|
|
8476
|
-
if (!eventIsVisible(startDate, endDate, schedulerDate, totalDays)) {
|
|
8477
|
-
return {
|
|
8478
|
-
left: 0,
|
|
8479
|
-
width: 0,
|
|
8480
|
-
};
|
|
8481
|
-
}
|
|
8482
|
-
const totalHours = totalDays * 24;
|
|
8483
|
-
// const dateString = schedulerDate.toISOString().split('T')[0];
|
|
8484
|
-
//const schedulerDateAtZero = new Date(dateString)
|
|
8485
|
-
let startHours = hoursBetween(schedulerDate, startDate);
|
|
8486
|
-
let durationHours = hoursBetween(startDate, endDate);
|
|
8487
|
-
const startOutOfScheduler = startHours < 0;
|
|
8488
|
-
if (startOutOfScheduler) {
|
|
8489
|
-
durationHours += startHours;
|
|
8490
|
-
startHours = 0;
|
|
8491
|
-
}
|
|
8492
|
-
const left = (startHours / totalHours) * 100;
|
|
8493
|
-
// Minimum width equivalent to 15 minutes so zero/near-zero duration events stay visible
|
|
8494
|
-
const MIN_WIDTH_HOURS = 0.25;
|
|
8495
|
-
const minWidth = (MIN_WIDTH_HOURS * 100) / totalHours;
|
|
8496
|
-
const width = Math.max((durationHours * 100) / totalHours, minWidth);
|
|
8497
|
-
return {
|
|
8498
|
-
left,
|
|
8499
|
-
width,
|
|
8500
|
-
};
|
|
8501
|
-
};
|
|
8502
|
-
|
|
8503
8561
|
function getLinesByDivisions(headerDivision, _) {
|
|
8504
8562
|
const lines = headerDivision.flatMap((division) => division.bottom.map((_, i) => ({ isDayBoundary: i === 0 })));
|
|
8505
8563
|
const left = 100 / lines.length;
|
|
@@ -8555,8 +8613,65 @@ const getNow = (isUtc) => {
|
|
|
8555
8613
|
};
|
|
8556
8614
|
const milliSecondsInSecond = 1000;
|
|
8557
8615
|
const refreshMilliSeconds = 45 * milliSecondsInSecond;
|
|
8616
|
+
const EMPTY_EVENTS = [];
|
|
8617
|
+
const EMPTY_BG_EVENTS = [];
|
|
8618
|
+
const EMPTY_INDICATORS = [];
|
|
8619
|
+
// Memoised row body. Receives flat props (the per-row buckets are looked up
|
|
8620
|
+
// by the outer Row wrapper). As long as those bucket arrays keep their
|
|
8621
|
+
// reference (see `groupByRowIdStable`) and the rest of the render-context
|
|
8622
|
+
// values are stable, this row will skip re-rendering on selection clicks
|
|
8623
|
+
// that don't affect it.
|
|
8624
|
+
const RowContent = React__default.memo(function RowContent(props) {
|
|
8625
|
+
const header = {
|
|
8626
|
+
value: props.row,
|
|
8627
|
+
width: props.rowHeaderWidth,
|
|
8628
|
+
onEvent: props.onEvent,
|
|
8629
|
+
};
|
|
8630
|
+
return (jsx("div", { style: {
|
|
8631
|
+
...props.style,
|
|
8632
|
+
backgroundColor: props.rowColor
|
|
8633
|
+
}, 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));
|
|
8634
|
+
});
|
|
8635
|
+
// Outer (unmemoised) row: looks up per-row buckets from the shared `data`
|
|
8636
|
+
// object and forwards them as flat props to `RowContent`. Because the
|
|
8637
|
+
// referenced arrays are reused when their contents are unchanged
|
|
8638
|
+
// (see `groupByRowIdStable`), `RowContent.memo` will skip the work.
|
|
8639
|
+
const Row = ({ index, style, data }) => {
|
|
8640
|
+
const row = data.rows[index];
|
|
8641
|
+
const rowColor = data.groupRowColors
|
|
8642
|
+
? Math.floor(index / 2) % 2 === 0 ? data.evenColor : data.oddColor
|
|
8643
|
+
: index % 2 === 0 ? data.evenColor : data.oddColor;
|
|
8644
|
+
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: data.rowHeightRem, weekendLines: data.weekendLines, divisionLines: data.divisionLines, timeLinePercentage: data.timeLinePercentage, selectedDate: data.selectedDate, visibleDays: data.visibleDays, contextMenuItems: data.contextMenuItems, onEvent: data.onEvent }));
|
|
8645
|
+
};
|
|
8646
|
+
// Bucket items by rowId, but reuse previous bucket arrays whenever a row's
|
|
8647
|
+
// contents have not changed. Keeping bucket references stable is essential
|
|
8648
|
+
// for `RowContent.memo` to skip work when only one row's events change
|
|
8649
|
+
// (e.g. on selection clicks).
|
|
8650
|
+
const groupByRowIdStable = (items, prev) => {
|
|
8651
|
+
const next = new Map();
|
|
8652
|
+
for (const item of items) {
|
|
8653
|
+
const bucket = next.get(item.rowId);
|
|
8654
|
+
if (bucket) {
|
|
8655
|
+
bucket.push(item);
|
|
8656
|
+
}
|
|
8657
|
+
else {
|
|
8658
|
+
next.set(item.rowId, [item]);
|
|
8659
|
+
}
|
|
8660
|
+
}
|
|
8661
|
+
if (!prev)
|
|
8662
|
+
return next;
|
|
8663
|
+
for (const [rowId, bucket] of next) {
|
|
8664
|
+
const prevBucket = prev.get(rowId);
|
|
8665
|
+
if (prevBucket
|
|
8666
|
+
&& prevBucket.length === bucket.length
|
|
8667
|
+
&& prevBucket.every((v, i) => v === bucket[i])) {
|
|
8668
|
+
next.set(rowId, prevBucket);
|
|
8669
|
+
}
|
|
8670
|
+
}
|
|
8671
|
+
return next;
|
|
8672
|
+
};
|
|
8558
8673
|
const Scheduler = (props) => {
|
|
8559
|
-
const { header: headerContent, id, events: eventsState, backgroundEvents, contextMenuItems, EventComp, RowTitleComp, orderCategories = ["title"], useOrderCategory, onEvent, groupRowColors, rowHeaderWidth = 180, rowHeightRem = 1.75, } = props;
|
|
8674
|
+
const { header: headerContent, id, events: eventsState, backgroundEvents, indicatorRows: allIndicatorRows = [], contextMenuItems, EventComp, RowTitleComp, orderCategories = ["title"], useOrderCategory, onEvent, groupRowColors, rowHeaderWidth = 180, rowHeightRem = 1.75, } = props;
|
|
8560
8675
|
const BackgroundEventComp = props.BackgroundEventComp ?? BackgroundEvent;
|
|
8561
8676
|
const rows = useOrderCategory === false
|
|
8562
8677
|
? props.rows
|
|
@@ -8564,21 +8679,49 @@ const Scheduler = (props) => {
|
|
|
8564
8679
|
const instanceRef = useRef(null);
|
|
8565
8680
|
// const rowHeaderWidth = "180px";
|
|
8566
8681
|
const { selectedDate, visibleDays, isUtc, isHeaderVisible, visibleRows: stateVisibleRows } = props.state;
|
|
8567
|
-
const events = filterVisibleEvents(eventsState, selectedDate, visibleDays);
|
|
8682
|
+
const events = useMemo(() => filterVisibleEvents(eventsState, selectedDate, visibleDays), [eventsState, selectedDate, visibleDays]);
|
|
8568
8683
|
useEffect(() => {
|
|
8569
8684
|
instanceRef.current?.resetAfterIndex(0);
|
|
8570
|
-
}, [orderCategories, props.rows.length, events]);
|
|
8571
|
-
|
|
8572
|
-
|
|
8685
|
+
}, [orderCategories, props.rows.length, events, allIndicatorRows]);
|
|
8686
|
+
// Bucket events / backgroundEvents / indicatorRows by rowId once per render
|
|
8687
|
+
// instead of running events.filter() per row inside the row renderer.
|
|
8688
|
+
// Reuse previous bucket arrays when their contents are unchanged so the
|
|
8689
|
+
// memoised RowContent below can skip work (essential for selection clicks
|
|
8690
|
+
// to be cheap).
|
|
8691
|
+
const eventsByRowRef = useRef();
|
|
8692
|
+
const backgroundEventsByRowRef = useRef();
|
|
8693
|
+
const indicatorRowsByRowRef = useRef();
|
|
8694
|
+
const eventsByRow = useMemo(() => {
|
|
8695
|
+
const next = groupByRowIdStable(events, eventsByRowRef.current);
|
|
8696
|
+
eventsByRowRef.current = next;
|
|
8697
|
+
return next;
|
|
8698
|
+
}, [events]);
|
|
8699
|
+
const backgroundEventsByRow = useMemo(() => {
|
|
8700
|
+
const next = groupByRowIdStable(backgroundEvents, backgroundEventsByRowRef.current);
|
|
8701
|
+
backgroundEventsByRowRef.current = next;
|
|
8702
|
+
return next;
|
|
8703
|
+
}, [backgroundEvents]);
|
|
8704
|
+
const indicatorRowsByRow = useMemo(() => {
|
|
8705
|
+
const next = groupByRowIdStable(allIndicatorRows, indicatorRowsByRowRef.current);
|
|
8706
|
+
indicatorRowsByRowRef.current = next;
|
|
8707
|
+
return next;
|
|
8708
|
+
}, [allIndicatorRows]);
|
|
8709
|
+
const totalHeightRem = rows.reduce((acc, row) => {
|
|
8710
|
+
const filteredEvents = eventsByRow.get(row.rowId) ?? [];
|
|
8573
8711
|
const innerRows = separateEventsToInnerRows(filteredEvents);
|
|
8574
|
-
|
|
8712
|
+
const eventHeight = Math.max(innerRows.length, 1) * rowHeightRem;
|
|
8713
|
+
const hasIndicators = indicatorRowsByRow.has(row.rowId);
|
|
8714
|
+
return acc + eventHeight + (hasIndicators ? INDICATOR_HEIGHT_REM : 0);
|
|
8575
8715
|
}, 0);
|
|
8576
|
-
const
|
|
8716
|
+
const schedulerContentHeight = stateVisibleRows != null
|
|
8717
|
+
? Math.min(totalHeightRem, stateVisibleRows * rowHeightRem)
|
|
8718
|
+
: Math.max(totalHeightRem, rowHeightRem);
|
|
8577
8719
|
const totalHours = visibleDays * 24;
|
|
8578
8720
|
const [timeLinePercentage, setTimeLinePercentage] = useState(0);
|
|
8721
|
+
const divisions = useMemo(() => getDefaultDivisions(visibleDays, selectedDate), [visibleDays, selectedDate]);
|
|
8579
8722
|
const header = {
|
|
8580
8723
|
content: headerContent,
|
|
8581
|
-
divisions
|
|
8724
|
+
divisions,
|
|
8582
8725
|
visibleDays: visibleDays,
|
|
8583
8726
|
width: rowHeaderWidth,
|
|
8584
8727
|
selectedDate,
|
|
@@ -8588,9 +8731,8 @@ const Scheduler = (props) => {
|
|
|
8588
8731
|
};
|
|
8589
8732
|
const evenColor = "var(--cw-color-surface-container-low)";
|
|
8590
8733
|
const oddColor = "var(--cw-color-surface-container)";
|
|
8591
|
-
const
|
|
8592
|
-
const
|
|
8593
|
-
const divisionLines = getLinesByDivisions(header.divisions);
|
|
8734
|
+
const weekendsLines = useMemo(() => getWeekendLinesByDatesVisible(selectedDate, visibleDays), [selectedDate, visibleDays]);
|
|
8735
|
+
const divisionLines = useMemo(() => getLinesByDivisions(divisions), [divisions, visibleDays]);
|
|
8594
8736
|
// Timeline percentage calculation
|
|
8595
8737
|
useEffect(() => {
|
|
8596
8738
|
const updateTimeLinePercentage = () => {
|
|
@@ -8601,30 +8743,55 @@ const Scheduler = (props) => {
|
|
|
8601
8743
|
const interval = setInterval(updateTimeLinePercentage, refreshMilliSeconds);
|
|
8602
8744
|
return () => clearInterval(interval);
|
|
8603
8745
|
}, [selectedDate, isUtc, totalHours]);
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
|
|
8746
|
+
const itemData = useMemo(() => ({
|
|
8747
|
+
rows,
|
|
8748
|
+
eventsByRow,
|
|
8749
|
+
backgroundEventsByRow,
|
|
8750
|
+
indicatorRowsByRow,
|
|
8751
|
+
EventComp: EventComp,
|
|
8752
|
+
BackgroundEventComp,
|
|
8753
|
+
RowTitleComp: RowTitleComp,
|
|
8754
|
+
rowHeaderWidth,
|
|
8755
|
+
rowHeightRem,
|
|
8756
|
+
weekendLines: weekendsLines,
|
|
8757
|
+
divisionLines,
|
|
8758
|
+
timeLinePercentage,
|
|
8759
|
+
selectedDate,
|
|
8760
|
+
visibleDays,
|
|
8761
|
+
contextMenuItems,
|
|
8762
|
+
onEvent,
|
|
8763
|
+
groupRowColors,
|
|
8764
|
+
evenColor,
|
|
8765
|
+
oddColor,
|
|
8766
|
+
}), [
|
|
8767
|
+
rows,
|
|
8768
|
+
eventsByRow,
|
|
8769
|
+
backgroundEventsByRow,
|
|
8770
|
+
indicatorRowsByRow,
|
|
8771
|
+
EventComp,
|
|
8772
|
+
BackgroundEventComp,
|
|
8773
|
+
RowTitleComp,
|
|
8774
|
+
rowHeaderWidth,
|
|
8775
|
+
rowHeightRem,
|
|
8776
|
+
weekendsLines,
|
|
8777
|
+
divisionLines,
|
|
8778
|
+
timeLinePercentage,
|
|
8779
|
+
selectedDate,
|
|
8780
|
+
visibleDays,
|
|
8781
|
+
contextMenuItems,
|
|
8782
|
+
onEvent,
|
|
8783
|
+
groupRowColors,
|
|
8784
|
+
]);
|
|
8620
8785
|
const getItemSize = useCallback((index) => {
|
|
8621
8786
|
const row = rows[index];
|
|
8622
|
-
const filteredEvents =
|
|
8787
|
+
const filteredEvents = eventsByRow.get(row.rowId) ?? [];
|
|
8623
8788
|
const innerRows = separateEventsToInnerRows(filteredEvents);
|
|
8624
8789
|
const rowsNumber = innerRows.length > 0 ? innerRows.length : 1;
|
|
8625
8790
|
const pixelsInRem = 16;
|
|
8626
|
-
|
|
8627
|
-
|
|
8791
|
+
const hasIndicators = indicatorRowsByRow.has(row.rowId);
|
|
8792
|
+
const indicatorPixels = hasIndicators ? INDICATOR_HEIGHT_REM * pixelsInRem : 0;
|
|
8793
|
+
return rowsNumber * rowHeightRem * pixelsInRem + indicatorPixels;
|
|
8794
|
+
}, [rows, eventsByRow, indicatorRowsByRow, rowHeightRem]);
|
|
8628
8795
|
// Render
|
|
8629
8796
|
return (jsxs("div", { id: id, style: {
|
|
8630
8797
|
position: "relative",
|
|
@@ -8635,7 +8802,7 @@ const Scheduler = (props) => {
|
|
|
8635
8802
|
position: "sticky",
|
|
8636
8803
|
top: 0,
|
|
8637
8804
|
zIndex: 1,
|
|
8638
|
-
}, children: jsx(SchedulerHeader, { ...header }) })), jsx(VariableSizeList, { height: schedulerContentHeight * 16, itemCount: rows.length, itemSize: getItemSize, width: "100%", style: { overflowX: "hidden" }, ref: instanceRef, className: styles$2["hide-scrollbar"], children: Row })] }));
|
|
8805
|
+
}, children: jsx(SchedulerHeader, { ...header }) })), jsx(VariableSizeList, { height: schedulerContentHeight * 16, itemCount: rows.length, itemSize: getItemSize, itemData: itemData, width: "100%", style: { overflowX: "hidden" }, ref: instanceRef, className: styles$2["hide-scrollbar"], children: Row })] }));
|
|
8639
8806
|
};
|
|
8640
8807
|
|
|
8641
8808
|
class UiEvent {
|
|
@@ -8998,13 +9165,13 @@ const PinRowHeader = ({ value, width, onEvent }) => {
|
|
|
8998
9165
|
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);
|
|
8999
9166
|
};
|
|
9000
9167
|
|
|
9001
|
-
const SuperScheduler = ({ id, state, header, rows, events, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, contextMenuItems, onEvent, rowHeightRem = 1.75 }) => {
|
|
9168
|
+
const SuperScheduler = ({ id, state, header, rows, events, pinnedOrderCategory, unPinnedOrderCategory, backgroundEvents, indicatorRows = [], contextMenuItems, onEvent, rowHeightRem = 1.75 }) => {
|
|
9002
9169
|
const pinnedRows = rows.filter((it) => it.isPinned);
|
|
9003
9170
|
const notPinnedRows = rows.filter((it) => !it.isPinned);
|
|
9004
9171
|
const isFirstVisible = pinnedRows.length > 0;
|
|
9005
|
-
return (jsxs(Fragment, { children: [isFirstVisible && (jsxs(Fragment, { children: [jsx(Scheduler, { id: `${id}-pinned`, state: state, header: header, rows: pinnedRows, events: events, backgroundEvents: backgroundEvents, contextMenuItems: contextMenuItems, orderCategories: pinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: PinRowHeader, rowHeightRem: rowHeightRem }), jsx("div", { children: jsx(CwButton, { onClick: () => {
|
|
9172
|
+
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: PinRowHeader, rowHeightRem: rowHeightRem }), jsx("div", { children: jsx(CwButton, { onClick: () => {
|
|
9006
9173
|
onEvent(new OnClearPinned());
|
|
9007
|
-
}, children: "Clear pinned" }) })] })), jsx(Scheduler, { id: `${id}-notPinned`, state: { ...state, isHeaderVisible: !isFirstVisible }, header: header, rows: notPinnedRows, events: events, backgroundEvents: backgroundEvents, contextMenuItems: contextMenuItems, orderCategories: unPinnedOrderCategory, onEvent: onEvent, EventComp: SchedulerEvent, RowTitleComp: PinRowHeader, rowHeightRem: rowHeightRem })] }));
|
|
9174
|
+
}, 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: PinRowHeader, rowHeightRem: rowHeightRem })] }));
|
|
9008
9175
|
};
|
|
9009
9176
|
|
|
9010
9177
|
const CwFindAirport = ({ handleChange, searchType = "OnlyDatabase", placeHolder = "Search airport…", required = false, cblConfig, className = "", value, disabled = false, displayMode, initialDisplayText, labelProps, alignProps, width }) => {
|