@owlmeans/web-auth-email 0.0.0-stage → 0.1.19

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 (263) hide show
  1. package/README.md +116 -2
  2. package/THIRD-PARTY-NOTICES.txt +24 -0
  3. package/agent-meta/manifest.json +16 -0
  4. package/agent-meta/skills/web-auth-email/SKILL.md +119 -0
  5. package/build/@/components/ui/alert.d.ts +10 -0
  6. package/build/@/components/ui/alert.d.ts.map +1 -0
  7. package/build/@/components/ui/alert.js +26 -0
  8. package/build/@/components/ui/alert.js.map +1 -0
  9. package/build/@/components/ui/button.d.ts +11 -0
  10. package/build/@/components/ui/button.d.ts.map +1 -0
  11. package/build/@/components/ui/button.js +32 -0
  12. package/build/@/components/ui/button.js.map +1 -0
  13. package/build/@/components/ui/card.d.ts +10 -0
  14. package/build/@/components/ui/card.d.ts.map +1 -0
  15. package/build/@/components/ui/card.js +25 -0
  16. package/build/@/components/ui/card.js.map +1 -0
  17. package/build/@/components/ui/input.d.ts +4 -0
  18. package/build/@/components/ui/input.d.ts.map +1 -0
  19. package/build/@/components/ui/input.js +7 -0
  20. package/build/@/components/ui/input.js.map +1 -0
  21. package/build/@/components/ui/label.d.ts +5 -0
  22. package/build/@/components/ui/label.d.ts.map +1 -0
  23. package/build/@/components/ui/label.js +8 -0
  24. package/build/@/components/ui/label.js.map +1 -0
  25. package/build/@/lib/utils.d.ts +3 -0
  26. package/build/@/lib/utils.d.ts.map +1 -0
  27. package/build/@/lib/utils.js +6 -0
  28. package/build/@/lib/utils.js.map +1 -0
  29. package/build/append.d.ts +23 -0
  30. package/build/append.d.ts.map +1 -0
  31. package/build/append.js +49 -0
  32. package/build/append.js.map +1 -0
  33. package/build/components/connected.d.ts +8 -0
  34. package/build/components/connected.d.ts.map +1 -0
  35. package/build/components/connected.js +16 -0
  36. package/build/components/connected.js.map +1 -0
  37. package/build/components/credit.d.ts +5 -0
  38. package/build/components/credit.d.ts.map +1 -0
  39. package/build/components/credit.js +16 -0
  40. package/build/components/credit.js.map +1 -0
  41. package/build/components/fields.d.ts +23 -0
  42. package/build/components/fields.d.ts.map +1 -0
  43. package/build/components/fields.js +39 -0
  44. package/build/components/fields.js.map +1 -0
  45. package/build/components/index.d.ts +9 -0
  46. package/build/components/index.d.ts.map +1 -0
  47. package/build/components/index.js +8 -0
  48. package/build/components/index.js.map +1 -0
  49. package/build/components/offer.d.ts +9 -0
  50. package/build/components/offer.d.ts.map +1 -0
  51. package/build/components/offer.js +99 -0
  52. package/build/components/offer.js.map +1 -0
  53. package/build/components/panel.d.ts +12 -0
  54. package/build/components/panel.d.ts.map +1 -0
  55. package/build/components/panel.js +129 -0
  56. package/build/components/panel.js.map +1 -0
  57. package/build/components/route.d.ts +9 -0
  58. package/build/components/route.d.ts.map +1 -0
  59. package/build/components/route.js +17 -0
  60. package/build/components/route.js.map +1 -0
  61. package/build/components/screen.d.ts +17 -0
  62. package/build/components/screen.d.ts.map +1 -0
  63. package/build/components/screen.js +79 -0
  64. package/build/components/screen.js.map +1 -0
  65. package/build/components/types.d.ts +81 -0
  66. package/build/components/types.d.ts.map +1 -0
  67. package/build/components/types.js +2 -0
  68. package/build/components/types.js.map +1 -0
  69. package/build/consts.d.ts +37 -0
  70. package/build/consts.d.ts.map +1 -0
  71. package/build/consts.js +43 -0
  72. package/build/consts.js.map +1 -0
  73. package/build/entrypoints.d.ts +10 -0
  74. package/build/entrypoints.d.ts.map +1 -0
  75. package/build/entrypoints.js +14 -0
  76. package/build/entrypoints.js.map +1 -0
  77. package/build/hooks/consts.local.d.ts +4 -0
  78. package/build/hooks/consts.local.d.ts.map +1 -0
  79. package/build/hooks/consts.local.js +9 -0
  80. package/build/hooks/consts.local.js.map +1 -0
  81. package/build/hooks/types.d.ts +78 -0
  82. package/build/hooks/types.d.ts.map +1 -0
  83. package/build/hooks/types.js +2 -0
  84. package/build/hooks/types.js.map +1 -0
  85. package/build/hooks/use-email-login.d.ts +13 -0
  86. package/build/hooks/use-email-login.d.ts.map +1 -0
  87. package/build/hooks/use-email-login.js +208 -0
  88. package/build/hooks/use-email-login.js.map +1 -0
  89. package/build/hooks/use-password.d.ts +13 -0
  90. package/build/hooks/use-password.d.ts.map +1 -0
  91. package/build/hooks/use-password.js +118 -0
  92. package/build/hooks/use-password.js.map +1 -0
  93. package/build/hooks/use-translate.d.ts +7 -0
  94. package/build/hooks/use-translate.d.ts.map +1 -0
  95. package/build/hooks/use-translate.js +12 -0
  96. package/build/hooks/use-translate.js.map +1 -0
  97. package/build/i18n/auth/be.json +7 -0
  98. package/build/i18n/auth/de.json +7 -0
  99. package/build/i18n/auth/en.json +7 -0
  100. package/build/i18n/auth/es.json +7 -0
  101. package/build/i18n/auth/fr.json +7 -0
  102. package/build/i18n/auth/pl.json +7 -0
  103. package/build/i18n/auth/ru.json +7 -0
  104. package/build/i18n/auth/uk.json +7 -0
  105. package/build/i18n/be.json +100 -0
  106. package/build/i18n/de.json +100 -0
  107. package/build/i18n/en.json +100 -0
  108. package/build/i18n/es.json +100 -0
  109. package/build/i18n/fr.json +100 -0
  110. package/build/i18n/pl.json +100 -0
  111. package/build/i18n/ru.json +100 -0
  112. package/build/i18n/uk.json +100 -0
  113. package/build/i18n.d.ts +2 -0
  114. package/build/i18n.d.ts.map +1 -0
  115. package/build/i18n.js +40 -0
  116. package/build/i18n.js.map +1 -0
  117. package/build/index.d.ts +23 -0
  118. package/build/index.d.ts.map +1 -0
  119. package/build/index.js +17 -0
  120. package/build/index.js.map +1 -0
  121. package/build/password/types.d.ts +39 -0
  122. package/build/password/types.d.ts.map +1 -0
  123. package/build/password/types.js +2 -0
  124. package/build/password/types.js.map +1 -0
  125. package/build/password.d.ts +4 -0
  126. package/build/password.d.ts.map +1 -0
  127. package/build/password.js +45 -0
  128. package/build/password.js.map +1 -0
  129. package/build/plugin.d.ts +10 -0
  130. package/build/plugin.d.ts.map +1 -0
  131. package/build/plugin.js +21 -0
  132. package/build/plugin.js.map +1 -0
  133. package/build/refusal/consts.local.d.ts +3 -0
  134. package/build/refusal/consts.local.d.ts.map +1 -0
  135. package/build/refusal/consts.local.js +3 -0
  136. package/build/refusal/consts.local.js.map +1 -0
  137. package/build/refusal/types.d.ts +38 -0
  138. package/build/refusal/types.d.ts.map +1 -0
  139. package/build/refusal/types.js +2 -0
  140. package/build/refusal/types.js.map +1 -0
  141. package/build/refusal.d.ts +4 -0
  142. package/build/refusal.d.ts.map +1 -0
  143. package/build/refusal.js +131 -0
  144. package/build/refusal.js.map +1 -0
  145. package/build/service.d.ts +12 -0
  146. package/build/service.d.ts.map +1 -0
  147. package/build/service.js +66 -0
  148. package/build/service.js.map +1 -0
  149. package/build/state/types.d.ts +90 -0
  150. package/build/state/types.d.ts.map +1 -0
  151. package/build/state/types.js +2 -0
  152. package/build/state/types.js.map +1 -0
  153. package/build/state.d.ts +4 -0
  154. package/build/state.d.ts.map +1 -0
  155. package/build/state.js +98 -0
  156. package/build/state.js.map +1 -0
  157. package/build/step.d.ts +16 -0
  158. package/build/step.d.ts.map +1 -0
  159. package/build/step.js +31 -0
  160. package/build/step.js.map +1 -0
  161. package/build/storage/types.d.ts +42 -0
  162. package/build/storage/types.d.ts.map +1 -0
  163. package/build/storage/types.js +2 -0
  164. package/build/storage/types.js.map +1 -0
  165. package/build/storage.d.ts +4 -0
  166. package/build/storage.d.ts.map +1 -0
  167. package/build/storage.js +100 -0
  168. package/build/storage.js.map +1 -0
  169. package/build/types.d.ts +102 -0
  170. package/build/types.d.ts.map +1 -0
  171. package/build/types.js +2 -0
  172. package/build/types.js.map +1 -0
  173. package/build/utils/account.d.ts +4 -0
  174. package/build/utils/account.d.ts.map +1 -0
  175. package/build/utils/account.js +11 -0
  176. package/build/utils/account.js.map +1 -0
  177. package/build/utils/locale.d.ts +6 -0
  178. package/build/utils/locale.d.ts.map +1 -0
  179. package/build/utils/locale.js +10 -0
  180. package/build/utils/locale.js.map +1 -0
  181. package/build/utils/text/types.d.ts +23 -0
  182. package/build/utils/text/types.d.ts.map +1 -0
  183. package/build/utils/text/types.js +2 -0
  184. package/build/utils/text/types.js.map +1 -0
  185. package/build/utils/text.d.ts +4 -0
  186. package/build/utils/text.d.ts.map +1 -0
  187. package/build/utils/text.js +26 -0
  188. package/build/utils/text.js.map +1 -0
  189. package/build/utils.d.ts +8 -0
  190. package/build/utils.d.ts.map +1 -0
  191. package/build/utils.js +9 -0
  192. package/build/utils.js.map +1 -0
  193. package/components.json +21 -0
  194. package/package.json +71 -4
  195. package/src/@/components/ui/alert.tsx +70 -0
  196. package/src/@/components/ui/button.tsx +60 -0
  197. package/src/@/components/ui/card.tsx +93 -0
  198. package/src/@/components/ui/input.tsx +22 -0
  199. package/src/@/components/ui/label.tsx +23 -0
  200. package/src/@/globals.css +57 -0
  201. package/src/@/lib/utils.ts +6 -0
  202. package/src/append.ts +65 -0
  203. package/src/components/connected.tsx +36 -0
  204. package/src/components/credit.tsx +30 -0
  205. package/src/components/fields.tsx +112 -0
  206. package/src/components/index.ts +8 -0
  207. package/src/components/offer.tsx +197 -0
  208. package/src/components/panel.tsx +299 -0
  209. package/src/components/route.tsx +20 -0
  210. package/src/components/screen.tsx +253 -0
  211. package/src/components/types.ts +85 -0
  212. package/src/consts.ts +53 -0
  213. package/src/entrypoints.ts +15 -0
  214. package/src/hooks/consts.local.ts +12 -0
  215. package/src/hooks/types.ts +79 -0
  216. package/src/hooks/use-email-login.ts +234 -0
  217. package/src/hooks/use-password.ts +137 -0
  218. package/src/hooks/use-translate.ts +14 -0
  219. package/src/i18n/auth/be.json +7 -0
  220. package/src/i18n/auth/de.json +7 -0
  221. package/src/i18n/auth/en.json +7 -0
  222. package/src/i18n/auth/es.json +7 -0
  223. package/src/i18n/auth/fr.json +7 -0
  224. package/src/i18n/auth/pl.json +7 -0
  225. package/src/i18n/auth/ru.json +7 -0
  226. package/src/i18n/auth/uk.json +7 -0
  227. package/src/i18n/be.json +100 -0
  228. package/src/i18n/de.json +100 -0
  229. package/src/i18n/en.json +100 -0
  230. package/src/i18n/es.json +100 -0
  231. package/src/i18n/fr.json +100 -0
  232. package/src/i18n/pl.json +100 -0
  233. package/src/i18n/ru.json +100 -0
  234. package/src/i18n/uk.json +100 -0
  235. package/src/i18n.ts +43 -0
  236. package/src/index.ts +22 -0
  237. package/src/password/types.ts +43 -0
  238. package/src/password.ts +65 -0
  239. package/src/plugin.ts +22 -0
  240. package/src/refusal/consts.local.ts +2 -0
  241. package/src/refusal/types.ts +64 -0
  242. package/src/refusal.ts +145 -0
  243. package/src/service.ts +95 -0
  244. package/src/state/types.ts +72 -0
  245. package/src/state.ts +115 -0
  246. package/src/step.ts +38 -0
  247. package/src/storage/types.ts +43 -0
  248. package/src/storage.ts +113 -0
  249. package/src/types.ts +111 -0
  250. package/src/utils/account.ts +12 -0
  251. package/src/utils/locale.ts +11 -0
  252. package/src/utils/text/types.ts +24 -0
  253. package/src/utils/text.ts +34 -0
  254. package/src/utils.ts +9 -0
  255. package/tests/helpers.ts +22 -0
  256. package/tests/i18n.spec.ts +94 -0
  257. package/tests/package-boundary.spec.ts +35 -0
  258. package/tests/password.spec.ts +56 -0
  259. package/tests/refusal.spec.ts +91 -0
  260. package/tests/state.spec.ts +99 -0
  261. package/tests/step.spec.ts +82 -0
  262. package/tests/storage.spec.ts +83 -0
  263. package/tsconfig.json +21 -0
