@daltonr/pathwrite-svelte 0.6.3 → 0.8.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/LICENSE +1 -1
- package/README.md +6 -1
- package/dist/PathShell.svelte +50 -7
- package/dist/PathShell.svelte.d.ts +9 -1
- package/dist/PathShell.svelte.d.ts.map +1 -1
- package/dist/index.css +109 -0
- package/dist/index.svelte.d.ts +4 -1
- package/dist/index.svelte.d.ts.map +1 -1
- package/dist/index.svelte.js +2 -0
- package/package.json +2 -2
- package/src/PathShell.svelte +50 -7
- package/src/index.svelte.ts +8 -0
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -532,7 +532,7 @@ setData('invalid', 'value');
|
|
|
532
532
|
|
|
533
533
|
## License
|
|
534
534
|
|
|
535
|
-
MIT
|
|
535
|
+
MIT — © 2026 Devjoy Ltd.
|
|
536
536
|
|
|
537
537
|
## See Also
|
|
538
538
|
|
|
@@ -540,3 +540,8 @@ MIT
|
|
|
540
540
|
- [@daltonr/pathwrite-store-http](../store-http) - HTTP persistence
|
|
541
541
|
- [Documentation](../../docs/guides/DEVELOPER_GUIDE.md)
|
|
542
542
|
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
© 2026 Devjoy Ltd. MIT License.
|
|
547
|
+
|
package/dist/PathShell.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import { usePath, setPathContext } from './index.svelte.js';
|
|
4
|
-
import type { PathDefinition, PathData, PathEngine, PathSnapshot } from './index.svelte.js';
|
|
4
|
+
import type { PathDefinition, PathData, PathEngine, PathSnapshot, ProgressLayout } from './index.svelte.js';
|
|
5
5
|
import type { Snippet } from 'svelte';
|
|
6
6
|
|
|
7
7
|
/** Converts a camelCase or lowercase field key to a display label. */
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
* - `"both"`: Render the shell summary AND whatever the step template renders.
|
|
35
35
|
*/
|
|
36
36
|
validationDisplay?: "summary" | "inline" | "both";
|
|
37
|
+
/**
|
|
38
|
+
* Controls how progress bars are arranged when a sub-path is active.
|
|
39
|
+
* - "merged" (default): Root and sub-path bars in one card.
|
|
40
|
+
* - "split": Root and sub-path bars as separate cards.
|
|
41
|
+
* - "rootOnly": Only the root bar — sub-path bar hidden.
|
|
42
|
+
* - "activeOnly": Only the active (sub-path) bar — root bar hidden.
|
|
43
|
+
*/
|
|
44
|
+
progressLayout?: ProgressLayout;
|
|
37
45
|
// Callback props replace event dispatching in Svelte 5
|
|
38
46
|
oncomplete?: (data: PathData) => void;
|
|
39
47
|
oncancel?: (data: PathData) => void;
|
|
@@ -58,6 +66,7 @@
|
|
|
58
66
|
hideProgress = false,
|
|
59
67
|
footerLayout = 'auto',
|
|
60
68
|
validationDisplay = 'inline',
|
|
69
|
+
progressLayout = 'merged',
|
|
61
70
|
oncomplete,
|
|
62
71
|
oncancel,
|
|
63
72
|
onevent,
|
|
@@ -123,7 +132,7 @@
|
|
|
123
132
|
}
|
|
124
133
|
</script>
|
|
125
134
|
|
|
126
|
-
<div class="pw-shell">
|
|
135
|
+
<div class="pw-shell {progressLayout !== 'merged' ? `pw-shell--progress-${progressLayout}` : ''}">
|
|
127
136
|
{#if !snap}
|
|
128
137
|
<div class="pw-shell__empty">
|
|
129
138
|
<p>No active path.</p>
|
|
@@ -134,8 +143,27 @@
|
|
|
134
143
|
{/if}
|
|
135
144
|
</div>
|
|
136
145
|
{:else}
|
|
146
|
+
<!-- Root progress: persistent top-level bar visible during sub-paths -->
|
|
147
|
+
{#if !hideProgress && snap.rootProgress && progressLayout !== 'activeOnly'}
|
|
148
|
+
<div class="pw-shell__root-progress">
|
|
149
|
+
<div class="pw-shell__steps">
|
|
150
|
+
{#each snap.rootProgress.steps as step, i}
|
|
151
|
+
<div class="pw-shell__step pw-shell__step--{step.status}">
|
|
152
|
+
<span class="pw-shell__step-dot">
|
|
153
|
+
{step.status === 'completed' ? '✓' : i + 1}
|
|
154
|
+
</span>
|
|
155
|
+
<span class="pw-shell__step-label">{step.title ?? step.id}</span>
|
|
156
|
+
</div>
|
|
157
|
+
{/each}
|
|
158
|
+
</div>
|
|
159
|
+
<div class="pw-shell__track">
|
|
160
|
+
<div class="pw-shell__track-fill" style="width: {snap.rootProgress.progress * 100}%"></div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
{/if}
|
|
164
|
+
|
|
137
165
|
<!-- Header: progress indicator (overridable via header snippet) -->
|
|
138
|
-
{#if !hideProgress}
|
|
166
|
+
{#if !hideProgress && progressLayout !== 'rootOnly'}
|
|
139
167
|
{#if header}
|
|
140
168
|
{@render header(snap)}
|
|
141
169
|
{:else if snap.stepCount > 1 || snap.nestingLevel > 0}
|
|
@@ -157,9 +185,13 @@
|
|
|
157
185
|
{/if}
|
|
158
186
|
{/if}
|
|
159
187
|
|
|
160
|
-
<!-- Body: current step rendered via named snippet
|
|
188
|
+
<!-- Body: current step rendered via named snippet.
|
|
189
|
+
Prefer formId (inner step id of a StepChoice) so consumers can
|
|
190
|
+
register snippets by inner step ids directly. -->
|
|
161
191
|
<div class="pw-shell__body">
|
|
162
|
-
{#if stepSnippets[snap.
|
|
192
|
+
{#if snap.formId && stepSnippets[snap.formId]}
|
|
193
|
+
{@render stepSnippets[snap.formId]()}
|
|
194
|
+
{:else if stepSnippets[snap.stepId]}
|
|
163
195
|
{@render stepSnippets[snap.stepId]()}
|
|
164
196
|
{:else}
|
|
165
197
|
<p>No content for step "{snap.stepId}"</p>
|
|
@@ -167,9 +199,9 @@
|
|
|
167
199
|
</div>
|
|
168
200
|
|
|
169
201
|
<!-- Validation messages — suppressed when validationDisplay="inline" -->
|
|
170
|
-
{#if validationDisplay !== 'inline' && snap.hasAttemptedNext && Object.keys(snap.
|
|
202
|
+
{#if validationDisplay !== 'inline' && snap.hasAttemptedNext && Object.keys(snap.fieldErrors).length > 0}
|
|
171
203
|
<ul class="pw-shell__validation">
|
|
172
|
-
{#each Object.entries(snap.
|
|
204
|
+
{#each Object.entries(snap.fieldErrors) as [key, msg]}
|
|
173
205
|
<li class="pw-shell__validation-item">
|
|
174
206
|
{#if key !== '_'}<span class="pw-shell__validation-label">{formatFieldKey(key)}</span>{/if}{msg}
|
|
175
207
|
</li>
|
|
@@ -177,6 +209,17 @@
|
|
|
177
209
|
</ul>
|
|
178
210
|
{/if}
|
|
179
211
|
|
|
212
|
+
<!-- Warning messages — non-blocking, shown immediately (no hasAttemptedNext gate) -->
|
|
213
|
+
{#if validationDisplay !== 'inline' && Object.keys(snap.fieldWarnings).length > 0}
|
|
214
|
+
<ul class="pw-shell__warnings">
|
|
215
|
+
{#each Object.entries(snap.fieldWarnings) as [key, msg]}
|
|
216
|
+
<li class="pw-shell__warnings-item">
|
|
217
|
+
{#if key !== '_'}<span class="pw-shell__warnings-label">{formatFieldKey(key)}</span>{/if}{msg}
|
|
218
|
+
</li>
|
|
219
|
+
{/each}
|
|
220
|
+
</ul>
|
|
221
|
+
{/if}
|
|
222
|
+
|
|
180
223
|
<!-- Footer: navigation buttons (overridable via footer snippet) -->
|
|
181
224
|
{#if footer}
|
|
182
225
|
{@render footer(snap, actions)}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PathDefinition, PathData, PathEngine, PathSnapshot } from './index.svelte.js';
|
|
1
|
+
import type { PathDefinition, PathData, PathEngine, PathSnapshot, ProgressLayout } from './index.svelte.js';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
interface Props {
|
|
4
4
|
path?: PathDefinition<any>;
|
|
@@ -25,6 +25,14 @@ interface Props {
|
|
|
25
25
|
* - `"both"`: Render the shell summary AND whatever the step template renders.
|
|
26
26
|
*/
|
|
27
27
|
validationDisplay?: "summary" | "inline" | "both";
|
|
28
|
+
/**
|
|
29
|
+
* Controls how progress bars are arranged when a sub-path is active.
|
|
30
|
+
* - "merged" (default): Root and sub-path bars in one card.
|
|
31
|
+
* - "split": Root and sub-path bars as separate cards.
|
|
32
|
+
* - "rootOnly": Only the root bar — sub-path bar hidden.
|
|
33
|
+
* - "activeOnly": Only the active (sub-path) bar — root bar hidden.
|
|
34
|
+
*/
|
|
35
|
+
progressLayout?: ProgressLayout;
|
|
28
36
|
oncomplete?: (data: PathData) => void;
|
|
29
37
|
oncancel?: (data: PathData) => void;
|
|
30
38
|
onevent?: (event: any) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PathShell.svelte.d.ts","sourceRoot":"","sources":["../src/PathShell.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"PathShell.svelte.d.ts","sourceRoot":"","sources":["../src/PathShell.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC5G,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGpC,UAAU,KAAK;IACb,IAAI,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1C;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAE/B,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAE9C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC;CAC9B;AAyNH,QAAA,MAAM,SAAS;mBAlIQ,QAAQ,IAAI,CAAC;MAkImB,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
package/dist/index.css
CHANGED
|
@@ -77,6 +77,75 @@
|
|
|
77
77
|
font-size: 14px;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/* ------------------------------------------------------------------ */
|
|
81
|
+
/* Root progress — persistent top-level bar visible during sub-paths */
|
|
82
|
+
/* ------------------------------------------------------------------ */
|
|
83
|
+
.pw-shell__root-progress {
|
|
84
|
+
background: var(--pw-color-bg);
|
|
85
|
+
border: 1px solid var(--pw-color-border);
|
|
86
|
+
border-radius: var(--pw-shell-radius);
|
|
87
|
+
padding: 20px 24px 16px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.pw-shell__root-progress .pw-shell__steps {
|
|
91
|
+
display: flex;
|
|
92
|
+
justify-content: space-between;
|
|
93
|
+
margin-bottom: 12px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.pw-shell__root-progress .pw-shell__step {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
align-items: center;
|
|
100
|
+
gap: 6px;
|
|
101
|
+
flex: 1;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Merge root progress + sub-path header into a single card */
|
|
105
|
+
.pw-shell__root-progress + .pw-shell__header {
|
|
106
|
+
margin-top: calc(-1 * var(--pw-shell-gap));
|
|
107
|
+
border-top: 1px solid var(--pw-color-border);
|
|
108
|
+
border-top-left-radius: 0;
|
|
109
|
+
border-top-right-radius: 0;
|
|
110
|
+
padding: 12px 24px 12px;
|
|
111
|
+
opacity: 0.6;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.pw-shell__root-progress:has(+ .pw-shell__header) {
|
|
115
|
+
border-bottom-left-radius: 0;
|
|
116
|
+
border-bottom-right-radius: 0;
|
|
117
|
+
padding-bottom: 12px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.pw-shell__root-progress + .pw-shell__header .pw-shell__steps {
|
|
121
|
+
margin-bottom: 6px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.pw-shell__root-progress + .pw-shell__header .pw-shell__step-dot {
|
|
125
|
+
width: 22px;
|
|
126
|
+
height: 22px;
|
|
127
|
+
font-size: 10px;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.pw-shell__root-progress + .pw-shell__header .pw-shell__step-label {
|
|
131
|
+
font-size: 10px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.pw-shell__root-progress + .pw-shell__header .pw-shell__track {
|
|
135
|
+
height: 3px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Split layout — disable the merged-card effect */
|
|
139
|
+
.pw-shell--progress-split .pw-shell__root-progress + .pw-shell__header {
|
|
140
|
+
margin-top: 0;
|
|
141
|
+
border-top: 1px solid var(--pw-color-border);
|
|
142
|
+
border-radius: var(--pw-shell-radius);
|
|
143
|
+
}
|
|
144
|
+
.pw-shell--progress-split .pw-shell__root-progress:has(+ .pw-shell__header) {
|
|
145
|
+
border-radius: var(--pw-shell-radius);
|
|
146
|
+
padding-bottom: 16px;
|
|
147
|
+
}
|
|
148
|
+
|
|
80
149
|
/* ------------------------------------------------------------------ */
|
|
81
150
|
/* Header — progress indicator */
|
|
82
151
|
/* ------------------------------------------------------------------ */
|
|
@@ -177,6 +246,9 @@
|
|
|
177
246
|
--pw-color-error: #dc2626;
|
|
178
247
|
--pw-color-error-bg: #fef2f2;
|
|
179
248
|
--pw-color-error-border: #fecaca;
|
|
249
|
+
--pw-color-warning: #d97706;
|
|
250
|
+
--pw-color-warning-bg: #fffbeb;
|
|
251
|
+
--pw-color-warning-border: #fde68a;
|
|
180
252
|
}
|
|
181
253
|
|
|
182
254
|
.pw-shell__validation {
|
|
@@ -213,6 +285,43 @@
|
|
|
213
285
|
content: ":";
|
|
214
286
|
}
|
|
215
287
|
|
|
288
|
+
/* ------------------------------------------------------------------ */
|
|
289
|
+
/* Warning messages */
|
|
290
|
+
/* ------------------------------------------------------------------ */
|
|
291
|
+
.pw-shell__warnings {
|
|
292
|
+
list-style: none;
|
|
293
|
+
margin: 0;
|
|
294
|
+
padding: 12px 16px;
|
|
295
|
+
background: var(--pw-color-warning-bg);
|
|
296
|
+
border: 1px solid var(--pw-color-warning-border);
|
|
297
|
+
border-radius: var(--pw-shell-radius);
|
|
298
|
+
display: flex;
|
|
299
|
+
flex-direction: column;
|
|
300
|
+
gap: 4px;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.pw-shell__warnings-item {
|
|
304
|
+
font-size: 13px;
|
|
305
|
+
color: var(--pw-color-warning);
|
|
306
|
+
padding-left: 16px;
|
|
307
|
+
position: relative;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.pw-shell__warnings-item::before {
|
|
311
|
+
content: "•";
|
|
312
|
+
position: absolute;
|
|
313
|
+
left: 4px;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.pw-shell__warnings-label {
|
|
317
|
+
font-weight: 600;
|
|
318
|
+
margin-right: 3px;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.pw-shell__warnings-label::after {
|
|
322
|
+
content: ":";
|
|
323
|
+
}
|
|
324
|
+
|
|
216
325
|
/* ------------------------------------------------------------------ */
|
|
217
326
|
/* Footer — navigation buttons */
|
|
218
327
|
/* ------------------------------------------------------------------ */
|
package/dist/index.svelte.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PathData, PathDefinition, PathEngine, PathEvent, PathSnapshot } from "@daltonr/pathwrite-core";
|
|
2
|
-
export type { PathData, FieldErrors, PathDefinition, PathEngine, PathEvent, PathSnapshot, PathStep, PathStepContext, SerializedPathState } from "@daltonr/pathwrite-core";
|
|
2
|
+
export type { PathData, FieldErrors, PathDefinition, PathEngine, PathEvent, PathSnapshot, PathStep, PathStepContext, ProgressLayout, RootProgress, SerializedPathState } from "@daltonr/pathwrite-core";
|
|
3
3
|
export interface UsePathOptions {
|
|
4
4
|
/**
|
|
5
5
|
* An externally-managed `PathEngine` to subscribe to — for example, the engine
|
|
@@ -34,6 +34,8 @@ export interface UsePathReturn<TData extends PathData = PathData> {
|
|
|
34
34
|
goToStepChecked: (stepId: string) => Promise<void>;
|
|
35
35
|
/** Update a single data value; triggers a re-render via stateChanged. When `TData` is specified, `key` and `value` are type-checked against your data shape. */
|
|
36
36
|
setData: <K extends string & keyof TData>(key: K, value: TData[K]) => Promise<void>;
|
|
37
|
+
/** Reset the current step's data to what it was when the step was entered. Useful for "Clear" or "Reset" buttons. */
|
|
38
|
+
resetStep: () => Promise<void>;
|
|
37
39
|
/**
|
|
38
40
|
* Tear down any active path (without firing hooks) and immediately start the
|
|
39
41
|
* given path fresh. Safe to call whether or not a path is currently active.
|
|
@@ -77,6 +79,7 @@ export interface PathContext<TData extends PathData = PathData> {
|
|
|
77
79
|
goToStep: (stepId: string) => Promise<void>;
|
|
78
80
|
goToStepChecked: (stepId: string) => Promise<void>;
|
|
79
81
|
setData: <K extends string & keyof TData>(key: K, value: TData[K]) => Promise<void>;
|
|
82
|
+
resetStep: () => Promise<void>;
|
|
80
83
|
restart: () => Promise<void>;
|
|
81
84
|
}
|
|
82
85
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.svelte.d.ts","sourceRoot":"","sources":["../src/index.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACb,MAAM,yBAAyB,CAAC;AAIjC,YAAY,EACV,QAAQ,EACR,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,mFAAmF;IACnF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,aAAa,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ;IAC9D,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC9C,iCAAiC;IACjC,KAAK,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,6MAA6M;IAC7M,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnH,6DAA6D;IAC7D,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,qJAAqJ;IACrJ,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,iGAAiG;IACjG,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,oLAAoL;IACpL,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,gKAAgK;IAChK,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF;;;;OAIG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,OAAO,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,EACvD,OAAO,CAAC,EAAE,cAAc,GACvB,aAAa,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.svelte.d.ts","sourceRoot":"","sources":["../src/index.svelte.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACb,MAAM,yBAAyB,CAAC;AAIjC,YAAY,EACV,QAAQ,EACR,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,cAAc,EACd,YAAY,EACZ,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAMjC,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,mFAAmF;IACnF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,aAAa,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ;IAC9D,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC9C,iCAAiC;IACjC,KAAK,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,6MAA6M;IAC7M,YAAY,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnH,6DAA6D;IAC7D,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,qJAAqJ;IACrJ,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,iGAAiG;IACjG,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,oLAAoL;IACpL,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,gKAAgK;IAChK,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,qHAAqH;IACrH,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B;;;;OAIG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,OAAO,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,EACvD,OAAO,CAAC,EAAE,cAAc,GACvB,aAAa,CAAC,KAAK,CAAC,CA0DtB;AAQD,MAAM,WAAW,WAAW,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ;IAC5D,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAC9C,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,KAAK,WAAW,CAAC,KAAK,CAAC,CAStF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,EAAE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAE/F;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,QAAQ,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,EAC7E,WAAW,EAAE,MAAM,YAAY,CAAC,KAAK,CAAC,GAAG,IAAI,EAC7C,OAAO,EAAE,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EACzF,GAAG,EAAE,CAAC,GACL;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;CAAE,CAS9D;AAGD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.svelte.js
CHANGED
|
@@ -54,6 +54,7 @@ export function usePath(options) {
|
|
|
54
54
|
const goToStep = (stepId) => engine.goToStep(stepId);
|
|
55
55
|
const goToStepChecked = (stepId) => engine.goToStepChecked(stepId);
|
|
56
56
|
const setData = ((key, value) => engine.setData(key, value));
|
|
57
|
+
const resetStep = () => engine.resetStep();
|
|
57
58
|
const restart = (path, initialData = {}) => engine.restart(path, initialData);
|
|
58
59
|
return {
|
|
59
60
|
get snapshot() { return _snapshot; },
|
|
@@ -65,6 +66,7 @@ export function usePath(options) {
|
|
|
65
66
|
goToStep,
|
|
66
67
|
goToStepChecked,
|
|
67
68
|
setData,
|
|
69
|
+
resetStep,
|
|
68
70
|
restart
|
|
69
71
|
};
|
|
70
72
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@daltonr/pathwrite-svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Svelte 5 adapter for @daltonr/pathwrite-core — runes-based reactive bindings and optional PathShell component.",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"svelte": ">=5.0.0"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@daltonr/pathwrite-core": "^0.
|
|
55
|
+
"@daltonr/pathwrite-core": "^0.8.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@sveltejs/package": "^2.5.7",
|
package/src/PathShell.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
import { usePath, setPathContext } from './index.svelte.js';
|
|
4
|
-
import type { PathDefinition, PathData, PathEngine, PathSnapshot } from './index.svelte.js';
|
|
4
|
+
import type { PathDefinition, PathData, PathEngine, PathSnapshot, ProgressLayout } from './index.svelte.js';
|
|
5
5
|
import type { Snippet } from 'svelte';
|
|
6
6
|
|
|
7
7
|
/** Converts a camelCase or lowercase field key to a display label. */
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
* - `"both"`: Render the shell summary AND whatever the step template renders.
|
|
35
35
|
*/
|
|
36
36
|
validationDisplay?: "summary" | "inline" | "both";
|
|
37
|
+
/**
|
|
38
|
+
* Controls how progress bars are arranged when a sub-path is active.
|
|
39
|
+
* - "merged" (default): Root and sub-path bars in one card.
|
|
40
|
+
* - "split": Root and sub-path bars as separate cards.
|
|
41
|
+
* - "rootOnly": Only the root bar — sub-path bar hidden.
|
|
42
|
+
* - "activeOnly": Only the active (sub-path) bar — root bar hidden.
|
|
43
|
+
*/
|
|
44
|
+
progressLayout?: ProgressLayout;
|
|
37
45
|
// Callback props replace event dispatching in Svelte 5
|
|
38
46
|
oncomplete?: (data: PathData) => void;
|
|
39
47
|
oncancel?: (data: PathData) => void;
|
|
@@ -58,6 +66,7 @@
|
|
|
58
66
|
hideProgress = false,
|
|
59
67
|
footerLayout = 'auto',
|
|
60
68
|
validationDisplay = 'inline',
|
|
69
|
+
progressLayout = 'merged',
|
|
61
70
|
oncomplete,
|
|
62
71
|
oncancel,
|
|
63
72
|
onevent,
|
|
@@ -123,7 +132,7 @@
|
|
|
123
132
|
}
|
|
124
133
|
</script>
|
|
125
134
|
|
|
126
|
-
<div class="pw-shell">
|
|
135
|
+
<div class="pw-shell {progressLayout !== 'merged' ? `pw-shell--progress-${progressLayout}` : ''}">
|
|
127
136
|
{#if !snap}
|
|
128
137
|
<div class="pw-shell__empty">
|
|
129
138
|
<p>No active path.</p>
|
|
@@ -134,8 +143,27 @@
|
|
|
134
143
|
{/if}
|
|
135
144
|
</div>
|
|
136
145
|
{:else}
|
|
146
|
+
<!-- Root progress: persistent top-level bar visible during sub-paths -->
|
|
147
|
+
{#if !hideProgress && snap.rootProgress && progressLayout !== 'activeOnly'}
|
|
148
|
+
<div class="pw-shell__root-progress">
|
|
149
|
+
<div class="pw-shell__steps">
|
|
150
|
+
{#each snap.rootProgress.steps as step, i}
|
|
151
|
+
<div class="pw-shell__step pw-shell__step--{step.status}">
|
|
152
|
+
<span class="pw-shell__step-dot">
|
|
153
|
+
{step.status === 'completed' ? '✓' : i + 1}
|
|
154
|
+
</span>
|
|
155
|
+
<span class="pw-shell__step-label">{step.title ?? step.id}</span>
|
|
156
|
+
</div>
|
|
157
|
+
{/each}
|
|
158
|
+
</div>
|
|
159
|
+
<div class="pw-shell__track">
|
|
160
|
+
<div class="pw-shell__track-fill" style="width: {snap.rootProgress.progress * 100}%"></div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
{/if}
|
|
164
|
+
|
|
137
165
|
<!-- Header: progress indicator (overridable via header snippet) -->
|
|
138
|
-
{#if !hideProgress}
|
|
166
|
+
{#if !hideProgress && progressLayout !== 'rootOnly'}
|
|
139
167
|
{#if header}
|
|
140
168
|
{@render header(snap)}
|
|
141
169
|
{:else if snap.stepCount > 1 || snap.nestingLevel > 0}
|
|
@@ -157,9 +185,13 @@
|
|
|
157
185
|
{/if}
|
|
158
186
|
{/if}
|
|
159
187
|
|
|
160
|
-
<!-- Body: current step rendered via named snippet
|
|
188
|
+
<!-- Body: current step rendered via named snippet.
|
|
189
|
+
Prefer formId (inner step id of a StepChoice) so consumers can
|
|
190
|
+
register snippets by inner step ids directly. -->
|
|
161
191
|
<div class="pw-shell__body">
|
|
162
|
-
{#if stepSnippets[snap.
|
|
192
|
+
{#if snap.formId && stepSnippets[snap.formId]}
|
|
193
|
+
{@render stepSnippets[snap.formId]()}
|
|
194
|
+
{:else if stepSnippets[snap.stepId]}
|
|
163
195
|
{@render stepSnippets[snap.stepId]()}
|
|
164
196
|
{:else}
|
|
165
197
|
<p>No content for step "{snap.stepId}"</p>
|
|
@@ -167,9 +199,9 @@
|
|
|
167
199
|
</div>
|
|
168
200
|
|
|
169
201
|
<!-- Validation messages — suppressed when validationDisplay="inline" -->
|
|
170
|
-
{#if validationDisplay !== 'inline' && snap.hasAttemptedNext && Object.keys(snap.
|
|
202
|
+
{#if validationDisplay !== 'inline' && snap.hasAttemptedNext && Object.keys(snap.fieldErrors).length > 0}
|
|
171
203
|
<ul class="pw-shell__validation">
|
|
172
|
-
{#each Object.entries(snap.
|
|
204
|
+
{#each Object.entries(snap.fieldErrors) as [key, msg]}
|
|
173
205
|
<li class="pw-shell__validation-item">
|
|
174
206
|
{#if key !== '_'}<span class="pw-shell__validation-label">{formatFieldKey(key)}</span>{/if}{msg}
|
|
175
207
|
</li>
|
|
@@ -177,6 +209,17 @@
|
|
|
177
209
|
</ul>
|
|
178
210
|
{/if}
|
|
179
211
|
|
|
212
|
+
<!-- Warning messages — non-blocking, shown immediately (no hasAttemptedNext gate) -->
|
|
213
|
+
{#if validationDisplay !== 'inline' && Object.keys(snap.fieldWarnings).length > 0}
|
|
214
|
+
<ul class="pw-shell__warnings">
|
|
215
|
+
{#each Object.entries(snap.fieldWarnings) as [key, msg]}
|
|
216
|
+
<li class="pw-shell__warnings-item">
|
|
217
|
+
{#if key !== '_'}<span class="pw-shell__warnings-label">{formatFieldKey(key)}</span>{/if}{msg}
|
|
218
|
+
</li>
|
|
219
|
+
{/each}
|
|
220
|
+
</ul>
|
|
221
|
+
{/if}
|
|
222
|
+
|
|
180
223
|
<!-- Footer: navigation buttons (overridable via footer snippet) -->
|
|
181
224
|
{#if footer}
|
|
182
225
|
{@render footer(snap, actions)}
|
package/src/index.svelte.ts
CHANGED
|
@@ -18,6 +18,8 @@ export type {
|
|
|
18
18
|
PathSnapshot,
|
|
19
19
|
PathStep,
|
|
20
20
|
PathStepContext,
|
|
21
|
+
ProgressLayout,
|
|
22
|
+
RootProgress,
|
|
21
23
|
SerializedPathState
|
|
22
24
|
} from "@daltonr/pathwrite-core";
|
|
23
25
|
|
|
@@ -60,6 +62,8 @@ export interface UsePathReturn<TData extends PathData = PathData> {
|
|
|
60
62
|
goToStepChecked: (stepId: string) => Promise<void>;
|
|
61
63
|
/** Update a single data value; triggers a re-render via stateChanged. When `TData` is specified, `key` and `value` are type-checked against your data shape. */
|
|
62
64
|
setData: <K extends string & keyof TData>(key: K, value: TData[K]) => Promise<void>;
|
|
65
|
+
/** Reset the current step's data to what it was when the step was entered. Useful for "Clear" or "Reset" buttons. */
|
|
66
|
+
resetStep: () => Promise<void>;
|
|
63
67
|
/**
|
|
64
68
|
* Tear down any active path (without firing hooks) and immediately start the
|
|
65
69
|
* given path fresh. Safe to call whether or not a path is currently active.
|
|
@@ -141,6 +145,8 @@ export function usePath<TData extends PathData = PathData>(
|
|
|
141
145
|
const setData = (<K extends string & keyof TData>(key: K, value: TData[K]): Promise<void> =>
|
|
142
146
|
engine.setData(key, value as unknown)) as UsePathReturn<TData>["setData"];
|
|
143
147
|
|
|
148
|
+
const resetStep = (): Promise<void> => engine.resetStep();
|
|
149
|
+
|
|
144
150
|
const restart = (path: PathDefinition<any>, initialData: PathData = {}): Promise<void> =>
|
|
145
151
|
engine.restart(path, initialData);
|
|
146
152
|
|
|
@@ -154,6 +160,7 @@ export function usePath<TData extends PathData = PathData>(
|
|
|
154
160
|
goToStep,
|
|
155
161
|
goToStepChecked,
|
|
156
162
|
setData,
|
|
163
|
+
resetStep,
|
|
157
164
|
restart
|
|
158
165
|
};
|
|
159
166
|
}
|
|
@@ -172,6 +179,7 @@ export interface PathContext<TData extends PathData = PathData> {
|
|
|
172
179
|
goToStep: (stepId: string) => Promise<void>;
|
|
173
180
|
goToStepChecked: (stepId: string) => Promise<void>;
|
|
174
181
|
setData: <K extends string & keyof TData>(key: K, value: TData[K]) => Promise<void>;
|
|
182
|
+
resetStep: () => Promise<void>;
|
|
175
183
|
restart: () => Promise<void>;
|
|
176
184
|
}
|
|
177
185
|
|