@design.estate/dees-catalog 9.5.0 → 9.6.2
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 +1319 -1452
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-dataview/dees-table/dees-table.js +5 -4
- package/dist_ts_web/elements/00group-input/dees-input-base/dees-input-base.d.ts +1 -8
- package/dist_ts_web/elements/00group-input/dees-input-base/dees-input-base.js +7 -2
- 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/dist_ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.d.ts +1 -1
- package/dist_ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.js +5 -4
- package/package.json +2 -2
- package/readme.md +52 -3
- package/scripts/check-bdtheme-ratchet.cjs +2 -2
- package/scripts/check-packed-consumer.mjs +45 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-dataview/dees-table/dees-table.ts +3 -2
- package/ts_web/elements/00group-input/dees-input-base/dees-input-base.ts +6 -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
- package/ts_web/elements/00group-overlay/dees-contextmenu/dees-contextmenu.ts +3 -3
- package/readme.hints.md +0 -1233
- package/readme.icons.md +0 -1849
- package/readme.info.md +0 -80
- package/readme.plan.md +0 -671
- package/readme.playbook.md +0 -820
- package/readme.theme-migration.md +0 -168
|
@@ -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>`);
|