package/README.md CHANGED
@@ -1,3 +1,117 @@
1
- # Temporary Holding Version
1
+ # @owlmeans/web-auth-email
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The browser half of OwlMeans e-mail sign-in: the "Continue with email" method and its card (a
4
+ mailed PIN, or a password where the deployment offers one), the post-sign-in "set a password" step,
5
+ and the password panel for a settings screen — in eight languages. The contracts live in
6
+ `@owlmeans/auth-email`; the server half is `@owlmeans/server-auth-email`.
7
+
8
+ ## Overview
9
+
10
+ - `appendEmailLogin(ctx, { protocols, screen?, method?, offer? })` — the whole wiring, explicit
11
+ (importing the package registers no plugin): the client service, the `email` method, the offer
12
+ step and the strings
13
+ - `emailAuthEntrypoints(protocols)` — the offer screen, bound, for the entrypoint list
14
+ - `EmailLoginScreen` / `LocalizedEmailLoginScreen` — the card; `useEmailLogin()` — its headless model
15
+ - `registerEmailLoginScreen(ctx, Component)` — replace the card entirely
16
+ - `PasswordOfferScreen` — the post-sign-in offer
17
+ - `PasswordPanel` (pure), `usePassword(aliases?)` (I/O), `ConnectedPasswordPanel` (both)
18
+ - `emailLoginStateHelper`, `emailRefusalHelper`, `emailStorageHelper`, `passwordPanelHelper` —
19
+ the pure parts, for a replacement UI or a test
20
+ - `cn` — the class-name merger the components are written against
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ bun add @owlmeans/web-auth-email@^0.1.19
26
+ ```
27
+
28
+ The package ships its own private shadcn primitives (`alert`, `button`, `card`, `input`, `label`)
29
+ and imports them with relative specifiers; consumers provide the React, Radix (`react-label`,
30
+ `react-slot`), `lucide-react` and Tailwind peers. It does not depend on `@owlmeans/web-panel`.
31
+
32
+ ## The `@source` line — required
33
+
34
+ Tailwind's scanner excludes `node_modules`, so add the package's `src` (and `@owlmeans/web-captcha`'s)
35
+ to the app's Tailwind entry:
36
+
37
+ ```css
38
+ @source "../../../node_modules/@owlmeans/web-auth-email/src";
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ```ts
44
+ import { bindAll } from '@owlmeans/client-entrypoint'
45
+ import { makeEmailAuthProtocols } from '@owlmeans/auth-email'
46
+ import { appendEmailLogin, emailAuthEntrypoints } from '@owlmeans/web-auth-email'
47
+
48
+ export const emailAuth = makeEmailAuthProtocols({ guards: [DEFAULT_GUARD], gate: { alias: APP_GATE } })
49
+
50
+ // makeContext
51
+ appendEmailLogin(context, { protocols: emailAuth, screen: { Logo: AppLogo, footer: <AppFooter /> } })
52
+
53
+ // entrypoints
54
+ export const entrypoints = [...framework, ...bindAll(emailAuth as never), ...emailAuthEntrypoints(emailAuth)]
55
+ ```
56
+
57
+ The chooser then offers "Continue with email" (`[data-login-method="email"]`), and its card answers
58
+ at `/authentication/login/email`. A sign-in ends like every self-contained plugin's: the token is
59
+ adopted through the client auth service and `loginLandingOf(ctx).landAfterLogin()` lands — a pending
60
+ step (marketing consent, then the password offer), a parked target, else home.
61
+
62
+ A settings screen renders the password panel:
63
+
64
+ ```tsx
65
+ <ConnectedPasswordPanel /> // the tree given to appendEmailLogin
66
+ <ConnectedPasswordPanel aliases={myAliases} /> // routes mounted under the app's own aliases
67
+ ```
68
+
69
+ ## Customising
70
+
71
+ | What | How |
72
+ |---|---|
73
+ | The chooser button | `appendEmailLogin({ method })`, or `cfg.security.auth.login.overrides.email` (label, icon, order, emphasis, `hidden`, `enabled`) and `methods` (allow-list and order) |
74
+ | The card | `screen`: `Logo`, `title`, `subtitle`, `footer`, `className`, `containerClassName`, `style`, `locale`, `translate` — the chooser card's own props |
75
+ | Everything | `registerEmailLoginScreen(ctx, MyScreen)` with `useEmailLogin()` inside |
76
+ | Strings | an app-tier bundle over `lib : auth-email` (below) |
77
+ | Tests and styling | `data-email-login-*`, `data-email-offer-*`, `data-email-password-*` hooks |
78
+
79
+ ## Translations
80
+
81
+ `lib : auth-email` (`login.*`, `captcha.*`, `offer.*`, `password.*`, `error.*`) in `en`, `pl`, `ru`,
82
+ `be`, `uk`, `es`, `de`, `fr`, plus `login.method.email` in the `auth` resource. Override any string at
83
+ the app tier, in the library namespace:
84
+
85
+ ```ts
86
+ import { i18nHelper, LIB_NAMESPACE } from '@owlmeans/i18n'
87
+
88
+ i18nHelper.addI18nApp('en', 'auth-email', { login: { title: 'Sign in to Acme' } }, { ns: LIB_NAMESPACE })
89
+ ```
90
+
91
+ ## Behaviour worth knowing
92
+
93
+ - The device id is 16 random bytes in `localStorage` (`owlmeans:auth-email:device`); the offer ticket
94
+ waits in `sessionStorage` (`owlmeans:auth-email:offer`), bound to the account and its 15 minutes.
95
+ A browser that refuses storage still signs in (an ephemeral device id, no offer).
96
+ - A captcha token is fetched right before each send-PIN and password sign-in when the deployment
97
+ asks for one, and Google's notice is shown; the badge stays hidden.
98
+ - Refusals are phrased from the error or, in production, the HTTP status alone: 401 is a wrong code
99
+ or wrong credentials, 403 a refused captcha or confirmation code, 429 too many attempts, 422 a
100
+ password outside the policy, 409 an expired offer, 404 passwords off, 503 an outage.
101
+ - No control is ever natively `disabled`: a blocked action carries `aria-disabled` and says why.
102
+
103
+ <!-- owlmeans:agent-guidance:start -->
104
+ ## Agent guidance
105
+
106
+ This package ships embedded agent skills under `agent-meta/`. After installing your
107
+ `@owlmeans/*` packages, run the OwlMeans agent-skills installer to place them into
108
+ your project's skill store (`.agents/skills/`):
109
+
110
+ ```sh
111
+ npx @owlmeans/agent-skills@^0.1.19
112
+ ```
113
+
114
+ The embedded files are version-matched to this package release. Do not edit them
115
+ directly — they are regenerated on each publish. To contribute guidance edits,
116
+ open a PR against the source monorepo.
117
+ <!-- owlmeans:agent-guidance:end -->
@@ -0,0 +1,24 @@
1
+ shadcn/ui — copied UI components
2
+ Source: https://github.com/shadcn-ui/ui
3
+
4
+ MIT License
5
+
6
+ Copyright (c) 2023 shadcn
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
@@ -0,0 +1,16 @@
1
+ {
2
+ "schemaVersion": 3,
3
+ "package": "@owlmeans/web-auth-email",
4
+ "version": "0.1.19",
5
+ "generatedAt": "2026-11-01T22:22:22.305Z",
6
+ "canonicalRepo": "https://github.com/owlmeans/common",
7
+ "entries": [
8
+ {
9
+ "kind": "skill",
10
+ "name": "web-auth-email",
11
+ "category": "package-specific",
12
+ "file": "skills/web-auth-email/SKILL.md",
13
+ "canonicalPath": ".agents/skills/web-auth-email/SKILL.md"
14
+ }
15
+ ]
16
+ }
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: web-auth-email
3
+ description: How to use @owlmeans/web-auth-email — the browser half of OwlMeans e-mail sign-in. appendEmailLogin (explicit, never a side-effect import) registers the client service, the "Continue with email" login method, its own card at /authentication/login/email that mirrors the chooser card and shares its customisation levers, the post-sign-in "set a password" offer step and the eight-language strings; emailAuthEntrypoints binds the offer screen; useEmailLogin is the headless model; PasswordPanel / usePassword / ConnectedPasswordPanel manage a password from a settings screen. Covers the device id and offer ticket storage, captcha use, refusal phrasing, the @source line and the data-email-* hooks. Auto-invoked when adding e-mail sign-in to a web app, customising or replacing the e-mail card, rendering the password panel, or writing an e2e against the e-mail card.
4
+ user-invocable: false
5
+ ---
6
+ <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
7
+
8
+ # @owlmeans/web-auth-email
9
+
10
+ **Layer:** Web (L11 — `client-auth`, `client-entrypoint`, `client-i18n`, `web-captcha`, `auth-email`; NOT `web-panel`)
11
+ **Install:** `"@owlmeans/web-auth-email": "^0.1.19"` in `dependencies`
12
+ **Peers:** React, `react-dom`, `@radix-ui/react-{label,slot}`, `class-variance-authority`, `clsx`,
13
+ `lucide-react`, `tailwind-merge`, `tailwindcss`
14
+
15
+ ## Wiring
16
+
17
+ ```typescript
18
+ import { bindAll } from '@owlmeans/client-entrypoint'
19
+ import { appendEmailLogin, emailAuthEntrypoints } from '@owlmeans/web-auth-email'
20
+
21
+ // makeContext, beside appendLoginScreen
22
+ appendEmailLogin(context, { protocols: emailAuthProtocols, screen: { Logo: AppLogo, footer: <AppFooter /> } })
23
+
24
+ // entrypoints: the API routes the browser calls — the tree minus `tech` (cast: the frozen tree has
25
+ // no index signature) — then the offer screen
26
+ const { base, options, pin, signIn, password } = emailAuthProtocols
27
+ export const entrypoints = [
28
+ ...framework,
29
+ ...bindAll({ base, options, pin, signIn, password } as never),
30
+ ...emailAuthEntrypoints(emailAuthProtocols),
31
+ ]
32
+ ```
33
+
34
+ `appendEmailLogin(ctx, { protocols, screen?, method?, offer? })` does everything beyond binding:
35
+
36
+ - the client service `EMAIL_LOGIN_SERVICE` over `protocols` (a thin transport — every call rejects
37
+ with its route's error; `options()` cached after the first success);
38
+ - the `email` `AuthenticationPlugin`: `requiresRenderer: false`, method `{ id: 'email', i18nKey:
39
+ 'email', icon: 'mail', order: 20, emphasis: 'secondary', ...opts.method }`, and `available`
40
+ asking for the client service — a bundle that merely contains the package never grows a button;
41
+ - the offer `LoginStep` (`offer !== false`), priority `-10`, below marketing consent (`0`);
42
+ - the `auth-email` library strings and `login.method.email` in the `auth` resource, 8 languages.
43
+
44
+ **Explicit by design** — importing the package registers nothing. Bind the API routes the browser
45
+ calls and leave `tech` out: the developer routes are Ed25519-signed operator calls, never the
46
+ browser's. `registerEmailLoginScreen(ctx, C)` must come after `appendEmailLogin`.
47
+
48
+ ## The card mirrors the chooser
49
+
50
+ The method button opens its own card at `/authentication/login/email` (the typed authentication
51
+ route). It is the chooser card's twin, customised with the SAME levers:
52
+
53
+ | What | How |
54
+ |---|---|
55
+ | The chooser button | `appendEmailLogin({ method })`, or `cfg.security.auth.login.overrides.email` (label, icon, order, emphasis, `hidden`, `enabled`) and `methods` (allow-list + order) |
56
+ | The card | `screen` = `Pick<LoginScreenProps, 'Logo' \| 'title' \| 'subtitle' \| 'footer' \| 'className' \| 'containerClassName' \| 'style' \| 'locale' \| 'translate'>` — a host's own props win |
57
+ | Everything | `registerEmailLoginScreen(ctx, MyScreen)` built on `useEmailLogin()` |
58
+ | Strings | an app-tier bundle over `lib : auth-email`, `{ ns: LIB_NAMESPACE }` |
59
+
60
+ Like `LoginScreen` it centres the card in an INLINE `minHeight: 100dvh` (never a class — a stale
61
+ `@source` scan drops a new utility), its default footer is the chooser's credit line
62
+ (`resolveCredit`), and "Other sign-in options" (`data-email-login-other`) leads back to the
63
+ dispatcher.
64
+
65
+ ## The flow (`useEmailLogin`)
66
+
67
+ e-mail → `options` → "Receive authentication PIN code" (a captcha token for `email_pin` when
68
+ `options.captcha`) → PIN field (`inputMode=numeric`, `autocomplete=one-time-code`, resend, change
69
+ address) → signed in. "Already set a password? Use it" appears only when `options.password`: a
70
+ password field (show/hide, `autocomplete=current-password`) with a captcha token for
71
+ `email_password`; a `{ challenge, reason: 'device' }` answer switches to PIN entry with the
72
+ unknown-device notice. The current UI language rides on every PIN request as `locale`. Completion
73
+ is every self-contained plugin's: keep the offer ticket, adopt the token through the client auth
74
+ service, `loginLandingOf(ctx).landAfterLogin()` — a pending step (marketing consent, then the
75
+ offer), a parked flow, else home.
76
+
77
+ - Device id: 16 random bytes base64url in `localStorage` `owlmeans:auth-email:device`; offer ticket
78
+ in `sessionStorage` `owlmeans:auth-email:offer`, bound to the account and its 15 minutes. Refused
79
+ storage still signs in (an ephemeral device id, no offer).
80
+ - The offer step is pending only while a ticket of THIS account is stored AND the status says
81
+ enabled, unset, not declined; a status read that fails is "not pending" (fails open).
82
+ `PasswordOfferScreen`: set (new + repeat) or "Not now" (decline); both continue the login.
83
+ - With a captcha, Google's notice (`CaptchaNotice`) is shown and the badge hidden (`web-captcha`).
84
+
85
+ ## Password panel
86
+
87
+ `PasswordPanel` is pure (props in, callbacks out); `usePassword(aliases?, { locale })` does the I/O
88
+ over injectable entrypoint aliases; `ConnectedPasswordPanel` joins them and sends the interface
89
+ language. States: feature off (a notice), no password (Set), password set (Change, Remove); each
90
+ action is "send code" → PIN (+ new password fields) → confirm, the PIN mailed to the account's own
91
+ address. The panel renders a complete `Card` — a host that puts it inside its own card flattens it
92
+ with direct-child `data-slot` selectors rather than nesting cards.
93
+
94
+ ## Rules
95
+
96
+ - **`@source` is required**: `@source "../../../node_modules/@owlmeans/web-auth-email/src";` — its
97
+ private shadcn primitives (`alert`, `button`, `card`, `input`, `label`, imported relatively) carry
98
+ classes the app's Tailwind scan never sees otherwise. `web-captcha` renders nothing and needs none.
99
+ - **No control is natively `disabled`**: a blocked action carries `aria-disabled` and says why (a
100
+ Playwright click on it needs `{ force: true }`).
101
+ - **Refusals are phrased from the error, or the status alone** (`emailRefusalHelper`): 401 wrong
102
+ code or credentials, 403 refused captcha or confirmation, 429 too many attempts (retry-after),
103
+ 422 weak password, 409 expired offer, 404 passwords off, 503 an outage.
104
+ - A new string goes into all eight `src/i18n/<lng>.json` files (`tests/i18n.spec.ts` checks parity
105
+ and every `t()` key).
106
+
107
+ ## Test hooks
108
+
109
+ `data-email-login-screen` / `-card` / `-form` (`email` \| `pin` \| `password`) / `-email` /
110
+ `-send` / `-pin` / `-submit` / `-resend` / `-change` / `-use-password` / `-use-pin` / `-password` /
111
+ `-captcha` / `-error` (`data-refusal`) / `-other` / `-done`; `data-email-offer` (`data-state="leaving"` when nothing is left to offer) / `-password` /
112
+ `-repeat` / `-save` / `-skip` / `-error`; `data-email-password-*` on the panel. `@owlmeans/test-ui`'s
113
+ `loginViaEmailForm` drives them.
114
+
115
+ ## Related
116
+
117
+ `auth-email` · `server-auth-email` · `login-methods` (the chooser, `overrides`, the credit line) ·
118
+ `login-plugins` (steps and landing) · `web-auth-token` (the same pure-panel + hook shape) ·
119
+ `web-captcha` · `testing-ui`
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ declare const alertVariants: (props?: ({
4
+ variant?: "default" | "destructive" | "success" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ declare function Alert({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>): React.JSX.Element;
7
+ declare function AlertTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
8
+ declare function AlertDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
9
+ export { Alert, AlertTitle, AlertDescription };
10
+ //# sourceMappingURL=alert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/alert.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,QAAA,MAAM,aAAa;;8EAgBlB,CAAA;AAED,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,qBASlE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAW7B;AAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cva } from 'class-variance-authority';
3
+ import { cn } from '../../lib/utils.js';
4
+ const alertVariants = cva("relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", {
5
+ variants: {
6
+ variant: {
7
+ default: "bg-card text-card-foreground",
8
+ destructive: "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
9
+ success: "text-success bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-success/90",
10
+ },
11
+ },
12
+ defaultVariants: {
13
+ variant: "default",
14
+ },
15
+ });
16
+ function Alert({ className, variant, ...props }) {
17
+ return (_jsx("div", { "data-slot": "alert", role: "alert", className: cn(alertVariants({ variant }), className), ...props }));
18
+ }
19
+ function AlertTitle({ className, ...props }) {
20
+ return (_jsx("div", { "data-slot": "alert-title", className: cn("col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", className), ...props }));
21
+ }
22
+ function AlertDescription({ className, ...props }) {
23
+ return (_jsx("div", { "data-slot": "alert-description", className: cn("text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed", className), ...props }));
24
+ }
25
+ export { Alert, AlertTitle, AlertDescription };
26
+ //# sourceMappingURL=alert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alert.js","sourceRoot":"","sources":["../../../../src/@/components/ui/alert.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,aAAa,GAAG,GAAG,CACvB,mOAAmO,EACnO;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,8BAA8B;YACvC,WAAW,EACT,mGAAmG;YACrG,OAAO,EACL,2FAA2F;SAC9F;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;KACnB;CACF,CACF,CAAA;AAED,SAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACyD;IACjE,OAAO,CACL,2BACY,OAAO,EACjB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,KAChD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,6DAA6D,EAC7D,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACoB;IAC5B,OAAO,CACL,2BACY,mBAAmB,EAC7B,SAAS,EAAE,EAAE,CACX,gGAAgG,EAChG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "default" | "destructive" | "ghost" | "link" | "outline" | "secondary" | null | undefined;
5
+ size?: "default" | "icon" | "lg" | "sm" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
8
+ asChild?: boolean;
9
+ }): React.JSX.Element;
10
+ export { Button, buttonVariants };
11
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/button.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,QAAA,MAAM,cAAc;;;8EA6BnB,CAAA;AAED,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAe,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAC/B,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,qBAUF;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Slot } from '@radix-ui/react-slot';
3
+ import { cva } from 'class-variance-authority';
4
+ import { cn } from '../../lib/utils.js';
5
+ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer", {
6
+ variants: {
7
+ variant: {
8
+ default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
9
+ destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
10
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
11
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
12
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
13
+ link: "text-primary underline-offset-4 hover:underline",
14
+ },
15
+ size: {
16
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
17
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
18
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
19
+ icon: "size-9",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ variant: "default",
24
+ size: "default",
25
+ },
26
+ });
27
+ function Button({ className, variant, size, asChild = false, ...props }) {
28
+ const Comp = asChild ? Slot : "button";
29
+ return (_jsx(Comp, { "data-slot": "button", className: cn(buttonVariants({ variant, size, className })), ...props }));
30
+ }
31
+ export { Button, buttonVariants };
32
+ //# sourceMappingURL=button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/@/components/ui/button.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAqB,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,cAAc,GAAG,GAAG,CACxB,4cAA4c,EAC5c;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EACL,kEAAkE;YACpE,WAAW,EACT,6JAA6J;YAC/J,OAAO,EACL,uIAAuI;YACzI,SAAS,EACP,wEAAwE;YAC1E,KAAK,EACH,sEAAsE;YACxE,IAAI,EAAE,iDAAiD;SACxD;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,+BAA+B;YACxC,EAAE,EAAE,+CAA+C;YACnD,EAAE,EAAE,sCAAsC;YAC1C,IAAI,EAAE,QAAQ;SACf;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;KAChB;CACF,CACF,CAAA;AAED,SAAS,MAAM,CAAC,EACd,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,GAAG,KAAK,EAIP;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;IAEtC,OAAO,CACL,KAAC,IAAI,iBACO,QAAQ,EAClB,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,KACvD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ declare function Card({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
3
+ declare function CardHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
4
+ declare function CardTitle({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
5
+ declare function CardDescription({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
6
+ declare function CardAction({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
7
+ declare function CardContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
8
+ declare function CardFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
9
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
10
+ //# sourceMappingURL=card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iBAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWjE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQtE;AAED,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQ5E;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAWvE;AAED,iBAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQxE;AAED,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,qBAQvE;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils.js';
3
+ function Card({ className, ...props }) {
4
+ return (_jsx("div", { "data-slot": "card", className: cn("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className), ...props }));
5
+ }
6
+ function CardHeader({ className, ...props }) {
7
+ return (_jsx("div", { "data-slot": "card-header", className: cn("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", className), ...props }));
8
+ }
9
+ function CardTitle({ className, ...props }) {
10
+ return (_jsx("div", { "data-slot": "card-title", className: cn("leading-none font-semibold", className), ...props }));
11
+ }
12
+ function CardDescription({ className, ...props }) {
13
+ return (_jsx("div", { "data-slot": "card-description", className: cn("text-muted-foreground text-sm", className), ...props }));
14
+ }
15
+ function CardAction({ className, ...props }) {
16
+ return (_jsx("div", { "data-slot": "card-action", className: cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className), ...props }));
17
+ }
18
+ function CardContent({ className, ...props }) {
19
+ return (_jsx("div", { "data-slot": "card-content", className: cn("px-6", className), ...props }));
20
+ }
21
+ function CardFooter({ className, ...props }) {
22
+ return (_jsx("div", { "data-slot": "card-footer", className: cn("flex items-center px-6 [.border-t]:pt-6", className), ...props }));
23
+ }
24
+ export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
25
+ //# sourceMappingURL=card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../../../src/@/components/ui/card.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAChE,OAAO,CACL,2BACY,MAAM,EAChB,SAAS,EAAE,EAAE,CACX,mFAAmF,EACnF,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,4JAA4J,EAC5J,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACrE,OAAO,CACL,2BACY,YAAY,EACtB,SAAS,EAAE,EAAE,CAAC,4BAA4B,EAAE,SAAS,CAAC,KAClD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IAC3E,OAAO,CACL,2BACY,kBAAkB,EAC5B,SAAS,EAAE,EAAE,CAAC,+BAA+B,EAAE,SAAS,CAAC,KACrD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CACX,gEAAgE,EAChE,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACvE,OAAO,CACL,2BACY,cAAc,EACxB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,KAC5B,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA+B;IACtE,OAAO,CACL,2BACY,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,yCAAyC,EAAE,SAAS,CAAC,KAC/D,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EACL,IAAI,EACJ,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,GACZ,CAAA"}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ declare function Input({ className, type, ...props }: React.ComponentProps<"input">): React.JSX.Element;
3
+ export { Input };
4
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/input.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,qBAc1E;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '../../lib/utils.js';
3
+ function Input({ className, type, ...props }) {
4
+ return (_jsx("input", { type: type, "data-slot": "input", className: cn("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className), ...props }));
5
+ }
6
+ export { Input };
7
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../src/@/components/ui/input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAiC;IACzE,OAAO,CACL,gBACE,IAAI,EAAE,IAAI,eACA,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,icAAic,EACjc,+EAA+E,EAC/E,wGAAwG,EACxG,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import * as LabelPrimitive from '@radix-ui/react-label';
3
+ declare function Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>): React.JSX.Element;
4
+ export { Label };
5
+ //# sourceMappingURL=label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../../src/@/components/ui/label.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AAIvD,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,cAAc,CAAC,IAAI,CAAC,qBAWlD;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as LabelPrimitive from '@radix-ui/react-label';
3
+ import { cn } from '../../lib/utils.js';
4
+ function Label({ className, ...props }) {
5
+ return (_jsx(LabelPrimitive.Root, { "data-slot": "label", className: cn("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className), ...props }));
6
+ }
7
+ export { Label };
8
+ //# sourceMappingURL=label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"label.js","sourceRoot":"","sources":["../../../../src/@/components/ui/label.tsx"],"names":[],"mappings":";AAEA,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,SAAS,KAAK,CAAC,EACb,SAAS,EACT,GAAG,KAAK,EACyC;IACjD,OAAO,CACL,KAAC,cAAc,CAAC,IAAI,iBACR,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,qNAAqN,EACrN,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from 'clsx';
2
+ export declare function cn(...inputs: ClassValue[]): string;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/@/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
@@ -0,0 +1,6 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ export function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
6
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/@/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAExC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { BasicConfig, BasicContext } from '@owlmeans/context';
2
+ import type { ClientConfig, ClientContext } from '@owlmeans/client-context';
3
+ import type { EmailLoginAppendOptions, EmailLoginScreenComponent } from './types.js';
4
+ import './i18n.js';
5
+ /**
6
+ * Wire e-mail sign-in into a web app — the whole of it beyond binding the protocol tree (`bindAll`)
7
+ * and `emailAuthEntrypoints(protocols)` in the application's entrypoint list:
8
+ *
9
+ * - the client service `EMAIL_LOGIN_SERVICE` over `protocols`;
10
+ * - the `email` authentication plugin — "Continue with email" on the chooser, its card at
11
+ * `/authentication/login/email` (`opts.screen` dresses it, `opts.method` the button);
12
+ * - the post-sign-in "set a password" step, below marketing consent (`opts.offer !== false`);
13
+ * - the `auth-email` strings and `login.method.email` in eight languages.
14
+ *
15
+ * Explicit by design: importing this package registers no plugin.
16
+ */
17
+ export declare const appendEmailLogin: <C extends ClientConfig, T extends ClientContext<C>>(context: T, opts: EmailLoginAppendOptions) => T;
18
+ /**
19
+ * Replace the screen the e-mail route renders — a whole new card built on `useEmailLogin()`, for an
20
+ * application whose sign-in looks nothing like the chooser. Call it after `appendEmailLogin`.
21
+ */
22
+ export declare const registerEmailLoginScreen: <C extends BasicConfig>(context: BasicContext<C>, screen: EmailLoginScreenComponent) => void;
23
+ //# sourceMappingURL=append.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAQ3E,OAAO,KAAK,EACV,uBAAuB,EAA2B,yBAAyB,EAE5E,MAAM,YAAY,CAAA;AACnB,OAAO,WAAW,CAAA;AAalB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,YAAY,EAAE,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,WACxE,CAAC,QAAQ,uBAAuB,KACxC,CAUF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,WAAW,WACnD,YAAY,CAAC,CAAC,CAAC,UAAU,yBAAyB,KAC1D,IAKF,CAAA"}
@@ -0,0 +1,49 @@
1
+ import { createElement } from 'react';
2
+ import { authPluginHelper } from '@owlmeans/client-auth/manager/plugins';
3
+ import { ensureLoginService } from '@owlmeans/client-auth/login';
4
+ import { EMAIL_LOGIN_SERVICE } from '@owlmeans/auth-email';
5
+ import { LocalizedEmailLoginScreen } from './components/screen.js';
6
+ import { makeEmailLoginPlugin } from './plugin.js';
7
+ import { appendEmailLoginClient } from './service.js';
8
+ import { emailOfferStep } from './step.js';
9
+ import './i18n.js';
10
+ /** The default screen, dressed with the application's setup; a host's own props still win. */
11
+ const screenOf = (setup) => {
12
+ if (setup == null || Object.keys(setup).length < 1) {
13
+ return LocalizedEmailLoginScreen;
14
+ }
15
+ const Configured = props => createElement(LocalizedEmailLoginScreen, { ...setup, ...props });
16
+ return Configured;
17
+ };
18
+ /**
19
+ * Wire e-mail sign-in into a web app — the whole of it beyond binding the protocol tree (`bindAll`)
20
+ * and `emailAuthEntrypoints(protocols)` in the application's entrypoint list:
21
+ *
22
+ * - the client service `EMAIL_LOGIN_SERVICE` over `protocols`;
23
+ * - the `email` authentication plugin — "Continue with email" on the chooser, its card at
24
+ * `/authentication/login/email` (`opts.screen` dresses it, `opts.method` the button);
25
+ * - the post-sign-in "set a password" step, below marketing consent (`opts.offer !== false`);
26
+ * - the `auth-email` strings and `login.method.email` in eight languages.
27
+ *
28
+ * Explicit by design: importing this package registers no plugin.
29
+ */
30
+ export const appendEmailLogin = (context, opts) => {
31
+ appendEmailLoginClient(context, opts.protocols, { screen: screenOf(opts.screen) });
32
+ authPluginHelper.registerAuthPlugin(makeEmailLoginPlugin(opts.method));
33
+ if (opts.offer !== false) {
34
+ const client = context.service(EMAIL_LOGIN_SERVICE);
35
+ ensureLoginService(context).registerStep(emailOfferStep(client, opts.protocols.offer.alias));
36
+ }
37
+ return context;
38
+ };
39
+ /**
40
+ * Replace the screen the e-mail route renders — a whole new card built on `useEmailLogin()`, for an
41
+ * application whose sign-in looks nothing like the chooser. Call it after `appendEmailLogin`.
42
+ */
43
+ export const registerEmailLoginScreen = (context, screen) => {
44
+ if (!context.hasService(EMAIL_LOGIN_SERVICE)) {
45
+ throw new SyntaxError('auth-email: call appendEmailLogin before registerEmailLoginScreen');
46
+ }
47
+ context.service(EMAIL_LOGIN_SERVICE).registerScreen(screen);
48
+ };
49
+ //# sourceMappingURL=append.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"append.js","sourceRoot":"","sources":["../src/append.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAW,MAAM,OAAO,CAAA;AAG9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAK1C,OAAO,WAAW,CAAA;AAElB,8FAA8F;AAC9F,MAAM,QAAQ,GAAG,CAAC,KAA6B,EAA6B,EAAE;IAC5E,IAAI,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,yBAAyB,CAAA;IAClC,CAAC;IACD,MAAM,UAAU,GAA8B,KAAK,CAAC,EAAE,CACpD,aAAa,CAAC,yBAAyB,EAAE,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAA;IAElE,OAAO,UAAU,CAAA;AACnB,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,OAAU,EAAE,IAA6B,EACtC,EAAE;IACL,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAClF,gBAAgB,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IAEtE,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAA0B,mBAAmB,CAAC,CAAA;QAC5E,kBAAkB,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC9F,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,OAAwB,EAAE,MAAiC,EACrD,EAAE;IACR,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,WAAW,CAAC,mEAAmE,CAAC,CAAA;IAC5F,CAAC;IACD,OAAO,CAAC,OAAO,CAA0B,mBAAmB,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;AACtF,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ import type { FC } from 'react';
2
+ import type { ConnectedPasswordPanelProps } from './types.js';
3
+ /**
4
+ * The password panel wired to the password routes of the current context — the whole feature in
5
+ * one element, and the only piece of it that talks to a server.
6
+ */
7
+ export declare const ConnectedPasswordPanel: FC<ConnectedPasswordPanelProps>;
8
+ //# sourceMappingURL=connected.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connected.d.ts","sourceRoot":"","sources":["../../src/components/connected.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAK/B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AAE7D;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,EAAE,CAAC,2BAA2B,CAwBlE,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useLanguage } from '@owlmeans/client-i18n';
3
+ import { usePassword } from '../hooks/use-password.js';
4
+ import { useEmailAuthTranslate } from '../hooks/use-translate.js';
5
+ import { PasswordPanel } from './panel.js';
6
+ /**
7
+ * The password panel wired to the password routes of the current context — the whole feature in
8
+ * one element, and the only piece of it that talks to a server.
9
+ */
10
+ export const ConnectedPasswordPanel = ({ aliases, translate, title, description, className, }) => {
11
+ const own = useEmailAuthTranslate();
12
+ const [lng] = useLanguage();
13
+ const model = usePassword(aliases, { locale: lng });
14
+ return _jsx(PasswordPanel, { status: model.status, loading: model.loading, busy: model.busy, pending: model.pending, refusal: model.refusal, done: model.done, onSendPin: model.sendPin, onConfirm: model.confirm, onCancel: model.cancel, onReload: model.reload, translate: translate ?? own, locale: lng, title: title, description: description, className: className });
15
+ };
16
+ //# sourceMappingURL=connected.js.map