@spaethtech/svelte-ui 0.13.0 → 0.14.0

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.d.ts CHANGED
@@ -19,6 +19,8 @@ export { default as Input } from "./components/Input.svelte";
19
19
  export { default as NotesEditor } from "./components/NotesEditor.svelte";
20
20
  export { default as Rating } from "./components/Rating.svelte";
21
21
  export { default as Select } from "./components/Select.svelte";
22
+ export { Combobox } from "./components/Combobox/index.js";
23
+ export { TokenInput } from "./components/TokenInput/index.js";
22
24
  export { Slider } from "./components/Slider/index.js";
23
25
  export { default as List } from "./components/List.svelte";
24
26
  export { default as TextArea } from "./components/TextArea.svelte";
@@ -36,6 +38,9 @@ export { default as DatePicker } from "./components/DatePicker.svelte";
36
38
  export { default as TimeSpinner } from "./components/TimeSpinner.svelte";
37
39
  export { default as TimePicker } from "./components/TimePicker.svelte";
38
40
  export { default as TimeRangeInput } from "./components/TimeRangeInput.svelte";
41
+ export { DateRangePicker } from "./components/DateRangePicker/index.js";
42
+ export { FileUpload } from "./components/FileUpload/index.js";
43
+ export type { RangePreset } from "./components/DateRangePicker/index.js";
39
44
  export { default as ThemeSelector } from "./components/ThemeSelector.svelte";
40
45
  export { default as ThemeToggle } from "./components/ThemeToggle.svelte";
41
46
  export { default as Popup } from "./components/Popup.svelte";
@@ -50,6 +55,8 @@ export { default as FieldGroup } from "./components/FieldGroup.svelte";
50
55
  export { default as Grid } from "./components/Grid.svelte";
51
56
  export { Divider } from "./components/Divider/index.js";
52
57
  export type { Columns, Gap } from "./components/field-group.js";
58
+ export { Stepper } from "./components/Stepper/index.js";
59
+ export type { StepItem } from "./components/Stepper/index.js";
53
60
  export { default as Disclosure } from "./components/Disclosure.svelte";
54
61
  export { default as Accordion } from "./components/Accordion.svelte";
55
62
  export { default as SideBarMenu } from "./components/SideBarMenu/SideBarMenu.svelte";
package/dist/index.js CHANGED
@@ -20,6 +20,8 @@ export { default as Input } from "./components/Input.svelte";
20
20
  export { default as NotesEditor } from "./components/NotesEditor.svelte";
21
21
  export { default as Rating } from "./components/Rating.svelte";
22
22
  export { default as Select } from "./components/Select.svelte";
23
+ export { Combobox } from "./components/Combobox/index.js";
24
+ export { TokenInput } from "./components/TokenInput/index.js";
23
25
  export { Slider } from "./components/Slider/index.js";
24
26
  export { default as List } from "./components/List.svelte";
25
27
  export { default as TextArea } from "./components/TextArea.svelte";
@@ -38,6 +40,8 @@ export { default as DatePicker } from "./components/DatePicker.svelte";
38
40
  export { default as TimeSpinner } from "./components/TimeSpinner.svelte";
39
41
  export { default as TimePicker } from "./components/TimePicker.svelte";
40
42
  export { default as TimeRangeInput } from "./components/TimeRangeInput.svelte";
43
+ export { DateRangePicker } from "./components/DateRangePicker/index.js";
44
+ export { FileUpload } from "./components/FileUpload/index.js";
41
45
  // Theme Components
42
46
  export { default as ThemeSelector } from "./components/ThemeSelector.svelte";
43
47
  export { default as ThemeToggle } from "./components/ThemeToggle.svelte";
@@ -51,6 +55,7 @@ export { default as Radio } from "./components/Radio.svelte";
51
55
  export { default as FieldGroup } from "./components/FieldGroup.svelte";
52
56
  export { default as Grid } from "./components/Grid.svelte";
53
57
  export { Divider } from "./components/Divider/index.js";
58
+ export { Stepper } from "./components/Stepper/index.js";
54
59
  export { default as Disclosure } from "./components/Disclosure.svelte";
55
60
  export { default as Accordion } from "./components/Accordion.svelte";
56
61
  // Navigation Components
@@ -79,6 +79,63 @@ Custom dropdown built on `Input` + `List`.
79
79
  `maxResults`, `headers`, `searchTerm`)
80
80
  - **Modes**: static `options` or search-as-you-type against `url`
81
81
 
