@authhero/widget 0.4.0 → 0.5.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 (39) hide show
  1. package/README.md +21 -1
  2. package/dist/authhero-widget/authhero-widget.esm.js +1 -1
  3. package/dist/authhero-widget/index.esm.js +1 -1
  4. package/dist/authhero-widget/p-7989dabd.entry.js +1 -0
  5. package/dist/authhero-widget/{p-Doiemx6o.js → p-bMtPc5Dm.js} +1 -1
  6. package/dist/authhero-widget/p-fa60ab6e.entry.js +1 -0
  7. package/dist/cjs/authhero-node.cjs.entry.js +97 -9
  8. package/dist/cjs/authhero-widget.cjs.entry.js +82 -18
  9. package/dist/cjs/authhero-widget.cjs.js +2 -2
  10. package/dist/cjs/{index-D0xitTOL.js → index-Db4bZu99.js} +28 -3
  11. package/dist/cjs/index.cjs.js +1 -1
  12. package/dist/cjs/loader.cjs.js +2 -2
  13. package/dist/collection/components/authhero-node/authhero-node.css +237 -94
  14. package/dist/collection/components/authhero-node/authhero-node.js +101 -8
  15. package/dist/collection/components/authhero-widget/authhero-widget.css +128 -70
  16. package/dist/collection/components/authhero-widget/authhero-widget.js +30 -5
  17. package/dist/collection/utils/branding.js +52 -13
  18. package/dist/components/authhero-node.js +1 -1
  19. package/dist/components/authhero-widget.js +1 -1
  20. package/dist/components/index.js +1 -1
  21. package/dist/components/p-pupmqprs.js +1 -0
  22. package/dist/components/p-uIy4ySa4.js +1 -0
  23. package/dist/esm/authhero-node.entry.js +97 -9
  24. package/dist/esm/authhero-widget.entry.js +82 -18
  25. package/dist/esm/authhero-widget.js +3 -3
  26. package/dist/esm/{index-Doiemx6o.js → index-bMtPc5Dm.js} +28 -3
  27. package/dist/esm/index.js +1 -1
  28. package/dist/esm/loader.js +3 -3
  29. package/dist/types/components/authhero-node/authhero-node.d.ts +14 -1
  30. package/dist/types/components/authhero-widget/authhero-widget.d.ts +8 -0
  31. package/hydrate/index.js +207 -29
  32. package/hydrate/index.mjs +207 -29
  33. package/package.json +10 -4
  34. package/dist/authhero-widget/p-2e93c814.entry.js +0 -1
  35. package/dist/authhero-widget/p-539fc666.entry.js +0 -1
  36. package/dist/collection/server/index.js +0 -453
  37. package/dist/components/p-086EZrPM.js +0 -1
  38. package/dist/components/p-DS6y_iDJ.js +0 -1
  39. package/dist/types/server/index.d.ts +0 -85
package/hydrate/index.mjs CHANGED
@@ -468,6 +468,10 @@ var require_brace_expansion = __commonJS({
468
468
  }
469
469
  }
470
470
  });
