svelte-comp 1.2.5 → 1.2.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.

Potentially problematic release.


This version of svelte-comp might be problematic. Click here for more details.

Files changed (84) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/dist/App.svelte +0 -551
  4. package/dist/App.svelte.d.ts +0 -3
  5. package/dist/Container.svelte +0 -60
  6. package/dist/Container.svelte.d.ts +0 -12
  7. package/dist/app.css +0 -235
  8. package/dist/index.d.ts +0 -5
  9. package/dist/index.js +0 -6
  10. package/dist/lang.d.ts +0 -1081
  11. package/dist/lang.js +0 -1096
  12. package/dist/lib/Accordion.svelte +0 -155
  13. package/dist/lib/Accordion.svelte.d.ts +0 -40
  14. package/dist/lib/Button.svelte +0 -170
  15. package/dist/lib/Button.svelte.d.ts +0 -53
  16. package/dist/lib/Card.svelte +0 -103
  17. package/dist/lib/Card.svelte.d.ts +0 -42
  18. package/dist/lib/Carousel.svelte +0 -293
  19. package/dist/lib/Carousel.svelte.d.ts +0 -13
  20. package/dist/lib/CheckBox.svelte +0 -210
  21. package/dist/lib/CheckBox.svelte.d.ts +0 -53
  22. package/dist/lib/CodeView.svelte +0 -307
  23. package/dist/lib/CodeView.svelte.d.ts +0 -64
  24. package/dist/lib/ColorPicker.svelte +0 -161
  25. package/dist/lib/ColorPicker.svelte.d.ts +0 -40
  26. package/dist/lib/DatePicker.svelte +0 -170
  27. package/dist/lib/DatePicker.svelte.d.ts +0 -53
  28. package/dist/lib/Dialog.svelte +0 -235
  29. package/dist/lib/Dialog.svelte.d.ts +0 -58
  30. package/dist/lib/Field.svelte +0 -299
  31. package/dist/lib/Field.svelte.d.ts +0 -8
  32. package/dist/lib/FilePicker.svelte +0 -241
  33. package/dist/lib/FilePicker.svelte.d.ts +0 -52
  34. package/dist/lib/Form.svelte +0 -438
  35. package/dist/lib/Form.svelte.d.ts +0 -20
  36. package/dist/lib/Hamburger.svelte +0 -211
  37. package/dist/lib/Hamburger.svelte.d.ts +0 -52
  38. package/dist/lib/Menu.svelte +0 -623
  39. package/dist/lib/Menu.svelte.d.ts +0 -33
  40. package/dist/lib/PaginatedCard.svelte +0 -73
  41. package/dist/lib/PaginatedCard.svelte.d.ts +0 -11
  42. package/dist/lib/Pagination.svelte +0 -119
  43. package/dist/lib/Pagination.svelte.d.ts +0 -9
  44. package/dist/lib/PrimaryColorSelect.svelte +0 -113
  45. package/dist/lib/PrimaryColorSelect.svelte.d.ts +0 -9
  46. package/dist/lib/ProgressBar.svelte +0 -141
  47. package/dist/lib/ProgressBar.svelte.d.ts +0 -48
  48. package/dist/lib/ProgressCircle.svelte +0 -192
  49. package/dist/lib/ProgressCircle.svelte.d.ts +0 -39
  50. package/dist/lib/Radio.svelte +0 -189
  51. package/dist/lib/Radio.svelte.d.ts +0 -55
  52. package/dist/lib/SearchInput.svelte +0 -106
  53. package/dist/lib/SearchInput.svelte.d.ts +0 -13
  54. package/dist/lib/Select.svelte +0 -524
  55. package/dist/lib/Select.svelte.d.ts +0 -21
  56. package/dist/lib/Slider.svelte +0 -253
  57. package/dist/lib/Slider.svelte.d.ts +0 -56
  58. package/dist/lib/Splitter.svelte +0 -150
  59. package/dist/lib/Splitter.svelte.d.ts +0 -43
  60. package/dist/lib/Switch.svelte +0 -167
  61. package/dist/lib/Switch.svelte.d.ts +0 -42
  62. package/dist/lib/Table.svelte +0 -299
  63. package/dist/lib/Table.svelte.d.ts +0 -17
  64. package/dist/lib/Tabs.svelte +0 -213
  65. package/dist/lib/Tabs.svelte.d.ts +0 -48
  66. package/dist/lib/ThemeToggle.svelte +0 -127
  67. package/dist/lib/ThemeToggle.svelte.d.ts +0 -32
  68. package/dist/lib/TimePicker.svelte +0 -269
  69. package/dist/lib/TimePicker.svelte.d.ts +0 -48
  70. package/dist/lib/Toast.svelte +0 -226
  71. package/dist/lib/Toast.svelte.d.ts +0 -14
  72. package/dist/lib/Tooltip.svelte +0 -110
  73. package/dist/lib/Tooltip.svelte.d.ts +0 -40
  74. package/dist/lib/index.d.ts +0 -32
  75. package/dist/lib/index.js +0 -33
  76. package/dist/lib/lang.d.ts +0 -158
  77. package/dist/lib/lang.js +0 -150
  78. package/dist/lib/types/index.d.ts +0 -111
  79. package/dist/lib/types/index.js +0 -26
  80. package/dist/main.d.ts +0 -3
  81. package/dist/main.js +0 -7
  82. package/dist/styles.css +0 -232
  83. package/dist/utils/index.d.ts +0 -34
  84. package/dist/utils/index.js +0 -268
