@design.estate/dees-catalog 9.3.0 → 9.4.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 +1372 -2727
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/00group-button/dees-button/dees-button.js +2 -1
- package/dist_ts_web/elements/00group-input/dees-input-quantityselector/dees-input-quantityselector.js +4 -2
- package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.d.ts +11 -9
- package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.demo.d.ts +2 -2
- package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.demo.js +148 -319
- package/dist_ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.js +60 -279
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.d.ts +25 -10
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.d.ts +3 -4
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.js +229 -388
- package/dist_ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.js +253 -813
- package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.d.ts +2 -0
- package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.js +150 -389
- package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.js +67 -11
- package/package.json +1 -1
- package/readme.hints.md +26 -0
- package/readme.md +76 -15
- package/scripts/bdtheme-baseline.json +0 -2
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/00group-button/dees-button/dees-button.ts +1 -0
- package/ts_web/elements/00group-input/dees-input-quantityselector/dees-input-quantityselector.ts +3 -1
- package/ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.demo.ts +67 -332
- package/ts_web/elements/00group-simple/dees-shopping-productcard/dees-shopping-productcard.ts +65 -322
- package/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.demo.ts +136 -382
- package/ts_web/elements/00group-simple/dees-simple-appdash/dees-simple-appdash.ts +224 -872
- package/ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.ts +116 -421
- package/ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.ts +66 -10
|
@@ -1,436 +1,131 @@
|
|
|
1
|
-
import { html, css, cssManager, customElement, state, DeesElement } from '@design.estate/dees-element';
|
|
1
|
+
import { html, css, cssManager, customElement, state, DeesElement, directives } from '@design.estate/dees-element';
|
|
2
2
|
import { themeDefaultStyles } from '../../00theme.js';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
IDeesLoginProviderContext,
|
|
8
|
-
TDeesLoginMethod,
|
|
9
|
-
} from './dees-simple-login.js';
|
|
3
|
+
import { demoPage } from '../../../demos/templates.js';
|
|
4
|
+
import type { DeesSimpleLogin, IDeesLoginProvider, IDeesLoginProviderContext, TDeesLoginPasskeyIntent, TDeesLoginMethod } from './dees-simple-login.js';
|
|
5
|
+
import '../../00group-input/dees-input-dropdown/dees-input-dropdown.js';
|
|
6
|
+
import '../../00group-input/dees-input-multitoggle/dees-input-multitoggle.js';
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* the consumer. These are neutral Lucide stand-ins for what a real deployment would pass.
|
|
14
|
-
*/
|
|
15
|
-
const demoProviders: IDeesLoginProvider[] = [
|
|
8
|
+
const providers: IDeesLoginProvider[] = [
|
|
9
|
+
{ id: 'workspace', label: 'Workspace account', icon: 'lucide:building2' },
|
|
16
10
|
{ id: 'idp-global', label: 'idp.global', icon: 'lucide:shieldCheck' },
|
|
17
|
-
{ id: 'workspace', label: 'Workspace SSO', icon: 'lucide:building2' },
|
|
18
|
-
{ id: 'email-link', label: 'Email link', icon: 'lucide:mail' },
|
|
19
11
|
];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
{
|
|
25
|
-
{ id: 'legacy-ldap', label: 'LDAP', icon: 'lucide:network', disabled: true },
|
|
12
|
+
const variants = [
|
|
13
|
+
{ key: 'full', option: 'All sign-in methods' }, { key: 'password', option: 'Password only' },
|
|
14
|
+
{ key: 'passkey', option: 'Passkey only' }, { key: 'enroll', option: 'Passkey enrollment' },
|
|
15
|
+
{ key: 'providers', option: 'Identity providers' }, { key: 'many', option: 'Six providers' },
|
|
16
|
+
{ key: 'events', option: 'Consumer-managed events' }, { key: 'unavailable', option: 'Unavailable passkey' },
|
|
26
17
|
];
|
|
27
18
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
| '
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
key: 'full',
|
|
55
|
-
title: 'Passkey + providers + password',
|
|
56
|
-
description:
|
|
57
|
-
'Handler mode. Every method has its own busy and error state — the passkey handler ' +
|
|
58
|
-
'below always rejects, and the password form stays untouched by it.',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
key: 'passkeyOnly',
|
|
62
|
-
title: 'Passkey only',
|
|
63
|
-
description: '`.passkey=${true} .password=${false}` — no credential fallback at all.',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
key: 'enrollment',
|
|
67
|
-
title: 'Passkey enrollment + sign in',
|
|
68
|
-
description:
|
|
69
|
-
"`.passkeyIntents=${['authenticate', 'register']}` renders both ceremonies. " +
|
|
70
|
-
'This is what Onebox hand-rolls today.',
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
key: 'providerOnly',
|
|
74
|
-
title: 'Providers only',
|
|
75
|
-
description: 'A pure OIDC surface. The provider handler resolves after a short delay.',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
key: 'manyProviders',
|
|
79
|
-
title: 'Six providers',
|
|
80
|
-
description:
|
|
81
|
-
'Four or more providers pair up into two columns instead of growing the card. The ' +
|
|
82
|
-
'last one is `disabled`.',
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
key: 'eventMode',
|
|
86
|
-
title: 'Event mode (no handlers)',
|
|
87
|
-
description:
|
|
88
|
-
'No handler properties. The component dispatches `passkey-login` / `provider-login` ' +
|
|
89
|
-
'and the demo drives busy and error state through `setBusy()` and `reportError()`.',
|
|
90
|
-
},
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
@customElement('dees-simple-login-demo')
|
|
94
|
-
class DeesSimpleLoginDemo extends DeesElement {
|
|
95
|
-
@state()
|
|
96
|
-
accessor variant: TDemoVariant = 'full';
|
|
97
|
-
|
|
98
|
-
@state()
|
|
99
|
-
accessor log: string[] = [];
|
|
100
|
-
|
|
101
|
-
public static styles = [
|
|
102
|
-
themeDefaultStyles,
|
|
103
|
-
cssManager.defaultStyles,
|
|
104
|
-
css`
|
|
105
|
-
:host {
|
|
106
|
-
display: block;
|
|
107
|
-
position: absolute;
|
|
108
|
-
inset: 0;
|
|
109
|
-
font-family: var(--dees-font-family);
|
|
110
|
-
color: var(--dees-color-text-primary);
|
|
111
|
-
background: var(--dees-color-bg-canvas);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.layout {
|
|
115
|
-
display: grid;
|
|
116
|
-
grid-template-columns: 320px 1fr;
|
|
117
|
-
height: 100%;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.sidebar {
|
|
121
|
-
display: flex;
|
|
122
|
-
flex-direction: column;
|
|
123
|
-
gap: var(--dees-spacing-md);
|
|
124
|
-
padding: var(--dees-spacing-xl);
|
|
125
|
-
overflow-y: auto;
|
|
126
|
-
border-right: 1px solid var(--dees-color-border-default);
|
|
127
|
-
background: var(--dees-color-bg-secondary);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.sidebarTitle {
|
|
131
|
-
font-size: var(--dees-font-control-size);
|
|
132
|
-
font-weight: 600;
|
|
133
|
-
color: var(--dees-color-text-muted);
|
|
134
|
-
text-transform: uppercase;
|
|
135
|
-
letter-spacing: 0.06em;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.variant {
|
|
139
|
-
padding: var(--dees-spacing-md);
|
|
140
|
-
border: 1px solid var(--dees-color-border-subtle);
|
|
141
|
-
border-radius: var(--dees-radius-lg);
|
|
142
|
-
corner-shape: var(--dees-corner-shape);
|
|
143
|
-
background: var(--dees-color-bg-primary);
|
|
144
|
-
cursor: pointer;
|
|
145
|
-
transition: border-color var(--dees-transition-fast) var(--dees-ease-standard);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.variant:hover {
|
|
149
|
-
border-color: var(--dees-color-border-strong);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.variant.selected {
|
|
153
|
-
border-color: var(--dees-color-accent-primary);
|
|
154
|
-
box-shadow: 0 0 0 1px var(--dees-color-accent-primary);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.variantTitle {
|
|
158
|
-
font-size: var(--dees-font-control-size);
|
|
159
|
-
font-weight: 600;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.variantDescription {
|
|
163
|
-
margin-top: var(--dees-spacing-xs);
|
|
164
|
-
font-size: var(--dees-font-control-size-sm);
|
|
165
|
-
line-height: 1.45;
|
|
166
|
-
color: var(--dees-color-text-muted);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.logTitle {
|
|
170
|
-
margin-top: var(--dees-spacing-lg);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.logEntries {
|
|
174
|
-
display: flex;
|
|
175
|
-
flex-direction: column;
|
|
176
|
-
gap: var(--dees-spacing-xs);
|
|
177
|
-
font-family: var(--dees-font-family-mono);
|
|
178
|
-
font-size: var(--dees-font-control-size-sm);
|
|
179
|
-
color: var(--dees-color-text-secondary);
|
|
180
|
-
user-select: text;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.stage {
|
|
184
|
-
position: relative;
|
|
185
|
-
overflow: hidden;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
.authenticated {
|
|
189
|
-
display: flex;
|
|
190
|
-
flex-direction: column;
|
|
191
|
-
gap: var(--dees-spacing-md);
|
|
192
|
-
align-items: center;
|
|
193
|
-
justify-content: center;
|
|
194
|
-
height: 100%;
|
|
195
|
-
text-align: center;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.authenticated h1 {
|
|
199
|
-
margin: 0;
|
|
200
|
-
font-size: var(--dees-font-title2-size);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.authenticated p {
|
|
204
|
-
margin: 0;
|
|
205
|
-
color: var(--dees-color-text-muted);
|
|
206
|
-
}
|
|
207
|
-
`,
|
|
208
|
-
];
|
|
209
|
-
|
|
210
|
-
private get loginElement(): DeesSimpleLogin | null {
|
|
211
|
-
return this.shadowRoot?.querySelector('dees-simple-login') || null;
|
|
19
|
+
@customElement('dees-demo-simple-login')
|
|
20
|
+
class DeesDemoSimpleLogin extends DeesElement {
|
|
21
|
+
@state() private accessor variant = 'full';
|
|
22
|
+
@state() private accessor outcome = 'success';
|
|
23
|
+
@state() private accessor revision = 0;
|
|
24
|
+
@state() private accessor result = 'Choose a sign-in method. These accounts and responses are local samples.';
|
|
25
|
+
private work = new AbortController();
|
|
26
|
+
private get login(): DeesSimpleLogin | null { return this.shadowRoot?.querySelector('dees-simple-login') || null; }
|
|
27
|
+
|
|
28
|
+
public static styles = [themeDefaultStyles, cssManager.defaultStyles, css`
|
|
29
|
+
:host { display: grid; gap: 16px; font-family: var(--dees-font-family); }
|
|
30
|
+
.controls { display: flex; align-items: end; flex-wrap: wrap; gap: 16px; }
|
|
31
|
+
.controls dees-input-dropdown { width: 250px; max-width: 100%; }
|
|
32
|
+
.controls dees-button { margin-left: auto; }
|
|
33
|
+
.stage { height: 720px; min-height: 0; position: relative; border: 1px solid var(--dees-color-border-subtle); border-radius: var(--dees-radius-2xl); corner-shape: var(--dees-corner-shape); overflow: hidden; }
|
|
34
|
+
.authenticated { display: grid; place-content: center; justify-items: center; text-align: center; gap: 16px; height: 100%; padding: 32px; background: var(--dees-color-bg-canvas); }
|
|
35
|
+
.authenticated > dees-icon { color: var(--dees-color-text-success); }
|
|
36
|
+
h2 { margin: 0; font-size: 28px; font-weight: 600; letter-spacing: -.03em; }
|
|
37
|
+
p, output { margin: 0; color: var(--dees-color-text-secondary); font-size: 13px; line-height: 1.5; }
|
|
38
|
+
output { min-height: 40px; padding: 12px 16px; background: var(--dees-color-bg-secondary); border-radius: var(--dees-radius-lg); }
|
|
39
|
+
@media (max-width: 480px) { .stage { height: 760px; } }
|
|
40
|
+
`];
|
|
41
|
+
|
|
42
|
+
private resetDemo(): void {
|
|
43
|
+
this.work.abort(); this.work = new AbortController(); this.revision++;
|
|
44
|
+
this.result = 'Ready. No account or personal information is required.';
|
|
212
45
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
46
|
+
public async disconnectedCallback(): Promise<void> { this.work.abort(); await super.disconnectedCallback(); }
|
|
47
|
+
public async connectedCallback(): Promise<void> { if (this.work.signal.aborted) this.work = new AbortController(); await super.connectedCallback(); }
|
|
48
|
+
|
|
49
|
+
private async respond(method: string, eventTarget?: { method: TDeesLoginMethod; providerId?: string; intent?: TDeesLoginPasskeyIntent }): Promise<void> {
|
|
50
|
+
const login = this.login;
|
|
51
|
+
if (!login) return;
|
|
52
|
+
const signal = this.work.signal;
|
|
53
|
+
const outcome = this.outcome;
|
|
54
|
+
if (eventTarget) login.setBusy(eventTarget, true);
|
|
55
|
+
const form = eventTarget?.method === 'password' ? login.shadowRoot?.querySelector('dees-form') : null;
|
|
56
|
+
form?.setStatus('pending', 'Signing in…');
|
|
57
|
+
this.result = `Waiting for ${method}…`;
|
|
58
|
+
const completed = await new Promise<boolean>(resolve => {
|
|
59
|
+
const abort = () => { window.clearTimeout(timer); resolve(false); };
|
|
60
|
+
const timer = window.setTimeout(() => { signal.removeEventListener('abort', abort); resolve(true); }, 700);
|
|
61
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
62
|
+
});
|
|
63
|
+
if (!completed || signal.aborted || !login.isConnected) return;
|
|
64
|
+
if (eventTarget) login.setBusy(eventTarget, false);
|
|
65
|
+
form?.setStatus('normal', 'Sign in');
|
|
66
|
+
if (outcome === 'error') {
|
|
67
|
+
this.result = `${method} was declined. The other sign-in methods remain available.`;
|
|
68
|
+
if (eventTarget) login.reportError(eventTarget, 'Could not sign in. Try again or choose another method.');
|
|
69
|
+
else throw new Error('Could not sign in. Try again or choose another method.');
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
this.result = `Signed in with ${method}.`;
|
|
73
|
+
await login.switchToSlottedContent();
|
|
74
|
+
if (signal.aborted || !login.isConnected) return;
|
|
75
|
+
await this.updateComplete;
|
|
76
|
+
login.querySelector('dees-button')?.focus();
|
|
216
77
|
}
|
|
217
78
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
</div>
|
|
235
|
-
`,
|
|
236
|
-
)}
|
|
237
|
-
<div class="sidebarTitle logTitle">Event log</div>
|
|
238
|
-
<div class="logEntries">
|
|
239
|
-
${this.log.length === 0
|
|
240
|
-
? html`<div>— nothing yet —</div>`
|
|
241
|
-
: this.log.map((entry) => html`<div>${entry}</div>`)}
|
|
242
|
-
</div>
|
|
243
|
-
</div>
|
|
244
|
-
<div class="stage">${this.renderVariant()}</div>
|
|
245
|
-
</div>
|
|
246
|
-
`;
|
|
79
|
+
private signOut(): void {
|
|
80
|
+
const login = this.login;
|
|
81
|
+
if (!login) return;
|
|
82
|
+
login.reset();
|
|
83
|
+
const root = login.shadowRoot!;
|
|
84
|
+
root.querySelector('dees-form')?.setStatus('normal', 'Sign in');
|
|
85
|
+
Object.assign(root.querySelector<HTMLElement>('.login')!.style, { opacity: '1', transform: 'translateY(0px)' });
|
|
86
|
+
root.querySelector<HTMLElement>('.loginContainer')!.style.pointerEvents = 'all';
|
|
87
|
+
Object.assign(root.querySelector<HTMLElement>('.slotContainer')!.style, { opacity: '0', pointerEvents: 'none' });
|
|
88
|
+
this.result = 'Signed out. The same login surface is ready again.';
|
|
89
|
+
requestAnimationFrame(() => {
|
|
90
|
+
if (!login.isConnected) return;
|
|
91
|
+
const button = root.querySelector('dees-button');
|
|
92
|
+
const input = root.querySelector('dees-input-text');
|
|
93
|
+
(button || input)?.focus();
|
|
94
|
+
});
|
|
247
95
|
}
|
|
248
96
|
|
|
249
|
-
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
97
|
+
public render() {
|
|
98
|
+
const v = this.variant;
|
|
99
|
+
const eventMode = v === 'events';
|
|
100
|
+
const passkey = ['full', 'passkey', 'enroll', 'events', 'unavailable'].includes(v);
|
|
101
|
+
const password = ['full', 'password', 'many', 'events'].includes(v);
|
|
102
|
+
const configuredProviders = ['full', 'providers', 'events'].includes(v) ? providers : v === 'many' ? [
|
|
103
|
+
...providers, { id: 'email', label: 'Email link', icon: 'lucide:mail' }, { id: 'key', label: 'Security key', icon: 'lucide:keyRound' },
|
|
104
|
+
{ id: 'card', label: 'Smartcard', icon: 'lucide:contact' }, { id: 'directory', label: 'Directory', icon: 'lucide:network', disabled: true },
|
|
105
|
+
] : [];
|
|
106
|
+
return html`<div class="controls">
|
|
107
|
+
<dees-input-dropdown label="Configuration" .options=${variants} .selectedOption=${variants.find(variant => variant.key === v)!}
|
|
108
|
+
@selectedOption=${(event: CustomEvent) => { this.variant = event.detail.key; this.resetDemo(); }}></dees-input-dropdown>
|
|
109
|
+
<dees-input-multitoggle label="Demo response" .options=${[{ key: 'success', label: 'Success' }, { key: 'error', label: 'Error' }]} .value=${this.outcome}
|
|
110
|
+
@change=${(event: CustomEvent) => { this.outcome = event.detail.value; }}></dees-input-multitoggle>
|
|
111
|
+
<dees-button type="ghost" text="Reset demo" @clicked=${this.resetDemo}></dees-button>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="stage">${directives.keyed(`${v}-${this.revision}`, html`<dees-simple-login name="Studio" .passkey=${passkey} .passkeyAvailable=${v !== 'unavailable'} .password=${password}
|
|
114
|
+
.providers=${configuredProviders} .passkeyIntents=${v === 'enroll' ? ['authenticate', 'register'] : ['authenticate']}
|
|
115
|
+
.labels=${{ heading: v === 'enroll' ? 'Your key to Studio' : 'Welcome to Studio', subheading: v === 'enroll' ? 'Sign in or create a passkey for this device.' : 'A little space for your next big idea.' }}
|
|
116
|
+
.passkeyLoginHandler=${eventMode ? undefined : () => this.respond('your passkey')}
|
|
117
|
+
.passkeyRegisterHandler=${() => this.respond('a new passkey')}
|
|
118
|
+
.providerLoginHandler=${eventMode ? undefined : (context: IDeesLoginProviderContext) => this.respond(context.provider.label)}
|
|
119
|
+
.passwordLoginHandler=${eventMode || v === 'password' ? undefined : () => this.respond('your password')}
|
|
120
|
+
@passkey-login=${() => { if (eventMode) void this.respond('your passkey', { method: 'passkey' }); }}
|
|
121
|
+
@provider-login=${(event: CustomEvent) => { if (eventMode) void this.respond(event.detail.provider.label, { method: 'provider', providerId: event.detail.providerId }); }}
|
|
122
|
+
@login=${() => { if (eventMode || v === 'password') void this.respond('your password', { method: 'password' }); }}>
|
|
123
|
+
<dees-icon slot="brand" icon="lucide:layers" iconSize="26"></dees-icon>
|
|
124
|
+
<div class="authenticated"><dees-icon icon="lucide:circleCheck" iconSize="36"></dees-icon><h2>You're in.</h2><p>Your Studio workspace is ready.</p>
|
|
125
|
+
<dees-button type="accent" text="Sign out" @clicked=${this.signOut}></dees-button>
|
|
254
126
|
</div>
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (this.variant === 'legacy') {
|
|
258
|
-
return html`
|
|
259
|
-
<dees-simple-login
|
|
260
|
-
name="My Application"
|
|
261
|
-
@login=${(eventArg: CustomEvent) => {
|
|
262
|
-
const data = eventArg.detail?.data;
|
|
263
|
-
this.note(`login: ${data?.username} / ${'*'.repeat(data?.password?.length || 0)}`);
|
|
264
|
-
void this.loginElement?.switchToSlottedContent();
|
|
265
|
-
}}
|
|
266
|
-
>
|
|
267
|
-
${shared}
|
|
268
|
-
</dees-simple-login>
|
|
269
|
-
`;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (this.variant === 'full') {
|
|
273
|
-
return html`
|
|
274
|
-
<dees-simple-login
|
|
275
|
-
name="idp.global"
|
|
276
|
-
.passkey=${true}
|
|
277
|
-
.passkeyAvailable=${true}
|
|
278
|
-
.providers=${demoProviders}
|
|
279
|
-
.labels=${{ subheading: 'Choose how you want to continue' }}
|
|
280
|
-
.passkeyLoginHandler=${async (contextArg: IDeesLoginPasskeyContext) => {
|
|
281
|
-
this.note(`passkey handler (${contextArg.mediation})`);
|
|
282
|
-
await delay(900);
|
|
283
|
-
throw new Error('No passkey found for this account.');
|
|
284
|
-
}}
|
|
285
|
-
.providerLoginHandler=${async (contextArg: IDeesLoginProviderContext) => {
|
|
286
|
-
this.note(`provider handler: ${contextArg.providerId}`);
|
|
287
|
-
await delay(900);
|
|
288
|
-
void this.loginElement?.switchToSlottedContent();
|
|
289
|
-
}}
|
|
290
|
-
.passwordLoginHandler=${async () => {
|
|
291
|
-
this.note('password handler');
|
|
292
|
-
await delay(900);
|
|
293
|
-
void this.loginElement?.switchToSlottedContent();
|
|
294
|
-
}}
|
|
295
|
-
@login=${(eventArg: CustomEvent) => {
|
|
296
|
-
this.note(`login event: ${eventArg.detail?.data?.username}`);
|
|
297
|
-
}}
|
|
298
|
-
>
|
|
299
|
-
${shared}
|
|
300
|
-
</dees-simple-login>
|
|
301
|
-
`;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (this.variant === 'passkeyOnly') {
|
|
305
|
-
return html`
|
|
306
|
-
<dees-simple-login
|
|
307
|
-
name="Onebox"
|
|
308
|
-
.passkey=${true}
|
|
309
|
-
.passkeyAvailable=${true}
|
|
310
|
-
.password=${false}
|
|
311
|
-
.labels=${{ subheading: 'Use a passkey registered for your Onebox account' }}
|
|
312
|
-
.passkeyLoginHandler=${async () => {
|
|
313
|
-
this.note('passkey sign in');
|
|
314
|
-
await delay(900);
|
|
315
|
-
void this.loginElement?.switchToSlottedContent();
|
|
316
|
-
}}
|
|
317
|
-
>
|
|
318
|
-
${shared}
|
|
319
|
-
</dees-simple-login>
|
|
320
|
-
`;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (this.variant === 'enrollment') {
|
|
324
|
-
return html`
|
|
325
|
-
<dees-simple-login
|
|
326
|
-
name="Onebox"
|
|
327
|
-
.passkey=${true}
|
|
328
|
-
.passkeyAvailable=${true}
|
|
329
|
-
.password=${false}
|
|
330
|
-
.passkeyIntents=${['authenticate', 'register']}
|
|
331
|
-
.labels=${{ subheading: 'Sign in, or enroll this device' }}
|
|
332
|
-
.passkeyLoginHandler=${async () => {
|
|
333
|
-
this.note('passkey authenticate');
|
|
334
|
-
await delay(900);
|
|
335
|
-
throw new Error('This device has no passkey for Onebox yet.');
|
|
336
|
-
}}
|
|
337
|
-
.passkeyRegisterHandler=${async () => {
|
|
338
|
-
this.note('passkey register');
|
|
339
|
-
await delay(900);
|
|
340
|
-
void this.loginElement?.switchToSlottedContent();
|
|
341
|
-
}}
|
|
342
|
-
>
|
|
343
|
-
${shared}
|
|
344
|
-
</dees-simple-login>
|
|
345
|
-
`;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
if (this.variant === 'providerOnly') {
|
|
349
|
-
return html`
|
|
350
|
-
<dees-simple-login
|
|
351
|
-
name="login.idp.global"
|
|
352
|
-
.password=${false}
|
|
353
|
-
.providers=${demoProviders}
|
|
354
|
-
.labels=${{ subheading: 'Continue with one of your identity providers' }}
|
|
355
|
-
.providerLoginHandler=${async (contextArg: IDeesLoginProviderContext) => {
|
|
356
|
-
this.note(`provider handler: ${contextArg.providerId}`);
|
|
357
|
-
await delay(900);
|
|
358
|
-
void this.loginElement?.switchToSlottedContent();
|
|
359
|
-
}}
|
|
360
|
-
>
|
|
361
|
-
${shared}
|
|
362
|
-
</dees-simple-login>
|
|
363
|
-
`;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (this.variant === 'manyProviders') {
|
|
367
|
-
return html`
|
|
368
|
-
<dees-simple-login
|
|
369
|
-
name="login.idp.global"
|
|
370
|
-
.providers=${manyProviders}
|
|
371
|
-
.methodOrder=${['provider', 'password'] as TDeesLoginMethod[]}
|
|
372
|
-
.providerLoginHandler=${async (contextArg: IDeesLoginProviderContext) => {
|
|
373
|
-
this.note(`provider handler: ${contextArg.providerId}`);
|
|
374
|
-
await delay(600);
|
|
375
|
-
throw new Error('Discovery endpoint unreachable.');
|
|
376
|
-
}}
|
|
377
|
-
@login=${() => this.note('login event')}
|
|
378
|
-
>
|
|
379
|
-
${shared}
|
|
380
|
-
</dees-simple-login>
|
|
381
|
-
`;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// eventMode
|
|
385
|
-
return html`
|
|
386
|
-
<dees-simple-login
|
|
387
|
-
name="Cloudly"
|
|
388
|
-
.passkey=${true}
|
|
389
|
-
.passkeyAvailable=${true}
|
|
390
|
-
.providers=${demoProviders}
|
|
391
|
-
@passkey-login=${async (eventArg: CustomEvent) => {
|
|
392
|
-
this.note(`passkey-login event (username: ${eventArg.detail.username || '—'})`);
|
|
393
|
-
const element = this.loginElement;
|
|
394
|
-
element?.setBusy({ method: 'passkey' }, true);
|
|
395
|
-
await delay(900);
|
|
396
|
-
element?.setBusy({ method: 'passkey' }, false);
|
|
397
|
-
element?.reportError({ method: 'passkey' }, 'Consumer-reported: ceremony declined.');
|
|
398
|
-
}}
|
|
399
|
-
@provider-login=${async (eventArg: CustomEvent) => {
|
|
400
|
-
this.note(`provider-login event: ${eventArg.detail.providerId}`);
|
|
401
|
-
const element = this.loginElement;
|
|
402
|
-
const target = { method: 'provider' as const, providerId: eventArg.detail.providerId };
|
|
403
|
-
element?.setBusy(target, true);
|
|
404
|
-
await delay(900);
|
|
405
|
-
element?.setBusy(target, false);
|
|
406
|
-
element?.reportError(target, 'Consumer-reported: redirect blocked.');
|
|
407
|
-
}}
|
|
408
|
-
@login=${(eventArg: CustomEvent) => {
|
|
409
|
-
this.note(`login event: ${eventArg.detail?.data?.username}`);
|
|
410
|
-
this.loginElement?.reportError('password', 'Consumer-reported: invalid credentials.');
|
|
411
|
-
}}
|
|
412
|
-
>
|
|
413
|
-
${shared}
|
|
414
|
-
</dees-simple-login>
|
|
415
|
-
`;
|
|
127
|
+
</dees-simple-login>`)}</div><output role="status">${this.result}</output>`;
|
|
416
128
|
}
|
|
417
129
|
}
|
|
418
130
|
|
|
419
|
-
export const demoFunc = () => html
|
|
420
|
-
<style>
|
|
421
|
-
body {
|
|
422
|
-
margin: 0;
|
|
423
|
-
padding: 0;
|
|
424
|
-
}
|
|
425
|
-
.demo-container {
|
|
426
|
-
width: 100%;
|
|
427
|
-
height: 100%;
|
|
428
|
-
position: absolute;
|
|
429
|
-
top: 0;
|
|
430
|
-
left: 0;
|
|
431
|
-
}
|
|
432
|
-
</style>
|
|
433
|
-
<div class="demo-container">
|
|
434
|
-
<dees-simple-login-demo></dees-simple-login-demo>
|
|
435
|
-
</div>
|
|
436
|
-
`;
|
|
131
|
+
export const demoFunc = () => demoPage('Sign in', 'One welcoming surface. Passkeys, workspace accounts, and passwords working together.', html`<dees-demo-simple-login></dees-demo-simple-login>`);
|