471
+
472
+ // src/utils/constants.ts
473
+ var SVG_NS = "http://www.w3.org/2000/svg";
474
+ var HTML_NS = "http://www.w3.org/1999/xhtml";
471
475
  var PrimitiveType = /* @__PURE__ */ ((PrimitiveType2) => {
472
476
  PrimitiveType2["Undefined"] = "undefined";
473
477
  PrimitiveType2["Null"] = "null";
@@ -3291,7 +3295,7 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
3291
3295
  }
3292
3296
  } else {
3293
3297
  const isComplex = isComplexType(newValue);
3294
- if ((isProp || isComplex && newValue !== null) && true) {
3298
+ if ((isProp || isComplex && newValue !== null) && !isSvg) {
3295
3299
  try {
3296
3300
  if (!elm.tagName.includes("-")) {
3297
3301
  const n = newValue == null ? "" : newValue;
@@ -3417,14 +3421,21 @@ var createElm = (oldParentVNode, newParentVNode, childIndex) => {
3417
3421
  updateElement(null, newVNode2, isSvgMode);
3418
3422
  }
3419
3423
  } else {
3424
+ if (!isSvgMode) {
3425
+ isSvgMode = newVNode2.$tag$ === "svg";
3426
+ }
3420
3427
  if (!win.document) {
3421
3428
  throw new Error(
3422
3429
  "You are trying to render a Stencil component in an environment that doesn't support the DOM. Make sure to populate the [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window/window) object before rendering a component."
3423
3430
  );
3424
3431
  }
3425
- elm = newVNode2.$elm$ = win.document.createElement(
3432
+ elm = newVNode2.$elm$ = win.document.createElementNS(
3433
+ isSvgMode ? SVG_NS : HTML_NS,
3426
3434
  !useNativeShadowDom && BUILD.slotRelocation && newVNode2.$flags$ & 2 /* isSlotFallback */ ? "slot-fb" : newVNode2.$tag$
3427
- );
3435
+ ) ;
3436
+ if (isSvgMode && newVNode2.$tag$ === "foreignObject") {
3437
+ isSvgMode = false;
3438
+ }
3428
3439
  {
3429
3440
  updateElement(null, newVNode2, isSvgMode);
3430
3441
  }
@@ -3440,6 +3451,13 @@ var createElm = (oldParentVNode, newParentVNode, childIndex) => {
3440
3451
  }
3441
3452
  }
3442
3453
  }
3454
+ {
3455
+ if (newVNode2.$tag$ === "svg") {
3456
+ isSvgMode = false;
3457
+ } else if (elm.tagName === "foreignObject") {
3458
+ isSvgMode = true;
3459
+ }
3460
+ }
3443
3461
  }
3444
3462
  elm["s-hn"] = hostTagName;
3445
3463
  {
@@ -3659,9 +3677,13 @@ var patch = (oldVNode, newVNode2, isInitialRender = false) => {
3659
3677
  const elm = newVNode2.$elm$ = oldVNode.$elm$;
3660
3678
  const oldChildren = oldVNode.$children$;
3661
3679
  const newChildren = newVNode2.$children$;
3680
+ const tag = newVNode2.$tag$;
3662
3681
  const text = newVNode2.$text$;
3663
3682
  let defaultHolder;
3664
3683
  if (text === null) {
3684
+ {
3685
+ isSvgMode = tag === "svg" ? true : tag === "foreignObject" ? false : isSvgMode;
3686
+ }
3665
3687
  {
3666
3688
  updateElement(oldVNode, newVNode2, isSvgMode, isInitialRender);
3667
3689
  }
@@ -3680,6 +3702,9 @@ var patch = (oldVNode, newVNode2, isInitialRender = false) => {
3680
3702
  } else if (isInitialRender && BUILD.updatable && oldChildren !== null && newChildren === null) {
3681
3703
  newVNode2.$children$ = oldChildren;
3682
3704
  }
3705
+ if (isSvgMode && tag === "svg") {
3706
+ isSvgMode = false;
3707
+ }
3683
3708
  } else if ((defaultHolder = elm["s-cr"])) {
3684
3709
  defaultHolder.parentNode.textContent = text;
3685
3710
  } else if (oldVNode.$text$ !== text) {
@@ -5007,7 +5032,7 @@ var setScopedSSR = (opts) => {
5007
5032
  var needsScopedSSR = () => scopedSSR;
5008
5033
  var scopedSSR = false;
5009
5034
 
5010
- const authheroNodeCss = () => `:host{display:block}.input-wrapper{display:flex;flex-direction:column;gap:var(--ah-space-1, 0.25rem)}.input-label{font-size:var(--ah-font-size-sm, 0.875rem);font-weight:var(--ah-font-weight-medium, 500);color:var(--ah-color-text-label, #374151);line-height:var(--ah-line-height-normal, 1.5)}.required{color:var(--ah-color-error, #dc2626);margin-left:var(--ah-space-1, 0.25rem)}.input-field{padding:var(--ah-input-padding-y, 0.75rem) var(--ah-input-padding-x, 1rem);font-size:var(--ah-font-size-base, 1rem);font-family:inherit;color:var(--ah-color-text, #1f2937);background-color:var(--ah-color-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #d1d5db);border-radius:var(--ah-input-radius, 6px);outline:none;transition:border-color var(--ah-transition-base, 200ms ease), box-shadow var(--ah-transition-base, 200ms ease)}.input-field::placeholder{color:var(--ah-color-text-muted, #9ca3af)}.input-field:focus{border-color:var(--ah-color-primary, #0066cc);box-shadow:0 0 0 3px var(--ah-color-primary-focus-ring, rgba(0, 102, 204, 0.1))}.input-field.has-error{border-color:var(--ah-color-error, #dc2626)}.input-field.has-error:focus{box-shadow:0 0 0 3px rgba(220, 38, 38, 0.1)}.input-field:disabled{background-color:var(--ah-color-bg-disabled, #f3f4f6);cursor:not-allowed;opacity:0.7}.error-text{font-size:var(--ah-font-size-xs, 0.75rem);color:var(--ah-color-error, #dc2626);margin-top:var(--ah-space-1, 0.25rem)}.helper-text{font-size:var(--ah-font-size-xs, 0.75rem);color:var(--ah-color-text-muted, #6b7280);margin-top:var(--ah-space-1, 0.25rem)}.checkbox-wrapper{display:flex;align-items:flex-start;gap:var(--ah-space-2, 0.5rem);cursor:pointer}.checkbox-wrapper input[type='checkbox']{width:1rem;height:1rem;margin-top:0.125rem;accent-color:var(--ah-color-primary, #0066cc);cursor:pointer}.checkbox-label{font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-label, #374151);line-height:var(--ah-line-height-normal, 1.5)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--ah-space-2, 0.5rem);width:100%;padding:var(--ah-btn-padding-y, 0.875rem) var(--ah-btn-padding-x, 1.5rem);font-size:var(--ah-font-size-base, 1rem);font-weight:var(--ah-btn-font-weight, 500);font-family:inherit;line-height:var(--ah-line-height-tight, 1.25);text-align:center;text-decoration:none;border:none;border-radius:var(--ah-btn-radius, 8px);cursor:pointer;transition:background-color var(--ah-transition-base, 200ms ease), transform var(--ah-transition-fast, 150ms ease), box-shadow var(--ah-transition-base, 200ms ease)}.btn:disabled{opacity:0.6;cursor:not-allowed}.btn:not(:disabled):active{transform:scale(0.98)}.btn:focus-visible{outline:2px solid var(--ah-color-primary, #0066cc);outline-offset:2px}.btn-primary{background-color:var(--ah-color-primary, #0066cc);color:var(--ah-color-text-on-primary, #ffffff)}.btn-primary:not(:disabled):hover{background-color:var(--ah-color-primary-hover, #0052a3)}.btn-secondary{background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text, #374151);border:1px solid var(--ah-color-border-muted, #e5e7eb)}.btn-secondary:not(:disabled):hover{background-color:var(--ah-color-bg-muted, #f9fafb);border-color:var(--ah-color-border, #d1d5db)}.text-title{font-size:var(--ah-font-size-xl, 1.25rem);font-weight:var(--ah-font-weight-semibold, 600);color:var(--ah-color-text, #1f2937);margin:var(--ah-space-2, 0.5rem) 0;line-height:var(--ah-line-height-tight, 1.25)}.text-title.text-success{color:var(--ah-color-success, #16a34a)}.text-description{font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #6b7280);margin:var(--ah-space-1, 0.25rem) 0;line-height:var(--ah-line-height-normal, 1.5)}.image{display:block;max-width:100%;height:auto;border-radius:var(--ah-radius-lg, 8px)}.image-centered{margin:0 auto var(--ah-space-4, 1rem);width:var(--ah-logo-size, 48px);height:var(--ah-logo-size, 48px);object-fit:contain}.link{color:var(--ah-color-primary, #0066cc);text-decoration:none;font-size:var(--ah-font-size-sm, 0.875rem);transition:color var(--ah-transition-fast, 150ms ease)}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-primary, #0066cc);outline-offset:2px}.node-error{padding:var(--ah-space-3, 0.75rem) var(--ah-space-4, 1rem);background-color:var(--ah-color-error-bg, #fee2e2);color:var(--ah-color-error, #dc2626);border:1px solid var(--ah-color-error-border, #fecaca);border-radius:var(--ah-radius-md, 6px);font-size:var(--ah-font-size-sm, 0.875rem)}.node-success{padding:var(--ah-space-3, 0.75rem) var(--ah-space-4, 1rem);background-color:var(--ah-color-success-bg, #dcfce7);color:var(--ah-color-success, #16a34a);border:1px solid var(--ah-color-success-border, #bbf7d0);border-radius:var(--ah-radius-md, 6px);font-size:var(--ah-font-size-sm, 0.875rem)}.divider{display:flex;align-items:center;text-align:center;margin:var(--ah-space-4, 1rem) 0}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #e5e7eb)}.divider-text{padding:0 var(--ah-space-4, 1rem);font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #9ca3af);text-transform:uppercase;letter-spacing:0.05em}`;
5035
+ const authheroNodeCss = () => `:host{display:block}.input-wrapper{display:flex;flex-direction:column;position:relative;margin-bottom:16px}.input-container{position:relative;width:100%}.input-label{position:absolute;left:16px;top:50%;transform:translateY(-50%);font-size:16px;font-weight:var(--ah-font-weight-label, 400);color:var(--ah-color-text-muted, #65676e);pointer-events:none;transition:all 0.15s ease-out;background-color:transparent;padding:0;z-index:1}.input-label.floating,.input-field:focus+.input-label,.input-field:not(:placeholder-shown)+.input-label{top:-8px;transform:translateY(0);font-size:12px;background-color:var(--ah-color-bg, #ffffff);padding:0 4px;left:12px;color:var(--ah-color-text-muted, #65676e)}.input-field:focus+.input-label{color:var(--ah-color-primary, #635dff)}.required{color:var(--ah-color-error, #d03c38);margin-left:2px}.input-field{width:100%;padding:16px;font-size:16px;font-family:inherit;color:var(--ah-color-text, #1e212a);background-color:var(--ah-color-input-bg, #ffffff);border:1px solid var(--ah-color-border, #c9cace);border-radius:var(--ah-input-radius, 3px);outline:none;transition:border-color 0.15s ease-out, box-shadow 0.15s ease-out;box-sizing:border-box}.input-field::placeholder{color:transparent}.input-field:hover{border-color:var(--ah-color-border-hover, #65676e)}.input-field:focus{border-color:var(--ah-color-primary, #635dff);box-shadow:inset 0 0 0 1px var(--ah-color-primary, #635dff)}.input-field.has-error{border-color:var(--ah-color-error, #d03c38)}.input-field.has-error:focus{box-shadow:inset 0 0 0 1px var(--ah-color-error, #d03c38)}.input-field:disabled{background-color:var(--ah-color-bg-disabled, #f5f5f5);border-color:var(--ah-color-border-disabled, #e0e1e3);cursor:not-allowed;opacity:0.7}.password-container{position:relative;display:flex;align-items:center}.password-container .input-field{padding-right:48px}.password-toggle{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;color:var(--ah-color-text-muted, #65676e);transition:color 0.15s ease}.password-toggle:hover{color:var(--ah-color-text, #1e212a)}.password-toggle svg{width:20px;height:20px}.error-text{font-size:12px;color:var(--ah-color-error, #d03c38);margin-top:4px;line-height:1.4}.helper-text{font-size:12px;color:var(--ah-color-text-muted, #65676e);margin-top:4px;line-height:1.4}.field-link{display:block;text-align:left;margin-top:8px;margin-bottom:16px}.field-link a{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;font-weight:var(--ah-font-weight-link, 400)}.field-link a:hover{text-decoration:underline}.checkbox-wrapper{display:flex;align-items:flex-start;gap:10px;cursor:pointer;margin-bottom:16px}.checkbox-wrapper input[type='checkbox']{width:18px;height:18px;margin:0;accent-color:var(--ah-color-primary, #635dff);cursor:pointer;flex-shrink:0}.checkbox-label{font-size:14px;color:var(--ah-color-text, #1e212a);line-height:1.5}.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:14px 20px;font-size:16px;font-weight:var(--ah-font-weight-btn, 400);font-family:inherit;line-height:1.25;text-align:center;text-decoration:none;border:none;border-radius:var(--ah-btn-radius, 3px);cursor:pointer;transition:background-color 0.15s ease, border-color 0.15s ease, transform 0.1s ease;box-sizing:border-box}.btn:disabled{opacity:0.6;cursor:not-allowed}.btn:not(:disabled):active{transform:scale(0.98)}.btn:focus-visible{outline:2px solid var(--ah-color-primary, #635dff);outline-offset:2px}.btn-primary{background-color:var(--ah-color-primary, #635dff);color:var(--ah-color-text-on-primary, #ffffff);margin-top:8px}.btn-primary:not(:disabled):hover{background-color:var(--ah-color-primary-hover);filter:brightness(0.9)}.btn-secondary{background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text, #1e212a);border:1px solid var(--ah-color-border, #c9cace)}.btn-secondary:not(:disabled):hover{background-color:var(--ah-color-bg-hover, #f5f5f5);border-color:var(--ah-color-border-hover, #65676e)}.btn-link{background:none;border:none;color:var(--ah-color-link, #635dff);padding:8px 0;font-weight:var(--ah-font-weight-link, 400);text-decoration:none}.btn-link:hover{text-decoration:underline}.btn-social{display:flex;align-items:center;justify-content:center;gap:12px}.social-icon{width:20px;height:20px;flex-shrink:0}.btn-icon{width:20px;height:20px;flex-shrink:0}.btn-icon img{width:100%;height:100%;object-fit:contain}.text-title{font-size:20px;font-weight:400;color:var(--ah-color-text, #1e212a);margin:8px 0;line-height:1.3}.text-title.text-success{color:var(--ah-color-success, #13a769)}.text-description{font-size:14px;color:var(--ah-color-text-muted, #65676e);margin:4px 0;line-height:1.5}.image{display:block;max-width:100%;height:auto;border-radius:4px}.image-centered{margin:0 auto 16px;width:52px;height:52px;object-fit:contain}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;transition:color 0.15s ease}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.node-error{padding:12px 16px;background-color:var(--ah-color-error-bg, #ffeaea);color:var(--ah-color-error, #d03c38);border-left:3px solid var(--ah-color-error, #d03c38);border-radius:0;font-size:14px;margin-bottom:16px}.node-success{padding:12px 16px;background-color:var(--ah-color-success-bg, #e6f9f1);color:var(--ah-color-success, #13a769);border-left:3px solid var(--ah-color-success, #13a769);border-radius:0;font-size:14px;margin-bottom:16px}.divider{display:flex;align-items:center;text-align:center;margin:16px 0}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #c9cace)}.divider-text{padding:0 10px;font-size:12px;font-weight:400;color:var(--ah-color-text-muted, #65676e);text-transform:uppercase;letter-spacing:0.5px}`;
5011
5036
 
5012
5037
  class AuthheroNode {
5013
5038
  constructor(hostRef) {
@@ -5028,6 +5053,10 @@ class AuthheroNode {
5028
5053
  * Whether the component is disabled.
5029
5054
  */
5030
5055
  disabled = false;
5056
+ /**
5057
+ * Whether the password field is visible.
5058
+ */
5059
+ passwordVisible = false;
5031
5060
  /**
5032
5061
  * Emitted when a field value changes.
5033
5062
  */
@@ -5053,6 +5082,9 @@ class AuthheroNode {
5053
5082
  }
5054
5083
  this.buttonClick.emit({ id: this.component.id, type, value });
5055
5084
  };
5085
+ togglePasswordVisibility = () => {
5086
+ this.passwordVisible = !this.passwordVisible;
5087
+ };
5056
5088
  /**
5057
5089
  * Get error messages from the component.
5058
5090
  */
@@ -5061,13 +5093,32 @@ class AuthheroNode {
5061
5093
  return (runtimeComp.messages?.filter((m) => m.type === "error") || []);
5062
5094
  }
5063
5095
  /**
5064
- * Render a label for a field.
5096
+ * Render a floating label for a field.
5097
+ */
5098
+ renderFloatingLabel(text, inputId, required, hasValue) {
5099
+ if (!text)
5100
+ return null;
5101
+ return (hAsync("label", { class: { "input-label": true, floating: !!hasValue }, part: "label", htmlFor: inputId }, text, required && hAsync("span", { class: "required" }, "*")));
5102
+ }
5103
+ /**
5104
+ * Render a label for a field (non-floating version for checkboxes etc).
5065
5105
  */
5066
5106
  renderLabel(text, inputId, required) {
5067
5107
  if (!text)
5068
5108
  return null;
5069
5109
  return (hAsync("label", { class: "input-label", part: "label", htmlFor: inputId }, text, required && hAsync("span", { class: "required" }, "*")));
5070
5110
  }
5111
+ /**
5112
+ * Render the eye icon for password visibility toggle.
5113
+ */
5114
+ renderPasswordToggle() {
5115
+ if (this.passwordVisible) {
5116
+ // Eye-off icon (password is visible, click to hide)
5117
+ return (hAsync("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, hAsync("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }), hAsync("line", { x1: "1", y1: "1", x2: "23", y2: "23" })));
5118
+ }
5119
+ // Eye icon (password is hidden, click to show)
5120
+ return (hAsync("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, hAsync("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }), hAsync("circle", { cx: "12", cy: "12", r: "3" })));
5121
+ }
5071
5122
  /**
5072
5123
  * Render error messages.
5073
5124
  */
@@ -5119,21 +5170,25 @@ class AuthheroNode {
5119
5170
  renderTextField(component) {
5120
5171
  const inputId = `input-${component.id}`;
5121
5172
  const errors = this.getErrors();
5122
- const { placeholder, multiline, max_length } = component.config ?? {};
5173
+ const { multiline, max_length } = component.config ?? {};
5174
+ const hasValue = !!(this.value && this.value.length > 0);
5123
5175
  if (multiline) {
5124
- return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, this.renderLabel(component.label, inputId, component.required), hAsync("textarea", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input textarea", name: component.id, placeholder: placeholder, required: component.required, disabled: this.disabled, maxLength: max_length, onInput: this.handleInput }, this.value ?? ""), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5176
+ return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, this.renderLabel(component.label, inputId, component.required), hAsync("textarea", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input textarea", name: component.id, placeholder: " ", required: component.required, disabled: this.disabled, maxLength: max_length, onInput: this.handleInput }, this.value ?? ""), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5125
5177
  }
5126
- return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, this.renderLabel(component.label, inputId, component.required), hAsync("input", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input", type: component.sensitive ? "password" : "text", name: component.id, value: this.value ?? "", placeholder: placeholder, required: component.required, disabled: this.disabled, maxLength: max_length, onInput: this.handleInput }), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5178
+ return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, hAsync("div", { class: "input-container" }, hAsync("input", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input", type: component.sensitive ? "password" : "text", name: component.id, value: this.value ?? "", placeholder: " ", required: component.required, disabled: this.disabled, maxLength: max_length, onInput: this.handleInput }), this.renderFloatingLabel(component.label, inputId, component.required, hasValue)), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5127
5179
  }
5128
5180
  renderEmailField(component) {
5129
5181
  const inputId = `input-${component.id}`;
5130
5182
  const errors = this.getErrors();
5131
- return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, this.renderLabel(component.label, inputId, component.required), hAsync("input", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input", type: "email", name: component.id, value: this.value ?? "", placeholder: component.config?.placeholder, required: component.required, disabled: this.disabled, autocomplete: "email", onInput: this.handleInput }), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5183
+ const hasValue = !!(this.value && this.value.length > 0);
5184
+ return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, hAsync("div", { class: "input-container" }, hAsync("input", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input", type: "email", name: component.id, value: this.value ?? "", placeholder: " ", required: component.required, disabled: this.disabled, autocomplete: "email", onInput: this.handleInput }), this.renderFloatingLabel(component.label, inputId, component.required, hasValue)), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5132
5185
  }
5133
5186
  renderPasswordField(component) {
5134
5187
  const inputId = `input-${component.id}`;
5135
5188
  const errors = this.getErrors();
5136
- return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, this.renderLabel(component.label, inputId, component.required), hAsync("input", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input", type: "password", name: component.id, value: this.value ?? "", placeholder: component.config?.placeholder, required: component.required, disabled: this.disabled, minLength: component.config?.min_length, autocomplete: "current-password", onInput: this.handleInput }), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint)));
5189
+ const hasValue = !!(this.value && this.value.length > 0);
5190
+ const forgotPasswordLink = component.config?.forgot_password_link;
5191
+ return (hAsync("div", { class: "input-wrapper", part: "input-wrapper" }, hAsync("div", { class: "input-container password-container" }, hAsync("input", { id: inputId, class: { "input-field": true, "has-error": errors.length > 0 }, part: "input", type: this.passwordVisible ? "text" : "password", name: component.id, value: this.value ?? "", placeholder: " ", required: component.required, disabled: this.disabled, minLength: component.config?.min_length, autocomplete: "current-password", onInput: this.handleInput }), this.renderFloatingLabel(component.label, inputId, component.required, hasValue), hAsync("button", { type: "button", class: "password-toggle", part: "password-toggle", onClick: this.togglePasswordVisibility, "aria-label": "Toggle password visibility", "aria-pressed": this.passwordVisible ? "true" : "false" }, this.renderPasswordToggle())), this.renderErrors(), errors.length === 0 && this.renderHint(component.hint), forgotPasswordLink && (hAsync("div", { class: "field-link", part: "field-link" }, hAsync("a", { href: forgotPasswordLink, class: "link", part: "link" }, "Forgot password?")))));
5137
5192
  }
5138
5193
  renderNumberField(component) {
5139
5194
  const inputId = `input-${component.id}`;
@@ -5180,7 +5235,65 @@ class AuthheroNode {
5180
5235
  }
5181
5236
  renderSocialField(component) {
5182
5237
  const providers = component.config?.providers ?? [];
5183
- return (hAsync("div", { class: "social-buttons", part: "social-buttons" }, providers.map((provider) => (hAsync("button", { type: "button", class: "btn btn-secondary btn-social", part: "button button-secondary button-social", "data-provider": provider, disabled: this.disabled, onClick: (e) => this.handleButtonClick(e, "social", provider), key: provider }, "Continue with ", provider.charAt(0).toUpperCase() + provider.slice(1))))));
5238
+ // Map provider IDs to display names
5239
+ const getProviderDisplayName = (provider) => {
5240
+ const displayNames = {
5241
+ "google-oauth2": "Google",
5242
+ facebook: "Facebook",
5243
+ twitter: "Twitter",
5244
+ github: "GitHub",
5245
+ linkedin: "LinkedIn",
5246
+ apple: "Apple",
5247
+ microsoft: "Microsoft",
5248
+ windowslive: "Microsoft",
5249
+ amazon: "Amazon",
5250
+ dropbox: "Dropbox",
5251
+ bitbucket: "Bitbucket",
5252
+ spotify: "Spotify",
5253
+ slack: "Slack",
5254
+ discord: "Discord",
5255
+ twitch: "Twitch",
5256
+ line: "LINE",
5257
+ shopify: "Shopify",
5258
+ paypal: "PayPal",
5259
+ "paypal-sandbox": "PayPal",
5260
+ box: "Box",
5261
+ salesforce: "Salesforce",
5262
+ "salesforce-sandbox": "Salesforce",
5263
+ yahoo: "Yahoo",
5264
+ auth0: "Auth0",
5265
+ };
5266
+ return (displayNames[provider.toLowerCase()] ||
5267
+ provider
5268
+ .split("-")
5269
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
5270
+ .join(" "));
5271
+ };
5272
+ // Get provider icon SVG
5273
+ const getProviderIcon = (provider) => {
5274
+ const p = provider.toLowerCase();
5275
+ if (p === "google-oauth2" || p === "google") {
5276
+ return (hAsync("svg", { class: "social-icon", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, hAsync("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z", fill: "#4285F4" }), hAsync("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }), hAsync("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }), hAsync("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" })));
5277
+ }
5278
+ if (p === "facebook") {
5279
+ return (hAsync("svg", { class: "social-icon", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, hAsync("path", { d: "M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z", fill: "#1877F2" })));
5280
+ }
5281
+ if (p === "apple") {
5282
+ return (hAsync("svg", { class: "social-icon", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, hAsync("path", { d: "M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z", fill: "#000000" })));
5283
+ }
5284
+ if (p === "github") {
5285
+ return (hAsync("svg", { class: "social-icon", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, hAsync("path", { d: "M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z", fill: "#181717" })));
5286
+ }
5287
+ if (p === "microsoft" || p === "windowslive") {
5288
+ return (hAsync("svg", { class: "social-icon", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, hAsync("path", { d: "M0 0h11.377v11.372H0V0z", fill: "#f25022" }), hAsync("path", { d: "M12.623 0H24v11.372H12.623V0z", fill: "#7fba00" }), hAsync("path", { d: "M0 12.623h11.377V24H0v-11.377z", fill: "#00a4ef" }), hAsync("path", { d: "M12.623 12.623H24V24H12.623v-11.377z", fill: "#ffb900" })));
5289
+ }
5290
+ if (p === "linkedin") {
5291
+ return (hAsync("svg", { class: "social-icon", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg" }, hAsync("path", { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z", fill: "#0A66C2" })));
5292
+ }
5293
+ // Default: no icon
5294
+ return null;
5295
+ };
5296
+ return (hAsync("div", { class: "social-buttons", part: "social-buttons" }, providers.map((provider) => (hAsync("button", { type: "button", class: "btn btn-secondary btn-social", part: "button button-secondary button-social", "data-provider": provider, disabled: this.disabled, onClick: (e) => this.handleButtonClick(e, "social", provider), key: provider }, getProviderIcon(provider), hAsync("span", null, "Continue with ", getProviderDisplayName(provider)))))));
5184
5297
  }
5185
5298
  // ===========================================================================
5186
5299
  // Main Render
@@ -5261,7 +5374,8 @@ class AuthheroNode {
5261
5374
  "$members$": {
5262
5375
  "component": [16],
5263
5376
  "value": [1],
5264
- "disabled": [4]
5377
+ "disabled": [4],
5378
+ "passwordVisible": [32]
5265
5379
  },
5266
5380
  "$listeners$": undefined,
5267
5381
  "$lazyBundleId$": "-",
@@ -5434,39 +5548,60 @@ function themeToCssVars(theme) {
5434
5548
  // Fonts
5435
5549
  if (theme.fonts) {
5436
5550
  const f = theme.fonts;
5551
+ // reference_text_size is the base font size in pixels (default 16px)
5552
+ const baseSize = f.reference_text_size || 16;
5437
5553
  if (f.font_url) {
5438
5554
  vars['--ah-font-url'] = f.font_url;
5439
5555
  }
5440
5556
  if (f.reference_text_size) {
5441
5557
  vars['--ah-font-size-base'] = `${f.reference_text_size}px`;
5442
5558
  }
5559
+ // Title, subtitle, etc. sizes are percentages of the base size
5443
5560
  if (f.title?.size) {
5444
- vars['--ah-font-size-title'] = `${f.title.size}px`;
5561
+ const titlePx = Math.round((f.title.size / 100) * baseSize);
5562
+ vars['--ah-font-size-title'] = `${titlePx}px`;
5445
5563
  }
5446
5564
  if (f.subtitle?.size) {
5447
- vars['--ah-font-size-subtitle'] = `${f.subtitle.size}px`;
5565
+ const subtitlePx = Math.round((f.subtitle.size / 100) * baseSize);
5566
+ vars['--ah-font-size-subtitle'] = `${subtitlePx}px`;
5448
5567
  }
5449
5568
  if (f.body_text?.size) {
5450
- vars['--ah-font-size-body'] = `${f.body_text.size}px`;
5569
+ const bodyPx = Math.round((f.body_text.size / 100) * baseSize);
5570
+ vars['--ah-font-size-body'] = `${bodyPx}px`;
5451
5571
  }
5452
5572
  if (f.input_labels?.size) {
5453
- vars['--ah-font-size-label'] = `${f.input_labels.size}px`;
5573
+ const labelPx = Math.round((f.input_labels.size / 100) * baseSize);
5574
+ vars['--ah-font-size-label'] = `${labelPx}px`;
5454
5575
  }
5455
5576
  if (f.buttons_text?.size) {
5456
- vars['--ah-font-size-btn'] = `${f.buttons_text.size}px`;
5577
+ const btnPx = Math.round((f.buttons_text.size / 100) * baseSize);
5578
+ vars['--ah-font-size-btn'] = `${btnPx}px`;
5457
5579
  }
5458
5580
  if (f.links?.size) {
5459
- vars['--ah-font-size-link'] = `${f.links.size}px`;
5581
+ const linkPx = Math.round((f.links.size / 100) * baseSize);
5582
+ vars['--ah-font-size-link'] = `${linkPx}px`;
5460
5583
  }
5461
5584
  if (f.links_style === 'underlined') {
5462
5585
  vars['--ah-link-decoration'] = 'underline';
5463
5586
  }
5464
- // Font weights
5465
- if (f.title?.bold) {
5466
- vars['--ah-font-weight-title'] = '700';
5587
+ // Font weights - bold option sets font-weight to 700
5588
+ if (f.title?.bold !== undefined) {
5589
+ vars['--ah-font-weight-title'] = f.title.bold ? '700' : '400';
5590
+ }
5591
+ if (f.subtitle?.bold !== undefined) {
5592
+ vars['--ah-font-weight-subtitle'] = f.subtitle.bold ? '700' : '400';
5593
+ }
5594
+ if (f.body_text?.bold !== undefined) {
5595
+ vars['--ah-font-weight-body'] = f.body_text.bold ? '700' : '400';
5467
5596
  }
5468
- if (f.buttons_text?.bold) {
5469
- vars['--ah-font-weight-btn'] = '600';
5597
+ if (f.input_labels?.bold !== undefined) {
5598
+ vars['--ah-font-weight-label'] = f.input_labels.bold ? '700' : '400';
5599
+ }
5600
+ if (f.buttons_text?.bold !== undefined) {
5601
+ vars['--ah-font-weight-btn'] = f.buttons_text.bold ? '600' : '400';
5602
+ }
5603
+ if (f.links?.bold !== undefined) {
5604
+ vars['--ah-font-weight-link'] = f.links.bold ? '700' : '400';
5470
5605
  }
5471
5606
  }
5472
5607
  // Widget settings
@@ -5483,9 +5618,27 @@ function themeToCssVars(theme) {
5483
5618
  center: 'center',
5484
5619
  left: 'flex-start',
5485
5620
  right: 'flex-end',
5486
- none: 'none',
5487
5621
  };
5488
- vars['--ah-logo-align'] = positionMap[w.logo_position] ?? 'center';
5622
+ if (w.logo_position === 'none') {
5623
+ vars['--ah-logo-display'] = 'none';
5624
+ }
5625
+ else {
5626
+ vars['--ah-logo-align'] = positionMap[w.logo_position] ?? 'center';
5627
+ }
5628
+ }
5629
+ if (w.social_buttons_layout) {
5630
+ // 'top' means social buttons above fields, 'bottom' means below
5631
+ // Divider is always order 1 (middle)
5632
+ if (w.social_buttons_layout === 'top') {
5633
+ vars['--ah-social-order'] = '0';
5634
+ vars['--ah-divider-order'] = '1';
5635
+ vars['--ah-fields-order'] = '2';
5636
+ }
5637
+ else {
5638
+ vars['--ah-social-order'] = '2';
5639
+ vars['--ah-divider-order'] = '1';
5640
+ vars['--ah-fields-order'] = '0';
5641
+ }
5489
5642
  }
5490
5643
  }
5491
5644
  // Page background
@@ -5518,7 +5671,7 @@ function applyCssVars(element, vars) {
5518
5671
  });
5519
5672
  }
5520
5673
 
5521
- const authheroWidgetCss = () => `:host{display:block;font-family:var(--ah-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif)}.widget-container{max-width:var(--ah-widget-max-width, 400px);margin:0 auto;padding:var(--ah-widget-padding, 2rem);background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 8px);box-shadow:var(--ah-widget-shadow, 0 2px 10px rgba(0, 0, 0, 0.1))}.logo{display:block;width:var(--ah-logo-size, 48px);height:var(--ah-logo-size, 48px);margin:0 auto var(--ah-space-6, 1.5rem);object-fit:contain;border-radius:var(--ah-logo-radius, 8px)}.title{font-size:var(--ah-font-size-2xl, 1.5rem);font-weight:var(--ah-font-weight-semibold, 600);text-align:center;margin:0 0 var(--ah-space-8, 2rem);color:var(--ah-color-text, #111827);line-height:var(--ah-line-height-tight, 1.25)}.message{padding:var(--ah-space-3, 0.75rem) var(--ah-space-4, 1rem);border-radius:var(--ah-radius-md, 4px);margin-bottom:var(--ah-space-4, 1rem);font-size:var(--ah-font-size-sm, 0.875rem);line-height:var(--ah-line-height-normal, 1.5)}.message-error{background-color:var(--ah-color-error-bg, #fee2e2);color:var(--ah-color-error, #dc2626);border:1px solid var(--ah-color-error-border, #fecaca)}.message-success{background-color:var(--ah-color-success-bg, #dcfce7);color:var(--ah-color-success, #16a34a);border:1px solid var(--ah-color-success-border, #bbf7d0)}form{display:flex;flex-direction:column;gap:var(--ah-space-4, 1rem)}.links{display:flex;flex-direction:column;align-items:center;gap:var(--ah-space-2, 0.5rem);margin-top:var(--ah-space-6, 1.5rem);padding-top:var(--ah-space-4, 1rem)}.link-wrapper{font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #6b7280)}.link{color:var(--ah-color-primary, #0066cc);text-decoration:none;font-size:var(--ah-font-size-sm, 0.875rem);transition:color var(--ah-transition-fast, 150ms ease)}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-primary, #0066cc);outline-offset:2px}.divider{display:flex;align-items:center;text-align:center;margin:var(--ah-space-2, 0.5rem) 0}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #e5e7eb)}.divider-text{padding:0 var(--ah-space-4, 1rem);font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #9ca3af);text-transform:uppercase;letter-spacing:0.05em}.loading-spinner{width:40px;height:40px;margin:var(--ah-space-8, 2rem) auto;border:3px solid var(--ah-color-border-muted, #f3f3f3);border-top:3px solid var(--ah-color-primary, #0066cc);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.error-message{text-align:center;color:var(--ah-color-error, #dc2626);padding:var(--ah-space-4, 1rem)}`;
5674
+ const authheroWidgetCss = () => `:host{display:block;font-family:var(--ah-font-family, 'ulp-font', -apple-system, BlinkMacSystemFont, Roboto, Helvetica, sans-serif);font-size:var(--ah-font-size-base, 14px);line-height:var(--ah-line-height-base, 1.5);color:var(--ah-color-text, #1e212a);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.widget-container{max-width:var(--ah-widget-max-width, 400px);width:100%;margin:0 auto;background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 5px);box-shadow:var(--ah-widget-shadow, 0 4px 22px 0 rgba(0, 0, 0, 0.11));box-sizing:border-box}.widget-header{padding:var(--ah-header-padding, 40px 40px 24px)}.widget-body{padding:var(--ah-body-padding, 0 40px 40px)}.logo-wrapper{display:var(--ah-logo-display, flex);justify-content:var(--ah-logo-align, center)}.logo{display:block;height:var(--ah-logo-height, 52px);max-width:100%;width:auto;object-fit:contain}.title{font-size:var(--ah-font-size-title, 24px);font-weight:var(--ah-font-weight-title, 700);text-align:var(--ah-title-align, center);margin:var(--ah-title-margin, 24px 0 16px);color:var(--ah-color-header, #1e212a);line-height:1.2}.description{font-size:var(--ah-font-size-description, 14px);text-align:var(--ah-title-align, center);margin:var(--ah-description-margin, 0);color:var(--ah-color-text, #1e212a);line-height:1.5}.message{padding:12px 16px;border-radius:4px;margin-bottom:16px;font-size:14px;line-height:1.5}.message-error{background-color:var(--ah-color-error-bg, #ffeaea);color:var(--ah-color-error, #d03c38);border-left:3px solid var(--ah-color-error, #d03c38)}.message-success{background-color:var(--ah-color-success-bg, #e6f9f1);color:var(--ah-color-success, #13a769);border-left:3px solid var(--ah-color-success, #13a769)}form{display:flex;flex-direction:column}.form-content{display:flex;flex-direction:column}.social-section{display:flex;flex-direction:column;gap:8px;order:var(--ah-social-order, 2)}.fields-section{display:flex;flex-direction:column;order:var(--ah-fields-order, 0)}.divider{display:flex;align-items:center;text-align:center;margin:16px 0;order:var(--ah-divider-order, 1)}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #c9cace)}.divider-text{padding:0 10px;font-size:12px;font-weight:400;color:var(--ah-color-text-muted, #65676e);text-transform:uppercase;letter-spacing:0}.links{display:flex;flex-direction:column;align-items:center;gap:8px;margin-top:16px}.link-wrapper{font-size:14px;color:var(--ah-color-text, #1e212a)}.link{color:var(--ah-color-link, #635dff);text-decoration:var(--ah-link-decoration, none);font-size:14px;font-weight:var(--ah-font-weight-link, 400);transition:color 150ms ease}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-link, #635dff);outline-offset:2px;border-radius:2px}.loading-spinner{width:32px;height:32px;margin:24px auto;border:3px solid var(--ah-color-border-muted, #e0e1e3);border-top-color:var(--ah-color-primary, #635dff);border-radius:50%;animation:spin 0.8s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.error-message{text-align:center;color:var(--ah-color-error, #d03c38);padding:16px;font-size:14px}`;
5522
5675
 
5523
5676
  class AuthheroWidget {
5524
5677
  constructor(hostRef) {
@@ -5776,6 +5929,13 @@ class AuthheroWidget {
5776
5929
  }
5777
5930
  };
5778
5931
  handleButtonClick = (detail) => {
5932
+ // If this is a submit button click, trigger form submission
5933
+ if (detail.type === 'submit') {
5934
+ // Create a synthetic submit event and call handleSubmit
5935
+ const syntheticEvent = { preventDefault: () => { } };
5936
+ this.handleSubmit(syntheticEvent);
5937
+ return;
5938
+ }
5779
5939
  this.buttonClick.emit(detail);
5780
5940
  };
5781
5941
  handleLinkClick = (e, link) => {
@@ -5813,6 +5973,20 @@ class AuthheroWidget {
5813
5973
  .filter((c) => c.visible !== false)
5814
5974
  .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
5815
5975
  }
5976
+ /**
5977
+ * Check if a component is a social button.
5978
+ */
5979
+ isSocialComponent(component) {
5980
+ // Check the type property directly - FormComponent has a 'type' field
5981
+ // SocialField has type 'SOCIAL'
5982
+ return component.type === 'SOCIAL';
5983
+ }
5984
+ /**
5985
+ * Check if a component is a divider.
5986
+ */
5987
+ isDividerComponent(component) {
5988
+ return component.type === 'DIVIDER';
5989
+ }
5816
5990
  render() {
5817
5991
  if (this.loading && !this._screen) {
5818
5992
  return (hAsync("div", { class: "widget-container" }, hAsync("div", { class: "loading-spinner" })));
@@ -5823,9 +5997,13 @@ class AuthheroWidget {
5823
5997
  const screenErrors = this.getScreenErrors();
5824
5998
  const screenSuccesses = this.getScreenSuccesses();
5825
5999
  const components = this.getOrderedComponents();
5826
- // Get logo URL from branding props
5827
- const logoUrl = this._branding?.logo_url;
5828
- return (hAsync("div", { class: "widget-container", part: "container" }, logoUrl && hAsync("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }), this._screen.title && (hAsync("h1", { class: "title", part: "title" }, this._screen.title)), this._screen.description && (hAsync("p", { class: "description", part: "description" }, this._screen.description)), screenErrors.map((err) => (hAsync("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (hAsync("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), hAsync("form", { onSubmit: this.handleSubmit, part: "form" }, components.map((component) => (hAsync("authhero-node", { key: component.id, component: component, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading })))), this._screen.links && this._screen.links.length > 0 && (hAsync("div", { class: "links", part: "links" }, this._screen.links.map((link) => (hAsync("span", { class: "link-wrapper", part: "link-wrapper", key: link.id ?? link.href }, link.linkText ? (hAsync("span", null, link.text, ' ', hAsync("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, { id: link.id, href: link.href, text: link.linkText || link.text }) }, link.linkText))) : (hAsync("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, { id: link.id, href: link.href, text: link.text }) }, link.text)))))))));
6000
+ // Separate social, divider, and field components for layout ordering
6001
+ const socialComponents = components.filter(c => this.isSocialComponent(c));
6002
+ const fieldComponents = components.filter(c => !this.isSocialComponent(c) && !this.isDividerComponent(c));
6003
+ const hasDivider = components.some(c => this.isDividerComponent(c));
6004
+ // Get logo URL from theme.widget (takes precedence) or branding
6005
+ const logoUrl = this._theme?.widget?.logo_url || this._branding?.logo_url;
6006
+ return (hAsync("div", { class: "widget-container", part: "container" }, hAsync("header", { class: "widget-header", part: "header" }, logoUrl && (hAsync("div", { class: "logo-wrapper", part: "logo-wrapper" }, hAsync("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }))), this._screen.title && (hAsync("h1", { class: "title", part: "title" }, this._screen.title)), this._screen.description && (hAsync("p", { class: "description", part: "description" }, this._screen.description))), hAsync("div", { class: "widget-body", part: "body" }, screenErrors.map((err) => (hAsync("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (hAsync("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), hAsync("form", { onSubmit: this.handleSubmit, part: "form" }, hAsync("div", { class: "form-content" }, socialComponents.length > 0 && (hAsync("div", { class: "social-section", part: "social-section" }, socialComponents.map((component) => (hAsync("authhero-node", { key: component.id, component: component, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading }))))), socialComponents.length > 0 && fieldComponents.length > 0 && hasDivider && (hAsync("div", { class: "divider", part: "divider" }, hAsync("span", { class: "divider-text" }, "Or"))), hAsync("div", { class: "fields-section", part: "fields-section" }, fieldComponents.map((component) => (hAsync("authhero-node", { key: component.id, component: component, value: this.formData[component.id], onFieldChange: (e) => this.handleInputChange(e.detail.id, e.detail.value), onButtonClick: (e) => this.handleButtonClick(e.detail), disabled: this.loading })))))), this._screen.links && this._screen.links.length > 0 && (hAsync("div", { class: "links", part: "links" }, this._screen.links.map((link) => (hAsync("span", { class: "link-wrapper", part: "link-wrapper", key: link.id ?? link.href }, link.linkText ? (hAsync("span", null, link.text, ' ', hAsync("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, { id: link.id, href: link.href, text: link.linkText || link.text }) }, link.linkText))) : (hAsync("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, { id: link.id, href: link.href, text: link.text }) }, link.text))))))))));
5829
6007
  }
5830
6008
  static get watchers() { return {
5831
6009
  "screen": [{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authhero/widget",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Server-Driven UI widget for AuthHero authentication flows",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,6 +22,7 @@
22
22
  ".": "./dist/index.js",
23
23
  "./hydrate": "./hydrate/index.js",
24
24
  "./loader": "./loader/index.js",
25
+ "./dist/esm/loader.js": "./dist/esm/loader.js",
25
26
  "./server": {
26
27
  "import": "./dist/collection/server/index.js",
27
28
  "types": "./dist/types/server/index.d.ts"
@@ -32,18 +33,23 @@
32
33
  }
33
34
  },
34
35
  "dependencies": {
35
- "@authhero/adapter-interfaces": "0.115.0"
36
+ "@authhero/adapter-interfaces": "0.116.0"
36
37
  },
37
38
  "devDependencies": {
39
+ "@hono/node-server": "^1.14.1",
38
40
  "@stencil/core": "^4.40.1",
39
41
  "@types/jest": "^29.5.14",
42
+ "concurrently": "^9.1.2",
43
+ "hono": "^4.7.10",
40
44
  "jest": "^29.7.0",
41
- "jest-cli": "^29.7.0"
45
+ "jest-cli": "^29.7.0",
46
+ "tsx": "^4.19.4"
42
47
  },
43
48
  "license": "MIT",
44
49
  "scripts": {
45
50
  "build": "stencil build",
46
- "dev": "stencil build --dev --watch --serve",
51
+ "dev": "concurrently \"stencil build --dev --watch\" \"tsx watch demo-server/server.ts\"",
52
+ "demo": "tsx demo-server/server.ts",
47
53
  "test": "stencil test --spec",
48
54
  "test:watch": "stencil test --spec --watchAll",
49
55
  "generate": "stencil generate"
@@ -1 +0,0 @@
1
- import{r as e,c as r,h as t}from"./p-Doiemx6o.js";const a=class{constructor(t){e(this,t),this.fieldChange=r(this,"fieldChange"),this.buttonClick=r(this,"buttonClick")}component;value;disabled=!1;fieldChange;buttonClick;handleInput=e=>{this.fieldChange.emit({id:this.component.id,value:e.target.value})};handleCheckbox=e=>{this.fieldChange.emit({id:this.component.id,value:e.target.checked?"true":"false"})};handleButtonClick=(e,r,t)=>{"submit"!==r&&e.preventDefault(),this.buttonClick.emit({id:this.component.id,type:r,value:t})};getErrors(){const e=this.component;return e.messages?.filter((e=>"error"===e.type))||[]}renderLabel(e,r,a){return e?t("label",{class:"input-label",part:"label",htmlFor:r},e,a&&t("span",{class:"required"},"*")):null}renderErrors(){return this.getErrors().map((e=>t("span",{class:"error-text",part:"error-text",key:e.id??e.text},e.text)))}renderHint(e){return e?t("span",{class:"helper-text",part:"helper-text"},e):null}renderDivider(){return t("hr",{class:"divider",part:"divider"})}renderHtml(e){return t("div",{class:"html-content",part:"html-content",innerHTML:e.config?.content??""})}renderImage(e){const{src:r,alt:a,width:i,height:s}=e.config??{};return r?t("img",{class:"image",part:"image",src:r,alt:a??"",width:i,height:s,loading:"lazy"}):null}renderRichText(e){return t("div",{class:"rich-text",part:"rich-text",innerHTML:e.config?.content??""})}renderNextButton(e){return t("button",{type:"submit",class:"btn btn-primary",part:"button button-primary",disabled:this.disabled,onClick:e=>this.handleButtonClick(e,"submit","next")},e.config.text??"Continue")}renderPreviousButton(e){return t("button",{type:"button",class:"btn btn-secondary",part:"button button-secondary",disabled:this.disabled,onClick:e=>this.handleButtonClick(e,"previous","back")},e.config.text??"Back")}renderJumpButton(e){return t("button",{type:"button",class:"btn btn-link",part:"button button-link",disabled:this.disabled,onClick:r=>this.handleButtonClick(r,"jump",e.config.target_step)},e.config.text??"Go")}renderResendButton(e){return t("button",{type:"button",class:"btn btn-link",part:"button button-link",disabled:this.disabled,onClick:r=>this.handleButtonClick(r,"resend",e.config.resend_action)},e.config.text??"Resend")}renderTextField(e){const r=`input-${e.id}`,a=this.getErrors(),{placeholder:i,multiline:s,max_length:o}=e.config??{};return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),s?t("textarea",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input textarea",name:e.id,placeholder:i,required:e.required,disabled:this.disabled,maxLength:o,onInput:this.handleInput},this.value??""):t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:e.sensitive?"password":"text",name:e.id,value:this.value??"",placeholder:i,required:e.required,disabled:this.disabled,maxLength:o,onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderEmailField(e){const r=`input-${e.id}`,a=this.getErrors();return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:"email",name:e.id,value:this.value??"",placeholder:e.config?.placeholder,required:e.required,disabled:this.disabled,autocomplete:"email",onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderPasswordField(e){const r=`input-${e.id}`,a=this.getErrors();return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:"password",name:e.id,value:this.value??"",placeholder:e.config?.placeholder,required:e.required,disabled:this.disabled,minLength:e.config?.min_length,autocomplete:"current-password",onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderNumberField(e){const r=`input-${e.id}`,a=this.getErrors(),{placeholder:i,min:s,max:o,step:n}=e.config??{};return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:"number",name:e.id,value:this.value??"",placeholder:i,required:e.required,disabled:this.disabled,min:s,max:o,step:n,onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderTelField(e){const r=`input-${e.id}`,a=this.getErrors();return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:"tel",name:e.id,value:this.value??"",placeholder:e.config?.placeholder,required:e.required,disabled:this.disabled,autocomplete:"tel",onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderUrlField(e){const r=`input-${e.id}`,a=this.getErrors();return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:"url",name:e.id,value:this.value??"",placeholder:e.config?.placeholder,required:e.required,disabled:this.disabled,onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderDateField(e){const r=`input-${e.id}`,a=this.getErrors(),{min:i,max:s}=e.config??{};return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("input",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input",type:"date",name:e.id,value:this.value??"",required:e.required,disabled:this.disabled,min:i,max:s,onInput:this.handleInput}),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderBooleanField(e){return t("label",{class:"checkbox-wrapper",part:"checkbox-wrapper"},t("input",{type:"checkbox",part:"checkbox",name:e.id,checked:"true"===this.value||!0===e.config?.default_value,required:e.required,disabled:this.disabled,onChange:this.handleCheckbox}),t("span",{class:"checkbox-label",part:"checkbox-label"},e.label))}renderLegalField(e){const r=e.config?.text??e.label??"",a=!0===e.config?.html;return t("label",{class:"checkbox-wrapper",part:"checkbox-wrapper"},t("input",{type:"checkbox",part:"checkbox",name:e.id,checked:"true"===this.value,required:e.required,disabled:this.disabled,onChange:this.handleCheckbox}),a?t("span",{class:"checkbox-label",part:"checkbox-label",innerHTML:r}):t("span",{class:"checkbox-label",part:"checkbox-label"},r))}renderDropdownField(e){const r=`input-${e.id}`,a=this.getErrors(),{options:i,placeholder:s}=e.config??{};return t("div",{class:"input-wrapper",part:"input-wrapper"},this.renderLabel(e.label,r,e.required),t("select",{id:r,class:{"input-field":!0,"has-error":a.length>0},part:"input select",name:e.id,required:e.required,disabled:this.disabled,onChange:this.handleInput},s&&t("option",{value:"",disabled:!0,selected:!this.value},s),i?.map((e=>t("option",{value:e.value,selected:this.value===e.value,key:e.value},e.label)))),this.renderErrors(),0===a.length&&this.renderHint(e.hint))}renderChoiceField(e){const r=this.getErrors(),{options:a,display:i}=e.config??{},s="checkbox"===i,o=s?"checkbox":"radio";return t("div",{class:"choice-wrapper",part:"choice-wrapper"},e.label&&t("span",{class:"choice-label",part:"choice-label"},e.label,e.required&&t("span",{class:"required"},"*")),t("div",{class:"choice-options",part:"choice-options"},a?.map((r=>t("label",{class:"choice-option",part:"choice-option",key:r.value},t("input",{type:o,part:o,name:e.id,value:r.value,checked:this.value===r.value,required:e.required&&!s,disabled:this.disabled,onChange:this.handleInput}),t("span",null,r.label))))),this.renderErrors(),0===r.length&&this.renderHint(e.hint))}renderSocialField(e){return t("div",{class:"social-buttons",part:"social-buttons"},(e.config?.providers??[]).map((e=>t("button",{type:"button",class:"btn btn-secondary btn-social",part:"button button-secondary button-social","data-provider":e,disabled:this.disabled,onClick:r=>this.handleButtonClick(r,"social",e),key:e},"Continue with ",e.charAt(0).toUpperCase()+e.slice(1)))))}render(){if(!this.component)return null;if(!1===this.component.visible)return null;switch(this.component.type){case"DIVIDER":return this.renderDivider();case"HTML":return this.renderHtml(this.component);case"IMAGE":return this.renderImage(this.component);case"RICH_TEXT":return this.renderRichText(this.component);case"NEXT_BUTTON":return this.renderNextButton(this.component);case"PREVIOUS_BUTTON":return this.renderPreviousButton(this.component);case"JUMP_BUTTON":return this.renderJumpButton(this.component);case"RESEND_BUTTON":return this.renderResendButton(this.component);case"TEXT":return this.renderTextField(this.component);case"EMAIL":return this.renderEmailField(this.component);case"PASSWORD":return this.renderPasswordField(this.component);case"NUMBER":return this.renderNumberField(this.component);case"TEL":return this.renderTelField(this.component);case"URL":return this.renderUrlField(this.component);case"DATE":return this.renderDateField(this.component);case"BOOLEAN":return this.renderBooleanField(this.component);case"LEGAL":return this.renderLegalField(this.component);case"DROPDOWN":return this.renderDropdownField(this.component);case"CHOICE":return this.renderChoiceField(this.component);case"SOCIAL":return this.renderSocialField(this.component);case"AUTH0_VERIFIABLE_CREDENTIALS":case"GMAPS_ADDRESS":case"RECAPTCHA":return console.warn(`Widget component "${this.component.type}" not yet implemented`),null;case"CARDS":case"CUSTOM":case"FILE":case"PAYMENT":return console.warn(`Component "${this.component.type}" not yet implemented`),null;default:return console.warn(`Unknown component type: ${this.component.type}`),null}}};a.style=":host{display:block}.input-wrapper{display:flex;flex-direction:column;gap:var(--ah-space-1, 0.25rem)}.input-label{font-size:var(--ah-font-size-sm, 0.875rem);font-weight:var(--ah-font-weight-medium, 500);color:var(--ah-color-text-label, #374151);line-height:var(--ah-line-height-normal, 1.5)}.required{color:var(--ah-color-error, #dc2626);margin-left:var(--ah-space-1, 0.25rem)}.input-field{padding:var(--ah-input-padding-y, 0.75rem) var(--ah-input-padding-x, 1rem);font-size:var(--ah-font-size-base, 1rem);font-family:inherit;color:var(--ah-color-text, #1f2937);background-color:var(--ah-color-bg, #ffffff);border:var(--ah-input-border-width, 1px) solid var(--ah-color-border, #d1d5db);border-radius:var(--ah-input-radius, 6px);outline:none;transition:border-color var(--ah-transition-base, 200ms ease), box-shadow var(--ah-transition-base, 200ms ease)}.input-field::placeholder{color:var(--ah-color-text-muted, #9ca3af)}.input-field:focus{border-color:var(--ah-color-primary, #0066cc);box-shadow:0 0 0 3px var(--ah-color-primary-focus-ring, rgba(0, 102, 204, 0.1))}.input-field.has-error{border-color:var(--ah-color-error, #dc2626)}.input-field.has-error:focus{box-shadow:0 0 0 3px rgba(220, 38, 38, 0.1)}.input-field:disabled{background-color:var(--ah-color-bg-disabled, #f3f4f6);cursor:not-allowed;opacity:0.7}.error-text{font-size:var(--ah-font-size-xs, 0.75rem);color:var(--ah-color-error, #dc2626);margin-top:var(--ah-space-1, 0.25rem)}.helper-text{font-size:var(--ah-font-size-xs, 0.75rem);color:var(--ah-color-text-muted, #6b7280);margin-top:var(--ah-space-1, 0.25rem)}.checkbox-wrapper{display:flex;align-items:flex-start;gap:var(--ah-space-2, 0.5rem);cursor:pointer}.checkbox-wrapper input[type='checkbox']{width:1rem;height:1rem;margin-top:0.125rem;accent-color:var(--ah-color-primary, #0066cc);cursor:pointer}.checkbox-label{font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-label, #374151);line-height:var(--ah-line-height-normal, 1.5)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--ah-space-2, 0.5rem);width:100%;padding:var(--ah-btn-padding-y, 0.875rem) var(--ah-btn-padding-x, 1.5rem);font-size:var(--ah-font-size-base, 1rem);font-weight:var(--ah-btn-font-weight, 500);font-family:inherit;line-height:var(--ah-line-height-tight, 1.25);text-align:center;text-decoration:none;border:none;border-radius:var(--ah-btn-radius, 8px);cursor:pointer;transition:background-color var(--ah-transition-base, 200ms ease), transform var(--ah-transition-fast, 150ms ease), box-shadow var(--ah-transition-base, 200ms ease)}.btn:disabled{opacity:0.6;cursor:not-allowed}.btn:not(:disabled):active{transform:scale(0.98)}.btn:focus-visible{outline:2px solid var(--ah-color-primary, #0066cc);outline-offset:2px}.btn-primary{background-color:var(--ah-color-primary, #0066cc);color:var(--ah-color-text-on-primary, #ffffff)}.btn-primary:not(:disabled):hover{background-color:var(--ah-color-primary-hover, #0052a3)}.btn-secondary{background-color:var(--ah-color-bg, #ffffff);color:var(--ah-color-text, #374151);border:1px solid var(--ah-color-border-muted, #e5e7eb)}.btn-secondary:not(:disabled):hover{background-color:var(--ah-color-bg-muted, #f9fafb);border-color:var(--ah-color-border, #d1d5db)}.text-title{font-size:var(--ah-font-size-xl, 1.25rem);font-weight:var(--ah-font-weight-semibold, 600);color:var(--ah-color-text, #1f2937);margin:var(--ah-space-2, 0.5rem) 0;line-height:var(--ah-line-height-tight, 1.25)}.text-title.text-success{color:var(--ah-color-success, #16a34a)}.text-description{font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #6b7280);margin:var(--ah-space-1, 0.25rem) 0;line-height:var(--ah-line-height-normal, 1.5)}.image{display:block;max-width:100%;height:auto;border-radius:var(--ah-radius-lg, 8px)}.image-centered{margin:0 auto var(--ah-space-4, 1rem);width:var(--ah-logo-size, 48px);height:var(--ah-logo-size, 48px);object-fit:contain}.link{color:var(--ah-color-primary, #0066cc);text-decoration:none;font-size:var(--ah-font-size-sm, 0.875rem);transition:color var(--ah-transition-fast, 150ms ease)}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-primary, #0066cc);outline-offset:2px}.node-error{padding:var(--ah-space-3, 0.75rem) var(--ah-space-4, 1rem);background-color:var(--ah-color-error-bg, #fee2e2);color:var(--ah-color-error, #dc2626);border:1px solid var(--ah-color-error-border, #fecaca);border-radius:var(--ah-radius-md, 6px);font-size:var(--ah-font-size-sm, 0.875rem)}.node-success{padding:var(--ah-space-3, 0.75rem) var(--ah-space-4, 1rem);background-color:var(--ah-color-success-bg, #dcfce7);color:var(--ah-color-success, #16a34a);border:1px solid var(--ah-color-success-border, #bbf7d0);border-radius:var(--ah-radius-md, 6px);font-size:var(--ah-font-size-sm, 0.875rem)}.divider{display:flex;align-items:center;text-align:center;margin:var(--ah-space-4, 1rem) 0}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #e5e7eb)}.divider-text{padding:0 var(--ah-space-4, 1rem);font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #9ca3af);text-transform:uppercase;letter-spacing:0.05em}";export{a as authhero_node}
@@ -1 +0,0 @@
1
- import{r as e,c as t,g as i,h as r}from"./p-Doiemx6o.js";function s(e,t){if(void 0!==t)return`${t}px`;switch(e){case"pill":return"9999px";case"rounded":return"8px";case"sharp":return"0";default:return}}function a(e){if(!e)return{};const t={};if(e.colors?.primary&&(t["--ah-color-primary"]=e.colors.primary,t["--ah-color-primary-hover"]=e.colors.primary),e.colors?.page_background){const i=e.colors.page_background;"solid"===i.type&&i.start?t["--ah-page-bg"]=i.start:"gradient"===i.type&&i.start&&i.end&&(t["--ah-page-bg"]=`linear-gradient(${i.angle_deg??180}deg, ${i.start}, ${i.end})`)}return e.logo_url&&(t["--ah-logo-url"]=`url(${e.logo_url})`),e.font?.url&&(t["--ah-font-url"]=e.font.url),t}function o(e){if(!e)return{};const t={};if(e.borders){const i=e.borders;void 0!==i.widget_corner_radius&&(t["--ah-widget-radius"]=`${i.widget_corner_radius}px`),void 0!==i.widget_border_weight&&(t["--ah-widget-border-width"]=`${i.widget_border_weight}px`),!1===i.show_widget_shadow&&(t["--ah-widget-shadow"]="none");const r=s(i.buttons_style,i.button_border_radius);r&&(t["--ah-btn-radius"]=r),void 0!==i.button_border_weight&&(t["--ah-btn-border-width"]=`${i.button_border_weight}px`);const a=s(i.inputs_style,i.input_border_radius);a&&(t["--ah-input-radius"]=a),void 0!==i.input_border_weight&&(t["--ah-input-border-width"]=`${i.input_border_weight}px`)}if(e.colors){const i=e.colors;i.primary_button&&(t["--ah-color-primary"]=i.primary_button,t["--ah-color-primary-hover"]=i.primary_button),i.primary_button_label&&(t["--ah-btn-primary-text"]=i.primary_button_label),i.secondary_button_border&&(t["--ah-btn-secondary-border"]=i.secondary_button_border),i.secondary_button_label&&(t["--ah-btn-secondary-text"]=i.secondary_button_label),i.body_text&&(t["--ah-color-text"]=i.body_text),i.header&&(t["--ah-color-text-header"]=i.header),i.input_labels_placeholders&&(t["--ah-color-text-label"]=i.input_labels_placeholders,t["--ah-color-text-muted"]=i.input_labels_placeholders),i.input_filled_text&&(t["--ah-color-input-text"]=i.input_filled_text),i.widget_background&&(t["--ah-color-bg"]=i.widget_background),i.input_background&&(t["--ah-color-input-bg"]=i.input_background),i.widget_border&&(t["--ah-widget-border-color"]=i.widget_border),i.input_border&&(t["--ah-color-border"]=i.input_border),i.links_focused_components&&(t["--ah-color-link"]=i.links_focused_components),i.base_focus_color&&(t["--ah-color-focus-ring"]=i.base_focus_color),i.base_hover_color&&(t["--ah-color-primary-hover"]=i.base_hover_color),i.error&&(t["--ah-color-error"]=i.error),i.success&&(t["--ah-color-success"]=i.success),i.icons&&(t["--ah-color-icon"]=i.icons)}if(e.fonts){const i=e.fonts;i.font_url&&(t["--ah-font-url"]=i.font_url),i.reference_text_size&&(t["--ah-font-size-base"]=`${i.reference_text_size}px`),i.title?.size&&(t["--ah-font-size-title"]=`${i.title.size}px`),i.subtitle?.size&&(t["--ah-font-size-subtitle"]=`${i.subtitle.size}px`),i.body_text?.size&&(t["--ah-font-size-body"]=`${i.body_text.size}px`),i.input_labels?.size&&(t["--ah-font-size-label"]=`${i.input_labels.size}px`),i.buttons_text?.size&&(t["--ah-font-size-btn"]=`${i.buttons_text.size}px`),i.links?.size&&(t["--ah-font-size-link"]=`${i.links.size}px`),"underlined"===i.links_style&&(t["--ah-link-decoration"]="underline"),i.title?.bold&&(t["--ah-font-weight-title"]="700"),i.buttons_text?.bold&&(t["--ah-font-weight-btn"]="600")}if(e.widget){const i=e.widget;i.header_text_alignment&&(t["--ah-title-align"]=i.header_text_alignment),i.logo_height&&(t["--ah-logo-height"]=`${i.logo_height}px`),i.logo_position&&(t["--ah-logo-align"]={center:"center",left:"flex-start",right:"flex-end",none:"none"}[i.logo_position]??"center")}if(e.page_background){const i=e.page_background;i.background_color&&(t["--ah-page-bg"]=i.background_color),i.background_image_url&&(t["--ah-page-bg-image"]=`url(${i.background_image_url})`)}return t}const n=class{constructor(i){e(this,i),this.formSubmit=t(this,"formSubmit"),this.buttonClick=t(this,"buttonClick"),this.linkClick=t(this,"linkClick"),this.navigate=t(this,"navigate"),this.flowComplete=t(this,"flowComplete"),this.flowError=t(this,"flowError"),this.screenChange=t(this,"screenChange")}get el(){return i(this)}screen;apiUrl;branding;theme;loading=!1;autoSubmit=!1;_screen;_branding;_theme;formData={};formSubmit;buttonClick;linkClick;navigate;flowComplete;flowError;screenChange;watchScreen(e){if("string"==typeof e)try{this._screen=JSON.parse(e)}catch{console.error("Failed to parse screen JSON")}else this._screen=e;this._screen&&this.screenChange.emit(this._screen)}watchBranding(e){if("string"==typeof e)try{this._branding=JSON.parse(e)}catch{console.error("Failed to parse branding JSON")}else this._branding=e;this.applyThemeStyles()}watchTheme(e){if("string"==typeof e)try{this._theme=JSON.parse(e)}catch{console.error("Failed to parse theme JSON")}else this._theme=e;this.applyThemeStyles()}applyThemeStyles(){const e=(t=this._theme,{...a(this._branding),...o(t)});var t;!function(e,t){Object.entries(t).forEach((([t,i])=>{e.style.setProperty(t,i)}))}(this.el,e)}async componentWillLoad(){this.watchScreen(this.screen),this.watchBranding(this.branding),this.watchTheme(this.theme),this.apiUrl&&!this._screen&&await this.fetchScreen()}async fetchScreen(){if(this.apiUrl){this.loading=!0;try{const e=await fetch(this.apiUrl,{credentials:"include",headers:{Accept:"application/json"}});e.ok&&(this._screen=await e.json(),this._screen&&this.screenChange.emit(this._screen))}catch(e){console.error("Failed to fetch screen:",e)}finally{this.loading=!1}}}handleInputChange=(e,t)=>{this.formData={...this.formData,[e]:t}};handleSubmit=async e=>{if(e.preventDefault(),this._screen&&(this.formSubmit.emit({screen:this._screen,data:this.formData}),this.autoSubmit)){this.loading=!0;try{const e=await fetch(this._screen.action,{method:this._screen.method,credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({data:this.formData})}),t=e.headers.get("content-type");if(t?.includes("application/json")){const t=await e.json();t.redirect?(this.flowComplete.emit({redirectUrl:t.redirect}),this.navigate.emit({url:t.redirect})):t.screen?(this._screen=t.screen,this.formData={},this.screenChange.emit(t.screen),t.branding&&(this._branding=t.branding,this.applyThemeStyles())):t.complete&&this.flowComplete.emit({}),!e.ok&&t.screen&&(this._screen=t.screen,this.screenChange.emit(t.screen))}}catch(e){console.error("Form submission failed:",e),this.flowError.emit({message:e instanceof Error?e.message:"Form submission failed"})}finally{this.loading=!1}}};handleButtonClick=e=>{this.buttonClick.emit(e)};handleLinkClick=(e,t)=>{this.linkClick.emit({id:t.id,href:t.href,text:t.text}),this.autoSubmit||e.preventDefault()};getScreenErrors(){return this._screen?.messages?.filter((e=>"error"===e.type))||[]}getScreenSuccesses(){return this._screen?.messages?.filter((e=>"success"===e.type))||[]}getOrderedComponents(){return this._screen?[...this._screen.components].filter((e=>!1!==e.visible)).sort(((e,t)=>(e.order??0)-(t.order??0))):[]}render(){if(this.loading&&!this._screen)return r("div",{class:"widget-container"},r("div",{class:"loading-spinner"}));if(!this._screen)return r("div",{class:"widget-container"},r("div",{class:"error-message"},"No screen configuration provided"));const e=this.getScreenErrors(),t=this.getScreenSuccesses(),i=this.getOrderedComponents(),s=this._branding?.logo_url;return r("div",{class:"widget-container",part:"container"},s&&r("img",{class:"logo",part:"logo",src:s,alt:"Logo"}),this._screen.title&&r("h1",{class:"title",part:"title"},this._screen.title),this._screen.description&&r("p",{class:"description",part:"description"},this._screen.description),e.map((e=>r("div",{class:"message message-error",part:"message message-error",key:e.id??e.text},e.text))),t.map((e=>r("div",{class:"message message-success",part:"message message-success",key:e.id??e.text},e.text))),r("form",{onSubmit:this.handleSubmit,part:"form"},i.map((e=>r("authhero-node",{key:e.id,component:e,value:this.formData[e.id],onFieldChange:e=>this.handleInputChange(e.detail.id,e.detail.value),onButtonClick:e=>this.handleButtonClick(e.detail),disabled:this.loading})))),this._screen.links&&this._screen.links.length>0&&r("div",{class:"links",part:"links"},this._screen.links.map((e=>r("span",{class:"link-wrapper",part:"link-wrapper",key:e.id??e.href},e.linkText?r("span",null,e.text," ",r("a",{href:e.href,class:"link",part:"link",onClick:t=>this.handleLinkClick(t,{id:e.id,href:e.href,text:e.linkText||e.text})},e.linkText)):r("a",{href:e.href,class:"link",part:"link",onClick:t=>this.handleLinkClick(t,{id:e.id,href:e.href,text:e.text})},e.text))))))}static get watchers(){return{screen:[{watchScreen:0}],branding:[{watchBranding:0}],theme:[{watchTheme:0}]}}};n.style=":host{display:block;font-family:var(--ah-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif)}.widget-container{max-width:var(--ah-widget-max-width, 400px);margin:0 auto;padding:var(--ah-widget-padding, 2rem);background-color:var(--ah-color-bg, #ffffff);border-radius:var(--ah-widget-radius, 8px);box-shadow:var(--ah-widget-shadow, 0 2px 10px rgba(0, 0, 0, 0.1))}.logo{display:block;width:var(--ah-logo-size, 48px);height:var(--ah-logo-size, 48px);margin:0 auto var(--ah-space-6, 1.5rem);object-fit:contain;border-radius:var(--ah-logo-radius, 8px)}.title{font-size:var(--ah-font-size-2xl, 1.5rem);font-weight:var(--ah-font-weight-semibold, 600);text-align:center;margin:0 0 var(--ah-space-8, 2rem);color:var(--ah-color-text, #111827);line-height:var(--ah-line-height-tight, 1.25)}.message{padding:var(--ah-space-3, 0.75rem) var(--ah-space-4, 1rem);border-radius:var(--ah-radius-md, 4px);margin-bottom:var(--ah-space-4, 1rem);font-size:var(--ah-font-size-sm, 0.875rem);line-height:var(--ah-line-height-normal, 1.5)}.message-error{background-color:var(--ah-color-error-bg, #fee2e2);color:var(--ah-color-error, #dc2626);border:1px solid var(--ah-color-error-border, #fecaca)}.message-success{background-color:var(--ah-color-success-bg, #dcfce7);color:var(--ah-color-success, #16a34a);border:1px solid var(--ah-color-success-border, #bbf7d0)}form{display:flex;flex-direction:column;gap:var(--ah-space-4, 1rem)}.links{display:flex;flex-direction:column;align-items:center;gap:var(--ah-space-2, 0.5rem);margin-top:var(--ah-space-6, 1.5rem);padding-top:var(--ah-space-4, 1rem)}.link-wrapper{font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #6b7280)}.link{color:var(--ah-color-primary, #0066cc);text-decoration:none;font-size:var(--ah-font-size-sm, 0.875rem);transition:color var(--ah-transition-fast, 150ms ease)}.link:hover{text-decoration:underline}.link:focus-visible{outline:2px solid var(--ah-color-primary, #0066cc);outline-offset:2px}.divider{display:flex;align-items:center;text-align:center;margin:var(--ah-space-2, 0.5rem) 0}.divider::before,.divider::after{content:'';flex:1;border-bottom:1px solid var(--ah-color-border-muted, #e5e7eb)}.divider-text{padding:0 var(--ah-space-4, 1rem);font-size:var(--ah-font-size-sm, 0.875rem);color:var(--ah-color-text-muted, #9ca3af);text-transform:uppercase;letter-spacing:0.05em}.loading-spinner{width:40px;height:40px;margin:var(--ah-space-8, 2rem) auto;border:3px solid var(--ah-color-border-muted, #f3f3f3);border-top:3px solid var(--ah-color-primary, #0066cc);border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.error-message{text-align:center;color:var(--ah-color-error, #dc2626);padding:var(--ah-space-4, 1rem)}";export{n as authhero_widget}