@zitadel/components 0.0.0 → 0.1.0-alpha.10

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 (119) hide show
  1. package/README.md +76 -55
  2. package/dist/atoms/index.d.mts +1 -1
  3. package/dist/atoms/index.mjs +1 -1
  4. package/dist/{atoms-CmOTltTH.mjs → atoms-BaayzEsr.mjs} +246 -93
  5. package/dist/atoms-BaayzEsr.mjs.map +1 -0
  6. package/dist/default-Cpl78hQN.mjs +6 -0
  7. package/dist/default-Cpl78hQN.mjs.map +1 -0
  8. package/dist/{index-7FDHEpv5.d.mts → index-DB_JTtln.d.mts} +104 -100
  9. package/dist/index-DB_JTtln.d.mts.map +1 -0
  10. package/dist/{index-DIUFZjXw.d.mts → index-DVDCrfkv.d.mts} +1550 -850
  11. package/dist/index-DVDCrfkv.d.mts.map +1 -0
  12. package/dist/{index-DaOSCm0T.d.mts → index-EJengPPu.d.mts} +1 -1
  13. package/dist/{index-DaOSCm0T.d.mts.map → index-EJengPPu.d.mts.map} +1 -1
  14. package/dist/index.d.mts +6 -5
  15. package/dist/index.d.mts.map +1 -1
  16. package/dist/index.mjs +5 -4
  17. package/dist/{manifest-DCC2FxCE.d.mts → manifest-DN5Al_Ur.d.mts} +1 -1
  18. package/dist/{manifest-DCC2FxCE.d.mts.map → manifest-DN5Al_Ur.d.mts.map} +1 -1
  19. package/dist/manifests.d.mts +1 -1
  20. package/dist/manifests.mjs +1 -1
  21. package/dist/orchestrator/index.d.mts +3 -2
  22. package/dist/orchestrator/index.mjs +3 -2
  23. package/dist/{orchestrator-CNKo2WQG.mjs → orchestrator-BEvS2wA_.mjs} +667 -641
  24. package/dist/orchestrator-BEvS2wA_.mjs.map +1 -0
  25. package/dist/standalone.mjs +12156 -0
  26. package/dist/tokens/index.d.mts +1 -1
  27. package/dist/tokens/index.mjs +1 -1
  28. package/dist/{tokens-TXmurodq.mjs → tokens-BQ_augxi.mjs} +2 -2
  29. package/dist/{tokens-TXmurodq.mjs.map → tokens-BQ_augxi.mjs.map} +1 -1
  30. package/package.json +9 -17
  31. package/dist/atoms/index.d.ts +0 -9
  32. package/dist/atoms/index.d.ts.map +0 -1
  33. package/dist/atoms/zl-alert.d.ts +0 -56
  34. package/dist/atoms/zl-alert.d.ts.map +0 -1
  35. package/dist/atoms/zl-button.d.ts +0 -83
  36. package/dist/atoms/zl-button.d.ts.map +0 -1
  37. package/dist/atoms/zl-card.d.ts +0 -46
  38. package/dist/atoms/zl-card.d.ts.map +0 -1
  39. package/dist/atoms/zl-field.d.ts +0 -73
  40. package/dist/atoms/zl-field.d.ts.map +0 -1
  41. package/dist/atoms/zl-icon.d.ts +0 -48
  42. package/dist/atoms/zl-icon.d.ts.map +0 -1
  43. package/dist/atoms/zl-page-shell.d.ts +0 -42
  44. package/dist/atoms/zl-page-shell.d.ts.map +0 -1
  45. package/dist/atoms/zl-passkey.d.ts +0 -118
  46. package/dist/atoms/zl-passkey.d.ts.map +0 -1
  47. package/dist/atoms/zl-pill.d.ts +0 -55
  48. package/dist/atoms/zl-pill.d.ts.map +0 -1
  49. package/dist/atoms-CmOTltTH.mjs.map +0 -1
  50. package/dist/index-7FDHEpv5.d.mts.map +0 -1
  51. package/dist/index-DIUFZjXw.d.mts.map +0 -1
  52. package/dist/index-bZEvwHtq.d.mts +0 -996
  53. package/dist/index-bZEvwHtq.d.mts.map +0 -1
  54. package/dist/index.d.ts +0 -16
  55. package/dist/index.d.ts.map +0 -1
  56. package/dist/internal/base64url.d.ts +0 -18
  57. package/dist/internal/base64url.d.ts.map +0 -1
  58. package/dist/internal/unique-id.d.ts +0 -2
  59. package/dist/internal/unique-id.d.ts.map +0 -1
  60. package/dist/manifest.d.ts +0 -36
  61. package/dist/manifest.d.ts.map +0 -1
  62. package/dist/manifests.d.ts +0 -6
  63. package/dist/manifests.d.ts.map +0 -1
  64. package/dist/orchestrator/api-client.d.ts +0 -33
  65. package/dist/orchestrator/api-client.d.ts.map +0 -1
  66. package/dist/orchestrator/branding-to-tokens.d.ts +0 -28
  67. package/dist/orchestrator/branding-to-tokens.d.ts.map +0 -1
  68. package/dist/orchestrator/branding-validator.d.ts +0 -7
  69. package/dist/orchestrator/branding-validator.d.ts.map +0 -1
  70. package/dist/orchestrator/branding.d.ts +0 -76
  71. package/dist/orchestrator/branding.d.ts.map +0 -1
  72. package/dist/orchestrator/font-loader.d.ts +0 -2
  73. package/dist/orchestrator/font-loader.d.ts.map +0 -1
  74. package/dist/orchestrator/index.d.ts +0 -25
  75. package/dist/orchestrator/index.d.ts.map +0 -1
  76. package/dist/orchestrator/liquid.d.ts +0 -28
  77. package/dist/orchestrator/liquid.d.ts.map +0 -1
  78. package/dist/orchestrator/locales/de.d.ts +0 -9
  79. package/dist/orchestrator/locales/de.d.ts.map +0 -1
  80. package/dist/orchestrator/locales/en.d.ts +0 -13
  81. package/dist/orchestrator/locales/en.d.ts.map +0 -1
  82. package/dist/orchestrator/locales/index.d.ts +0 -12
  83. package/dist/orchestrator/locales/index.d.ts.map +0 -1
  84. package/dist/orchestrator/mandatory-gates.d.ts +0 -26
  85. package/dist/orchestrator/mandatory-gates.d.ts.map +0 -1
  86. package/dist/orchestrator/sanitiser.d.ts +0 -6
  87. package/dist/orchestrator/sanitiser.d.ts.map +0 -1
  88. package/dist/orchestrator/template-context.d.ts +0 -55
  89. package/dist/orchestrator/template-context.d.ts.map +0 -1
  90. package/dist/orchestrator/template-names.d.ts +0 -16
  91. package/dist/orchestrator/template-names.d.ts.map +0 -1
  92. package/dist/orchestrator/templates/auth-form.liquid.d.ts +0 -14
  93. package/dist/orchestrator/templates/auth-form.liquid.d.ts.map +0 -1
  94. package/dist/orchestrator/templates/default.liquid.d.ts +0 -23
  95. package/dist/orchestrator/templates/default.liquid.d.ts.map +0 -1
  96. package/dist/orchestrator/templates/passkey-upsell.liquid.d.ts +0 -15
  97. package/dist/orchestrator/templates/passkey-upsell.liquid.d.ts.map +0 -1
  98. package/dist/orchestrator/templates/signed-in.liquid.d.ts +0 -20
  99. package/dist/orchestrator/templates/signed-in.liquid.d.ts.map +0 -1
  100. package/dist/orchestrator/theme-controller.d.ts +0 -30
  101. package/dist/orchestrator/theme-controller.d.ts.map +0 -1
  102. package/dist/orchestrator/zitadel-login.d.ts +0 -182
  103. package/dist/orchestrator/zitadel-login.d.ts.map +0 -1
  104. package/dist/orchestrator/zitadel-logout.d.ts +0 -86
  105. package/dist/orchestrator/zitadel-logout.d.ts.map +0 -1
  106. package/dist/orchestrator-CNKo2WQG.mjs.map +0 -1
  107. package/dist/styles/base.d.ts +0 -7
  108. package/dist/styles/base.d.ts.map +0 -1
  109. package/dist/styles/focus-ring.d.ts +0 -7
  110. package/dist/styles/focus-ring.d.ts.map +0 -1
  111. package/dist/styles/index.d.ts +0 -5
  112. package/dist/styles/index.d.ts.map +0 -1
  113. package/dist/styles/surface.d.ts +0 -8
  114. package/dist/styles/surface.d.ts.map +0 -1
  115. package/dist/styles/tokens.d.ts +0 -11
  116. package/dist/styles/tokens.d.ts.map +0 -1
  117. package/dist/tokens/index.d.ts +0 -9
  118. package/dist/tokens/index.d.ts.map +0 -1
  119. package/dist/tsconfig.lib.tsbuildinfo +0 -1
