@authhero/widget 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/authhero-widget/authhero-widget.esm.js +1 -0
  2. package/dist/authhero-widget/index.esm.js +1 -0
  3. package/dist/authhero-widget/p-2e93c814.entry.js +1 -0
  4. package/dist/authhero-widget/p-539fc666.entry.js +1 -0
  5. package/dist/authhero-widget/p-DQuL1Twl.js +1 -0
  6. package/dist/authhero-widget/p-Doiemx6o.js +2 -0
  7. package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
  8. package/dist/cjs/authhero-node.cjs.entry.js +255 -0
  9. package/dist/cjs/authhero-widget.cjs.entry.js +577 -0
  10. package/dist/cjs/authhero-widget.cjs.js +25 -0
  11. package/dist/cjs/index-D0xitTOL.js +3788 -0
  12. package/dist/cjs/index.cjs.js +8123 -0
  13. package/dist/cjs/loader.cjs.js +13 -0
  14. package/dist/collection/collection-manifest.json +13 -0
  15. package/dist/collection/components/authhero-node/authhero-node.css +298 -0
  16. package/dist/collection/components/authhero-node/authhero-node.js +360 -0
  17. package/dist/collection/components/authhero-widget/authhero-widget.css +186 -0
  18. package/dist/collection/components/authhero-widget/authhero-widget.js +628 -0
  19. package/dist/collection/index.js +2 -0
  20. package/dist/collection/server/index.js +453 -0
  21. package/dist/collection/themes/index.js +71 -0
  22. package/dist/collection/types/components.js +8 -0
  23. package/dist/collection/utils/branding.js +248 -0
  24. package/dist/components/authhero-node.d.ts +11 -0
  25. package/dist/components/authhero-node.js +1 -0
  26. package/dist/components/authhero-widget.d.ts +11 -0
  27. package/dist/components/authhero-widget.js +1 -0
  28. package/dist/components/index.d.ts +35 -0
  29. package/dist/components/index.js +1 -0
  30. package/dist/components/p-086EZrPM.js +1 -0
  31. package/dist/components/p-DS6y_iDJ.js +1 -0
  32. package/dist/esm/app-globals-DQuL1Twl.js +3 -0
  33. package/dist/esm/authhero-node.entry.js +253 -0
  34. package/dist/esm/authhero-widget.entry.js +575 -0
  35. package/dist/esm/authhero-widget.js +21 -0
  36. package/dist/esm/index-Doiemx6o.js +3780 -0
  37. package/dist/esm/index.js +8122 -0
  38. package/dist/esm/loader.js +11 -0
  39. package/dist/index.cjs.js +1 -0
  40. package/dist/index.js +1 -0
  41. package/dist/types/components/authhero-node/authhero-node.d.ts +72 -0
  42. package/dist/types/components/authhero-widget/authhero-widget.d.ts +172 -0
  43. package/dist/types/components.d.ts +215 -0
  44. package/dist/types/index.d.ts +1 -0
  45. package/dist/types/server/index.d.ts +85 -0
  46. package/dist/types/stencil-public-runtime.d.ts +1839 -0
  47. package/dist/types/themes/index.d.ts +40 -0
  48. package/dist/types/types/components.d.ts +8 -0
  49. package/dist/types/utils/branding.d.ts +119 -0
  50. package/hydrate/index.d.ts +287 -0
  51. package/hydrate/index.js +23729 -0
  52. package/hydrate/index.mjs +23719 -0
  53. package/hydrate/package.json +12 -0
  54. package/loader/cdn.js +1 -0
  55. package/loader/index.cjs.js +1 -0
  56. package/loader/index.d.ts +24 -0
  57. package/loader/index.es2017.js +1 -0
  58. package/loader/index.js +2 -0
  59. package/package.json +1 -1
