@alfadocs/ui-kit-debug 1.54.1 → 1.54.2

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.
@@ -1,6 +1,22 @@
1
- import { jsx as r, jsxs as t, Fragment as a } from "react/jsx-runtime";
2
- import { useRef as w, useState as N, useEffect as $ } from "react";
3
- import { M as s, A as x, P as l, C as W } from "./mark-pieces-m_rn1mAc.js";
1
+ import { jsx as r, jsxs as t, Fragment as i } from "react/jsx-runtime";
2
+ import { useRef as L, useState as N, useEffect as $ } from "react";
3
+ import { M as s, A as x, P as l, C as E } from "./mark-pieces-m_rn1mAc.js";
4
+ const rr = [
5
+ "jumbled",
6
+ "locked",
7
+ "roped",
8
+ "lost",
9
+ "wrong-way",
10
+ "vanished",
11
+ "asleep",
12
+ "patched",
13
+ "melt",
14
+ "unplugged",
15
+ "rebuild",
16
+ "snail",
17
+ "adrift",
18
+ "puzzled"
19
+ ];
4
20
  function h({ name: n }) {
5
21
  return /* @__PURE__ */ r(
6
22
  l,
@@ -27,24 +43,24 @@ function c({ cx: n = 74, rx: e = 46 }) {
27
43
  }
28
44
  );
29
45
  }