@@ -1,14 +1,36 @@
1
- import { t as cssVars } from "./tokens-TXmurodq.mjs";
1
+ import { t as cssVars } from "./tokens-BQ_augxi.mjs";
2
2
  import { LitElement, css, html, nothing, unsafeCSS } from "lit";
3
- import { customElement, property, state } from "lit/decorators.js";
3
+ import { customElement, property, query, state } from "lit/decorators.js";
4
+ import { classMap } from "lit/directives/class-map.js";
4
5
  import { unsafeSVG } from "lit/directives/unsafe-svg.js";
5
6
  import { ArrowLeft, ArrowRight, Check, CircleAlert, Eye, EyeOff, Info, KeyRound, LoaderCircle, Plus, TriangleAlert, User, X } from "lucide";
7
+ import { ifDefined } from "lit/directives/if-defined.js";
8
+ import { live } from "lit/directives/live.js";
6
9
  //#region ../shared-component-styles/src/lit/alert-host.css?inline
7
10
  var alert_host_default = ":host {\n display: block;\n}\n";
8
11
  //#endregion
9
12
  //#region ../shared-component-styles/src/alert.css?inline
10
13
  var alert_default = ".zr-alert {\n align-items: flex-start;\n gap: var(--zl-spacing-03, 1rem);\n padding: var(--zl-spacing-03, 1rem);\n border-radius: var(--zl-radius-m, .75rem);\n background: var(--zl-color-surface-default-primary-gray, #252528);\n color: var(--zl-color-text-button-invert, #f4f4f6);\n font-family: var(--zl-font-family-sans, system-ui, sans-serif);\n font-size: .875rem;\n font-weight: 400;\n line-height: 1.25rem;\n display: flex;\n box-shadow: 0 1px 2px #1018280d;\n}\n\n.zr-alert__icon {\n color: var(--zl-color-text-error, #ea4f70);\n flex-shrink: 0;\n}\n\n.zr-alert--warning .zr-alert__icon {\n color: var(--zl-color-text-subtitle-orange, #f25543);\n}\n\n.zr-alert--success .zr-alert__icon {\n color: var(--zl-color-text-success, #33a779);\n}\n\n.zr-alert--info .zr-alert__icon {\n color: var(--zl-color-text-subtitle-gray, #bfbfcf);\n}\n\n.zr-alert__body {\n gap: var(--zl-spacing-01, .25rem);\n flex-direction: column;\n flex: auto;\n min-width: 0;\n display: flex;\n}\n\n.zr-alert__title {\n color: var(--zl-color-text-button-invert, #f4f4f6);\n font-weight: 600;\n}\n\n.zr-alert__message {\n color: var(--zl-color-border-default-white, #f4f4f6);\n margin: 0;\n}\n\n.zr-alert:not(:has(.zr-alert__title)) .zr-alert__message {\n color: var(--zl-color-text-button-invert, #f4f4f6);\n}\n\n.zr-alert__close {\n all: unset;\n width: 2.25rem;\n height: 2.25rem;\n padding: var(--zl-spacing-02, .5rem);\n border-radius: var(--zl-radius-s, .5rem);\n color: var(--zl-color-text-secondary-gray, #bfbfcf);\n cursor: pointer;\n transition: background-color var(--zl-duration-fast, .12s) var(--zl-easing-standard, cubic-bezier(.2, 0, 0, 1));\n flex-shrink: 0;\n justify-content: center;\n align-items: center;\n display: inline-flex;\n}\n\n.zr-alert__close .zr-icon {\n --zl-icon-size: 1.25rem;\n width: 1.25rem;\n height: 1.25rem;\n}\n\n.zr-alert__close:hover {\n background: var(--zl-color-gray-200, #484a57);\n}\n\n.zr-alert__close:focus-visible {\n outline: var(--zl-focus-width, 2px) solid var(--zl-focus-color, #f4f4f6);\n outline-offset: var(--zl-focus-offset, 2px);\n}\n";
