@design.estate/dees-catalog 9.5.0 → 9.6.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_bundle/bundle.js +1307 -1448
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-layout/dees-stepper/dees-stepper.d.ts +21 -2
- package/dist_ts_web/elements/00group-layout/dees-stepper/dees-stepper.demo.d.ts +4 -0
- package/dist_ts_web/elements/00group-layout/dees-stepper/dees-stepper.demo.js +218 -193
- package/dist_ts_web/elements/00group-layout/dees-stepper/dees-stepper.js +288 -403
- package/dist_ts_web/elements/00group-layout/dees-stepper/styles.d.ts +1 -0
- package/dist_ts_web/elements/00group-layout/dees-stepper/styles.js +41 -0
- package/package.json +1 -1
- package/readme.md +31 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-layout/dees-stepper/dees-stepper.demo.ts +142 -200
- package/ts_web/elements/00group-layout/dees-stepper/dees-stepper.ts +216 -400
- package/ts_web/elements/00group-layout/dees-stepper/styles.ts +41 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const stepperStyles: import("@design.estate/dees-element").CSSResult;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { css } from '@design.estate/dees-element';
|
|
2
|
+
export const stepperStyles = css `
|
|
3
|
+
:host { display: block; position: relative; width: 100%; height: 100%; min-height: 440px; min-width: 0; font-family: var(--dees-font-family); color: var(--dees-color-text-primary); }
|
|
4
|
+
:host([overlay]) { position: static; width: 0; height: 0; min-height: 0; }
|
|
5
|
+
.stepperContainer { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; overflow-anchor: none; box-sizing: border-box; container: stepper-surface / inline-size; }
|
|
6
|
+
.stepperContainer.overlay { position: fixed; width: 100%; height: 100dvh; max-width: none; max-height: none; border: 0; padding: 0; margin: 0; color: inherit; background: transparent; }
|
|
7
|
+
.stepperContainer::backdrop { background: var(--dees-color-scrim); }
|
|
8
|
+
dees-tile.step { position: relative; width: min(var(--dees-stepper-width, 520px), calc(100% - 40px)); max-height: calc(100% - 48px); min-height: min(280px, calc(100% - 48px)); margin: 0 auto 20px; pointer-events: none; opacity: .25; transition: opacity 240ms var(--dees-ease-standard); }
|
|
9
|
+
dees-tile.step::part(outer) { border-color: var(--dees-color-border-subtle); }
|
|
10
|
+
dees-tile.step.selected { pointer-events: auto; opacity: 1; }
|
|
11
|
+
dees-tile.step.selected::part(outer) { border-color: var(--dees-color-border-default); box-shadow: var(--dees-shadow-md); }
|
|
12
|
+
dees-tile.step.hiddenStep { opacity: 0; }
|
|
13
|
+
dees-tile.step:last-child { margin-bottom: 100dvh; }
|
|
14
|
+
.step-header { display: flex; align-items: center; gap: 16px; padding: 16px 24px; min-height: 48px; box-sizing: border-box; }
|
|
15
|
+
.step-rail { display: flex; flex: 1; gap: 5px; list-style: none; margin: 0; padding: 0; min-width: 0; }
|
|
16
|
+
.step-marker { flex: 1; height: 4px; border-radius: 2px; background: var(--dees-color-fill-secondary); }
|
|
17
|
+
.step-marker.complete { background: var(--dees-color-text-secondary); }
|
|
18
|
+
.step-marker.current { background: var(--dees-color-accent-primary); }
|
|
19
|
+
.step-counter { flex: none; font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--dees-color-text-secondary); }
|
|
20
|
+
.step-body { padding: 24px; }
|
|
21
|
+
.heading-row { display: flex; align-items: flex-start; gap: 16px; }
|
|
22
|
+
.title { margin: 0; font-size: 20px; line-height: 1.3; font-weight: 600; letter-spacing: -.025em; overflow-wrap: anywhere; outline: none; }
|
|
23
|
+
.description { margin: 8px 0 0; font-size: 13px; line-height: 1.55; color: var(--dees-color-text-secondary); }
|
|
24
|
+
.content { margin-top: 24px; font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; }
|
|
25
|
+
.content:empty { display: none; }
|
|
26
|
+
.progressStep { margin: 20px -8px 0; }
|
|
27
|
+
.step-error { display: flex; align-items: flex-start; gap: 8px; padding: 12px; margin-top: 16px; border-radius: var(--dees-radius-md); background: var(--dees-color-badge-error-bg); color: var(--dees-color-text-error); font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
|
|
28
|
+
.step-error dees-icon { flex: none; margin-top: 1px; }
|
|
29
|
+
.step-footer { padding: 12px 24px; }
|
|
30
|
+
.step-hint { flex: 0 0 120px; padding-top: 4px; margin-left: auto; color: var(--dees-color-text-secondary); font-size: 11px; line-height: 1.4; text-align: right; transition: opacity 160ms var(--dees-ease-standard), visibility 160ms; }
|
|
31
|
+
.step-hint[aria-hidden='true'] { opacity: 0; visibility: hidden; pointer-events: none; }
|
|
32
|
+
.bottomButtons { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
|
33
|
+
.back-action { margin-right: auto; }
|
|
34
|
+
.footer-spacer { margin-right: auto; }
|
|
35
|
+
.empty { display: grid; place-content: center; height: 100%; text-align: center; color: var(--dees-color-text-secondary); font-size: 13px; }
|
|
36
|
+
.predestroy .step.selected { animation: stepper-exit 160ms var(--dees-ease-standard) forwards; }
|
|
37
|
+
@keyframes stepper-exit { to { opacity: 0; transform: translateY(10px); } }
|
|
38
|
+
@media (prefers-reduced-motion: reduce) { dees-tile.step, .step-hint { transition: none; } .predestroy .step.selected { animation: none; } }
|
|
39
|
+
@container stepper-surface (max-width: 540px) { dees-tile.step { width: calc(100% - 24px); max-height: calc(100% - 24px); } .step-header { padding: 12px 20px; } .step-body { padding: 20px; } .step-footer { padding: 12px 20px; } .step-hint { flex-basis: 84px; } }
|
|
40
|
+
`;
|
|
41
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3R5bGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHNfd2ViL2VsZW1lbnRzLzAwZ3JvdXAtbGF5b3V0L2RlZXMtc3RlcHBlci9zdHlsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRWxELE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyxHQUFHLENBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBc0MvQixDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design.estate/dees-catalog",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
|
|
6
6
|
"main": "dist_ts_web/index.js",
|
package/readme.md
CHANGED
|
@@ -2173,13 +2173,43 @@ const layer = await DeesWindowLayer.createAndShow({
|
|
|
2173
2173
|
### Navigation Components
|
|
2174
2174
|
|
|
2175
2175
|
#### `DeesStepper`
|
|
2176
|
-
|
|
2176
|
+
Guided form and background-work flows with a compact progress strip, shared action
|
|
2177
|
+
buttons, and a vertical transition between steps. Use it inline or open the same
|
|
2178
|
+
steps as a modal with `DeesStepper.createAndShow({ steps, cancelable: true })`.
|
|
2179
|
+
|
|
2180
|
+
- `IStep` accepts `title`, optional `description`, `content`, `menuOptions`,
|
|
2181
|
+
`allowBack`, `validationFunc`, `onReturnToStepFunc`, and `progressStep`.
|
|
2182
|
+
- The last menu action is primary. A nested `dees-form` gates that action on its
|
|
2183
|
+
required fields and dispatches collected `formData` before the action runs.
|
|
2184
|
+
The required-fields hint fades beside the heading without changing its layout.
|
|
2185
|
+
- Async actions prevent duplicate activation and display failures in the current
|
|
2186
|
+
step. Progress failures expose **Try again**; `retryStep()` reruns validation.
|
|
2187
|
+
Keep external work abortable using the callback's `AbortSignal`.
|
|
2188
|
+
- Progress steps use `dees-progressbar` and advance after successful validation
|
|
2189
|
+
unless `progressStep.autoAdvance` is `false`. Use `updateProgressStep()`,
|
|
2190
|
+
`appendProgressStepLine()`, and `resetProgressStep()` to report work.
|
|
2191
|
+
- `goNext()` and `goBack()` preserve mounted form contents. Back honors
|
|
2192
|
+
`allowBack: false`. Inactive steps are inert. Transitions respect reduced motion
|
|
2193
|
+
and adjust to changing content and container sizes without snapping.
|
|
2194
|
+
- Overlay mode uses native dialog focus containment and restoration. Cancel,
|
|
2195
|
+
Escape, and backdrop clicks share a confirmation flow; `cancelable: false`
|
|
2196
|
+
disables those dismissal paths. `destroy()` closes the flow; `stepper-close`
|
|
2197
|
+
fires when it disconnects. Disconnecting also aborts work and releases observers.
|
|
2198
|
+
- Inline steppers fill a bounded area (440px minimum height by default). Set a
|
|
2199
|
+
height appropriate to the composition; `--dees-stepper-width` controls the card's
|
|
2200
|
+
maximum width (520px by default).
|
|
2201
|
+
|
|
2202
|
+
The catalog demo combines setup fields, preferences, a review, background work,
|
|
2203
|
+
and completion. **Retry example** fails the first background attempt and preserves
|
|
2204
|
+
the choices for recovery. It also shows optional and required-completion overlays.
|
|
2177
2205
|
|
|
2178
2206
|
```typescript
|
|
2179
2207
|
<dees-stepper
|
|
2208
|
+
style="height: 540px"
|
|
2180
2209
|
.steps=${[
|
|
2181
2210
|
{
|
|
2182
2211
|
title: 'Account Setup',
|
|
2212
|
+
description: 'Choose the owner of your workspace.',
|
|
2183
2213
|
content: html`<dees-form>...</dees-form>`,
|
|
2184
2214
|
menuOptions: [{ name: 'Continue', action: async (stepper) => stepper?.goNext() }]
|
|
2185
2215
|
},
|
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-catalog',
|
|
6
|
-
version: '9.
|
|
6
|
+
version: '9.6.0',
|
|
7
7
|
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
|
8
8
|
}
|
|
@@ -1,212 +1,154 @@
|
|
|
1
|
-
import { html } from '@design.estate/dees-element';
|
|
1
|
+
import { DeesElement, customElement, property, state, html, css, cssManager } from '@design.estate/dees-element';
|
|
2
2
|
import { DeesStepper, type IStep } from './dees-stepper.js';
|
|
3
|
+
import { themeDefaultStyles } from '../../00theme.js';
|
|
4
|
+
import { demoPage } from '../../../demos/templates.js';
|
|
5
|
+
import '../../00group-form/dees-form/dees-form.js';
|
|
6
|
+
import '../../00group-input/dees-input-text/dees-input-text.js';
|
|
7
|
+
import '../../00group-input/dees-input-multitoggle/dees-input-multitoggle.js';
|
|
8
|
+
import '../../00group-input/dees-input-toggle/dees-input-toggle.js';
|
|
3
9
|
|
|
4
|
-
const waitForProgressTick =
|
|
5
|
-
|
|
6
|
-
|
|
10
|
+
const waitForProgressTick = (duration: number, signal?: AbortSignal): Promise<boolean> => new Promise(resolve => {
|
|
11
|
+
if (signal?.aborted) { resolve(false); return; }
|
|
12
|
+
const abort = () => { clearTimeout(timer); resolve(false); };
|
|
13
|
+
const timer = setTimeout(() => { signal?.removeEventListener('abort', abort); resolve(true); }, duration);
|
|
14
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
15
|
+
});
|
|
7
16
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
const contentStyles = html`<style>
|
|
18
|
+
.setup-summary { margin: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px 24px; font-size: 13px; }
|
|
19
|
+
.setup-summary dt { color: var(--dees-color-text-secondary); }
|
|
20
|
+
.setup-summary dd { margin: 0; text-align: right; overflow-wrap: anywhere; font-weight: 500; }
|
|
21
|
+
.setup-note { color: var(--dees-color-text-secondary); font-size: 12px; line-height: 1.6; margin: 20px 0 0; }
|
|
22
|
+
.setup-success { display: flex; align-items: center; gap: 10px; margin: 0 0 20px; color: var(--dees-color-text-success); }
|
|
23
|
+
</style>`;
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const createContinueMenuOptions = (labelArg = 'Continue') => [
|
|
36
|
-
{
|
|
37
|
-
name: labelArg,
|
|
38
|
-
action: async (stepper?: DeesStepper) => stepper?.goNext(),
|
|
39
|
-
},
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const createDemoSteps = (): IStep[] => [
|
|
43
|
-
{
|
|
44
|
-
title: 'Account Setup',
|
|
45
|
-
content: html`
|
|
46
|
-
<dees-form>
|
|
47
|
-
<dees-input-text key="email" label="Work Email" required></dees-input-text>
|
|
48
|
-
<dees-input-text key="password" label="Create Password" type="password" required></dees-input-text>
|
|
49
|
-
</dees-form>
|
|
50
|
-
`,
|
|
51
|
-
menuOptions: createContinueMenuOptions(),
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
title: 'Profile Details',
|
|
55
|
-
content: html`
|
|
56
|
-
<dees-form>
|
|
57
|
-
<dees-input-text key="firstName" label="First Name" required></dees-input-text>
|
|
58
|
-
<dees-input-text key="lastName" label="Last Name" required></dees-input-text>
|
|
59
|
-
</dees-form>
|
|
60
|
-
`,
|
|
61
|
-
menuOptions: createContinueMenuOptions(),
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
title: 'Contact Information',
|
|
65
|
-
content: html`
|
|
66
|
-
<dees-form>
|
|
67
|
-
<dees-input-phone key="phone" label="Mobile Number" required></dees-input-phone>
|
|
68
|
-
<dees-input-text key="company" label="Company"></dees-input-text>
|
|
69
|
-
</dees-form>
|
|
70
|
-
`,
|
|
71
|
-
menuOptions: createContinueMenuOptions(),
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
title: 'Provision Workspace',
|
|
75
|
-
content: html`
|
|
76
|
-
<dees-panel>
|
|
77
|
-
<p>
|
|
78
|
-
We are creating your starter workspace, applying your onboarding choices,
|
|
79
|
-
and preparing a live preview. This step moves forward automatically when
|
|
80
|
-
the environment is ready.
|
|
81
|
-
</p>
|
|
82
|
-
</dees-panel>
|
|
83
|
-
`,
|
|
84
|
-
progressStep: {
|
|
85
|
-
label: 'Workspace setup',
|
|
86
|
-
percentage: 8,
|
|
87
|
-
indeterminate: true,
|
|
88
|
-
statusRows: 4,
|
|
89
|
-
statusText: 'Allocating a clean workspace...',
|
|
90
|
-
terminalLines: ['Allocating a clean workspace'],
|
|
25
|
+
const createDemoSteps = (failFirst: boolean, finish: (name: string) => void): IStep[] => {
|
|
26
|
+
const draft = { name: '', email: '', purpose: 'Product', updates: true };
|
|
27
|
+
let attempts = 0;
|
|
28
|
+
const summary = () => html`${contentStyles}<dl class="setup-summary">
|
|
29
|
+
<dt>Workspace</dt><dd>${draft.name}</dd><dt>Owner</dt><dd>${draft.email}</dd>
|
|
30
|
+
<dt>Built for</dt><dd>${draft.purpose}</dd><dt>Weekly digest</dt><dd>${draft.updates ? 'On' : 'Off'}</dd>
|
|
31
|
+
</dl>`;
|
|
32
|
+
const collect = (event: CustomEvent<{ data: Partial<typeof draft> }>) => {
|
|
33
|
+
Object.assign(draft, event.detail.data);
|
|
34
|
+
steps[2].content = summary();
|
|
35
|
+
steps[4].content = html`${contentStyles}<p class="setup-success"><dees-icon icon="lucide:CircleCheck" iconSize="20"></dees-icon>Everything is in place.</p>${summary()}`;
|
|
36
|
+
};
|
|
37
|
+
const next = [{ name: 'Continue', action: async (stepper?: DeesStepper) => stepper?.goNext() }];
|
|
38
|
+
const steps: IStep[] = [
|
|
39
|
+
{
|
|
40
|
+
title: 'Create a workspace.',
|
|
41
|
+
description: 'Give your workspace a name and choose who will own it.',
|
|
42
|
+
content: html`<dees-form @formData=${collect}>
|
|
43
|
+
<dees-input-text key="name" label="Workspace name" placeholder="Studio Notes" required></dees-input-text>
|
|
44
|
+
<dees-input-text key="email" label="Work email" placeholder="alex@example.com" type="email" required></dees-input-text>
|
|
45
|
+
</dees-form>`,
|
|
46
|
+
menuOptions: next,
|
|
91
47
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
48
|
+
{
|
|
49
|
+
title: 'Make it yours.',
|
|
50
|
+
description: 'Start with a focus. You can change these choices later.',
|
|
51
|
+
content: html`<dees-form @formData=${collect}>
|
|
52
|
+
<dees-input-multitoggle key="purpose" label="What are you working on?" .options=${['Product', 'Operations', 'Research']}></dees-input-multitoggle>
|
|
53
|
+
<dees-input-toggle key="updates" label="Weekly workspace digest" .value=${true}></dees-input-toggle>
|
|
54
|
+
</dees-form>`,
|
|
55
|
+
menuOptions: next,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
title: 'Ready to create?',
|
|
59
|
+
description: 'Take a moment to check your choices.',
|
|
60
|
+
content: summary(),
|
|
61
|
+
menuOptions: [{ name: 'Create workspace', action: async (stepper) => stepper?.goNext() }],
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
title: 'Bringing it together.',
|
|
65
|
+
description: 'Your workspace is taking shape. This usually takes a few seconds.',
|
|
66
|
+
content: html`${contentStyles}<p class="setup-note">You can go back to adjust your choices, or cancel while setup is running.</p>`,
|
|
67
|
+
progressStep: { label: 'Creating workspace', percentage: 0, statusRows: 3 },
|
|
68
|
+
validationFunc: async (stepper, _element, signal) => {
|
|
69
|
+
attempts++;
|
|
70
|
+
const messages = ['Creating your space', 'Applying preferences', 'Preparing starter files', 'Workspace ready'];
|
|
71
|
+
for (const [index, message] of messages.entries()) {
|
|
72
|
+
if (!await waitForProgressTick(650, signal)) return;
|
|
73
|
+
if (failFirst && attempts === 1 && index === 2) throw new Error('Starter files could not be copied. Your choices are saved. Try again.');
|
|
74
|
+
stepper.appendProgressStepLine(message);
|
|
75
|
+
stepper.updateProgressStep({ percentage: (index + 1) * 25, statusText: message, indeterminate: false });
|
|
106
76
|
}
|
|
77
|
+
await waitForProgressTick(450, signal);
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
title: 'Your workspace is ready.',
|
|
82
|
+
description: 'A fresh start, with all the details you chose.',
|
|
83
|
+
allowBack: false,
|
|
84
|
+
content: summary(),
|
|
85
|
+
menuOptions: [{ name: 'Done', action: async stepper => { finish(draft.name); await stepper?.destroy(); } }],
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
return steps;
|
|
89
|
+
};
|
|
107
90
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
} else {
|
|
116
|
-
stepper.appendProgressStepLine(progressFrame.line);
|
|
117
|
-
stepper.updateProgressStep({
|
|
118
|
-
percentage: progressFrame.percentage,
|
|
119
|
-
indeterminate: true,
|
|
120
|
-
statusText: `${progressFrame.line}...`,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
91
|
+
@customElement('dees-demo-stepper')
|
|
92
|
+
class DeesDemoStepper extends DeesElement {
|
|
93
|
+
@property() accessor scenario = 'Standard setup';
|
|
94
|
+
@state() private accessor closed = false;
|
|
95
|
+
@state() private accessor result = '';
|
|
96
|
+
private steps = createDemoSteps(false, name => { this.result = `${name} is ready.`; });
|
|
97
|
+
private overlayStepper?: DeesStepper;
|
|
123
98
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
99
|
+
public static styles = [themeDefaultStyles, cssManager.defaultStyles, css`
|
|
100
|
+
:host { display: block; min-width: 0; }
|
|
101
|
+
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }
|
|
102
|
+
.actions { display: flex; gap: 8px; flex-wrap: wrap; }
|
|
103
|
+
.stage { position: relative; height: 540px; border: 1px solid var(--dees-color-border-subtle); border-radius: 18px; background: var(--dees-color-bg-secondary); overflow: hidden; }
|
|
104
|
+
.finished { display: grid; place-content: center; justify-items: center; gap: 16px; height: 100%; padding: 24px; box-sizing: border-box; text-align: center; }
|
|
105
|
+
.finished h2 { margin: 0; font-size: 20px; letter-spacing: -.025em; font-weight: 600; }
|
|
106
|
+
.finished p, .caption { font-size: 12px; line-height: 1.6; color: var(--dees-color-text-secondary); }
|
|
107
|
+
.caption { margin: 16px 0 0; }
|
|
108
|
+
summary.caption { cursor: pointer; font-size: 13px; font-weight: 500; }
|
|
109
|
+
.finished dees-icon { color: var(--dees-color-text-success); }
|
|
110
|
+
@media (max-width: 540px) { .stage { height: 560px; } }
|
|
111
|
+
`];
|
|
129
112
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
113
|
+
private reset() {
|
|
114
|
+
this.result = '';
|
|
115
|
+
this.closed = false;
|
|
116
|
+
this.steps = createDemoSteps(this.scenario === 'Retry example', name => { this.result = `${name} is ready.`; });
|
|
117
|
+
this.requestUpdate();
|
|
118
|
+
}
|
|
136
119
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
<dees-input-dropdown
|
|
145
|
-
key="teamSize"
|
|
146
|
-
label="How big is your team?"
|
|
147
|
-
.options=${[
|
|
148
|
-
{ label: '1-5', value: '1-5' },
|
|
149
|
-
{ label: '6-20', value: '6-20' },
|
|
150
|
-
{ label: '21-50', value: '21-50' },
|
|
151
|
-
{ label: '51+', value: '51+' },
|
|
152
|
-
]}
|
|
153
|
-
required
|
|
154
|
-
></dees-input-dropdown>
|
|
155
|
-
</dees-form>
|
|
156
|
-
`,
|
|
157
|
-
menuOptions: createContinueMenuOptions(),
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
title: 'Goals',
|
|
161
|
-
content: html`
|
|
162
|
-
<dees-form>
|
|
163
|
-
<dees-input-multitoggle
|
|
164
|
-
key="goal"
|
|
165
|
-
label="Main objective"
|
|
166
|
-
.options=${[
|
|
167
|
-
{ label: 'Onboarding', key: 'onboarding' },
|
|
168
|
-
{ label: 'Analytics', key: 'analytics' },
|
|
169
|
-
{ label: 'Automation', key: 'automation' },
|
|
170
|
-
]}
|
|
171
|
-
></dees-input-multitoggle>
|
|
172
|
-
</dees-form>
|
|
173
|
-
`,
|
|
174
|
-
menuOptions: createContinueMenuOptions(),
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
title: 'Review & Launch',
|
|
178
|
-
content: html`
|
|
179
|
-
<dees-panel>
|
|
180
|
-
<p>
|
|
181
|
-
Your workspace is ready. Review the collected details and launch when
|
|
182
|
-
you are ready to start.
|
|
183
|
-
</p>
|
|
184
|
-
</dees-panel>
|
|
185
|
-
`,
|
|
186
|
-
menuOptions: [
|
|
187
|
-
{
|
|
188
|
-
name: 'Launch',
|
|
189
|
-
action: async (stepper?: DeesStepper) => {
|
|
190
|
-
if (stepper?.overlay) {
|
|
191
|
-
await stepper.destroy();
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
],
|
|
196
|
-
},
|
|
197
|
-
];
|
|
120
|
+
private async openOverlay(cancelable = true) {
|
|
121
|
+
if (this.overlayStepper?.isConnected) return;
|
|
122
|
+
this.overlayStepper = await DeesStepper.createAndShow({
|
|
123
|
+
cancelable,
|
|
124
|
+
steps: createDemoSteps(this.scenario === 'Retry example', name => { this.result = `${name} is ready.`; }),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
198
127
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
<dees-button
|
|
205
|
-
|
|
206
|
-
await DeesStepper.createAndShow({ steps: createDemoSteps() });
|
|
207
|
-
}}
|
|
208
|
-
>Open stepper as overlay</dees-button>
|
|
128
|
+
public render() {
|
|
129
|
+
return html`<div class="toolbar">
|
|
130
|
+
<dees-input-multitoggle size="sm" label="Demo scenario" labelPosition="none"
|
|
131
|
+
.options=${['Standard setup', 'Retry example']} .selectedOption=${this.scenario}
|
|
132
|
+
@change=${(event: CustomEvent<{ value: string }>) => { this.scenario = event.detail.value; this.reset(); }}></dees-input-multitoggle>
|
|
133
|
+
<div class="actions"><dees-button type="secondary" text="Open overlay" @clicked=${() => this.openOverlay()}></dees-button>
|
|
134
|
+
<dees-button type="ghost" text="Reset" @clicked=${this.reset}></dees-button></div>
|
|
209
135
|
</div>
|
|
210
|
-
<
|
|
211
|
-
|
|
212
|
-
|
|
136
|
+
<div class="stage">${this.closed ? html`<div class="finished">
|
|
137
|
+
<dees-icon icon=${this.result ? 'lucide:CircleCheck' : 'lucide:Layers'} iconSize="32"></dees-icon>
|
|
138
|
+
<h2>${this.result || 'Setup cancelled.'}</h2><p>This example uses local sample data.</p>
|
|
139
|
+
<dees-button type="secondary" text="Start again" @clicked=${this.reset}></dees-button>
|
|
140
|
+
</div>` : html`<dees-stepper .steps=${this.steps} @stepper-close=${() => { this.closed = true; }}></dees-stepper>`}</div>
|
|
141
|
+
<p class="caption">${this.scenario === 'Retry example' ? 'The first setup attempt pauses with an error. Try again to continue with your saved choices.' : 'Move forward, go back, and review your choices. Changes stay in this demo.'}</p>
|
|
142
|
+
<details><summary class="caption">Completion required</summary>
|
|
143
|
+
<p class="caption">For a flow that must finish, such as a required update, cancellation can be disabled.</p>
|
|
144
|
+
<dees-button type="secondary" text="Open required setup" @clicked=${() => this.openOverlay(false)}></dees-button>
|
|
145
|
+
</details>`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public async disconnectedCallback() {
|
|
149
|
+
if (this.overlayStepper?.isConnected) await this.overlayStepper.destroy();
|
|
150
|
+
await super.disconnectedCallback();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const stepperDemo = () => demoPage('Stepper', 'A clear path from the first detail to the finished result.', html`<dees-demo-stepper></dees-demo-stepper>`);
|