@authhero/widget 0.37.1 → 0.38.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 (32) hide show
  1. package/dist/authhero-widget/authhero-widget.esm.js +1 -1
  2. package/dist/authhero-widget/index.esm.js +1 -1
  3. package/dist/authhero-widget/p-b5f14fa6.entry.js +1 -0
  4. package/dist/authhero-widget/p-f94037cd.entry.js +1 -0
  5. package/dist/cjs/authhero-node.cjs.entry.js +458 -13
  6. package/dist/cjs/authhero-widget.cjs.entry.js +79 -10
  7. package/dist/cjs/authhero-widget.cjs.js +1 -1
  8. package/dist/cjs/index.cjs.js +1 -1
  9. package/dist/cjs/loader.cjs.js +1 -1
  10. package/dist/collection/components/authhero-node/authhero-node.css +94 -0
  11. package/dist/collection/components/authhero-node/authhero-node.js +302 -13
  12. package/dist/collection/components/authhero-widget/authhero-widget.js +98 -10
  13. package/dist/collection/utils/date-format.js +176 -0
  14. package/dist/components/authhero-node.js +1 -1
  15. package/dist/components/authhero-widget.js +1 -1
  16. package/dist/components/index.js +1 -1
  17. package/dist/components/p-C9ZfIQiS.js +1 -0
  18. package/dist/esm/authhero-node.entry.js +458 -13
  19. package/dist/esm/authhero-widget.entry.js +79 -10
  20. package/dist/esm/authhero-widget.js +1 -1
  21. package/dist/esm/index.js +1 -1
  22. package/dist/esm/loader.js +1 -1
  23. package/dist/types/components/authhero-node/authhero-node.d.ts +83 -0
  24. package/dist/types/components/authhero-widget/authhero-widget.d.ts +19 -0
  25. package/dist/types/components.d.ts +18 -0
  26. package/dist/types/utils/date-format.d.ts +52 -0
  27. package/hydrate/index.js +541 -24
  28. package/hydrate/index.mjs +541 -24
  29. package/package.json +2 -2
  30. package/dist/authhero-widget/p-cdfc4555.entry.js +0 -1
  31. package/dist/authhero-widget/p-e95c436f.entry.js +0 -1
  32. package/dist/components/p-BP46GHTc.js +0 -1
@@ -1,6 +1,7 @@
1
1
  import { EventEmitter } from "../../stencil-public-runtime";
2
2
  import type { FormComponent, RuntimeComponent } from "../../types/components";
3
3
  import { type CountryData } from "../../utils/country-data";