11
14
  //#endregion
15
+ //#region src/internal/emit.ts
16
+ /**
17
+ * Dispatch a custom event with the project-wide defaults (`bubbles` +
18
+ * `composed`) so it crosses the shadow boundary and reaches delegated
19
+ * listeners — whether it's an atom's `zl-*` event or the orchestrator's
20
+ * public `zitadel-*` event.
21
+ *
22
+ * Centralising the dispatch shape keeps every event contract identical and
23
+ * removes the repeated `new CustomEvent(..., { bubbles: true, composed: true,
24
+ * detail })` boilerplate.
25
+ */
26
+ function emit(host, type, detail) {
27
+ return host.dispatchEvent(new CustomEvent(type, {
28
+ bubbles: true,
29
+ composed: true,
30
+ detail
31
+ }));
32
+ }
33
+ //#endregion
12
34
  //#region src/styles/tokens.ts
13
35
  function wrap(node) {
14
36
  if (typeof node === "string") return unsafeCSS(node);
@@ -123,12 +145,12 @@ let ZlIcon = class ZlIcon extends LitElement {
123
145
  const ariaLabel = this.label ?? DEFAULT_LABELS[this.name];
124
146
  const hidden = this.decorative || !ariaLabel;
125
147
  return html`
126
- <span class=${[
127
- "zr-icon",
128
- `zr-icon--${this.size}`,
129
- this.tone !== "default" ? `zr-icon--tone-${this.tone}` : "",
130
- this.spin ? "zr-icon--spin" : ""
131
- ].filter(Boolean).join(" ")}>
148
+ <span class=${classMap({
149
+ "zr-icon": true,
150
+ [`zr-icon--${this.size}`]: true,
151
+ [`zr-icon--tone-${this.tone}`]: this.tone !== "default",
152
+ "zr-icon--spin": this.spin
153
+ })}>
132
154
  <svg
133
155
  viewBox="0 0 24 24"
134
156
  fill="none"
@@ -257,10 +279,7 @@ let ZlAlert = class ZlAlert extends LitElement {
257
279
  `;
258
280
  }
259
281
  handleDismiss = () => {
260
- this.dispatchEvent(new CustomEvent("zl-dismiss", {
261
- bubbles: true,
262
- composed: true
263
- }));
282
+ emit(this, "zl-dismiss");
264
283
  this.remove();
265
284
  };
266
285
  };
