@marktiderman/genesis-ui 2.15.0 → 2.17.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 (36) hide show
  1. package/SKILL.md +2 -1
  2. package/dist/{AppShell-HCXpi6nv.d.ts → AppShell-DDyVqNmJ.d.ts} +12 -2
  3. package/dist/{chunk-46TZGMFW.js → chunk-24NUW3QN.js} +22 -22
  4. package/dist/chunk-24NUW3QN.js.map +1 -0
  5. package/dist/{chunk-DTQHAZWN.js → chunk-3FKF2SN4.js} +19 -5
  6. package/dist/chunk-3FKF2SN4.js.map +1 -0
  7. package/dist/{chunk-25XEXYGC.js → chunk-OT6KKSD2.js} +20 -20
  8. package/dist/chunk-OT6KKSD2.js.map +1 -0
  9. package/dist/{chunk-STZVZUYO.js → chunk-TQ7OJDSU.js} +8 -6
  10. package/dist/chunk-TQ7OJDSU.js.map +1 -0
  11. package/dist/chunk-YCQAYWMX.js +192 -0
  12. package/dist/chunk-YCQAYWMX.js.map +1 -0
  13. package/dist/components/data/index.d.ts +6 -6
  14. package/dist/components/data/index.js +170 -123
  15. package/dist/components/data/index.js.map +1 -1
  16. package/dist/components/layout/detail-page.d.ts +1 -1
  17. package/dist/components/layout/index.d.ts +27 -11
  18. package/dist/components/layout/index.js +73 -23
  19. package/dist/components/layout/index.js.map +1 -1
  20. package/dist/components/layout/settings-page.d.ts +1 -1
  21. package/dist/components/patterns/index.js +3 -2
  22. package/dist/components/patterns/sortable-list.js +2 -1
  23. package/dist/hooks/index.d.ts +2 -2
  24. package/dist/hooks/index.js +2 -1
  25. package/dist/hooks/use-resource-page.d.ts +1 -1
  26. package/dist/index.d.ts +176 -2
  27. package/dist/index.js +9 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/{split-Dk9f4Mi0.d.ts → split-D-uYckQ_.d.ts} +1 -1
  30. package/dist/{use-resource-page-DaJzuq3M.d.ts → use-resource-page-BA1P7xea.d.ts} +1 -1
  31. package/dist/{use-resource-table-easmRDQI.d.ts → use-resource-table-WDqz7oQ-.d.ts} +17 -3
  32. package/package.json +2 -2
  33. package/dist/chunk-25XEXYGC.js.map +0 -1
  34. package/dist/chunk-46TZGMFW.js.map +0 -1
  35. package/dist/chunk-DTQHAZWN.js.map +0 -1
  36. package/dist/chunk-STZVZUYO.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { a as SplitBreakpoint } from '../../split-Dk9f4Mi0.js';
2
+ import { S as SplitBreakpoint } from '../../split-D-uYckQ_.js';
3
3
  import 'class-variance-authority/types';
4
4
  import 'class-variance-authority';
5
5
 
@@ -1,4 +1,4 @@
1
- export { A as AppShell, a as AppShellOptions, b as AppShellPageHeader, c as AppShellProps, d as AppShellSubNavEnd, N as NavItem, P as ParentNavigation, S as SubNavItem, e as SubNavMode, f as SubNavTabs, g as SubNavTabsProps, U as UseAppShellSubNavOptions, u as useAppShellSubNav } from '../../AppShell-HCXpi6nv.js';
1
+ export { A as AppShell, a as AppShellOptions, b as AppShellPageHeader, c as AppShellProps, d as AppShellSubNavEnd, N as NavItem, P as ParentNavigation, S as SubNavItem, e as SubNavMode, f as SubNavTabs, g as SubNavTabsProps, U as UseAppShellSubNavOptions, u as useAppShellSubNav } from '../../AppShell-DDyVqNmJ.js';
2
2
  export { G as GenesisLinkProps, L as LinkComponent } from '../../navigation-vmFJ6r1m.js';
3
3
  export { P as PageHeader, a as PageHeaderOptions, b as PageHeaderProps } from '../../PageHeader-V9lVkZtF.js';
4
4
  export { DetailPage, DetailPageProps } from './detail-page.js';
@@ -8,7 +8,7 @@ export { SettingsPage, SettingsPageProps, SettingsPageSection } from './settings
8
8
  export { BuilderLayout, BuilderLayoutProps, BuilderLayoutSlotProps } from './builder-layout.js';
9
9
  import { a as ContainerProps } from '../../spacing-BS6qECD4.js';
10
10
  export { C as Container, G as GAP_CLASSES, S as Section, b as SectionProps, c as SpaceToken, d as Stack, e as StackProps, f as containerVariants, s as sectionHeadingVariants, g as spaceScale, h as stackVariants } from '../../spacing-BS6qECD4.js';
11
- export { S as Split, a as SplitBreakpoint, b as SplitProps, c as SplitRatio, s as splitVariants } from '../../split-Dk9f4Mi0.js';
11
+ export { a as Split, S as SplitBreakpoint, b as SplitProps, c as SplitRatio, s as splitVariants } from '../../split-D-uYckQ_.js';
12
12
  export { Band, BandLead, BandLeadProps, BandProps, Display, DisplayProps, bandVariants, displayVariants, leadVariants } from './band.js';
13
13
  import * as React from 'react';
14
14
  import { Slots, SlotPropsFor } from '@marktiderman/genesis-core/slots';
@@ -130,11 +130,15 @@ declare const AuthPage: React.ForwardRefExoticComponent<AuthPageProps & React.Re
130
130
  */
131
131
  /** What a host knows about the brand a public page belongs to. */