82
+ ### Combobox
83
+
84
+ Free-text autocomplete — a text input with a suggestion listbox. Unlike `Select` (a closed choice),
85
+ the value is arbitrary text and options are suggestions.
86
+
87
+ - **Location**: `src/lib/components/Combobox/Combobox.svelte`
88
+ - **Axes**: `variant`, `size`
89
+ - **Props**: `value` (bindable text), `options` (`string[]`, client substring filter) OR
90
+ `suggest` (`(q) => Promise<string[]>`, debounced by `debounceMs`, gated by `minChars`), `maxResults`,
91
+ `onselect`, `icon`, `placeholder`, plus the FieldChrome vocabulary (`label`/`aside`/`error`/
92
+ `description`/`id`/`required`), `class`
93
+ - **Keyboard**: ↓/↑ highlight, Enter select, Esc close, Tab close; options select on pointerdown
94
+ - **Accessibility**: `role="combobox"` + `aria-autocomplete`/`-expanded`/`-controls`/`-activedescendant`;
95
+ `role="listbox"`/`option`
96
+ - **Composition**: `Input` (FieldChrome + frame + anchor + trailing chevron) + `Popup` (listbox)
97
+
98
+ ### TokenInput
99
+
100
+ Multi-value entry — Enter/comma adds a removable `Chip` token.
101
+
102
+ - **Location**: `src/lib/components/TokenInput/TokenInput.svelte`
103
+ - **Axes**: `variant` (border + chip accent), `size`
104
+ - **Props**: `values` (bindable `string[]`), `allowDuplicates`, `max`, `disabled`, `placeholder`,
105
+ plus the FieldChrome vocabulary (`label`/`aside`/`error`/`description`/`id`/`required`), `class`
106
+ - **Behavior**: Enter/comma commits the trimmed draft (skips empty/duplicate/at-max); Backspace on an
107
+ empty draft removes the last token; each token's × removes it
108
+ - **Composition**: a `<label>` (click-to-focus) wrapping `Chip` tokens + a bare `<input>`; the field
109
+ border matches `Input` (variant tint at rest / focus-within, error override)
110
+
111
+ ### FileUpload
112
+
113
+ Drag-and-drop + click file field with thumbnails, remove, and optional progress.
114
+
115
+ - **Location**: `src/lib/components/FileUpload/FileUpload.svelte`
116
+ - **Axes**: `variant` (drag accent + browse button), `size`
117
+ - **Props**: `files` (bindable `File[]`), `accept`, `multiple`, `maxSize` (bytes; rejects oversized),
118
+ `progress` (`Record<name, 0–100>` → per-file `Progress`), `onfiles`, plus FieldChrome, `class`
119
+ - **Behavior**: drop or Browse adds; `!multiple` replaces; duplicates skipped; image thumbnails (object
120
+ URLs, revoked on remove/unmount); each file has a × remove
121
+ - **Accessibility**: focusable `role="button"` dropzone (Enter/Space opens the picker); hidden
122
+ `<input type=file>`; labelled remove ×s
123
+ - **Composition**: `Button` + `Progress`; FieldChrome for label/error
124
+
125
+ ### DateRangePicker
126
+
127
+ Start–end date range with a presets rail; composes `Calendar mode="range"` + `Input` + `Popup`.
128
+
129
+ - **Location**: `src/lib/components/DateRangePicker/DateRangePicker.svelte`
130
+ - **Axes**: `variant`, `size`
131
+ - **Props**: `start`/`end` (bindable ISO), `min`/`max`, `presets` (`RangePreset[]`; default set, `[]`
132
+ hides the rail), `format`, `placeholder`, plus FieldChrome (`label`/`aside`/`error`/`description`/
133
+ `id`/`required`), `class`
134
+ - **Behavior**: readonly `Input` trigger shows the formatted range; the popup pairs a presets column
135
+ (`Button` ghost) with the range calendar; a preset or the second calendar pick closes it
136
+ - **Note**: `DatePicker range` covers a bare range (object value, no presets); this is the
137
+ presets-first, `bind:start`/`bind:end` variant
138
+
82
139
  ### Slider
83
140
 
84
141
  Draggable range input — a single value or a `[min, max]` pair.
@@ -192,6 +249,19 @@ A thin separating rule.
192
249
  - **Accessibility**: `role="separator"` + `aria-orientation` (plain horizontal uses `<hr>`)
193
250
  - **Theming**: line = `--ui-border-color`; label muted. Vertical stretches to the row via `self-stretch`.
194
251
 