4
+ import { type DateSegment } from "../../utils/date-format";
4
5
  export declare class AuthheroNode {
5
6
  /**
6
7
  * The component configuration to render.
@@ -16,6 +17,12 @@ export declare class AuthheroNode {
16
17
  * Whether the component is disabled.
17
18
  */
18
19
  disabled: boolean;
20
+ /**
21
+ * BCP-47 locale used for locale-dependent field layout (currently the
22
+ * segment order of DATE fields). Resolved server-side so SSR and hydration
23
+ * agree; falls back to day-month-year when absent.
24
+ */
25
+ locale?: string;
19
26
  /**
20
27
  * Whether the password field is visible.
21
28
  */
@@ -37,6 +44,11 @@ export declare class AuthheroNode {
37
44
  * When true, the value is emitted as-is without dial code prefix.
38
45
  */
39
46
  telEmailMode: boolean;
47
+ /**
48
+ * Segment values for the DATE input, each held as typed (unpadded while the
49
+ * user is mid-entry) and normalised on blur.
50
+ */
51
+ dateSegments: Record<DateSegment, string>;
40
52
  /**
41
53
  * Emitted when a field value changes.
42
54
  */
@@ -57,6 +69,17 @@ export declare class AuthheroNode {
57
69
  componentWillLoad(): void;
58
70
  componentDidLoad(): void;
59
71
  private initCountryFromConfig;
72
+ /**
73
+ * The last value this field emitted for a TEL component. The widget mirrors
74
+ * every emitted value back onto the `value` prop, and that echo must not be
75
+ * re-parsed: the wire format carries only a dial code, so a country picked
76
+ * from the list would be replaced by the first entry sharing that code — a
77
+ * user who chose Canada would be silently moved to the US on their next
78
+ * keystroke.
79
+ */
80
+ private lastEmittedTel?;
81
+ /** Emit a TEL value and remember it, so the echo can be recognised. */
82
+ private emitTelValue;
60
83
  /**
61
84
  * Hydrate localPhoneNumber (and selectedCountry) from the effective value
62
85
  * for TEL fields. The full value is stored as `{dialCode}{localNumber}`,
@@ -80,6 +103,59 @@ export declare class AuthheroNode {
80
103
  private processPhoneInput;
81
104
  private handlePhoneInput;
82
105
  private handleInput;
106
+ /**
107
+ * The last ISO value this field emitted. The widget mirrors every emitted
108
+ * value back onto the `value` prop, and that echo must not be treated as an
109
+ * external change: it would re-format the segments under the caret while
110
+ * the user is still typing (a day of "3" comes back as "03", swallowing the
111
+ * next digit).
112
+ */
113
+ private lastEmittedDate?;
114
+ /** Hydrate the day/month/year segments from the effective ISO value. */
115
+ private initDateValue;
116
+ private dateConfig;
117
+ private getDateLayoutForField;
118
+ private static readonly SEGMENT_LENGTH;
119
+ /** Birthdate autofill tokens — the common case for a typed date. */
120
+ private static readonly SEGMENT_AUTOCOMPLETE;
121
+ /**
122
+ * The submittable value for the current segments: an ISO date, or "" when
123
+ * it is incomplete, impossible, or outside the field's `min`/`max`. ISO
124
+ * strings compare chronologically, so the bounds need no parsing.
125
+ */
126
+ private dateIsoValue;
127
+ private setDateSegments;
128
+ private focusDateSegment;
129
+ /**
130
+ * Whether typing this digit completes the segment. A segment is complete at
131
+ * its full width, and also as soon as a further digit could not produce a
132
+ * valid number — no day starts with 4 and no month starts with 2.
133
+ */
134
+ private isDateSegmentComplete;
135
+ private handleDateSegmentInput;
136
+ /**
137
+ * Pad a single digit ("5" -> "05") and expand a two-digit year against the
138
+ * field's upper bound ("85" -> 1985). Shared by blur and paste so a pasted
139
+ * date is read the same way as a typed one.
140
+ */
141
+ private normalizeDateSegment;
142
+ /**
143
+ * Normalise on blur: pad a single digit ("5" -> "05") and expand a two-digit
144
+ * year against the field's upper bound ("85" -> 1985).
145
+ */
146
+ private handleDateSegmentBlur;
147
+ /**
148
+ * Backspace at the start of an empty segment moves to the previous one, so
149
+ * the whole date can be cleared without reaching for the mouse.
150
+ */
151
+ private handleDateSegmentKeyDown;
152
+ /**
153
+ * Pasting a whole date into any segment fills all three. An ISO value is
154
+ * read year-first; anything else follows the field's displayed order. A
155
+ * two-digit year is expanded the same way a typed one is, so "15/03/85"
156
+ * pastes as 1985 rather than falling through to the browser's own paste.
157
+ */
158
+ private handleDatePaste;
83
159
  private handleKeyDown;
84
160
  private handleCodeInput;
85
161
  private handleCheckbox;
@@ -153,6 +229,13 @@ export declare class AuthheroNode {
153
229
  private renderNumberField;
154
230
  private renderTelField;
155
231
  private renderUrlField;
232
+ /**
233
+ * DATE is rendered as three numeric segments rather than `input type=date`.
234
+ * A native date input renders differently in every browser (Safari adds a
235
+ * stepper), keeps its dd/mm/yyyy hint visible while half-filled, and asks
236
+ * for a calendar gesture to reach a year decades back — all wrong for a
237
+ * date typed from memory, which is what these fields collect.
238
+ */
156
239
  private renderDateField;
157
240
  private renderBooleanField;
158
241
  private renderLegalField;
@@ -153,6 +153,13 @@ export declare class AuthheroWidget {
153
153
  * @default false (same as autoSubmit when not specified)
154
154
  */
155
155
  autoNavigate?: boolean;
156
+ /**
157
+ * BCP-47 locale for locale-dependent field layout, e.g. whether a DATE
158
+ * field reads DD/MM/YYYY, MM/DD/YYYY or YYYY-MM-DD. Resolve it server-side
159
+ * and pass it in so the server-rendered markup and the hydrated one agree;
160
+ * screen text itself is already localized by the server.
161
+ */
162
+ locale?: string;
156
163
  /**
157
164
  * Internal parsed screen state.
158
165
  */
@@ -385,6 +392,18 @@ export declare class AuthheroWidget {
385
392
  * Check if a component is a divider.
386
393
  */
387
394
  private isDividerComponent;
395
+ /**
396
+ * Whether a required component holds a value the user has supplied.
397
+ */
398
+ private isRequiredFieldFilled;
399
+ /**
400
+ * Whether the screen still has required fields the user has not filled in.
401
+ * Used to hold the primary action button disabled: the widget submits via
402
+ * its own handler rather than a native form submit, so the browser's
403
+ * constraint validation never runs and an empty required field would
404
+ * otherwise only surface as a server error after a round trip.
405
+ */
406
+ private hasUnfilledRequiredFields;
388
407
  /**
389
408
  * Visible label of a choice button, used to filter searchable choice lists.
390
409
  */
@@ -19,6 +19,10 @@ export namespace Components {
19
19
  * @default false
20
20
  */
21
21
  "disabled": boolean;
22
+ /**
23
+ * BCP-47 locale used for locale-dependent field layout (currently the segment order of DATE fields). Resolved server-side so SSR and hydration agree; falls back to day-month-year when absent.
24
+ */
25
+ "locale"?: string;
22
26
  /**
23
27
  * Current value for field components.
24
28
  */
@@ -56,6 +60,10 @@ export namespace Components {
56
60
  * @default false
57
61
  */
58
62
  "loading": boolean;
63
+ /**
64
+ * BCP-47 locale for locale-dependent field layout, e.g. whether a DATE field reads DD/MM/YYYY, MM/DD/YYYY or YYYY-MM-DD. Resolve it server-side and pass it in so the server-rendered markup and the hydrated one agree; screen text itself is already localized by the server.
65
+ */
66
+ "locale"?: string;
59
67
  /**
60
68
  * The UI screen configuration from the server. Can be passed as a JSON string or object. Follows Auth0 Forms component schema.
61
69
  */
@@ -151,6 +159,10 @@ declare namespace LocalJSX {
151
159
  * @default false
152
160
  */
153
161
  "disabled"?: boolean;
162
+ /**
163
+ * BCP-47 locale used for locale-dependent field layout (currently the segment order of DATE fields). Resolved server-side so SSR and hydration agree; falls back to day-month-year when absent.
164
+ */
165
+ "locale"?: string;
154
166
  /**
155
167
  * Emitted when a button is clicked.
156
168
  */
@@ -200,6 +212,10 @@ declare namespace LocalJSX {
200
212
  * @default false
201
213
  */
202
214
  "loading"?: boolean;
215
+ /**
216
+ * BCP-47 locale for locale-dependent field layout, e.g. whether a DATE field reads DD/MM/YYYY, MM/DD/YYYY or YYYY-MM-DD. Resolve it server-side and pass it in so the server-rendered markup and the hydrated one agree; screen text itself is already localized by the server.
217
+ */
218
+ "locale"?: string;
203
219
  /**
204
220
  * Emitted when a non-submit button is clicked (social login, back, etc.). The consuming application decides what to do based on id/type/value.
205
221
  */
@@ -259,6 +275,7 @@ declare namespace LocalJSX {
259
275
  interface AuthheroNodeAttributes {
260
276
  "value": string;
261
277
  "disabled": boolean;
278
+ "locale": string;
262
279
  }
263
280
  interface AuthheroWidgetAttributes {
264
281
  "screen": UiScreen | string;
@@ -274,6 +291,7 @@ declare namespace LocalJSX {
274
291
  "loading": boolean;
275
292
  "autoSubmit": boolean;
276
293
  "autoNavigate": boolean;
294
+ "locale": string;
277
295
  }
278
296
 
279
297
  interface IntrinsicElements {
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Locale-aware layout for the segmented DATE input.
3
+ *
4
+ * The segment order is resolved from a static table rather than from
5
+ * `Intl.DateTimeFormat`, deliberately: the widget is server-rendered and then
6
+ * hydrated in the browser, and the two runtimes do not ship the same ICU data
7
+ * (a Workers runtime commonly falls back to en-US ordering). A static table
8
+ * gives the server and the client the same answer, so the hydrated DOM matches
9
+ * the rendered one.
10
+ */
11
+ export type DateSegment = "year" | "month" | "day";
12
+ export interface DateLayout {
13
+ /** Segment order, left to right. */
14
+ order: DateSegment[];
15
+ /** Placeholder token per segment, e.g. { day: "DD", ... }. */
16
+ tokens: Record<DateSegment, string>;
17
+ /** Character drawn between segments. */
18
+ separator: string;
19
+ }
20
+ /**
21
+ * Resolve the segment order for a locale. Falls back to day-month-year, which
22
+ * is what most of the world writes.
23
+ */
24
+ export declare function getDateOrder(locale?: string): DateSegment[];
25
+ /**
26
+ * Resolve the full layout for a DATE field. An explicit `config.format` wins;
27
+ * otherwise the locale decides the order.
28
+ */
29
+ export declare function getDateLayout(format?: string, locale?: string): DateLayout;
30
+ /** Number of days in a given month, honouring leap years. */
31
+ export declare function daysInMonth(year: number, month: number): number;
32
+ /** Split an ISO "YYYY-MM-DD" value into its segments. */
33
+ export declare function parseIsoDate(value: string | undefined): Record<DateSegment, string> | null;
34
+ /**
35
+ * Build an ISO "YYYY-MM-DD" string from segment values. Returns "" unless all
36
+ * three segments are complete and form a real calendar date — a half-filled or
37
+ * impossible date (31 February) is not a value worth submitting.
38
+ */
39
+ export declare function toIsoDate(segments: Record<DateSegment, string>): string;
40
+ /**
41
+ * Expand a two-digit year into the most recent matching year at or before
42
+ * `anchorYear` — "85" becomes 1985, "05" becomes 2005. Anything that is not
43
+ * exactly two digits is returned unchanged, so a fully typed year is never
44
+ * second-guessed.
45
+ */
46
+ export declare function expandTwoDigitYear(year: string, anchorYear: number): string;
47
+ /**
48
+ * The latest year a two-digit entry may expand to. `config.max` pins it when
49
+ * the field has an upper bound; otherwise we assume a date in the past (the
50
+ * birthdate case) and anchor on the current year.
51
+ */
52
+ export declare function resolveYearAnchor(max: string | undefined, today: Date): number;