132
132
  interface PublicBrand {
133
- /** Display name, shown in the header and used as the logo's alt text. */
133
+ /** Display name, shown in the header beside the logo (so the logo itself is decorative, `alt=""`). */
134
134
  name: string;
135
135
  /** Logo image URL. */
136
136
  logoUrl?: string;
137
- /** Accent colour: `#rgb`, `#rrggbb` or `rgb(r, g, b)`. Invalid or absent: Genesis's own primary. */
137
+ /**
138
+ * Accent colour: `#rgb`, `#rrggbb`, `rgb()`/`rgba()`, `hsl()`/`hsla()` or a
139
+ * bare token triplet like `"160 84% 39%"`. Alpha is ignored (the accent is
140
+ * treated as opaque). Invalid or absent: Genesis's own primary.
141
+ */
138
142
  accent?: string;
139
143
  /** Optional wide cover image above the header row. Decorative. */
140
144
  headerImageUrl?: string;
@@ -147,7 +151,12 @@ interface Rgb {
147
151
  }
148
152
  /** WCAG AA for normal-size text. */
149
153
  declare const MIN_TEXT_CONTRAST = 4.5;
150
- /** Parses `#rgb`, `#rrggbb` or `rgb(r, g, b)` / `rgb(r g b)`. Anything else: `null`. */
154
+ /**
155
+ * Parses `#rgb`, `#rrggbb`, `rgb()`/`rgba()`, `hsl()`/`hsla()` (commas or
156
+ * spaces, optional `/` or `,` alpha, which is ignored) and bare HSL triplets
157
+ * like `"160 84% 39%"`. Anything else, including out-of-range channels: `null`.
158
+ * Never throws.
159
+ */
151
160
  declare function parseColor(input: string | undefined | null): Rgb | null;
152
161
  /** WCAG 2 relative luminance, 0 (black) to 1 (white). */
153
162
  declare function relativeLuminance({ r, g, b }: Rgb): number;
@@ -160,19 +169,26 @@ interface AccessibleAccent {
160
169
  accent: Rgb;
161
170
  /** The shade to use for text on white and for fills under white text. Equals `accent` when it already passes. */
162
171
  strong: Rgb;
172
+ /**
173
+ * `strong` as the exact HSL triplet to emit (`"H S% L%"`, 0.1 precision).
174
+ * The contrast check runs on this value, not on the unrounded colour, so
175
+ * what the browser renders is what was checked.
176
+ */
177
+ strongTriplet: string;
163
178
  /** Contrast of the given accent against the background. */
164
179
  ratio: number;
165
- /** Contrast of `strong` against the background (at least `minRatio`). */
180
+ /** Contrast of `strongTriplet`, as rendered, against the background (at least `minRatio`). */
166
181
  strongRatio: number;
167
182
  /** True when `strong` had to be darkened from `accent`. */
168
183
  adjusted: boolean;
169
184
  }
170
185
  /**
171
- * The contrast fallback. Returns the accent unchanged when it reaches
172
- * `minRatio` against `background` (white by default); otherwise the same hue
173
- * and saturation at the highest lightness that does. The search walks
174
- * lightness down in 0.5% steps, so the shade stays as close to the brand as
175
- * the ratio allows, and it always ends: lightness 0 is black, 21:1.
186
+ * The contrast fallback. Returns the accent unchanged when its emitted
187
+ * triplet reaches `minRatio` against `background` (white by default);
188
+ * otherwise the same (rounded) hue and saturation at the highest lightness,
189
+ * to 0.1%, whose emitted triplet does. Every check runs on the value
190
+ * that is actually emitted, after rounding. It always ends: lightness 0 is
191
+ * black, 21:1 on white.
176
192
  */
177
193
  declare function accessibleAccent(accent: Rgb | string, { background, minRatio }?: {
178
194
  background?: Rgb;
@@ -1,5 +1,5 @@
1
- export { AppShell, AppShellPageHeader, AppShellSubNavEnd, PageHeader, SubNavTabs, useAppShellSubNav } from '../../chunk-DTQHAZWN.js';
2
- import '../../chunk-46TZGMFW.js';
1
+ export { AppShell, AppShellPageHeader, AppShellSubNavEnd, PageHeader, SubNavTabs, useAppShellSubNav } from '../../chunk-3FKF2SN4.js';
2
+ import '../../chunk-24NUW3QN.js';
3
3
  export { Stack, stackVariants } from '../../chunk-ORCI5SVM.js';
4
4
  import '../../chunk-B2GIBUQD.js';
5
5
  import '../../chunk-NPNADZHM.js';
@@ -20,8 +20,10 @@ import '../../chunk-OZZTPE7F.js';
20
20
  export { Section, SettingsPage, sectionHeadingVariants } from '../../chunk-P64MFQXZ.js';
21
21
  export { Split, splitVariants } from '../../chunk-D2LIXA2Y.js';
22
22
  export { GAP_CLASSES, spaceScale } from '../../chunk-AVFZ4P4B.js';
23
+ import '../../chunk-YCQAYWMX.js';
23
24
  import { cn } from '../../chunk-NZ5WBA4R.js';
24
25
  export { resolveNavigation } from '../../chunk-J45FHL7D.js';
26
+ import '../../chunk-VFO3I7PV.js';
25
27
  import '../../chunk-424PT5DM.js';
26
28
  import * as React from 'react';
27
29
  import { renderSlot } from '@marktiderman/genesis-core/slots';
@@ -133,9 +135,17 @@ function DefaultFooter({ children, testID }) {
133
135
  // src/components/layout/brand-theme.ts
134
136
  var MIN_TEXT_CONTRAST = 4.5;
135
137
  var WHITE = { r: 255, g: 255, b: 255 };
138
+ var NUM = String.raw`[+-]?(?:\d+\.?\d*|\.\d+)`;
139
+ var HUE = `(${NUM})(?:deg)?`;
140
+ var PCT = `(${NUM})%?`;
141
+ var ALPHA = String.raw`(?:\s*[,/]\s*${NUM}%?)?`;
142
+ var SEP = String.raw`(?:\s*,\s*|\s+)`;
143
+ var HSL_FN = new RegExp(String.raw`^hsla?\(\s*${HUE}${SEP}${PCT}${SEP}${PCT}${ALPHA}\s*\)$`);
144
+ var HSL_BARE = new RegExp(String.raw`^${HUE}\s+(${NUM})%\s+(${NUM})%$`);
136
145
  function parseColor(input) {
137
- if (!input) return null;
146
+ if (typeof input !== "string") return null;
138
147
  const value = input.trim().toLowerCase();
148
+ if (!value) return null;
139
149
  const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/.exec(value);
140
150
  if (hex) {
141
151
  const digits = hex[1];
@@ -150,6 +160,13 @@ function parseColor(input) {
150
160
  if (fn) {
151
161
  const [r, g, b] = [fn[1], fn[2], fn[3]].map(Number);
152
162
  if ([r, g, b].every((c) => c <= 255)) return { r, g, b };
163
+ return null;
164
+ }
165
+ const hsl = HSL_FN.exec(value) ?? HSL_BARE.exec(value);
166
+ if (hsl) {
167
+ const [h, sat, l] = [hsl[1], hsl[2], hsl[3]].map(Number);
168
+ if (![h, sat, l].every(Number.isFinite) || sat < 0 || sat > 100 || l < 0 || l > 100) return null;
169
+ return hslToRgb({ h, s: sat, l });
153
170
  }
154
171
  return null;
155
172
  }
@@ -178,42 +195,75 @@ function rgbToHsl({ r, g, b }) {
178
195
  else h = (rn - gn) / d + 4;
179
196
  return { h: h * 60, s: s * 100, l: l * 100 };
180
197
  }
181
- function hslToRgb({ h, s, l }) {
182
- const sn = s / 100;
183
- const ln = l / 100;
184
- const k = (n) => (n + h / 30) % 12;
185
- const a = sn * Math.min(ln, 1 - ln);
186
- const f = (n) => ln - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
187
- return { r: Math.round(f(0) * 255), g: Math.round(f(8) * 255), b: Math.round(f(4) * 255) };
198
+ function hslToRgb(hsl) {
199
+ const { r, g, b } = hslToRgbExact(hsl);
200
+ return { r: Math.round(r), g: Math.round(g), b: Math.round(b) };
188
201
  }
189
202
  function toHslTriplet(color) {
190
203
  const { h, s, l } = rgbToHsl(color);
191
204
  return `${round(h)} ${round(s)}% ${round(l)}%`;
192
205
  }
193
206
  var round = (n) => Math.round(n * 10) / 10;
207
+ function hslToRgbExact({ h, s, l }) {
208
+ const hn = (h % 360 + 360) % 360;
209
+ const sn = s / 100;
210
+ const ln = l / 100;
211
+ const k = (n) => (n + hn / 30) % 12;
212
+ const a = sn * Math.min(ln, 1 - ln);
213
+ const f = (n) => ln - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
214
+ return { r: f(0) * 255, g: f(8) * 255, b: f(4) * 255 };
215
+ }
216
+ function emittedRatio(hsl, background) {
217
+ return Math.min(contrastRatio(hslToRgbExact(hsl), background), contrastRatio(hslToRgb(hsl), background));
218
+ }
219
+ var tripletOf = ({ h, s, l }) => `${h} ${s}% ${l}%`;
194
220
  function accessibleAccent(accent, { background = WHITE, minRatio = MIN_TEXT_CONTRAST } = {}) {
195
221
  const base = typeof accent === "string" ? parseColor(accent) : accent;
196
222
  if (!base) return null;
197
223
  const ratio = contrastRatio(base, background);
198
- if (ratio >= minRatio) return { accent: base, strong: base, ratio, strongRatio: ratio, adjusted: false };
199
- const { h, s, l } = rgbToHsl(base);
200
- let strong = base;
201
- let strongRatio = ratio;
202
- for (let next = l - 0.5; next >= 0; next -= 0.5) {
203
- strong = hslToRgb({ h, s, l: next });
204
- strongRatio = contrastRatio(strong, background);
205
- if (strongRatio >= minRatio) break;
224
+ const exact = rgbToHsl(base);
225
+ const h = round(exact.h);
226
+ const s = round(exact.s);
227
+ const l = round(exact.l);
228
+ const emitted = emittedRatio({ h, s, l }, background);
229
+ if (emitted >= minRatio) {
230
+ return { accent: base, strong: base, strongTriplet: tripletOf({ h, s, l }), ratio, strongRatio: emitted, adjusted: false };
206
231
  }
207
- if (strongRatio < minRatio) {
208
- strong = { r: 0, g: 0, b: 0 };
209
- strongRatio = contrastRatio(strong, background);
232
+ const start = Math.round(l * 10);
233
+ const pick = (tenths) => {
234
+ const candidate = { h, s, l: tenths / 10 };
235
+ const strongRatio = emittedRatio(candidate, background);
236
+ return strongRatio >= minRatio ? { candidate, strongRatio } : null;
237
+ };
238
+ for (let coarse = start - 10; coarse > -10; coarse -= 10) {
239
+ const floor = Math.max(coarse, 0);
240
+ const passing = pick(floor);
241
+ if (!passing) continue;
242
+ let best = passing;
243
+ for (let fine = Math.min(floor + 9, start - 1); fine > floor; fine -= 1) {
244
+ const found = pick(fine);
245
+ if (found) {
246
+ best = found;
247
+ break;
248
+ }
249
+ }
250
+ const { candidate, strongRatio } = best;
251
+ return { accent: base, strong: hslToRgb(candidate), strongTriplet: tripletOf(candidate), ratio, strongRatio, adjusted: true };
210
252
  }
211
- return { accent: base, strong, ratio, strongRatio, adjusted: true };
253
+ const black = { h: 0, s: 0, l: 0 };
254
+ return {
255
+ accent: base,
256
+ strong: { r: 0, g: 0, b: 0 },
257
+ strongTriplet: tripletOf(black),
258
+ ratio,
259
+ strongRatio: emittedRatio(black, background),
260
+ adjusted: true
261
+ };
212
262
  }
213
263
  function brandThemeStyle(brand) {
214
264
  const result = brand?.accent ? accessibleAccent(brand.accent) : null;
215
265
  if (!result) return {};
216
- const strong = toHslTriplet(result.strong);
266
+ const strong = result.strongTriplet;
217
267
  const foreground = toHslTriplet(WHITE);
218
268
  return {
219
269
  "--brand-accent": toHslTriplet(result.accent),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/layout/auth-page.tsx","../../../src/components/layout/brand-theme.ts","../../../src/components/layout/public-page.tsx"],"names":["React2","jsxs","renderSlot","jsx","DefaultFooter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFO,IAAM,QAAA,GAAiB,KAAA,CAAA,UAAA;AAAA,EAC5B,CACE;AAAA,IACE,QAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,aAAA,GAAgB,KAAA;AAAA,IAChB,QAAQ,EAAC;AAAA,IACT,YAAY,EAAC;AAAA,IACb,MAAA,GAAS,WAAA;AAAA,IACT,SAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,qBAEA,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,WAAA,EAAU,WAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,SAAA,EAAW,EAAA;AAAA,QACT,6DAAA;AAAA,QACA,QAAQ,wBAAA,GAA2B,IAAA;AAAA,QACnC;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,WAAA,EAAU,gBAAA;AAAA,YACV,SAAA,EAAU,6EAAA;AAAA,YAEV,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6CAAA,EACZ,QAAA,EAAA;AAAA,cAAA,UAAA;AAAA,gBACC,eAAA;AAAA,gBACA,KAAA,CAAM,QAAA;AAAA,gBACN,EAAE,GAAG,QAAA,EAAU,MAAA,EAAQ,SAAS,MAAA,IAAU,CAAA,EAAG,MAAM,CAAA,SAAA,CAAA,EAAY;AAAA,gBAC/D,SAAA,CAAU;AAAA,eACZ;AAAA,8BACA,IAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,WAAA,EAAU,gBAAA;AAAA,kBACV,aAAA,EAAa,GAAG,MAAM,CAAA,KAAA,CAAA;AAAA,kBACtB,SAAA,EAAU,wGAAA;AAAA,kBAET,QAAA,EAAA;AAAA,oBAAA,MAAA,GAAS,UAAA,CAAW,aAAA,EAAe,KAAA,CAAM,MAAA,EAAQ,EAAE,QAAA,EAAU,MAAA,EAAQ,MAAA,EAAQ,CAAA,EAAG,MAAM,CAAA,OAAA,CAAA,EAAU,EAAG,SAAA,CAAU,MAAM,CAAA,GAAI,IAAA;AAAA,oBACvH;AAAA;AAAA;AAAA,eACH;AAAA,cACC,MAAA,GACG,UAAA,CAAW,aAAA,EAAe,KAAA,CAAM,QAAQ,EAAE,QAAA,EAAU,MAAA,EAAQ,MAAA,EAAQ,GAAG,MAAM,CAAA,OAAA,CAAA,EAAU,EAAG,SAAA,CAAU,MAAM,CAAA,GAC1G,IAAA;AAAA,cACH,KAAA,mBACC,GAAA;AAAA,gBAAC,GAAA;AAAA,gBAAA;AAAA,kBACC,WAAA,EAAU,iBAAA;AAAA,kBACV,aAAA,EAAa,GAAG,MAAM,CAAA,MAAA,CAAA;AAAA,kBACtB,SAAA,EAAU,2CAAA;AAAA,kBAET,QAAA,EAAA;AAAA;AAAA,eACH,GACE;AAAA,aAAA,EACN;AAAA;AAAA,SACF;AAAA,QACC,KAAA,mBACC,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,WAAA,EAAU,iBAAA;AAAA,YACV,aAAA,EAAa,GAAG,MAAM,CAAA,MAAA,CAAA;AAAA,YACtB,SAAA,EAAW,EAAA;AAAA,cACT,4FAAA;AAAA,cACA,aAAA,KAAkB,UAAU,gBAAA,GAAmB;AAAA,aACjD;AAAA,YAEC,QAAA,EAAA;AAAA;AAAA,SACH,GACE;AAAA;AAAA;AAAA;AAGV;AACA,QAAA,CAAS,WAAA,GAAc,UAAA;AAEvB,SAAS,gBAAgB,EAAE,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,QAAO,EAAgC;AACzF,EAAA,4BACG,QAAA,EAAA,EAAO,WAAA,EAAU,sBAAqB,aAAA,EAAa,MAAA,EAAQ,WAAU,8CAAA,EACnE,QAAA,EAAA;AAAA,IAAA,IAAA,mBACC,GAAA,CAAC,SAAI,aAAA,EAAa,CAAA,EAAG,MAAM,CAAA,KAAA,CAAA,EAAS,SAAA,EAAU,MAAA,EAC3C,QAAA,EAAA,IAAA,EACH,CAAA,GACE,IAAA;AAAA,oBACJ,GAAA,CAAC,QAAG,aAAA,EAAa,CAAA,EAAG,MAAM,CAAA,SAAA,CAAA,EAAa,SAAA,EAAU,iDAC9C,QAAA,EAAA,QAAA,EACH,CAAA;AAAA,IACC,OAAA,mBACC,GAAA,CAAC,GAAA,EAAA,EAAE,aAAA,EAAa,CAAA,EAAG,MAAM,CAAA,QAAA,CAAA,EAAY,SAAA,EAAU,+BAAA,EAC5C,QAAA,EAAA,OAAA,EACH,CAAA,GACE;AAAA,GAAA,EACN,CAAA;AAEJ;AAEA,SAAS,aAAA,CAAc,EAAE,QAAA,EAAU,MAAA,EAAO,EAA8B;AACtE,EAAA,uBACE,GAAA,CAAC,SAAI,WAAA,EAAU,kBAAA,EAAmB,eAAa,MAAA,EAAQ,SAAA,EAAU,uBAC9D,QAAA,EACH,CAAA;AAEJ;AAEA,SAAS,aAAA,CAAc,EAAE,QAAA,EAAU,MAAA,EAAO,EAA8B;AACtE,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,kBAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,SAAA,EAAU,sGAAA;AAAA,MAET;AAAA;AAAA,GACH;AAEJ;;;ACtJO,IAAM,iBAAA,GAAoB;AAEjC,IAAM,QAAa,EAAE,CAAA,EAAG,KAAK,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI;AAGrC,SAAS,WAAW,KAAA,EAA8C;AACvE,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,EAAK,CAAE,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,8BAAA,CAA+B,IAAA,CAAK,KAAK,CAAA;AACrD,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,MAAM,MAAA,GAAS,IAAI,CAAC,CAAA;AACpB,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,KAAW,CAAA,GAAI,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA;AACxE,IAAA,OAAO;AAAA,MACL,GAAG,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAAA,MAChC,GAAG,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAAA,MAChC,GAAG,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA,EAAG,CAAC,GAAG,EAAE;AAAA,KAClC;AAAA,EACF;AACA,EAAA,MAAM,EAAA,GAAK,iFAAA,CAAkF,IAAA,CAAK,KAAK,CAAA;AACvG,EAAA,IAAI,EAAA,EAAI;AACN,IAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,CAAC,EAAA,CAAG,CAAC,CAAA,EAAG,EAAA,CAAG,CAAC,CAAA,EAAG,EAAA,CAAG,CAAC,CAAC,CAAA,CAAE,IAAI,MAAM,CAAA;AAClD,IAAA,IAAI,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,EAAE,KAAA,CAAM,CAAC,CAAA,KAAM,CAAA,IAAK,GAAG,CAAA,EAAG,OAAO,EAAE,CAAA,EAAG,GAAG,CAAA,EAAE;AAAA,EACzD;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,iBAAA,CAAkB,EAAE,CAAA,EAAG,CAAA,EAAG,GAAE,EAAgB;AAC1D,EAAA,MAAM,GAAA,GAAM,CAAC,CAAA,KAAc;AACzB,IAAA,MAAM,IAAI,CAAA,GAAI,GAAA;AACd,IAAA,OAAO,KAAK,OAAA,GAAU,CAAA,GAAI,KAAA,GAAA,CAAA,CAAU,CAAA,GAAI,SAAS,KAAA,KAAU,GAAA;AAAA,EAC7D,CAAA;AACA,EAAA,OAAO,MAAA,GAAS,GAAA,CAAI,CAAC,CAAA,GAAI,MAAA,GAAS,IAAI,CAAC,CAAA,GAAI,MAAA,GAAS,GAAA,CAAI,CAAC,CAAA;AAC3D;AAGO,SAAS,aAAA,CAAc,GAAQ,CAAA,EAAgB;AACpD,EAAA,MAAM,CAAC,EAAA,EAAI,EAAE,CAAA,GAAI,CAAC,kBAAkB,CAAC,CAAA,EAAG,iBAAA,CAAkB,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AAClF,EAAA,OAAA,CAAQ,EAAA,GAAK,SAAS,EAAA,GAAK,IAAA,CAAA;AAC7B;AAGO,SAAS,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,GAAE,EAA6C;AAC9E,EAAA,MAAM,CAAC,EAAA,EAAI,EAAA,EAAI,EAAE,CAAA,GAAI,CAAC,CAAA,GAAI,GAAA,EAAK,CAAA,GAAI,GAAA,EAAK,CAAA,GAAI,GAAG,CAAA;AAC/C,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAI,EAAE,CAAA;AAC/B,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAI,EAAE,CAAA;AAC/B,EAAA,MAAM,CAAA,GAAA,CAAK,MAAM,GAAA,IAAO,CAAA;AACxB,EAAA,IAAI,GAAA,KAAQ,GAAA,EAAK,OAAO,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,GAAI,GAAA,EAAI;AACjD,EAAA,MAAM,IAAI,GAAA,GAAM,GAAA;AAChB,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,GAAM,CAAA,IAAK,IAAI,GAAA,GAAM,GAAA,CAAA,GAAO,KAAK,GAAA,GAAM,GAAA,CAAA;AACrD,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI,GAAA,KAAQ,IAAI,CAAA,GAAA,CAAK,EAAA,GAAK,MAAM,CAAA,IAAK,EAAA,GAAK,KAAK,CAAA,GAAI,CAAA,CAAA;AAAA,OAAA,IAC1C,GAAA,KAAQ,EAAA,EAAI,CAAA,GAAA,CAAK,EAAA,GAAK,MAAM,CAAA,GAAI,CAAA;AAAA,OACpC,CAAA,GAAA,CAAK,EAAA,GAAK,EAAA,IAAM,CAAA,GAAI,CAAA;AACzB,EAAA,OAAO,EAAE,GAAG,CAAA,GAAI,EAAA,EAAI,GAAG,CAAA,GAAI,GAAA,EAAK,CAAA,EAAG,CAAA,GAAI,GAAA,EAAI;AAC7C;AAGO,SAAS,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,GAAE,EAA6C;AAC9E,EAAA,MAAM,KAAK,CAAA,GAAI,GAAA;AACf,EAAA,MAAM,KAAK,CAAA,GAAI,GAAA;AACf,EAAA,MAAM,CAAA,GAAI,CAAC,CAAA,KAAA,CAAe,CAAA,GAAI,IAAI,EAAA,IAAM,EAAA;AACxC,EAAA,MAAM,IAAI,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAI,EAAE,CAAA;AAClC,EAAA,MAAM,CAAA,GAAI,CAAC,CAAA,KAAc,EAAA,GAAK,IAAI,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,GAAI,EAAE,CAAC,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA;AACxF,EAAA,OAAO,EAAE,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,CAAC,CAAA,GAAI,GAAG,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,EAAE,CAAC,CAAA,GAAI,GAAG,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,CAAE,CAAC,CAAA,GAAI,GAAG,CAAA,EAAE;AAC3F;AAGO,SAAS,aAAa,KAAA,EAAoB;AAC/C,EAAA,MAAM,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,GAAI,SAAS,KAAK,CAAA;AAClC,EAAA,OAAO,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAC,CAAA,EAAA,EAAK,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,CAAA;AAC7C;AAEA,IAAM,QAAQ,CAAC,CAAA,KAAc,KAAK,KAAA,CAAM,CAAA,GAAI,EAAE,CAAA,GAAI,EAAA;AAsB3C,SAAS,gBAAA,CACd,QACA,EAAE,UAAA,GAAa,OAAO,QAAA,GAAW,iBAAA,EAAkB,GAA6C,EAAC,EACxE;AACzB,EAAA,MAAM,OAAO,OAAO,MAAA,KAAW,QAAA,GAAW,UAAA,CAAW,MAAM,CAAA,GAAI,MAAA;AAC/D,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,UAAU,CAAA;AAC5C,EAAA,IAAI,KAAA,IAAS,QAAA,EAAU,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,QAAA,EAAU,KAAA,EAAM;AACvG,EAAA,MAAM,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE,GAAI,SAAS,IAAI,CAAA;AACjC,EAAA,IAAI,MAAA,GAAS,IAAA;AACb,EAAA,IAAI,WAAA,GAAc,KAAA;AAClB,EAAA,KAAA,IAAS,OAAO,CAAA,GAAI,GAAA,EAAK,IAAA,IAAQ,CAAA,EAAG,QAAQ,GAAA,EAAK;AAC/C,IAAA,MAAA,GAAS,SAAS,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,MAAM,CAAA;AACnC,IAAA,WAAA,GAAc,aAAA,CAAc,QAAQ,UAAU,CAAA;AAC9C,IAAA,IAAI,eAAe,QAAA,EAAU;AAAA,EAC/B;AACA,EAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,IAAA,MAAA,GAAS,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAC5B,IAAA,WAAA,GAAc,aAAA,CAAc,QAAQ,UAAU,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,QAAQ,KAAA,EAAO,WAAA,EAAa,UAAU,IAAA,EAAK;AACpE;AAMO,SAAS,gBAAgB,KAAA,EAAqE;AACnG,EAAA,MAAM,SAAS,KAAA,EAAO,MAAA,GAAS,gBAAA,CAAiB,KAAA,CAAM,MAAM,CAAA,GAAI,IAAA;AAChE,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AACrB,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,MAAA,CAAO,MAAM,CAAA;AACzC,EAAA,MAAM,UAAA,GAAa,aAAa,KAAK,CAAA;AACrC,EAAA,OAAO;AAAA,IACL,gBAAA,EAAkB,YAAA,CAAa,MAAA,CAAO,MAAM,CAAA;AAAA,IAC5C,uBAAA,EAAyB,MAAA;AAAA,IACzB,2BAAA,EAA6B,UAAA;AAAA,IAC7B,WAAA,EAAa,MAAA;AAAA,IACb,sBAAA,EAAwB,UAAA;AAAA,IACxB,QAAA,EAAU;AAAA,GACZ;AACF;AC3GO,IAAM,UAAA,GAAmBA,KAAA,CAAA,UAAA;AAAA,EAC9B,CACE;AAAA,IACE,KAAA;AAAA,IACA,KAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA,GAAW,IAAA;AAAA,IACX,SAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAA,GAAW,KAAA;AAAA,IACX,QAAQ,EAAC;AAAA,IACT,YAAY,EAAC;AAAA,IACb,MAAA,GAAS,aAAA;AAAA,IACT,SAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,MAAM,aAAA,GAAgB,SAAA,KAAc,MAAA,IAAa,SAAA,KAAc,QAAQ,SAAA,KAAc,KAAA;AACrF,IAAA,MAAM,YAAY,aAAA,IAAkB,MAAA,KAAW,MAAA,IAAa,MAAA,KAAW,QAAQ,MAAA,KAAW,KAAA;AAC1F,IAAA,uBACEC,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAA,EAAU,aAAA;AAAA,QACV,eAAA,EAAe,WAAW,MAAA,GAAS,MAAA;AAAA,QACnC,aAAA,EAAa,MAAA;AAAA,QACb,SAAA,EAAW,EAAA;AAAA,UACT,8CAAA;AAAA,UACA,WAAW,gBAAA,GAAmB,yBAAA;AAAA,UAC9B;AAAA,SACF;AAAA,QACA,OAAO,EAAE,GAAG,gBAAgB,KAAK,CAAA,EAAG,GAAG,KAAA,EAAM;AAAA,QAC5C,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,CAAC,QAAA,IAAY,KAAA,GACVC,UAAAA,CAAW,aAAA,EAAe,MAAM,MAAA,EAAQ,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAG,MAAM,CAAA,OAAA,CAAA,EAAU,EAAG,SAAA,CAAU,MAAM,CAAA,GAC/F,IAAA;AAAA,0BACJC,GAAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,kBAAA;AAAA,cACV,aAAA,EAAa,GAAG,MAAM,CAAA,KAAA,CAAA;AAAA,cACtB,SAAA,EAAW,EAAA,CAAG,8BAAA,EAAgC,QAAA,GAAW,SAAS,eAAe,CAAA;AAAA,cAEjF,0BAAAF,IAAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAM,QAAA,EAAU,WAAU,6BAAA,EAClC,QAAA,EAAA;AAAA,gBAAA,KAAA,mBACCA,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,qBAAA,EAAsB,WAAU,6BAAA,EAC7C,QAAA,EAAA;AAAA,kCAAAE,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,2DAAA,EAA6D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,kBAChF,8BAAcA,GAAAA,CAAC,OAAE,SAAA,EAAU,uBAAA,EAAyB,uBAAY,CAAA,GAAO;AAAA,iBAAA,EAC1E,CAAA,GACE,IAAA;AAAA,gBACH;AAAA,eAAA,EACH;AAAA;AAAA,WACF;AAAA,UACC,CAAC,YAAY,SAAA,GACVD,UAAAA;AAAA,YACEE,cAAAA;AAAA,YACA,KAAA,CAAM,MAAA;AAAA,YACN,EAAE,QAAA,EAAU,MAAA,EAAQ,SAAA,EAAW,aAAA,GAAgB,YAAY,MAAA,EAAW,MAAA,EAAQ,CAAA,EAAG,MAAM,CAAA,OAAA,CAAA,EAAU;AAAA,YACjG,SAAA,CAAU;AAAA,WACZ,GACA;AAAA;AAAA;AAAA,KACN;AAAA,EAEJ;AACF;AACA,UAAA,CAAW,WAAA,GAAc,YAAA;AAEzB,SAAS,aAAA,CAAc,EAAE,KAAA,EAAO,MAAA,EAAO,EAAgC;AACrE,EAAA,uBACEH,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,oBAAA;AAAA,MACV,aAAA,EAAa,MAAA;AAAA,MACb,SAAA,EAAU,oGAAA;AAAA,MAET,QAAA,EAAA;AAAA,QAAA,KAAA,CAAM,iCACLE,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAK,KAAA,CAAM,cAAA;AAAA,YACX,GAAA,EAAI,EAAA;AAAA,YACJ,WAAA,EAAU,mBAAA;AAAA,YACV,SAAA,EAAU;AAAA;AAAA,SACZ,GACE,IAAA;AAAA,wBACJF,IAAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAK,IAAA,EAAK,WAAU,uCAAA,EAC5B,QAAA,EAAA;AAAA,UAAA,KAAA,CAAM,OAAA;AAAA;AAAA;AAAA,4BAGLE,GAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,OAAA,EAAS,GAAA,EAAI,EAAA,EAAG,WAAA,EAAU,kBAAA,EAAmB,SAAA,EAAU,6CAAA,EAA8C;AAAA,cACnH,IAAA;AAAA,0BACJA,IAAC,MAAA,EAAA,EAAK,WAAA,EAAU,0BAAyB,SAAA,EAAU,gCAAA,EAChD,gBAAM,IAAA,EACT;AAAA,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;AAEA,SAASC,cAAAA,CAAc,EAAE,QAAA,EAAU,SAAA,EAAW,QAAO,EAAgC;AACnF,EAAA,uBACED,IAAC,QAAA,EAAA,EAAO,WAAA,EAAU,sBAAqB,aAAA,EAAa,MAAA,EAAQ,SAAA,EAAU,wBAAA,EACpE,QAAA,kBAAAF,IAAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,IAAA;AAAA,MACL,SAAA,EAAU,6HAAA;AAAA,MAET,QAAA,EAAA;AAAA,QAAA,QAAA,mBAAWE,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,SAAA,EAAW,UAAS,CAAA,GAAS,IAAA;AAAA,QACvD,4BACCF,IAAAA,CAAC,OAAE,WAAA,EAAU,wBAAA,EAAyB,WAAU,YAAA,EAAa,QAAA,EAAA;AAAA,UAAA,aAAA;AAAA,UAC/C;AAAA,SAAA,EACd,CAAA,GACE;AAAA;AAAA;AAAA,GACN,EACF,CAAA;AAEJ","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { renderSlot, type SlotPropsFor, type Slots } from \"@marktiderman/genesis-core/slots\";\nimport { cn } from \"../../utils\";\n\n/**\n * The brand block above the card. Same fields as native `AuthBrandingProps`\n * (`logo`, `headline`, `subhead`), except that `headline` is required here:\n * it is the page's `<h1>`.\n */\nexport interface AuthPageBrandingProps {\n /** Brand mark (logo node). */\n logo?: React.ReactNode;\n /** \"Sign in\", \"Reset your password\", \"You're invited\". Renders as the page's h1. */\n headline: React.ReactNode;\n /** One line under the headline. */\n subhead?: React.ReactNode;\n testID?: string;\n}\n\n/** The parts of an {@link AuthPage} that `slots` and `slotProps` reach. Names match native `AuthScreenSlotMap`. */\nexport type AuthPageSlotMap = {\n branding: AuthPageBrandingProps & { testID: string };\n social: { children: React.ReactNode; testID: string };\n footer: { children: React.ReactNode; testID: string };\n};\n\nexport interface AuthPageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Logo, headline (h1) and subhead above the card. */\n branding: AuthPageBrandingProps;\n /** Sign-in provider buttons (Google, Apple…), above the form inside the card. */\n social?: React.ReactNode;\n /** The form: sign-in, sign-up, reset, invite acceptance, verify. The card's body. */\n children?: React.ReactNode;\n /** Below the card: \"Forgot password?\", \"Create account\". */\n footer?: React.ReactNode;\n /** The small print under everything: terms and privacy. */\n legal?: React.ReactNode;\n /**\n * A panel beside the card on wide screens (an illustration, a quote, a\n * product shot). Hidden below the `lg` breakpoint, where the card is the\n * whole page.\n */\n aside?: React.ReactNode;\n /** Which side `aside` sits on. Default `\"end\"`. */\n asidePosition?: \"start\" | \"end\";\n /** Replace (a component) or drop (`null`) one part. */\n slots?: Slots<AuthPageSlotMap>;\n /** More props for a default part, merged over what the page passes. */\n slotProps?: SlotPropsFor<AuthPageSlotMap>;\n /** testID on the root. Default `\"auth-page\"`; parts use `${testID}-branding`, `-card`, `-social`, `-footer`, `-legal`, `-aside`. */\n testID?: string;\n}\n\n/**\n * AuthPage — the web counterpart of native `AuthScreen`: a whole-screen,\n * centred card for sign-in, sign-up, password reset, invite acceptance and\n * email verification.\n *\n * ```tsx\n * <AuthPage\n * branding={{ logo: <Logo />, headline: \"Sign in\", subhead: \"Welcome back.\" }}\n * footer={<><a href=\"/reset\">Forgot password?</a> · <a href=\"/sign-up\">Create account</a></>}\n * legal={<>By continuing you agree to the <a href=\"/terms\">terms</a>.</>}\n * aside={<img src={hero} alt=\"\" />}\n * >\n * <SignInForm />\n * </AuthPage>\n * ```\n *\n * The card column is a `<main>` landmark and the headline is its single\n * `<h1>`, so a screen reader lands on the form's purpose. The page fills the\n * viewport (`min-height: 100dvh`) and the card shrinks to the screen with a\n * 16px gutter, so nothing scrolls sideways at 375px.\n *\n * Native `AuthScreen` takes `form` and `providers` as data and renders its\n * own `AuthForm`; this one is a **layout**, so the form and the provider\n * buttons are nodes the app passes. Slots are the same contract:\n * replace or drop (`null`) `branding`, `social` or `footer`.\n *\n * @stability Beta\n */\nexport const AuthPage = React.forwardRef<HTMLDivElement, AuthPageProps>(\n (\n {\n branding,\n social,\n children,\n footer,\n legal,\n aside,\n asidePosition = \"end\",\n slots = {},\n slotProps = {},\n testID = \"auth-page\",\n className,\n ...props\n },\n ref,\n ) => (\n <div\n ref={ref}\n data-slot=\"auth-page\"\n data-testid={testID}\n className={cn(\n \"flex min-h-dvh w-full min-w-0 bg-background text-foreground\",\n aside ? \"lg:grid lg:grid-cols-2\" : null,\n className,\n )}\n {...props}\n >\n <main\n data-slot=\"auth-page-main\"\n className=\"flex min-w-0 flex-1 flex-col items-center justify-center px-4 py-10 sm:px-6\"\n >\n <div className=\"flex w-full max-w-sm min-w-0 flex-col gap-6\">\n {renderSlot(\n DefaultBranding,\n slots.branding,\n { ...branding, testID: branding.testID ?? `${testID}-branding` },\n slotProps.branding,\n )}\n <div\n data-slot=\"auth-page-card\"\n data-testid={`${testID}-card`}\n className=\"flex min-w-0 flex-col gap-6 rounded-xl border border-border bg-card p-6 text-card-foreground shadow-sm\"\n >\n {social ? renderSlot(DefaultSocial, slots.social, { children: social, testID: `${testID}-social` }, slotProps.social) : null}\n {children}\n </div>\n {footer\n ? renderSlot(DefaultFooter, slots.footer, { children: footer, testID: `${testID}-footer` }, slotProps.footer)\n : null}\n {legal ? (\n <p\n data-slot=\"auth-page-legal\"\n data-testid={`${testID}-legal`}\n className=\"text-center text-xs text-muted-foreground\"\n >\n {legal}\n </p>\n ) : null}\n </div>\n </main>\n {aside ? (\n <aside\n data-slot=\"auth-page-aside\"\n data-testid={`${testID}-aside`}\n className={cn(\n \"relative hidden min-w-0 overflow-hidden bg-muted lg:flex lg:items-center lg:justify-center\",\n asidePosition === \"start\" ? \"lg:order-first\" : null,\n )}\n >\n {aside}\n </aside>\n ) : null}\n </div>\n ),\n);\nAuthPage.displayName = \"AuthPage\";\n\nfunction DefaultBranding({ logo, headline, subhead, testID }: AuthPageSlotMap[\"branding\"]) {\n return (\n <header data-slot=\"auth-page-branding\" data-testid={testID} className=\"flex flex-col items-center gap-3 text-center\">\n {logo ? (\n <div data-testid={`${testID}-logo`} className=\"mb-1\">\n {logo}\n </div>\n ) : null}\n <h1 data-testid={`${testID}-headline`} className=\"text-2xl font-bold tracking-tight break-words\">\n {headline}\n </h1>\n {subhead ? (\n <p data-testid={`${testID}-subhead`} className=\"text-sm text-muted-foreground\">\n {subhead}\n </p>\n ) : null}\n </header>\n );\n}\n\nfunction DefaultSocial({ children, testID }: AuthPageSlotMap[\"social\"]) {\n return (\n <div data-slot=\"auth-page-social\" data-testid={testID} className=\"flex flex-col gap-2\">\n {children}\n </div>\n );\n}\n\nfunction DefaultFooter({ children, testID }: AuthPageSlotMap[\"footer\"]) {\n return (\n <div\n data-slot=\"auth-page-footer\"\n data-testid={testID}\n className=\"flex flex-wrap items-center justify-center gap-x-4 gap-y-2 text-center text-sm text-muted-foreground\"\n >\n {children}\n </div>\n );\n}\n","import type * as React from \"react\";\n\n/**\n * Brand theming for public pages: a host's brand object becomes CSS\n * variables on a page root, so every Genesis component inside it (a\n * `Button`, a focus ring, a link styled `text-primary`) picks up the accent\n * without knowing a brand exists.\n *\n * The accent is the one colour a public page takes from outside the token\n * set, and it is the one most likely to be unreadable: brand palettes are\n * picked for logos, not for 14px text. Emerald `#10b981` with white text is\n * 2.5:1, half of WCAG AA's 4.5:1. So the accent is never used as-is for\n * text or for a button's fill. {@link accessibleAccent} keeps its hue and\n * saturation and lowers its lightness until white text on it (and it as\n * text on white) clears 4.5:1; the raw accent stays available for\n * decoration (`--brand-accent`: a header rule, a border).\n *\n * Variables set (all HSL triplets, the same shape as Genesis tokens, so\n * `hsl(var(--x))` works everywhere):\n *\n * - `--brand-accent`: the accent exactly as given. Decoration only.\n * - `--brand-accent-strong`: the accessible shade. Text and fills.\n * - `--brand-accent-foreground`: text on `--brand-accent-strong`.\n * - `--primary`, `--primary-foreground`, `--ring`: the Genesis tokens,\n * pointed at the accessible shade, which is what makes nested components\n * follow the brand.\n */\n\n/** What a host knows about the brand a public page belongs to. */\nexport interface PublicBrand {\n /** Display name, shown in the header and used as the logo's alt text. */\n name: string;\n /** Logo image URL. */\n logoUrl?: string;\n /** Accent colour: `#rgb`, `#rrggbb` or `rgb(r, g, b)`. Invalid or absent: Genesis's own primary. */\n accent?: string;\n /** Optional wide cover image above the header row. Decorative. */\n headerImageUrl?: string;\n}\n\n/** An sRGB colour, 0-255 per channel. */\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\n/** WCAG AA for normal-size text. */\nexport const MIN_TEXT_CONTRAST = 4.5;\n\nconst WHITE: Rgb = { r: 255, g: 255, b: 255 };\n\n/** Parses `#rgb`, `#rrggbb` or `rgb(r, g, b)` / `rgb(r g b)`. Anything else: `null`. */\nexport function parseColor(input: string | undefined | null): Rgb | null {\n if (!input) return null;\n const value = input.trim().toLowerCase();\n const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/.exec(value);\n if (hex) {\n const digits = hex[1]!;\n const full = digits.length === 3 ? digits.replace(/./g, (c) => c + c) : digits;\n return {\n r: parseInt(full.slice(0, 2), 16),\n g: parseInt(full.slice(2, 4), 16),\n b: parseInt(full.slice(4, 6), 16),\n };\n }\n const fn = /^rgba?\\(\\s*(\\d{1,3})[\\s,]+(\\d{1,3})[\\s,]+(\\d{1,3})\\s*(?:[,/]\\s*[\\d.]+%?\\s*)?\\)$/.exec(value);\n if (fn) {\n const [r, g, b] = [fn[1], fn[2], fn[3]].map(Number) as [number, number, number];\n if ([r, g, b].every((c) => c <= 255)) return { r, g, b };\n }\n return null;\n}\n\n/** WCAG 2 relative luminance, 0 (black) to 1 (white). */\nexport function relativeLuminance({ r, g, b }: Rgb): number {\n const lin = (c: number) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);\n}\n\n/** WCAG 2 contrast ratio between two colours, 1 to 21. */\nexport function contrastRatio(a: Rgb, b: Rgb): number {\n const [hi, lo] = [relativeLuminance(a), relativeLuminance(b)].sort((x, y) => y - x) as [number, number];\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/** sRGB to HSL: hue 0-360, saturation and lightness 0-100. */\nexport function rgbToHsl({ r, g, b }: Rgb): { h: number; s: number; l: number } {\n const [rn, gn, bn] = [r / 255, g / 255, b / 255];\n const max = Math.max(rn, gn, bn);\n const min = Math.min(rn, gn, bn);\n const l = (max + min) / 2;\n if (max === min) return { h: 0, s: 0, l: l * 100 };\n const d = max - min;\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h: number;\n if (max === rn) h = (gn - bn) / d + (gn < bn ? 6 : 0);\n else if (max === gn) h = (bn - rn) / d + 2;\n else h = (rn - gn) / d + 4;\n return { h: h * 60, s: s * 100, l: l * 100 };\n}\n\n/** HSL (hue 0-360, saturation and lightness 0-100) to sRGB. */\nexport function hslToRgb({ h, s, l }: { h: number; s: number; l: number }): Rgb {\n const sn = s / 100;\n const ln = l / 100;\n const k = (n: number) => (n + h / 30) % 12;\n const a = sn * Math.min(ln, 1 - ln);\n const f = (n: number) => ln - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));\n return { r: Math.round(f(0) * 255), g: Math.round(f(8) * 255), b: Math.round(f(4) * 255) };\n}\n\n/** The Genesis token shape: `\"160 84% 39%\"`, for `hsl(var(--x))`. */\nexport function toHslTriplet(color: Rgb): string {\n const { h, s, l } = rgbToHsl(color);\n return `${round(h)} ${round(s)}% ${round(l)}%`;\n}\n\nconst round = (n: number) => Math.round(n * 10) / 10;\n\nexport interface AccessibleAccent {\n /** The accent as given. */\n accent: Rgb;\n /** The shade to use for text on white and for fills under white text. Equals `accent` when it already passes. */\n strong: Rgb;\n /** Contrast of the given accent against the background. */\n ratio: number;\n /** Contrast of `strong` against the background (at least `minRatio`). */\n strongRatio: number;\n /** True when `strong` had to be darkened from `accent`. */\n adjusted: boolean;\n}\n\n/**\n * The contrast fallback. Returns the accent unchanged when it reaches\n * `minRatio` against `background` (white by default); otherwise the same hue\n * and saturation at the highest lightness that does. The search walks\n * lightness down in 0.5% steps, so the shade stays as close to the brand as\n * the ratio allows, and it always ends: lightness 0 is black, 21:1.\n */\nexport function accessibleAccent(\n accent: Rgb | string,\n { background = WHITE, minRatio = MIN_TEXT_CONTRAST }: { background?: Rgb; minRatio?: number } = {},\n): AccessibleAccent | null {\n const base = typeof accent === \"string\" ? parseColor(accent) : accent;\n if (!base) return null;\n const ratio = contrastRatio(base, background);\n if (ratio >= minRatio) return { accent: base, strong: base, ratio, strongRatio: ratio, adjusted: false };\n const { h, s, l } = rgbToHsl(base);\n let strong = base;\n let strongRatio = ratio;\n for (let next = l - 0.5; next >= 0; next -= 0.5) {\n strong = hslToRgb({ h, s, l: next });\n strongRatio = contrastRatio(strong, background);\n if (strongRatio >= minRatio) break;\n }\n if (strongRatio < minRatio) {\n strong = { r: 0, g: 0, b: 0 };\n strongRatio = contrastRatio(strong, background);\n }\n return { accent: base, strong, ratio, strongRatio, adjusted: true };\n}\n\n/**\n * The CSS variables for a brand's accent, for a page root's `style`. Empty\n * when the brand has no valid accent, so the page keeps Genesis's primary.\n */\nexport function brandThemeStyle(brand: Pick<PublicBrand, \"accent\"> | undefined): React.CSSProperties {\n const result = brand?.accent ? accessibleAccent(brand.accent) : null;\n if (!result) return {};\n const strong = toHslTriplet(result.strong);\n const foreground = toHslTriplet(WHITE);\n return {\n \"--brand-accent\": toHslTriplet(result.accent),\n \"--brand-accent-strong\": strong,\n \"--brand-accent-foreground\": foreground,\n \"--primary\": strong,\n \"--primary-foreground\": foreground,\n \"--ring\": strong,\n } as React.CSSProperties;\n}\n","import * as React from \"react\";\nimport { renderSlot, type SlotPropsFor, type Slots } from \"@marktiderman/genesis-core/slots\";\nimport { cn } from \"../../utils\";\nimport { Container, type ContainerProps } from \"./container\";\nimport { brandThemeStyle, type PublicBrand } from \"./brand-theme\";\n\n/** The parts of a {@link PublicPage} that `slots` and `slotProps` reach. */\nexport type PublicPageSlotMap = {\n header: { brand: PublicBrand; testID: string };\n footer: { children: React.ReactNode; poweredBy?: React.ReactNode; testID: string };\n};\n\nexport interface PublicPageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /**\n * The brand the page belongs to. Its header (logo, name, cover image) shows\n * at the top, and its `accent` themes the page: see `brandThemeStyle`.\n */\n brand?: PublicBrand;\n /** Optional page heading, rendered as the page's `<h1>` above the content. Leave it out when the content brings its own (a form's title). */\n title?: React.ReactNode;\n /** Supporting copy under `title`. */\n description?: React.ReactNode;\n /** Width of the content column: a `Container` size. Default `\"sm\"`. */\n maxWidth?: NonNullable<ContainerProps[\"size\"]>;\n /**\n * Who runs the page, as \"Powered by …\" in the footer (a name or a link).\n * Leave it out, or pass `false`, to hide it.\n */\n poweredBy?: React.ReactNode;\n /** More footer content: privacy and terms links, an address. */\n footer?: React.ReactNode;\n /**\n * For an iframe: no header or footer chrome, a transparent background and\n * no full-viewport height, so the frame is as tall as its content. The\n * brand accent still applies. A host usually sets it from `?embed=1`.\n */\n embedded?: boolean;\n /** Replace (a component) or drop (`null`) the header or footer. */\n slots?: Slots<PublicPageSlotMap>;\n /** More props for a default part, merged over what the page passes. */\n slotProps?: SlotPropsFor<PublicPageSlotMap>;\n /** testID on the root. Default `\"public-page\"`; parts use `${testID}-header`, `-main`, `-footer`. */\n testID?: string;\n}\n\n/**\n * PublicPage — a page anyone can open without signing in: a public form, a\n * QR poster, a landing page. A brand header, one content column, and a\n * \"Powered by …\" footer, themed from a brand object.\n *\n * ```tsx\n * <PublicPage\n * brand={{ name: \"Riverside Physio\", logoUrl, accent: \"#10b981\" }}\n * poweredBy={<a href=\"https://example.com\">Example</a>}\n * embedded={searchParams.get(\"embed\") === \"1\"}\n * >\n * <Form … />\n * </PublicPage>\n * ```\n *\n * The brand's accent becomes `--primary` (darkened when it fails 4.5:1 on\n * white) on the page root, so a `Button` or link inside follows the brand\n * with no props. The check is against white, Genesis's light background;\n * under a `.dark` theme the fill stays readable (white on the shade) but\n * accent-coloured text may not, so public pages are best served light.\n *\n * `embedded` is the frame-ancestors case. It drops the header and footer,\n * the background and `min-height: 100dvh` (inside an iframe the viewport is\n * the frame, so a full-height page would never let the frame shrink to its\n * content).\n *\n * This is a **layout**: it positions content and binds to nothing. The\n * content column is a `Container` for the one-home reason.\n *\n * @stability Beta\n */\nexport const PublicPage = React.forwardRef<HTMLDivElement, PublicPageProps>(\n (\n {\n brand,\n title,\n description,\n maxWidth = \"sm\",\n poweredBy,\n footer,\n embedded = false,\n slots = {},\n slotProps = {},\n testID = \"public-page\",\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const showPoweredBy = poweredBy !== undefined && poweredBy !== null && poweredBy !== false;\n const hasFooter = showPoweredBy || (footer !== undefined && footer !== null && footer !== false);\n return (\n <div\n ref={ref}\n data-slot=\"public-page\"\n data-embedded={embedded ? \"true\" : undefined}\n data-testid={testID}\n className={cn(\n \"flex w-full min-w-0 flex-col text-foreground\",\n embedded ? \"bg-transparent\" : \"min-h-dvh bg-background\",\n className,\n )}\n style={{ ...brandThemeStyle(brand), ...style }}\n {...props}\n >\n {!embedded && brand\n ? renderSlot(DefaultHeader, slots.header, { brand, testID: `${testID}-header` }, slotProps.header)\n : null}\n <main\n data-slot=\"public-page-main\"\n data-testid={`${testID}-main`}\n className={cn(\"flex min-w-0 flex-1 flex-col\", embedded ? \"py-4\" : \"py-8 sm:py-12\")}\n >\n <Container size={maxWidth} className=\"flex min-w-0 flex-col gap-6\">\n {title ? (\n <div data-slot=\"public-page-heading\" className=\"flex min-w-0 flex-col gap-1\">\n <h1 className=\"text-2xl font-bold tracking-tight break-words sm:text-3xl\">{title}</h1>\n {description ? <p className=\"text-muted-foreground\">{description}</p> : null}\n </div>\n ) : null}\n {children}\n </Container>\n </main>\n {!embedded && hasFooter\n ? renderSlot(\n DefaultFooter,\n slots.footer,\n { children: footer, poweredBy: showPoweredBy ? poweredBy : undefined, testID: `${testID}-footer` },\n slotProps.footer,\n )\n : null}\n </div>\n );\n },\n);\nPublicPage.displayName = \"PublicPage\";\n\nfunction DefaultHeader({ brand, testID }: PublicPageSlotMap[\"header\"]) {\n return (\n <header\n data-slot=\"public-page-header\"\n data-testid={testID}\n className=\"border-b border-border border-t-4 border-t-[hsl(var(--brand-accent,var(--primary)))] bg-background\"\n >\n {brand.headerImageUrl ? (\n <img\n src={brand.headerImageUrl}\n alt=\"\"\n data-slot=\"public-page-cover\"\n className=\"block h-28 w-full object-cover sm:h-44\"\n />\n ) : null}\n <Container size=\"lg\" className=\"flex min-h-14 items-center gap-3 py-3\">\n {brand.logoUrl ? (\n // The name is beside it, so the image is decorative: an alt of the\n // name would read it twice.\n <img src={brand.logoUrl} alt=\"\" data-slot=\"public-page-logo\" className=\"h-8 w-auto max-w-32 shrink-0 object-contain\" />\n ) : null}\n <span data-slot=\"public-page-brand-name\" className=\"min-w-0 truncate font-semibold\">\n {brand.name}\n </span>\n </Container>\n </header>\n );\n}\n\nfunction DefaultFooter({ children, poweredBy, testID }: PublicPageSlotMap[\"footer\"]) {\n return (\n <footer data-slot=\"public-page-footer\" data-testid={testID} className=\"border-t border-border\">\n <Container\n size=\"lg\"\n className=\"flex flex-col items-center gap-2 py-6 text-center text-sm text-muted-foreground sm:flex-row sm:justify-between sm:text-left\"\n >\n {children ? <div className=\"min-w-0\">{children}</div> : null}\n {poweredBy ? (\n <p data-slot=\"public-page-powered-by\" className=\"sm:ml-auto\">\n Powered by {poweredBy}\n </p>\n ) : null}\n </Container>\n </footer>\n );\n}\n"]}
1
+ {"version":3,"sources":["../../../src/components/layout/auth-page.tsx","../../../src/components/layout/brand-theme.ts","../../../src/components/layout/public-page.tsx"],"names":["React2","jsxs","renderSlot","jsx","DefaultFooter"],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { renderSlot, type SlotPropsFor, type Slots } from \"@marktiderman/genesis-core/slots\";\nimport { cn } from \"../../utils\";\n\n/**\n * The brand block above the card. Same fields as native `AuthBrandingProps`\n * (`logo`, `headline`, `subhead`), except that `headline` is required here:\n * it is the page's `<h1>`.\n */\nexport interface AuthPageBrandingProps {\n /** Brand mark (logo node). */\n logo?: React.ReactNode;\n /** \"Sign in\", \"Reset your password\", \"You're invited\". Renders as the page's h1. */\n headline: React.ReactNode;\n /** One line under the headline. */\n subhead?: React.ReactNode;\n testID?: string;\n}\n\n/** The parts of an {@link AuthPage} that `slots` and `slotProps` reach. Names match native `AuthScreenSlotMap`. */\nexport type AuthPageSlotMap = {\n branding: AuthPageBrandingProps & { testID: string };\n social: { children: React.ReactNode; testID: string };\n footer: { children: React.ReactNode; testID: string };\n};\n\nexport interface AuthPageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Logo, headline (h1) and subhead above the card. */\n branding: AuthPageBrandingProps;\n /** Sign-in provider buttons (Google, Apple…), above the form inside the card. */\n social?: React.ReactNode;\n /** The form: sign-in, sign-up, reset, invite acceptance, verify. The card's body. */\n children?: React.ReactNode;\n /** Below the card: \"Forgot password?\", \"Create account\". */\n footer?: React.ReactNode;\n /** The small print under everything: terms and privacy. */\n legal?: React.ReactNode;\n /**\n * A panel beside the card on wide screens (an illustration, a quote, a\n * product shot). Hidden below the `lg` breakpoint, where the card is the\n * whole page.\n */\n aside?: React.ReactNode;\n /** Which side `aside` sits on. Default `\"end\"`. */\n asidePosition?: \"start\" | \"end\";\n /** Replace (a component) or drop (`null`) one part. */\n slots?: Slots<AuthPageSlotMap>;\n /** More props for a default part, merged over what the page passes. */\n slotProps?: SlotPropsFor<AuthPageSlotMap>;\n /** testID on the root. Default `\"auth-page\"`; parts use `${testID}-branding`, `-card`, `-social`, `-footer`, `-legal`, `-aside`. */\n testID?: string;\n}\n\n/**\n * AuthPage — the web counterpart of native `AuthScreen`: a whole-screen,\n * centred card for sign-in, sign-up, password reset, invite acceptance and\n * email verification.\n *\n * ```tsx\n * <AuthPage\n * branding={{ logo: <Logo />, headline: \"Sign in\", subhead: \"Welcome back.\" }}\n * footer={<><a href=\"/reset\">Forgot password?</a> · <a href=\"/sign-up\">Create account</a></>}\n * legal={<>By continuing you agree to the <a href=\"/terms\">terms</a>.</>}\n * aside={<img src={hero} alt=\"\" />}\n * >\n * <SignInForm />\n * </AuthPage>\n * ```\n *\n * The card column is a `<main>` landmark and the headline is its single\n * `<h1>`, so a screen reader lands on the form's purpose. The page fills the\n * viewport (`min-height: 100dvh`) and the card shrinks to the screen with a\n * 16px gutter, so nothing scrolls sideways at 375px.\n *\n * Native `AuthScreen` takes `form` and `providers` as data and renders its\n * own `AuthForm`; this one is a **layout**, so the form and the provider\n * buttons are nodes the app passes. Slots are the same contract:\n * replace or drop (`null`) `branding`, `social` or `footer`.\n *\n * @stability Beta\n */\nexport const AuthPage = React.forwardRef<HTMLDivElement, AuthPageProps>(\n (\n {\n branding,\n social,\n children,\n footer,\n legal,\n aside,\n asidePosition = \"end\",\n slots = {},\n slotProps = {},\n testID = \"auth-page\",\n className,\n ...props\n },\n ref,\n ) => (\n <div\n ref={ref}\n data-slot=\"auth-page\"\n data-testid={testID}\n className={cn(\n \"flex min-h-dvh w-full min-w-0 bg-background text-foreground\",\n aside ? \"lg:grid lg:grid-cols-2\" : null,\n className,\n )}\n {...props}\n >\n <main\n data-slot=\"auth-page-main\"\n className=\"flex min-w-0 flex-1 flex-col items-center justify-center px-4 py-10 sm:px-6\"\n >\n <div className=\"flex w-full max-w-sm min-w-0 flex-col gap-6\">\n {renderSlot(\n DefaultBranding,\n slots.branding,\n { ...branding, testID: branding.testID ?? `${testID}-branding` },\n slotProps.branding,\n )}\n <div\n data-slot=\"auth-page-card\"\n data-testid={`${testID}-card`}\n className=\"flex min-w-0 flex-col gap-6 rounded-xl border border-border bg-card p-6 text-card-foreground shadow-sm\"\n >\n {social ? renderSlot(DefaultSocial, slots.social, { children: social, testID: `${testID}-social` }, slotProps.social) : null}\n {children}\n </div>\n {footer\n ? renderSlot(DefaultFooter, slots.footer, { children: footer, testID: `${testID}-footer` }, slotProps.footer)\n : null}\n {legal ? (\n <p\n data-slot=\"auth-page-legal\"\n data-testid={`${testID}-legal`}\n className=\"text-center text-xs text-muted-foreground\"\n >\n {legal}\n </p>\n ) : null}\n </div>\n </main>\n {aside ? (\n <aside\n data-slot=\"auth-page-aside\"\n data-testid={`${testID}-aside`}\n className={cn(\n \"relative hidden min-w-0 overflow-hidden bg-muted lg:flex lg:items-center lg:justify-center\",\n asidePosition === \"start\" ? \"lg:order-first\" : null,\n )}\n >\n {aside}\n </aside>\n ) : null}\n </div>\n ),\n);\nAuthPage.displayName = \"AuthPage\";\n\nfunction DefaultBranding({ logo, headline, subhead, testID }: AuthPageSlotMap[\"branding\"]) {\n return (\n <header data-slot=\"auth-page-branding\" data-testid={testID} className=\"flex flex-col items-center gap-3 text-center\">\n {logo ? (\n <div data-testid={`${testID}-logo`} className=\"mb-1\">\n {logo}\n </div>\n ) : null}\n <h1 data-testid={`${testID}-headline`} className=\"text-2xl font-bold tracking-tight break-words\">\n {headline}\n </h1>\n {subhead ? (\n <p data-testid={`${testID}-subhead`} className=\"text-sm text-muted-foreground\">\n {subhead}\n </p>\n ) : null}\n </header>\n );\n}\n\nfunction DefaultSocial({ children, testID }: AuthPageSlotMap[\"social\"]) {\n return (\n <div data-slot=\"auth-page-social\" data-testid={testID} className=\"flex flex-col gap-2\">\n {children}\n </div>\n );\n}\n\nfunction DefaultFooter({ children, testID }: AuthPageSlotMap[\"footer\"]) {\n return (\n <div\n data-slot=\"auth-page-footer\"\n data-testid={testID}\n className=\"flex flex-wrap items-center justify-center gap-x-4 gap-y-2 text-center text-sm text-muted-foreground\"\n >\n {children}\n </div>\n );\n}\n","import type * as React from \"react\";\n\n/**\n * Brand theming for public pages: a host's brand object becomes CSS\n * variables on a page root, so every Genesis component inside it (a\n * `Button`, a focus ring, a link styled `text-primary`) picks up the accent\n * without knowing a brand exists.\n *\n * The accent is the one colour a public page takes from outside the token\n * set, and it is the one most likely to be unreadable: brand palettes are\n * picked for logos, not for 14px text. Emerald `#10b981` with white text is\n * 2.5:1, half of WCAG AA's 4.5:1. So the accent is never used as-is for\n * text or for a button's fill. {@link accessibleAccent} keeps its hue and\n * saturation and lowers its lightness until white text on it (and it as\n * text on white) clears 4.5:1; the raw accent stays available for\n * decoration (`--brand-accent`: a header rule, a border).\n *\n * Variables set (all HSL triplets, the same shape as Genesis tokens, so\n * `hsl(var(--x))` works everywhere):\n *\n * - `--brand-accent`: the accent exactly as given. Decoration only.\n * - `--brand-accent-strong`: the accessible shade. Text and fills.\n * - `--brand-accent-foreground`: text on `--brand-accent-strong`.\n * - `--primary`, `--primary-foreground`, `--ring`: the Genesis tokens,\n * pointed at the accessible shade, which is what makes nested components\n * follow the brand.\n */\n\n/** What a host knows about the brand a public page belongs to. */\nexport interface PublicBrand {\n /** Display name, shown in the header beside the logo (so the logo itself is decorative, `alt=\"\"`). */\n name: string;\n /** Logo image URL. */\n logoUrl?: string;\n /**\n * Accent colour: `#rgb`, `#rrggbb`, `rgb()`/`rgba()`, `hsl()`/`hsla()` or a\n * bare token triplet like `\"160 84% 39%\"`. Alpha is ignored (the accent is\n * treated as opaque). Invalid or absent: Genesis's own primary.\n */\n accent?: string;\n /** Optional wide cover image above the header row. Decorative. */\n headerImageUrl?: string;\n}\n\n/** An sRGB colour, 0-255 per channel. */\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\n/** WCAG AA for normal-size text. */\nexport const MIN_TEXT_CONTRAST = 4.5;\n\nconst WHITE: Rgb = { r: 255, g: 255, b: 255 };\n\nconst NUM = String.raw`[+-]?(?:\\d+\\.?\\d*|\\.\\d+)`;\nconst HUE = `(${NUM})(?:deg)?`;\nconst PCT = `(${NUM})%?`;\nconst ALPHA = String.raw`(?:\\s*[,/]\\s*${NUM}%?)?`;\nconst SEP = String.raw`(?:\\s*,\\s*|\\s+)`;\nconst HSL_FN = new RegExp(String.raw`^hsla?\\(\\s*${HUE}${SEP}${PCT}${SEP}${PCT}${ALPHA}\\s*\\)$`);\n// Bare shadcn-style token triplet: percentages required so it can't be read as rgb.\nconst HSL_BARE = new RegExp(String.raw`^${HUE}\\s+(${NUM})%\\s+(${NUM})%$`);\n\n/**\n * Parses `#rgb`, `#rrggbb`, `rgb()`/`rgba()`, `hsl()`/`hsla()` (commas or\n * spaces, optional `/` or `,` alpha, which is ignored) and bare HSL triplets\n * like `\"160 84% 39%\"`. Anything else, including out-of-range channels: `null`.\n * Never throws.\n */\nexport function parseColor(input: string | undefined | null): Rgb | null {\n if (typeof input !== \"string\") return null;\n const value = input.trim().toLowerCase();\n if (!value) return null;\n const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/.exec(value);\n if (hex) {\n const digits = hex[1]!;\n const full = digits.length === 3 ? digits.replace(/./g, (c) => c + c) : digits;\n return {\n r: parseInt(full.slice(0, 2), 16),\n g: parseInt(full.slice(2, 4), 16),\n b: parseInt(full.slice(4, 6), 16),\n };\n }\n const fn = /^rgba?\\(\\s*(\\d{1,3})[\\s,]+(\\d{1,3})[\\s,]+(\\d{1,3})\\s*(?:[,/]\\s*[\\d.]+%?\\s*)?\\)$/.exec(value);\n if (fn) {\n const [r, g, b] = [fn[1], fn[2], fn[3]].map(Number) as [number, number, number];\n if ([r, g, b].every((c) => c <= 255)) return { r, g, b };\n return null;\n }\n const hsl = HSL_FN.exec(value) ?? HSL_BARE.exec(value);\n if (hsl) {\n const [h, sat, l] = [hsl[1], hsl[2], hsl[3]].map(Number) as [number, number, number];\n if (![h, sat, l].every(Number.isFinite) || sat < 0 || sat > 100 || l < 0 || l > 100) return null;\n return hslToRgb({ h, s: sat, l });\n }\n return null;\n}\n\n/** WCAG 2 relative luminance, 0 (black) to 1 (white). */\nexport function relativeLuminance({ r, g, b }: Rgb): number {\n const lin = (c: number) => {\n const s = c / 255;\n return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);\n}\n\n/** WCAG 2 contrast ratio between two colours, 1 to 21. */\nexport function contrastRatio(a: Rgb, b: Rgb): number {\n const [hi, lo] = [relativeLuminance(a), relativeLuminance(b)].sort((x, y) => y - x) as [number, number];\n return (hi + 0.05) / (lo + 0.05);\n}\n\n/** sRGB to HSL: hue 0-360, saturation and lightness 0-100. */\nexport function rgbToHsl({ r, g, b }: Rgb): { h: number; s: number; l: number } {\n const [rn, gn, bn] = [r / 255, g / 255, b / 255];\n const max = Math.max(rn, gn, bn);\n const min = Math.min(rn, gn, bn);\n const l = (max + min) / 2;\n if (max === min) return { h: 0, s: 0, l: l * 100 };\n const d = max - min;\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n let h: number;\n if (max === rn) h = (gn - bn) / d + (gn < bn ? 6 : 0);\n else if (max === gn) h = (bn - rn) / d + 2;\n else h = (rn - gn) / d + 4;\n return { h: h * 60, s: s * 100, l: l * 100 };\n}\n\n/** HSL (hue 0-360, saturation and lightness 0-100) to sRGB, channels rounded to 8 bits. */\nexport function hslToRgb(hsl: { h: number; s: number; l: number }): Rgb {\n const { r, g, b } = hslToRgbExact(hsl);\n return { r: Math.round(r), g: Math.round(g), b: Math.round(b) };\n}\n\n/** The Genesis token shape: `\"160 84% 39%\"`, for `hsl(var(--x))`. */\nexport function toHslTriplet(color: Rgb): string {\n const { h, s, l } = rgbToHsl(color);\n return `${round(h)} ${round(s)}% ${round(l)}%`;\n}\n\nconst round = (n: number) => Math.round(n * 10) / 10;\n\nexport interface AccessibleAccent {\n /** The accent as given. */\n accent: Rgb;\n /** The shade to use for text on white and for fills under white text. Equals `accent` when it already passes. */\n strong: Rgb;\n /**\n * `strong` as the exact HSL triplet to emit (`\"H S% L%\"`, 0.1 precision).\n * The contrast check runs on this value, not on the unrounded colour, so\n * what the browser renders is what was checked.\n */\n strongTriplet: string;\n /** Contrast of the given accent against the background. */\n ratio: number;\n /** Contrast of `strongTriplet`, as rendered, against the background (at least `minRatio`). */\n strongRatio: number;\n /** True when `strong` had to be darkened from `accent`. */\n adjusted: boolean;\n}\n\n/** HSL to sRGB without rounding the channels, for checking what a browser may render. */\nfunction hslToRgbExact({ h, s, l }: { h: number; s: number; l: number }): Rgb {\n const hn = ((h % 360) + 360) % 360;\n const sn = s / 100;\n const ln = l / 100;\n const k = (n: number) => (n + hn / 30) % 12;\n const a = sn * Math.min(ln, 1 - ln);\n const f = (n: number) => ln - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));\n return { r: f(0) * 255, g: f(8) * 255, b: f(4) * 255 };\n}\n\n/**\n * Contrast of an emitted HSL triplet against `background`: the worse of the\n * exact colour and its 8-bit rendering, so neither a float nor a quantising\n * renderer can land under the target.\n */\nfunction emittedRatio(hsl: { h: number; s: number; l: number }, background: Rgb): number {\n return Math.min(contrastRatio(hslToRgbExact(hsl), background), contrastRatio(hslToRgb(hsl), background));\n}\n\nconst tripletOf = ({ h, s, l }: { h: number; s: number; l: number }) => `${h} ${s}% ${l}%`;\n\n/**\n * The contrast fallback. Returns the accent unchanged when its emitted\n * triplet reaches `minRatio` against `background` (white by default);\n * otherwise the same (rounded) hue and saturation at the highest lightness,\n * to 0.1%, whose emitted triplet does. Every check runs on the value\n * that is actually emitted, after rounding. It always ends: lightness 0 is\n * black, 21:1 on white.\n */\nexport function accessibleAccent(\n accent: Rgb | string,\n { background = WHITE, minRatio = MIN_TEXT_CONTRAST }: { background?: Rgb; minRatio?: number } = {},\n): AccessibleAccent | null {\n const base = typeof accent === \"string\" ? parseColor(accent) : accent;\n if (!base) return null;\n const ratio = contrastRatio(base, background);\n const exact = rgbToHsl(base);\n const h = round(exact.h);\n const s = round(exact.s);\n const l = round(exact.l);\n const emitted = emittedRatio({ h, s, l }, background);\n if (emitted >= minRatio) {\n return { accent: base, strong: base, strongTriplet: tripletOf({ h, s, l }), ratio, strongRatio: emitted, adjusted: false };\n }\n // Lightness in integer tenths (no float drift). Walk down in whole\n // percents to the first passing shade, then take the lightest passing\n // tenth above it, so the result stays as close to the brand as it can.\n const start = Math.round(l * 10);\n const pick = (tenths: number) => {\n const candidate = { h, s, l: tenths / 10 };\n const strongRatio = emittedRatio(candidate, background);\n return strongRatio >= minRatio ? { candidate, strongRatio } : null;\n };\n for (let coarse = start - 10; coarse > -10; coarse -= 10) {\n const floor = Math.max(coarse, 0);\n const passing = pick(floor);\n if (!passing) continue;\n let best = passing;\n for (let fine = Math.min(floor + 9, start - 1); fine > floor; fine -= 1) {\n const found = pick(fine);\n if (found) {\n best = found;\n break;\n }\n }\n const { candidate, strongRatio } = best;\n return { accent: base, strong: hslToRgb(candidate), strongTriplet: tripletOf(candidate), ratio, strongRatio, adjusted: true };\n }\n const black = { h: 0, s: 0, l: 0 };\n return {\n accent: base,\n strong: { r: 0, g: 0, b: 0 },\n strongTriplet: tripletOf(black),\n ratio,\n strongRatio: emittedRatio(black, background),\n adjusted: true,\n };\n}\n\n/**\n * The CSS variables for a brand's accent, for a page root's `style`. Empty\n * when the brand has no valid accent, so the page keeps Genesis's primary.\n */\nexport function brandThemeStyle(brand: Pick<PublicBrand, \"accent\"> | undefined): React.CSSProperties {\n const result = brand?.accent ? accessibleAccent(brand.accent) : null;\n if (!result) return {};\n const strong = result.strongTriplet;\n const foreground = toHslTriplet(WHITE);\n return {\n \"--brand-accent\": toHslTriplet(result.accent),\n \"--brand-accent-strong\": strong,\n \"--brand-accent-foreground\": foreground,\n \"--primary\": strong,\n \"--primary-foreground\": foreground,\n \"--ring\": strong,\n } as React.CSSProperties;\n}\n","import * as React from \"react\";\nimport { renderSlot, type SlotPropsFor, type Slots } from \"@marktiderman/genesis-core/slots\";\nimport { cn } from \"../../utils\";\nimport { Container, type ContainerProps } from \"./container\";\nimport { brandThemeStyle, type PublicBrand } from \"./brand-theme\";\n\n/** The parts of a {@link PublicPage} that `slots` and `slotProps` reach. */\nexport type PublicPageSlotMap = {\n header: { brand: PublicBrand; testID: string };\n footer: { children: React.ReactNode; poweredBy?: React.ReactNode; testID: string };\n};\n\nexport interface PublicPageProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /**\n * The brand the page belongs to. Its header (logo, name, cover image) shows\n * at the top, and its `accent` themes the page: see `brandThemeStyle`.\n */\n brand?: PublicBrand;\n /** Optional page heading, rendered as the page's `<h1>` above the content. Leave it out when the content brings its own (a form's title). */\n title?: React.ReactNode;\n /** Supporting copy under `title`. */\n description?: React.ReactNode;\n /** Width of the content column: a `Container` size. Default `\"sm\"`. */\n maxWidth?: NonNullable<ContainerProps[\"size\"]>;\n /**\n * Who runs the page, as \"Powered by …\" in the footer (a name or a link).\n * Leave it out, or pass `false`, to hide it.\n */\n poweredBy?: React.ReactNode;\n /** More footer content: privacy and terms links, an address. */\n footer?: React.ReactNode;\n /**\n * For an iframe: no header or footer chrome, a transparent background and\n * no full-viewport height, so the frame is as tall as its content. The\n * brand accent still applies. A host usually sets it from `?embed=1`.\n */\n embedded?: boolean;\n /** Replace (a component) or drop (`null`) the header or footer. */\n slots?: Slots<PublicPageSlotMap>;\n /** More props for a default part, merged over what the page passes. */\n slotProps?: SlotPropsFor<PublicPageSlotMap>;\n /** testID on the root. Default `\"public-page\"`; parts use `${testID}-header`, `-main`, `-footer`. */\n testID?: string;\n}\n\n/**\n * PublicPage — a page anyone can open without signing in: a public form, a\n * QR poster, a landing page. A brand header, one content column, and a\n * \"Powered by …\" footer, themed from a brand object.\n *\n * ```tsx\n * <PublicPage\n * brand={{ name: \"Riverside Physio\", logoUrl, accent: \"#10b981\" }}\n * poweredBy={<a href=\"https://example.com\">Example</a>}\n * embedded={searchParams.get(\"embed\") === \"1\"}\n * >\n * <Form … />\n * </PublicPage>\n * ```\n *\n * The brand's accent becomes `--primary` (darkened when it fails 4.5:1 on\n * white) on the page root, so a `Button` or link inside follows the brand\n * with no props. The check is against white, Genesis's light background;\n * under a `.dark` theme the fill stays readable (white on the shade) but\n * accent-coloured text may not, so public pages are best served light.\n *\n * `embedded` is the frame-ancestors case. It drops the header and footer,\n * the background and `min-height: 100dvh` (inside an iframe the viewport is\n * the frame, so a full-height page would never let the frame shrink to its\n * content).\n *\n * This is a **layout**: it positions content and binds to nothing. The\n * content column is a `Container` for the one-home reason.\n *\n * @stability Beta\n */\nexport const PublicPage = React.forwardRef<HTMLDivElement, PublicPageProps>(\n (\n {\n brand,\n title,\n description,\n maxWidth = \"sm\",\n poweredBy,\n footer,\n embedded = false,\n slots = {},\n slotProps = {},\n testID = \"public-page\",\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n const showPoweredBy = poweredBy !== undefined && poweredBy !== null && poweredBy !== false;\n const hasFooter = showPoweredBy || (footer !== undefined && footer !== null && footer !== false);\n return (\n <div\n ref={ref}\n data-slot=\"public-page\"\n data-embedded={embedded ? \"true\" : undefined}\n data-testid={testID}\n className={cn(\n \"flex w-full min-w-0 flex-col text-foreground\",\n embedded ? \"bg-transparent\" : \"min-h-dvh bg-background\",\n className,\n )}\n style={{ ...brandThemeStyle(brand), ...style }}\n {...props}\n >\n {!embedded && brand\n ? renderSlot(DefaultHeader, slots.header, { brand, testID: `${testID}-header` }, slotProps.header)\n : null}\n <main\n data-slot=\"public-page-main\"\n data-testid={`${testID}-main`}\n className={cn(\"flex min-w-0 flex-1 flex-col\", embedded ? \"py-4\" : \"py-8 sm:py-12\")}\n >\n <Container size={maxWidth} className=\"flex min-w-0 flex-col gap-6\">\n {title ? (\n <div data-slot=\"public-page-heading\" className=\"flex min-w-0 flex-col gap-1\">\n <h1 className=\"text-2xl font-bold tracking-tight break-words sm:text-3xl\">{title}</h1>\n {description ? <p className=\"text-muted-foreground\">{description}</p> : null}\n </div>\n ) : null}\n {children}\n </Container>\n </main>\n {!embedded && hasFooter\n ? renderSlot(\n DefaultFooter,\n slots.footer,\n { children: footer, poweredBy: showPoweredBy ? poweredBy : undefined, testID: `${testID}-footer` },\n slotProps.footer,\n )\n : null}\n </div>\n );\n },\n);\nPublicPage.displayName = \"PublicPage\";\n\nfunction DefaultHeader({ brand, testID }: PublicPageSlotMap[\"header\"]) {\n return (\n <header\n data-slot=\"public-page-header\"\n data-testid={testID}\n className=\"border-b border-border border-t-4 border-t-[hsl(var(--brand-accent,var(--primary)))] bg-background\"\n >\n {brand.headerImageUrl ? (\n <img\n src={brand.headerImageUrl}\n alt=\"\"\n data-slot=\"public-page-cover\"\n className=\"block h-28 w-full object-cover sm:h-44\"\n />\n ) : null}\n <Container size=\"lg\" className=\"flex min-h-14 items-center gap-3 py-3\">\n {brand.logoUrl ? (\n // The name is beside it, so the image is decorative: an alt of the\n // name would read it twice.\n <img src={brand.logoUrl} alt=\"\" data-slot=\"public-page-logo\" className=\"h-8 w-auto max-w-32 shrink-0 object-contain\" />\n ) : null}\n <span data-slot=\"public-page-brand-name\" className=\"min-w-0 truncate font-semibold\">\n {brand.name}\n </span>\n </Container>\n </header>\n );\n}\n\nfunction DefaultFooter({ children, poweredBy, testID }: PublicPageSlotMap[\"footer\"]) {\n return (\n <footer data-slot=\"public-page-footer\" data-testid={testID} className=\"border-t border-border\">\n <Container\n size=\"lg\"\n className=\"flex flex-col items-center gap-2 py-6 text-center text-sm text-muted-foreground sm:flex-row sm:justify-between sm:text-left\"\n >\n {children ? <div className=\"min-w-0\">{children}</div> : null}\n {poweredBy ? (\n <p data-slot=\"public-page-powered-by\" className=\"sm:ml-auto\">\n Powered by {poweredBy}\n </p>\n ) : null}\n </Container>\n </footer>\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { a as SplitBreakpoint } from '../../split-Dk9f4Mi0.js';
2
+ import { S as SplitBreakpoint } from '../../split-D-uYckQ_.js';
3
3
  import 'class-variance-authority/types';
4
4
  import 'class-variance-authority';
5
5
 
@@ -1,7 +1,7 @@
1
- export { ViewSettings, ViewToggle } from '../../chunk-46TZGMFW.js';
1
+ export { ViewSettings, ViewToggle } from '../../chunk-24NUW3QN.js';
2
2
  export { UserAvatar, userAvatarVariants } from '../../chunk-XBX6QMR5.js';
3
3
  import '../../chunk-LNFF2RBD.js';
4
- export { SortableList } from '../../chunk-25XEXYGC.js';
4
+ export { SortableList } from '../../chunk-OT6KKSD2.js';
5
5
  export { StatusBadge, statusBadgeVariants } from '../../chunk-XMK3T4TA.js';
6
6
  export { ToggleRow } from '../../chunk-6M4NHHKG.js';
7
7
  export { SettingsRow } from '../../chunk-A7AHVDG7.js';
@@ -16,6 +16,7 @@ import '../../chunk-NWSCYLPT.js';
16
16
  import '../../chunk-QJ6P2DW6.js';
17
17
  import '../../chunk-27ELYTGE.js';
18
18
  import '../../chunk-F47U5KNW.js';
19
+ import '../../chunk-YCQAYWMX.js';
19
20
  import '../../chunk-NZ5WBA4R.js';
20
21
  import '../../chunk-424PT5DM.js';
21
22
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
- export { SortableList } from '../../chunk-25XEXYGC.js';
1
+ export { SortableList } from '../../chunk-OT6KKSD2.js';
2
2
  import '../../chunk-I4NBE2KL.js';
3
3
  import '../../chunk-QJ6P2DW6.js';
4
+ import '../../chunk-YCQAYWMX.js';
4
5
  import '../../chunk-NZ5WBA4R.js';
5
6
  import '../../chunk-424PT5DM.js';
6
7
  //# sourceMappingURL=sortable-list.js.map
@@ -6,9 +6,9 @@ export { ResponsiveViewMode, ViewModeDefault, useViewPreference } from './use-vi
6
6
  export { Density, ViewSettings, useViewSettings } from './use-view-settings.js';
7
7
  export { UseSavedViewsReturn, useSavedViews } from './use-saved-views.js';
8
8
  export { RouteMap, createPrefetch } from './use-prefetch.js';
9
- export { R as ResourceTableState, u as useResourceTable } from '../use-resource-table-easmRDQI.js';
9
+ export { R as ResourceTableState, u as useResourceTable } from '../use-resource-table-WDqz7oQ-.js';
10
10
  export { ResourceUrlParams, ResourceUrlState, ResourceUrlStateOptions, useResourceUrlState } from './use-resource-url-state.js';
11
- export { R as ResourceActions, a as ResourceColumnDef, U as UseResourcePageProps, b as UseResourcePageReturn, u as useResourcePage } from '../use-resource-page-DaJzuq3M.js';
11
+ export { R as ResourceActions, a as ResourceColumnDef, U as UseResourcePageProps, b as UseResourcePageReturn, u as useResourcePage } from '../use-resource-page-BA1P7xea.js';
12
12
  export { CommandPalette, CommandPaletteItem, CommandPaletteProps, useCommandPaletteHotkey } from '../components/ui/command-palette.js';
13
13
  import '../navigation-vmFJ6r1m.js';
14
14
  import 'react';
@@ -1,4 +1,4 @@
1
- export { useResourceTable } from '../chunk-STZVZUYO.js';
1
+ export { useResourceTable } from '../chunk-TQ7OJDSU.js';
2
2
  export { useResourcePage } from '../chunk-RKPS7ERS.js';
3
3
  export { useResourceUrlState } from '../chunk-DIV4BYXX.js';
4
4
  export { useSavedViews } from '../chunk-GCQFVMPI.js';
@@ -8,6 +8,7 @@ export { CommandPalette, useCommandPaletteHotkey } from '../chunk-CNTWQSUT.js';
8
8
  import '../chunk-SEFK4NZV.js';
9
9
  import '../chunk-4RAZJ6LL.js';
10
10
  import '../chunk-7XMZVISM.js';
11
+ import '../chunk-YCQAYWMX.js';
11
12
  import '../chunk-NZ5WBA4R.js';
12
13
  export { useDataFilters } from '../chunk-PMCUHSZS.js';
13
14
  import '../chunk-J45FHL7D.js';
@@ -1,5 +1,5 @@
1
1
  import 'react';
2
- export { R as ResourceActions, a as ResourceColumnDef, U as UseResourcePageProps, b as UseResourcePageReturn, t as titleCase, u as useResourcePage } from '../use-resource-page-DaJzuq3M.js';
2
+ export { R as ResourceActions, a as ResourceColumnDef, U as UseResourcePageProps, b as UseResourcePageReturn, t as titleCase, u as useResourcePage } from '../use-resource-page-BA1P7xea.js';
3
3
  import '../view-toggle-CahQ87PW.js';
4
4
  import '@marktiderman/genesis-core/provider';
5
5
  import './use-view-preference.js';