hazo_auth 6.1.1 → 7.0.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.
Files changed (210) hide show
  1. package/README.md +65 -167
  2. package/SETUP_CHECKLIST.md +28 -100
  3. package/cli-src/cli/generate.ts +1 -10
  4. package/cli-src/cli/validate.ts +0 -4
  5. package/cli-src/lib/auth/auth_types.ts +12 -21
  6. package/cli-src/lib/auth/hazo_get_tenant_auth.server.ts +24 -25
  7. package/cli-src/lib/auth/index.ts +2 -2
  8. package/cli-src/lib/auth/nextauth_config.ts +61 -1
  9. package/cli-src/lib/auth/with_auth.server.ts +15 -15
  10. package/cli-src/lib/config/default_config.ts +8 -0
  11. package/cli-src/lib/cookies_config.server.ts +1 -1
  12. package/cli-src/lib/login_config.server.ts +2 -18
  13. package/cli-src/lib/oauth_config.server.ts +32 -0
  14. package/cli-src/lib/register_config.server.ts +4 -0
  15. package/cli-src/lib/services/email_template_manifest.ts +0 -17
  16. package/cli-src/lib/services/index.ts +2 -8
  17. package/cli-src/lib/services/oauth_service.ts +143 -0
  18. package/cli-src/lib/services/otp_service.ts +7 -2
  19. package/cli-src/lib/services/session_token_service.ts +0 -2
  20. package/config/hazo_auth_config.example.ini +0 -38
  21. package/dist/cli/generate.d.ts.map +1 -1
  22. package/dist/cli/generate.js +1 -10
  23. package/dist/cli/validate.d.ts.map +1 -1
  24. package/dist/cli/validate.js +0 -4
  25. package/dist/client.d.ts +0 -2
  26. package/dist/client.d.ts.map +1 -1
  27. package/dist/client.js +0 -1
  28. package/dist/components/layouts/login/index.d.ts +5 -7
  29. package/dist/components/layouts/login/index.d.ts.map +1 -1
  30. package/dist/components/layouts/login/index.js +5 -2
  31. package/dist/components/layouts/otp/index.d.ts +12 -1
  32. package/dist/components/layouts/otp/index.d.ts.map +1 -1
  33. package/dist/components/layouts/otp/index.js +4 -2
  34. package/dist/components/layouts/register/index.d.ts +4 -0
  35. package/dist/components/layouts/register/index.d.ts.map +1 -1
  36. package/dist/components/layouts/register/index.js +4 -1
  37. package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts +21 -0
  38. package/dist/components/layouts/shared/components/facebook_sign_in_button.d.ts.map +1 -0
  39. package/dist/components/layouts/shared/components/facebook_sign_in_button.js +47 -0
  40. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -1
  41. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +3 -8
  42. package/dist/components/layouts/shared/index.d.ts +2 -0
  43. package/dist/components/layouts/shared/index.d.ts.map +1 -1
  44. package/dist/components/layouts/shared/index.js +1 -0
  45. package/dist/components/layouts/user_management/index.d.ts.map +1 -1
  46. package/dist/components/layouts/user_management/index.js +39 -2
  47. package/dist/consent/consent_state.d.ts +18 -0
  48. package/dist/consent/consent_state.d.ts.map +1 -0
  49. package/dist/consent/consent_state.js +29 -0
  50. package/dist/consent/cookie_consent_banner.d.ts +11 -0
  51. package/dist/consent/cookie_consent_banner.d.ts.map +1 -0
  52. package/dist/consent/cookie_consent_banner.js +40 -0
  53. package/dist/consent/gtm_mapping.d.ts +13 -0
  54. package/dist/consent/gtm_mapping.d.ts.map +1 -0
  55. package/dist/consent/gtm_mapping.js +30 -0
  56. package/dist/consent/index.d.ts +7 -0
  57. package/dist/consent/index.d.ts.map +1 -0
  58. package/dist/consent/index.js +7 -0
  59. package/dist/consent/manage_modal.d.ts +2 -0
  60. package/dist/consent/manage_modal.d.ts.map +1 -0
  61. package/dist/consent/manage_modal.js +33 -0
  62. package/dist/consent/read_consent.d.ts +15 -0
  63. package/dist/consent/read_consent.d.ts.map +1 -0
  64. package/dist/consent/read_consent.js +23 -0
  65. package/dist/consent/use_consent.d.ts +7 -0
  66. package/dist/consent/use_consent.d.ts.map +1 -0
  67. package/dist/consent/use_consent.js +55 -0
  68. package/dist/index.d.ts +1 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/lib/auth/auth_types.d.ts +12 -13
  71. package/dist/lib/auth/auth_types.d.ts.map +1 -1
  72. package/dist/lib/auth/auth_types.js +0 -8
  73. package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts +7 -8
  74. package/dist/lib/auth/hazo_get_tenant_auth.server.d.ts.map +1 -1
  75. package/dist/lib/auth/hazo_get_tenant_auth.server.js +22 -23
  76. package/dist/lib/auth/index.d.ts +2 -2
  77. package/dist/lib/auth/index.d.ts.map +1 -1
  78. package/dist/lib/auth/nextauth_config.d.ts.map +1 -1
  79. package/dist/lib/auth/nextauth_config.js +50 -1
  80. package/dist/lib/auth/with_auth.server.d.ts +13 -13
  81. package/dist/lib/auth/with_auth.server.d.ts.map +1 -1
  82. package/dist/lib/auth/with_auth.server.js +2 -2
  83. package/dist/lib/config/default_config.d.ts +16 -0
  84. package/dist/lib/config/default_config.d.ts.map +1 -1
  85. package/dist/lib/config/default_config.js +8 -0
  86. package/dist/lib/cookies_config.server.d.ts +1 -1
  87. package/dist/lib/cookies_config.server.js +1 -1
  88. package/dist/lib/login_config.server.d.ts +0 -6
  89. package/dist/lib/login_config.server.d.ts.map +1 -1
  90. package/dist/lib/login_config.server.js +2 -11
  91. package/dist/lib/oauth_config.server.d.ts +8 -0
  92. package/dist/lib/oauth_config.server.d.ts.map +1 -1
  93. package/dist/lib/oauth_config.server.js +10 -0
  94. package/dist/lib/register_config.server.d.ts +2 -0
  95. package/dist/lib/register_config.server.d.ts.map +1 -1
  96. package/dist/lib/register_config.server.js +2 -0
  97. package/dist/lib/services/email_template_manifest.d.ts.map +1 -1
  98. package/dist/lib/services/email_template_manifest.js +0 -17
  99. package/dist/lib/services/index.d.ts +0 -2
  100. package/dist/lib/services/index.d.ts.map +1 -1
  101. package/dist/lib/services/index.js +0 -1
  102. package/dist/lib/services/oauth_service.d.ts +13 -0
  103. package/dist/lib/services/oauth_service.d.ts.map +1 -1
  104. package/dist/lib/services/oauth_service.js +122 -0
  105. package/dist/lib/services/otp_service.d.ts +1 -1
  106. package/dist/lib/services/otp_service.d.ts.map +1 -1
  107. package/dist/lib/services/otp_service.js +6 -1
  108. package/dist/lib/services/session_token_service.d.ts +0 -2
  109. package/dist/lib/services/session_token_service.d.ts.map +1 -1
  110. package/dist/lib/services/session_token_service.js +0 -2
  111. package/dist/server/routes/assets.d.ts +8 -0
  112. package/dist/server/routes/assets.d.ts.map +1 -0
  113. package/dist/server/routes/assets.js +38 -0
  114. package/dist/server/routes/consent_me.d.ts +4 -0
  115. package/dist/server/routes/consent_me.d.ts.map +1 -0
  116. package/dist/server/routes/consent_me.js +15 -0
  117. package/dist/server/routes/index.d.ts +6 -3
  118. package/dist/server/routes/index.d.ts.map +1 -1
  119. package/dist/server/routes/index.js +9 -4
  120. package/dist/server/routes/me.d.ts.map +1 -1
  121. package/dist/server/routes/me.js +1 -43
  122. package/dist/server/routes/oauth_facebook_callback.d.ts +8 -0
  123. package/dist/server/routes/oauth_facebook_callback.d.ts.map +1 -0
  124. package/dist/server/routes/oauth_facebook_callback.js +164 -0
  125. package/dist/server/routes/otp/verify.js +2 -2
  126. package/dist/server/routes/strings_defaults.d.ts +4 -0
  127. package/dist/server/routes/strings_defaults.d.ts.map +1 -0
  128. package/dist/server/routes/strings_defaults.js +7 -0
  129. package/dist/server/routes/user_management_users.d.ts +11 -0
  130. package/dist/server/routes/user_management_users.d.ts.map +1 -1
  131. package/dist/server/routes/user_management_users.js +50 -0
  132. package/dist/server-lib.d.ts +0 -3
  133. package/dist/server-lib.d.ts.map +1 -1
  134. package/dist/server-lib.js +0 -2
  135. package/dist/server_pages/forgot_password.d.ts +1 -1
  136. package/dist/server_pages/forgot_password.d.ts.map +1 -1
  137. package/dist/server_pages/forgot_password.js +9 -3
  138. package/dist/server_pages/forgot_password_client_wrapper.d.ts +3 -1
  139. package/dist/server_pages/forgot_password_client_wrapper.d.ts.map +1 -1
  140. package/dist/server_pages/forgot_password_client_wrapper.js +2 -2
  141. package/dist/server_pages/index.d.ts +2 -0
  142. package/dist/server_pages/index.d.ts.map +1 -1
  143. package/dist/server_pages/index.js +1 -0
  144. package/dist/server_pages/login.d.ts +1 -1
  145. package/dist/server_pages/login.d.ts.map +1 -1
  146. package/dist/server_pages/login.js +12 -3
  147. package/dist/server_pages/login_client_wrapper.d.ts +4 -1
  148. package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
  149. package/dist/server_pages/login_client_wrapper.js +2 -2
  150. package/dist/server_pages/my_settings.d.ts +1 -1
  151. package/dist/server_pages/my_settings.d.ts.map +1 -1
  152. package/dist/server_pages/my_settings.js +1 -2
  153. package/dist/server_pages/otp.d.ts +16 -2
  154. package/dist/server_pages/otp.d.ts.map +1 -1
  155. package/dist/server_pages/otp.js +10 -3
  156. package/dist/server_pages/register.d.ts +1 -1
  157. package/dist/server_pages/register.d.ts.map +1 -1
  158. package/dist/server_pages/register.js +11 -3
  159. package/dist/server_pages/register_client_wrapper.d.ts +3 -1
  160. package/dist/server_pages/register_client_wrapper.d.ts.map +1 -1
  161. package/dist/server_pages/register_client_wrapper.js +2 -2
  162. package/dist/server_pages/reset_password.d.ts +1 -1
  163. package/dist/server_pages/reset_password.d.ts.map +1 -1
  164. package/dist/server_pages/reset_password.js +9 -3
  165. package/dist/server_pages/reset_password_client_wrapper.d.ts +3 -1
  166. package/dist/server_pages/reset_password_client_wrapper.d.ts.map +1 -1
  167. package/dist/server_pages/reset_password_client_wrapper.js +2 -2
  168. package/dist/server_pages/verify_email.d.ts +1 -1
  169. package/dist/server_pages/verify_email.d.ts.map +1 -1
  170. package/dist/server_pages/verify_email.js +8 -3
  171. package/dist/server_pages/verify_email_client_wrapper.d.ts +3 -1
  172. package/dist/server_pages/verify_email_client_wrapper.d.ts.map +1 -1
  173. package/dist/server_pages/verify_email_client_wrapper.js +2 -2
  174. package/dist/strings/default_strings.d.ts +47 -0
  175. package/dist/strings/default_strings.d.ts.map +1 -0
  176. package/dist/strings/default_strings.js +18 -0
  177. package/dist/strings/index.d.ts +4 -0
  178. package/dist/strings/index.d.ts.map +1 -0
  179. package/dist/strings/index.js +3 -0
  180. package/dist/strings/strings_context.d.ts +12 -0
  181. package/dist/strings/strings_context.d.ts.map +1 -0
  182. package/dist/strings/strings_context.js +23 -0
  183. package/dist/strings/strings_provider.d.ts +26 -0
  184. package/dist/strings/strings_provider.d.ts.map +1 -0
  185. package/dist/strings/strings_provider.js +45 -0
  186. package/dist/theme/create_theme.d.ts +7 -0
  187. package/dist/theme/create_theme.d.ts.map +1 -0
  188. package/dist/theme/create_theme.js +97 -0
  189. package/dist/theme/hex_to_hsl.d.ts +16 -0
  190. package/dist/theme/hex_to_hsl.d.ts.map +1 -0
  191. package/dist/theme/hex_to_hsl.js +110 -0
  192. package/dist/theme/index.d.ts +4 -0
  193. package/dist/theme/index.d.ts.map +1 -0
  194. package/dist/theme/index.js +3 -0
  195. package/dist/theme/luminance.d.ts +11 -0
  196. package/dist/theme/luminance.d.ts.map +1 -0
  197. package/dist/theme/luminance.js +45 -0
  198. package/dist/theme/theme_provider.d.ts +14 -0
  199. package/dist/theme/theme_provider.d.ts.map +1 -0
  200. package/dist/theme/theme_provider.js +23 -0
  201. package/dist/theme/theme_types.d.ts +36 -0
  202. package/dist/theme/theme_types.d.ts.map +1 -0
  203. package/dist/theme/theme_types.js +1 -0
  204. package/dist/themes/index.d.ts +2 -0
  205. package/dist/themes/index.d.ts.map +1 -0
  206. package/dist/themes/index.js +2 -0
  207. package/dist/themes/preset_neutral.d.ts +3 -0
  208. package/dist/themes/preset_neutral.d.ts.map +1 -0
  209. package/dist/themes/preset_neutral.js +14 -0
  210. package/package.json +25 -22