@@ -0,0 +1,575 @@
1
+ import { r as registerInstance, c as createEvent, g as getElement, h } from './index-Doiemx6o.js';
2
+
3
+ /**
4
+ * AuthHero Widget - Branding Utilities
5
+ *
6
+ * Converts AuthHero branding and theme configurations to CSS custom properties.
7
+ */
8
+ /**
9
+ * Convert a style enum to border radius value
10
+ */
11
+ function styleToRadius(style, baseRadius) {
12
+ if (baseRadius !== undefined)
13
+ return `${baseRadius}px`;
14
+ switch (style) {
15
+ case 'pill':
16
+ return '9999px';
17
+ case 'rounded':
18
+ return '8px';
19
+ case 'sharp':
20
+ return '0';
21
+ default:
22
+ return undefined;
23
+ }
24
+ }
25
+ /**
26
+ * Convert branding configuration to CSS custom properties
27
+ */
28
+ function brandingToCssVars(branding) {
29
+ if (!branding)
30
+ return {};
31
+ const vars = {};
32
+ // Primary color
33
+ if (branding.colors?.primary) {
34
+ vars['--ah-color-primary'] = branding.colors.primary;
35
+ // Generate hover variant (slightly darker)
36
+ vars['--ah-color-primary-hover'] = branding.colors.primary;
37
+ }
38
+ // Page background
39
+ if (branding.colors?.page_background) {
40
+ const bg = branding.colors.page_background;
41
+ if (bg.type === 'solid' && bg.start) {
42
+ vars['--ah-page-bg'] = bg.start;
43
+ }
44
+ else if (bg.type === 'gradient' && bg.start && bg.end) {
45
+ const angle = bg.angle_deg ?? 180;
46
+ vars['--ah-page-bg'] = `linear-gradient(${angle}deg, ${bg.start}, ${bg.end})`;
47
+ }
48
+ }
49
+ // Logo URL (stored for reference, used via prop)
50
+ if (branding.logo_url) {
51
+ vars['--ah-logo-url'] = `url(${branding.logo_url})`;
52
+ }
53
+ // Font URL
54
+ if (branding.font?.url) {
55
+ vars['--ah-font-url'] = branding.font.url;
56
+ }
57
+ return vars;
58
+ }
59
+ /**
60
+ * Convert theme configuration to CSS custom properties
61
+ */
62
+ function themeToCssVars(theme) {
63
+ if (!theme)
64
+ return {};
65
+ const vars = {};
66
+ // Border radii
67
+ if (theme.borders) {
68
+ const b = theme.borders;
69
+ // Widget
70
+ if (b.widget_corner_radius !== undefined) {
71
+ vars['--ah-widget-radius'] = `${b.widget_corner_radius}px`;
72
+ }
73
+ if (b.widget_border_weight !== undefined) {
74
+ vars['--ah-widget-border-width'] = `${b.widget_border_weight}px`;
75
+ }
76
+ if (b.show_widget_shadow === false) {
77
+ vars['--ah-widget-shadow'] = 'none';
78
+ }
79
+ // Buttons
80
+ const btnRadius = styleToRadius(b.buttons_style, b.button_border_radius);
81
+ if (btnRadius) {
82
+ vars['--ah-btn-radius'] = btnRadius;
83
+ }
84
+ if (b.button_border_weight !== undefined) {
85
+ vars['--ah-btn-border-width'] = `${b.button_border_weight}px`;
86
+ }
87
+ // Inputs
88
+ const inputRadius = styleToRadius(b.inputs_style, b.input_border_radius);
89
+ if (inputRadius) {
90
+ vars['--ah-input-radius'] = inputRadius;
91
+ }
92
+ if (b.input_border_weight !== undefined) {
93
+ vars['--ah-input-border-width'] = `${b.input_border_weight}px`;
94
+ }
95
+ }
96
+ // Colors
97
+ if (theme.colors) {
98
+ const c = theme.colors;
99
+ // Primary button
100
+ if (c.primary_button) {
101
+ vars['--ah-color-primary'] = c.primary_button;
102
+ vars['--ah-color-primary-hover'] = c.primary_button;
103
+ }
104
+ if (c.primary_button_label) {
105
+ vars['--ah-btn-primary-text'] = c.primary_button_label;
106
+ }
107
+ // Secondary button
108
+ if (c.secondary_button_border) {
109
+ vars['--ah-btn-secondary-border'] = c.secondary_button_border;
110
+ }
111
+ if (c.secondary_button_label) {
112
+ vars['--ah-btn-secondary-text'] = c.secondary_button_label;
113
+ }
114
+ // Text colors
115
+ if (c.body_text) {
116
+ vars['--ah-color-text'] = c.body_text;
117
+ }
118
+ if (c.header) {
119
+ vars['--ah-color-text-header'] = c.header;
120
+ }
121
+ if (c.input_labels_placeholders) {
122
+ vars['--ah-color-text-label'] = c.input_labels_placeholders;
123
+ vars['--ah-color-text-muted'] = c.input_labels_placeholders;
124
+ }
125
+ if (c.input_filled_text) {
126
+ vars['--ah-color-input-text'] = c.input_filled_text;
127
+ }
128
+ // Backgrounds
129
+ if (c.widget_background) {
130
+ vars['--ah-color-bg'] = c.widget_background;
131
+ }
132
+ if (c.input_background) {
133
+ vars['--ah-color-input-bg'] = c.input_background;
134
+ }
135
+ // Borders
136
+ if (c.widget_border) {
137
+ vars['--ah-widget-border-color'] = c.widget_border;
138
+ }
139
+ if (c.input_border) {
140
+ vars['--ah-color-border'] = c.input_border;
141
+ }
142
+ // Links
143
+ if (c.links_focused_components) {
144
+ vars['--ah-color-link'] = c.links_focused_components;
145
+ }
146
+ // Focus/hover
147
+ if (c.base_focus_color) {
148
+ vars['--ah-color-focus-ring'] = c.base_focus_color;
149
+ }
150
+ if (c.base_hover_color) {
151
+ vars['--ah-color-primary-hover'] = c.base_hover_color;
152
+ }
153
+ // Semantic colors
154
+ if (c.error) {
155
+ vars['--ah-color-error'] = c.error;
156
+ }
157
+ if (c.success) {
158
+ vars['--ah-color-success'] = c.success;
159
+ }
160
+ // Icons
161
+ if (c.icons) {
162
+ vars['--ah-color-icon'] = c.icons;
163
+ }
164
+ }
165
+ // Fonts
166
+ if (theme.fonts) {
167
+ const f = theme.fonts;
168
+ if (f.font_url) {
169
+ vars['--ah-font-url'] = f.font_url;
170
+ }
171
+ if (f.reference_text_size) {
172
+ vars['--ah-font-size-base'] = `${f.reference_text_size}px`;
173
+ }
174
+ if (f.title?.size) {
175
+ vars['--ah-font-size-title'] = `${f.title.size}px`;
176
+ }
177
+ if (f.subtitle?.size) {
178
+ vars['--ah-font-size-subtitle'] = `${f.subtitle.size}px`;
179
+ }
180
+ if (f.body_text?.size) {
181
+ vars['--ah-font-size-body'] = `${f.body_text.size}px`;
182
+ }
183
+ if (f.input_labels?.size) {
184
+ vars['--ah-font-size-label'] = `${f.input_labels.size}px`;
185
+ }
186
+ if (f.buttons_text?.size) {
187
+ vars['--ah-font-size-btn'] = `${f.buttons_text.size}px`;
188
+ }
189
+ if (f.links?.size) {
190
+ vars['--ah-font-size-link'] = `${f.links.size}px`;
191
+ }
192
+ if (f.links_style === 'underlined') {
193
+ vars['--ah-link-decoration'] = 'underline';
194
+ }
195
+ // Font weights
196
+ if (f.title?.bold) {
197
+ vars['--ah-font-weight-title'] = '700';
198
+ }
199
+ if (f.buttons_text?.bold) {
200
+ vars['--ah-font-weight-btn'] = '600';
201
+ }
202
+ }
203
+ // Widget settings
204
+ if (theme.widget) {
205
+ const w = theme.widget;
206
+ if (w.header_text_alignment) {
207
+ vars['--ah-title-align'] = w.header_text_alignment;
208
+ }
209
+ if (w.logo_height) {
210
+ vars['--ah-logo-height'] = `${w.logo_height}px`;
211
+ }
212
+ if (w.logo_position) {
213
+ const positionMap = {
214
+ center: 'center',
215
+ left: 'flex-start',
216
+ right: 'flex-end',
217
+ none: 'none',
218
+ };
219
+ vars['--ah-logo-align'] = positionMap[w.logo_position] ?? 'center';
220
+ }
221
+ }
222
+ // Page background
223
+ if (theme.page_background) {
224
+ const pb = theme.page_background;
225
+ if (pb.background_color) {
226
+ vars['--ah-page-bg'] = pb.background_color;
227
+ }
228
+ if (pb.background_image_url) {
229
+ vars['--ah-page-bg-image'] = `url(${pb.background_image_url})`;
230
+ }
231
+ }
232
+ return vars;
233
+ }
234
+ /**
235
+ * Merge branding and theme into a single CSS variables object
236
+ */
237
+ function mergeThemeVars(branding, theme) {
238
+ return {
239
+ ...brandingToCssVars(branding),
240
+ ...themeToCssVars(theme),
241
+ };
242
+ }
243
+ /**
244
+ * Apply CSS variables to an element's style
245
+ */
246
+ function applyCssVars(element, vars) {
247
+ Object.entries(vars).forEach(([key, value]) => {
248
+ element.style.setProperty(key, value);
249
+ });
250
+ }
251
+
252
+ 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)}`;
253
+
254
+ const AuthheroWidget = class {
255
+ constructor(hostRef) {
256
+ registerInstance(this, hostRef);
257
+ this.formSubmit = createEvent(this, "formSubmit");
258
+ this.buttonClick = createEvent(this, "buttonClick");
259
+ this.linkClick = createEvent(this, "linkClick");
260
+ this.navigate = createEvent(this, "navigate");
261
+ this.flowComplete = createEvent(this, "flowComplete");
262
+ this.flowError = createEvent(this, "flowError");
263
+ this.screenChange = createEvent(this, "screenChange");
264
+ }
265
+ get el() { return getElement(this); }
266
+ /**
267
+ * The UI screen configuration from the server.
268
+ * Can be passed as a JSON string or object.
269
+ * Follows Auth0 Forms component schema.
270
+ */
271
+ screen;
272
+ /**
273
+ * API endpoint to fetch the initial screen from.
274
+ * If provided, the widget will fetch the screen on load.
275
+ */
276
+ apiUrl;
277
+ /**
278
+ * Branding configuration from AuthHero API.
279
+ * Controls logo, primary color, and page background.
280
+ * Can be passed as a JSON string or object.
281
+ */
282
+ branding;
283
+ /**
284
+ * Theme configuration from AuthHero API.
285
+ * Controls colors, borders, fonts, and layout.
286
+ * Can be passed as a JSON string or object.
287
+ */
288
+ theme;
289
+ /**
290
+ * Whether the widget is in a loading state.
291
+ */
292
+ loading = false;
293
+ /**
294
+ * Whether the widget should automatically submit forms to the action URL.
295
+ * When false (default), the widget only emits events and the consuming
296
+ * application handles all HTTP requests.
297
+ * When true, the widget handles form submission and screen updates.
298
+ * @default false
299
+ */
300
+ autoSubmit = false;
301
+ /**
302
+ * Internal parsed screen state.
303
+ */
304
+ _screen;
305
+ /**
306
+ * Internal parsed branding state.
307
+ */
308
+ _branding;
309
+ /**
310
+ * Internal parsed theme state.
311
+ */
312
+ _theme;
313
+ /**
314
+ * Form data collected from inputs.
315
+ */
316
+ formData = {};
317
+ /**
318
+ * Emitted when the form is submitted.
319
+ * The consuming application should handle the submission unless autoSubmit is true.
320
+ */
321
+ formSubmit;
322
+ /**
323
+ * Emitted when a non-submit button is clicked (social login, back, etc.).
324
+ * The consuming application decides what to do based on id/type/value.
325
+ */
326
+ buttonClick;
327
+ /**
328
+ * Emitted when a link is clicked.
329
+ * The consuming application decides how to handle navigation.
330
+ */
331
+ linkClick;
332
+ /**
333
+ * Emitted when the widget wants to navigate (e.g., after successful auth).
334
+ * The consuming application decides how to handle navigation.
335
+ */
336
+ navigate;
337
+ /**
338
+ * Emitted when auth flow completes with a redirect URL.
339
+ * The consuming application can redirect or extract the code.
340
+ */
341
+ flowComplete;
342
+ /**
343
+ * Emitted when an error occurs.
344
+ */
345
+ flowError;
346
+ /**
347
+ * Emitted when the screen changes.
348
+ */
349
+ screenChange;
350
+ watchScreen(newValue) {
351
+ if (typeof newValue === 'string') {
352
+ try {
353
+ this._screen = JSON.parse(newValue);
354
+ }
355
+ catch {
356
+ console.error('Failed to parse screen JSON');
357
+ }
358
+ }
359
+ else {
360
+ this._screen = newValue;
361
+ }
362
+ if (this._screen) {
363
+ this.screenChange.emit(this._screen);
364
+ }
365
+ }
366
+ watchBranding(newValue) {
367
+ if (typeof newValue === 'string') {
368
+ try {
369
+ this._branding = JSON.parse(newValue);
370
+ }
371
+ catch {
372
+ console.error('Failed to parse branding JSON');
373
+ }
374
+ }
375
+ else {
376
+ this._branding = newValue;
377
+ }
378
+ this.applyThemeStyles();
379
+ }
380
+ watchTheme(newValue) {
381
+ if (typeof newValue === 'string') {
382
+ try {
383
+ this._theme = JSON.parse(newValue);
384
+ }
385
+ catch {
386
+ console.error('Failed to parse theme JSON');
387
+ }
388
+ }
389
+ else {
390
+ this._theme = newValue;
391
+ }
392
+ this.applyThemeStyles();
393
+ }
394
+ /**
395
+ * Apply branding and theme as CSS custom properties
396
+ */
397
+ applyThemeStyles() {
398
+ const vars = mergeThemeVars(this._branding, this._theme);
399
+ applyCssVars(this.el, vars);
400
+ }
401
+ async componentWillLoad() {
402
+ // Parse initial props
403
+ this.watchScreen(this.screen);
404
+ this.watchBranding(this.branding);
405
+ this.watchTheme(this.theme);
406
+ // Fetch screen from API if URL provided and no screen prop
407
+ if (this.apiUrl && !this._screen) {
408
+ await this.fetchScreen();
409
+ }
410
+ }
411
+ async fetchScreen() {
412
+ if (!this.apiUrl)
413
+ return;
414
+ this.loading = true;
415
+ try {
416
+ const response = await fetch(this.apiUrl, {
417
+ credentials: 'include',
418
+ headers: {
419
+ Accept: 'application/json',
420
+ },
421
+ });
422
+ if (response.ok) {
423
+ this._screen = await response.json();
424
+ if (this._screen) {
425
+ this.screenChange.emit(this._screen);
426
+ }
427
+ }
428
+ }
429
+ catch (error) {
430
+ console.error('Failed to fetch screen:', error);
431
+ }
432
+ finally {
433
+ this.loading = false;
434
+ }
435
+ }
436
+ handleInputChange = (name, value) => {
437
+ this.formData = {
438
+ ...this.formData,
439
+ [name]: value,
440
+ };
441
+ };
442
+ handleSubmit = async (e) => {
443
+ e.preventDefault();
444
+ if (!this._screen)
445
+ return;
446
+ // Always emit the submit event
447
+ this.formSubmit.emit({
448
+ screen: this._screen,
449
+ data: this.formData,
450
+ });
451
+ // If autoSubmit is disabled, let the consuming app handle it
452
+ if (!this.autoSubmit) {
453
+ return;
454
+ }
455
+ // Submit to the server
456
+ this.loading = true;
457
+ try {
458
+ const response = await fetch(this._screen.action, {
459
+ method: this._screen.method,
460
+ credentials: 'include',
461
+ headers: {
462
+ 'Content-Type': 'application/json',
463
+ Accept: 'application/json',
464
+ },
465
+ body: JSON.stringify({ data: this.formData }),
466
+ });
467
+ const contentType = response.headers.get('content-type');
468
+ if (contentType?.includes('application/json')) {
469
+ const result = await response.json();
470
+ // Handle different response types
471
+ if (result.redirect) {
472
+ // Auth complete - emit complete event
473
+ this.flowComplete.emit({ redirectUrl: result.redirect });
474
+ // Also emit navigate for backwards compatibility
475
+ this.navigate.emit({ url: result.redirect });
476
+ }
477
+ else if (result.screen) {
478
+ // Next screen
479
+ this._screen = result.screen;
480
+ this.formData = {};
481
+ this.screenChange.emit(result.screen);
482
+ // Apply branding if included
483
+ if (result.branding) {
484
+ this._branding = result.branding;
485
+ this.applyThemeStyles();
486
+ }
487
+ }
488
+ else if (result.complete) {
489
+ // Flow complete without redirect
490
+ this.flowComplete.emit({});
491
+ }
492
+ // Handle validation errors (400 response)
493
+ if (!response.ok && result.screen) {
494
+ this._screen = result.screen;
495
+ this.screenChange.emit(result.screen);
496
+ }
497
+ }
498
+ }
499
+ catch (err) {
500
+ console.error('Form submission failed:', err);
501
+ this.flowError.emit({
502
+ message: err instanceof Error ? err.message : 'Form submission failed',
503
+ });
504
+ }
505
+ finally {
506
+ this.loading = false;
507
+ }
508
+ };
509
+ handleButtonClick = (detail) => {
510
+ this.buttonClick.emit(detail);
511
+ };
512
+ handleLinkClick = (e, link) => {
513
+ // Emit the event so the consuming app can handle it
514
+ this.linkClick.emit({
515
+ id: link.id,
516
+ href: link.href,
517
+ text: link.text,
518
+ });
519
+ // If autoSubmit is enabled, let the browser handle the navigation
520
+ // Otherwise, prevent default and let the app decide
521
+ if (!this.autoSubmit) {
522
+ e.preventDefault();
523
+ }
524
+ };
525
+ /**
526
+ * Get error messages from the screen-level messages array.
527
+ */
528
+ getScreenErrors() {
529
+ return this._screen?.messages?.filter((m) => m.type === 'error') || [];
530
+ }
531
+ /**
532
+ * Get success messages from the screen-level messages array.
533
+ */
534
+ getScreenSuccesses() {
535
+ return this._screen?.messages?.filter((m) => m.type === 'success') || [];
536
+ }
537
+ /**
538
+ * Sort components by order.
539
+ */
540
+ getOrderedComponents() {
541
+ if (!this._screen)
542
+ return [];
543
+ return [...this._screen.components]
544
+ .filter((c) => c.visible !== false)
545
+ .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
546
+ }
547
+ render() {
548
+ if (this.loading && !this._screen) {
549
+ return (h("div", { class: "widget-container" }, h("div", { class: "loading-spinner" })));
550
+ }
551
+ if (!this._screen) {
552
+ return (h("div", { class: "widget-container" }, h("div", { class: "error-message" }, "No screen configuration provided")));
553
+ }
554
+ const screenErrors = this.getScreenErrors();
555
+ const screenSuccesses = this.getScreenSuccesses();
556
+ const components = this.getOrderedComponents();
557
+ // Get logo URL from branding props
558
+ const logoUrl = this._branding?.logo_url;
559
+ return (h("div", { class: "widget-container", part: "container" }, logoUrl && h("img", { class: "logo", part: "logo", src: logoUrl, alt: "Logo" }), this._screen.title && (h("h1", { class: "title", part: "title" }, this._screen.title)), this._screen.description && (h("p", { class: "description", part: "description" }, this._screen.description)), screenErrors.map((err) => (h("div", { class: "message message-error", part: "message message-error", key: err.id ?? err.text }, err.text))), screenSuccesses.map((msg) => (h("div", { class: "message message-success", part: "message message-success", key: msg.id ?? msg.text }, msg.text))), h("form", { onSubmit: this.handleSubmit, part: "form" }, components.map((component) => (h("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 && (h("div", { class: "links", part: "links" }, this._screen.links.map((link) => (h("span", { class: "link-wrapper", part: "link-wrapper", key: link.id ?? link.href }, link.linkText ? (h("span", null, link.text, ' ', h("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))) : (h("a", { href: link.href, class: "link", part: "link", onClick: (e) => this.handleLinkClick(e, { id: link.id, href: link.href, text: link.text }) }, link.text)))))))));
560
+ }
561
+ static get watchers() { return {
562
+ "screen": [{
563
+ "watchScreen": 0
564
+ }],
565
+ "branding": [{
566
+ "watchBranding": 0
567
+ }],
568
+ "theme": [{
569
+ "watchTheme": 0
570
+ }]
571
+ }; }
572
+ };
573
+ AuthheroWidget.style = authheroWidgetCss();
574
+
575
+ export { AuthheroWidget as authhero_widget };
@@ -0,0 +1,21 @@
1
+ import { p as promiseResolve, b as bootstrapLazy } from './index-Doiemx6o.js';
2
+ export { s as setNonce } from './index-Doiemx6o.js';
3
+ import { g as globalScripts } from './app-globals-DQuL1Twl.js';
4
+
5
+ /*
6
+ Stencil Client Patch Browser v4.41.0 | MIT Licensed | https://stenciljs.com
7
+ */
8
+
9
+ var patchBrowser = () => {
10
+ const importMeta = import.meta.url;
11
+ const opts = {};
12
+ if (importMeta !== "") {
13
+ opts.resourcesUrl = new URL(".", importMeta).href;
14
+ }
15
+ return promiseResolve(opts);
16
+ };
17
+
18
+ patchBrowser().then(async (options) => {
19
+ await globalScripts();
20
+ return bootstrapLazy([["authhero-node",[[513,"authhero-node",{"component":[16],"value":[1],"disabled":[4]}]]],["authhero-widget",[[513,"authhero-widget",{"screen":[1],"apiUrl":[1,"api-url"],"branding":[1],"theme":[1],"loading":[1028],"autoSubmit":[4,"auto-submit"],"_screen":[32],"_branding":[32],"_theme":[32],"formData":[32]},null,{"screen":[{"watchScreen":0}],"branding":[{"watchBranding":0}],"theme":[{"watchTheme":0}]}]]]], options);
21
+ });