svelte-comp 1.3.5 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE.md +21 -21
  2. package/README.md +101 -101
  3. package/dist/App.svelte +1046 -1046
  4. package/dist/Container.svelte +59 -59
  5. package/dist/app.css +234 -234
  6. package/dist/app.d.ts +10 -10
  7. package/dist/lib/Accordion.svelte +155 -155
  8. package/dist/lib/Badge.svelte +44 -44
  9. package/dist/lib/Button.svelte +185 -185
  10. package/dist/lib/Calendar.svelte +384 -384
  11. package/dist/lib/Card.svelte +103 -103
  12. package/dist/lib/Carousel.svelte +293 -293
  13. package/dist/lib/CheckBox.svelte +210 -210
  14. package/dist/lib/CodeView.svelte +308 -308
  15. package/dist/lib/ColorPicker.svelte +159 -159
  16. package/dist/lib/ContextMenu.svelte +328 -328
  17. package/dist/lib/DatePicker.svelte +246 -246
  18. package/dist/lib/Dialog.svelte +233 -233
  19. package/dist/lib/Field.svelte +299 -299
  20. package/dist/lib/FilePicker.svelte +295 -295
  21. package/dist/lib/Form.svelte +438 -438
  22. package/dist/lib/Hamburger.svelte +217 -217
  23. package/dist/lib/InstallPWA.svelte +94 -94
  24. package/dist/lib/Menu.svelte +623 -623
  25. package/dist/lib/NoticeBase.svelte +140 -140
  26. package/dist/lib/PaginatedCard.svelte +73 -73
  27. package/dist/lib/Pagination.svelte +119 -119
  28. package/dist/lib/PrimaryColorSelect.svelte +111 -111
  29. package/dist/lib/ProgressBar.svelte +141 -141
  30. package/dist/lib/ProgressCircle.svelte +190 -190
  31. package/dist/lib/Radio.svelte +189 -189
  32. package/dist/lib/SearchInput.svelte +104 -104
  33. package/dist/lib/Select.svelte +524 -524
  34. package/dist/lib/Slider.svelte +253 -253
  35. package/dist/lib/Splitter.svelte +159 -159
  36. package/dist/lib/Switch.svelte +168 -168
  37. package/dist/lib/Table.svelte +299 -299
  38. package/dist/lib/Tabs.svelte +213 -213
  39. package/dist/lib/ThemeToggle.svelte +128 -128
  40. package/dist/lib/TimePicker.svelte +312 -312
  41. package/dist/lib/TimePickerNew.svelte +634 -634
  42. package/dist/lib/Toast.svelte +123 -123
  43. package/dist/lib/Tooltip.svelte +110 -110
  44. package/dist/lib/Topbar.svelte +112 -112
  45. package/dist/styles.css +234 -234
  46. package/package.json +52 -52
