@design.estate/dees-catalog 3.97.1 → 3.98.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.
Files changed (22) hide show
  1. package/dist_bundle/bundle.js +4606 -3404
  2. package/dist_ts_web/00_commitinfo_data.js +1 -1
  3. package/dist_ts_web/elements/00group-button/dees-button/dees-button.d.ts +35 -0
  4. package/dist_ts_web/elements/00group-button/dees-button/dees-button.js +128 -5
  5. package/dist_ts_web/elements/00group-feedback/dees-spinner/dees-spinner.js +12 -3
  6. package/dist_ts_web/elements/00group-form/dees-form-submit/dees-form-submit.d.ts +9 -0
  7. package/dist_ts_web/elements/00group-form/dees-form-submit/dees-form-submit.js +25 -2
  8. package/dist_ts_web/elements/00group-input/dees-input-text/dees-input-text.d.ts +15 -0
  9. package/dist_ts_web/elements/00group-input/dees-input-text/dees-input-text.js +36 -2
  10. package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.d.ts +246 -0
  11. package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.js +439 -21
  12. package/dist_ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.js +857 -23
  13. package/package.json +3 -3
  14. package/readme.hints.md +35 -0
  15. package/readme.md +80 -11
  16. package/ts_web/00_commitinfo_data.ts +1 -1
  17. package/ts_web/elements/00group-button/dees-button/dees-button.ts +128 -2
  18. package/ts_web/elements/00group-feedback/dees-spinner/dees-spinner.ts +11 -2
  19. package/ts_web/elements/00group-form/dees-form-submit/dees-form-submit.ts +18 -0
  20. package/ts_web/elements/00group-input/dees-input-text/dees-input-text.ts +29 -0
  21. package/ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.demo.ts +418 -19
  22. package/ts_web/elements/00group-simple/dees-simple-login/dees-simple-login.ts +969 -20
@@ -33,9 +33,46 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
33
33
  return useValue ? value : void 0;
34
34
  };
35
35
  import { demoFunc } from './dees-simple-login.demo.js';
36
- import { customElement, html, DeesElement, property, cssManager, css, } from '@design.estate/dees-element';
36
+ import { customElement, html, DeesElement, property, state, cssManager, css, } from '@design.estate/dees-element';
37
37
  import { themeDefaultStyles } from '../../00theme.js';
38
38
  import '../../00group-layout/dees-tile/dees-tile.js';
