@joewinke/jatui 0.1.27 → 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/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
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Exports `clear()` and `isEmpty()` methods. Outputs signature as base64 PNG data URL
|
|
6
6
|
* via the bindable `signatureData` prop or `onSignatureChange` callback.
|
|
7
|
+
*
|
|
8
|
+
* Pass `disabled` to render a non-interactive, dimmed pad (e.g. form-builder previews).
|
|
7
9
|
*/
|
|
8
10
|
import { onMount } from 'svelte';
|
|
9
11
|
|
|
@@ -17,6 +19,7 @@
|
|
|
17
19
|
label = 'Signature',
|
|
18
20
|
required = false,
|
|
19
21
|
placeholder = 'Sign here',
|
|
22
|
+
disabled = false,
|
|
20
23
|
}: {
|
|
21
24
|
signatureData?: string;
|
|
22
25
|
onSignatureChange?: (data: string) => void;
|
|
@@ -27,6 +30,7 @@
|
|
|
27
30
|
label?: string;
|
|
28
31
|
required?: boolean;
|
|
29
32
|
placeholder?: string;
|
|
33
|
+
disabled?: boolean;
|
|
30
34
|
} = $props();
|
|
31
35
|
|
|
32
36
|
let canvas: HTMLCanvasElement;
|
|
@@ -68,6 +72,7 @@
|
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
function startDrawing(e: MouseEvent | TouchEvent) {
|
|
75
|
+
if (disabled) return;
|
|
71
76
|
e.preventDefault();
|
|
72
77
|
isDrawing = true;
|
|
73
78
|
const coords = getCoordinates(e);
|
|
@@ -76,7 +81,7 @@
|
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
function draw(e: MouseEvent | TouchEvent) {
|
|
79
|
-
if (!isDrawing || !ctx) return;
|
|
84
|
+
if (disabled || !isDrawing || !ctx) return;
|
|
80
85
|
e.preventDefault();
|
|
81
86
|
|
|
82
87
|
const coords = getCoordinates(e);
|
|
@@ -145,19 +150,21 @@
|
|
|
145
150
|
<span class="text-error">*</span>
|
|
146
151
|
{/if}
|
|
147
152
|
</span>
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
{#if !disabled}
|
|
154
|
+
<button type="button" onclick={() => clear()} class="btn btn-ghost btn-xs">
|
|
155
|
+
Clear
|
|
156
|
+
</button>
|
|
157
|
+
{/if}
|
|
151
158
|
</div>
|
|
152
159
|
{/if}
|
|
153
160
|
|
|
154
161
|
<div class="rounded-lg bg-base-100 overflow-hidden relative transition-all duration-300
|
|
155
|
-
{hasDrawn ? 'border-2 border-success/60' : 'border-2 border-base-300'}">
|
|
162
|
+
{disabled ? 'opacity-50 border-2 border-base-300' : hasDrawn ? 'border-2 border-success/60' : 'border-2 border-base-300'}">
|
|
156
163
|
<canvas
|
|
157
164
|
bind:this={canvas}
|
|
158
165
|
{width}
|
|
159
166
|
{height}
|
|
160
|
-
class="w-full touch-none cursor-crosshair"
|
|
167
|
+
class="w-full touch-none {disabled ? 'cursor-not-allowed' : 'cursor-crosshair'}"
|
|
161
168
|
></canvas>
|
|
162
169
|
|
|
163
170
|
{#if !hasDrawn}
|
|
@@ -53,12 +53,18 @@
|
|
|
53
53
|
defaultTheme = 'light',
|
|
54
54
|
storageKey = 'theme',
|
|
55
55
|
onThemeChange,
|
|
56
|
+
compact = false,
|
|
57
|
+
inline = false,
|
|
56
58
|
}: {
|
|
57
59
|
dropUp?: boolean;
|
|
58
60
|
themes?: ThemeOption[];
|
|
59
61
|
defaultTheme?: string;
|
|
60
62
|
storageKey?: string;
|
|
61
63
|
onThemeChange?: (theme: string) => void;
|
|
64
|
+
/** Icon-only trigger (label hidden, shown as tooltip). Dropdown mode only. */
|
|
65
|
+
compact?: boolean;
|
|
66
|
+
/** Render a collapsible `<details>` theme list instead of a dropdown — for embedding inside another menu. */
|
|
67
|
+
inline?: boolean;
|
|
62
68
|
} = $props();
|
|
63
69
|
|
|
64
70
|
// svelte-ignore state_referenced_locally
|
|
@@ -104,6 +110,51 @@
|
|
|
104
110
|
}
|
|
105
111
|
</script>
|
|
106
112
|
|
|
113
|
+
{#if inline}
|
|
114
|
+
<!-- Inline mode: collapsible theme list with color previews, for embedding inside another menu -->
|
|
115
|
+
<details class="w-full theme-details">
|
|
116
|
+
<summary class="flex items-center gap-2 cursor-pointer hover:bg-base-300 transition-colors px-2 py-1.5 rounded list-none">
|
|
117
|
+
<div
|
|
118
|
+
data-theme={currentTheme}
|
|
119
|
+
class="bg-base-100 grid shrink-0 grid-cols-2 gap-0.5 rounded p-0.5 w-4 h-4 transition-transform duration-300 ease-out"
|
|
120
|
+
class:theme-spin={isAnimating}
|
|
121
|
+
>
|
|
122
|
+
<div class="bg-base-content size-1 rounded-full transition-all duration-300 theme-dot" class:theme-dot-animate={isAnimating} style="--dot-delay: 0ms"></div>
|
|
123
|
+
<div class="bg-primary size-1 rounded-full transition-all duration-300 theme-dot" class:theme-dot-animate={isAnimating} style="--dot-delay: 50ms"></div>
|
|
124
|
+
<div class="bg-secondary size-1 rounded-full transition-all duration-300 theme-dot" class:theme-dot-animate={isAnimating} style="--dot-delay: 100ms"></div>
|
|
125
|
+
<div class="bg-accent size-1 rounded-full transition-all duration-300 theme-dot" class:theme-dot-animate={isAnimating} style="--dot-delay: 150ms"></div>
|
|
126
|
+
</div>
|
|
127
|
+
<span class="text-[0.75rem] flex-1 text-left text-base-content/70">{currentThemeLabel}</span>
|
|
128
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-3 h-3 text-base-content/45 transition-transform duration-200 details-chevron">
|
|
129
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
|
|
130
|
+
</svg>
|
|
131
|
+
</summary>
|
|
132
|
+
<div class="max-h-48 overflow-y-auto mt-1 ml-2 border-l border-base-content/10 pl-2">
|
|
133
|
+
{#each themes as theme}
|
|
134
|
+
<button
|
|
135
|
+
class="flex items-center gap-2 w-full px-2 py-1 rounded transition-colors hover:bg-base-300 {currentTheme === theme.name ? 'bg-primary/20' : ''}"
|
|
136
|
+
onclick={() => handleThemeChange(theme.name)}
|
|
137
|
+
>
|
|
138
|
+
<div
|
|
139
|
+
data-theme={theme.name}
|
|
140
|
+
class="bg-base-100 grid shrink-0 grid-cols-2 gap-0.5 rounded p-0.5 w-4 h-4"
|
|
141
|
+
>
|
|
142
|
+
<div class="bg-base-content size-1 rounded-full"></div>
|
|
143
|
+
<div class="bg-primary size-1 rounded-full"></div>
|
|
144
|
+
<div class="bg-secondary size-1 rounded-full"></div>
|
|
145
|
+
<div class="bg-accent size-1 rounded-full"></div>
|
|
146
|
+
</div>
|
|
147
|
+
<span class="text-[0.75rem] text-base-content/70 flex-1 text-left">{theme.label}</span>
|
|
148
|
+
{#if currentTheme === theme.name}
|
|
149
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="w-3 h-3 text-primary">
|
|
150
|
+
<path d="M20.285 2l-11.285 11.567-5.286-5.011-3.714 3.716 9 8.728 15-15.285z"></path>
|
|
151
|
+
</svg>
|
|
152
|
+
{/if}
|
|
153
|
+
</button>
|
|
154
|
+
{/each}
|
|
155
|
+
</div>
|
|
156
|
+
</details>
|
|
157
|
+
{:else}
|
|
107
158
|
<div class="dropdown dropdown-end" class:dropdown-top={dropUp}>
|
|
108
159
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
109
160
|
<div
|
|
@@ -111,7 +162,7 @@
|
|
|
111
162
|
role="button"
|
|
112
163
|
class="flex items-center gap-2 cursor-pointer hover:bg-base-300 transition-colors px-2 py-1 rounded"
|
|
113
164
|
aria-label="Change Theme"
|
|
114
|
-
title=
|
|
165
|
+
title={compact ? currentThemeLabel : 'Change Theme'}
|
|
115
166
|
>
|
|
116
167
|
<div
|
|
117
168
|
data-theme={currentTheme}
|
|
@@ -123,7 +174,9 @@
|
|
|
123
174
|
<div class="bg-secondary size-1 rounded-full transition-all duration-300 theme-dot" class:theme-dot-animate={isAnimating} style="--dot-delay: 100ms"></div>
|
|
124
175
|
<div class="bg-accent size-1 rounded-full transition-all duration-300 theme-dot" class:theme-dot-animate={isAnimating} style="--dot-delay: 150ms"></div>
|
|
125
176
|
</div>
|
|
126
|
-
|
|
177
|
+
{#if !compact}
|
|
178
|
+
<span class="text-sm font-medium transition-opacity duration-200" class:opacity-50={isAnimating}>{currentThemeLabel}</span>
|
|
179
|
+
{/if}
|
|
127
180
|
</div>
|
|
128
181
|
|
|
129
182
|
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
@@ -171,8 +224,14 @@
|
|
|
171
224
|
</ul>
|
|
172
225
|
</div>
|
|
173
226
|
</div>
|
|
227
|
+
{/if}
|
|
174
228
|
|
|
175
229
|
<style>
|
|
230
|
+
/* Rotate chevron when the inline details list is open */
|
|
231
|
+
.theme-details[open] .details-chevron {
|
|
232
|
+
transform: rotate(180deg);
|
|
233
|
+
}
|
|
234
|
+
|
|
176
235
|
/* NOTE: DaisyUI v5.0.0 has a stuck-animation bug on `.dropdown-content`
|
|
177
236
|
(`@keyframes dropdown { 0% { opacity: 0 } }` pins opacity to 0). If the
|
|
178
237
|
theme dropdown opens but stays invisible, the consuming project needs
|
|
@@ -8,6 +8,10 @@ type $$ComponentProps = {
|
|
|
8
8
|
defaultTheme?: string;
|
|
9
9
|
storageKey?: string;
|
|
10
10
|
onThemeChange?: (theme: string) => void;
|
|
11
|
+
/** Icon-only trigger (label hidden, shown as tooltip). Dropdown mode only. */
|
|
12
|
+
compact?: boolean;
|
|
13
|
+
/** Render a collapsible `<details>` theme list instead of a dropdown — for embedding inside another menu. */
|
|
14
|
+
inline?: boolean;
|
|
11
15
|
};
|
|
12
16
|
declare const ThemeSelector: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
13
17
|
type ThemeSelector = ReturnType<typeof ThemeSelector>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { railNav, createRailNav, cycle } from './actions/railNav';
|
|
2
2
|
export type { RailNavOptions, RailNavController } from './actions/railNav';
|
|
3
|
+
export { listNav, createListNav } from './actions/listNav';
|
|
4
|
+
export type { ListNavOptions, ListNavController } from './actions/listNav';
|
|
3
5
|
export { collapse } from './actions/collapse';
|
|
4
6
|
export type { CollapseOptions } from './actions/collapse';
|
|
5
7
|
export { default as Collapse } from './components/Collapse.svelte';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Actions
|
|
2
2
|
export { railNav, createRailNav, cycle } from './actions/railNav';
|
|
3
|
+
export { listNav, createListNav } from './actions/listNav';
|
|
3
4
|
export { collapse } from './actions/collapse';
|
|
4
5
|
export { default as Collapse } from './components/Collapse.svelte';
|
|
5
6
|
// Components — Session primitives (from JAT IDE, jat-jj79f.16 G1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joewinke/jatui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.28",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared Svelte 5 component library for JAT projects",
|
|
6
6
|
"type": "module",
|
|
@@ -20,10 +20,13 @@
|
|
|
20
20
|
"README.md"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"dev": "vite dev --port 5180",
|
|
23
|
+
"dev": "npm run package && vite dev --port 5180",
|
|
24
24
|
"build": "vite build",
|
|
25
|
+
"build:site": "npm run package && vite build",
|
|
25
26
|
"preview": "vite preview",
|
|
26
27
|
"package": "svelte-package --input src/lib --output dist",
|
|
28
|
+
"check:demos": "node scripts/check-demo-coverage.mjs",
|
|
29
|
+
"guard": "node scripts/check-demo-coverage.mjs",
|
|
27
30
|
"prepublishOnly": "npm run package"
|
|
28
31
|
},
|
|
29
32
|
"peerDependencies": {
|
|
@@ -45,6 +48,7 @@
|
|
|
45
48
|
},
|
|
46
49
|
"devDependencies": {
|
|
47
50
|
"@sveltejs/adapter-auto": "^6.0.0",
|
|
51
|
+
"@sveltejs/adapter-static": "^3.0.10",
|
|
48
52
|
"@sveltejs/kit": "^2.21.0",
|
|
49
53
|
"@sveltejs/package": "^2.5.8",
|
|
50
54
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|