@@ -1,312 +1,312 @@
1
- <!-- src/lib/TimePicker.svelte -->
2
- <script lang="ts">
3
- /**
4
- * @component TimePicker
5
- * @description Simple time selector that stores values in ISO `HH:MM` format. Supports a fixed step and two display systems.
6
- *
7
- * @prop value {string | null} - Stored time in ISO `HH:MM` (bindable)
8
- * @default null
9
- *
10
- * @prop step {number} - Step in seconds
11
- * @default 60
12
- *
13
- * @prop label {string} - Label text
14
- *
15
- * @prop placeholder {string} - Placeholder when value is null
16
- *
17
- * @prop disabled {boolean} - Disable all interactions
18
- * @default false
19
- *
20
- * @prop clearable {boolean} - Show the clear button
21
- * @default true
22
- *
23
- * @prop initialSystem {"iso" | "english"} - Picker mode (24h vs 12h)
24
- * @default "iso"
25
- *
26
- * @prop onChange {(value: string | null) => void} - Fired when value changes
27
- *
28
- * @prop class {string} - Wrapper classes
29
- * @default ""
30
- *
31
- * @note ISO mode uses 24-hour time; English mode uses 12-hour time with AM/PM
32
- * @note The stored value is always ISO (`HH:MM`)
33
- * @note `step` defines the minute grid (derived from seconds)
34
- * @note No locale or date-formatting APIs are used internally
35
- */
36
- import type { HTMLAttributes } from "svelte/elements";
37
- import Button from "./Button.svelte";
38
- import Select from "./Select.svelte";
39
- import { cx } from "../utils";
40
- import { getComponentText, getLangContext, getLangKey } from "./lang-context";
41
-
42
- type Props = HTMLAttributes<HTMLDivElement> & {
43
- value?: string | null;
44
- step?: number;
45
- label?: string;
46
- placeholder?: string;
47
- disabled?: boolean;
48
- clearable?: boolean;
49
- initialSystem?: "iso" | "english";
50
- onChange?: (value: string | null) => void;
51
- class?: string;
52
- };
53
- type Period = "AM" | "PM";
54
-
55
- let {
56
- value = $bindable<string | null>(null),
57
- step = 60,
58
- label,
59
- placeholder,
60
- disabled = false,
61
- clearable = true,
62
- initialSystem = "iso",
63
- onChange,
64
- class: externalClass = "",
65
- ...rest
66
- }: Props = $props();
67
-
68
- const langCtx = getLangContext();
69
- const langKey = $derived(getLangKey(langCtx));
70
- const L = $derived(getComponentText("timePicker", langKey));
71
-
72
- const labelFinal = $derived(label ?? L.text);
73
- const placeholderFinal = $derived(placeholder ?? L.placeholder);
74
-
75
- const pickerClass = $derived(cx("inline-block w-full", externalClass));
76
-
77
- let timeSystem = $state<"iso" | "english">("iso");
78
- let didInitSystem = $state(false);
79
-
80
- let hour = $state("00");
81
- let minute = $state("00");
82
- let period = $state<Period>("AM");
83
-
84
- const hasValue = $derived(value != null);
85
-
86
- const isoHours = Array.from({ length: 24 }, (_, i) => {
87
- const h = i.toString().padStart(2, "0");
88
- return { value: h, label: h };
89
- });
90
-
91
- const englishHours = Array.from({ length: 12 }, (_, i) => {
92
- const h = (i + 1).toString().padStart(2, "0");
93
- return { value: h, label: h };
94
- });
95
-
96
- const periodOptions: Array<{ value: Period; label: Period }> = [
97
- { value: "AM", label: "AM" },
98
- { value: "PM", label: "PM" },
99
- ];
100
-
101
- const minuteIncrement = $derived(
102
- !step || step <= 0 ? 1 : Math.min(60, Math.max(1, Math.round(step / 60)))
103
- );
104
-
105
- const minuteOptions = $derived.by(() => {
106
- const arr = [];
107
- for (let i = 0; i < 60; i += minuteIncrement) {
108
- const m = i.toString().padStart(2, "0");
109
- arr.push({ value: m, label: m });
110
- }
111
- return arr;
112
- });
113
-
114
- function normalize(x: string) {
115
- return x.padStart(2, "0").slice(-2);
116
- }
117
-
118
- function toIsoHour(h: string, p: "AM" | "PM") {
119
- const numeric = Number.parseInt(h, 10);
120
- if (Number.isNaN(numeric)) return "00";
121
- const base = numeric % 12;
122
- const withPeriod = p === "PM" ? base + 12 : base;
123
- return normalize(String(withPeriod));
124
- }
125
-
126
- function toEnglishHour(isoHour: string): { hour: string; period: Period } {
127
- const numeric = Number.parseInt(isoHour, 10);
128
- if (Number.isNaN(numeric)) {
129
- return { hour: "12", period: "AM" as const };
130
- }
131
- const periodValue: Period = numeric >= 12 ? "PM" : "AM";
132
- const normalized = numeric % 12 || 12;
133
- return { hour: normalize(String(normalized)), period: periodValue };
134
- }
135
-
136
- function emit() {
137
- const isoHour =
138
- timeSystem === "english" ? toIsoHour(hour, period) : normalize(hour);
139
- const v = `${isoHour}:${normalize(minute)}`;
140
- value = v;
141
- onChange?.(v);
142
- }
143
-
144
- function handleIsoHour(v: string) {
145
- hour = normalize(v);
146
- emit();
147
- }
148
-
149
- function handleMinute(v: string) {
150
- minute = normalize(v);
151
- emit();
152
- }
153
-
154
- function handleEnglishHour(v: string) {
155
- hour = normalize(v);
156
- emit();
157
- }
158
-
159
- function handlePeriod(v: string) {
160
- period = v === "AM" || v === "PM" ? v : "AM";
161
- emit();
162
- }
163
-
164
- function toggleSystem() {
165
- if (disabled) return;
166
-
167
- if (timeSystem === "iso") {
168
- timeSystem = "english";
169
- const mapped = toEnglishHour(hour);
170
- hour = mapped.hour;
171
- period = mapped.period;
172
- } else {
173
- timeSystem = "iso";
174
- hour = toIsoHour(hour, period);
175
- period = "AM";
176
- }
177
-
178
- emit();
179
- }
180
-
181
- function clearSelection() {
182
- if (!clearable) return;
183
- hour = "00";
184
- minute = "00";
185
- period = "AM";
186
- value = null;
187
- onChange?.(null);
188
- }
189
-
190
- const displayValue = $derived.by(() => {
191
- if (!value) return "";
192
- const [isoH, isoM] = value.split(":");
193
- if (timeSystem === "english") {
194
- const { hour: h, period: p } = toEnglishHour(isoH);
195
- return `${h}:${normalize(isoM)} ${p}`;
196
- }
197
- return `${normalize(isoH)}:${normalize(isoM)}`;
198
- });
199
-
200
- $effect(() => {
201
- if (didInitSystem) return;
202
- didInitSystem = true;
203
- timeSystem = initialSystem;
204
- });
205
-
206
- $effect(() => {
207
- if (value == null) return;
208
-
209
- let raw = value;
210
- let parsedPeriod: Period | null = null;
211
-
212
- if (raw.includes("AM") || raw.includes("PM")) {
213
- parsedPeriod = raw.includes("PM") ? "PM" : "AM";
214
- raw = raw.replace(" AM", "").replace(" PM", "");
215
- }
216
-
217
- const [h, m] = raw.split(":");
218
- const isoHour = normalize(h);
219
- const isoMinute = normalize(m);
220
-
221
- if (timeSystem === "english") {
222
- const mapped = parsedPeriod
223
- ? { hour: normalize(h), period: parsedPeriod }
224
- : toEnglishHour(isoHour);
225
- hour = mapped.hour;
226
- period = mapped.period;
227
- } else {
228
- hour = isoHour;
229
- period = toEnglishHour(isoHour).period;
230
- }
231
- minute = isoMinute;
232
- });
233
- </script>
234
-
235
- <div class={pickerClass} {...rest}>
236
- <div class="text-md font-medium mb-2 [color:var(--color-text-default)]">
237
- {labelFinal}
238
- </div>
239
-
240
- <div class="flex flex-wrap items-start gap-4">
241
- <div class="flex flex-wrap gap-3 min-w-[0] flex-1">
242
- {#if timeSystem === "iso"}
243
- <Select
244
- label={L.hour}
245
- options={isoHours}
246
- value={hour}
247
- onChange={handleIsoHour}
248
- {disabled}
249
- sz="sm"
250
- />
251
- {:else}
252
- <Select
253
- label={L.hour}
254
- options={englishHours}
255
- value={hour}
256
- onChange={handleEnglishHour}
257
- {disabled}
258
- sz="sm"
259
- />
260
-
261
- <Select
262
- label={L.period}
263
- options={periodOptions}
264
- value={period}
265
- onChange={handlePeriod}
266
- {disabled}
267
- sz="sm"
268
- />
269
- {/if}
270
-
271
- <Select
272
- label={L.minute}
273
- options={minuteOptions}
274
- value={minute}
275
- onChange={handleMinute}
276
- {disabled}
277
- sz="sm"
278
- />
279
- </div>
280
-
281
- <div class="flex items-center gap-3 basis-full pt-2">
282
- <Button onClick={toggleSystem} {disabled} sz="xs">
283
- {timeSystem === "iso" ? L.switchTo12h : L.switchTo24h}
284
- </Button>
285
-
286
- {#if clearable}
287
- <Button
288
- onClick={clearSelection}
289
- variant="danger"
290
- disabled={!hasValue || disabled}
291
- sz="xs"
292
- >
293
- {L.clear}
294
- </Button>
295
- {/if}
296
- </div>
297
- </div>
298
-
299
- <div class="mt-4 p-4 bg-[var(--color-bg-surface)] text-center">
300
- <p class="text-xs uppercase tracking-wide [color:var(--color-text-muted)]">
301
- {L.selectedTime}
302
- </p>
303
-
304
- <p class="text-sm font-semibold mt-1 [color:var(--color-text-default)]">
305
- {#if hasValue}
306
- {displayValue}
307
- {:else}
308
- {placeholderFinal}
309
- {/if}
310
- </p>
311
- </div>
312
- </div>
1
+ <!-- src/lib/TimePicker.svelte -->
2
+ <script lang="ts">
3
+ /**
4
+ * @component TimePicker
5
+ * @description Simple time selector that stores values in ISO `HH:MM` format. Supports a fixed step and two display systems.
6
+ *
7
+ * @prop value {string | null} - Stored time in ISO `HH:MM` (bindable)
8
+ * @default null
9
+ *
10
+ * @prop step {number} - Step in seconds
11
+ * @default 60
12
+ *
13
+ * @prop label {string} - Label text
14
+ *
15
+ * @prop placeholder {string} - Placeholder when value is null
16
+ *
17
+ * @prop disabled {boolean} - Disable all interactions
18
+ * @default false
19
+ *
20
+ * @prop clearable {boolean} - Show the clear button
21
+ * @default true
22
+ *
23
+ * @prop initialSystem {"iso" | "english"} - Picker mode (24h vs 12h)
24
+ * @default "iso"
25
+ *
26
+ * @prop onChange {(value: string | null) => void} - Fired when value changes
27
+ *
28
+ * @prop class {string} - Wrapper classes
29
+ * @default ""
30
+ *
31
+ * @note ISO mode uses 24-hour time; English mode uses 12-hour time with AM/PM
32
+ * @note The stored value is always ISO (`HH:MM`)
33
+ * @note `step` defines the minute grid (derived from seconds)
34
+ * @note No locale or date-formatting APIs are used internally
35
+ */
36
+ import type { HTMLAttributes } from "svelte/elements";
37
+ import Button from "./Button.svelte";
38
+ import Select from "./Select.svelte";
39
+ import { cx } from "../utils";
40
+ import { getComponentText, getLangContext, getLangKey } from "./lang-context";
41
+
42
+ type Props = HTMLAttributes<HTMLDivElement> & {
43
+ value?: string | null;
44
+ step?: number;
45
+ label?: string;
46
+ placeholder?: string;
47
+ disabled?: boolean;
48
+ clearable?: boolean;
49
+ initialSystem?: "iso" | "english";
50
+ onChange?: (value: string | null) => void;
51
+ class?: string;
52
+ };
53
+ type Period = "AM" | "PM";
54
+
55
+ let {
56
+ value = $bindable<string | null>(null),
57
+ step = 60,
58
+ label,
59
+ placeholder,
60
+ disabled = false,
61
+ clearable = true,
62
+ initialSystem = "iso",
63
+ onChange,
64
+ class: externalClass = "",
65
+ ...rest
66
+ }: Props = $props();
67
+
68
+ const langCtx = getLangContext();
69
+ const langKey = $derived(getLangKey(langCtx));
70
+ const L = $derived(getComponentText("timePicker", langKey));
71
+
72
+ const labelFinal = $derived(label ?? L.text);
73
+ const placeholderFinal = $derived(placeholder ?? L.placeholder);
74
+
75
+ const pickerClass = $derived(cx("inline-block w-full", externalClass));
76
+
77
+ let timeSystem = $state<"iso" | "english">("iso");
78
+ let didInitSystem = $state(false);
79
+
80
+ let hour = $state("00");
81
+ let minute = $state("00");
82
+ let period = $state<Period>("AM");
83
+
84
+ const hasValue = $derived(value != null);
85
+
86
+ const isoHours = Array.from({ length: 24 }, (_, i) => {
87
+ const h = i.toString().padStart(2, "0");
88
+ return { value: h, label: h };
89
+ });
90
+
91
+ const englishHours = Array.from({ length: 12 }, (_, i) => {
92
+ const h = (i + 1).toString().padStart(2, "0");
93
+ return { value: h, label: h };
94
+ });
95
+
96
+ const periodOptions: Array<{ value: Period; label: Period }> = [
97
+ { value: "AM", label: "AM" },
98
+ { value: "PM", label: "PM" },
99
+ ];
100
+
101
+ const minuteIncrement = $derived(
102
+ !step || step <= 0 ? 1 : Math.min(60, Math.max(1, Math.round(step / 60)))
103
+ );
104
+
105
+ const minuteOptions = $derived.by(() => {
106
+ const arr = [];
107
+ for (let i = 0; i < 60; i += minuteIncrement) {
108
+ const m = i.toString().padStart(2, "0");
109
+ arr.push({ value: m, label: m });
110
+ }
111
+ return arr;
112
+ });
113
+
114
+ function normalize(x: string) {
115
+ return x.padStart(2, "0").slice(-2);
116
+ }
117
+
118
+ function toIsoHour(h: string, p: "AM" | "PM") {
119
+ const numeric = Number.parseInt(h, 10);
120
+ if (Number.isNaN(numeric)) return "00";
121
+ const base = numeric % 12;
122
+ const withPeriod = p === "PM" ? base + 12 : base;
123
+ return normalize(String(withPeriod));
124
+ }
125
+
126
+ function toEnglishHour(isoHour: string): { hour: string; period: Period } {
127
+ const numeric = Number.parseInt(isoHour, 10);
128
+ if (Number.isNaN(numeric)) {
129
+ return { hour: "12", period: "AM" as const };
130
+ }
131
+ const periodValue: Period = numeric >= 12 ? "PM" : "AM";
132
+ const normalized = numeric % 12 || 12;
133
+ return { hour: normalize(String(normalized)), period: periodValue };
134
+ }
135
+
136
+ function emit() {
137
+ const isoHour =
138
+ timeSystem === "english" ? toIsoHour(hour, period) : normalize(hour);
139
+ const v = `${isoHour}:${normalize(minute)}`;
140
+ value = v;
141
+ onChange?.(v);
142
+ }
143
+
144
+ function handleIsoHour(v: string) {
145
+ hour = normalize(v);
146
+ emit();
147
+ }
148
+
149
+ function handleMinute(v: string) {
150
+ minute = normalize(v);
151
+ emit();
152
+ }
153
+
154
+ function handleEnglishHour(v: string) {
155
+ hour = normalize(v);
156
+ emit();
157
+ }
158
+
159
+ function handlePeriod(v: string) {
160
+ period = v === "AM" || v === "PM" ? v : "AM";
161
+ emit();
162
+ }
163
+
164
+ function toggleSystem() {
165
+ if (disabled) return;
166
+
167
+ if (timeSystem === "iso") {
168
+ timeSystem = "english";
169
+ const mapped = toEnglishHour(hour);
170
+ hour = mapped.hour;
171
+ period = mapped.period;
172
+ } else {
173
+ timeSystem = "iso";
174
+ hour = toIsoHour(hour, period);
175
+ period = "AM";
176
+ }
177
+
178
+ emit();
179
+ }
180
+
181
+ function clearSelection() {
182
+ if (!clearable) return;
183
+ hour = "00";
184
+ minute = "00";
185
+ period = "AM";
186
+ value = null;
187
+ onChange?.(null);
188
+ }
189
+
190
+ const displayValue = $derived.by(() => {
191
+ if (!value) return "";
192
+ const [isoH, isoM] = value.split(":");
193
+ if (timeSystem === "english") {
194
+ const { hour: h, period: p } = toEnglishHour(isoH);
195
+ return `${h}:${normalize(isoM)} ${p}`;
196
+ }
197
+ return `${normalize(isoH)}:${normalize(isoM)}`;
198
+ });
199
+
200
+ $effect(() => {
201
+ if (didInitSystem) return;
202
+ didInitSystem = true;
203
+ timeSystem = initialSystem;
204
+ });
205
+
206
+ $effect(() => {
207
+ if (value == null) return;
208
+
209
+ let raw = value;
210
+ let parsedPeriod: Period | null = null;
211
+
212
+ if (raw.includes("AM") || raw.includes("PM")) {
213
+ parsedPeriod = raw.includes("PM") ? "PM" : "AM";
214
+ raw = raw.replace(" AM", "").replace(" PM", "");
215
+ }
216
+
217
+ const [h, m] = raw.split(":");
218
+ const isoHour = normalize(h);
219
+ const isoMinute = normalize(m);
220
+
221
+ if (timeSystem === "english") {
222
+ const mapped = parsedPeriod
223
+ ? { hour: normalize(h), period: parsedPeriod }
224
+ : toEnglishHour(isoHour);
225
+ hour = mapped.hour;
226
+ period = mapped.period;
227
+ } else {
228
+ hour = isoHour;
229
+ period = toEnglishHour(isoHour).period;
230
+ }
231
+ minute = isoMinute;
232
+ });
233
+ </script>
234
+
235
+ <div class={pickerClass} {...rest}>
236
+ <div class="text-md font-medium mb-2 [color:var(--color-text-default)]">
237
+ {labelFinal}
238
+ </div>
239
+
240
+ <div class="flex flex-wrap items-start gap-4">
241
+ <div class="flex flex-wrap gap-3 min-w-[0] flex-1">
242
+ {#if timeSystem === "iso"}
243
+ <Select
244
+ label={L.hour}
245
+ options={isoHours}
246
+ value={hour}
247
+ onChange={handleIsoHour}
248
+ {disabled}
249
+ sz="sm"
250
+ />
251
+ {:else}
252
+ <Select
253
+ label={L.hour}
254
+ options={englishHours}
255
+ value={hour}
256
+ onChange={handleEnglishHour}
257
+ {disabled}
258
+ sz="sm"
259
+ />
260
+
261
+ <Select
262
+ label={L.period}
263
+ options={periodOptions}
264
+ value={period}
265
+ onChange={handlePeriod}
266
+ {disabled}
267
+ sz="sm"
268
+ />
269
+ {/if}
270
+
271
+ <Select
272
+ label={L.minute}
273
+ options={minuteOptions}
274
+ value={minute}
275
+ onChange={handleMinute}
276
+ {disabled}
277
+ sz="sm"
278
+ />
279
+ </div>
280
+
281
+ <div class="flex items-center gap-3 basis-full pt-2">
282
+ <Button onClick={toggleSystem} {disabled} sz="xs">
283
+ {timeSystem === "iso" ? L.switchTo12h : L.switchTo24h}
284
+ </Button>
285
+
286
+ {#if clearable}
287
+ <Button
288
+ onClick={clearSelection}
289
+ variant="danger"
290
+ disabled={!hasValue || disabled}
291
+ sz="xs"
292
+ >
293
+ {L.clear}
294
+ </Button>
295
+ {/if}
296
+ </div>
297
+ </div>
298
+
299
+ <div class="mt-4 p-4 bg-[var(--color-bg-surface)] text-center">
300
+ <p class="text-xs uppercase tracking-wide [color:var(--color-text-muted)]">
301
+ {L.selectedTime}
302
+ </p>
303
+
304
+ <p class="text-sm font-semibold mt-1 [color:var(--color-text-default)]">
305
+ {#if hasValue}
306
+ {displayValue}
307
+ {:else}
308
+ {placeholderFinal}
309
+ {/if}
310
+ </p>
311
+ </div>
312
+ </div>