30
- const E = "ds:[transform-box:fill-box] ds:origin-top ds:motion-safe:animate-[error-page-drip_calc(var(--animation-duration)*15)_ease-in-out_1]", O = "ds:motion-safe:animate-[error-page-drop_calc(var(--animation-duration)*12)_ease-in_2]", y = "ds:[transform-box:fill-box] ds:origin-bottom ds:motion-safe:animate-[error-page-rock_calc(var(--animation-duration)*20)_ease-in-out_1]", b = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-bob_calc(var(--animation-duration)*14)_ease-in-out_1]", v = "ds:[transform-box:fill-box] ds:origin-top ds:motion-safe:animate-[error-page-swing_calc(var(--animation-duration)*18)_ease-in-out_1]", R = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-wiggle_calc(var(--animation-duration)*10)_ease-in-out_2]", _ = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-rise_calc(var(--animation-duration)*16)_ease-out_1]", M = "ds:motion-safe:animate-[error-page-flicker_calc(var(--animation-duration)*6)_steps(1)_4]", P = "ds:motion-safe:animate-[error-page-crawl_calc(var(--animation-duration)*24)_ease-in-out_1]", A = "ds:motion-safe:animate-[error-page-bump_calc(var(--animation-duration)*12)_ease-in-out_2]", L = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-breathe_calc(var(--animation-duration)*20)_ease-in-out_1]", u = "ds:[animation-delay:calc(var(--animation-duration)*5)]", m = "ds:[animation-delay:calc(var(--animation-duration)*9)]", j = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-pop_calc(var(--animation-duration)*3)_ease-out_1]";
31
- function I() {
46
+ const O = "ds:[transform-box:fill-box] ds:origin-top ds:motion-safe:animate-[error-page-drip_calc(var(--animation-duration)*15)_ease-in-out_1]", W = "ds:motion-safe:animate-[error-page-drop_calc(var(--animation-duration)*12)_ease-in_2]", y = "ds:[transform-box:fill-box] ds:origin-bottom ds:motion-safe:animate-[error-page-rock_calc(var(--animation-duration)*20)_ease-in-out_1]", b = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-bob_calc(var(--animation-duration)*14)_ease-in-out_1]", v = "ds:[transform-box:fill-box] ds:origin-top ds:motion-safe:animate-[error-page-swing_calc(var(--animation-duration)*18)_ease-in-out_1]", R = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-wiggle_calc(var(--animation-duration)*10)_ease-in-out_2]", _ = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-rise_calc(var(--animation-duration)*16)_ease-out_1]", M = "ds:motion-safe:animate-[error-page-flicker_calc(var(--animation-duration)*6)_steps(1)_4]", P = "ds:motion-safe:animate-[error-page-crawl_calc(var(--animation-duration)*24)_ease-in-out_1]", A = "ds:motion-safe:animate-[error-page-bump_calc(var(--animation-duration)*12)_ease-in-out_2]", w = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-breathe_calc(var(--animation-duration)*20)_ease-in-out_1]", u = "ds:[animation-delay:calc(var(--animation-duration)*5)]", m = "ds:[animation-delay:calc(var(--animation-duration)*9)]", j = "ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-pop_calc(var(--animation-duration)*3)_ease-out_1]";
47
+ function S() {
32
48
  const n = {
33
49
  top: 75,
34
50
  right: -60,
35
51
  left: 40,
36
52
  bottom: -95
37
53
  };
38
- return /* @__PURE__ */ t(a, { children: [
39
- x.map((e, o) => {
40
- const [i, d] = W[e];
41
- return /* @__PURE__ */ r("g", { transform: `rotate(${n[e]} ${i} ${d})`, children: /* @__PURE__ */ r("g", { className: `${R} ${o % 2 ? u : ""}`, children: /* @__PURE__ */ r(l, { name: e }) }) }, e);
54
+ return /* @__PURE__ */ t(i, { children: [
55
+ x.map((e, a) => {
56
+ const [o, d] = E[e];
57
+ return /* @__PURE__ */ r("g", { transform: `rotate(${n[e]} ${o} ${d})`, children: /* @__PURE__ */ r("g", { className: `${R} ${a % 2 ? u : ""}`, children: /* @__PURE__ */ r(l, { name: e }) }) }, e);
42
58
  }),
43
59
  /* @__PURE__ */ r(c, {})
44
60
  ] });
45
61
  }
46
- function S() {
47
- return /* @__PURE__ */ t(a, { children: [
62
+ function D() {
63
+ return /* @__PURE__ */ t(i, { children: [
48
64
  /* @__PURE__ */ r(s, {}),
49
65
  /* @__PURE__ */ t("g", { className: v, children: [
50
66
  /* @__PURE__ */ r(
@@ -84,13 +100,13 @@ function S() {
84
100
  /* @__PURE__ */ r(c, {})
85
101
  ] });
86
102
  }
87
- function T() {
103
+ function I() {
88
104
  const n = (e) => /* @__PURE__ */ t("g", { fill: "var(--muted-foreground)", children: [
89
105
  /* @__PURE__ */ r("rect", { x: e - 3, y: "158", width: "6", height: "48", rx: "3" }),
90
106
  /* @__PURE__ */ r("circle", { cx: e, cy: "157", r: "6" }),
91
107
  /* @__PURE__ */ r("rect", { x: e - 11, y: "202", width: "22", height: "5", rx: "2.5" })
92
108
  ] });
93
- return /* @__PURE__ */ t(a, { children: [
109
+ return /* @__PURE__ */ t(i, { children: [
94
110
  /* @__PURE__ */ r(s, {}),
95
111
  n(8),
96
112
  n(140),
@@ -106,8 +122,8 @@ function T() {
106
122
  ) })
107
123
  ] });
108
124
  }
109
- function D() {
110
- return /* @__PURE__ */ t(a, { children: [
125
+ function T() {
126
+ return /* @__PURE__ */ t(i, { children: [
111
127
  /* @__PURE__ */ r(s, { except: ["right"] }),
112
128
  /* @__PURE__ */ r(h, { name: "right" }),
113
129
  /* @__PURE__ */ r(c, { cx: 150, rx: 28 }),
@@ -125,7 +141,7 @@ function D() {
125
141
  ] });
126
142
  }
127
143
  function B() {
128
- return /* @__PURE__ */ t(a, { children: [
144
+ return /* @__PURE__ */ t(i, { children: [
129
145
  /* @__PURE__ */ r(s, { except: ["right"] }),
130
146
  /* @__PURE__ */ r(h, { name: "right" }),
131
147
  /* @__PURE__ */ r("g", { className: A, children: /* @__PURE__ */ r("g", { transform: "translate(40 0) rotate(90 121 70)", children: /* @__PURE__ */ r(l, { name: "right" }) }) }),
@@ -140,28 +156,28 @@ function C() {
140
156
  [62, 118, u],
141
157
  [20, 96, m]
142
158
  ];
143
- return /* @__PURE__ */ t(a, { children: [
159
+ return /* @__PURE__ */ t(i, { children: [
144
160
  x.map((e) => /* @__PURE__ */ r(h, { name: e }, e)),
145
- n.map(([e, o, i]) => /* @__PURE__ */ r(
161
+ n.map(([e, a, o]) => /* @__PURE__ */ r(
146
162
  "rect",
147
163
  {
148
164
  x: e,
149
- y: o,
165
+ y: a,
150
166
  width: "6",
151
167
  height: "6",
152
168
  rx: "1.5",
153
- className: `${_} ${i}`
169
+ className: `${_} ${o}`
154
170
  },
155
- `${e}-${o}`
171
+ `${e}-${a}`
156
172
  )),
157
173
  /* @__PURE__ */ r(c, {})
158
174
  ] });
159
175
  }
160
176
  function F() {
161
- const n = (e, o, i, d) => /* @__PURE__ */ r(
177
+ const n = (e, a, o, d) => /* @__PURE__ */ r(
162
178
  "path",
163
179
  {
164
- d: `M${e} ${o} h${i} l-${i} ${i} h${i}`,
180
+ d: `M${e} ${a} h${o} l-${o} ${o} h${o}`,
165
181
  fill: "none",
166
182
  stroke: "var(--muted-foreground)",
167
183
  strokeWidth: "3",
@@ -170,8 +186,8 @@ function F() {
170
186
  className: `${_} ${d}`
171
187
  }
172
188
  );
173
- return /* @__PURE__ */ t(a, { children: [
174
- /* @__PURE__ */ r("g", { transform: "rotate(14 74 74)", children: /* @__PURE__ */ r("g", { className: L, children: /* @__PURE__ */ r(s, {}) }) }),
189
+ return /* @__PURE__ */ t(i, { children: [
190
+ /* @__PURE__ */ r("g", { transform: "rotate(14 74 74)", children: /* @__PURE__ */ r("g", { className: w, children: /* @__PURE__ */ r(s, {}) }) }),
175
191
  n(122, 22, 10, ""),
176
192
  n(140, 2, 13, u),
177
193
  n(160, -16, 16, m),
@@ -179,8 +195,8 @@ function F() {
179
195
  ] });
180
196
  }
181
197
  function G() {
182
- return /* @__PURE__ */ t(a, { children: [
183
- /* @__PURE__ */ t("g", { className: L, children: [
198
+ return /* @__PURE__ */ t(i, { children: [
199
+ /* @__PURE__ */ t("g", { className: w, children: [
184
200
  /* @__PURE__ */ r(s, {}),
185
201
  /* @__PURE__ */ r(
186
202
  "polyline",
@@ -232,27 +248,27 @@ function G() {
232
248
  function p({
233
249
  cx: n,
234
250
  top: e,
235
- length: o,
236
- className: i = ""
251
+ length: a,
252
+ className: o = ""
237
253
  }) {
238
- return /* @__PURE__ */ t("g", { className: `${E} ${i}`, children: [
239
- /* @__PURE__ */ r("rect", { x: n - 3.5, y: e, width: "7", height: o, rx: "3.5" }),
240
- /* @__PURE__ */ r("circle", { cx: n, cy: e + o, r: "4.2" })
254
+ return /* @__PURE__ */ t("g", { className: `${O} ${o}`, children: [
255
+ /* @__PURE__ */ r("rect", { x: n - 3.5, y: e, width: "7", height: a, rx: "3.5" }),
256
+ /* @__PURE__ */ r("circle", { cx: n, cy: e + a, r: "4.2" })
241
257
  ] });
242
258
  }
243
- function Q() {
244
- return /* @__PURE__ */ t(a, { children: [
259
+ function z() {
260
+ return /* @__PURE__ */ t(i, { children: [
245
261
  /* @__PURE__ */ r(s, {}),
246
262
  /* @__PURE__ */ r("path", { d: "M67 139 L99 131 L101 138 Q92 151 80 152 Q70 153 68 143 Z" }),
247
263
  /* @__PURE__ */ r(p, { cx: 75, top: 144, length: 20, className: u }),
248
264
  /* @__PURE__ */ r(p, { cx: 85.5, top: 141, length: 32 }),
249
265
  /* @__PURE__ */ r(p, { cx: 96, top: 137, length: 13, className: m }),
250
- /* @__PURE__ */ r("circle", { cx: "85.5", cy: "179", r: "3.2", className: O }),
266
+ /* @__PURE__ */ r("circle", { cx: "85.5", cy: "179", r: "3.2", className: W }),
251
267
  /* @__PURE__ */ r("ellipse", { cx: "86", cy: "204", rx: "30", ry: "5.5", fillOpacity: "0.3" })
252
268
  ] });
253
269
  }
254
- function z() {
255
- return /* @__PURE__ */ t(a, { children: [
270
+ function Q() {
271
+ return /* @__PURE__ */ t(i, { children: [
256
272
  /* @__PURE__ */ t("g", { transform: "translate(-12 -8)", children: [
257
273
  /* @__PURE__ */ r(l, { name: "top" }),
258
274
  /* @__PURE__ */ r(l, { name: "left" })
@@ -277,7 +293,7 @@ function z() {
277
293
  ] });
278
294
  }
279
295
  function K() {
280
- return /* @__PURE__ */ t(a, { children: [
296
+ return /* @__PURE__ */ t(i, { children: [
281
297
  /* @__PURE__ */ r(s, { except: ["right"] }),
282
298
  /* @__PURE__ */ r(h, { name: "right" }),
283
299
  /* @__PURE__ */ t("g", { className: v, children: [
@@ -309,7 +325,7 @@ function K() {
309
325
  ] });
310
326
  }
311
327
  function U() {
312
- return /* @__PURE__ */ t(a, { children: [
328
+ return /* @__PURE__ */ t(i, { children: [
313
329
  /* @__PURE__ */ r(s, { except: ["right"] }),
314
330
  /* @__PURE__ */ r(h, { name: "right" }),
315
331
  /* @__PURE__ */ r(c, { cx: 140, rx: 34 }),
@@ -373,16 +389,16 @@ function H() {
373
389
  left: [-14, 0, m],
374
390
  bottom: [0, 14, u]
375
391
  };
376
- return /* @__PURE__ */ t(a, { children: [
392
+ return /* @__PURE__ */ t(i, { children: [
377
393
  /* @__PURE__ */ r(c, {}),
378
394
  x.map((e) => {
379
- const [o, i, d] = n[e];
380
- return /* @__PURE__ */ r("g", { transform: `translate(${o} ${i})`, children: /* @__PURE__ */ r("g", { className: `${b} ${d}`, children: /* @__PURE__ */ r(l, { name: e }) }) }, e);
395
+ const [a, o, d] = n[e];
396
+ return /* @__PURE__ */ r("g", { transform: `translate(${a} ${o})`, children: /* @__PURE__ */ r("g", { className: `${b} ${d}`, children: /* @__PURE__ */ r(l, { name: e }) }) }, e);
381
397
  })
382
398
  ] });
383
399
  }
384
400
  function J() {
385
- return /* @__PURE__ */ t(a, { children: [
401
+ return /* @__PURE__ */ t(i, { children: [
386
402
  /* @__PURE__ */ r("g", { className: y, children: /* @__PURE__ */ r(s, {}) }),
387
403
  /* @__PURE__ */ t("g", { className: b, children: [
388
404
  /* @__PURE__ */ r(
@@ -402,31 +418,31 @@ function J() {
402
418
  ] });
403
419
  }
404
420
  const V = {
405
- jumbled: I,
406
- locked: S,
407
- roped: T,
408
- lost: D,
421
+ jumbled: S,
422
+ locked: D,
423
+ roped: I,
424
+ lost: T,
409
425
  "wrong-way": B,
410
426
  vanished: C,
411
427
  asleep: F,
412
428
  patched: G,
413
- melt: Q,
414
- unplugged: z,
429
+ melt: z,
430
+ unplugged: Q,
415
431
  rebuild: K,
416
432
  snail: U,
417
433
  adrift: H,
418
434
  puzzled: J
419
435
  }, X = 3e3;
420
- function rr({
436
+ function er({
421
437
  mood: n
422
438
  }) {
423
- const e = w(null), [o, i] = N(!1);
439
+ const e = L(null), [a, o] = N(!1);
424
440
  $(() => {
425
441
  const f = e.current;
426
442
  if (!f) return;
427
443
  let g;
428
444
  const k = () => {
429
- i(!0), clearTimeout(g), g = setTimeout(() => i(!1), X);
445
+ o(!0), clearTimeout(g), g = setTimeout(() => o(!1), X);
430
446
  };
431
447
  return f.addEventListener("click", k), () => {
432
448
  f.removeEventListener("click", k), clearTimeout(g);
@@ -438,7 +454,7 @@ function rr({
438
454
  {
439
455
  ref: e,
440
456
  "aria-hidden": "true",
441
- "data-mood": o ? "fixed" : n,
457
+ "data-mood": a ? "fixed" : n,
442
458
  className: "ds:w-48 ds:select-none",
443
459
  children: /* @__PURE__ */ r(
444
460
  "svg",
@@ -447,13 +463,14 @@ function rr({
447
463
  viewBox: "-20 -24 200 240",
448
464
  fill: "var(--primary)",
449
465
  className: "ds:block ds:w-full ds:h-auto ds:overflow-visible",
450
- children: o ? /* @__PURE__ */ r("g", { className: j, children: /* @__PURE__ */ r(s, {}) }) : /* @__PURE__ */ r(d, {})
466
+ children: a ? /* @__PURE__ */ r("g", { className: j, children: /* @__PURE__ */ r(s, {}) }) : /* @__PURE__ */ r(d, {})
451
467
  }
452
468
  )
453
469
  }
454
470
  );
455
471
  }
456
472
  export {
457
- rr as E
473
+ rr as E,
474
+ er as a
458
475
  };
459
- //# sourceMappingURL=error-page-illustration-QGJAvuFB.js.map
476
+ //# sourceMappingURL=error-page-illustration-bFti0VEc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-page-illustration-bFti0VEc.js","sources":["../../src/patterns/error-page/error-page-illustration.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* ErrorPageIllustration — the Alfadocs mark, having a bad day. */\n/* */\n/* One mood per error, all drawn from the four pieces of the mark. */\n/* Easter egg: click the mark and it snaps back together for a moment. */\n/* Decorative and pointer-only on purpose: nothing here is needed to */\n/* recover from the error. Every motion scales off */\n/* --animation-duration, so reduced motion and the accessible themes */\n/* hold it still, and each mood settles after about five seconds. */\n/* -------------------------------------------------------------------- */\n\nimport { useEffect, useRef, useState, type ReactNode } from 'react';\nimport {\n ALL,\n CENTRE,\n Mark,\n Piece,\n type PieceName,\n} from '../_shared/mark-pieces';\n\n/** Every mood the mark can show, in the order of the status table. */\nexport const ERROR_PAGE_MOODS = [\n 'jumbled',\n 'locked',\n 'roped',\n 'lost',\n 'wrong-way',\n 'vanished',\n 'asleep',\n 'patched',\n 'melt',\n 'unplugged',\n 'rebuild',\n 'snail',\n 'adrift',\n 'puzzled',\n] as const;\n\nexport type ErrorPageMood = (typeof ERROR_PAGE_MOODS)[number];\n\n/* ---- The mark ------------------------------------------------------ */\n/* Its four pieces live in `_shared/mark-pieces`, shared with the\n animated brand mark. */\n\n/** A dashed outline where a piece belongs. */\nfunction Slot({ name }: { name: PieceName }): ReactNode {\n return (\n <Piece\n name={name}\n fill=\"none\"\n stroke=\"var(--primary)\"\n strokeWidth=\"2\"\n strokeDasharray=\"5 5\"\n strokeOpacity=\"0.55\"\n />\n );\n}\n\nfunction Ground({ cx = 74, rx = 46 }: { cx?: number; rx?: number }) {\n return (\n <ellipse\n cx={cx}\n cy=\"206\"\n rx={rx}\n ry=\"4\"\n fill=\"var(--muted-foreground)\"\n fillOpacity=\"0.2\"\n />\n );\n}\n\n/* ---- Motion ---------------------------------------------------------- */\n/* Every class is written out in full: Tailwind only generates the ones it\n can read as a whole string. Each mood plays for about five seconds and\n then rests, so nothing moves for longer without the visitor asking\n (WCAG 2.2.2); a click on the mark plays it again. */\n\nconst DRIP =\n 'ds:[transform-box:fill-box] ds:origin-top ds:motion-safe:animate-[error-page-drip_calc(var(--animation-duration)*15)_ease-in-out_1]';\nconst DROP =\n 'ds:motion-safe:animate-[error-page-drop_calc(var(--animation-duration)*12)_ease-in_2]';\nconst ROCK =\n 'ds:[transform-box:fill-box] ds:origin-bottom ds:motion-safe:animate-[error-page-rock_calc(var(--animation-duration)*20)_ease-in-out_1]';\nconst BOB =\n 'ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-bob_calc(var(--animation-duration)*14)_ease-in-out_1]';\nconst SWING =\n 'ds:[transform-box:fill-box] ds:origin-top ds:motion-safe:animate-[error-page-swing_calc(var(--animation-duration)*18)_ease-in-out_1]';\nconst WIGGLE =\n 'ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-wiggle_calc(var(--animation-duration)*10)_ease-in-out_2]';\nconst RISE =\n 'ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-rise_calc(var(--animation-duration)*16)_ease-out_1]';\nconst FLICKER =\n 'ds:motion-safe:animate-[error-page-flicker_calc(var(--animation-duration)*6)_steps(1)_4]';\nconst CRAWL =\n 'ds:motion-safe:animate-[error-page-crawl_calc(var(--animation-duration)*24)_ease-in-out_1]';\nconst BUMP =\n 'ds:motion-safe:animate-[error-page-bump_calc(var(--animation-duration)*12)_ease-in-out_2]';\nconst BREATHE =\n 'ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-breathe_calc(var(--animation-duration)*20)_ease-in-out_1]';\nconst LATE = 'ds:[animation-delay:calc(var(--animation-duration)*5)]';\nconst LATER = 'ds:[animation-delay:calc(var(--animation-duration)*9)]';\nconst POP =\n 'ds:[transform-box:fill-box] ds:origin-center ds:motion-safe:animate-[error-page-pop_calc(var(--animation-duration)*3)_ease-out_1]';\n\n/* ---- Moods ----------------------------------------------------------- */\n\n/** 400: the pieces have been put together the wrong way round. */\nfunction Jumbled(): ReactNode {\n const turns: Record<PieceName, number> = {\n top: 75,\n right: -60,\n left: 40,\n bottom: -95,\n };\n return (\n <>\n {ALL.map((name, i) => {\n const [cx, cy] = CENTRE[name];\n return (\n <g key={name} transform={`rotate(${turns[name]} ${cx} ${cy})`}>\n <g className={`${WIGGLE} ${i % 2 ? LATE : ''}`}>\n <Piece name={name} />\n </g>\n </g>\n );\n })}\n <Ground />\n </>\n );\n}\n\n/** 401: a padlock hangs on the mark until you log in. */\nfunction Locked(): ReactNode {\n return (\n <>\n <Mark />\n <g className={SWING}>\n <path\n d=\"M60 84 v-12 a14 14 0 0 1 28 0 v12\"\n fill=\"none\"\n stroke=\"var(--muted-foreground)\"\n strokeWidth=\"6\"\n strokeLinecap=\"round\"\n />\n <rect\n x=\"50\"\n y=\"82\"\n width=\"48\"\n height=\"38\"\n rx=\"7\"\n fill=\"var(--muted-foreground)\"\n />\n <circle cx=\"74\" cy=\"97\" r=\"4.5\" fill=\"var(--background)\" />\n <rect\n x=\"72\"\n y=\"99\"\n width=\"4\"\n height=\"10\"\n rx=\"2\"\n fill=\"var(--background)\"\n />\n </g>\n <Ground />\n </>\n );\n}\n\n/** 403: roped off, like a VIP area. */\nfunction Roped(): ReactNode {\n const post = (x: number) => (\n <g fill=\"var(--muted-foreground)\">\n <rect x={x - 3} y=\"158\" width=\"6\" height=\"48\" rx=\"3\" />\n <circle cx={x} cy=\"157\" r=\"6\" />\n <rect x={x - 11} y=\"202\" width=\"22\" height=\"5\" rx=\"2.5\" />\n </g>\n );\n return (\n <>\n <Mark />\n {post(8)}\n {post(140)}\n <g className={SWING}>\n <path\n d=\"M8 160 Q74 196 140 160\"\n fill=\"none\"\n stroke=\"var(--destructive)\"\n strokeWidth=\"6\"\n strokeLinecap=\"round\"\n />\n </g>\n </>\n );\n}\n\n/** 404: a piece has fallen off and rocks on the ground. */\nfunction Lost(): ReactNode {\n return (\n <>\n <Mark except={['right']} />\n <Slot name=\"right\" />\n <Ground cx={150} rx={28} />\n <g transform=\"translate(150 204)\">\n <g className={ROCK}>\n <rect\n x=\"-24.67\"\n y=\"-35\"\n width=\"49.34\"\n height=\"33.99\"\n rx=\"4.56\"\n transform=\"rotate(10)\"\n />\n </g>\n </g>\n </>\n );\n}\n\n/** 405: a piece turned the wrong way keeps bumping into its slot. */\nfunction WrongWay(): ReactNode {\n return (\n <>\n <Mark except={['right']} />\n <Slot name=\"right\" />\n <g className={BUMP}>\n <g transform=\"translate(40 0) rotate(90 121 70)\">\n <Piece name=\"right\" />\n </g>\n </g>\n <Ground />\n </>\n );\n}\n\n/** 410: only a ghost of the mark is left, drifting away. */\nfunction Vanished(): ReactNode {\n const bits: [number, number, string][] = [\n [34, 44, ''],\n [96, 18, LATE],\n [118, 92, LATER],\n [62, 118, LATE],\n [20, 96, LATER],\n ];\n return (\n <>\n {ALL.map((name) => (\n <Slot key={name} name={name} />\n ))}\n {bits.map(([x, y, delay]) => (\n <rect\n key={`${x}-${y}`}\n x={x}\n y={y}\n width=\"6\"\n height=\"6\"\n rx=\"1.5\"\n className={`${RISE} ${delay}`}\n />\n ))}\n <Ground />\n </>\n );\n}\n\n/** 419: the page was left open so long the mark fell asleep. */\nfunction Asleep(): ReactNode {\n const z = (x: number, y: number, size: number, delay: string) => (\n <path\n d={`M${x} ${y} h${size} l-${size} ${size} h${size}`}\n fill=\"none\"\n stroke=\"var(--muted-foreground)\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={`${RISE} ${delay}`}\n />\n );\n return (\n <>\n <g transform=\"rotate(14 74 74)\">\n <g className={BREATHE}>\n <Mark />\n </g>\n </g>\n {z(122, 22, 10, '')}\n {z(140, 2, 13, LATE)}\n {z(160, -16, 16, LATER)}\n <Ground />\n </>\n );\n}\n\n/** 500: something broke on our side, and it is being patched up. */\nfunction Patched(): ReactNode {\n return (\n <>\n <g className={BREATHE}>\n <Mark />\n {/* The crack, cut through the bottom piece. */}\n <polyline\n points=\"62,102 75,113 67,119 83,128 75,137 91,145\"\n fill=\"none\"\n stroke=\"var(--background)\"\n strokeWidth=\"4.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n {/* A sticking plaster across it. */}\n <g transform=\"rotate(-40 78 122)\">\n <rect\n x=\"46\"\n y=\"111\"\n width=\"64\"\n height=\"22\"\n rx=\"11\"\n fill=\"var(--muted)\"\n stroke=\"var(--border)\"\n strokeWidth=\"1.5\"\n />\n <rect\n x=\"68\"\n y=\"111\"\n width=\"20\"\n height=\"22\"\n fill=\"var(--border)\"\n fillOpacity=\"0.6\"\n />\n <g fill=\"var(--muted-foreground)\" fillOpacity=\"0.5\">\n <circle cx=\"55\" cy=\"118\" r=\"1.4\" />\n <circle cx=\"55\" cy=\"126\" r=\"1.4\" />\n <circle cx=\"101\" cy=\"118\" r=\"1.4\" />\n <circle cx=\"101\" cy=\"126\" r=\"1.4\" />\n </g>\n </g>\n </g>\n <Ground />\n </>\n );\n}\n\n/** A drip hanging from the melting edge, with a round bead at its end. */\nfunction Drip({\n cx,\n top,\n length,\n className = '',\n}: {\n cx: number;\n top: number;\n length: number;\n className?: string;\n}): ReactNode {\n return (\n <g className={`${DRIP} ${className}`}>\n <rect x={cx - 3.5} y={top} width=\"7\" height={length} rx=\"3.5\" />\n <circle cx={cx} cy={top + length} r=\"4.2\" />\n </g>\n );\n}\n\n/** 429: so many requests the mark has overheated and melted. */\nfunction Melt(): ReactNode {\n return (\n <>\n <Mark />\n {/* The bottom edge sags as it melts. */}\n <path d=\"M67 139 L99 131 L101 138 Q92 151 80 152 Q70 153 68 143 Z\" />\n <Drip cx={75} top={144} length={20} className={LATE} />\n <Drip cx={85.5} top={141} length={32} />\n <Drip cx={96} top={137} length={13} className={LATER} />\n <circle cx=\"85.5\" cy=\"179\" r=\"3.2\" className={DROP} />\n <ellipse cx=\"86\" cy=\"204\" rx=\"30\" ry=\"5.5\" fillOpacity=\"0.3\" />\n </>\n );\n}\n\n/** 502: the mark has come apart, with a spark where it broke. */\nfunction Unplugged(): ReactNode {\n return (\n <>\n <g transform=\"translate(-12 -8)\">\n <Piece name=\"top\" />\n <Piece name=\"left\" />\n </g>\n <g transform=\"translate(12 8)\">\n <Piece name=\"right\" />\n <Piece name=\"bottom\" />\n </g>\n <polyline\n points=\"66,62 80,72 68,78 84,90\"\n fill=\"none\"\n stroke=\"var(--accent)\"\n strokeWidth=\"4\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={FLICKER}\n />\n <Ground />\n </>\n );\n}\n\n/** 503 and maintenance: a crane lowers a piece back into place. */\nfunction Rebuild(): ReactNode {\n return (\n <>\n <Mark except={['right']} />\n <Slot name=\"right\" />\n <g className={SWING}>\n <line\n x1=\"121\"\n y1=\"-24\"\n x2=\"121\"\n y2=\"6\"\n stroke=\"var(--muted-foreground)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M121 6 v5 a4 4 0 1 1 -4 4\"\n fill=\"none\"\n stroke=\"var(--muted-foreground)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <g transform=\"translate(0 -36)\">\n <Piece name=\"right\" />\n </g>\n </g>\n <Ground />\n </>\n );\n}\n\n/** 504: the missing piece is on its way, by snail. */\nfunction Snail(): ReactNode {\n return (\n <>\n <Mark except={['right']} />\n <Slot name=\"right\" />\n <Ground cx={140} rx={34} />\n <g className={CRAWL}>\n <g fill=\"var(--muted-foreground)\" fillOpacity=\"0.45\">\n <rect x=\"110\" y=\"198\" width=\"58\" height=\"8\" rx=\"4\" />\n <rect x=\"110\" y=\"184\" width=\"12\" height=\"22\" rx=\"6\" />\n </g>\n <g\n stroke=\"var(--muted-foreground)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n >\n <line x1=\"113\" y1=\"186\" x2=\"108\" y2=\"173\" />\n <line x1=\"119\" y1=\"186\" x2=\"121\" y2=\"172\" />\n </g>\n <circle cx=\"108\" cy=\"172\" r=\"2.5\" fill=\"var(--muted-foreground)\" />\n <circle cx=\"121\" cy=\"171\" r=\"2.5\" fill=\"var(--muted-foreground)\" />\n <circle\n cx=\"146\"\n cy=\"185\"\n r=\"16\"\n fill=\"var(--muted-foreground)\"\n fillOpacity=\"0.7\"\n />\n <path\n d=\"M146 185 a3 3 0 1 1 3 3 a7 7 0 1 1 -7 -7 a11 11 0 1 1 11 11\"\n fill=\"none\"\n stroke=\"var(--background)\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <rect\n x=\"-13\"\n y=\"-9\"\n width=\"26\"\n height=\"18\"\n rx=\"3\"\n transform=\"translate(147 161) rotate(-15)\"\n />\n </g>\n </>\n );\n}\n\n/** Offline: the pieces have drifted apart. */\nfunction Adrift(): ReactNode {\n const drift: Record<PieceName, [number, number, string]> = {\n top: [0, -12, ''],\n right: [14, 0, LATE],\n left: [-14, 0, LATER],\n bottom: [0, 14, LATE],\n };\n return (\n <>\n <Ground />\n {ALL.map((name) => {\n const [x, y, delay] = drift[name];\n return (\n <g key={name} transform={`translate(${x} ${y})`}>\n <g className={`${BOB} ${delay}`}>\n <Piece name={name} />\n </g>\n </g>\n );\n })}\n </>\n );\n}\n\n/** Any other error: the mark is as puzzled as you are. */\nfunction Puzzled(): ReactNode {\n return (\n <>\n <g className={ROCK}>\n <Mark />\n </g>\n <g className={BOB}>\n <path\n d=\"M140 -2 a10 10 0 1 1 10 10 v7\"\n fill=\"none\"\n stroke=\"var(--muted-foreground)\"\n strokeWidth=\"5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <circle cx=\"150\" cy=\"27\" r=\"3\" fill=\"var(--muted-foreground)\" />\n </g>\n <Ground />\n </>\n );\n}\n\nconst MOODS: Record<ErrorPageMood, () => ReactNode> = {\n jumbled: Jumbled,\n locked: Locked,\n roped: Roped,\n lost: Lost,\n 'wrong-way': WrongWay,\n vanished: Vanished,\n asleep: Asleep,\n patched: Patched,\n melt: Melt,\n unplugged: Unplugged,\n rebuild: Rebuild,\n snail: Snail,\n adrift: Adrift,\n puzzled: Puzzled,\n};\n\n/** How long the mark stays fixed after a click, in milliseconds. */\nconst FIXED_FOR = 3000;\n\nexport function ErrorPageIllustration({\n mood,\n}: {\n mood: ErrorPageMood;\n}): ReactNode {\n const ref = useRef<HTMLDivElement | null>(null);\n const [fixed, setFixed] = useState(false);\n\n // A listener rather than onClick: the egg is for the pointer only, and\n // the element stays out of the accessibility tree.\n useEffect(() => {\n const element = ref.current;\n if (!element) return undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const fix = () => {\n setFixed(true);\n clearTimeout(timer);\n timer = setTimeout(() => setFixed(false), FIXED_FOR);\n };\n element.addEventListener('click', fix);\n return () => {\n element.removeEventListener('click', fix);\n clearTimeout(timer);\n };\n }, []);\n\n const Scene = MOODS[mood];\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n data-mood={fixed ? 'fixed' : mood}\n className=\"ds:w-48 ds:select-none\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"-20 -24 200 240\"\n fill=\"var(--primary)\"\n className=\"ds:block ds:w-full ds:h-auto ds:overflow-visible\"\n >\n {fixed ? (\n <g className={POP}>\n <Mark />\n </g>\n ) : (\n <Scene />\n )}\n </svg>\n </div>\n );\n}\n"],"names":["ERROR_PAGE_MOODS","Slot","name","jsx","Piece","Ground","cx","rx","DRIP","DROP","ROCK","BOB","SWING","WIGGLE","RISE","FLICKER","CRAWL","BUMP","BREATHE","LATE","LATER","POP","Jumbled","turns","jsxs","Fragment","ALL","i","cy","CENTRE","Locked","Mark","Roped","post","x","Lost","WrongWay","Vanished","bits","y","delay","Asleep","z","size","Patched","Drip","top","length","className","Melt","Unplugged","Rebuild","Snail","Adrift","drift","Puzzled","MOODS","FIXED_FOR","ErrorPageIllustration","mood","ref","useRef","fixed","setFixed","useState","useEffect","element","timer","fix","Scene"],"mappings":"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"}
@@ -11,7 +11,7 @@ import { i as rs } from "./safe-href-5dbsfbQn.js";
11
11
  import { u as ws, a as xs, A as Fs, b as bs, E as Ns, d as ys, c as Es } from "./auth-form-parts-Celi-TLV.js";
12
12
  import { u as Is } from "./use-registration-submit-DxCWic5_.js";
13
13
  import { M as Rs } from "./matrix-rain-sDOUUwZp.js";
14
- import { E as Ls } from "./error-page-illustration-QGJAvuFB.js";
14
+ import { a as Ls } from "./error-page-illustration-bFti0VEc.js";
15
15
  const Cs = ["email", "password"], Bs = z(
16
16
  "ds:flex ds:w-full ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-lg)] ds:text-start ds:text-[var(--foreground)] ds:lg:flex-row ds:lg:items-stretch"
17
17
  ), V = z("ds:w-full ds:max-w-[400px]"), As = (t) => Object.values(t).some(Boolean), ss = (t) => Cs.find((i) => t[i]) ?? (t.form ? "password" : void 0), qs = es(
@@ -272,4 +272,4 @@ export {
272
272
  Ms as a,
273
273
  qs as b
274
274
  };
275
- //# sourceMappingURL=login-dev-card-C7wo-Hv1.js.map
275
+ //# sourceMappingURL=login-dev-card-q7iTojvV.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login-dev-card-C7wo-Hv1.js","sources":["../../src/patterns/login-form/login-form.tsx","../../src/patterns/login-form/login-dev-card.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* LoginForm — the sign-in card. */\n/* */\n/* One export for the card: the mark, the heading, email and password, */\n/* the button and the way to a new password. The host keeps the page */\n/* around it and every server rule. The card checks what a browser can */\n/* check, then hands the values to `onSubmit` or posts a real form to */\n/* the host's own field names. */\n/* */\n/* The email must be an email address. A server that also signs people */\n/* in by a username cannot use this card for those accounts. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\n// The validator EmailInput itself uses, so the two never disagree.\nimport isEmail from 'validator/lib/isEmail';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { EmailInput } from '../../components/email-input';\nimport { FormField } from '../../components/form-field';\nimport { PasswordInput } from '../../components/password-input';\nimport { isSafeHref } from '../../components/_shared/safe-href';\nimport {\n AuthCardHeading,\n AuthFormMessage,\n AuthFormStatus,\n AuthTextLink,\n ExtraFields,\n useExtraFields,\n useFormAction,\n} from '../_shared/auth-form-parts';\nimport type { BrandMarkMotion } from '../_shared/brand-mark';\nimport { useRegistrationSubmit } from '../registration-form/use-registration-submit';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** The fields of the form, in the order they appear. */\nexport const LOGIN_FORM_FIELDS = ['email', 'password'] as const;\n\nexport type LoginFormField = (typeof LOGIN_FORM_FIELDS)[number];\n\n/** What `onSubmit` receives once both checks have passed. */\nexport interface LoginFormValues {\n email: string;\n password: string;\n}\n\n/** Values to show when the form opens. There is no password here, on\n * purpose: a password is never sent back to the browser. */\nexport type LoginFormInitialValues = Partial<Pick<LoginFormValues, 'email'>>;\n\n/** Messages from the server, already translated: one per field, plus\n * `form` for a message about the whole form, such as \"the email or\n * password is incorrect\". */\nexport type LoginFormErrors = Partial<Record<LoginFormField | 'form', string>>;\n\n/** The host's own form field names, for a native form post. Both are\n * needed: a field without a name is not posted. */\nexport type LoginFormFieldNames = Record<LoginFormField, string>;\n\nexport interface LoginFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title' | 'onSubmit'\n> {\n /** Replaces the heading \"Sign in to Alfadocs\". Pass it translated. */\n title?: string;\n /** A line under the heading. Pass it translated. */\n description?: string;\n /**\n * The heading's level. Default 1: a sign-in page usually has no other\n * heading. Pass 2 on a page that has its own `h1`.\n */\n headingLevel?: 1 | 2 | 3;\n /**\n * Shows the Alfadocs mark above the heading, with the heading and its\n * line centred under it. Default true. With `false` the heading sits\n * at the start edge, for a host that shows its own logo.\n */\n showLogo?: boolean;\n /**\n * How the mark arrives when the card opens: its pieces come together\n * (`assemble`, the default), it turns once (`spin`), it beats\n * (`pulse`), or it is still (`none`). It plays once and rests, and\n * holds still under reduced motion and in the accessible themes.\n */\n logoMotion?: BrandMarkMotion;\n /**\n * Host content between the heading and the fields, such as a notice\n * (\"You have been signed out\"). It sits outside the form, so nothing in\n * it is posted. Keep any heading inside it below the card's own level.\n */\n children?: ReactNode;\n /** The email to show when the form opens, such as the one last used.\n * Read once. There is never an initial password. */\n initialValues?: LoginFormInitialValues;\n /**\n * Messages from the server, already translated. A field's message\n * shows on that field until the user changes it; `form` shows above\n * the fields.\n *\n * When messages arrive, the password is emptied and focus moves: to\n * the first field with a message, or, when only `form` says something,\n * to the password, which is then described by that message. The same\n * happens for messages present when the form opens (a page the server\n * rendered after a failed post).\n *\n * Never say which of the two values was wrong: one message for both.\n * Set `submitting` while you send, so the form also notices an answer\n * that says the same as the last one.\n */\n errors?: LoginFormErrors;\n /**\n * Adds \"Forgot password?\" under the button. A path on the same site,\n * or an address written in full (`https://…`). Anything else shows no\n * link.\n */\n forgotPasswordHref?: string;\n /** Replaces the button's \"Sign in\". Pass it translated. */\n submitLabel?: string;\n /**\n * True while the host sends the values: the button shows a spinner and\n * a second submit is ignored. Set it inside `onSubmit`, before anything\n * is awaited: until it is true, a second press sends a second sign-in.\n */\n submitting?: boolean;\n /** For React hosts: called with the values once both checks have\n * passed. Not called when `fieldNames` is set. */\n onSubmit?: (values: LoginFormValues) => void;\n /**\n * For a native form post: the host's own field names, both of them,\n * e.g. `{ email: 'email', password: 'password' }`. When set, the inputs\n * carry these names and the browser posts the form.\n */\n fieldNames?: LoginFormFieldNames;\n /**\n * Where a native form post goes. Default: the current address. Only a\n * path, or an address on the page's own origin, is accepted: another\n * origin is never sent what the user typed, and the post then goes to\n * the current address. Does nothing without `fieldNames`.\n */\n action?: string;\n /**\n * Extra hidden inputs posted with a native form, by name: a CSRF token,\n * a return address. Not used with `onSubmit`. A name that is also one\n * of `fieldNames` is left out: the form's own field wins. The server\n * must check a return address itself: anyone can change a hidden input.\n */\n hiddenFields?: Readonly<Record<string, string>>;\n /**\n * A second card beside the sign-in, the same height: the development\n * quick sign-in (`LoginDevCard`). Pass it only when the server says\n * this is a development environment: the kit never decides that\n * itself. The two sit side by side where there is room and stack on a\n * phone.\n */\n devCard?: ReactNode;\n}\n\n/* -------------------------------------------------------------------- */\n/* Styles */\n/* -------------------------------------------------------------------- */\n\n// The card is 400px wide at most, written in px: a host whose root font\n// size is not 16px would stretch or squeeze a width in rem.\nconst loginFormVariants = cva(\n 'ds:flex ds:w-full ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-lg)] ds:text-start ds:text-[var(--foreground)] ds:lg:flex-row ds:lg:items-stretch',\n);\n\nconst columnVariants = cva('ds:w-full ds:max-w-[400px]');\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst hasMessage = (errors: LoginFormErrors): boolean =>\n Object.values(errors).some(Boolean);\n\n/**\n * Where to send the user for a set of server messages: the first field\n * that has one. A message about the whole form sends them to the\n * password, the field they will have to type again.\n */\nconst focusTargetFor = (\n messages: LoginFormErrors,\n): LoginFormField | undefined =>\n LOGIN_FORM_FIELDS.find((field) => messages[field]) ??\n (messages.form ? 'password' : undefined);\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\n/**\n * The sign-in card. Mount it on the login page, inside `SignedOutFrame`\n * or the host's own chrome.\n */\nexport const LoginForm = forwardRef<HTMLDivElement, LoginFormProps>(\n (\n {\n title,\n description,\n headingLevel = 1,\n showLogo = true,\n logoMotion = 'assemble',\n children,\n initialValues,\n errors,\n forgotPasswordHref,\n submitLabel,\n submitting = false,\n onSubmit,\n fieldNames,\n action,\n hiddenFields,\n devCard,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const titleId = useId();\n const formMessageId = useId();\n const native = fieldNames !== undefined;\n\n /* ------------------------------ State ----------------------------- */\n\n // Read once. The password always starts empty.\n const [email, setEmail] = useState(() => initialValues?.email ?? '');\n const [password, setPassword] = useState('');\n // A field the user has filled in and left. An email that arrives\n // filled in counts: a bad one is then flagged at once, with its\n // message. An empty field is not flagged for being passed through: a\n // keyboard user on the way to \"Forgot password?\" has made no mistake.\n // Its message waits for a submit.\n const [touched, setTouched] = useState<\n Partial<Record<LoginFormField, boolean>>\n >(() => ({ email: Boolean(initialValues?.email) }));\n const [submitted, setSubmitted] = useState(false);\n const [serverErrors, setServerErrors] = useState<LoginFormErrors>(\n () => errors ?? {},\n );\n\n const leave = (field: LoginFormField) =>\n setTouched((previous) =>\n previous[field] ? previous : { ...previous, [field]: true },\n );\n // The server's message was about the old value.\n const forget = (field: LoginFormField) =>\n setServerErrors((previous) =>\n previous[field] ? { ...previous, [field]: undefined } : previous,\n );\n\n const emailInput = useRef<HTMLInputElement>(null);\n const passwordInput = useRef<HTMLInputElement>(null);\n\n const emptyPassword = () => {\n setPassword('');\n setTouched((previous) => ({ ...previous, password: false }));\n };\n /**\n * What the two inputs hold now. Read from the inputs, not from state:\n * a browser or a password manager can fill a field without telling\n * React, and the form must not refuse a field that is visibly filled.\n */\n const held = (): LoginFormValues => {\n const values = {\n email: emailInput.current?.value ?? email,\n password: passwordInput.current?.value ?? password,\n };\n if (values.email !== email) setEmail(values.email);\n if (values.password !== password) setPassword(values.password);\n return values;\n };\n\n /* ---------------------------- Validation -------------------------- */\n\n /** What stops a submit, whether or not the message shows yet. The\n * password only has to be there: its rules are for a new password. */\n const invalid: Record<LoginFormField, boolean> = {\n email: !isEmail(email),\n password: password === '',\n };\n // A message shows once the user has filled in and left the field, or\n // tried to submit.\n const due = (field: LoginFormField) => submitted || touched[field] === true;\n const ownErrors: Record<LoginFormField, string | undefined> = {\n email:\n due('email') && invalid.email\n ? email === ''\n ? t('loginForm.emailRequired')\n : t('inputs.email.invalid')\n : undefined,\n password:\n due('password') && invalid.password\n ? t('loginForm.passwordRequired')\n : undefined,\n };\n const errorFor = (field: LoginFormField) =>\n serverErrors[field] ?? ownErrors[field];\n\n /* ------------------------------ Focus ----------------------------- */\n\n // A new object for each request, so asking twice for the same place\n // moves focus twice. The effect runs after the messages are drawn, so\n // a screen reader lands on something that already says what is wrong.\n // It starts with the messages the form opened with: a page the server\n // rendered after a failed post announces nothing itself.\n const [focusRequest, setFocusRequest] = useState<{\n target: LoginFormField;\n } | null>(() => {\n const target = focusTargetFor(errors ?? {});\n return target ? { target } : null;\n });\n useEffect(() => {\n if (!focusRequest) return;\n (focusRequest.target === 'email'\n ? emailInput\n : passwordInput\n ).current?.focus();\n }, [focusRequest]);\n\n /* ------------------------------ Submit ---------------------------- */\n\n const submit = useRegistrationSubmit<LoginFormField>({\n errors,\n submitting,\n native,\n captcha: false,\n firstProblem: () => {\n const values = held();\n if (!isEmail(values.email)) return 'email';\n return values.password === '' ? 'password' : undefined;\n },\n onRefused: (field) => {\n // Both messages now show, and focus goes to the first problem.\n setSubmitted(true);\n setFocusRequest({ target: field });\n },\n // Only a React host gets here: a native post is the browser's own.\n deliver: () => onSubmit?.(held()),\n onAnswer: (answer) => {\n const next: LoginFormErrors = answer;\n setServerErrors(next);\n if (!hasMessage(next)) return;\n // Never keep a password the server did not accept.\n emptyPassword();\n setSubmitted(false);\n const target = focusTargetFor(next);\n if (target) setFocusRequest({ target });\n },\n // The page came back from the browser's cache as it was left: the\n // password must not come back with it.\n onRestore: emptyPassword,\n });\n const { busy } = submit;\n\n /* ------------------------------ Render ---------------------------- */\n\n const formAction = useFormAction('LoginForm', native, action);\n const forgotLink =\n forgotPasswordHref && isSafeHref(forgotPasswordHref)\n ? forgotPasswordHref\n : undefined;\n const extraFields = useExtraFields(\n 'LoginForm',\n native,\n fieldNames,\n hiddenFields,\n );\n const formError = serverErrors.form;\n\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"login-form\"\n className={loginFormVariants({ className })}\n >\n <div className={columnVariants()}>\n <Card variant=\"elevated\" className=\"ds:h-full\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <AuthCardHeading\n id={titleId}\n title={title ?? t('loginForm.title')}\n description={description}\n level={headingLevel}\n showLogo={showLogo}\n logoMotion={logoMotion}\n />\n\n {children ? (\n <div\n data-slot=\"host-content\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {children}\n </div>\n ) : null}\n\n {/* Always POST, in both modes: should the script ever fail to\n run, the browser must not put a password in the address. */}\n <form\n noValidate\n method=\"post\"\n action={formAction}\n aria-labelledby={titleId}\n aria-busy={busy || undefined}\n onSubmit={submit.handleSubmit}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {formError && (\n <AuthFormMessage id={formMessageId}>\n {formError}\n </AuthFormMessage>\n )}\n\n <FormField\n label={t('loginForm.email')}\n required\n error={errorFor('email')}\n data-field=\"email\"\n >\n {/* One check, above, drives the message, the red mark and\n aria-invalid through FormField. EmailInput's own check\n is off so the two cannot disagree. `username` is the\n name browsers and password managers give the field\n that goes with `current-password`. */}\n <EmailInput\n ref={emailInput}\n name={native ? fieldNames.email : 'email'}\n autoComplete=\"username\"\n disableBuiltInValidation\n value={email}\n onChange={(event) => {\n setEmail(event.target.value);\n forget('email');\n }}\n onBlur={(event) => {\n // Whatever a browser filled in without saying so.\n setEmail(event.target.value);\n if (event.target.value !== '') leave('email');\n }}\n />\n </FormField>\n\n <FormField\n label={t('loginForm.password')}\n required\n error={errorFor('password')}\n data-field=\"password\"\n >\n {/* Described by the message above the fields when there is\n one: focus lands here after a refused sign-in, and a\n screen reader then reads why. */}\n <PasswordInput\n ref={passwordInput}\n name={native ? fieldNames.password : 'password'}\n autoComplete=\"current-password\"\n aria-describedby={formError ? formMessageId : undefined}\n value={password}\n onChange={(event) => {\n setPassword(event.target.value);\n forget('password');\n }}\n onBlur={(event) => {\n setPassword(event.target.value);\n if (event.target.value !== '') leave('password');\n }}\n />\n </FormField>\n\n <ExtraFields fields={extraFields} />\n\n <Button\n type=\"submit\"\n intent=\"primary\"\n size=\"lg\"\n loading={busy}\n className=\"ds:w-full\"\n data-action=\"submit\"\n >\n {submitLabel ?? t('loginForm.submit')}\n </Button>\n\n {forgotLink && (\n <AuthTextLink href={forgotLink} action=\"forgot-password\">\n {t('loginForm.forgot')}\n </AuthTextLink>\n )}\n </form>\n {/* Outside the form: a screen reader may hold back what\n changes inside a busy region. */}\n <AuthFormStatus busy={busy} />\n </Card.Body>\n </Card>\n </div>\n {devCard ? <div className={columnVariants()}>{devCard}</div> : null}\n </div>\n );\n },\n);\nLoginForm.displayName = 'LoginForm';\n","/* -------------------------------------------------------------------- */\n/* LoginDevCard — the development quick sign-in card. */\n/* */\n/* A second card beside the login, for developers: one link per test */\n/* account the host's server can sign in. The kit only draws it. The */\n/* host decides whether it is rendered, supplies every word on it, and */\n/* its server must refuse the routes outside development. */\n/* -------------------------------------------------------------------- */\n\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { MatrixRain } from '../../components/matrix-rain';\nimport { isSafeHref } from '../../components/_shared/safe-href';\nimport { ErrorPageIllustration } from '../error-page/error-page-illustration';\n\nexport interface LoginDevOption {\n /** The link's text, e.g. \"Sign in as admin\". The host supplies it, so\n * the kit ships no text for a card that users never see. */\n label: string;\n /** The development-only route that signs the test account in. A path\n * on the same site, or an address written in full. */\n href: string;\n /** A Lucide icon for the link, passed bare: `<ShieldUser />`. */\n icon?: ReactNode;\n}\n\nexport interface LoginDevCardProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title'\n> {\n /** The card's heading, e.g. \"Developer quick login\". */\n title: string;\n /** One link per test account. An option with an unsafe address is\n * left out. */\n options: readonly LoginDevOption[];\n /** The heading's level. Default 2, under the login's own heading. */\n headingLevel?: 2 | 3;\n}\n\n// As tall as the login beside it, so the two cards read as a pair.\nconst loginDevCardVariants = cva('ds:h-full ds:w-full');\n\n/**\n * The development quick sign-in card. Render it only when the server\n * says this is a development environment: it never checks the\n * environment itself. Pass it to `LoginForm` as `devCard`.\n */\nexport const LoginDevCard = forwardRef<HTMLDivElement, LoginDevCardProps>(\n ({ title, options, headingLevel = 2, className, ...rest }, ref) => {\n const titleId = useId();\n const Heading = `h${headingLevel}` as const;\n const links = options.filter((option) => isSafeHref(option.href));\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"login-dev-card\"\n className={loginDevCardVariants({ className })}\n >\n <Card\n variant=\"elevated\"\n aria-labelledby={titleId}\n className=\"ds:relative ds:isolate ds:flex ds:h-full ds:flex-col ds:overflow-hidden\"\n >\n {/* Code rain round the edges, clear in the middle so it never runs\n behind the links. MatrixRain holds still under reduced motion by\n itself; it does not know the accessible themes, so the rain is\n taken out there, like the kit's other decorative motion. */}\n <div className=\"ds:absolute ds:inset-0 ds:z-0 ds:[.theme-accessible_&]:hidden\">\n <MatrixRain\n glyphs=\"hex\"\n decay=\"fast\"\n mask=\"center\"\n maskRadius=\"xl\"\n className=\"ds:size-full\"\n />\n </div>\n <Card.Header className=\"ds:relative ds:z-[1]\">\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:text-center\">\n {/* The melting mark from the error pages, at half its size\n there. */}\n <div className=\"ds:[&>div]:w-24\">\n <ErrorPageIllustration mood=\"melt\" />\n </div>\n <Heading\n id={titleId}\n className=\"type-title-card ds:text-[var(--foreground)]\"\n >\n {title}\n </Heading>\n </div>\n </Card.Header>\n <Card.Body className=\"ds:relative ds:z-[1] ds:flex ds:flex-1 ds:flex-col ds:justify-center\">\n {/* The top margin keeps the heading clear of the links when the\n cards stack and this one is only as tall as its content. */}\n <div className=\"ds:mt-[var(--spacing-md)] ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {links.map((option, index) => (\n <Button\n // Two options may share an address, so the place in the\n // list is part of the key.\n key={`${index}:${option.href}`}\n asChild\n intent=\"primary\"\n startIcon={option.icon}\n className=\"ds:min-h-[var(--min-target-size)] ds:w-full\"\n >\n <a href={option.href} data-action=\"dev-login\">\n {option.label}\n </a>\n </Button>\n ))}\n </div>\n </Card.Body>\n </Card>\n </div>\n );\n },\n);\nLoginDevCard.displayName = 'LoginDevCard';\n"],"names":["LOGIN_FORM_FIELDS","loginFormVariants","cva","columnVariants","hasMessage","errors","focusTargetFor","messages","field","LoginForm","forwardRef","title","description","headingLevel","showLogo","logoMotion","children","initialValues","forgotPasswordHref","submitLabel","submitting","onSubmit","fieldNames","action","hiddenFields","devCard","className","rest","ref","t","useTranslation","titleId","useId","formMessageId","native","email","setEmail","useState","password","setPassword","touched","setTouched","submitted","setSubmitted","serverErrors","setServerErrors","leave","previous","forget","emailInput","useRef","passwordInput","emptyPassword","held","values","_a","_b","invalid","isEmail","due","ownErrors","errorFor","focusRequest","setFocusRequest","target","useEffect","submit","useRegistrationSubmit","answer","next","busy","formAction","useFormAction","forgotLink","isSafeHref","extraFields","useExtraFields","formError","jsxs","jsx","Card","AuthCardHeading","AuthFormMessage","FormField","EmailInput","event","PasswordInput","ExtraFields","Button","AuthTextLink","AuthFormStatus","loginDevCardVariants","LoginDevCard","options","Heading","links","option","MatrixRain","ErrorPageIllustration","index"],"mappings":";;;;;;;;;;;;;;AAiDO,MAAMA,KAAoB,CAAC,SAAS,UAAU,GA+H/CC,KAAoBC;AAAA,EACxB;AACF,GAEMC,IAAiBD,EAAI,4BAA4B,GAMjDE,KAAa,CAACC,MAClB,OAAO,OAAOA,CAAM,EAAE,KAAK,OAAO,GAO9BC,KAAiB,CACrBC,MAEAP,GAAkB,KAAK,CAACQ,MAAUD,EAASC,CAAK,CAAC,MAChDD,EAAS,OAAO,aAAa,SAUnBE,KAAYC;AAAA,EACvB,CACE;AAAA,IACE,OAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC,IAAe;AAAA,IACf,UAAAC,IAAW;AAAA,IACX,YAAAC,IAAa;AAAA,IACb,UAAAC;AAAA,IACA,eAAAC;AAAA,IACA,QAAAZ;AAAA,IACA,oBAAAa;AAAA,IACA,aAAAC;AAAA,IACA,YAAAC,IAAa;AAAA,IACb,UAAAC;AAAA,IACA,YAAAC;AAAA,IACA,QAAAC;AAAA,IACA,cAAAC;AAAA,IACA,SAAAC;AAAA,IACA,WAAAC;AAAA,IACA,GAAGC;AAAA,EAAA,GAELC,OACG;AACH,UAAM,EAAE,GAAAC,EAAA,IAAMC,GAAe,IAAI,GAC3BC,IAAUC,EAAA,GACVC,IAAgBD,EAAA,GAChBE,IAASZ,MAAe,QAKxB,CAACa,GAAOC,CAAQ,IAAIC,EAAS,OAAMpB,KAAA,gBAAAA,EAAe,UAAS,EAAE,GAC7D,CAACqB,GAAUC,CAAW,IAAIF,EAAS,EAAE,GAMrC,CAACG,IAASC,CAAU,IAAIJ,EAE5B,OAAO,EAAE,OAAO,GAAQpB,KAAA,QAAAA,EAAe,OAAK,EAAI,GAC5C,CAACyB,IAAWC,CAAY,IAAIN,EAAS,EAAK,GAC1C,CAACO,GAAcC,CAAe,IAAIR;AAAA,MACtC,MAAMhC,KAAU,CAAA;AAAA,IAAC,GAGbyC,IAAQ,CAACtC,MACbiC;AAAA,MAAW,CAACM,MACVA,EAASvC,CAAK,IAAIuC,IAAW,EAAE,GAAGA,GAAU,CAACvC,CAAK,GAAG,GAAA;AAAA,IAAK,GAGxDwC,IAAS,CAACxC,MACdqC;AAAA,MAAgB,CAACE,MACfA,EAASvC,CAAK,IAAI,EAAE,GAAGuC,GAAU,CAACvC,CAAK,GAAG,WAAcuC;AAAA,IAAA,GAGtDE,IAAaC,EAAyB,IAAI,GAC1CC,IAAgBD,EAAyB,IAAI,GAE7CE,IAAgB,MAAM;AAC1B,MAAAb,EAAY,EAAE,GACdE,EAAW,CAACM,OAAc,EAAE,GAAGA,GAAU,UAAU,KAAQ;AAAA,IAC7D,GAMMM,IAAO,MAAuB;;AAClC,YAAMC,IAAS;AAAA,QACb,SAAOC,IAAAN,EAAW,YAAX,gBAAAM,EAAoB,UAASpB;AAAA,QACpC,YAAUqB,IAAAL,EAAc,YAAd,gBAAAK,EAAuB,UAASlB;AAAA,MAAA;AAE5C,aAAIgB,EAAO,UAAUnB,KAAOC,EAASkB,EAAO,KAAK,GAC7CA,EAAO,aAAahB,KAAUC,EAAYe,EAAO,QAAQ,GACtDA;AAAA,IACT,GAMMG,IAA2C;AAAA,MAC/C,OAAO,CAACC,EAAQvB,CAAK;AAAA,MACrB,UAAUG,MAAa;AAAA,IAAA,GAInBqB,IAAM,CAACnD,MAA0BkC,MAAaF,GAAQhC,CAAK,MAAM,IACjEoD,KAAwD;AAAA,MAC5D,OACED,EAAI,OAAO,KAAKF,EAAQ,QAElB5B,EADFM,MAAU,KACN,4BACA,sBADyB,IAE7B;AAAA,MACN,UACEwB,EAAI,UAAU,KAAKF,EAAQ,WACvB5B,EAAE,4BAA4B,IAC9B;AAAA,IAAA,GAEFgC,IAAW,CAACrD,MAChBoC,EAAapC,CAAK,KAAKoD,GAAUpD,CAAK,GASlC,CAACsD,GAAcC,CAAe,IAAI1B,EAE9B,MAAM;AACd,YAAM2B,IAAS1D,GAAeD,KAAU,EAAE;AAC1C,aAAO2D,IAAS,EAAE,QAAAA,EAAA,IAAW;AAAA,IAC/B,CAAC;AACD,IAAAC,GAAU,MAAM;;AACd,MAAKH,OACJP,KAAAO,EAAa,WAAW,UACrBb,IACAE,GACF,YAHD,QAAAI,EAGU;AAAA,IACb,GAAG,CAACO,CAAY,CAAC;AAIjB,UAAMI,IAASC,GAAsC;AAAA,MACnD,QAAA9D;AAAA,MACA,YAAAe;AAAA,MACA,QAAAc;AAAA,MACA,SAAS;AAAA,MACT,cAAc,MAAM;AAClB,cAAMoB,IAASD,EAAA;AACf,eAAKK,EAAQJ,EAAO,KAAK,IAClBA,EAAO,aAAa,KAAK,aAAa,SADV;AAAA,MAErC;AAAA,MACA,WAAW,CAAC9C,MAAU;AAEpB,QAAAmC,EAAa,EAAI,GACjBoB,EAAgB,EAAE,QAAQvD,GAAO;AAAA,MACnC;AAAA;AAAA,MAEA,SAAS,MAAMa,KAAA,gBAAAA,EAAWgC;MAC1B,UAAU,CAACe,MAAW;AACpB,cAAMC,IAAwBD;AAE9B,YADAvB,EAAgBwB,CAAI,GAChB,CAACjE,GAAWiE,CAAI,EAAG;AAEvB,QAAAjB,EAAA,GACAT,EAAa,EAAK;AAClB,cAAMqB,IAAS1D,GAAe+D,CAAI;AAClC,QAAIL,KAAQD,EAAgB,EAAE,QAAAC,GAAQ;AAAA,MACxC;AAAA;AAAA;AAAA,MAGA,WAAWZ;AAAA,IAAA,CACZ,GACK,EAAE,MAAAkB,MAASJ,GAIXK,KAAaC,GAAc,aAAatC,GAAQX,EAAM,GACtDkD,IACJvD,KAAsBwD,GAAWxD,CAAkB,IAC/CA,IACA,QACAyD,KAAcC;AAAA,MAClB;AAAA,MACA1C;AAAA,MACAZ;AAAA,MACAE;AAAA,IAAA,GAEIqD,IAAYjC,EAAa;AAE/B,WACE,gBAAAkC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAlD;AAAA,QACC,GAAGD;AAAA,QACJ,kBAAe;AAAA,QACf,WAAW1B,GAAkB,EAAE,WAAAyB,IAAW;AAAA,QAE1C,UAAA;AAAA,UAAA,gBAAAqD,EAAC,OAAA,EAAI,WAAW5E,EAAA,GACd,4BAAC6E,GAAA,EAAK,SAAQ,YAAW,WAAU,aACjC,UAAA,gBAAAF,EAACE,EAAK,MAAL,EAAU,WAAU,kDACnB,UAAA;AAAA,YAAA,gBAAAD;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,IAAIlD;AAAA,gBACJ,OAAOpB,KAASkB,EAAE,iBAAiB;AAAA,gBACnC,aAAAjB;AAAA,gBACA,OAAOC;AAAA,gBACP,UAAAC;AAAA,gBACA,YAAAC;AAAA,cAAA;AAAA,YAAA;AAAA,YAGDC,IACC,gBAAA+D;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,aAAU;AAAA,gBACV,WAAU;AAAA,gBAET,UAAA/D;AAAA,cAAA;AAAA,YAAA,IAED;AAAA,YAIJ,gBAAA8D;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,YAAU;AAAA,gBACV,QAAO;AAAA,gBACP,QAAQP;AAAA,gBACR,mBAAiBxC;AAAA,gBACjB,aAAWuC,KAAQ;AAAA,gBACnB,UAAUJ,EAAO;AAAA,gBACjB,WAAU;AAAA,gBAET,UAAA;AAAA,kBAAAW,KACC,gBAAAE,EAACG,IAAA,EAAgB,IAAIjD,GAClB,UAAA4C,GACH;AAAA,kBAGF,gBAAAE;AAAA,oBAACI;AAAA,oBAAA;AAAA,sBACC,OAAOtD,EAAE,iBAAiB;AAAA,sBAC1B,UAAQ;AAAA,sBACR,OAAOgC,EAAS,OAAO;AAAA,sBACvB,cAAW;AAAA,sBAOX,UAAA,gBAAAkB;AAAA,wBAACK;AAAA,wBAAA;AAAA,0BACC,KAAKnC;AAAA,0BACL,MAAMf,IAASZ,EAAW,QAAQ;AAAA,0BAClC,cAAa;AAAA,0BACb,0BAAwB;AAAA,0BACxB,OAAOa;AAAA,0BACP,UAAU,CAACkD,MAAU;AACnB,4BAAAjD,EAASiD,EAAM,OAAO,KAAK,GAC3BrC,EAAO,OAAO;AAAA,0BAChB;AAAA,0BACA,QAAQ,CAACqC,MAAU;AAEjB,4BAAAjD,EAASiD,EAAM,OAAO,KAAK,GACvBA,EAAM,OAAO,UAAU,QAAU,OAAO;AAAA,0BAC9C;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACF;AAAA,kBAAA;AAAA,kBAGF,gBAAAN;AAAA,oBAACI;AAAA,oBAAA;AAAA,sBACC,OAAOtD,EAAE,oBAAoB;AAAA,sBAC7B,UAAQ;AAAA,sBACR,OAAOgC,EAAS,UAAU;AAAA,sBAC1B,cAAW;AAAA,sBAKX,UAAA,gBAAAkB;AAAA,wBAACO;AAAA,wBAAA;AAAA,0BACC,KAAKnC;AAAA,0BACL,MAAMjB,IAASZ,EAAW,WAAW;AAAA,0BACrC,cAAa;AAAA,0BACb,oBAAkBuD,IAAY5C,IAAgB;AAAA,0BAC9C,OAAOK;AAAA,0BACP,UAAU,CAAC+C,MAAU;AACnB,4BAAA9C,EAAY8C,EAAM,OAAO,KAAK,GAC9BrC,EAAO,UAAU;AAAA,0BACnB;AAAA,0BACA,QAAQ,CAACqC,MAAU;AACjB,4BAAA9C,EAAY8C,EAAM,OAAO,KAAK,GAC1BA,EAAM,OAAO,UAAU,QAAU,UAAU;AAAA,0BACjD;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBACF;AAAA,kBAAA;AAAA,kBAGF,gBAAAN,EAACQ,IAAA,EAAY,QAAQZ,GAAA,CAAa;AAAA,kBAElC,gBAAAI;AAAA,oBAACS;AAAA,oBAAA;AAAA,sBACC,MAAK;AAAA,sBACL,QAAO;AAAA,sBACP,MAAK;AAAA,sBACL,SAASlB;AAAA,sBACT,WAAU;AAAA,sBACV,eAAY;AAAA,sBAEX,UAAAnD,KAAeU,EAAE,kBAAkB;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAGrC4C,uBACEgB,IAAA,EAAa,MAAMhB,GAAY,QAAO,mBACpC,UAAA5C,EAAE,kBAAkB,EAAA,CACvB;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAKJ,gBAAAkD,EAACW,MAAe,MAAApB,EAAA,CAAY;AAAA,UAAA,EAAA,CAC9B,GACF,GACF;AAAA,UACC7C,IAAU,gBAAAsD,EAAC,OAAA,EAAI,WAAW5E,KAAmB,aAAQ,IAAS;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGrE;AACF;AACAM,GAAU,cAAc;ACxdxB,MAAMkF,KAAuBzF,EAAI,qBAAqB,GAOzC0F,KAAelF;AAAA,EAC1B,CAAC,EAAE,OAAAC,GAAO,SAAAkF,GAAS,cAAAhF,IAAe,GAAG,WAAAa,GAAW,GAAGC,EAAA,GAAQC,MAAQ;AACjE,UAAMG,IAAUC,EAAA,GACV8D,IAAU,IAAIjF,CAAY,IAC1BkF,IAAQF,EAAQ,OAAO,CAACG,MAAWtB,GAAWsB,EAAO,IAAI,CAAC;AAChE,WACE,gBAAAjB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAnD;AAAA,QACC,GAAGD;AAAA,QACJ,kBAAe;AAAA,QACf,WAAWgE,GAAqB,EAAE,WAAAjE,GAAW;AAAA,QAE7C,UAAA,gBAAAoD;AAAA,UAACE;AAAA,UAAA;AAAA,YACC,SAAQ;AAAA,YACR,mBAAiBjD;AAAA,YACjB,WAAU;AAAA,YAMV,UAAA;AAAA,cAAA,gBAAAgD,EAAC,OAAA,EAAI,WAAU,iEACb,UAAA,gBAAAA;AAAA,gBAACkB;AAAA,gBAAA;AAAA,kBACC,QAAO;AAAA,kBACP,OAAM;AAAA,kBACN,MAAK;AAAA,kBACL,YAAW;AAAA,kBACX,WAAU;AAAA,gBAAA;AAAA,cAAA,GAEd;AAAA,cACA,gBAAAlB,EAACC,EAAK,QAAL,EAAY,WAAU,wBACrB,UAAA,gBAAAF,EAAC,OAAA,EAAI,WAAU,iFAGb,UAAA;AAAA,gBAAA,gBAAAC,EAAC,SAAI,WAAU,mBACb,4BAACmB,IAAA,EAAsB,MAAK,QAAO,EAAA,CACrC;AAAA,gBACA,gBAAAnB;AAAA,kBAACe;AAAA,kBAAA;AAAA,oBACC,IAAI/D;AAAA,oBACJ,WAAU;AAAA,oBAET,UAAApB;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACH,EAAA,CACF,EAAA,CACF;AAAA,cACA,gBAAAoE,EAACC,EAAK,MAAL,EAAU,WAAU,wEAGnB,UAAA,gBAAAD,EAAC,OAAA,EAAI,WAAU,4EACZ,UAAAgB,EAAM,IAAI,CAACC,GAAQG,MAClB,gBAAApB;AAAA,gBAACS;AAAA,gBAAA;AAAA,kBAIC,SAAO;AAAA,kBACP,QAAO;AAAA,kBACP,WAAWQ,EAAO;AAAA,kBAClB,WAAU;AAAA,kBAEV,UAAA,gBAAAjB,EAAC,OAAE,MAAMiB,EAAO,MAAM,eAAY,aAC/B,YAAO,MAAA,CACV;AAAA,gBAAA;AAAA,gBARK,GAAGG,CAAK,IAAIH,EAAO,IAAI;AAAA,cAAA,CAU/B,GACH,EAAA,CACF;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAGN;AACF;AACAJ,GAAa,cAAc;"}
1
+ {"version":3,"file":"login-dev-card-q7iTojvV.js","sources":["../../src/patterns/login-form/login-form.tsx","../../src/patterns/login-form/login-dev-card.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* LoginForm — the sign-in card. */\n/* */\n/* One export for the card: the mark, the heading, email and password, */\n/* the button and the way to a new password. The host keeps the page */\n/* around it and every server rule. The card checks what a browser can */\n/* check, then hands the values to `onSubmit` or posts a real form to */\n/* the host's own field names. */\n/* */\n/* The email must be an email address. A server that also signs people */\n/* in by a username cannot use this card for those accounts. */\n/* -------------------------------------------------------------------- */\n\nimport {\n forwardRef,\n useEffect,\n useId,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { cva } from 'class-variance-authority';\n// The validator EmailInput itself uses, so the two never disagree.\nimport isEmail from 'validator/lib/isEmail';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { EmailInput } from '../../components/email-input';\nimport { FormField } from '../../components/form-field';\nimport { PasswordInput } from '../../components/password-input';\nimport { isSafeHref } from '../../components/_shared/safe-href';\nimport {\n AuthCardHeading,\n AuthFormMessage,\n AuthFormStatus,\n AuthTextLink,\n ExtraFields,\n useExtraFields,\n useFormAction,\n} from '../_shared/auth-form-parts';\nimport type { BrandMarkMotion } from '../_shared/brand-mark';\nimport { useRegistrationSubmit } from '../registration-form/use-registration-submit';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** The fields of the form, in the order they appear. */\nexport const LOGIN_FORM_FIELDS = ['email', 'password'] as const;\n\nexport type LoginFormField = (typeof LOGIN_FORM_FIELDS)[number];\n\n/** What `onSubmit` receives once both checks have passed. */\nexport interface LoginFormValues {\n email: string;\n password: string;\n}\n\n/** Values to show when the form opens. There is no password here, on\n * purpose: a password is never sent back to the browser. */\nexport type LoginFormInitialValues = Partial<Pick<LoginFormValues, 'email'>>;\n\n/** Messages from the server, already translated: one per field, plus\n * `form` for a message about the whole form, such as \"the email or\n * password is incorrect\". */\nexport type LoginFormErrors = Partial<Record<LoginFormField | 'form', string>>;\n\n/** The host's own form field names, for a native form post. Both are\n * needed: a field without a name is not posted. */\nexport type LoginFormFieldNames = Record<LoginFormField, string>;\n\nexport interface LoginFormProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title' | 'onSubmit'\n> {\n /** Replaces the heading \"Sign in to Alfadocs\". Pass it translated. */\n title?: string;\n /** A line under the heading. Pass it translated. */\n description?: string;\n /**\n * The heading's level. Default 1: a sign-in page usually has no other\n * heading. Pass 2 on a page that has its own `h1`.\n */\n headingLevel?: 1 | 2 | 3;\n /**\n * Shows the Alfadocs mark above the heading, with the heading and its\n * line centred under it. Default true. With `false` the heading sits\n * at the start edge, for a host that shows its own logo.\n */\n showLogo?: boolean;\n /**\n * How the mark arrives when the card opens: its pieces come together\n * (`assemble`, the default), it turns once (`spin`), it beats\n * (`pulse`), or it is still (`none`). It plays once and rests, and\n * holds still under reduced motion and in the accessible themes.\n */\n logoMotion?: BrandMarkMotion;\n /**\n * Host content between the heading and the fields, such as a notice\n * (\"You have been signed out\"). It sits outside the form, so nothing in\n * it is posted. Keep any heading inside it below the card's own level.\n */\n children?: ReactNode;\n /** The email to show when the form opens, such as the one last used.\n * Read once. There is never an initial password. */\n initialValues?: LoginFormInitialValues;\n /**\n * Messages from the server, already translated. A field's message\n * shows on that field until the user changes it; `form` shows above\n * the fields.\n *\n * When messages arrive, the password is emptied and focus moves: to\n * the first field with a message, or, when only `form` says something,\n * to the password, which is then described by that message. The same\n * happens for messages present when the form opens (a page the server\n * rendered after a failed post).\n *\n * Never say which of the two values was wrong: one message for both.\n * Set `submitting` while you send, so the form also notices an answer\n * that says the same as the last one.\n */\n errors?: LoginFormErrors;\n /**\n * Adds \"Forgot password?\" under the button. A path on the same site,\n * or an address written in full (`https://…`). Anything else shows no\n * link.\n */\n forgotPasswordHref?: string;\n /** Replaces the button's \"Sign in\". Pass it translated. */\n submitLabel?: string;\n /**\n * True while the host sends the values: the button shows a spinner and\n * a second submit is ignored. Set it inside `onSubmit`, before anything\n * is awaited: until it is true, a second press sends a second sign-in.\n */\n submitting?: boolean;\n /** For React hosts: called with the values once both checks have\n * passed. Not called when `fieldNames` is set. */\n onSubmit?: (values: LoginFormValues) => void;\n /**\n * For a native form post: the host's own field names, both of them,\n * e.g. `{ email: 'email', password: 'password' }`. When set, the inputs\n * carry these names and the browser posts the form.\n */\n fieldNames?: LoginFormFieldNames;\n /**\n * Where a native form post goes. Default: the current address. Only a\n * path, or an address on the page's own origin, is accepted: another\n * origin is never sent what the user typed, and the post then goes to\n * the current address. Does nothing without `fieldNames`.\n */\n action?: string;\n /**\n * Extra hidden inputs posted with a native form, by name: a CSRF token,\n * a return address. Not used with `onSubmit`. A name that is also one\n * of `fieldNames` is left out: the form's own field wins. The server\n * must check a return address itself: anyone can change a hidden input.\n */\n hiddenFields?: Readonly<Record<string, string>>;\n /**\n * A second card beside the sign-in, the same height: the development\n * quick sign-in (`LoginDevCard`). Pass it only when the server says\n * this is a development environment: the kit never decides that\n * itself. The two sit side by side where there is room and stack on a\n * phone.\n */\n devCard?: ReactNode;\n}\n\n/* -------------------------------------------------------------------- */\n/* Styles */\n/* -------------------------------------------------------------------- */\n\n// The card is 400px wide at most, written in px: a host whose root font\n// size is not 16px would stretch or squeeze a width in rem.\nconst loginFormVariants = cva(\n 'ds:flex ds:w-full ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-lg)] ds:text-start ds:text-[var(--foreground)] ds:lg:flex-row ds:lg:items-stretch',\n);\n\nconst columnVariants = cva('ds:w-full ds:max-w-[400px]');\n\n/* -------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------- */\n\nconst hasMessage = (errors: LoginFormErrors): boolean =>\n Object.values(errors).some(Boolean);\n\n/**\n * Where to send the user for a set of server messages: the first field\n * that has one. A message about the whole form sends them to the\n * password, the field they will have to type again.\n */\nconst focusTargetFor = (\n messages: LoginFormErrors,\n): LoginFormField | undefined =>\n LOGIN_FORM_FIELDS.find((field) => messages[field]) ??\n (messages.form ? 'password' : undefined);\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\n/**\n * The sign-in card. Mount it on the login page, inside `SignedOutFrame`\n * or the host's own chrome.\n */\nexport const LoginForm = forwardRef<HTMLDivElement, LoginFormProps>(\n (\n {\n title,\n description,\n headingLevel = 1,\n showLogo = true,\n logoMotion = 'assemble',\n children,\n initialValues,\n errors,\n forgotPasswordHref,\n submitLabel,\n submitting = false,\n onSubmit,\n fieldNames,\n action,\n hiddenFields,\n devCard,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const titleId = useId();\n const formMessageId = useId();\n const native = fieldNames !== undefined;\n\n /* ------------------------------ State ----------------------------- */\n\n // Read once. The password always starts empty.\n const [email, setEmail] = useState(() => initialValues?.email ?? '');\n const [password, setPassword] = useState('');\n // A field the user has filled in and left. An email that arrives\n // filled in counts: a bad one is then flagged at once, with its\n // message. An empty field is not flagged for being passed through: a\n // keyboard user on the way to \"Forgot password?\" has made no mistake.\n // Its message waits for a submit.\n const [touched, setTouched] = useState<\n Partial<Record<LoginFormField, boolean>>\n >(() => ({ email: Boolean(initialValues?.email) }));\n const [submitted, setSubmitted] = useState(false);\n const [serverErrors, setServerErrors] = useState<LoginFormErrors>(\n () => errors ?? {},\n );\n\n const leave = (field: LoginFormField) =>\n setTouched((previous) =>\n previous[field] ? previous : { ...previous, [field]: true },\n );\n // The server's message was about the old value.\n const forget = (field: LoginFormField) =>\n setServerErrors((previous) =>\n previous[field] ? { ...previous, [field]: undefined } : previous,\n );\n\n const emailInput = useRef<HTMLInputElement>(null);\n const passwordInput = useRef<HTMLInputElement>(null);\n\n const emptyPassword = () => {\n setPassword('');\n setTouched((previous) => ({ ...previous, password: false }));\n };\n /**\n * What the two inputs hold now. Read from the inputs, not from state:\n * a browser or a password manager can fill a field without telling\n * React, and the form must not refuse a field that is visibly filled.\n */\n const held = (): LoginFormValues => {\n const values = {\n email: emailInput.current?.value ?? email,\n password: passwordInput.current?.value ?? password,\n };\n if (values.email !== email) setEmail(values.email);\n if (values.password !== password) setPassword(values.password);\n return values;\n };\n\n /* ---------------------------- Validation -------------------------- */\n\n /** What stops a submit, whether or not the message shows yet. The\n * password only has to be there: its rules are for a new password. */\n const invalid: Record<LoginFormField, boolean> = {\n email: !isEmail(email),\n password: password === '',\n };\n // A message shows once the user has filled in and left the field, or\n // tried to submit.\n const due = (field: LoginFormField) => submitted || touched[field] === true;\n const ownErrors: Record<LoginFormField, string | undefined> = {\n email:\n due('email') && invalid.email\n ? email === ''\n ? t('loginForm.emailRequired')\n : t('inputs.email.invalid')\n : undefined,\n password:\n due('password') && invalid.password\n ? t('loginForm.passwordRequired')\n : undefined,\n };\n const errorFor = (field: LoginFormField) =>\n serverErrors[field] ?? ownErrors[field];\n\n /* ------------------------------ Focus ----------------------------- */\n\n // A new object for each request, so asking twice for the same place\n // moves focus twice. The effect runs after the messages are drawn, so\n // a screen reader lands on something that already says what is wrong.\n // It starts with the messages the form opened with: a page the server\n // rendered after a failed post announces nothing itself.\n const [focusRequest, setFocusRequest] = useState<{\n target: LoginFormField;\n } | null>(() => {\n const target = focusTargetFor(errors ?? {});\n return target ? { target } : null;\n });\n useEffect(() => {\n if (!focusRequest) return;\n (focusRequest.target === 'email'\n ? emailInput\n : passwordInput\n ).current?.focus();\n }, [focusRequest]);\n\n /* ------------------------------ Submit ---------------------------- */\n\n const submit = useRegistrationSubmit<LoginFormField>({\n errors,\n submitting,\n native,\n captcha: false,\n firstProblem: () => {\n const values = held();\n if (!isEmail(values.email)) return 'email';\n return values.password === '' ? 'password' : undefined;\n },\n onRefused: (field) => {\n // Both messages now show, and focus goes to the first problem.\n setSubmitted(true);\n setFocusRequest({ target: field });\n },\n // Only a React host gets here: a native post is the browser's own.\n deliver: () => onSubmit?.(held()),\n onAnswer: (answer) => {\n const next: LoginFormErrors = answer;\n setServerErrors(next);\n if (!hasMessage(next)) return;\n // Never keep a password the server did not accept.\n emptyPassword();\n setSubmitted(false);\n const target = focusTargetFor(next);\n if (target) setFocusRequest({ target });\n },\n // The page came back from the browser's cache as it was left: the\n // password must not come back with it.\n onRestore: emptyPassword,\n });\n const { busy } = submit;\n\n /* ------------------------------ Render ---------------------------- */\n\n const formAction = useFormAction('LoginForm', native, action);\n const forgotLink =\n forgotPasswordHref && isSafeHref(forgotPasswordHref)\n ? forgotPasswordHref\n : undefined;\n const extraFields = useExtraFields(\n 'LoginForm',\n native,\n fieldNames,\n hiddenFields,\n );\n const formError = serverErrors.form;\n\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"login-form\"\n className={loginFormVariants({ className })}\n >\n <div className={columnVariants()}>\n <Card variant=\"elevated\" className=\"ds:h-full\">\n <Card.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-lg)]\">\n <AuthCardHeading\n id={titleId}\n title={title ?? t('loginForm.title')}\n description={description}\n level={headingLevel}\n showLogo={showLogo}\n logoMotion={logoMotion}\n />\n\n {children ? (\n <div\n data-slot=\"host-content\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {children}\n </div>\n ) : null}\n\n {/* Always POST, in both modes: should the script ever fail to\n run, the browser must not put a password in the address. */}\n <form\n noValidate\n method=\"post\"\n action={formAction}\n aria-labelledby={titleId}\n aria-busy={busy || undefined}\n onSubmit={submit.handleSubmit}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\"\n >\n {formError && (\n <AuthFormMessage id={formMessageId}>\n {formError}\n </AuthFormMessage>\n )}\n\n <FormField\n label={t('loginForm.email')}\n required\n error={errorFor('email')}\n data-field=\"email\"\n >\n {/* One check, above, drives the message, the red mark and\n aria-invalid through FormField. EmailInput's own check\n is off so the two cannot disagree. `username` is the\n name browsers and password managers give the field\n that goes with `current-password`. */}\n <EmailInput\n ref={emailInput}\n name={native ? fieldNames.email : 'email'}\n autoComplete=\"username\"\n disableBuiltInValidation\n value={email}\n onChange={(event) => {\n setEmail(event.target.value);\n forget('email');\n }}\n onBlur={(event) => {\n // Whatever a browser filled in without saying so.\n setEmail(event.target.value);\n if (event.target.value !== '') leave('email');\n }}\n />\n </FormField>\n\n <FormField\n label={t('loginForm.password')}\n required\n error={errorFor('password')}\n data-field=\"password\"\n >\n {/* Described by the message above the fields when there is\n one: focus lands here after a refused sign-in, and a\n screen reader then reads why. */}\n <PasswordInput\n ref={passwordInput}\n name={native ? fieldNames.password : 'password'}\n autoComplete=\"current-password\"\n aria-describedby={formError ? formMessageId : undefined}\n value={password}\n onChange={(event) => {\n setPassword(event.target.value);\n forget('password');\n }}\n onBlur={(event) => {\n setPassword(event.target.value);\n if (event.target.value !== '') leave('password');\n }}\n />\n </FormField>\n\n <ExtraFields fields={extraFields} />\n\n <Button\n type=\"submit\"\n intent=\"primary\"\n size=\"lg\"\n loading={busy}\n className=\"ds:w-full\"\n data-action=\"submit\"\n >\n {submitLabel ?? t('loginForm.submit')}\n </Button>\n\n {forgotLink && (\n <AuthTextLink href={forgotLink} action=\"forgot-password\">\n {t('loginForm.forgot')}\n </AuthTextLink>\n )}\n </form>\n {/* Outside the form: a screen reader may hold back what\n changes inside a busy region. */}\n <AuthFormStatus busy={busy} />\n </Card.Body>\n </Card>\n </div>\n {devCard ? <div className={columnVariants()}>{devCard}</div> : null}\n </div>\n );\n },\n);\nLoginForm.displayName = 'LoginForm';\n","/* -------------------------------------------------------------------- */\n/* LoginDevCard — the development quick sign-in card. */\n/* */\n/* A second card beside the login, for developers: one link per test */\n/* account the host's server can sign in. The kit only draws it. The */\n/* host decides whether it is rendered, supplies every word on it, and */\n/* its server must refuse the routes outside development. */\n/* -------------------------------------------------------------------- */\n\nimport { forwardRef, useId, type HTMLAttributes, type ReactNode } from 'react';\nimport { cva } from 'class-variance-authority';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { MatrixRain } from '../../components/matrix-rain';\nimport { isSafeHref } from '../../components/_shared/safe-href';\nimport { ErrorPageIllustration } from '../error-page/error-page-illustration';\n\nexport interface LoginDevOption {\n /** The link's text, e.g. \"Sign in as admin\". The host supplies it, so\n * the kit ships no text for a card that users never see. */\n label: string;\n /** The development-only route that signs the test account in. A path\n * on the same site, or an address written in full. */\n href: string;\n /** A Lucide icon for the link, passed bare: `<ShieldUser />`. */\n icon?: ReactNode;\n}\n\nexport interface LoginDevCardProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'title'\n> {\n /** The card's heading, e.g. \"Developer quick login\". */\n title: string;\n /** One link per test account. An option with an unsafe address is\n * left out. */\n options: readonly LoginDevOption[];\n /** The heading's level. Default 2, under the login's own heading. */\n headingLevel?: 2 | 3;\n}\n\n// As tall as the login beside it, so the two cards read as a pair.\nconst loginDevCardVariants = cva('ds:h-full ds:w-full');\n\n/**\n * The development quick sign-in card. Render it only when the server\n * says this is a development environment: it never checks the\n * environment itself. Pass it to `LoginForm` as `devCard`.\n */\nexport const LoginDevCard = forwardRef<HTMLDivElement, LoginDevCardProps>(\n ({ title, options, headingLevel = 2, className, ...rest }, ref) => {\n const titleId = useId();\n const Heading = `h${headingLevel}` as const;\n const links = options.filter((option) => isSafeHref(option.href));\n return (\n <div\n ref={ref}\n {...rest}\n data-component=\"login-dev-card\"\n className={loginDevCardVariants({ className })}\n >\n <Card\n variant=\"elevated\"\n aria-labelledby={titleId}\n className=\"ds:relative ds:isolate ds:flex ds:h-full ds:flex-col ds:overflow-hidden\"\n >\n {/* Code rain round the edges, clear in the middle so it never runs\n behind the links. MatrixRain holds still under reduced motion by\n itself; it does not know the accessible themes, so the rain is\n taken out there, like the kit's other decorative motion. */}\n <div className=\"ds:absolute ds:inset-0 ds:z-0 ds:[.theme-accessible_&]:hidden\">\n <MatrixRain\n glyphs=\"hex\"\n decay=\"fast\"\n mask=\"center\"\n maskRadius=\"xl\"\n className=\"ds:size-full\"\n />\n </div>\n <Card.Header className=\"ds:relative ds:z-[1]\">\n <div className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-sm)] ds:text-center\">\n {/* The melting mark from the error pages, at half its size\n there. */}\n <div className=\"ds:[&>div]:w-24\">\n <ErrorPageIllustration mood=\"melt\" />\n </div>\n <Heading\n id={titleId}\n className=\"type-title-card ds:text-[var(--foreground)]\"\n >\n {title}\n </Heading>\n </div>\n </Card.Header>\n <Card.Body className=\"ds:relative ds:z-[1] ds:flex ds:flex-1 ds:flex-col ds:justify-center\">\n {/* The top margin keeps the heading clear of the links when the\n cards stack and this one is only as tall as its content. */}\n <div className=\"ds:mt-[var(--spacing-md)] ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n {links.map((option, index) => (\n <Button\n // Two options may share an address, so the place in the\n // list is part of the key.\n key={`${index}:${option.href}`}\n asChild\n intent=\"primary\"\n startIcon={option.icon}\n className=\"ds:min-h-[var(--min-target-size)] ds:w-full\"\n >\n <a href={option.href} data-action=\"dev-login\">\n {option.label}\n </a>\n </Button>\n ))}\n </div>\n </Card.Body>\n </Card>\n </div>\n );\n },\n);\nLoginDevCard.displayName = 'LoginDevCard';\n"],"names":["LOGIN_FORM_FIELDS","loginFormVariants","cva","columnVariants","hasMessage","errors","focusTargetFor","messages","field","LoginForm","forwardRef","title","description","headingLevel","showLogo","logoMotion","children","initialValues","forgotPasswordHref","submitLabel","submitting","onSubmit","fieldNames","action","hiddenFields","devCard","className","rest","ref","t","useTranslation","titleId","useId","formMessageId","native","email","setEmail","useState","password","setPassword","touched","setTouched","submitted","setSubmitted","serverErrors","setServerErrors","leave","previous","forget","emailInput","useRef","passwordInput","emptyPassword","held","values","_a","_b","invalid","isEmail","due","ownErrors","errorFor","focusRequest","setFocusRequest","target","useEffect","submit","useRegistrationSubmit","answer","next","busy","formAction","useFormAction","forgotLink","isSafeHref","extraFields","useExtraFields","formError","jsxs","jsx","Card","AuthCardHeading","AuthFormMessage","FormField","EmailInput","event","PasswordInput","ExtraFields","Button","AuthTextLink","AuthFormStatus","loginDevCardVariants","LoginDevCard","options","Heading","links","option","MatrixRain","ErrorPageIllustration","index"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "1.54.1",
3
+ "packageVersion": "1.54.2",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -19019,6 +19019,10 @@
19019
19019
  {
19020
19020
  "component": "button",
19021
19021
  "as": "support"
19022
+ },
19023
+ {
19024
+ "component": "button",
19025
+ "as": "custom"
19022
19026
  }
19023
19027
  ],
19024
19028
  "workflows": [