252
+ ### Stepper
253
+
254
+ Step indicator for a linear multi-step flow (wizard).
255
+
256
+ - **Location**: `src/lib/components/Stepper/Stepper.svelte`
257
+ - **Axes**: `variant` (done/current markers + connectors), `size`
258
+ - **Props**: `steps` (`StepItem[]` = `{ label, description?, icon? }`), `current` (bindable, 0-based),
259
+ `orientation` (`horizontal`/`vertical`), `onstep` (clickable markers), `class`
260
+ - **Behavior**: `i<current` done (check), `i===current` current, `i>current` upcoming; connectors fill
261
+ up to `current`. Shows position only — panels + Next/Back + validation are the consumer's.
262
+ - **Accessibility**: `<ol>`/`<li>`; `aria-current="step"` on the active marker; clickable markers are
263
+ `<button>`s with an accessible name
264
+
195
265
  ### Disclosure
196
266
 
197
267
  A single expand/collapse section — a `<Button>` header (title + rotating chevron) over a content
package/docs/usage.md CHANGED
@@ -295,6 +295,92 @@ A neutral placeholder shown while content loads. Compose primitives to sketch th
295
295
  </Card>
296
296
  ```
297
297
 
298
+ ### FileUpload
299
+
300
+ A drag-and-drop + click file field (thumbnails, remove, optional progress).
301
+
302
+ ```svelte
303
+ <script>
304
+ import { FileUpload } from "@spaethtech/svelte-ui";
305
+ let files = $state([]);
306
+ // filename → 0-100, driven by your upload
307
+ let progress = $state({});
308
+ </script>
309
+
310
+ <FileUpload bind:files {progress} multiple accept="image/*,.pdf" maxSize={5 * 1024 * 1024}
311
+ label="Attachments" onfiles={(f) => console.log(f)} />
312
+ ```
313
+
314
+ ### DateRangePicker
315
+
316
+ A start–end range with a presets rail (composes `Calendar mode="range"`).
317
+
318
+ ```svelte
319
+ <script>
320
+ import { DateRangePicker } from "@spaethtech/svelte-ui";
321
+ let start = $state("");
322
+ let end = $state("");
323
+ </script>
324
+
325
+ <DateRangePicker bind:start bind:end label="Reporting period" />
326
+
327
+ <!-- custom presets, or presets={[]} for calendar-only -->
328
+ <DateRangePicker bind:start bind:end presets={[{ label: "Q1", start: "2026-01-01", end: "2026-03-31" }]} />
329
+ ```
330
+
331
+ ### Stepper
332
+
333
+ A step indicator for a wizard; your panels + Next/Back drive `current`.
334
+
335
+ ```svelte
336
+ <script>
337
+ import { Stepper, Button } from "@spaethtech/svelte-ui";
338
+ const steps = [{ label: "Account" }, { label: "Profile" }, { label: "Review" }];
339
+ let current = $state(0);
340
+ </script>
341
+
342
+ <Stepper {steps} bind:current onstep={(i) => (i <= current ? (current = i) : null)} />
343
+
344
+ <!-- your step panels here -->
345
+ <Button text="Back" onclick={() => current--} disabled={current === 0} />
346
+ <Button text="Next" variant="primary" onclick={() => current++} />
347
+ ```
348
+
349
+ ### TokenInput
350
+
351
+ Multi-value entry — Enter/comma adds a removable token.
352
+
353
+ ```svelte
354
+ <script>
355
+ import { TokenInput } from "@spaethtech/svelte-ui";
356
+ let tags = $state(["svelte", "ui"]);
357
+ </script>
358
+
359
+ <!-- Type + Enter/comma to add; × or Backspace-on-empty to remove -->
360
+ <TokenInput bind:values={tags} label="Tags" placeholder="Add a tag…" max={8} />
361
+ ```
362
+
363
+ ### Combobox
364
+
365
+ Free-text autocomplete — a text input with suggestions (vs `Select`, a closed choice).
366
+
367
+ ```svelte
368
+ <script>
369
+ import { Combobox } from "@spaethtech/svelte-ui";
370
+ const FRUITS = ["Apple", "Banana", "Cherry"];
371
+ let fruit = $state("");
372
+
373
+ // Async: return string[] for the query
374
+ const suggest = async (q) => (await fetch("/api/cities?q=" + q)).json();
375
+ </script>
376
+
377
+ <!-- Client-side filter -->
378
+ <Combobox bind:value={fruit} options={FRUITS} label="Fruit" placeholder="Type to filter…" />
379
+
380
+ <!-- Async suggestions (debounced) -->
381
+ <Combobox bind:value={fruit} {suggest} minChars={1} label="City" />
382
+ ```
383
+
298
384
  ### Slider
299
385
 
300
386
  A draggable range input — a single value or a `[min, max]` pair. A form field (wears FieldChrome).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaethtech/svelte-ui",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/spaethtech/svelte-ui.git"