@@ -1,299 +0,0 @@
1
- <!-- src/lib/Field.svelte -->
2
- <script lang="ts">
3
- /**
4
- * @component Field
5
- * @description Unified input/textarea field with label, leading/trailing content, clear button, and validation.
6
- *
7
- * @prop as {"input" | "textarea"} - Underlying element to render
8
- * @default "input"
9
- *
10
- * @prop label {string} - Label text rendered above the field
11
- *
12
- * @prop sz {SizeKey} - Size preset for spacing and typography
13
- * @options xs|sm|md|lg|xl
14
- * @default md
15
- *
16
- * @prop variant {FieldVariant} - Visual style variant
17
- * @options default|filled|neutral
18
- * @default default
19
- *
20
- * @prop clearable {boolean} - Shows a clear button for text inputs
21
- * @default true
22
- *
23
- * @prop rows {number} - Row count for textarea mode
24
- * @default 3
25
- *
26
- * @prop parseNumber {boolean} - Coerces numeric input when possible
27
- * @default false
28
- *
29
- * @prop leading {Snippet | string} - Leading content rendered inside the field
30
- *
31
- * @prop trailing {Snippet | string} - Trailing content rendered inside the field
32
- *
33
- * @prop onChange {(val: string | number) => void} - Fired when the value changes
34
- *
35
- * @prop value {string | number} - Controlled field value (bindable)
36
- * @default ""
37
- *
38
- * @prop class {string} - Additional classes applied to the root label
39
- * @default ""
40
- *
41
- * @prop id {string} - Custom id used for label and input linkage
42
- *
43
- * @prop type {string} - Input type when `as="input"`
44
- *
45
- * @prop invalid {boolean} - Marks the field invalid and sets `aria-invalid`
46
- * @default false
47
- *
48
- * @prop describedBy {string} - ID of helper or error text for accessibility
49
- *
50
- * @note `bind:value` is supported; `onChange` receives cast value (`number` when `parseNumber` succeeds, otherwise `string` or `""`).
51
- * @note Clear button appears only for text inputs (not for `type="number"`) and sets value to an empty string.
52
- * @note Automatic padding for leading/trailing content; label is linked via an auto-generated `id`.
53
- * @note Accessibility: sets `aria-invalid`, `aria-describedby`; number inputs also set `inputmode="decimal"`.
54
- */
55
- import type { Snippet } from "svelte";
56
- import type {
57
- HTMLInputAttributes,
58
- HTMLTextareaAttributes,
59
- } from "svelte/elements";
60
- import type { SizeKey, FieldVariant, FieldType } from "./types";
61
- import { TEXT } from "./types";
62
- import { uid, cx } from "../utils";
63
-
64
- type Props = (HTMLInputAttributes & HTMLTextareaAttributes & FieldType) & {
65
- value?: string | number;
66
- };
67
-
68
- let {
69
- as = "input",
70
- label,
71
- sz = "md",
72
- variant = "default",
73
- clearable = true,
74
- rows = 3,
75
- parseNumber = false,
76
- leading,
77
- trailing,
78
- onChange,
79
- value = $bindable<string | number>(""),
80
- class: externalClass = "",
81
- id: externalId,
82
- type,
83
- invalid = false,
84
- describedBy,
85
- ...rest
86
- }: Props = $props();
87
-
88
- const base =
89
- "w-full outline-none transition-colors duration-[var(--transition-fast)] ease-[var(--timing-default)] box-border rounded-[var(--radius-md)] border focus:border-[var(--border-color-focus)] focus:ring-2 focus:ring-[var(--border-color-focus)] disabled:opacity-[var(--opacity-disabled)] disabled:cursor-not-allowed";
90
-
91
- const sizes: Record<SizeKey, string> = {
92
- xs: "px-2 h-6",
93
- sm: "px-3 h-7",
94
- md: "px-4 h-8",
95
- lg: "px-5 h-9",
96
- xl: "px-6 h-10",
97
- };
98
-
99
- const variants: Record<FieldVariant, string> = {
100
- default:
101
- "bg-[var(--color-bg-surface)] [color:var(--color-text-default)] placeholder:[color:var(--color-text-muted)] border-[var(--border-color-default)]",
102
- filled:
103
- "bg-[var(--color-bg-muted)] [color:var(--color-text-default)] placeholder:[color:var(--color-text-muted)] border-[var(--border-color-default)]",
104
- neutral:
105
- "bg-transparent [color:var(--color-text-default)] placeholder:[color:var(--color-text-muted)] border-transparent hover:border-[var(--border-color-default)] focus:border-[var(--border-color-focus)]",
106
- };
107
-
108
- const rootClass = $derived(cx("flex flex-col gap-1", externalClass));
109
-
110
- const inputClass = $derived(
111
- as === "textarea"
112
- ? cx(base, variants[variant], TEXT.md, "px-4")
113
- : cx(base, sizes[sz], TEXT[sz], variants[variant])
114
- );
115
-
116
- const containerClass = $derived(
117
- cx("relative flex items-stretch", as === "textarea" && "items-start")
118
- );
119
-
120
- const id = $derived(externalId ?? uid("fld-"));
121
-
122
- const effectiveType = $derived(
123
- as === "input"
124
- ? type || (rest as HTMLInputAttributes).type || "text"
125
- : undefined
126
- );
127
-
128
- const isNumber = $derived(as === "input" && effectiveType === "number");
129
- const isPassword = $derived(as === "input" && effectiveType === "password");
130
-
131
- let showPassword = $state(false);
132
-
133
- function toOutgoing(v: string): string | number {
134
- if (parseNumber && isNumber) {
135
- if (v === "" || v === "-" || v === "." || v === "-.") {
136
- return v;
137
- }
138
- const n = Number(v);
139
- return Number.isNaN(n) ? "" : n;
140
- }
141
- return v;
142
- }
143
-
144
- function handleInput(e: Event) {
145
- const t = e.target as HTMLInputElement | HTMLTextAreaElement;
146
- const rawValue = t.value;
147
- const outgoing = toOutgoing(rawValue);
148
- value = outgoing;
149
- onChange?.(outgoing);
150
- }
151
-
152
- function clear() {
153
- const newValue = parseNumber && isNumber ? 0 : "";
154
- value = newValue;
155
- onChange?.(newValue);
156
- }
157
-
158
- const displayValue = $derived(String(value ?? ""));
159
- const showClear = $derived(
160
- clearable && as === "input" && displayValue.length > 0 && !isNumber
161
- );
162
- const needsRightPad = $derived(Boolean(trailing) || showClear || isPassword);
163
-
164
- const labelColor = "[color:var(--color-text-muted)]";
165
- </script>
166
-
167
- <label for={id} class={rootClass}>
168
- {#if label}
169
- <span class={cx(TEXT[sz], "font-medium", labelColor)}>{label}</span>
170
- {/if}
171
-
172
- <div class={containerClass}>
173
- {#if leading}
174
- {@const leadingIsSnippet = typeof leading === "function"}
175
- <div
176
- class={cx(
177
- "absolute inset-y-0 left-2 flex items-center [color:var(--color-text-muted)]"
178
- )}
179
- aria-hidden="true"
180
- >
181
- {#if leadingIsSnippet}
182
- {@render (leading as Snippet)()}
183
- {:else}
184
- {leading}
185
- {/if}
186
- </div>
187
- {/if}
188
-
189
- {#if as === "textarea"}
190
- <textarea
191
- {...rest}
192
- {id}
193
- {rows}
194
- class={cx(inputClass, needsRightPad && "pr-8", leading && "pl-8")}
195
- value={displayValue}
196
- aria-invalid={invalid || undefined}
197
- aria-describedby={describedBy}
198
- oninput={handleInput}
199
- ></textarea>
200
- {:else}
201
- <input
202
- {...rest}
203
- {id}
204
- type={isPassword ? (showPassword ? "text" : "password") : effectiveType}
205
- inputmode={isNumber ? "decimal" : undefined}
206
- class={cx(inputClass, needsRightPad && "pr-8", leading && "pl-8")}
207
- value={displayValue}
208
- aria-invalid={invalid || undefined}
209
- aria-describedby={describedBy}
210
- oninput={handleInput}
211
- />
212
- {/if}
213
-
214
- <div class={cx("absolute inset-y-0 right-2 flex items-center gap-1")}>
215
- {#if trailing}
216
- {@const trailingIsSnippet = typeof trailing === "function"}
217
- <span aria-hidden="true">
218
- {#if trailingIsSnippet}
219
- {@render (trailing as Snippet)()}
220
- {:else}
221
- {trailing}
222
- {/if}
223
- </span>
224
- {/if}
225
-
226
- {#if isPassword}
227
- <button
228
- type="button"
229
- class={cx("password-toggle [color:var(--color-text-muted)] hover:opacity-[var(--opacity-hover)]")}
230
- onmousedown={(e) => e.preventDefault()}
231
- onclick={() => (showPassword = !showPassword)}
232
- aria-label={showPassword ? "Hide password" : "Show password"}
233
- >
234
- {#if showPassword}
235
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
236
- <path d="M3 3L21 21" stroke="currentColor" stroke-width="2" />
237
- <path
238
- d="M10.5 10.677a2 2 0 002.823 2.823"
239
- stroke="currentColor"
240
- stroke-width="2"
241
- />
242
- <path
243
- d="M7.362 7.561C5.68 8.74 4.279 10.42 3 12c2.4 3.6 6 6 9 6 1.4 0 2.8-.5 4.1-1.2"
244
- stroke="currentColor"
245
- stroke-width="2"
246
- />
247
- <path
248
- d="M12 6c3 0 6 2.4 9 6-.6.9-1.3 1.7-2 2.5"
249
- stroke="currentColor"
250
- stroke-width="2"
251
- />
252
- </svg>
253
- {:else}
254
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
255
- <path
256
- d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"
257
- stroke="currentColor"
258
- stroke-width="2"
259
- />
260
- <circle
261
- cx="12"
262
- cy="12"
263
- r="3"
264
- stroke="currentColor"
265
- stroke-width="2"
266
- />
267
- </svg>
268
- {/if}
269
- </button>
270
- {/if}
271
-
272
- {#if showClear}
273
- <button
274
- type="button"
275
- tabindex="-1"
276
- onmousedown={(e) => e.preventDefault()}
277
- class={cx("[color:var(--color-text-muted)] hover:opacity-[var(--opacity-hover)]")}
278
- onclick={clear}
279
- aria-label="Clear"
280
- title="Clear"
281
- >
282
- <svg
283
- width="18"
284
- height="18"
285
- viewBox="0 0 24 24"
286
- fill="none"
287
- stroke="currentColor"
288
- stroke-width="2"
289
- stroke-linecap="round"
290
- stroke-linejoin="round"
291
- >
292
- <line x1="18" y1="6" x2="6" y2="18" />
293
- <line x1="6" y1="6" x2="18" y2="18" />
294
- </svg>
295
- </button>
296
- {/if}
297
- </div>
298
- </div>
299
- </label>
@@ -1,8 +0,0 @@
1
- import type { HTMLInputAttributes, HTMLTextareaAttributes } from "svelte/elements";
2
- import type { FieldType } from "./types";
3
- type Props = (HTMLInputAttributes & HTMLTextareaAttributes & FieldType) & {
4
- value?: string | number;
5
- };
6
- declare const Field: import("svelte").Component<Props, {}, "value">;
7
- type Field = ReturnType<typeof Field>;
8
- export default Field;
@@ -1,241 +0,0 @@
1
- <!-- src/lib/FilePicker.svelte -->
2
- <script lang="ts">
3
- /**
4
- * @component FilePicker
5
- * @description Lightweight file selector with click support and drag-and-drop. Internally uses a hidden `<input type="file">` plus a drop zone.
6
- *
7
- * @prop accept {string} - Accepted file types
8
- * @default "*\\/*"
9
- *
10
- * @prop multiple {boolean} - Allows selecting multiple files
11
- * @default false
12
- *
13
- * @prop label {string} - Button label; falls back to localized text
14
- *
15
- * @prop disabled {boolean} - Disables all interactions
16
- * @default false
17
- *
18
- * @prop clearable {boolean} - Shows a clear button to reset selection
19
- * @default true
20
- *
21
- * @prop placeholder {string} - Placeholder text for the drop zone
22
- *
23
- * @prop value {FileList | null} - Controlled selected files (bindable)
24
- * @default null
25
- *
26
- * @prop onFilesSelected {(files: FileList | null) => void} - Fired when files are chosen
27
- *
28
- * @prop onError {(error: string) => void} - Fired on validation errors
29
- *
30
- * @prop class {string} - Additional classes for the wrapper
31
- * @default ""
32
- *
33
- * @note The entire area is clickable and supports drag-and-drop.
34
- * @note After a selection, the underlying input resets its value, so choosing the same file twice still triggers updates.
35
- * @note `accept` does not apply to dropped files, only to the picker UI; validate files inside `onFilesSelected`.
36
- * @note When `clearable=true`, the user can clear selected files and the callback receives `null`.
37
- * @note When `disabled=true`, clicks, drag events, focus, and keyboard input are blocked.
38
- */
39
- import type { HTMLAttributes } from "svelte/elements";
40
- import { getContext } from "svelte";
41
- import Button from "./Button.svelte";
42
- import { cx } from "../utils";
43
- import { TEXTS } from "./lang";
44
-
45
- type Props = HTMLAttributes<HTMLDivElement> & {
46
- accept?: string;
47
- multiple?: boolean;
48
- label?: string;
49
- disabled?: boolean;
50
- clearable?: boolean;
51
- placeholder?: string;
52
- value?: FileList | null;
53
- onFilesSelected?: (files: FileList | null) => void;
54
- onError?: (error: string) => void;
55
- class?: string;
56
- };
57
-
58
- let {
59
- accept = "*/*",
60
- multiple = false,
61
- label,
62
- disabled = false,
63
- clearable = true,
64
- placeholder,
65
- value: propValue = null,
66
- onFilesSelected,
67
- class: externalClass = "",
68
- ...rest
69
- }: Props = $props();
70
-
71
- const lang = getContext<{ value: keyof typeof TEXTS }>("lang");
72
- const L = $derived(TEXTS[lang.value].components.filePicker);
73
-
74
- const labelFinal = $derived(label ?? L.text);
75
- const placeholderFinal = $derived(placeholder ?? L.placeholder);
76
-
77
- let inputEl: HTMLInputElement;
78
- let internalValue: FileList | null = $derived(propValue);
79
- let isDragOver = $state(false);
80
-
81
- const base = "inline-block w-full";
82
- const pickerClass = $derived(cx(base, externalClass));
83
-
84
- const hasValue = $derived(Boolean(internalValue && internalValue.length > 0));
85
- const fileNames = $derived(
86
- internalValue
87
- ? Array.from(internalValue)
88
- .map((file) => file.name)
89
- .join(", ")
90
- : ""
91
- );
92
-
93
- function handleButtonClick() {
94
- if (disabled) return;
95
- inputEl?.click();
96
- }
97
-
98
- function handleFileChange(event: Event) {
99
- const target = event.target as HTMLInputElement;
100
- const files = target.files;
101
- internalValue = files;
102
- if (files && files.length > 0) {
103
- onFilesSelected?.(files);
104
- }
105
- }
106
-
107
- function handleDrop(event: DragEvent) {
108
- event.preventDefault();
109
- isDragOver = false;
110
- if (disabled) return;
111
- const files = event.dataTransfer?.files;
112
- internalValue = files || null;
113
- if (files && files.length > 0) {
114
- onFilesSelected?.(files);
115
- }
116
- }
117
-
118
- function handleDragOver(event: DragEvent) {
119
- event.preventDefault();
120
- }
121
-
122
- function handleDragEnter(event: DragEvent) {
123
- event.preventDefault();
124
- if (!disabled) {
125
- isDragOver = true;
126
- }
127
- }
128
-
129
- function handleDragLeave(event: DragEvent) {
130
- event.preventDefault();
131
- isDragOver = false;
132
- }
133
-
134
- function handleKeyDown(event: KeyboardEvent) {
135
- if (disabled) return;
136
- if (event.key === "Enter" || event.key === " ") {
137
- event.preventDefault();
138
- handleButtonClick();
139
- }
140
- }
141
-
142
- function clearSelection() {
143
- if (!clearable) return;
144
- internalValue = null;
145
- if (inputEl) {
146
- inputEl.value = "";
147
- }
148
- onFilesSelected?.(null);
149
- }
150
- </script>
151
-
152
- <div class={pickerClass} {...rest}>
153
- <input
154
- bind:this={inputEl}
155
- type="file"
156
- {accept}
157
- {multiple}
158
- class="hidden"
159
- onchange={handleFileChange}
160
- />
161
-
162
- <div class="flex flex-wrap items-center gap-x-3 gap-y-2">
163
- <Button {disabled} onClick={handleButtonClick} class="relative" sz="xs">
164
- {labelFinal}
165
- </Button>
166
-
167
- {#if clearable}
168
- <Button
169
- onClick={clearSelection}
170
- variant="danger"
171
- disabled={!hasValue || disabled}
172
- sz="xs"
173
- >
174
- {L.clear}
175
- </Button>
176
- {/if}
177
- </div>
178
-
179
- <div
180
- class="mt-2 p-4 border-2 border-dashed rounded-[var(--radius-md)] text-center transition-colors duration-200"
181
- class:border-[var(--color-primary)]={isDragOver && !disabled}
182
- class:border-[var(--border-color-default)]={!isDragOver || disabled}
183
- class:bg-[var(--color-bg-surface-hover)]={isDragOver && !disabled}
184
- class:cursor-pointer={!disabled}
185
- class:opacity-[var(--opacity-disabled)]={disabled}
186
- class:cursor-not-allowed={disabled}
187
- class:cursor-copy={isDragOver && !disabled}
188
- role="button"
189
- tabindex={disabled ? -1 : 0}
190
- aria-disabled={disabled}
191
- ondrop={handleDrop}
192
- ondragover={handleDragOver}
193
- ondragenter={handleDragEnter}
194
- ondragleave={handleDragLeave}
195
- onclick={handleButtonClick}
196
- onkeydown={handleKeyDown}
197
- >
198
- <p class="text-sm [color:var(--color-text-muted)]">
199
- {L.dragDrop}
200
- </p>
201
- {#if accept !== "*/*"}
202
- <p class="text-xs mt-1 [color:var(--color-text-muted)]">
203
- {L.accepted}: {accept}
204
- </p>
205
- {/if}
206
- </div>
207
-
208
- <div
209
- class="mt-3 p-4 bg-[var(--color-bg-surface)] text-center"
210
- aria-live="polite"
211
- >
212
- <p class="text-xs uppercase tracking-wide [color:var(--color-text-muted)]">
213
- {L.selectedFiles}
214
- </p>
215
- <p
216
- class="text-sm font-semibold mt-1 [color:var(--color-text-default)] break-words"
217
- >
218
- {#if hasValue}
219
- {fileNames}
220
- {:else}
221
- {placeholderFinal}
222
- {/if}
223
- </p>
224
- {#if hasValue && internalValue}
225
- <p class="text-sm mt-1 [color:var(--color-text-muted)]">
226
- {L.fileCount.replace("{n}", String(internalValue.length))}
227
-
228
- {#if multiple && internalValue.length > 1}
229
- • {L.totalSize}: {(
230
- Array.from(internalValue).reduce(
231
- (acc, file) => acc + file.size,
232
- 0
233
- ) /
234
- 1024 /
235
- 1024
236
- ).toFixed(2)} MB
237
- {/if}
238
- </p>
239
- {/if}
240
- </div>
241
- </div>
@@ -1,52 +0,0 @@
1
- /**
2
- * @component FilePicker
3
- * @description Lightweight file selector with click support and drag-and-drop. Internally uses a hidden `<input type="file">` plus a drop zone.
4
- *
5
- * @prop accept {string} - Accepted file types
6
- * @default "*\\/*"
7
- *
8
- * @prop multiple {boolean} - Allows selecting multiple files
9
- * @default false
10
- *
11
- * @prop label {string} - Button label; falls back to localized text
12
- *
13
- * @prop disabled {boolean} - Disables all interactions
14
- * @default false
15
- *
16
- * @prop clearable {boolean} - Shows a clear button to reset selection
17
- * @default true
18
- *
19
- * @prop placeholder {string} - Placeholder text for the drop zone
20
- *
21
- * @prop value {FileList | null} - Controlled selected files (bindable)
22
- * @default null
23
- *
24
- * @prop onFilesSelected {(files: FileList | null) => void} - Fired when files are chosen
25
- *
26
- * @prop onError {(error: string) => void} - Fired on validation errors
27
- *
28
- * @prop class {string} - Additional classes for the wrapper
29
- * @default ""
30
- *
31
- * @note The entire area is clickable and supports drag-and-drop.
32
- * @note After a selection, the underlying input resets its value, so choosing the same file twice still triggers updates.
33
- * @note `accept` does not apply to dropped files, only to the picker UI; validate files inside `onFilesSelected`.
34
- * @note When `clearable=true`, the user can clear selected files and the callback receives `null`.
35
- * @note When `disabled=true`, clicks, drag events, focus, and keyboard input are blocked.
36
- */
37
- import type { HTMLAttributes } from "svelte/elements";
38
- type Props = HTMLAttributes<HTMLDivElement> & {
39
- accept?: string;
40
- multiple?: boolean;
41
- label?: string;
42
- disabled?: boolean;
43
- clearable?: boolean;
44
- placeholder?: string;
45
- value?: FileList | null;
46
- onFilesSelected?: (files: FileList | null) => void;
47
- onError?: (error: string) => void;
48
- class?: string;
49
- };
50
- declare const FilePicker: import("svelte").Component<Props, {}, "">;
51
- type FilePicker = ReturnType<typeof FilePicker>;
52
- export default FilePicker;