@@ -292,7 +311,7 @@ const zlAlertManifest = {
292
311
  "message",
293
312
  "close"
294
313
  ],
295
- slots: [],
314
+ slots: [""],
296
315
  events: ["zl-dismiss"]
297
316
  };
298
317
  //#endregion
@@ -366,63 +385,116 @@ let ZlButton = class ZlButton extends LitElement {
366
385
  set label(value) {
367
386
  this.#_label_accessor_storage = value;
368
387
  }
388
+ #_testId_accessor_storage = void 0;
389
+ get testId() {
390
+ return this.#_testId_accessor_storage;
391
+ }
392
+ set testId(value) {
393
+ this.#_testId_accessor_storage = value;
394
+ }
395
+ #_forcedState_accessor_storage = null;
396
+ get forcedState() {
397
+ return this.#_forcedState_accessor_storage;
398
+ }
399
+ set forcedState(value) {
400
+ this.#_forcedState_accessor_storage = value;
401
+ }
369
402
  internals;
370
403
  constructor() {
371
404
  super();
372
405
  this.internals = this.attachInternals();
373
406
  }
407
+ connectedCallback() {
408
+ super.connectedCallback();
409
+ this.addEventListener("click", this.handleHostClick);
410
+ }
411
+ disconnectedCallback() {
412
+ this.removeEventListener("click", this.handleHostClick);
413
+ super.disconnectedCallback();
414
+ }
374
415
  focus(options) {
375
416
  this.shadowRoot?.querySelector("button")?.focus(options);
376
417
  }
377
- surfaceClasses() {
378
- return [
379
- "root",
380
- "zr-btn",
381
- `zr-btn--${this.hierarchy}`,
382
- `zr-btn--${this.size}`,
383
- this.block ? "zr-btn--block" : ""
384
- ].filter(Boolean).join(" ");
385
- }
386
418
  render() {
387
- const blocked = this.disabled || this.loading;
388
- const forcedState = this.getAttribute("data-state");
389
- const body = this.label !== void 0 ? html`<span>${this.label}</span>` : html`<slot></slot>`;
419
+ const hierarchy = this.stringOption("hierarchy", this.hierarchy, "primary");
420
+ const size = this.stringOption("size", this.size, "medium");
421
+ const type = this.buttonType();
422
+ const loading = this.booleanOption("loading", this.loading);
423
+ const disabled = this.booleanOption("disabled", this.disabled);
424
+ const block = this.booleanOption("block", this.block);
425
+ const label = this.stringOption("label", this.label);
426
+ const blocked = disabled || loading;
427
+ const body = label !== void 0 ? html`<span>${label}</span>` : html`<slot></slot>`;
390
428
  return html`
391
429
  <button
392
- class=${this.surfaceClasses()}
430
+ class=${classMap({
431
+ root: true,
432
+ "zr-btn": true,
433
+ [`zr-btn--${hierarchy}`]: true,
434
+ [`zr-btn--${size}`]: true,
435
+ "zr-btn--block": block
436
+ })}
393
437
  part="root"
394
- type=${this.type}
438
+ type=${type}
395
439
  ?disabled=${blocked}
396
- aria-busy=${this.loading ? "true" : "false"}
397
- data-state=${forcedState ?? nothing}
440
+ aria-busy=${loading ? "true" : "false"}
441
+ data-testid=${this.nativeButtonTestId() ?? nothing}
442
+ data-state=${this.forcedState ?? nothing}
398
443
  @click=${this.handleClick}
399
444
  >
400
445
  <slot name="leading"></slot>
401
446
  ${body}
402
- ${this.loading ? html`<span class="spinner" part="spinner"><zl-icon name="spinner" size=${this.size === "small" ? "16" : "24"} spin decorative></zl-icon></span>` : html`<slot name="trailing"></slot>`}
447
+ ${loading ? html`<span class="spinner" part="spinner"><zl-icon name="spinner" size=${size === "small" ? "16" : "24"} spin decorative></zl-icon></span>` : html`<slot name="trailing"></slot>`}
403
448
  </button>
404
449
  `;
405
450
  }
406
451
  handleClick = (event) => {
407
- if (this.disabled || this.loading) {
452
+ this.activate(event);
453
+ };
454
+ handleHostClick = (event) => {
455
+ if (event.composedPath()[0] !== this) return;
456
+ this.activate(event);
457
+ };
458
+ nativeButtonTestId() {
459
+ const testId = this.stringOption("data-testid", this.testId);
460
+ if (testId) return `${testId}-button`;
461
+ const action = this.buttonAction();
462
+ return action ? `zitadel-action-${action}` : void 0;
463
+ }
464
+ buttonType() {
465
+ const type = this.stringOption("type", this.type, "button");
466
+ return type === "submit" || type === "reset" ? type : "button";
467
+ }
468
+ buttonAction() {
469
+ return this.stringOption("action", this.action);
470
+ }
471
+ activate(event) {
472
+ const type = this.buttonType();
473
+ const action = this.buttonAction();
474
+ if (this.booleanOption("disabled", this.disabled) || this.booleanOption("loading", this.loading)) {
408
475
  event.preventDefault();
409
476
  event.stopImmediatePropagation();
410
477
  return;
411
478
  }
412
479
  const form = this.internals.form;
413
- if (this.type === "submit" && form) {
480
+ if (type === "submit" && form) {
414
481
  event.preventDefault();
415
482
  form.requestSubmit();
416
- } else if (this.type === "reset" && form) {
483
+ } else if (type === "reset" && form) {
417
484
  event.preventDefault();
418
485
  form.reset();
419
486
  }
420
- this.dispatchEvent(new CustomEvent("zl-submit", {
421
- bubbles: true,
422
- composed: true,
423
- detail: { action: this.action ?? null }
424
- }));
425
- };
487
+ emit(this, "zl-submit", { action: action ?? null });
488
+ }
489
+ stringOption(attribute, value, fallback) {
490
+ if (typeof value === "string" && value.length > 0) return value;
491
+ const attr = this.getAttribute(attribute);
492
+ if (attr !== null && attr.length > 0) return attr;
493
+ return fallback;
494
+ }
495
+ booleanOption(attribute, value) {
496
+ return value === true || this.hasAttribute(attribute);
497
+ }
426
498
  };
427
499
  __decorate([property({ reflect: true })], ZlButton.prototype, "hierarchy", null);
428
500
  __decorate([property({ reflect: true })], ZlButton.prototype, "size", null);
@@ -438,6 +510,8 @@ __decorate([property({
438
510
  reflect: true
439
511
  })], ZlButton.prototype, "block", null);
440
512
  __decorate([property()], ZlButton.prototype, "label", null);
513
+ __decorate([property({ attribute: "data-testid" })], ZlButton.prototype, "testId", null);
514
+ __decorate([property({ attribute: "data-state" })], ZlButton.prototype, "forcedState", null);
441
515
  ZlButton = __decorate([customElement("zl-button")], ZlButton);
442
516
  const zlButtonManifest = {
443
517
  tag: "zl-button",
@@ -453,7 +527,8 @@ const zlButtonManifest = {
453
527
  "loading",
454
528
  "disabled",
455
529
  "block",
456
- "label"
530
+ "label",
531
+ "data-testid"
457
532
  ],
458
533
  parts: ["root", "spinner"],
459
534
  slots: [
@@ -483,20 +558,32 @@ let ZlCard = class ZlCard extends LitElement {
483
558
  render() {
484
559
  const hasHeader = this.lightDomSlotFilled("header");
485
560
  const hasFooter = this.lightDomSlotFilled("footer");
561
+ const cardClass = this.compact ? "zr-card zr-card--compact" : "zr-card";
562
+ const headerClass = hasHeader ? "zr-card__header" : "zr-card__header zr-card__region--empty";
563
+ const footerClass = hasFooter ? "zr-card__footer" : "zr-card__footer zr-card__region--empty";
486
564
  return html`
487
- <section class=${this.compact ? "zr-card zr-card--compact" : "zr-card"} part="card">
488
- <header class=${hasHeader ? "zr-card__header" : "zr-card__header zr-card__region--empty"} part="header">
489
- <slot name="header"></slot>
565
+ <section class=${cardClass} part="card">
566
+ <header class=${headerClass} part="header">
567
+ <slot name="header" @slotchange=${this.onSlotChange}></slot>
490
568
  </header>
491
569
  <div class="zr-card__body" part="body">
492
570
  <slot></slot>
493
571
  </div>
494
- <footer class=${hasFooter ? "zr-card__footer" : "zr-card__footer zr-card__region--empty"} part="footer">
495
- <slot name="footer"></slot>
572
+ <footer class=${footerClass} part="footer">
573
+ <slot name="footer" @slotchange=${this.onSlotChange}></slot>
496
574
  </footer>
497
575
  </section>
498
576
  `;
499
577
  }
578
+ /**
579
+ * `lightDomSlotFilled` is a render-time snapshot, so re-run render whenever a
580
+ * named slot's assignment changes (e.g. a header added after first paint).
581
+ * The initial render still reads children synchronously, avoiding the
582
+ * empty-then-filled flash a slotchange-only approach would introduce.
583
+ */
584
+ onSlotChange = () => {
585
+ this.requestUpdate();
586
+ };
500
587
  /** Slotted nodes are always light-DOM children of the host in our templates. */
501
588
  lightDomSlotFilled(slot) {
502
589
  for (const child of this.children) if (child.getAttribute("slot") === slot) return true;
@@ -557,12 +644,17 @@ let ZlField = class ZlField extends LitElement {
557
644
  delegatesFocus: true
558
645
  };
559
646
  static styles = [baseHostStyles, ...surfaceStyles(text_field_host_default, text_field_default)];
560
- #_name_accessor_storage = "";
647
+ /**
648
+ * Field name — used as the key in form submission and in `zl-input` event
649
+ * detail. For form-associated custom elements the browser owns a native
650
+ * `name` property; using `@property()` would create a conflicting accessor
651
+ * that loses sync with the DOM attribute. We therefore manage it manually.
652
+ */
561
653
  get name() {
562
- return this.#_name_accessor_storage;
654
+ return this.getAttribute("name") ?? "";
563
655
  }
564
656
  set name(value) {
565
- this.#_name_accessor_storage = value;
657
+ this.setAttribute("name", value);
566
658
  }
567
659
  #_label_accessor_storage = "";
568
660
  get label() {
@@ -620,6 +712,13 @@ let ZlField = class ZlField extends LitElement {
620
712
  set success(value) {
621
713
  this.#_success_accessor_storage = value;
622
714
  }
715
+ #_testId_accessor_storage = void 0;
716
+ get testId() {
717
+ return this.#_testId_accessor_storage;
718
+ }
719
+ set testId(value) {
720
+ this.#_testId_accessor_storage = value;
721
+ }
623
722
  #_forgotPasswordHref_accessor_storage = void 0;
624
723
  get forgotPasswordHref() {
625
724
  return this.#_forgotPasswordHref_accessor_storage;
@@ -676,6 +775,13 @@ let ZlField = class ZlField extends LitElement {
676
775
  set hasSuffixSlot(value) {
677
776
  this.#_hasSuffixSlot_accessor_storage = value;
678
777
  }
778
+ #_inputEl_accessor_storage = null;
779
+ get inputEl() {
780
+ return this.#_inputEl_accessor_storage;
781
+ }
782
+ set inputEl(value) {
783
+ this.#_inputEl_accessor_storage = value;
784
+ }
679
785
  inputId = nextUid("zl-field");
680
786
  internals;
681
787
  constructor() {
@@ -696,7 +802,7 @@ let ZlField = class ZlField extends LitElement {
696
802
  this.value = state ?? "";
697
803
  }
698
804
  focus(options) {
699
- this.shadowRoot?.querySelector("input")?.focus(options);
805
+ this.inputEl?.focus(options);
700
806
  }
701
807
  render() {
702
808
  const labelId = `${this.inputId}-label`;
@@ -710,15 +816,18 @@ let ZlField = class ZlField extends LitElement {
710
816
  showSuccess ? successId : null,
711
817
  this.hasHelp ? helpId : null
712
818
  ].filter(Boolean).join(" ");
713
- const rootClass = [
714
- "zr-field",
715
- this.invalid || showError ? "zr-field--invalid" : "",
716
- showSuccess ? "zr-field--success" : "",
717
- this.disabled ? "zr-field--disabled" : ""
718
- ].filter(Boolean).join(" ");
819
+ const rootClass = classMap({
820
+ "zr-field": true,
821
+ "zr-field--invalid": this.invalid || showError,
822
+ "zr-field--success": showSuccess,
823
+ "zr-field--disabled": this.disabled
824
+ });
719
825
  const showDefaultTrailing = this.trailingIcon && !this.hasSuffixSlot && !this.disabled;
720
826
  const trailing = showDefaultTrailing ? this.renderTrailingIcon() : null;
721
- const wrapClass = ["zr-field__wrap", showDefaultTrailing ? "zr-field__wrap--trailing" : ""].filter(Boolean).join(" ");
827
+ const wrapClass = classMap({
828
+ "zr-field__wrap": true,
829
+ "zr-field__wrap--trailing": showDefaultTrailing
830
+ });
722
831
  return html`
723
832
  <div class=${rootClass} part="root">
724
833
  ${this.renderLabelRow(labelId)}
@@ -728,12 +837,13 @@ let ZlField = class ZlField extends LitElement {
728
837
  class="zr-field__input"
729
838
  part="input"
730
839
  id=${this.inputId}
840
+ data-testid=${ifDefined(this.nativeInputTestId())}
731
841
  name=${this.name}
732
842
  type=${this.type}
733
- .value=${this.value}
843
+ .value=${live(this.value)}
734
844
  placeholder=${this.placeholder}
735
- autocomplete=${this.autocomplete ?? ""}
736
- pattern=${this.pattern ?? ""}
845
+ autocomplete=${ifDefined(this.autocomplete)}
846
+ pattern=${ifDefined(this.pattern)}
737
847
  ?required=${this.required}
738
848
  ?disabled=${this.disabled}
739
849
  aria-invalid=${this.invalid || showError ? "true" : "false"}
@@ -829,36 +939,31 @@ let ZlField = class ZlField extends LitElement {
829
939
  };
830
940
  handleClear = () => {
831
941
  this.value = "";
832
- this.dispatchEvent(new CustomEvent("zl-input", {
833
- bubbles: true,
834
- composed: true,
835
- detail: {
836
- name: this.name,
837
- value: this.value
838
- }
839
- }));
942
+ emit(this, "zl-input", {
943
+ name: this.name,
944
+ value: this.value
945
+ });
840
946
  this.syncFormState();
841
- this.shadowRoot?.querySelector(".zr-field__input")?.focus();
947
+ this.dispatchNativeInput();
948
+ this.inputEl?.focus();
842
949
  };
843
950
  handleInput = (event) => {
951
+ event.stopPropagation();
844
952
  const input = event.target;
845
953
  this.value = input.value;
846
- this.dispatchEvent(new CustomEvent("zl-input", {
847
- bubbles: true,
848
- composed: true,
849
- detail: {
850
- name: this.name,
851
- value: this.value
852
- }
853
- }));
954
+ this.syncFormState();
955
+ emit(this, "zl-input", {
956
+ name: this.name,
957
+ value: this.value
958
+ });
959
+ this.dispatchNativeInput(event);
854
960
  };
855
961
  handleChange = (event) => {
962
+ event.stopPropagation();
856
963
  const input = event.target;
857
964
  this.value = input.value;
858
- this.dispatchEvent(new Event("change", {
859
- bubbles: true,
860
- composed: true
861
- }));
965
+ this.syncFormState();
966
+ this.dispatchNativeChange();
862
967
  };
863
968
  handleKeyDown = (event) => {
864
969
  if (event.key === "Enter" && !event.isComposing && !event.shiftKey && !event.altKey && !event.metaKey && !event.ctrlKey) {
@@ -869,8 +974,34 @@ let ZlField = class ZlField extends LitElement {
869
974
  }
870
975
  }
871
976
  };
977
+ nativeInputTestId() {
978
+ if (this.name) return `zitadel-input-${this.name}`;
979
+ if (this.testId) return `${this.testId}-input`;
980
+ }
981
+ dispatchNativeInput(source) {
982
+ if (typeof InputEvent === "function") {
983
+ const input = source instanceof InputEvent ? source : void 0;
984
+ this.dispatchEvent(new InputEvent("input", {
985
+ bubbles: true,
986
+ composed: true,
987
+ data: input?.data ?? null,
988
+ inputType: input?.inputType ?? "",
989
+ isComposing: input?.isComposing ?? false
990
+ }));
991
+ return;
992
+ }
993
+ this.dispatchEvent(new Event("input", {
994
+ bubbles: true,
995
+ composed: true
996
+ }));
997
+ }
998
+ dispatchNativeChange() {
999
+ this.dispatchEvent(new Event("change", {
1000
+ bubbles: true,
1001
+ composed: true
1002
+ }));
1003
+ }
872
1004
  };
873
- __decorate([property()], ZlField.prototype, "name", null);
874
1005
  __decorate([property()], ZlField.prototype, "label", null);
875
1006
  __decorate([property()], ZlField.prototype, "type", null);
876
1007
  __decorate([property()], ZlField.prototype, "value", null);
@@ -879,6 +1010,7 @@ __decorate([property()], ZlField.prototype, "autocomplete", null);
879
1010
  __decorate([property()], ZlField.prototype, "pattern", null);
880
1011
  __decorate([property()], ZlField.prototype, "error", null);
881
1012
  __decorate([property()], ZlField.prototype, "success", null);
1013
+ __decorate([property({ attribute: "data-testid" })], ZlField.prototype, "testId", null);
882
1014
  __decorate([property({ attribute: "forgot-password-href" })], ZlField.prototype, "forgotPasswordHref", null);
883
1015
  __decorate([property({ attribute: "forgot-password-label" })], ZlField.prototype, "forgotPasswordLabel", null);
884
1016
  __decorate([property({
@@ -896,6 +1028,7 @@ __decorate([property({
896
1028
  })], ZlField.prototype, "invalid", null);
897
1029
  __decorate([state()], ZlField.prototype, "hasHelp", null);
898
1030
  __decorate([state()], ZlField.prototype, "hasSuffixSlot", null);
1031
+ __decorate([query(".zr-field__input")], ZlField.prototype, "inputEl", null);
899
1032
  ZlField = __decorate([customElement("zl-field")], ZlField);
900
1033
  const zlFieldManifest = {
901
1034
  tag: "zl-field",
@@ -908,6 +1041,7 @@ const zlFieldManifest = {
908
1041
  "placeholder",
909
1042
  "autocomplete",
910
1043
  "pattern",
1044
+ "data-testid",
911
1045
  "required",
912
1046
  "disabled",
913
1047
  "invalid",
@@ -950,20 +1084,30 @@ let ZlPageShell = class ZlPageShell extends LitElement {
950
1084
  render() {
951
1085
  const hasHeader = this.lightDomSlotFilled("header");
952
1086
  const hasFooter = this.lightDomSlotFilled("footer");
1087
+ const headerClass = hasHeader ? "zr-page-shell__header" : "zr-page-shell__header zr-page-shell__region--empty";
1088
+ const footerClass = hasFooter ? "zr-page-shell__footer" : "zr-page-shell__footer zr-page-shell__region--empty";
953
1089
  return html`
954
1090
  <div class="zr-page-shell" part="shell">
955
- <header class=${hasHeader ? "zr-page-shell__header" : "zr-page-shell__header zr-page-shell__region--empty"} part="header">
956
- <slot name="header"></slot>
1091
+ <header class=${headerClass} part="header">
1092
+ <slot name="header" @slotchange=${this.onSlotChange}></slot>
957
1093
  </header>
958
1094
  <main class="zr-page-shell__main" part="main">
959
1095
  <slot></slot>
960
1096
  </main>
961
- <footer class=${hasFooter ? "zr-page-shell__footer" : "zr-page-shell__footer zr-page-shell__region--empty"} part="footer">
962
- <slot name="footer"></slot>
1097
+ <footer class=${footerClass} part="footer">
1098
+ <slot name="footer" @slotchange=${this.onSlotChange}></slot>
963
1099
  </footer>
964
1100
  </div>
965
1101
  `;
966
1102
  }
1103
+ /**
1104
+ * Re-render when a named slot's assignment changes so a footer/header added
1105
+ * after first paint updates the empty-region class. The initial render reads
1106
+ * children synchronously (no empty-then-filled flash).
1107
+ */
1108
+ onSlotChange = () => {
1109
+ this.requestUpdate();
1110
+ };
967
1111
  lightDomSlotFilled(slot) {
968
1112
  for (const child of this.children) if (child.getAttribute("slot") === slot) return true;
969
1113
  return false;
@@ -1041,6 +1185,13 @@ let ZlPasskey = class ZlPasskey extends LitElement {
1041
1185
  set options(value) {
1042
1186
  this.#_options_accessor_storage = value;
1043
1187
  }
1188
+ #_method_accessor_storage = "passkey";
1189
+ get method() {
1190
+ return this.#_method_accessor_storage;
1191
+ }
1192
+ set method(value) {
1193
+ this.#_method_accessor_storage = value;
1194
+ }
1044
1195
  #_manual_accessor_storage = false;
1045
1196
  get manual() {
1046
1197
  return this.#_manual_accessor_storage;
@@ -1185,7 +1336,7 @@ let ZlPasskey = class ZlPasskey extends LitElement {
1185
1336
  emitResult(proof) {
1186
1337
  const detail = {
1187
1338
  challenge_id: this.challengeId,
1188
- method: "passkey",
1339
+ method: this.method,
1189
1340
  proof
1190
1341
  };
1191
1342
  this.dispatchEvent(new CustomEvent("zl-passkey-result", {
@@ -1229,6 +1380,7 @@ __decorate([property({
1229
1380
  }
1230
1381
  }
1231
1382
  })], ZlPasskey.prototype, "options", null);
1383
+ __decorate([property({ type: String })], ZlPasskey.prototype, "method", null);
1232
1384
  __decorate([property({ type: Boolean })], ZlPasskey.prototype, "manual", null);
1233
1385
  ZlPasskey = __decorate([customElement("zl-passkey")], ZlPasskey);
1234
1386
  const zlPasskeyManifest = {
@@ -1236,6 +1388,7 @@ const zlPasskeyManifest = {
1236
1388
  consumes: {},
1237
1389
  attrs: [
1238
1390
  "ceremony",
1391
+ "method",
1239
1392
  "challenge-id",
1240
1393
  "options",
1241
1394
  "manual"
@@ -1275,11 +1428,11 @@ let ZlPill = class ZlPill extends LitElement {
1275
1428
  set ariaLabel(value) {
1276
1429
  this.#_ariaLabel_accessor_storage = value;
1277
1430
  }
1278
- surfaceClasses() {
1279
- return ["zr-pill", this.tone !== "neutral" ? `zr-pill--${this.tone}` : ""].filter(Boolean).join(" ");
1280
- }
1281
1431
  render() {
1282
- const classes = this.surfaceClasses();
1432
+ const classes = classMap({
1433
+ "zr-pill": true,
1434
+ [`zr-pill--${this.tone}`]: this.tone !== "neutral"
1435
+ });
1283
1436
  if (this.href) return html`<a
1284
1437
  class=${classes}
1285
1438
  part="pill"
@@ -1302,10 +1455,10 @@ const zlPillManifest = {
1302
1455
  "aria-label"
1303
1456
  ],
1304
1457
  parts: ["pill"],
1305
- slots: [],
1458
+ slots: [""],
1306
1459
  events: []
1307
1460
  };
1308
1461
  //#endregion
1309
- export { __decorate as _, ZlPageShell as a, t as b, zlFieldManifest as c, ZlButton as d, zlButtonManifest as f, zlIconManifest as g, ZlIcon as h, zlPasskeyManifest as i, ZlCard as l, zlAlertManifest as m, zlPillManifest as n, zlPageShellManifest as o, ZlAlert as p, ZlPasskey as r, ZlField as s, ZlPill as t, zlCardManifest as u, focusVisibleStyles as v, baseHostStyles as y };
1462
+ export { __decorate as _, ZlPageShell as a, t as b, zlFieldManifest as c, ZlButton as d, zlButtonManifest as f, zlIconManifest as g, ZlIcon as h, zlPasskeyManifest as i, ZlCard as l, zlAlertManifest as m, zlPillManifest as n, zlPageShellManifest as o, ZlAlert as p, ZlPasskey as r, ZlField as s, ZlPill as t, zlCardManifest as u, focusVisibleStyles as v, emit as x, baseHostStyles as y };
1310
1463
 
1311
- //# sourceMappingURL=atoms-CmOTltTH.mjs.map
1464
+ //# sourceMappingURL=atoms-BaayzEsr.mjs.map