@joewinke/jatui 0.1.26 → 0.1.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/CLAUDE.md +3 -3
- package/dist/actions/collapse.d.ts +1 -1
- package/dist/actions/collapse.js +1 -1
- package/dist/actions/listNav.d.ts +134 -0
- package/dist/actions/listNav.js +672 -0
- package/dist/actions/railNav.js +7 -1
- package/dist/components/InlineEdit.svelte +26 -1
- package/dist/components/InlineEdit.svelte.d.ts +13 -0
- package/dist/components/PhoneInput.svelte +70 -20
- package/dist/components/PhoneInput.svelte.d.ts +5 -2
- package/dist/components/ResizableDivider.svelte +148 -18
- package/dist/components/ResizableDivider.svelte.d.ts +14 -3
- package/dist/components/SearchDropdown.svelte +437 -172
- package/dist/components/SearchDropdown.svelte.d.ts +17 -1
- package/dist/components/SignaturePad.svelte +13 -6
- package/dist/components/SignaturePad.svelte.d.ts +1 -0
- package/dist/components/ThemeSelector.svelte +61 -2
- package/dist/components/ThemeSelector.svelte.d.ts +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/package.json +6 -2
package/CLAUDE.md
CHANGED
|
@@ -24,9 +24,9 @@ Then import:
|
|
|
24
24
|
| `TextInput` | Text input with label, error, icon slots | `label`, `value` (bindable), `placeholder`, `error`, `disabled` |
|
|
25
25
|
| `TextArea` | Multiline text input | `label`, `value` (bindable), `placeholder`, `rows`, `error`, `maxlength` |
|
|
26
26
|
| `SelectInput` | Dropdown select | `label`, `value` (bindable), `options: SelectOption[]`, `placeholder` |
|
|
27
|
-
| `PhoneInput` | Intl phone (country dropdown + tel input, outputs E.164) | `value` (bindable), `name`, `defaultCountry`, `required` |
|
|
27
|
+
| `PhoneInput` | Intl phone (country dropdown + tel input, outputs E.164; caps national digits per country). Fires `onChange(value)` on every change. | `value` (bindable), `name`, `defaultCountry`, `required`, `onChange` |
|
|
28
28
|
| `ChipInput` | Tag/chip entry with suggestions | `chips` (bindable), `suggestions: SuggestionGroup[]`, `placeholder` |
|
|
29
|
-
| `SearchDropdown` | Searchable dropdown with grouped results | `groups: SearchDropdownGroup[]`, `placeholder`, `
|
|
29
|
+
| `SearchDropdown` | Searchable dropdown with grouped results, keyboard nav, avatar/initials options. `appendToBody` escapes table/overflow stacking contexts; `variant='chip'` renders a compact pill; `size='sm'` a smaller trigger; `dropup` opens upward; `clearable` shows an × when a value is set. Exposes `openDropdown()`. | `groups: SearchDropdownGroup[]`, `value`, `onChange`, `placeholder`, `variant`, `size`, `dropup`, `appendToBody`, `clearable`, `colorFn` |
|
|
30
30
|
| `FilterDropdown` | Multi-select filter dropdown | `label`, `options: string[]`, `selected: Set<string>` (bindable) |
|
|
31
31
|
| `SortDropdown` | Sort by column with direction | `options: SortOption[]`, `sortBy` (bindable), `sortDir` (bindable) |
|
|
32
32
|
| `InlineEdit` | Click-to-edit text | `value` (bindable), `segments: DisplaySegment[]`, `onSave` |
|
|
@@ -37,7 +37,7 @@ Then import:
|
|
|
37
37
|
| `SmartImageEditor` | AI-powered image upload with background removal and multi-variant processing pipeline. **Preferred over `ImageUpload` in editor contexts.** Two modes: simple (drop-in replacement, outputs blob URL) and editor (POST multipart to backend → variant grid). | `value` (bindable), `spec?: ImageProcessingSpec`, `uploadEndpoint?`, `onComplete?`, `accept?`, `maxSizeMb?` |
|
|
38
38
|
| `FileDropzone` | Multi-file/folder/ZIP drag-drop upload zone. Handles FileSystem API folder recursion, MIME/size validation, and shows a pending-file grid. Calls `onFilesSelected(files, errors)` with validated `File[]`. Accepts already-uploaded files via `uploadedFiles: FileDropzoneFile[]` for post-upload display. | `accept?: string[]`, `maxSize?`, `maxFiles?`, `multiple?`, `uploadedFiles?`, `isUploading?`, `isExtracting?`, `dropLabel?`, `dropSubtext?`, `onFilesSelected?` |
|
|
39
39
|
| `FileThumbnail` | File thumbnail with MIME-aware icon fallback. Shows an `<img>` for image files (with loading/error states) and typed icons for PDF, ZIP, CAD, and generic files. Size variants: `sm`, `md`, `lg`, `xl`. | `name`, `mimeType`, `url?`, `size?` |
|
|
40
|
-
| `SignaturePad` | Draw signature on canvas
|
|
40
|
+
| `SignaturePad` | Draw signature on canvas (mouse + touch). Emits base64 PNG on each stroke-end via bindable `signatureData` or `onSignatureChange(data)`. Exposes `clear()`/`isEmpty()`. Pass `disabled` for a dimmed, non-interactive preview. | `signatureData` (bindable), `onSignatureChange`, `label`, `width`, `height`, `disabled`, `required` |
|
|
41
41
|
|
|
42
42
|
### Scheduling & Time
|
|
43
43
|
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* ─── Usage — action form (most sites) ─────────────────────────────────────────
|
|
34
34
|
*
|
|
35
35
|
* <script>
|
|
36
|
-
* import { collapse } from '
|
|
36
|
+
* import { collapse } from '../../../dist'
|
|
37
37
|
* let collapsible = $state(false)
|
|
38
38
|
* let expanded = $state(false)
|
|
39
39
|
* const bodyId = `collapse-${$props.id()}`
|
package/dist/actions/collapse.js
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* ─── Usage — action form (most sites) ─────────────────────────────────────────
|
|
34
34
|
*
|
|
35
35
|
* <script>
|
|
36
|
-
* import { collapse } from '
|
|
36
|
+
* import { collapse } from '../../../dist'
|
|
37
37
|
* let collapsible = $state(false)
|
|
38
38
|
* let expanded = $state(false)
|
|
39
39
|
* const bodyId = `collapse-${$props.id()}`
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared keyboard-navigation action + composable for list-like UIs.
|
|
3
|
+
*
|
|
4
|
+
* Base motions — j/k / ArrowDown/ArrowUp with wraparound, Enter/Space to
|
|
5
|
+
* trigger select, Escape to clear focus. Typing targets (input, textarea,
|
|
6
|
+
* select, contenteditable) and most modifier combos are skipped so the
|
|
7
|
+
* shortcuts never interfere with typing or app-level keybindings.
|
|
8
|
+
*
|
|
9
|
+
* Vim-motion layer (always on):
|
|
10
|
+
*
|
|
11
|
+
* gg jump to first item
|
|
12
|
+
* G jump to last item
|
|
13
|
+
* {n}j / {n}k move `n` items (count-prefix buffer with 1.5s timeout)
|
|
14
|
+
* {n}G, {n}gg jump to 1-indexed line `n` (clamped to list length)
|
|
15
|
+
* Ctrl+D / Ctrl+U move roughly half a viewport's worth of items
|
|
16
|
+
* zz scroll the focused item to the centre of its viewport
|
|
17
|
+
*
|
|
18
|
+
* Selection layer (opt-in via `selectable: true`):
|
|
19
|
+
*
|
|
20
|
+
* V toggle visual mode (anchor at current focus, selects it)
|
|
21
|
+
* j / k while visual mode is on, also extends the range from anchor
|
|
22
|
+
* x toggle selection of the focused item (no movement)
|
|
23
|
+
* Shift+J / K toggle current + move down/up + toggle new focus (range-build)
|
|
24
|
+
* * toggle select-all of the currently visible items
|
|
25
|
+
* Escape backs out one layer at a time:
|
|
26
|
+
* pending motion → visual mode → selection → focus / onEscape
|
|
27
|
+
*
|
|
28
|
+
* Selected items get the `selected-class` (default `jk-selected`) so pages
|
|
29
|
+
* can style them. The controller exposes selectedIds()/clearSelection()/
|
|
30
|
+
* selectAll()/toggleSelection()/isSelecting() and fires onSelectionChange
|
|
31
|
+
* whenever the set mutates. A floating `BulkActionBar` is the canonical
|
|
32
|
+
* chip for surfacing the count + per-route bulk actions.
|
|
33
|
+
*
|
|
34
|
+
* Usage — action form (simplest):
|
|
35
|
+
*
|
|
36
|
+
* <div use:listNav={{
|
|
37
|
+
* onSelect: (el, idx) => openDetail(el.dataset.navId!),
|
|
38
|
+
* onEscape: () => closeDetail(),
|
|
39
|
+
* }}>
|
|
40
|
+
* {#each items as item}
|
|
41
|
+
* <button data-nav-id={item.id}>{item.title}</button>
|
|
42
|
+
* {/each}
|
|
43
|
+
* </div>
|
|
44
|
+
*
|
|
45
|
+
* Usage — composable form (when you already have a keydown handler):
|
|
46
|
+
*
|
|
47
|
+
* const nav = createListNav({
|
|
48
|
+
* getItems: () => Array.from(container.querySelectorAll('[data-nav-id]')),
|
|
49
|
+
* onSelect: (el) => openDetail(el.dataset.navId!),
|
|
50
|
+
* selectable: true,
|
|
51
|
+
* onSelectionChange: (ids) => { selectedIds = ids; },
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* function onKeydown(e: KeyboardEvent) {
|
|
55
|
+
* if (nav.handleKeydown(e)) return;
|
|
56
|
+
* // ...page-specific shortcuts
|
|
57
|
+
* }
|
|
58
|
+
*/
|
|
59
|
+
import type { Action } from 'svelte/action';
|
|
60
|
+
export interface ListNavOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Return the navigable HTML elements in list order. Called on every
|
|
63
|
+
* navigation event so reactive lists stay in sync. When omitted in the
|
|
64
|
+
* action form, the action queries the node itself using {@link itemSelector}.
|
|
65
|
+
*/
|
|
66
|
+
getItems?: () => HTMLElement[] | ArrayLike<HTMLElement>;
|
|
67
|
+
/** CSS selector used by the action to locate items. Default: `[data-nav-id]`. */
|
|
68
|
+
itemSelector?: string;
|
|
69
|
+
/** Fired when Enter or Space is pressed on the focused item. */
|
|
70
|
+
onSelect?: (item: HTMLElement, index: number) => void;
|
|
71
|
+
/** Fired when Escape is pressed. Default behaviour: clears focus. */
|
|
72
|
+
onEscape?: () => void;
|
|
73
|
+
/** Fired whenever the focused index changes (including cleared focus). */
|
|
74
|
+
onFocusChange?: (item: HTMLElement | null, index: number) => void;
|
|
75
|
+
/** When true, j at the last item wraps to first (and vice-versa). Default: true. */
|
|
76
|
+
wraparound?: boolean;
|
|
77
|
+
/** Class applied to the currently focused item. Default: `jk-focused`. */
|
|
78
|
+
focusedClass?: string;
|
|
79
|
+
/** When false, all shortcuts no-op. Default: true. */
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
/** Action-only. When true, listen on window; when false, on the node. Default: true. */
|
|
82
|
+
global?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Enable the selection layer (V / Shift+J / Shift+K / x / *). Default: false.
|
|
85
|
+
* When false, those keys pass through unhandled so pages can keep them.
|
|
86
|
+
*/
|
|
87
|
+
selectable?: boolean;
|
|
88
|
+
/** Class applied to selected items. Default: `jk-selected`. */
|
|
89
|
+
selectedClass?: string;
|
|
90
|
+
/** Fires whenever the selection set mutates. Receives a fresh Set snapshot. */
|
|
91
|
+
onSelectionChange?: (ids: Set<string>) => void;
|
|
92
|
+
/**
|
|
93
|
+
* Resolve an item's stable id. Default: `el.dataset.navId`. Override if
|
|
94
|
+
* your items use a different attribute (e.g. `data-rule-nav-id`).
|
|
95
|
+
*/
|
|
96
|
+
getItemId?: (el: HTMLElement) => string | null | undefined;
|
|
97
|
+
}
|
|
98
|
+
export interface KeyboardShortcut {
|
|
99
|
+
key: string;
|
|
100
|
+
description: string;
|
|
101
|
+
}
|
|
102
|
+
export interface ListNavController {
|
|
103
|
+
/** Returns true if the event was handled (preventDefault was called). */
|
|
104
|
+
handleKeydown(event: KeyboardEvent): boolean;
|
|
105
|
+
focusedIndex(): number;
|
|
106
|
+
focus(index: number): void;
|
|
107
|
+
focusFirst(): void;
|
|
108
|
+
focusLast(): void;
|
|
109
|
+
clear(): void;
|
|
110
|
+
/** Re-apply the focused class after items change (e.g. after a filter). */
|
|
111
|
+
refresh(): void;
|
|
112
|
+
/** Read-only snapshot of selected item ids. */
|
|
113
|
+
selectedIds(): Set<string>;
|
|
114
|
+
/** Toggle selection. With no arg, toggles the focused item. */
|
|
115
|
+
toggleSelection(navId?: string): void;
|
|
116
|
+
/** Replace the selection with the given ids (or clear if empty). */
|
|
117
|
+
setSelection(ids: Iterable<string>): void;
|
|
118
|
+
/** Drop the selection and exit visual mode. */
|
|
119
|
+
clearSelection(): void;
|
|
120
|
+
/** Toggle select-all of the currently visible items. */
|
|
121
|
+
selectAll(): void;
|
|
122
|
+
/** True while visual-mode (V) is active. */
|
|
123
|
+
isSelecting(): boolean;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Imperative composable — use when you already own a keydown handler and want
|
|
127
|
+
* listNav to decide whether to consume the event.
|
|
128
|
+
*/
|
|
129
|
+
export declare function createListNav(options: ListNavOptions): ListNavController;
|
|
130
|
+
/**
|
|
131
|
+
* Svelte action — attaches a keydown listener (window by default) and handles
|
|
132
|
+
* j/k/ArrowDown/ArrowUp/Enter/Space/Escape navigation over children of `node`.
|
|
133
|
+
*/
|
|
134
|
+
export declare const listNav: Action<HTMLElement, ListNavOptions | undefined>;
|