@@ -0,0 +1,97 @@
1
+ import { hex_to_hsl, adjust_lightness } from "./hex_to_hsl.js";
2
+ import { pick_foreground } from "./luminance.js";
3
+ import { preset_neutral } from "../themes/preset_neutral.js";
4
+ /**
5
+ * Creates a fully-resolved HazoAuthTheme from a partial input, applying defaults
6
+ * from preset_neutral. Computes all shadcn CSS variable overrides.
7
+ */
8
+ export function createTheme(input) {
9
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
10
+ // Step 1: Deep merge input over preset_neutral defaults
11
+ const merged = Object.assign(Object.assign(Object.assign({}, preset_neutral), input), { colors: Object.assign(Object.assign({}, preset_neutral.colors), ((_a = input.colors) !== null && _a !== void 0 ? _a : {})), fonts: (_b = input.fonts) !== null && _b !== void 0 ? _b : preset_neutral.fonts, radius: Object.assign(Object.assign({}, ((_c = preset_neutral.radius) !== null && _c !== void 0 ? _c : {})), ((_d = input.radius) !== null && _d !== void 0 ? _d : {})), layout: (_e = input.layout) !== null && _e !== void 0 ? _e : preset_neutral.layout, brandPanel: (_f = input.brandPanel) !== null && _f !== void 0 ? _f : preset_neutral.brandPanel });
12
+ // Step 2: Compute CSS variable overrides
13
+ const colors = merged.colors;
14
+ const radius = (_g = merged.radius) !== null && _g !== void 0 ? _g : { md: "0.5rem" };
15
+ const md = (_h = radius.md) !== null && _h !== void 0 ? _h : "0.5rem";
16
+ // Derive radius values
17
+ const derivedRadius = _derive_radius(md);
18
+ // Build computed overrides
19
+ const computed = {
20
+ "--primary": hex_to_hsl(colors.primary),
21
+ "--primary-foreground": hex_to_hsl(pick_foreground(colors.primary)),
22
+ "--ring": hex_to_hsl(colors.accent),
23
+ "--background": hex_to_hsl(colors.surface),
24
+ "--foreground": hex_to_hsl(colors.textPrimary),
25
+ "--card": hex_to_hsl(colors.surfaceElevated),
26
+ "--card-foreground": hex_to_hsl(pick_foreground(colors.surfaceElevated)),
27
+ "--popover": hex_to_hsl(colors.surfaceElevated),
28
+ "--popover-foreground": hex_to_hsl(pick_foreground(colors.surfaceElevated)),
29
+ "--border": hex_to_hsl(colors.border),
30
+ "--input": hex_to_hsl(colors.border),
31
+ "--muted-foreground": hex_to_hsl(colors.textMuted),
32
+ "--secondary-foreground": hex_to_hsl(colors.textSecondary),
33
+ "--destructive": "0 84% 60%",
34
+ "--destructive-foreground": "0 0% 100%",
35
+ // Derived background tones
36
+ "--secondary": hex_to_hsl(adjust_lightness(colors.surface, -0.03)),
37
+ "--muted": hex_to_hsl(adjust_lightness(colors.surface, -0.06)),
38
+ "--accent": hex_to_hsl(adjust_lightness(colors.surface, -0.04)),
39
+ "--accent-foreground": hex_to_hsl(pick_foreground(adjust_lightness(colors.surface, -0.04))),
40
+ // Radius
41
+ "--radius-sm": derivedRadius.sm,
42
+ "--radius": derivedRadius.md,
43
+ "--radius-lg": derivedRadius.lg,
44
+ "--radius-xl": derivedRadius.xl,
45
+ };
46
+ // Font vars (only if provided)
47
+ if ((_j = merged.fonts) === null || _j === void 0 ? void 0 : _j.display) {
48
+ computed["--font-display"] = merged.fonts.display;
49
+ }
50
+ if ((_k = merged.fonts) === null || _k === void 0 ? void 0 : _k.body) {
51
+ computed["--font-body"] = merged.fonts.body;
52
+ }
53
+ if ((_l = merged.fonts) === null || _l === void 0 ? void 0 : _l.mono) {
54
+ computed["--font-mono"] = merged.fonts.mono;
55
+ }
56
+ // Step 3: Merge user overrides on top (escape hatch — user wins)
57
+ const finalOverrides = Object.assign(Object.assign({}, computed), ((_m = input.overrides) !== null && _m !== void 0 ? _m : {}));
58
+ // Step 4: Return resolved theme
59
+ return Object.assign(Object.assign({}, merged), { overrides: finalOverrides });
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // Internal helpers
63
+ // ---------------------------------------------------------------------------
64
+ /**
65
+ * Derives sm, lg, xl radius values from the md value.
66
+ * Handles rem and px units.
67
+ */
68
+ function _derive_radius(md) {
69
+ const remMatch = md.match(/^([\d.]+)rem$/);
70
+ const pxMatch = md.match(/^([\d.]+)px$/);
71
+ if (remMatch) {
72
+ const base = parseFloat(remMatch[1]);
73
+ const unit = "rem";
74
+ return {
75
+ sm: `${_round(base * 0.5)}${unit}`,
76
+ md: md,
77
+ lg: `${_round(base * 1.5)}${unit}`,
78
+ xl: `${_round(base * 2)}${unit}`,
79
+ };
80
+ }
81
+ if (pxMatch) {
82
+ const base = parseFloat(pxMatch[1]);
83
+ const unit = "px";
84
+ return {
85
+ sm: `${_round(base * 0.5)}${unit}`,
86
+ md: md,
87
+ lg: `${_round(base * 1.5)}${unit}`,
88
+ xl: `${_round(base * 2)}${unit}`,
89
+ };
90
+ }
91
+ // Fallback: can't parse, use md for everything
92
+ return { sm: md, md, lg: md, xl: md };
93
+ }
94
+ function _round(n) {
95
+ // Round to 4 decimal places max, but trim trailing zeros
96
+ return parseFloat(n.toFixed(4));
97
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Converts a hex color string to HSL format "H S% L%".
3
+ * Returns shadcn-compatible space-separated string: "<h> <s>% <l>%"
4
+ * Handles: 3-digit hex, uppercase, with or without leading #
5
+ */
6
+ export declare function hex_to_hsl(hex: string): string;
7
+ /**
8
+ * Shifts the L (lightness) channel of a hex color by `delta` (0–1 range of percentage points).
9
+ * e.g. adjust_lightness("#FFFFFF", -0.03) drops L by 3 percentage points.
10
+ * Clamps result to [0, 100]%. Returns a hex string.
11
+ *
12
+ * Note: uses HSL lightness (0–100 scale), NOT WCAG relative luminance (0–1 scale).
13
+ * See luminance.ts for WCAG relative_luminance.
14
+ */
15
+ export declare function adjust_lightness(hex: string, delta: number): string;
16
+ //# sourceMappingURL=hex_to_hsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hex_to_hsl.d.ts","sourceRoot":"","sources":["../../src/theme/hex_to_hsl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnE"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Converts a hex color string to HSL format "H S% L%".
3
+ * Returns shadcn-compatible space-separated string: "<h> <s>% <l>%"
4
+ * Handles: 3-digit hex, uppercase, with or without leading #
5
+ */
6
+ export function hex_to_hsl(hex) {
7
+ const { h, s, l } = _hex_to_hsl_values(hex);
8
+ return `${Math.round(h)} ${Math.round(s)}% ${Math.round(l)}%`;
9
+ }
10
+ /**
11
+ * Shifts the L (lightness) channel of a hex color by `delta` (0–1 range of percentage points).
12
+ * e.g. adjust_lightness("#FFFFFF", -0.03) drops L by 3 percentage points.
13
+ * Clamps result to [0, 100]%. Returns a hex string.
14
+ *
15
+ * Note: uses HSL lightness (0–100 scale), NOT WCAG relative luminance (0–1 scale).
16
+ * See luminance.ts for WCAG relative_luminance.
17
+ */
18
+ export function adjust_lightness(hex, delta) {
19
+ const { h, s, l } = _hex_to_hsl_values(hex);
20
+ // delta is in the same scale as l (0–100)
21
+ const deltaPercent = delta * 100;
22
+ const newL = Math.max(0, Math.min(100, l + deltaPercent));
23
+ return _hsl_to_hex(h, s, newL);
24
+ }
25
+ function _normalize_hex(hex) {
26
+ // Strip leading # if present
27
+ let h = hex.startsWith("#") ? hex.slice(1) : hex;
28
+ // Expand 3-digit shorthand
29
+ if (h.length === 3) {
30
+ h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];
31
+ }
32
+ return h.toLowerCase();
33
+ }
34
+ function _hex_to_hsl_values(hex) {
35
+ const h = _normalize_hex(hex);
36
+ const r = parseInt(h.slice(0, 2), 16) / 255;
37
+ const g = parseInt(h.slice(2, 4), 16) / 255;
38
+ const b = parseInt(h.slice(4, 6), 16) / 255;
39
+ const max = Math.max(r, g, b);
40
+ const min = Math.min(r, g, b);
41
+ const delta = max - min;
42
+ // Lightness
43
+ const l = (max + min) / 2;
44
+ // Saturation
45
+ let s = 0;
46
+ if (delta !== 0) {
47
+ s = delta / (1 - Math.abs(2 * l - 1));
48
+ }
49
+ // Hue
50
+ let hue = 0;
51
+ if (delta !== 0) {
52
+ if (max === r) {
53
+ hue = ((g - b) / delta) % 6;
54
+ }
55
+ else if (max === g) {
56
+ hue = (b - r) / delta + 2;
57
+ }
58
+ else {
59
+ hue = (r - g) / delta + 4;
60
+ }
61
+ hue = hue * 60;
62
+ if (hue < 0)
63
+ hue += 360;
64
+ }
65
+ return { h: hue, s: s * 100, l: l * 100 };
66
+ }
67
+ function _hsl_to_hex(h, s, l) {
68
+ // Normalize s, l to 0–1
69
+ const sN = s / 100;
70
+ const lN = l / 100;
71
+ const c = (1 - Math.abs(2 * lN - 1)) * sN;
72
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
73
+ const m = lN - c / 2;
74
+ let r = 0, g = 0, b = 0;
75
+ if (h >= 0 && h < 60) {
76
+ r = c;
77
+ g = x;
78
+ b = 0;
79
+ }
80
+ else if (h >= 60 && h < 120) {
81
+ r = x;
82
+ g = c;
83
+ b = 0;
84
+ }
85
+ else if (h >= 120 && h < 180) {
86
+ r = 0;
87
+ g = c;
88
+ b = x;
89
+ }
90
+ else if (h >= 180 && h < 240) {
91
+ r = 0;
92
+ g = x;
93
+ b = c;
94
+ }
95
+ else if (h >= 240 && h < 300) {
96
+ r = x;
97
+ g = 0;
98
+ b = c;
99
+ }
100
+ else {
101
+ r = c;
102
+ g = 0;
103
+ b = x;
104
+ }
105
+ const toHex = (n) => {
106
+ const val = Math.round((n + m) * 255);
107
+ return Math.max(0, Math.min(255, val)).toString(16).padStart(2, "0");
108
+ };
109
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
110
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./theme_types.js";
2
+ export * from "./create_theme.js";
3
+ export * from "./theme_provider.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from "./theme_types.js";
2
+ export * from "./create_theme.js";
3
+ export * from "./theme_provider.js";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Calculates the relative luminance of a hex color per WCAG 2.1.
3
+ * Returns a value between 0 (black) and 1 (white).
4
+ */
5
+ export declare function relative_luminance(hex: string): number;
6
+ /**
7
+ * Returns the foreground color (light or dark) with best contrast against bg_hex.
8
+ * Uses WCAG contrast ratio formula.
9
+ */
10
+ export declare function pick_foreground(bg_hex: string, light_hex?: string, dark_hex?: string): string;
11
+ //# sourceMappingURL=luminance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"luminance.d.ts","sourceRoot":"","sources":["../../src/theme/luminance.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAStD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAkB,EAC7B,QAAQ,GAAE,MAAkB,GAC3B,MAAM,CAeR"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Calculates the relative luminance of a hex color per WCAG 2.1.
3
+ * Returns a value between 0 (black) and 1 (white).
4
+ */
5
+ export function relative_luminance(hex) {
6
+ const { r, g, b } = _hex_to_rgb(hex);
7
+ const linearize = (c) => {
8
+ const normalized = c / 255;
9
+ return normalized <= 0.04045
10
+ ? normalized / 12.92
11
+ : Math.pow((normalized + 0.055) / 1.055, 2.4);
12
+ };
13
+ return 0.2126 * linearize(r) + 0.7152 * linearize(g) + 0.0722 * linearize(b);
14
+ }
15
+ /**
16
+ * Returns the foreground color (light or dark) with best contrast against bg_hex.
17
+ * Uses WCAG contrast ratio formula.
18
+ */
19
+ export function pick_foreground(bg_hex, light_hex = "#FFFFFF", dark_hex = "#0F172A") {
20
+ const bgL = relative_luminance(bg_hex);
21
+ const lightL = relative_luminance(light_hex);
22
+ const darkL = relative_luminance(dark_hex);
23
+ const contrast_ratio = (l1, l2) => {
24
+ const lighter = Math.max(l1, l2);
25
+ const darker = Math.min(l1, l2);
26
+ return (lighter + 0.05) / (darker + 0.05);
27
+ };
28
+ const lightContrast = contrast_ratio(bgL, lightL);
29
+ const darkContrast = contrast_ratio(bgL, darkL);
30
+ return lightContrast >= darkContrast ? light_hex : dark_hex;
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // Internal helpers
34
+ // ---------------------------------------------------------------------------
35
+ function _hex_to_rgb(hex) {
36
+ let h = hex.startsWith("#") ? hex.slice(1) : hex;
37
+ if (h.length === 3) {
38
+ h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];
39
+ }
40
+ return {
41
+ r: parseInt(h.slice(0, 2), 16),
42
+ g: parseInt(h.slice(2, 4), 16),
43
+ b: parseInt(h.slice(4, 6), 16),
44
+ };
45
+ }
@@ -0,0 +1,14 @@
1
+ import type { HazoAuthTheme } from "./theme_types";
2
+ /**
3
+ * Server Component that injects theme CSS variables into the page at SSR time.
4
+ * Wraps children in a div with a style tag containing :root overrides.
5
+ * CSS variable values are derived from the theme object — all values are hex
6
+ * colors converted to HSL strings (e.g. "244 55% 41%") or rem/px radius
7
+ * values, so they cannot contain HTML or script injection.
8
+ * No "use client" — runs on the server.
9
+ */
10
+ export declare function HazoAuthThemeProvider({ theme, children, }: {
11
+ theme: HazoAuthTheme;
12
+ children: React.ReactNode;
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ //# sourceMappingURL=theme_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme_provider.d.ts","sourceRoot":"","sources":["../../src/theme/theme_provider.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,2CAgBA"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // file_description: Server Component that applies a HazoAuthTheme via CSS variables injected at SSR time
3
+ // NO "use client" — this is intentionally a Server Component
4
+ import { createTheme } from "./create_theme.js";
5
+ /**
6
+ * Server Component that injects theme CSS variables into the page at SSR time.
7
+ * Wraps children in a div with a style tag containing :root overrides.
8
+ * CSS variable values are derived from the theme object — all values are hex
9
+ * colors converted to HSL strings (e.g. "244 55% 41%") or rem/px radius
10
+ * values, so they cannot contain HTML or script injection.
11
+ * No "use client" — runs on the server.
12
+ */
13
+ export function HazoAuthThemeProvider({ theme, children, }) {
14
+ var _a;
15
+ const resolved = createTheme(theme);
16
+ const cssVars = Object.entries((_a = resolved.overrides) !== null && _a !== void 0 ? _a : {})
17
+ .map(([key, val]) => `${key}: ${val};`)
18
+ .join(" ");
19
+ // CSS variable values come from createTheme which produces only HSL strings,
20
+ // rem/px values, and font family tokens — never raw user HTML.
21
+ const css = `:root { ${cssVars} }`;
22
+ return (_jsxs("div", { "data-hazo-auth-theme": "true", children: [_jsx("style", { dangerouslySetInnerHTML: { __html: css } }), children] }));
23
+ }
@@ -0,0 +1,36 @@
1
+ export interface HazoAuthTheme {
2
+ colors: {
3
+ primary: string;
4
+ accent: string;
5
+ surface: string;
6
+ surfaceElevated: string;
7
+ border: string;
8
+ textPrimary: string;
9
+ textSecondary: string;
10
+ textMuted: string;
11
+ };
12
+ fonts?: {
13
+ display?: string;
14
+ body?: string;
15
+ mono?: string;
16
+ };
17
+ radius?: {
18
+ sm?: string;
19
+ md?: string;
20
+ lg?: string;
21
+ xl?: string;
22
+ };
23
+ layout: "split" | "centered";
24
+ brandPanel?: {
25
+ logoSrc: string;
26
+ tagline?: string;
27
+ backgroundGradient?: string;
28
+ accentImage?: string;
29
+ };
30
+ overrides?: Record<string, string>;
31
+ }
32
+ export type ResolvedTheme = Required<HazoAuthTheme> & {
33
+ colors: Required<HazoAuthTheme["colors"]>;
34
+ radius: Required<NonNullable<HazoAuthTheme["radius"]>>;
35
+ };
36
+ //# sourceMappingURL=theme_types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme_types.d.ts","sourceRoot":"","sources":["../../src/theme/theme_types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,CAAC,EAAE;QACP,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,CAAC;IACF,MAAM,EAAE,OAAO,GAAG,UAAU,CAAC;IAC7B,UAAU,CAAC,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAGD,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG;IACpD,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1C,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;CACxD,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export { preset_neutral } from "./preset_neutral.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/themes/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ // file_description: barrel export for hazo_auth theme presets
2
+ export { preset_neutral } from "./preset_neutral.js";
@@ -0,0 +1,3 @@
1
+ import type { HazoAuthTheme } from "../theme/theme_types";
2
+ export declare const preset_neutral: HazoAuthTheme;
3
+ //# sourceMappingURL=preset_neutral.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset_neutral.d.ts","sourceRoot":"","sources":["../../src/themes/preset_neutral.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,aAa5B,CAAC"}
@@ -0,0 +1,14 @@
1
+ export const preset_neutral = {
2
+ colors: {
3
+ primary: "#475569",
4
+ accent: "#475569",
5
+ surface: "#FFFFFF",
6
+ surfaceElevated: "#F8FAFC",
7
+ border: "#E2E8F0",
8
+ textPrimary: "#0F172A",
9
+ textSecondary: "#475569",
10
+ textMuted: "#64748B",
11
+ },
12
+ radius: { md: "0.5rem" },
13
+ layout: "centered",
14
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "6.1.1",
3
+ "version": "7.0.2",
4
4
  "description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
5
5
  "keywords": [
6
6
  "authentication",
@@ -81,10 +81,6 @@
81
81
  "types": "./dist/components/layouts/create_firm/index.d.ts",
82
82
  "import": "./dist/components/layouts/create_firm/index.js"
83
83
  },
84
- "./components/layouts/otp": {
85
- "types": "./dist/components/layouts/otp/index.d.ts",
86
- "import": "./dist/components/layouts/otp/index.js"
87
- },
88
84
  "./components/layouts/shared": {
89
85
  "types": "./dist/components/layouts/shared/index.d.ts",
90
86
  "import": "./dist/components/layouts/shared/index.js"
@@ -109,6 +105,22 @@
109
105
  "types": "./dist/server/middleware.d.ts",
110
106
  "import": "./dist/server/middleware.js"
111
107
  },
108
+ "./theme": {
109
+ "types": "./dist/theme/index.d.ts",
110
+ "import": "./dist/theme/index.js"
111
+ },
112
+ "./themes": {
113
+ "types": "./dist/themes/index.d.ts",
114
+ "import": "./dist/themes/index.js"
115
+ },
116
+ "./consent": {
117
+ "types": "./dist/consent/index.d.ts",
118
+ "import": "./dist/consent/index.js"
119
+ },
120
+ "./strings": {
121
+ "types": "./dist/strings/index.d.ts",
122
+ "import": "./dist/strings/index.js"
123
+ },
112
124
  "./pages": {
113
125
  "types": "./dist/server_pages/index.d.ts",
114
126
  "import": "./dist/server_pages/index.js"
@@ -117,10 +129,6 @@
117
129
  "types": "./dist/server_pages/login.d.ts",
118
130
  "import": "./dist/server_pages/login.js"
119
131
  },
120
- "./pages/otp": {
121
- "types": "./dist/server_pages/otp.d.ts",
122
- "import": "./dist/server_pages/otp.js"
123
- },
124
132
  "./pages/register": {
125
133
  "types": "./dist/server_pages/register.d.ts",
126
134
  "import": "./dist/server_pages/register.js"
@@ -141,6 +149,10 @@
141
149
  "types": "./dist/server_pages/my_settings.d.ts",
142
150
  "import": "./dist/server_pages/my_settings.js"
143
151
  },
152
+ "./pages/otp": {
153
+ "types": "./dist/server_pages/otp.d.ts",
154
+ "import": "./dist/server_pages/otp.js"
155
+ },
144
156
  "./page_components": {
145
157
  "types": "./dist/page_components/index.d.ts",
146
158
  "import": "./dist/page_components/index.js"
@@ -149,10 +161,6 @@
149
161
  "types": "./dist/page_components/login.d.ts",
150
162
  "import": "./dist/page_components/login.js"
151
163
  },
152
- "./page_components/otp": {
153
- "types": "./dist/page_components/otp.d.ts",
154
- "import": "./dist/page_components/otp.js"
155
- },
156
164
  "./page_components/register": {
157
165
  "types": "./dist/page_components/register.d.ts",
158
166
  "import": "./dist/page_components/register.js"
@@ -262,11 +270,10 @@
262
270
  "@radix-ui/react-tabs": "^1.1.0",
263
271
  "@radix-ui/react-tooltip": "^1.2.0",
264
272
  "hazo_config": "^2.1.0",
265
- "hazo_connect": "^2.6.0",
273
+ "hazo_connect": "^2.4.0",
266
274
  "hazo_logs": "^1.0.13",
267
275
  "hazo_notify": "^3.0.0",
268
- "hazo_ui": "^2.7.0",
269
- "input-otp": "^1.4.0",
276
+ "hazo_ui": "^2.17.0",
270
277
  "lucide-react": "^0.553.0",
271
278
  "next": ">=14.0.0",
272
279
  "next-auth": "^4.24.0",
@@ -291,9 +298,6 @@
291
298
  "hazo_ui": {
292
299
  "optional": true
293
300
  },
294
- "input-otp": {
295
- "optional": true
296
- },
297
301
  "next-themes": {
298
302
  "optional": true
299
303
  },
@@ -390,13 +394,12 @@
390
394
  "eslint-plugin-storybook": "^10.0.6",
391
395
  "@tailwindcss/postcss": "^4.2.4",
392
396
  "hazo_config": "^2.1.0",
393
- "hazo_connect": "^2.6.0",
397
+ "hazo_connect": "^2.4.0",
394
398
  "hazo_logs": "^1.0.13",
395
399
  "hazo_notify": "^3.0.0",
396
- "hazo_ui": "^2.7.0",
400
+ "hazo_ui": "^2.17.0",
397
401
  "jest": "^30.2.0",
398
402
  "jest-environment-jsdom": "^30.0.0",
399
- "input-otp": "^1.4.0",
400
403
  "lucide-react": "^0.553.0",
401
404
  "next": "^16.0.7",
402
405
  "next-auth": "^4.24.13",