@poirazis/supercomponents-shared 1.0.26 → 1.0.28
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.js +19311 -18109
- package/dist/index.umd.cjs +12 -12
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/lib/SuperButton/SuperButton.svelte +20 -5
- package/src/lib/SuperField/SuperField.svelte +10 -1
- package/src/lib/SuperTable/SuperTable.css +14 -10
- package/src/lib/SuperTable/SuperTable.svelte +39 -30
- package/src/lib/SuperTable/controls/ColumnsSection.svelte +1 -1
- package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +16 -11
- package/src/lib/SuperTable/controls/SelectionColumn.svelte +85 -60
- package/src/lib/SuperTable/overlays/ScrollbarsOverlay.svelte +1 -1
- package/src/lib/SuperTableCells/CellBoolean.svelte +36 -28
- package/src/lib/SuperTableCells/CellCommon.css +84 -19
- package/src/lib/SuperTableCells/CellDateRange.svelte +597 -0
- package/src/lib/SuperTableCells/CellDatetime.svelte +161 -8
- package/src/lib/SuperTableCells/CellLink.svelte +36 -14
- package/src/lib/SuperTableCells/CellLinkPickerSelect.svelte +9 -9
- package/src/lib/SuperTableCells/CellNumber.svelte +67 -40
- package/src/lib/SuperTableCells/CellOptions.svelte +12 -9
- package/src/lib/SuperTableCells/CellString.svelte +12 -8
- package/src/lib/SuperTableCells/index.js +1 -1
- package/src/lib/SuperTableColumn/SuperTableColumn.svelte +4 -0
- package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +36 -23
- package/src/lib/SuperTree/SuperTree.svelte +2 -2
- package/src/lib/SuperTableCells/CellLinkPickerTable.svelte +0 -91
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { createEventDispatcher, getContext, onMount } from "svelte";
|
|
3
|
+
import SuperPopover from "../SuperPopover/SuperPopover.svelte";
|
|
4
|
+
import { DatePicker } from "date-picker-svelte";
|
|
5
|
+
const dispatch = new createEventDispatcher();
|
|
6
|
+
const { processStringSync } = getContext("sdk");
|
|
7
|
+
import fsm from "svelte-fsm";
|
|
8
|
+
|
|
9
|
+
export let value;
|
|
10
|
+
export let formattedValue;
|
|
11
|
+
export let cellOptions;
|
|
12
|
+
export let autofocus;
|
|
13
|
+
|
|
14
|
+
let originalValue;
|
|
15
|
+
|
|
16
|
+
export let cellState = fsm("View", {
|
|
17
|
+
"*": {
|
|
18
|
+
goTo(state) {
|
|
19
|
+
return state;
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
View: {
|
|
23
|
+
focus() {
|
|
24
|
+
if (!cellOptions.readonly) return "Editing";
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
Hovered: {
|
|
28
|
+
cancel: () => {
|
|
29
|
+
return "View";
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
Focused: {
|
|
33
|
+
unfocus() {
|
|
34
|
+
return "View";
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
Error: { check: "View" },
|
|
38
|
+
Editing: {
|
|
39
|
+
_enter() {
|
|
40
|
+
originalValue = value ? { ...value } : null;
|
|
41
|
+
open = true;
|
|
42
|
+
dispatch("enteredit");
|
|
43
|
+
},
|
|
44
|
+
_exit() {
|
|
45
|
+
dispatch("exitedit");
|
|
46
|
+
},
|
|
47
|
+
handleKeyboard(e) {
|
|
48
|
+
if (e.keyCode == 32) {
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
open = !open;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
focusout(e) {
|
|
55
|
+
const isInPicker = picker?.contains(e.relatedTarget);
|
|
56
|
+
const isInFromTime = fromTimePicker?.contains
|
|
57
|
+
? fromTimePicker?.contains(e.relatedTarget)
|
|
58
|
+
: false;
|
|
59
|
+
const isInToTime = toTimePicker?.contains
|
|
60
|
+
? toTimePicker?.contains(e.relatedTarget)
|
|
61
|
+
: false;
|
|
62
|
+
|
|
63
|
+
if (!isInPicker && !isInFromTime && !isInToTime) {
|
|
64
|
+
open = false;
|
|
65
|
+
if (JSON.stringify(value) != JSON.stringify(originalValue)) {
|
|
66
|
+
dispatch("change", value);
|
|
67
|
+
}
|
|
68
|
+
return "View";
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
cancel() {
|
|
72
|
+
value = originalValue ? { ...originalValue } : null;
|
|
73
|
+
return "View";
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
let anchor;
|
|
79
|
+
let picker;
|
|
80
|
+
let popup;
|
|
81
|
+
let open = false;
|
|
82
|
+
let fromPicker;
|
|
83
|
+
let toPicker;
|
|
84
|
+
let fromTimePicker;
|
|
85
|
+
let toTimePicker;
|
|
86
|
+
|
|
87
|
+
// Current date format and showTime - extracted to ensure reactivity
|
|
88
|
+
$: currentDateFormat = cellOptions?.dateFormat;
|
|
89
|
+
$: currentShowTime = cellOptions?.showTime;
|
|
90
|
+
|
|
91
|
+
// Time values (format: HH:mm)
|
|
92
|
+
$: fromTime = currentShowTime && value?.fromTime ? value.fromTime : "00:00";
|
|
93
|
+
$: toTime = currentShowTime && value?.toTime ? value.toTime : "00:00";
|
|
94
|
+
|
|
95
|
+
$: fromDate = value?.from ? new Date(value.from) : new Date();
|
|
96
|
+
$: toDate = value?.to ? new Date(value.to) : new Date();
|
|
97
|
+
|
|
98
|
+
// Combine date and time for validation
|
|
99
|
+
$: fromDateTime =
|
|
100
|
+
currentShowTime && value?.from
|
|
101
|
+
? new Date(`${fromDate.toISOString().split("T")[0]}T${fromTime}`)
|
|
102
|
+
: fromDate;
|
|
103
|
+
$: toDateTime =
|
|
104
|
+
currentShowTime && value?.to
|
|
105
|
+
? new Date(`${toDate.toISOString().split("T")[0]}T${toTime}`)
|
|
106
|
+
: toDate;
|
|
107
|
+
|
|
108
|
+
// DateTime formatting helper function
|
|
109
|
+
function formatDateRangeWithTime(
|
|
110
|
+
fromDate,
|
|
111
|
+
toDate,
|
|
112
|
+
dateFormat,
|
|
113
|
+
fromTime,
|
|
114
|
+
toTime,
|
|
115
|
+
showTime
|
|
116
|
+
) {
|
|
117
|
+
if (!showTime) {
|
|
118
|
+
return {
|
|
119
|
+
from: formatDateRange(fromDate, fromDate, dateFormat).from,
|
|
120
|
+
to: formatDateRange(toDate, toDate, dateFormat).to,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const fromFormatted =
|
|
125
|
+
formatDateRange(fromDate, fromDate, dateFormat).from + " " + fromTime;
|
|
126
|
+
const toFormatted =
|
|
127
|
+
formatDateRange(toDate, toDate, dateFormat).to + " " + toTime;
|
|
128
|
+
|
|
129
|
+
return { from: fromFormatted, to: toFormatted };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Date formatting helper function
|
|
133
|
+
function formatDateRange(fromDate, toDate, dateFormat) {
|
|
134
|
+
console.log("🔍 formatDateRange called with:", {
|
|
135
|
+
fromDate,
|
|
136
|
+
toDate,
|
|
137
|
+
dateFormat,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (!dateFormat || dateFormat === "default") {
|
|
141
|
+
console.log("➡️ Using default format");
|
|
142
|
+
return {
|
|
143
|
+
from: fromDate.toDateString(),
|
|
144
|
+
to: toDate.toDateString(),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Manual formatting for specific formats to ensure exact order
|
|
149
|
+
if (dateFormat === "MM/DD/YYYY") {
|
|
150
|
+
const fromFormatted = `${(fromDate.getMonth() + 1).toString().padStart(2, "0")}/${fromDate.getDate().toString().padStart(2, "0")}/${fromDate.getFullYear()}`;
|
|
151
|
+
const toFormatted = `${(toDate.getMonth() + 1).toString().padStart(2, "0")}/${toDate.getDate().toString().padStart(2, "0")}/${toDate.getFullYear()}`;
|
|
152
|
+
console.log("✅ MM/DD/YYYY formatted:", {
|
|
153
|
+
from: fromFormatted,
|
|
154
|
+
to: toFormatted,
|
|
155
|
+
});
|
|
156
|
+
return { from: fromFormatted, to: toFormatted };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (dateFormat === "DD/MM/YYYY") {
|
|
160
|
+
const fromFormatted = `${fromDate.getDate().toString().padStart(2, "0")}/${(fromDate.getMonth() + 1).toString().padStart(2, "0")}/${fromDate.getFullYear()}`;
|
|
161
|
+
const toFormatted = `${toDate.getDate().toString().padStart(2, "0")}/${(toDate.getMonth() + 1).toString().padStart(2, "0")}/${toDate.getFullYear()}`;
|
|
162
|
+
console.log("✅ DD/MM/YYYY formatted:", {
|
|
163
|
+
from: fromFormatted,
|
|
164
|
+
to: toFormatted,
|
|
165
|
+
});
|
|
166
|
+
return { from: fromFormatted, to: toFormatted };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (dateFormat === "YYYY-MM-DD") {
|
|
170
|
+
const fromFormatted = `${fromDate.getFullYear()}-${(fromDate.getMonth() + 1).toString().padStart(2, "0")}-${fromDate.getDate().toString().padStart(2, "0")}`;
|
|
171
|
+
const toFormatted = `${toDate.getFullYear()}-${(toDate.getMonth() + 1).toString().padStart(2, "0")}-${toDate.getDate().toString().padStart(2, "0")}`;
|
|
172
|
+
console.log("✅ YYYY-MM-DD formatted:", {
|
|
173
|
+
from: fromFormatted,
|
|
174
|
+
to: toFormatted,
|
|
175
|
+
});
|
|
176
|
+
return { from: fromFormatted, to: toFormatted };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// For shorter formats, still use locale-specific formatting
|
|
180
|
+
const options = {
|
|
181
|
+
"MMM DD, YYYY": {
|
|
182
|
+
month: "short",
|
|
183
|
+
day: "numeric",
|
|
184
|
+
year: "numeric",
|
|
185
|
+
timeZone: "UTC",
|
|
186
|
+
},
|
|
187
|
+
"DD MMM YYYY": {
|
|
188
|
+
day: "numeric",
|
|
189
|
+
month: "short",
|
|
190
|
+
year: "numeric",
|
|
191
|
+
timeZone: "UTC",
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const format = options[dateFormat];
|
|
196
|
+
console.log("📅 Format object:", format);
|
|
197
|
+
|
|
198
|
+
if (format) {
|
|
199
|
+
const fromFormatted = fromDate.toLocaleDateString("en-US", format);
|
|
200
|
+
const toFormatted = toDate.toLocaleDateString("en-US", format);
|
|
201
|
+
console.log("✅ Formatted result:", {
|
|
202
|
+
from: fromFormatted,
|
|
203
|
+
to: toFormatted,
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
from: fromFormatted,
|
|
207
|
+
to: toFormatted,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
console.log("⚠️ Format not found, using fallback");
|
|
212
|
+
// Fallback to default
|
|
213
|
+
return {
|
|
214
|
+
from: fromDate.toDateString(),
|
|
215
|
+
to: toDate.toDateString(),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Ensure range is valid (from date shouldn't be after to date)
|
|
220
|
+
$: isValidRange = (() => {
|
|
221
|
+
if (!value?.from || !value?.to) return true;
|
|
222
|
+
if (currentShowTime) {
|
|
223
|
+
return fromDateTime <= toDateTime;
|
|
224
|
+
}
|
|
225
|
+
return fromDate <= toDate;
|
|
226
|
+
})();
|
|
227
|
+
|
|
228
|
+
$: formattedValue =
|
|
229
|
+
cellOptions.template && value
|
|
230
|
+
? processStringSync(cellOptions.template, { value })
|
|
231
|
+
: undefined;
|
|
232
|
+
|
|
233
|
+
$: rangeDisplay = (() => {
|
|
234
|
+
if (formattedValue) return formattedValue;
|
|
235
|
+
if (!value?.from && !value?.to) return placeholder;
|
|
236
|
+
|
|
237
|
+
const dateFormat = currentDateFormat; // Use the extracted reactive format
|
|
238
|
+
let fromFormatted = placeholder;
|
|
239
|
+
let toFormatted = placeholder;
|
|
240
|
+
|
|
241
|
+
if (value?.from) {
|
|
242
|
+
if (dateFormat === "default" || !dateFormat) {
|
|
243
|
+
fromFormatted = currentShowTime
|
|
244
|
+
? fromDate.toDateString() + " " + fromTime
|
|
245
|
+
: fromDate.toDateString();
|
|
246
|
+
} else {
|
|
247
|
+
if (currentShowTime) {
|
|
248
|
+
const formatted = formatDateRangeWithTime(
|
|
249
|
+
fromDate,
|
|
250
|
+
fromDate,
|
|
251
|
+
dateFormat,
|
|
252
|
+
fromTime,
|
|
253
|
+
fromTime,
|
|
254
|
+
true
|
|
255
|
+
);
|
|
256
|
+
fromFormatted = formatted.from;
|
|
257
|
+
} else {
|
|
258
|
+
const formatted = formatDateRange(fromDate, fromDate, dateFormat);
|
|
259
|
+
fromFormatted = formatted.from;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (value?.to) {
|
|
265
|
+
if (dateFormat === "default" || !dateFormat) {
|
|
266
|
+
toFormatted = currentShowTime
|
|
267
|
+
? toDate.toDateString() + " " + toTime
|
|
268
|
+
: toDate.toDateString();
|
|
269
|
+
} else {
|
|
270
|
+
if (currentShowTime) {
|
|
271
|
+
const formatted = formatDateRangeWithTime(
|
|
272
|
+
toDate,
|
|
273
|
+
toDate,
|
|
274
|
+
dateFormat,
|
|
275
|
+
toTime,
|
|
276
|
+
toTime,
|
|
277
|
+
true
|
|
278
|
+
);
|
|
279
|
+
toFormatted = formatted.to;
|
|
280
|
+
} else {
|
|
281
|
+
const formatted = formatDateRange(toDate, toDate, dateFormat);
|
|
282
|
+
toFormatted = formatted.to;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (value?.from && value?.to) {
|
|
288
|
+
return `${fromFormatted} - ${toFormatted}`;
|
|
289
|
+
} else if (value?.from) {
|
|
290
|
+
return `${fromFormatted} - [Select end date]`;
|
|
291
|
+
} else if (value?.to) {
|
|
292
|
+
return `[Select start date] - ${toFormatted}`;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return placeholder;
|
|
296
|
+
})();
|
|
297
|
+
|
|
298
|
+
$: placeholder =
|
|
299
|
+
cellOptions.readonly || cellOptions.disabled
|
|
300
|
+
? ""
|
|
301
|
+
: cellOptions.placeholder || "Select date range";
|
|
302
|
+
|
|
303
|
+
$: inEdit = $cellState == "Editing";
|
|
304
|
+
$: inline = cellOptions.role == "inlineInput";
|
|
305
|
+
$: isDirty = inEdit && JSON.stringify(value) != JSON.stringify(originalValue);
|
|
306
|
+
|
|
307
|
+
onMount(() => {
|
|
308
|
+
if (autofocus)
|
|
309
|
+
setTimeout(() => {
|
|
310
|
+
cellState.focus();
|
|
311
|
+
}, 30);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const handleFromDateChange = (e) => {
|
|
315
|
+
const newFromDate = e.detail;
|
|
316
|
+
value = {
|
|
317
|
+
...value,
|
|
318
|
+
from: newFromDate,
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// If to date exists and is before from date, clear it
|
|
322
|
+
if (value.to && new Date(value.to) < newFromDate) {
|
|
323
|
+
value = {
|
|
324
|
+
...value,
|
|
325
|
+
to: null,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
dispatch("change", value);
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const handleToDateChange = (e) => {
|
|
333
|
+
const newToDate = e.detail;
|
|
334
|
+
value = {
|
|
335
|
+
...value,
|
|
336
|
+
to: newToDate,
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
dispatch("change", value);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const handleFromTimeChange = (e) => {
|
|
343
|
+
const newFromTime = e.target.value;
|
|
344
|
+
value = {
|
|
345
|
+
...value,
|
|
346
|
+
fromTime: newFromTime,
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
dispatch("change", value);
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const handleToTimeChange = (e) => {
|
|
353
|
+
const newToTime = e.target.value;
|
|
354
|
+
value = {
|
|
355
|
+
...value,
|
|
356
|
+
toTime: newToTime,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
dispatch("change", value);
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const clearRange = () => {
|
|
363
|
+
value = null;
|
|
364
|
+
dispatch("change", null);
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
$: console.log(cellOptions);
|
|
368
|
+
</script>
|
|
369
|
+
|
|
370
|
+
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
|
|
371
|
+
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
372
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
373
|
+
<div
|
|
374
|
+
bind:this={anchor}
|
|
375
|
+
class="superCell"
|
|
376
|
+
tabindex={cellOptions.readonly || cellOptions.disabled ? "-1" : "0"}
|
|
377
|
+
class:inEdit
|
|
378
|
+
class:isDirty={isDirty && cellOptions.showDirty}
|
|
379
|
+
class:inline
|
|
380
|
+
class:tableCell={cellOptions.role == "tableCell"}
|
|
381
|
+
class:formInput={cellOptions.role == "formInput"}
|
|
382
|
+
class:disabled={cellOptions.disabled}
|
|
383
|
+
class:readonly={cellOptions.readonly}
|
|
384
|
+
class:error={cellOptions.error}
|
|
385
|
+
style:color={cellOptions.color}
|
|
386
|
+
style:background={cellOptions.background}
|
|
387
|
+
style:font-weight={cellOptions.fontWeight}
|
|
388
|
+
on:focus={cellState.focus}
|
|
389
|
+
on:keypress={cellState.handleKeyboard}
|
|
390
|
+
on:focusout={cellState.focusout}
|
|
391
|
+
>
|
|
392
|
+
{#if cellOptions.icon}
|
|
393
|
+
<i class={cellOptions.icon + " icon"}></i>
|
|
394
|
+
{/if}
|
|
395
|
+
|
|
396
|
+
{#if inEdit}
|
|
397
|
+
<div
|
|
398
|
+
class="editor"
|
|
399
|
+
class:with-icon={cellOptions.icon}
|
|
400
|
+
class:placeholder={!value}
|
|
401
|
+
on:click={() => (open = !open)}
|
|
402
|
+
>
|
|
403
|
+
<span>{rangeDisplay}</span>
|
|
404
|
+
<i
|
|
405
|
+
class="ri-calendar-line"
|
|
406
|
+
style="font-size: 16px; justify-self: flex-end"
|
|
407
|
+
></i>
|
|
408
|
+
|
|
409
|
+
{#if value && cellOptions.showDirty != false}
|
|
410
|
+
<button
|
|
411
|
+
class="clear-button ri-close-line"
|
|
412
|
+
style="font-size: 14px; color: var(--spectrum-global-color-gray-500);"
|
|
413
|
+
on:click|stopPropagation={clearRange}
|
|
414
|
+
aria-label="Clear date range"
|
|
415
|
+
></button>
|
|
416
|
+
{/if}
|
|
417
|
+
</div>
|
|
418
|
+
{:else}
|
|
419
|
+
<div
|
|
420
|
+
class="value"
|
|
421
|
+
class:with-icon={cellOptions.icon}
|
|
422
|
+
class:placeholder={!value}
|
|
423
|
+
style:justify-content={cellOptions.align}
|
|
424
|
+
>
|
|
425
|
+
<span>
|
|
426
|
+
{#if rangeDisplay}
|
|
427
|
+
{rangeDisplay}
|
|
428
|
+
{:else}
|
|
429
|
+
{placeholder}
|
|
430
|
+
{/if}
|
|
431
|
+
</span>
|
|
432
|
+
</div>
|
|
433
|
+
{/if}
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
{#if inEdit}
|
|
437
|
+
<SuperPopover {anchor} dismissible={false} {open} align="right">
|
|
438
|
+
<div
|
|
439
|
+
bind:this={picker}
|
|
440
|
+
class="range-picker-container"
|
|
441
|
+
style:--date-picker-background="var(--spectrum-global-color-gray-75)"
|
|
442
|
+
style:--date-picker-foreground="var(--spectrum-global-color-gray-800)"
|
|
443
|
+
style:--date-picker-selected-background="var(--accent-color)"
|
|
444
|
+
>
|
|
445
|
+
<div class="datepickers-container">
|
|
446
|
+
<div class="range-section">
|
|
447
|
+
<!-- svelte-ignore a11y-label-has-associated-control -->
|
|
448
|
+
<label class="range-label">From:</label>
|
|
449
|
+
<div bind:this={fromPicker}>
|
|
450
|
+
<DatePicker value={fromDate} on:select={handleFromDateChange} />
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
{#if currentShowTime}
|
|
454
|
+
<div class="time-section">
|
|
455
|
+
<!-- svelte-ignore a11y-label-has-associated-control -->
|
|
456
|
+
<input
|
|
457
|
+
bind:this={fromTimePicker}
|
|
458
|
+
type="time"
|
|
459
|
+
bind:value={fromTime}
|
|
460
|
+
on:change={handleFromTimeChange}
|
|
461
|
+
class="time-input"
|
|
462
|
+
step="900"
|
|
463
|
+
/>
|
|
464
|
+
</div>
|
|
465
|
+
{/if}
|
|
466
|
+
</div>
|
|
467
|
+
|
|
468
|
+
<div class="range-section">
|
|
469
|
+
<!-- svelte-ignore a11y-label-has-associated-control -->
|
|
470
|
+
<label class="range-label">To:</label>
|
|
471
|
+
<div bind:this={toPicker}>
|
|
472
|
+
<DatePicker
|
|
473
|
+
value={toDate}
|
|
474
|
+
on:select={handleToDateChange}
|
|
475
|
+
min={fromDate}
|
|
476
|
+
/>
|
|
477
|
+
</div>
|
|
478
|
+
|
|
479
|
+
{#if currentShowTime}
|
|
480
|
+
<div class="time-section">
|
|
481
|
+
<!-- svelte-ignore a11y-label-has-associated-control -->
|
|
482
|
+
<input
|
|
483
|
+
bind:this={toTimePicker}
|
|
484
|
+
type="time"
|
|
485
|
+
bind:value={toTime}
|
|
486
|
+
on:change={handleToTimeChange}
|
|
487
|
+
class="time-input"
|
|
488
|
+
step="900"
|
|
489
|
+
/>
|
|
490
|
+
</div>
|
|
491
|
+
{/if}
|
|
492
|
+
</div>
|
|
493
|
+
</div>
|
|
494
|
+
|
|
495
|
+
{#if !isValidRange}
|
|
496
|
+
<div class="range-error">
|
|
497
|
+
<i
|
|
498
|
+
class="ri-error-warning-line"
|
|
499
|
+
style="color: var(--spectrum-global-color-red-500);"
|
|
500
|
+
></i>
|
|
501
|
+
<span
|
|
502
|
+
style="color: var(--spectrum-global-color-red-500); font-size: 12px;"
|
|
503
|
+
>
|
|
504
|
+
End date cannot be before start date
|
|
505
|
+
</span>
|
|
506
|
+
</div>
|
|
507
|
+
{/if}
|
|
508
|
+
</div>
|
|
509
|
+
</SuperPopover>
|
|
510
|
+
{/if}
|
|
511
|
+
|
|
512
|
+
<style>
|
|
513
|
+
.range-picker-container {
|
|
514
|
+
display: flex;
|
|
515
|
+
flex-direction: column;
|
|
516
|
+
gap: 1rem;
|
|
517
|
+
padding: 0.5rem;
|
|
518
|
+
min-width: 300px;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.datepickers-container {
|
|
522
|
+
display: flex;
|
|
523
|
+
flex-direction: row;
|
|
524
|
+
gap: 1rem;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.range-section {
|
|
528
|
+
display: flex;
|
|
529
|
+
flex-direction: column;
|
|
530
|
+
gap: 8px;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.range-label {
|
|
534
|
+
font-size: 14px;
|
|
535
|
+
font-weight: 500;
|
|
536
|
+
color: var(--spectrum-global-color-gray-800);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.time-section {
|
|
540
|
+
display: flex;
|
|
541
|
+
flex-direction: column;
|
|
542
|
+
gap: 4px;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.time-label {
|
|
546
|
+
font-size: 12px;
|
|
547
|
+
font-weight: 500;
|
|
548
|
+
color: var(--spectrum-global-color-gray-700);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
.time-input {
|
|
552
|
+
padding: 6px 8px;
|
|
553
|
+
border: 1px solid var(--spectrum-global-color-gray-300);
|
|
554
|
+
border-radius: 4px;
|
|
555
|
+
font-size: 14px;
|
|
556
|
+
min-width: 120px;
|
|
557
|
+
background: var(--spectrum-global-color-gray-50);
|
|
558
|
+
color: var(--spectrum-global-color-gray-800);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.time-input:focus {
|
|
562
|
+
outline: none;
|
|
563
|
+
border-color: var(--spectrum-global-color-blue-500);
|
|
564
|
+
box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.2);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.range-error {
|
|
568
|
+
display: flex;
|
|
569
|
+
align-items: center;
|
|
570
|
+
gap: 6px;
|
|
571
|
+
padding: 8px;
|
|
572
|
+
background: var(--spectrum-global-color-red-200);
|
|
573
|
+
border-radius: 4px;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
.clear-button {
|
|
577
|
+
background: none;
|
|
578
|
+
border: none;
|
|
579
|
+
cursor: pointer;
|
|
580
|
+
padding: 4px;
|
|
581
|
+
border-radius: 2px;
|
|
582
|
+
transition: all 0.2s ease;
|
|
583
|
+
margin-left: 8px;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.clear-button:hover {
|
|
587
|
+
background-color: var(--spectrum-global-color-gray-200);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.editor {
|
|
591
|
+
display: flex;
|
|
592
|
+
align-items: center;
|
|
593
|
+
justify-content: space-between;
|
|
594
|
+
cursor: pointer;
|
|
595
|
+
padding: 8px 4px;
|
|
596
|
+
}
|
|
597
|
+
</style>
|