@poirazis/supercomponents-shared 1.2.16 → 1.2.18
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 +17703 -22317
- package/dist/index.umd.cjs +19 -19
- package/package.json +11 -11
- package/src/lib/SuperButton/SuperButton.svelte +57 -22
- package/src/lib/SuperField/SuperField.svelte +0 -2
- package/src/lib/SuperForm/InnerForm.svelte +7 -8
- package/src/lib/SuperTable/SuperTable.css +13 -6
- package/src/lib/SuperTable/SuperTable.svelte +26 -15
- package/src/lib/SuperTable/constants.js +1 -1
- package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +33 -17
- package/src/lib/SuperTable/controls/SelectionColumn.svelte +2 -2
- package/src/lib/SuperTableCells/CellBoolean.svelte +52 -45
- package/src/lib/SuperTableCells/CellDatetime.svelte +268 -120
- package/src/lib/SuperTableCells/CellLink.svelte +16 -7
- package/src/lib/SuperTableCells/CellLinkPickerSelect.svelte +28 -24
- package/src/lib/SuperTableCells/CellLinkPickerTree.svelte +22 -20
- package/src/lib/SuperTableCells/CellNumber.svelte +55 -53
- package/src/lib/SuperTableCells/CellOptions.svelte +59 -32
- package/src/lib/SuperTableCells/CellOptionsAdvanced.svelte +131 -129
- package/src/lib/SuperTableCells/CellSQLLink.svelte +32 -32
- package/src/lib/SuperTableCells/CellSQLLinkPicker.svelte +2 -7
- package/src/lib/SuperTableCells/CellString.svelte +49 -47
- package/src/lib/SuperTableCells/CellStringMask.svelte +41 -40
- package/src/lib/SuperTableColumn/SuperTableColumn.svelte +2 -0
- package/src/lib/SuperTableColumn/parts/SuperColumnBody.svelte +3 -0
- package/src/lib/SuperTableColumn/parts/SuperColumnHeader.svelte +44 -42
- package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +1 -1
- package/src/lib/SuperTabs/SuperTabs.svelte +33 -17
- package/src/lib/UI/elements/Checkbox.svelte +68 -10
- package/src/lib/UI/elements/Switch.svelte +162 -0
- package/src/lib/UI/elements/Tooltip.svelte +15 -43
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { createEventDispatcher
|
|
2
|
+
import { createEventDispatcher } from "svelte";
|
|
3
3
|
import fsm from "svelte-fsm";
|
|
4
|
+
import Switch from "../UI/elements/Switch.svelte";
|
|
5
|
+
import Checkbox from "../UI/elements/Checkbox.svelte";
|
|
4
6
|
import "./CellCommon.css";
|
|
5
7
|
|
|
6
8
|
export let value;
|
|
@@ -21,20 +23,20 @@
|
|
|
21
23
|
View: {
|
|
22
24
|
focus() {
|
|
23
25
|
if (!cellOptions.readonly && !cellOptions.disabled) return "Editing";
|
|
24
|
-
editor?.focus();
|
|
25
26
|
},
|
|
26
27
|
},
|
|
27
28
|
Editing: {
|
|
28
29
|
_enter() {
|
|
29
30
|
originalValue = value;
|
|
30
|
-
editor?.focus();
|
|
31
31
|
dispatch("enteredit");
|
|
32
32
|
},
|
|
33
33
|
_exit() {
|
|
34
34
|
dispatch("exitedit");
|
|
35
35
|
},
|
|
36
|
-
focus() {
|
|
37
|
-
|
|
36
|
+
focus() {},
|
|
37
|
+
toggle() {
|
|
38
|
+
value = !value;
|
|
39
|
+
dispatch("change", value);
|
|
38
40
|
},
|
|
39
41
|
change(e) {
|
|
40
42
|
if (cellOptions.debounce) dispatch("change", value);
|
|
@@ -56,15 +58,10 @@
|
|
|
56
58
|
$: inline = cellOptions.role == "inlineInput";
|
|
57
59
|
$: inEdit = $cellState == "Editing";
|
|
58
60
|
$: isDirty = inEdit && originalValue !== value;
|
|
59
|
-
$: checkbox = cellOptions?.controlType == "checkbox";
|
|
60
61
|
$: tableCell = cellOptions.role == "tableCell";
|
|
61
62
|
$: inlineLabel = cellOptions.inlineLabel;
|
|
62
63
|
$: icon = cellOptions.error ? "ri-error-warning-line" : cellOptions.icon;
|
|
63
64
|
$: error = cellOptions.error;
|
|
64
|
-
|
|
65
|
-
const focus = (node) => {
|
|
66
|
-
if (cellOptions.role == "tableCell") node.focus();
|
|
67
|
-
};
|
|
68
65
|
</script>
|
|
69
66
|
|
|
70
67
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
@@ -72,6 +69,7 @@
|
|
|
72
69
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
73
70
|
<div
|
|
74
71
|
class="superCell"
|
|
72
|
+
tabindex={cellOptions.disabled || cellOptions.readonly ? undefined : "1"}
|
|
75
73
|
class:inEdit
|
|
76
74
|
class:isDirty={isDirty && cellOptions.showDirty}
|
|
77
75
|
class:inline
|
|
@@ -84,6 +82,11 @@
|
|
|
84
82
|
? "var(--spectrum-global-color-gray-50)"
|
|
85
83
|
: cellOptions.background}
|
|
86
84
|
style:font-weight={cellOptions.fontWeight}
|
|
85
|
+
on:keydown={(e) => {
|
|
86
|
+
if (e.code == "Space") cellState.toggle();
|
|
87
|
+
}}
|
|
88
|
+
on:focusin={cellState.focus}
|
|
89
|
+
on:focusout={cellState.submit}
|
|
87
90
|
>
|
|
88
91
|
{#if icon}
|
|
89
92
|
<i class={icon + " field-icon"} class:with-error={error}></i>
|
|
@@ -95,48 +98,40 @@
|
|
|
95
98
|
class:naked-field={!tableCell}
|
|
96
99
|
style:justify-content={cellOptions.align ?? "center"}
|
|
97
100
|
>
|
|
98
|
-
{#if
|
|
99
|
-
<div class="
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
bind:checked={value}
|
|
103
|
-
bind:this={editor}
|
|
104
|
-
type="checkbox"
|
|
101
|
+
{#if cellOptions.controlType == "switch"}
|
|
102
|
+
<div class="switch-wrapper">
|
|
103
|
+
<Switch
|
|
104
|
+
checked={value}
|
|
105
105
|
disabled={cellOptions.disabled || cellOptions.readonly}
|
|
106
|
-
|
|
107
|
-
on:
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
size="medium"
|
|
107
|
+
on:change={(e) => {
|
|
108
|
+
value = e.detail.checked;
|
|
109
|
+
cellState.change();
|
|
110
|
+
}}
|
|
110
111
|
/>
|
|
111
|
-
<span class="spectrum-Switch-switch"></span>
|
|
112
112
|
{#if inlineLabel}
|
|
113
|
-
<span class="
|
|
113
|
+
<span class="switch-label">{inlineLabel}</span>
|
|
114
114
|
{/if}
|
|
115
115
|
</div>
|
|
116
116
|
{:else}
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
<div class="checkbox-wrapper">
|
|
118
|
+
<Checkbox
|
|
119
|
+
checked={value}
|
|
120
|
+
size="medium"
|
|
121
|
+
disabled={cellOptions.disabled || cellOptions.readonly}
|
|
122
|
+
on:change={(e) => {
|
|
123
|
+
value = e.detail.checked;
|
|
124
|
+
cellState.change();
|
|
125
|
+
}}
|
|
126
|
+
/>
|
|
127
|
+
{#if inlineLabel}
|
|
128
|
+
<span class="checkbox-label">{inlineLabel}</span>
|
|
129
|
+
{/if}
|
|
130
|
+
</div>
|
|
131
131
|
{/if}
|
|
132
132
|
</div>
|
|
133
133
|
{:else}
|
|
134
|
-
<div
|
|
135
|
-
class="value"
|
|
136
|
-
tabIndex="0"
|
|
137
|
-
style:justify-content={cellOptions.align ?? "center"}
|
|
138
|
-
on:focusin={cellState.focus}
|
|
139
|
-
>
|
|
134
|
+
<div class="value" style:justify-content={cellOptions.align ?? "center"}>
|
|
140
135
|
{#if value}
|
|
141
136
|
<i class="ri-check-line valueicon"></i>
|
|
142
137
|
{:else if cellOptions.showFalse}
|
|
@@ -147,8 +142,20 @@
|
|
|
147
142
|
</div>
|
|
148
143
|
|
|
149
144
|
<style>
|
|
150
|
-
.
|
|
151
|
-
|
|
145
|
+
.switch-wrapper {
|
|
146
|
+
display: flex;
|
|
147
|
+
align-items: center;
|
|
148
|
+
gap: 0.5rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.checkbox-wrapper {
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
gap: 0.5rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.switch-label {
|
|
158
|
+
margin-left: 0.25rem;
|
|
152
159
|
}
|
|
153
160
|
|
|
154
161
|
.checkbox-label {
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
export let autofocus;
|
|
13
13
|
|
|
14
14
|
let originalValue;
|
|
15
|
+
let anchor;
|
|
16
|
+
let picker;
|
|
17
|
+
let timePicker;
|
|
18
|
+
let open;
|
|
19
|
+
let selection = false;
|
|
15
20
|
|
|
16
21
|
export let cellState = fsm("View", {
|
|
17
22
|
"*": {
|
|
@@ -20,6 +25,10 @@
|
|
|
20
25
|
},
|
|
21
26
|
},
|
|
22
27
|
View: {
|
|
28
|
+
_enter() {
|
|
29
|
+
open = false;
|
|
30
|
+
selection = false;
|
|
31
|
+
},
|
|
23
32
|
focus() {
|
|
24
33
|
if (!cellOptions.readonly) return "Editing";
|
|
25
34
|
},
|
|
@@ -33,125 +42,176 @@
|
|
|
33
42
|
_exit() {
|
|
34
43
|
dispatch("exitedit");
|
|
35
44
|
},
|
|
45
|
+
toggle(e) {
|
|
46
|
+
open = !open;
|
|
47
|
+
},
|
|
36
48
|
handleKeyboard(e) {
|
|
37
49
|
if (e.keyCode == 32) {
|
|
38
50
|
e.stopPropagation();
|
|
39
51
|
e.preventDefault();
|
|
40
52
|
open = !open;
|
|
41
53
|
}
|
|
54
|
+
|
|
55
|
+
if (e.code == "Delete" || e.code == "Backspace") {
|
|
56
|
+
e.stopPropagation();
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
value = null;
|
|
59
|
+
dispatch("change", value);
|
|
60
|
+
}
|
|
42
61
|
},
|
|
43
62
|
focusout(e) {
|
|
44
63
|
const isInPicker = picker?.contains(e.relatedTarget);
|
|
45
64
|
const isInTimePicker = timePicker?.contains(e.relatedTarget);
|
|
46
65
|
|
|
66
|
+
if (isInPicker || isInTimePicker) return;
|
|
67
|
+
|
|
47
68
|
if (!isInPicker && !isInTimePicker) {
|
|
48
69
|
open = false;
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
let outputValue = innerDate.toISOString();
|
|
71
|
+
if (!currentShowTime) {
|
|
72
|
+
outputValue = innerDate.toLocaleDateString("en-CA"); // YYYY-MM-DD format without time
|
|
51
73
|
}
|
|
74
|
+
|
|
75
|
+
if (ignoreTimeZone) {
|
|
76
|
+
outputValue = innerDate.toISOString().slice(0, -1);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (selection) dispatch("change", outputValue);
|
|
52
80
|
return "View";
|
|
53
81
|
}
|
|
54
82
|
},
|
|
83
|
+
submit() {
|
|
84
|
+
dispatch("change", innerDate.toISOString());
|
|
85
|
+
return "View";
|
|
86
|
+
},
|
|
55
87
|
cancel() {
|
|
56
|
-
value =
|
|
57
|
-
? [...originalValue]
|
|
58
|
-
: originalValue;
|
|
88
|
+
value = originalValue;
|
|
59
89
|
return "View";
|
|
60
90
|
},
|
|
61
91
|
},
|
|
62
92
|
});
|
|
63
93
|
|
|
64
|
-
let anchor;
|
|
65
|
-
let picker;
|
|
66
|
-
let timePicker;
|
|
67
|
-
let open;
|
|
68
|
-
|
|
69
94
|
// Current date format and showTime - extracted to ensure reactivity
|
|
70
95
|
$: currentDateFormat = cellOptions?.dateFormat;
|
|
71
96
|
$: currentShowTime = cellOptions?.showTime;
|
|
97
|
+
$: ignoreTimeZone = cellOptions?.ignoreTimezone;
|
|
98
|
+
$: show24HTime = cellOptions?.show24HTime;
|
|
99
|
+
$: innerDate = parseValueToDate(value);
|
|
100
|
+
$: timeValue = innerDate.toLocaleTimeString("en-US", {
|
|
101
|
+
hour12: !show24HTime,
|
|
102
|
+
hour: "2-digit",
|
|
103
|
+
minute: "2-digit",
|
|
104
|
+
});
|
|
72
105
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
106
|
+
// Helper function to create a Date object that properly handles UTC when ignoreTimezone is true
|
|
107
|
+
function parseValueToDate(valueStr) {
|
|
108
|
+
if (!valueStr) return new Date();
|
|
109
|
+
if (valueStr instanceof Date) {
|
|
110
|
+
valueStr = valueStr;
|
|
111
|
+
}
|
|
76
112
|
|
|
77
|
-
|
|
78
|
-
function getTimeFromValue() {
|
|
79
|
-
if (!value) return "00:00";
|
|
80
|
-
const date = new Date(value);
|
|
81
|
-
return `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
|
|
113
|
+
return new Date(valueStr);
|
|
82
114
|
}
|
|
83
115
|
|
|
84
|
-
//
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
116
|
+
// Parse 12-hour time format to 24-hour format
|
|
117
|
+
function parse12HourTime(timeStr) {
|
|
118
|
+
const match = timeStr.match(/(\d{1,2}):(\d{2})\s*(AM|PM)/i);
|
|
119
|
+
if (!match) return null;
|
|
120
|
+
let hours = parseInt(match[1]);
|
|
121
|
+
const minutes = parseInt(match[2]);
|
|
122
|
+
const ampm = match[3].toUpperCase();
|
|
91
123
|
|
|
92
|
-
|
|
93
|
-
if (
|
|
94
|
-
return `${(date.getMonth() + 1).toString().padStart(2, "0")}/${date.getDate().toString().padStart(2, "0")}/${date.getFullYear()}`;
|
|
95
|
-
}
|
|
124
|
+
if (ampm === "PM" && hours !== 12) hours += 12;
|
|
125
|
+
if (ampm === "AM" && hours === 12) hours = 0;
|
|
96
126
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
127
|
+
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
128
|
+
}
|
|
100
129
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
130
|
+
// Format date/datetime helper function
|
|
131
|
+
// Only applies formatting - timezone handling is done in parseValueToDate
|
|
132
|
+
// If showTime is false (default), returns formatted date only
|
|
133
|
+
// If showTime is true, returns formatted date + time
|
|
134
|
+
function formatDateTime(date, dateFormat, showTime = false) {
|
|
135
|
+
if (!date) return "";
|
|
104
136
|
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
"MMM DD, YYYY": {
|
|
108
|
-
month: "short",
|
|
109
|
-
day: "numeric",
|
|
110
|
-
year: "numeric",
|
|
111
|
-
timeZone: "UTC",
|
|
112
|
-
},
|
|
113
|
-
"DD MMM YYYY": {
|
|
114
|
-
day: "numeric",
|
|
115
|
-
month: "short",
|
|
116
|
-
year: "numeric",
|
|
117
|
-
timeZone: "UTC",
|
|
118
|
-
},
|
|
119
|
-
};
|
|
137
|
+
// Format the date part
|
|
138
|
+
let dateResult = "";
|
|
120
139
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
140
|
+
if (!dateFormat || dateFormat === "default") {
|
|
141
|
+
dateResult = date?.toDateString();
|
|
142
|
+
} else {
|
|
143
|
+
// Use local methods to format - timezone is already handled by parseValueToDate
|
|
144
|
+
const month = date.getMonth();
|
|
145
|
+
const dayOfMonth = date.getDate();
|
|
146
|
+
const year = date.getFullYear();
|
|
147
|
+
|
|
148
|
+
// Manual formatting for specific formats to ensure exact order
|
|
149
|
+
if (dateFormat === "MM/DD/YYYY") {
|
|
150
|
+
dateResult = `${(month + 1).toString().padStart(2, "0")}/${dayOfMonth.toString().padStart(2, "0")}/${year}`;
|
|
151
|
+
} else if (dateFormat === "DD/MM/YYYY") {
|
|
152
|
+
dateResult = `${dayOfMonth.toString().padStart(2, "0")}/${(month + 1).toString().padStart(2, "0")}/${year}`;
|
|
153
|
+
} else if (dateFormat === "YYYY-MM-DD") {
|
|
154
|
+
dateResult = `${year}-${(month + 1).toString().padStart(2, "0")}-${dayOfMonth.toString().padStart(2, "0")}`;
|
|
155
|
+
} else {
|
|
156
|
+
// For shorter formats, use locale-specific formatting
|
|
157
|
+
const options = {
|
|
158
|
+
"MMM DD, YYYY": {
|
|
159
|
+
month: "short",
|
|
160
|
+
day: "numeric",
|
|
161
|
+
year: "numeric",
|
|
162
|
+
},
|
|
163
|
+
"DD MMM YYYY": {
|
|
164
|
+
day: "numeric",
|
|
165
|
+
month: "short",
|
|
166
|
+
year: "numeric",
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const formatOption = options[dateFormat];
|
|
171
|
+
if (formatOption) {
|
|
172
|
+
dateResult = date.toLocaleDateString("en-US", formatOption);
|
|
173
|
+
} else {
|
|
174
|
+
// Fallback to default
|
|
175
|
+
dateResult = date?.toDateString();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
124
178
|
}
|
|
125
179
|
|
|
126
|
-
//
|
|
127
|
-
return date?.toDateString();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// DateTime formatting helper function
|
|
131
|
-
function formatDateTime(date, dateFormat, showTime) {
|
|
132
|
-
if (!date) return "";
|
|
133
|
-
|
|
180
|
+
// If not showing time, return just the formatted date
|
|
134
181
|
if (!showTime) {
|
|
135
|
-
return
|
|
182
|
+
return dateResult;
|
|
136
183
|
}
|
|
137
184
|
|
|
138
|
-
|
|
139
|
-
|
|
185
|
+
// Format the time part when showTime is true (using local time)
|
|
186
|
+
let hours = date.getHours();
|
|
187
|
+
let minutes = date.getMinutes();
|
|
188
|
+
|
|
189
|
+
// Format based on show24HTime
|
|
190
|
+
let timeString;
|
|
191
|
+
if (show24HTime) {
|
|
192
|
+
timeString = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
193
|
+
} else {
|
|
194
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
195
|
+
const display12h = hours % 12 || 12;
|
|
196
|
+
timeString = `${display12h.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")} ${ampm}`;
|
|
197
|
+
}
|
|
140
198
|
|
|
141
|
-
return `${
|
|
199
|
+
return `${dateResult} ${timeString}`;
|
|
142
200
|
}
|
|
143
201
|
|
|
144
202
|
$: formattedValue =
|
|
145
|
-
cellOptions.template && value
|
|
146
|
-
? processStringSync(cellOptions.template, {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
203
|
+
cellOptions.template && value && value != "" && value != null
|
|
204
|
+
? processStringSync(cellOptions.template, {
|
|
205
|
+
value: innerDate,
|
|
206
|
+
})
|
|
207
|
+
: (value && value != "" && value != null) || selection
|
|
208
|
+
? formatDateTime(innerDate, currentDateFormat, currentShowTime)
|
|
209
|
+
: "";
|
|
150
210
|
|
|
151
211
|
$: placeholder = cellOptions?.placeholder || "";
|
|
152
212
|
$: inEdit = $cellState == "Editing";
|
|
153
213
|
$: inline = cellOptions.role == "inlineInpur";
|
|
154
|
-
$: isDirty = inEdit &&
|
|
214
|
+
$: isDirty = inEdit && true;
|
|
155
215
|
|
|
156
216
|
onMount(() => {
|
|
157
217
|
if (autofocus)
|
|
@@ -161,20 +221,72 @@
|
|
|
161
221
|
}, 30);
|
|
162
222
|
});
|
|
163
223
|
|
|
164
|
-
// Handle time
|
|
224
|
+
// Handle Start button - set time to beginning of day (00:00 or 12:00 AM)
|
|
225
|
+
const handleStartTime = () => {
|
|
226
|
+
const startTime = show24HTime ? "00:00" : "12:00 AM";
|
|
227
|
+
timeValue = startTime;
|
|
228
|
+
|
|
229
|
+
innerDate.setHours(0, 0, 0, 0);
|
|
230
|
+
innerDate = innerDate;
|
|
231
|
+
selection = true;
|
|
232
|
+
anchor?.focus();
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// Handle End button - set time to end of day (23:59 or 11:59 PM)
|
|
236
|
+
const handleEndTime = () => {
|
|
237
|
+
const endTime = show24HTime ? "23:59" : "11:59 PM";
|
|
238
|
+
timeValue = endTime;
|
|
239
|
+
|
|
240
|
+
innerDate.setHours(23, 59, 0, 0);
|
|
241
|
+
innerDate = innerDate;
|
|
242
|
+
selection = true;
|
|
243
|
+
anchor?.focus();
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Handle Now button - set both date and time to current date/time
|
|
247
|
+
const handleNowTime = () => {
|
|
248
|
+
innerDate = new Date();
|
|
249
|
+
selection = true;
|
|
250
|
+
anchor?.focus();
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// Handle Clear button - clear the value
|
|
254
|
+
const handleClearValue = () => {
|
|
255
|
+
cellState.submit();
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// Handle time picker changes - only affects the time, not timezone
|
|
165
259
|
const handleTimeChange = (e) => {
|
|
166
|
-
if (!
|
|
260
|
+
if (!currentShowTime) return;
|
|
261
|
+
selection = true;
|
|
167
262
|
|
|
168
263
|
const newTime = e.target.value;
|
|
169
|
-
|
|
170
|
-
const
|
|
264
|
+
// Convert 12-hour format to 24-hour if needed
|
|
265
|
+
const time24h = show24HTime ? newTime : parse12HourTime(newTime);
|
|
266
|
+
if (!time24h) return;
|
|
267
|
+
|
|
268
|
+
const [hours, minutes] = time24h.split(":").map(Number);
|
|
269
|
+
|
|
270
|
+
innerDate.setHours(hours, minutes, 0, 0);
|
|
271
|
+
};
|
|
171
272
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
273
|
+
const handleDateChange = (e) => {
|
|
274
|
+
const newDate = e.detail;
|
|
275
|
+
selection = true;
|
|
276
|
+
|
|
277
|
+
if (currentShowTime) {
|
|
278
|
+
// Preserve the time from the current innerDate when appending to the selected date
|
|
279
|
+
newDate.setHours(
|
|
280
|
+
innerDate.getHours(),
|
|
281
|
+
innerDate.getMinutes(),
|
|
282
|
+
innerDate.getSeconds(),
|
|
283
|
+
innerDate.getMilliseconds(),
|
|
284
|
+
);
|
|
285
|
+
}
|
|
175
286
|
|
|
176
|
-
|
|
177
|
-
|
|
287
|
+
innerDate = newDate;
|
|
288
|
+
anchor?.focus();
|
|
289
|
+
open = false;
|
|
178
290
|
};
|
|
179
291
|
</script>
|
|
180
292
|
|
|
@@ -197,45 +309,45 @@
|
|
|
197
309
|
style:color={cellOptions.color}
|
|
198
310
|
style:background={cellOptions.background}
|
|
199
311
|
on:focus={cellState.focus}
|
|
200
|
-
on:
|
|
312
|
+
on:keydown={cellState.handleKeyboard}
|
|
201
313
|
on:focusout={cellState.focusout}
|
|
314
|
+
on:mousedown={cellState.toggle}
|
|
202
315
|
>
|
|
203
|
-
{#
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
class="editor"
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
</div>
|
|
229
|
-
{/if}
|
|
316
|
+
{#key $cellState}
|
|
317
|
+
{#if cellOptions.icon}
|
|
318
|
+
<i class={cellOptions.icon + " field-icon"}></i>
|
|
319
|
+
{/if}
|
|
320
|
+
|
|
321
|
+
{#if inEdit}
|
|
322
|
+
<div class="editor" class:placeholder={!formattedValue}>
|
|
323
|
+
<span>{formattedValue || placeholder}</span>
|
|
324
|
+
<i
|
|
325
|
+
class="ri-calendar-line"
|
|
326
|
+
style="font-size: 16px; justify-self: flex-end"
|
|
327
|
+
></i>
|
|
328
|
+
</div>
|
|
329
|
+
{:else}
|
|
330
|
+
<div
|
|
331
|
+
class="value"
|
|
332
|
+
class:placeholder={!formattedValue}
|
|
333
|
+
style:justify-content={cellOptions.align}
|
|
334
|
+
>
|
|
335
|
+
<span>
|
|
336
|
+
{value ? formattedValue : placeholder}
|
|
337
|
+
</span>
|
|
338
|
+
</div>
|
|
339
|
+
{/if}
|
|
340
|
+
{/key}
|
|
230
341
|
</div>
|
|
231
342
|
|
|
232
343
|
{#if inEdit}
|
|
233
344
|
<SuperPopover
|
|
234
345
|
{anchor}
|
|
235
|
-
dismissible={false}
|
|
236
346
|
{open}
|
|
347
|
+
ignoreAnchor
|
|
237
348
|
align="right"
|
|
238
349
|
maxHeight={400}
|
|
350
|
+
on:close={cellState.focusout}
|
|
239
351
|
>
|
|
240
352
|
<div
|
|
241
353
|
bind:this={picker}
|
|
@@ -244,26 +356,34 @@
|
|
|
244
356
|
style:--date-picker-foreground="var(--spectrum-global-color-gray-800)"
|
|
245
357
|
style:--date-picker-selected-background="var(--accent-color)"
|
|
246
358
|
>
|
|
247
|
-
<DatePicker
|
|
248
|
-
bind:value={innerDate}
|
|
249
|
-
on:select={(e) => {
|
|
250
|
-
value = e.detail;
|
|
251
|
-
anchor?.focus();
|
|
252
|
-
open = false;
|
|
253
|
-
}}
|
|
254
|
-
/>
|
|
359
|
+
<DatePicker value={innerDate} on:select={handleDateChange} />
|
|
255
360
|
|
|
256
361
|
{#if currentShowTime}
|
|
257
362
|
<div class="time-section">
|
|
258
363
|
<!-- svelte-ignore a11y-label-has-associated-control -->
|
|
259
364
|
<input
|
|
260
365
|
bind:this={timePicker}
|
|
261
|
-
type="
|
|
366
|
+
type="text"
|
|
367
|
+
placeholder={show24HTime ? "HH:MM" : "HH:MM AM/PM"}
|
|
262
368
|
bind:value={timeValue}
|
|
263
369
|
on:change={handleTimeChange}
|
|
370
|
+
on:focusout={cellState.focusout}
|
|
264
371
|
class="time-input"
|
|
265
|
-
step="900"
|
|
266
372
|
/>
|
|
373
|
+
<div class="time-buttons">
|
|
374
|
+
<button class="time-button start-button" on:click={handleStartTime}
|
|
375
|
+
>Start</button
|
|
376
|
+
>
|
|
377
|
+
<button class="time-button end-button" on:click={handleEndTime}
|
|
378
|
+
>End</button
|
|
379
|
+
>
|
|
380
|
+
<button class="time-button now-button" on:click={handleNowTime}
|
|
381
|
+
>Now</button
|
|
382
|
+
>
|
|
383
|
+
<button class="time-button clear-button" on:click={handleClearValue}
|
|
384
|
+
>Select</button
|
|
385
|
+
>
|
|
386
|
+
</div>
|
|
267
387
|
</div>
|
|
268
388
|
{/if}
|
|
269
389
|
</div>
|
|
@@ -283,7 +403,35 @@
|
|
|
283
403
|
.time-section {
|
|
284
404
|
display: flex;
|
|
285
405
|
flex-direction: column;
|
|
286
|
-
gap:
|
|
406
|
+
gap: 8px;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.time-buttons {
|
|
410
|
+
display: flex;
|
|
411
|
+
gap: 6px;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.time-button {
|
|
415
|
+
flex: 1;
|
|
416
|
+
padding: 6px 12px;
|
|
417
|
+
border: 1px solid var(--spectrum-global-color-gray-300);
|
|
418
|
+
border-radius: 4px;
|
|
419
|
+
background: var(--spectrum-global-color-gray-50);
|
|
420
|
+
color: var(--spectrum-global-color-gray-800);
|
|
421
|
+
font-size: 13px;
|
|
422
|
+
font-weight: 500;
|
|
423
|
+
cursor: pointer;
|
|
424
|
+
transition: all 0.15s ease;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.time-button:hover {
|
|
428
|
+
background: var(--spectrum-global-color-gray-100);
|
|
429
|
+
border-color: var(--spectrum-global-color-gray-400);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.time-button:active {
|
|
433
|
+
background: var(--spectrum-global-color-gray-200);
|
|
434
|
+
border-color: var(--spectrum-global-color-gray-500);
|
|
287
435
|
}
|
|
288
436
|
|
|
289
437
|
.time-label {
|