39
+ import '../../00group-button/dees-button/dees-button.js';
40
+ import '../../00group-form/dees-form/dees-form.js';
41
+ import '../../00group-form/dees-form-submit/dees-form-submit.js';
42
+ import '../../00group-input/dees-input-text/dees-input-text.js';
43
+ import '../../00group-utility/dees-icon/dees-icon.js';
44
+ const canonicalMethodOrder = ['passkey', 'provider', 'password'];
45
+ /**
46
+ * dees-simple-login — the login surface for an application shell.
47
+ *
48
+ * Offers up to three authentication methods in one card: passkeys, identity providers
49
+ * ("sign in with …") and a username/password form. A method is offered only when it is
50
+ * configured, so the zero-configuration default is the password form alone.
51
+ *
52
+ * ## Who owns the WebAuthn ceremony
53
+ *
54
+ * Not this component. A passkey ceremony needs server-issued options and server-side
55
+ * verification, so the catalog deliberately carries no WebAuthn dependency and no
56
+ * knowledge of any wire protocol. There are two ways to plug a ceremony in, and exactly
57
+ * one of them is active per interaction:
58
+ *
59
+ * 1. **Event mode** (no handler set) — the component dispatches `passkey-login`,
60
+ * `passkey-register` or `provider-login` and stops. The consumer drives everything and
61
+ * reports progress back through `setBusy()` / `reportError()`.
62
+ * 2. **Handler mode** (handler property set) — the component awaits the handler, owns the
63
+ * per-method busy state and turns a rejection into that method's error message. The
64
+ * request event is *not* dispatched, so a ceremony can never be started twice.
65
+ *
66
+ * The legacy `login` event is a notification rather than a request and always fires, even
67
+ * when `passwordLoginHandler` is set. Do not both listen to `login` and set that handler.
68
+ *
69
+ * ## Shadow DOM contract
70
+ *
71
+ * Consumers reach into this shadow root: `.loginContainer`, `.login` and `.slotContainer`
72
+ * carry the post-login transition, and `shadowRoot.querySelector('dees-form')` is expected
73
+ * to be the password form. Those are load-bearing and must not be renamed, and no second
74
+ * `dees-form` may precede the password form.
75
+ */
39
76
  let DeesSimpleLogin = (() => {
40
77
  let _classDecorators = [customElement('dees-simple-login')];
41
78
  let _classDescriptor;
@@ -45,12 +82,87 @@ let DeesSimpleLogin = (() => {
45
82
  let _name_decorators;
46
83
  let _name_initializers = [];
47
84
  let _name_extraInitializers = [];
85
+ let _passkey_decorators;
86
+ let _passkey_initializers = [];
87
+ let _passkey_extraInitializers = [];
88
+ let _passkeyIntents_decorators;
89
+ let _passkeyIntents_initializers = [];
90
+ let _passkeyIntents_extraInitializers = [];
91
+ let _passkeyAvailable_decorators;
92
+ let _passkeyAvailable_initializers = [];
93
+ let _passkeyAvailable_extraInitializers = [];
94
+ let _passkeyAutofill_decorators;
95
+ let _passkeyAutofill_initializers = [];
96
+ let _passkeyAutofill_extraInitializers = [];
97
+ let _providers_decorators;
98
+ let _providers_initializers = [];
99
+ let _providers_extraInitializers = [];
100
+ let _password_decorators;
101
+ let _password_initializers = [];
102
+ let _password_extraInitializers = [];
103
+ let _methodOrder_decorators;
104
+ let _methodOrder_initializers = [];
105
+ let _methodOrder_extraInitializers = [];
106
+ let _labels_decorators;
107
+ let _labels_initializers = [];
108
+ let _labels_extraInitializers = [];
109
+ let _passkeyLoginHandler_decorators;
110
+ let _passkeyLoginHandler_initializers = [];
111
+ let _passkeyLoginHandler_extraInitializers = [];
112
+ let _passkeyRegisterHandler_decorators;
113
+ let _passkeyRegisterHandler_initializers = [];
114
+ let _passkeyRegisterHandler_extraInitializers = [];
115
+ let _providerLoginHandler_decorators;
116
+ let _providerLoginHandler_initializers = [];
117
+ let _providerLoginHandler_extraInitializers = [];
118
+ let _passwordLoginHandler_decorators;
119
+ let _passwordLoginHandler_initializers = [];
120
+ let _passwordLoginHandler_extraInitializers = [];
121
+ let _detectedPasskeySupport_decorators;
122
+ let _detectedPasskeySupport_initializers = [];
123
+ let _detectedPasskeySupport_extraInitializers = [];
124
+ let _busyKeys_decorators;
125
+ let _busyKeys_initializers = [];
126
+ let _busyKeys_extraInitializers = [];
127
+ let _errorMap_decorators;
128
+ let _errorMap_initializers = [];
129
+ let _errorMap_extraInitializers = [];
48
130
  var DeesSimpleLogin = class extends _classSuper {
49
131
  static { _classThis = this; }
50
132
  static {
51
133
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
52
134
  _name_decorators = [property()];
135
+ _passkey_decorators = [property({ type: Boolean })];
136
+ _passkeyIntents_decorators = [property({ attribute: false })];
137
+ _passkeyAvailable_decorators = [property({ attribute: false })];
138
+ _passkeyAutofill_decorators = [property({ type: Boolean })];
139
+ _providers_decorators = [property({ attribute: false })];
140
+ _password_decorators = [property({ type: Boolean })];
141
+ _methodOrder_decorators = [property({ attribute: false })];
142
+ _labels_decorators = [property({ attribute: false })];
143
+ _passkeyLoginHandler_decorators = [property({ attribute: false })];
144
+ _passkeyRegisterHandler_decorators = [property({ attribute: false })];
145
+ _providerLoginHandler_decorators = [property({ attribute: false })];
146
+ _passwordLoginHandler_decorators = [property({ attribute: false })];
147
+ _detectedPasskeySupport_decorators = [state()];
148
+ _busyKeys_decorators = [state()];
149
+ _errorMap_decorators = [state()];
53
150
  __esDecorate(this, null, _name_decorators, { kind: "accessor", name: "name", static: false, private: false, access: { has: obj => "name" in obj, get: obj => obj.name, set: (obj, value) => { obj.name = value; } }, metadata: _metadata }, _name_initializers, _name_extraInitializers);
151
+ __esDecorate(this, null, _passkey_decorators, { kind: "accessor", name: "passkey", static: false, private: false, access: { has: obj => "passkey" in obj, get: obj => obj.passkey, set: (obj, value) => { obj.passkey = value; } }, metadata: _metadata }, _passkey_initializers, _passkey_extraInitializers);
152
+ __esDecorate(this, null, _passkeyIntents_decorators, { kind: "accessor", name: "passkeyIntents", static: false, private: false, access: { has: obj => "passkeyIntents" in obj, get: obj => obj.passkeyIntents, set: (obj, value) => { obj.passkeyIntents = value; } }, metadata: _metadata }, _passkeyIntents_initializers, _passkeyIntents_extraInitializers);
153
+ __esDecorate(this, null, _passkeyAvailable_decorators, { kind: "accessor", name: "passkeyAvailable", static: false, private: false, access: { has: obj => "passkeyAvailable" in obj, get: obj => obj.passkeyAvailable, set: (obj, value) => { obj.passkeyAvailable = value; } }, metadata: _metadata }, _passkeyAvailable_initializers, _passkeyAvailable_extraInitializers);
154
+ __esDecorate(this, null, _passkeyAutofill_decorators, { kind: "accessor", name: "passkeyAutofill", static: false, private: false, access: { has: obj => "passkeyAutofill" in obj, get: obj => obj.passkeyAutofill, set: (obj, value) => { obj.passkeyAutofill = value; } }, metadata: _metadata }, _passkeyAutofill_initializers, _passkeyAutofill_extraInitializers);
155
+ __esDecorate(this, null, _providers_decorators, { kind: "accessor", name: "providers", static: false, private: false, access: { has: obj => "providers" in obj, get: obj => obj.providers, set: (obj, value) => { obj.providers = value; } }, metadata: _metadata }, _providers_initializers, _providers_extraInitializers);
156
+ __esDecorate(this, null, _password_decorators, { kind: "accessor", name: "password", static: false, private: false, access: { has: obj => "password" in obj, get: obj => obj.password, set: (obj, value) => { obj.password = value; } }, metadata: _metadata }, _password_initializers, _password_extraInitializers);
157
+ __esDecorate(this, null, _methodOrder_decorators, { kind: "accessor", name: "methodOrder", static: false, private: false, access: { has: obj => "methodOrder" in obj, get: obj => obj.methodOrder, set: (obj, value) => { obj.methodOrder = value; } }, metadata: _metadata }, _methodOrder_initializers, _methodOrder_extraInitializers);
158
+ __esDecorate(this, null, _labels_decorators, { kind: "accessor", name: "labels", static: false, private: false, access: { has: obj => "labels" in obj, get: obj => obj.labels, set: (obj, value) => { obj.labels = value; } }, metadata: _metadata }, _labels_initializers, _labels_extraInitializers);
159
+ __esDecorate(this, null, _passkeyLoginHandler_decorators, { kind: "accessor", name: "passkeyLoginHandler", static: false, private: false, access: { has: obj => "passkeyLoginHandler" in obj, get: obj => obj.passkeyLoginHandler, set: (obj, value) => { obj.passkeyLoginHandler = value; } }, metadata: _metadata }, _passkeyLoginHandler_initializers, _passkeyLoginHandler_extraInitializers);
160
+ __esDecorate(this, null, _passkeyRegisterHandler_decorators, { kind: "accessor", name: "passkeyRegisterHandler", static: false, private: false, access: { has: obj => "passkeyRegisterHandler" in obj, get: obj => obj.passkeyRegisterHandler, set: (obj, value) => { obj.passkeyRegisterHandler = value; } }, metadata: _metadata }, _passkeyRegisterHandler_initializers, _passkeyRegisterHandler_extraInitializers);
161
+ __esDecorate(this, null, _providerLoginHandler_decorators, { kind: "accessor", name: "providerLoginHandler", static: false, private: false, access: { has: obj => "providerLoginHandler" in obj, get: obj => obj.providerLoginHandler, set: (obj, value) => { obj.providerLoginHandler = value; } }, metadata: _metadata }, _providerLoginHandler_initializers, _providerLoginHandler_extraInitializers);
162
+ __esDecorate(this, null, _passwordLoginHandler_decorators, { kind: "accessor", name: "passwordLoginHandler", static: false, private: false, access: { has: obj => "passwordLoginHandler" in obj, get: obj => obj.passwordLoginHandler, set: (obj, value) => { obj.passwordLoginHandler = value; } }, metadata: _metadata }, _passwordLoginHandler_initializers, _passwordLoginHandler_extraInitializers);
163
+ __esDecorate(this, null, _detectedPasskeySupport_decorators, { kind: "accessor", name: "detectedPasskeySupport", static: false, private: false, access: { has: obj => "detectedPasskeySupport" in obj, get: obj => obj.detectedPasskeySupport, set: (obj, value) => { obj.detectedPasskeySupport = value; } }, metadata: _metadata }, _detectedPasskeySupport_initializers, _detectedPasskeySupport_extraInitializers);
164
+ __esDecorate(this, null, _busyKeys_decorators, { kind: "accessor", name: "busyKeys", static: false, private: false, access: { has: obj => "busyKeys" in obj, get: obj => obj.busyKeys, set: (obj, value) => { obj.busyKeys = value; } }, metadata: _metadata }, _busyKeys_initializers, _busyKeys_extraInitializers);
165
+ __esDecorate(this, null, _errorMap_decorators, { kind: "accessor", name: "errorMap", static: false, private: false, access: { has: obj => "errorMap" in obj, get: obj => obj.errorMap, set: (obj, value) => { obj.errorMap = value; } }, metadata: _metadata }, _errorMap_initializers, _errorMap_extraInitializers);
54
166
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
55
167
  DeesSimpleLogin = _classThis = _classDescriptor.value;
56
168
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
@@ -60,8 +172,88 @@ let DeesSimpleLogin = (() => {
60
172
  static demoGroups = ['Simple'];
61
173
  #name_accessor_storage = __runInitializers(this, _name_initializers, 'Application');
62
174
  // INSTANCE
175
+ /** application name, interpolated into the default subheading */
63
176
  get name() { return this.#name_accessor_storage; }
64
177
  set name(value) { this.#name_accessor_storage = value; }
178
+ #passkey_accessor_storage = (__runInitializers(this, _name_extraInitializers), __runInitializers(this, _passkey_initializers, false));
179
+ /**
180
+ * offer a passkey affordance. Silently drops out when the browser cannot do WebAuthn,
181
+ * unless it is the only configured method — then the card explains itself instead of
182
+ * rendering empty.
183
+ */
184
+ get passkey() { return this.#passkey_accessor_storage; }
185
+ set passkey(value) { this.#passkey_accessor_storage = value; }
186
+ #passkeyIntents_accessor_storage = (__runInitializers(this, _passkey_extraInitializers), __runInitializers(this, _passkeyIntents_initializers, ['authenticate']));
187
+ /** which passkey affordances to render, in this order */
188
+ get passkeyIntents() { return this.#passkeyIntents_accessor_storage; }
189
+ set passkeyIntents(value) { this.#passkeyIntents_accessor_storage = value; }
190
+ #passkeyAvailable_accessor_storage = (__runInitializers(this, _passkeyIntents_extraInitializers), __runInitializers(this, _passkeyAvailable_initializers, undefined));
191
+ /**
192
+ * overrides browser capability detection. `undefined` detects automatically; set it when
193
+ * the server already knows whether passkeys are configured for this deployment.
194
+ */
195
+ get passkeyAvailable() { return this.#passkeyAvailable_accessor_storage; }
196
+ set passkeyAvailable(value) { this.#passkeyAvailable_accessor_storage = value; }
197
+ #passkeyAutofill_accessor_storage = (__runInitializers(this, _passkeyAvailable_extraInitializers), __runInitializers(this, _passkeyAutofill_initializers, false));
198
+ /**
199
+ * opt into WebAuthn conditional mediation (passkey autofill). Requires
200
+ * `passkeyLoginHandler` and a rendered password method — the username field is what the
201
+ * browser attaches its passkey picker to. Silently inert when either is missing.
202
+ */
203
+ get passkeyAutofill() { return this.#passkeyAutofill_accessor_storage; }
204
+ set passkeyAutofill(value) { this.#passkeyAutofill_accessor_storage = value; }
205
+ #providers_accessor_storage = (__runInitializers(this, _passkeyAutofill_extraInitializers), __runInitializers(this, _providers_initializers, []));
206
+ /** identity providers to offer. Empty means the provider method is not configured. */
207
+ get providers() { return this.#providers_accessor_storage; }
208
+ set providers(value) { this.#providers_accessor_storage = value; }
209
+ #password_accessor_storage = (__runInitializers(this, _providers_extraInitializers), __runInitializers(this, _password_initializers, true));
210
+ /** offer the username/password form. On by default — set `.password=${false}` to drop it. */
211
+ get password() { return this.#password_accessor_storage; }
212
+ set password(value) { this.#password_accessor_storage = value; }
213
+ #methodOrder_accessor_storage = (__runInitializers(this, _password_extraInitializers), __runInitializers(this, _methodOrder_initializers, ['passkey', 'provider', 'password']));
214
+ /**
215
+ * reorders the configured methods. Configured methods missing from this list are appended
216
+ * in canonical order, so an incomplete list can never silently hide a method.
217
+ */
218
+ get methodOrder() { return this.#methodOrder_accessor_storage; }
219
+ set methodOrder(value) { this.#methodOrder_accessor_storage = value; }
220
+ #labels_accessor_storage = (__runInitializers(this, _methodOrder_extraInitializers), __runInitializers(this, _labels_initializers, {}));
221
+ /** copy overrides */
222
+ get labels() { return this.#labels_accessor_storage; }
223
+ set labels(value) { this.#labels_accessor_storage = value; }
224
+ #passkeyLoginHandler_accessor_storage = (__runInitializers(this, _labels_extraInitializers), __runInitializers(this, _passkeyLoginHandler_initializers, undefined));
225
+ /** drives the passkey sign-in ceremony — see "Who owns the WebAuthn ceremony" */
226
+ get passkeyLoginHandler() { return this.#passkeyLoginHandler_accessor_storage; }
227
+ set passkeyLoginHandler(value) { this.#passkeyLoginHandler_accessor_storage = value; }
228
+ #passkeyRegisterHandler_accessor_storage = (__runInitializers(this, _passkeyLoginHandler_extraInitializers), __runInitializers(this, _passkeyRegisterHandler_initializers, undefined));
229
+ /** drives the passkey enrollment ceremony */
230
+ get passkeyRegisterHandler() { return this.#passkeyRegisterHandler_accessor_storage; }
231
+ set passkeyRegisterHandler(value) { this.#passkeyRegisterHandler_accessor_storage = value; }
232
+ #providerLoginHandler_accessor_storage = (__runInitializers(this, _passkeyRegisterHandler_extraInitializers), __runInitializers(this, _providerLoginHandler_initializers, undefined));
233
+ /** drives a provider sign-in (redirect or popup) */
234
+ get providerLoginHandler() { return this.#providerLoginHandler_accessor_storage; }
235
+ set providerLoginHandler(value) { this.#providerLoginHandler_accessor_storage = value; }
236
+ #passwordLoginHandler_accessor_storage = (__runInitializers(this, _providerLoginHandler_extraInitializers), __runInitializers(this, _passwordLoginHandler_initializers, undefined));
237
+ /** drives a credential sign-in. The legacy `login` event fires regardless. */
238
+ get passwordLoginHandler() { return this.#passwordLoginHandler_accessor_storage; }
239
+ set passwordLoginHandler(value) { this.#passwordLoginHandler_accessor_storage = value; }
240
+ #detectedPasskeySupport_accessor_storage = (__runInitializers(this, _passwordLoginHandler_extraInitializers), __runInitializers(this, _detectedPasskeySupport_initializers, {
241
+ available: false,
242
+ conditionalMediation: false,
243
+ platformAuthenticator: false,
244
+ }));
245
+ get detectedPasskeySupport() { return this.#detectedPasskeySupport_accessor_storage; }
246
+ set detectedPasskeySupport(value) { this.#detectedPasskeySupport_accessor_storage = value; }
247
+ #busyKeys_accessor_storage = (__runInitializers(this, _detectedPasskeySupport_extraInitializers), __runInitializers(this, _busyKeys_initializers, []));
248
+ get busyKeys() { return this.#busyKeys_accessor_storage; }
249
+ set busyKeys(value) { this.#busyKeys_accessor_storage = value; }
250
+ #errorMap_accessor_storage = (__runInitializers(this, _busyKeys_extraInitializers), __runInitializers(this, _errorMap_initializers, {}));
251
+ get errorMap() { return this.#errorMap_accessor_storage; }
252
+ set errorMap(value) { this.#errorMap_accessor_storage = value; }
253
+ ceremonyControllers = (__runInitializers(this, _errorMap_extraInitializers), new Map());
254
+ autofillController = undefined;
255
+ autofillStarted = false;
256
+ interactivityObserver = undefined;
65
257
  static styles = [
66
258
  themeDefaultStyles,
67
259
  cssManager.defaultStyles,
@@ -84,6 +276,11 @@ let DeesSimpleLogin = (() => {
84
276
  height: 100%;
85
277
  top: 0;
86
278
  left: 0;
279
+ box-sizing: border-box;
280
+ /* a card with passkey + several providers + credentials can outgrow a short
281
+ viewport, so the container scrolls instead of clipping */
282
+ padding: var(--dees-spacing-xl);
283
+ overflow-y: auto;
87
284
  background: var(--dees-color-bg-primary);
88
285
  }
89
286
 
@@ -121,8 +318,117 @@ let DeesSimpleLogin = (() => {
121
318
  }
122
319
 
123
320
  .subheader {
321
+ font-size: var(--dees-font-control-size);
322
+ /* secondary rather than muted: the tertiary label token is a 0.30 alpha and drops
323
+ under 2:1 against both backgrounds */
324
+ color: var(--dees-color-text-secondary);
325
+ }
326
+
327
+ .methods {
328
+ display: flex;
329
+ flex-direction: column;
330
+ gap: var(--dees-spacing-lg);
331
+ }
332
+
333
+ .method {
334
+ display: flex;
335
+ flex-direction: column;
336
+ gap: var(--dees-spacing-sm);
337
+ }
338
+
339
+ .methodActions {
340
+ display: flex;
341
+ flex-direction: column;
342
+ gap: var(--dees-spacing-sm);
343
+ }
344
+
345
+ /* Four or more providers would turn the card into a tower, so they pair up. The
346
+ labels lose their prefix at the same time — see denseProviders. */
347
+ .methodActions.dense {
348
+ display: grid;
349
+ grid-template-columns: repeat(2, minmax(0, 1fr));
350
+ }
351
+
352
+ /* an odd trailing provider spans the row instead of leaving a ragged half cell */
353
+ .methodActions.dense > :last-child:nth-child(odd) {
354
+ grid-column: 1 / -1;
355
+ }
356
+
357
+ /* dees-button's default pending face is a 20% accent tint with accent-coloured text,
358
+ which lands under 2:1 on a dark canvas. Each group therefore states a busy face in
359
+ its own emphasis instead: the primary action keeps its solid accent, and a provider
360
+ keeps its secondary surface so only the spinner changes. */
361
+ .passkeyActions dees-button {
362
+ --button-pending-bg: var(--dees-color-accent-primary);
363
+ --button-pending-fg: var(--dees-color-on-accent);
364
+ --dees-spinner-color: var(--dees-color-on-accent);
365
+ }
366
+
367
+ .providerActions dees-button {
368
+ --button-pending-bg: var(--dees-color-fill-secondary);
369
+ --button-pending-fg: var(--dees-color-text-primary);
370
+ --dees-spinner-color: var(--dees-color-text-primary);
371
+ }
372
+
373
+ .divider {
374
+ display: flex;
375
+ align-items: center;
376
+ gap: var(--dees-spacing-md);
377
+ font-size: var(--dees-font-control-size-sm);
378
+ color: var(--dees-color-text-secondary);
379
+ text-transform: lowercase;
380
+ }
381
+
382
+ .divider::before,
383
+ .divider::after {
384
+ content: '';
385
+ flex: 1;
386
+ height: 1px;
387
+ background: var(--dees-color-border-subtle);
388
+ }
389
+
390
+ .methodError {
391
+ display: flex;
392
+ align-items: flex-start;
393
+ gap: var(--dees-spacing-xs);
394
+ font-size: var(--dees-font-control-size-sm);
395
+ line-height: 1.4;
396
+ color: var(--dees-color-text-error);
397
+ user-select: text;
398
+ }
399
+
400
+ .methodError dees-icon {
401
+ flex-shrink: 0;
402
+ margin-top: 1px;
403
+ }
404
+
405
+ .unavailable {
406
+ padding: var(--dees-spacing-lg);
407
+ border: 1px solid var(--dees-color-border-subtle);
408
+ border-radius: var(--dees-radius-xl);
409
+ corner-shape: var(--dees-corner-shape);
410
+ background: var(--dees-color-bg-secondary);
124
411
  font-size: var(--dees-font-control-size);
125
412
  color: var(--dees-color-text-muted);
413
+ text-align: center;
414
+ }
415
+
416
+ /* The bare credentials block, used whenever the card already offers another method.
417
+ A nested tile there would inset the fields 24px against full-width buttons above
418
+ it and add a second frame inside the card. */
419
+ .credentials {
420
+ display: flex;
421
+ flex-direction: column;
422
+ gap: var(--dees-spacing-lg);
423
+ }
424
+
425
+ .credentials dees-input-text {
426
+ width: 100%;
427
+ }
428
+
429
+ .credentials dees-form-submit {
430
+ margin-top: var(--dees-spacing-sm);
431
+ width: 100%;
126
432
  }
127
433
 
128
434
  dees-tile {
@@ -149,21 +455,149 @@ let DeesSimpleLogin = (() => {
149
455
  }
150
456
  `,
151
457
  ];
458
+ // ------------------------------------------------------------------------------------
459
+ // resolution
460
+ // ------------------------------------------------------------------------------------
461
+ /** resolved browser capability, with `passkeyAvailable` applied */
462
+ get passkeySupport() {
463
+ if (this.passkeyAvailable === undefined) {
464
+ return this.detectedPasskeySupport;
465
+ }
466
+ return { ...this.detectedPasskeySupport, available: this.passkeyAvailable };
467
+ }
468
+ /** the methods that are configured, in render order */
469
+ get resolvedMethods() {
470
+ const configured = canonicalMethodOrder.filter((methodArg) => this.isConfigured(methodArg));
471
+ const ordered = [];
472
+ for (const methodArg of this.methodOrder || []) {
473
+ if (configured.includes(methodArg) && !ordered.includes(methodArg)) {
474
+ ordered.push(methodArg);
475
+ }
476
+ }
477
+ for (const methodArg of configured) {
478
+ if (!ordered.includes(methodArg)) {
479
+ ordered.push(methodArg);
480
+ }
481
+ }
482
+ return ordered;
483
+ }
484
+ isConfigured(methodArg) {
485
+ switch (methodArg) {
486
+ case 'passkey':
487
+ return this.passkey && this.passkeySupport.available && this.resolvedPasskeyIntents.length > 0;
488
+ case 'provider':
489
+ return this.providers.length > 0;
490
+ case 'password':
491
+ return this.password;
492
+ default:
493
+ return false;
494
+ }
495
+ }
496
+ get resolvedPasskeyIntents() {
497
+ const intents = (this.passkeyIntents || []).filter((intentArg, index, all) => all.indexOf(intentArg) === index);
498
+ return intents.length > 0 ? intents : ['authenticate'];
499
+ }
500
+ /**
501
+ * true when nothing at all is offered — typically a passkey-only card in a browser that
502
+ * cannot do WebAuthn. Silent degradation would leave an empty card, so this case gets a
503
+ * message instead.
504
+ */
505
+ get isUnavailable() {
506
+ return this.resolvedMethods.length === 0;
507
+ }
508
+ get shouldOfferPasskeyAutofill() {
509
+ const methods = this.resolvedMethods;
510
+ return (this.passkeyAutofill &&
511
+ Boolean(this.passkeyLoginHandler) &&
512
+ this.passkeySupport.conditionalMediation &&
513
+ methods.includes('passkey') &&
514
+ methods.includes('password'));
515
+ }
516
+ copy(keyArg, fallbackArg) {
517
+ const value = (this.labels || {})[keyArg];
518
+ return value === undefined ? fallbackArg : value;
519
+ }
520
+ // ------------------------------------------------------------------------------------
521
+ // per-method state
522
+ // ------------------------------------------------------------------------------------
523
+ static targetKey(targetArg) {
524
+ const target = typeof targetArg === 'string' ? { method: targetArg } : targetArg;
525
+ if (target.method === 'passkey') {
526
+ return `passkey:${target.intent || 'authenticate'}`;
527
+ }
528
+ if (target.method === 'provider') {
529
+ return `provider:${target.providerId || ''}`;
530
+ }
531
+ return 'password';
532
+ }
533
+ /** true while a ceremony for this target is running */
534
+ isBusy(targetArg) {
535
+ return this.busyKeys.includes(DeesSimpleLogin.targetKey(targetArg));
536
+ }
537
+ /** marks a target busy — for consumers driving a ceremony from an intent event */
538
+ setBusy(targetArg, busyArg) {
539
+ const key = DeesSimpleLogin.targetKey(targetArg);
540
+ const isBusy = this.busyKeys.includes(key);
541
+ if (busyArg === isBusy) {
542
+ return;
543
+ }
544
+ this.busyKeys = busyArg
545
+ ? [...this.busyKeys, key]
546
+ : this.busyKeys.filter((busyKey) => busyKey !== key);
547
+ }
548
+ /** the error currently shown for a target, if any */
549
+ getError(targetArg) {
550
+ return this.errorMap[DeesSimpleLogin.targetKey(targetArg)];
551
+ }
552
+ /**
553
+ * shows an error next to one method without touching the others — a failed passkey
554
+ * attempt must never blank the password form.
555
+ */
556
+ reportError(targetArg, messageArg) {
557
+ const key = DeesSimpleLogin.targetKey(targetArg);
558
+ if (this.errorMap[key] === messageArg) {
559
+ return;
560
+ }
561
+ this.errorMap = { ...this.errorMap, [key]: messageArg };
562
+ }
563
+ /** clears one target's error, or every error when called without a target */
564
+ clearError(targetArg) {
565
+ if (targetArg === undefined) {
566
+ if (Object.keys(this.errorMap).length > 0) {
567
+ this.errorMap = {};
568
+ }
569
+ return;
570
+ }
571
+ const key = DeesSimpleLogin.targetKey(targetArg);
572
+ if (this.errorMap[key] === undefined) {
573
+ return;
574
+ }
575
+ const nextMap = { ...this.errorMap };
576
+ delete nextMap[key];
577
+ this.errorMap = nextMap;
578
+ }
579
+ /** clears every busy and error state and resets the password form */
580
+ reset() {
581
+ this.abortCeremonies();
582
+ this.busyKeys = [];
583
+ this.errorMap = {};
584
+ const form = this.shadowRoot?.querySelector('dees-form');
585
+ form?.reset();
586
+ }
587
+ // ------------------------------------------------------------------------------------
588
+ // render
589
+ // ------------------------------------------------------------------------------------
152
590
  render() {
153
591
  return html `
154
592
  <div class="loginContainer">
155
593
  <div class="login">
156
594
  <div class="login-header">
157
- <div class="header">Sign in</div>
158
- <div class="subheader">Enter your credentials to access ${this.name}</div>
595
+ <div class="header">${this.copy('heading', 'Sign in')}</div>
596
+ <div class="subheader">
597
+ ${this.copy('subheading', `Enter your credentials to access ${this.name}`)}
598
+ </div>
159
599
  </div>
160
- <dees-tile .heading=${'Credentials'}>
161
- <dees-form>
162
- <dees-input-text key="username" label="Username" required></dees-input-text>
163
- <dees-input-text key="password" label="Password" isPasswordBool required></dees-input-text>
164
- <dees-form-submit>Sign in</dees-form-submit>
165
- </dees-form>
166
- </dees-tile>
600
+ ${this.renderMethods()}
167
601
  </div>
168
602
  </div>
169
603
  <div class="slotContainer">
@@ -171,18 +605,422 @@ let DeesSimpleLogin = (() => {
171
605
  </div>
172
606
  `;
173
607
  }
608
+ renderMethods() {
609
+ if (this.isUnavailable) {
610
+ return html `
611
+ <div class="methods">
612
+ <div class="unavailable">
613
+ ${this.copy('unavailable', 'No sign-in method is available in this browser.')}
614
+ </div>
615
+ </div>
616
+ `;
617
+ }
618
+ const methods = this.resolvedMethods;
619
+ return html `
620
+ <div class="methods">
621
+ ${methods.map((methodArg, index) => html `
622
+ ${index === 0
623
+ ? ''
624
+ : html `<div class="divider">${this.copy('divider', 'or')}</div>`}
625
+ ${this.renderMethod(methodArg)}
626
+ `)}
627
+ </div>
628
+ `;
629
+ }
630
+ renderMethod(methodArg) {
631
+ if (methodArg === 'passkey') {
632
+ return this.renderPasskeyMethod();
633
+ }
634
+ if (methodArg === 'provider') {
635
+ return this.renderProviderMethod();
636
+ }
637
+ return this.renderPasswordMethod();
638
+ }
639
+ renderPasskeyMethod() {
640
+ const intents = this.resolvedPasskeyIntents;
641
+ // Concurrent WebAuthn calls reject each other, so a running ceremony locks the *other*
642
+ // passkey intent — providers and the password form stay usable. The busy button itself
643
+ // is never marked disabled: dees-button dims a disabled face to 50% opacity, which
644
+ // would wash out the pending spinner. handlePasskey() guards the re-entry instead.
645
+ const anyPasskeyBusy = intents.some((intentArg) => this.isBusy({ method: 'passkey', intent: intentArg }));
646
+ return html `
647
+ <div class="method">
648
+ <div class="methodActions passkeyActions">
649
+ ${intents.map((intentArg) => {
650
+ const busy = this.isBusy({ method: 'passkey', intent: intentArg });
651
+ const isRegister = intentArg === 'register';
652
+ return html `
653
+ <dees-button
654
+ full-width
655
+ .type=${isRegister ? 'outline' : 'accent'}
656
+ .icon=${busy ? '' : isRegister ? 'lucide:keyRound' : 'lucide:fingerprint'}
657
+ .text=${isRegister
658
+ ? this.copy('passkeyRegister', 'Create a passkey')
659
+ : this.copy('passkeyAuthenticate', 'Sign in with a passkey')}
660
+ .status=${busy ? 'pending' : 'normal'}
661
+ .disabled=${anyPasskeyBusy && !busy}
662
+ @clicked=${() => this.handlePasskey(intentArg)}
663
+ ></dees-button>
664
+ `;
665
+ })}
666
+ </div>
667
+ ${intents.map((intentArg) => this.renderError(this.getError({ method: 'passkey', intent: intentArg })))}
668
+ </div>
669
+ `;
670
+ }
671
+ /**
672
+ * Past three providers the buttons pair up into two columns, and the "Continue with"
673
+ * prefix is dropped so a bare provider name still fits its half-width button.
674
+ */
675
+ get denseProviders() {
676
+ return this.providers.length >= 4;
677
+ }
678
+ renderProviderMethod() {
679
+ const dense = this.denseProviders;
680
+ // Half-width buttons cannot carry "Continue with …", so the prefix is dropped when the
681
+ // grid kicks in — unless the consumer stated one explicitly, which always wins.
682
+ const prefix = this.copy('providerPrefix', dense ? '' : 'Continue with');
683
+ return html `
684
+ <div class="method">
685
+ <div class="methodActions providerActions ${dense ? 'dense' : ''}">
686
+ ${this.providers.map((providerArg) => {
687
+ const busy = this.isBusy({ method: 'provider', providerId: providerArg.id });
688
+ return html `
689
+ <dees-button
690
+ full-width
691
+ title=${dense ? providerArg.label : ''}
692
+ .type=${'secondary'}
693
+ .icon=${busy ? '' : providerArg.icon || ''}
694
+ .text=${prefix ? `${prefix} ${providerArg.label}` : providerArg.label}
695
+ .status=${busy ? 'pending' : 'normal'}
696
+ .disabled=${Boolean(providerArg.disabled)}
697
+ @clicked=${() => this.handleProvider(providerArg)}
698
+ ></dees-button>
699
+ `;
700
+ })}
701
+ </div>
702
+ ${this.renderError(this.getError({ method: 'provider' }))}
703
+ ${this.providers.map((providerArg) => {
704
+ const message = this.getError({ method: 'provider', providerId: providerArg.id });
705
+ if (!message) {
706
+ return '';
707
+ }
708
+ return this.renderError(this.providers.length > 1 ? `${providerArg.label}: ${message}` : message);
709
+ })}
710
+ </div>
711
+ `;
712
+ }
713
+ renderPasswordMethod() {
714
+ // The submit label is slotted, not bound: consumers call dees-form.setStatus(), which
715
+ // writes dees-form-submit.text imperatively. A property binding here would clobber
716
+ // their status text on the next render.
717
+ const form = html `
718
+ <dees-form @formData=${this.handleFormData}>
719
+ <dees-input-text
720
+ key="username"
721
+ .label=${this.copy('usernameLabel', 'Username')}
722
+ .autocomplete=${this.shouldOfferPasskeyAutofill ? 'username webauthn' : 'username'}
723
+ required
724
+ ></dees-input-text>
725
+ <dees-input-text
726
+ key="password"
727
+ .label=${this.copy('passwordLabel', 'Password')}
728
+ .autocomplete=${'current-password'}
729
+ isPasswordBool
730
+ required
731
+ ></dees-input-text>
732
+ <dees-form-submit full-width>${this.copy('passwordSubmit', 'Sign in')}</dees-form-submit>
733
+ </dees-form>
734
+ `;
735
+ // The tile is what gives a lone credentials form its card. Once the column holds other
736
+ // methods the column *is* the card, and a second frame around only the fields reads as
737
+ // a stray box — so the form joins the column bare and keeps the same 360px edge.
738
+ return html `
739
+ <div class="method">
740
+ ${this.resolvedMethods.length === 1
741
+ ? html `
742
+ <dees-tile .heading=${this.copy('credentialsHeading', 'Credentials')}>
743
+ ${form}
744
+ </dees-tile>
745
+ `
746
+ : html `<div class="credentials">${form}</div>`}
747
+ ${this.renderError(this.getError('password'))}
748
+ </div>
749
+ `;
750
+ }
751
+ renderError(messageArg) {
752
+ if (!messageArg) {
753
+ return '';
754
+ }
755
+ return html `
756
+ <div class="methodError" role="alert">
757
+ <dees-icon .icon=${'lucide:circleAlert'} .iconSize=${14}></dees-icon>
758
+ <span>${messageArg}</span>
759
+ </div>
760
+ `;
761
+ }
762
+ // ------------------------------------------------------------------------------------
763
+ // lifecycle
764
+ // ------------------------------------------------------------------------------------
765
+ async connectedCallback() {
766
+ await super.connectedCallback();
767
+ this.detectPasskeySupportSync();
768
+ void this.detectPasskeySupportAsync();
769
+ }
174
770
  async firstUpdated(_changedProperties) {
175
771
  super.firstUpdated(_changedProperties);
176
- const form = this.shadowRoot.querySelector('dees-form');
177
- if (form) {
178
- form.addEventListener('formData', ((event) => {
179
- this.dispatchEvent(new CustomEvent('login', {
180
- detail: event.detail,
181
- bubbles: true,
182
- composed: true
183
- }));
772
+ this.observeContainerInteractivity();
773
+ void this.maybeStartPasskeyAutofill();
774
+ }
775
+ updated(_changedProperties) {
776
+ super.updated(_changedProperties);
777
+ // Only take over the submit button's visual state when this component actually owns
778
+ // the credential ceremony. Legacy consumers drive it through dees-form.setStatus().
779
+ if (this.passwordLoginHandler) {
780
+ const submitButton = this.shadowRoot?.querySelector('dees-form-submit');
781
+ if (submitButton) {
782
+ submitButton.status = this.isBusy('password') ? 'pending' : 'normal';
783
+ }
784
+ }
785
+ void this.maybeStartPasskeyAutofill();
786
+ }
787
+ async disconnectedCallback() {
788
+ await super.disconnectedCallback();
789
+ this.abortCeremonies();
790
+ this.interactivityObserver?.disconnect();
791
+ this.interactivityObserver = undefined;
792
+ // re-arm autofill if this element is attached again
793
+ this.autofillStarted = false;
794
+ }
795
+ detectPasskeySupportSync() {
796
+ const available = typeof window !== 'undefined' &&
797
+ window.isSecureContext === true &&
798
+ typeof window.PublicKeyCredential ===
799
+ 'function' &&
800
+ typeof navigator !== 'undefined' &&
801
+ typeof navigator.credentials?.get === 'function';
802
+ if (this.detectedPasskeySupport.available !== available) {
803
+ this.detectedPasskeySupport = { ...this.detectedPasskeySupport, available };
804
+ }
805
+ }
806
+ async detectPasskeySupportAsync() {
807
+ if (!this.detectedPasskeySupport.available) {
808
+ return;
809
+ }
810
+ const publicKeyCredential = window.PublicKeyCredential;
811
+ const probe = async (probeArg) => {
812
+ if (typeof probeArg !== 'function') {
813
+ return false;
814
+ }
815
+ try {
816
+ return (await probeArg.call(publicKeyCredential)) === true;
817
+ }
818
+ catch {
819
+ return false;
820
+ }
821
+ };
822
+ const [conditionalMediation, platformAuthenticator] = await Promise.all([
823
+ probe(publicKeyCredential.isConditionalMediationAvailable),
824
+ probe(publicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable),
825
+ ]);
826
+ this.detectedPasskeySupport = {
827
+ available: true,
828
+ conditionalMediation,
829
+ platformAuthenticator,
830
+ };
831
+ }
832
+ // ------------------------------------------------------------------------------------
833
+ // interactions
834
+ // ------------------------------------------------------------------------------------
835
+ handleFormData = async (eventArg) => {
836
+ const detail = eventArg.detail;
837
+ if (this.isBusy('password')) {
838
+ return;
839
+ }
840
+ this.clearError('password');
841
+ // Unchanged legacy contract: `login` carries dees-form's detail verbatim.
842
+ this.dispatchEvent(new CustomEvent('login', {
843
+ detail,
844
+ bubbles: true,
845
+ composed: true,
846
+ }));
847
+ if (!this.passwordLoginHandler) {
848
+ return;
849
+ }
850
+ const handler = this.passwordLoginHandler;
851
+ await this.runCeremony({ method: 'password' }, () => handler({ data: detail?.data || {} }));
852
+ };
853
+ handlePasskey = async (intentArg) => {
854
+ const target = { method: 'passkey', intent: intentArg };
855
+ if (this.resolvedPasskeyIntents.some((candidate) => this.isBusy({ method: 'passkey', intent: candidate }))) {
856
+ return;
857
+ }
858
+ // An explicit ceremony supersedes a silent autofill request; leaving both in flight
859
+ // makes the browser reject one of them.
860
+ this.abortAutofill();
861
+ this.clearError(target);
862
+ const handler = intentArg === 'register' ? this.passkeyRegisterHandler : this.passkeyLoginHandler;
863
+ if (!handler) {
864
+ this.dispatchEvent(new CustomEvent(intentArg === 'register' ? 'passkey-register' : 'passkey-login', {
865
+ detail: { intent: intentArg, username: this.readUsername() },
866
+ bubbles: true,
867
+ composed: true,
868
+ }));
869
+ return;
870
+ }
871
+ const key = DeesSimpleLogin.targetKey(target);
872
+ const controller = new AbortController();
873
+ this.ceremonyControllers.set(key, controller);
874
+ try {
875
+ await this.runCeremony(target, () => handler({
876
+ intent: intentArg,
877
+ username: this.readUsername(),
878
+ mediation: 'optional',
879
+ signal: controller.signal,
880
+ }));
881
+ }
882
+ finally {
883
+ if (this.ceremonyControllers.get(key) === controller) {
884
+ this.ceremonyControllers.delete(key);
885
+ }
886
+ }
887
+ };
888
+ handleProvider = async (providerArg) => {
889
+ const target = { method: 'provider', providerId: providerArg.id };
890
+ if (providerArg.disabled || this.isBusy(target)) {
891
+ return;
892
+ }
893
+ this.clearError(target);
894
+ if (!this.providerLoginHandler) {
895
+ this.dispatchEvent(new CustomEvent('provider-login', {
896
+ detail: { providerId: providerArg.id, provider: providerArg },
897
+ bubbles: true,
898
+ composed: true,
184
899
  }));
900
+ return;
901
+ }
902
+ const handler = this.providerLoginHandler;
903
+ await this.runCeremony(target, () => handler({ providerId: providerArg.id, provider: providerArg }));
904
+ };
905
+ async runCeremony(targetArg, ceremonyArg) {
906
+ this.setBusy(targetArg, true);
907
+ try {
908
+ await ceremonyArg();
909
+ }
910
+ catch (error) {
911
+ if (!DeesSimpleLogin.isAbortError(error)) {
912
+ this.reportError(targetArg, DeesSimpleLogin.toErrorMessage(error));
913
+ }
914
+ }
915
+ finally {
916
+ this.setBusy(targetArg, false);
917
+ }
918
+ }
919
+ /**
920
+ * Starts the browser's passkey autofill. Conditional mediation has to be requested
921
+ * before the user touches anything, and it must stay silent — a background ceremony that
922
+ * finds no credential is not an error the user should see.
923
+ */
924
+ async maybeStartPasskeyAutofill() {
925
+ if (this.autofillStarted || !this.shouldOfferPasskeyAutofill) {
926
+ return;
927
+ }
928
+ const handler = this.passkeyLoginHandler;
929
+ if (!handler) {
930
+ return;
931
+ }
932
+ this.autofillStarted = true;
933
+ const controller = new AbortController();
934
+ this.autofillController = controller;
935
+ try {
936
+ await handler({
937
+ intent: 'authenticate',
938
+ username: undefined,
939
+ mediation: 'conditional',
940
+ signal: controller.signal,
941
+ });
942
+ }
943
+ catch (error) {
944
+ if (!DeesSimpleLogin.isAbortError(error)) {
945
+ console.warn('dees-simple-login: passkey autofill ceremony failed', error);
946
+ }
947
+ }
948
+ finally {
949
+ if (this.autofillController === controller) {
950
+ this.autofillController = undefined;
951
+ }
952
+ // deliberately not reset: one silent attempt per connection, so a rejecting handler
953
+ // can never be retried in a render loop
954
+ }
955
+ }
956
+ abortAutofill() {
957
+ this.autofillController?.abort();
958
+ this.autofillController = undefined;
959
+ }
960
+ abortCeremonies() {
961
+ this.abortAutofill();
962
+ for (const controller of this.ceremonyControllers.values()) {
963
+ controller.abort();
964
+ }
965
+ this.ceremonyControllers.clear();
966
+ }
967
+ readUsername() {
968
+ const input = this.shadowRoot?.querySelector('dees-input-text[key="username"]');
969
+ const value = input?.value;
970
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
971
+ }
972
+ static isAbortError(errorArg) {
973
+ return Boolean(errorArg) && errorArg.name === 'AbortError';
974
+ }
975
+ static toErrorMessage(errorArg) {
976
+ if (errorArg instanceof Error) {
977
+ return errorArg.message;
978
+ }
979
+ return String(errorArg);
980
+ }
981
+ /**
982
+ * The login card and the slotted app are both permanently in the DOM, stacked and
983
+ * cross-faded with opacity plus `pointer-events`. That was enough while nothing inside
984
+ * either half could hold focus — but `dees-button` faces are focusable now, and
985
+ * `pointer-events: none` does not remove anything from the tab order. Without this, a
986
+ * keyboard user could Tab out of the password form straight into the invisible app shell,
987
+ * and after signing in could Tab back into the invisible login card and start a passkey
988
+ * ceremony there. `inert` is what actually takes a hidden subtree out of focus and the
989
+ * accessibility tree.
990
+ *
991
+ * Inertness is derived from each container's effective `pointer-events` rather than from
992
+ * an internal flag, because consumers reverse this transition by hand — cloudly's
993
+ * `switchToLoginContent()` writes these inline styles directly and knows nothing about
994
+ * `inert`. Keying off a flag they cannot reset would leave their login card permanently
995
+ * inert. A MutationObserver on the inline styles keeps both directions correct no matter
996
+ * who wrote them.
997
+ */
998
+ syncContainerInertness = () => {
999
+ for (const selector of ['.loginContainer', '.slotContainer']) {
1000
+ const container = this.shadowRoot?.querySelector(selector);
1001
+ if (!(container instanceof HTMLElement)) {
1002
+ continue;
1003
+ }
1004
+ container.inert = getComputedStyle(container).pointerEvents === 'none';
1005
+ }
1006
+ };
1007
+ observeContainerInteractivity() {
1008
+ if (this.interactivityObserver) {
1009
+ return;
185
1010
  }
1011
+ this.interactivityObserver = new MutationObserver(() => this.syncContainerInertness());
1012
+ for (const selector of ['.loginContainer', '.slotContainer']) {
1013
+ const container = this.shadowRoot?.querySelector(selector);
1014
+ if (container) {
1015
+ // only the inline style matters; `inert` reflects to an attribute of its own and
1016
+ // must not re-trigger this observer
1017
+ this.interactivityObserver.observe(container, {
1018
+ attributes: true,
1019
+ attributeFilter: ['style'],
1020
+ });
1021
+ }
1022
+ }
1023
+ this.syncContainerInertness();
186
1024
  }
187
1025
  /**
188
1026
  * allows switching to slotted content
@@ -202,10 +1040,6 @@ let DeesSimpleLogin = (() => {
202
1040
  await domtools.convenience.smartdelay.delayFor(300);
203
1041
  slotContainerDiv.style.pointerEvents = 'all';
204
1042
  }
205
- constructor() {
206
- super(...arguments);
207
- __runInitializers(this, _name_extraInitializers);
208
- }
209
1043
  static {
210
1044
  __runInitializers(_classThis, _classExtraInitializers);
211
1045
  }
@@ -213,4 +1047,4 @@ let DeesSimpleLogin = (() => {
213
1047
  return DeesSimpleLogin = _classThis;
214
1048
  })();
215
1049
  export { DeesSimpleLogin };
216
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1zaW1wbGUtbG9naW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1zaW1wbGUvZGVlcy1zaW1wbGUtbG9naW4vZGVlcy1zaW1wbGUtbG9naW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUV2RCxPQUFPLEVBQ0wsYUFBYSxFQUNiLElBQUksRUFDSixXQUFXLEVBQ1gsUUFBUSxFQUVSLFVBQVUsRUFDVixHQUFHLEdBQ0osTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN0RCxPQUFPLDZDQUE2QyxDQUFDO0lBU3hDLGVBQWU7NEJBRDNCLGFBQWEsQ0FBQyxtQkFBbUIsQ0FBQzs7OztzQkFDRSxXQUFXOzs7OytCQUFuQixTQUFRLFdBQVc7Ozs7Z0NBTTdDLFFBQVEsRUFBRTtZQUNYLGlLQUFTLElBQUksNkJBQUosSUFBSSxtRkFBeUI7WUFQeEMsNktBeUpDOzs7O1FBeEpDLFNBQVM7UUFDRixNQUFNLENBQUMsSUFBSSxHQUFHLFFBQVEsQ0FBQztRQUN2QixNQUFNLENBQUMsVUFBVSxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFJdEMscUVBQXdCLGFBQWEsRUFBQztRQUh0QyxXQUFXO1FBR1gsSUFBUyxJQUFJLDBDQUF5QjtRQUF0QyxJQUFTLElBQUksZ0RBQXlCO1FBRS9CLE1BQU0sQ0FBQyxNQUFNLEdBQUc7WUFDckIsa0JBQWtCO1lBQ2xCLFVBQVUsQ0FBQyxhQUFhO1lBQ3hCLEdBQUcsQ0FBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztLQWtGRjtTQUNGLENBQUM7UUFFSyxNQUFNO1lBQ1gsT0FBTyxJQUFJLENBQUE7Ozs7O3NFQUt1RCxJQUFJLENBQUMsSUFBSTs7Z0NBRS9DLGFBQWE7Ozs7Ozs7Ozs7OztLQVl4QyxDQUFDO1FBQ0osQ0FBQztRQUVNLEtBQUssQ0FBQyxZQUFZLENBQUMsa0JBQTBEO1lBQ2xGLEtBQUssQ0FBQyxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUV2QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVyxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQVEsQ0FBQztZQUNoRSxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUNULElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLEtBQWtCLEVBQUUsRUFBRTtvQkFDeEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxPQUFPLEVBQUU7d0JBQzFDLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTt3QkFDcEIsT0FBTyxFQUFFLElBQUk7d0JBQ2IsUUFBUSxFQUFFLElBQUk7cUJBQ2YsQ0FBQyxDQUFDLENBQUM7Z0JBQ04sQ0FBQyxDQUFrQixDQUFDLENBQUM7WUFDdkIsQ0FBQztRQUNILENBQUM7UUFFRDs7V0FFRztRQUNJLEtBQUssQ0FBQyxzQkFBc0I7WUFDakMsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDO1lBQzVDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFXLENBQUMsYUFBYSxDQUFDLFFBQVEsQ0FBbUIsQ0FBQztZQUM1RSxNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxVQUFXLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFtQixDQUFDO1lBQzlGLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFVBQVcsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLENBQW1CLENBQUM7WUFDNUYsUUFBUSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDO1lBQzdCLFFBQVEsQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLGtCQUFrQixDQUFDO1lBQzlDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO1lBQy9DLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsa0JBQWtCLENBQUM7WUFDdEQsTUFBTSxRQUFRLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDcEQsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUM7WUFDckMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxpQkFBaUIsQ0FBQztZQUNyRCxNQUFNLFFBQVEsQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNwRCxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMvQyxDQUFDOzs7Ozs7WUF4SlUsdURBQWU7Ozs7O1NBQWYsZUFBZSJ9
1050
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1zaW1wbGUtbG9naW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1zaW1wbGUvZGVlcy1zaW1wbGUtbG9naW4vZGVlcy1zaW1wbGUtbG9naW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUV2RCxPQUFPLEVBQ0wsYUFBYSxFQUNiLElBQUksRUFDSixXQUFXLEVBQ1gsUUFBUSxFQUNSLEtBQUssRUFFTCxVQUFVLEVBQ1YsR0FBRyxHQUNKLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdEQsT0FBTyw2Q0FBNkMsQ0FBQztBQUNyRCxPQUFPLGlEQUFpRCxDQUFDO0FBQ3pELE9BQU8sMkNBQTJDLENBQUM7QUFDbkQsT0FBTyx5REFBeUQsQ0FBQztBQUNqRSxPQUFPLHdEQUF3RCxDQUFDO0FBQ2hFLE9BQU8sOENBQThDLENBQUM7QUErR3RELE1BQU0sb0JBQW9CLEdBQXVCLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLENBQUMsQ0FBQztBQUVyRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEJHO0lBRVUsZUFBZTs0QkFEM0IsYUFBYSxDQUFDLG1CQUFtQixDQUFDOzs7O3NCQUNFLFdBQVc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7K0JBQW5CLFNBQVEsV0FBVzs7OztnQ0FRN0MsUUFBUSxFQUFFO21DQVFWLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQzswQ0FJM0IsUUFBUSxDQUFDLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxDQUFDOzRDQU85QixRQUFRLENBQUMsRUFBRSxT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