@realiizlabs/admin 0.8.0 → 0.8.1
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.
- package/dist/auth-ui/index.cjs +56 -0
- package/dist/auth-ui/index.cjs.map +1 -1
- package/dist/auth-ui/index.js +1 -1
- package/dist/chunk-CE2DRQBD.js +98 -0
- package/dist/chunk-CE2DRQBD.js.map +1 -0
- package/dist/{chunk-FGKT5FD4.js → chunk-J6FI73PF.js} +31 -4
- package/dist/chunk-J6FI73PF.js.map +1 -0
- package/dist/forms/index.cjs +29 -2
- package/dist/forms/index.cjs.map +1 -1
- package/dist/forms/index.d.cts +2 -2
- package/dist/forms/index.d.ts +2 -2
- package/dist/forms/index.js +1 -1
- package/dist/forms-ui/index.cjs +770 -39
- package/dist/forms-ui/index.cjs.map +1 -1
- package/dist/forms-ui/index.d.cts +123 -12
- package/dist/forms-ui/index.d.ts +123 -12
- package/dist/forms-ui/index.js +691 -41
- package/dist/forms-ui/index.js.map +1 -1
- package/dist/git/index.cjs +16 -4
- package/dist/git/index.cjs.map +1 -1
- package/dist/git/index.d.cts +25 -2
- package/dist/git/index.d.ts +25 -2
- package/dist/git/index.js +15 -5
- package/dist/git/index.js.map +1 -1
- package/dist/shell/index.cjs +248 -77
- package/dist/shell/index.cjs.map +1 -1
- package/dist/shell/index.d.cts +29 -5
- package/dist/shell/index.d.ts +29 -5
- package/dist/shell/index.js +247 -79
- package/dist/shell/index.js.map +1 -1
- package/dist/{types-DsSMscTh.d.cts → types-DyryuIX1.d.cts} +24 -1
- package/dist/{types-DsSMscTh.d.ts → types-DyryuIX1.d.ts} +24 -1
- package/package.json +1 -1
- package/dist/chunk-4OCBMOEP.js +0 -42
- package/dist/chunk-4OCBMOEP.js.map +0 -1
- package/dist/chunk-FGKT5FD4.js.map +0 -1
package/dist/auth-ui/index.cjs
CHANGED
|
@@ -41,9 +41,65 @@ var FORM_CSS = `
|
|
|
41
41
|
.realiiz-form__alert{border:1px solid var(--_danger);border-radius:var(--_radius);padding:12px 14px;margin:0 0 20px;color:var(--_danger)}
|
|
42
42
|
.realiiz-form__alert ul{margin:6px 0 0;padding-left:18px}
|
|
43
43
|
.realiiz-form__actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:8px}
|
|
44
|
+
.realiiz-form__help{text-decoration:underline dotted;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:4px;cursor:help}
|
|
45
|
+
.realiiz-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
|
46
|
+
.realiiz-form__footer{max-width:920px}
|
|
47
|
+
.realiiz-form__bar{display:flex;align-items:center;gap:10px;margin-top:16px;padding:12px 0;border-top:1px solid var(--_border);background:#fff}
|
|
48
|
+
.realiiz-form__status{margin-right:auto;font-size:.85rem;color:var(--_muted)}
|
|
49
|
+
.realiiz-form__bar[data-dirty] .realiiz-form__status{color:var(--_fg)}
|
|
44
50
|
.realiiz-form__button{font:inherit;font-weight:600;border-radius:var(--_radius);padding:10px 16px;border:1px solid var(--_border);background:#fff;color:var(--_fg);cursor:pointer;min-height:40px}
|
|
45
51
|
.realiiz-form__button--primary{background:var(--_accent);color:var(--_accent-fg);border-color:var(--_accent)}
|
|
46
52
|
.realiiz-form__button:disabled{opacity:.6;cursor:default}
|
|
53
|
+
.realiiz-md{--_md-head:#fafbfd;--_md-hover:#f4f8fd;--_md-hover-line:#bcd0ea;--_md-on:#eef4fb;--_md-tip:#1f2933;position:relative}
|
|
54
|
+
.realiiz-md__mode{display:inline-flex;align-self:flex-start;width:max-content;gap:2px;padding:3px;background:color-mix(in srgb,var(--_border) 40%,transparent);border-radius:8px;margin-bottom:8px}
|
|
55
|
+
.realiiz-md__mode button{font:inherit;font-size:.8rem;padding:5px 13px;border:0;border-radius:6px;background:transparent;color:var(--_muted);cursor:pointer}
|
|
56
|
+
.realiiz-md__mode button[aria-selected="true"]{background:#fff;color:var(--_fg);box-shadow:0 1px 2px rgba(0,0,0,.12)}
|
|
57
|
+
.realiiz-md__panel{position:relative;z-index:0;display:flex;flex-direction:column;border:1px solid var(--_border);border-radius:10px;background:#fff;overflow:hidden}
|
|
58
|
+
.realiiz-md__panel:focus-within{border-color:var(--_md-hover-line)}
|
|
59
|
+
.realiiz-md__head{position:relative;z-index:5;display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding:5px 7px;background:var(--_md-head);border-bottom:1px solid var(--_border);flex-shrink:0}
|
|
60
|
+
.realiiz-md__tools{display:flex;align-items:center;gap:3px;flex-wrap:wrap}
|
|
61
|
+
.realiiz-md__spacer{flex:1}
|
|
62
|
+
.realiiz-md__head button{position:relative;min-width:31px;height:28px;padding:0 9px;display:inline-flex;align-items:center;justify-content:center;background:#fff;border:1px solid var(--_border);border-radius:6px;font-family:inherit;font-size:.82rem;color:var(--_fg);cursor:pointer;line-height:1}
|
|
63
|
+
.realiiz-md__head button:hover:not(:disabled){border-color:var(--_md-hover-line);background:var(--_md-hover)}
|
|
64
|
+
.realiiz-md__head button:active{background:var(--_md-on)}
|
|
65
|
+
.realiiz-md__head button.on{background:var(--_md-on);border-color:var(--_accent);color:var(--_accent);font-weight:600}
|
|
66
|
+
.realiiz-md__ico{width:15px;height:15px;display:block}
|
|
67
|
+
.realiiz-md__dot{font-size:1.05rem;line-height:1}
|
|
68
|
+
.realiiz-md__sep{width:1px;height:17px;background:var(--_border);margin:0 5px}
|
|
69
|
+
.realiiz-md__insert{display:inline-flex;align-items:center;gap:3px;border-left:1px solid var(--_border);padding-left:8px;margin-left:6px}
|
|
70
|
+
.realiiz-md__insert button{background:#f6f8fa;color:var(--_muted);padding:0;width:31px}
|
|
71
|
+
.realiiz-md__insert button:hover{color:var(--_accent)}
|
|
72
|
+
.realiiz-md__lab{font-size:.74rem;color:var(--_muted);margin-right:3px}
|
|
73
|
+
.realiiz-md__head button[data-tip]::after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);left:0;background:var(--_md-tip);color:#fff;font-size:.72rem;padding:4px 8px;border-radius:5px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;z-index:20}
|
|
74
|
+
.realiiz-md__head button[data-tip]:hover::after,.realiiz-md__head button[data-tip]:focus-visible::after{opacity:1}
|
|
75
|
+
.realiiz-md__expand[data-tip]::after{left:auto;right:0}
|
|
76
|
+
.realiiz-md__tgwrap{position:relative;display:inline-flex}
|
|
77
|
+
.realiiz-md__tgrid{position:absolute;top:calc(100% + 6px);left:0;background:#fff;border:1px solid var(--_border);border-radius:9px;padding:9px;box-shadow:0 10px 28px rgba(0,0,0,.14);z-index:7;display:block}
|
|
78
|
+
.realiiz-md__tgcells{display:grid;grid-template-columns:repeat(6,17px);gap:3px}
|
|
79
|
+
.realiiz-md__tgcells i{width:17px;height:15px;border:1px solid var(--_border);border-radius:2px;background:#fff;cursor:pointer;display:block}
|
|
80
|
+
.realiiz-md__tgcells i.hot{background:#dbe9fb;border-color:var(--_accent)}
|
|
81
|
+
.realiiz-md__tglab{display:block;margin-top:8px;font-size:.74rem;color:var(--_muted);text-align:center;white-space:nowrap}
|
|
82
|
+
.realiiz-md .realiiz-md__ta{flex:1 1 auto;border:0;border-radius:0;resize:vertical;background:#fff;max-width:none;padding:16px 18px;line-height:1.65}
|
|
83
|
+
.realiiz-md .realiiz-md__ta:focus{outline:none;box-shadow:none}
|
|
84
|
+
.realiiz-md__preview{padding:20px 24px;background:#fff}
|
|
85
|
+
.realiiz-md__note{padding:4px 2px}
|
|
86
|
+
.realiiz-md--fs{position:fixed;inset:0;z-index:60;background:#fff;padding:14px 22px 22px;overflow:auto;display:flex;flex-direction:column}
|
|
87
|
+
.realiiz-md--fs .realiiz-md__panel{flex:1;min-height:0}
|
|
88
|
+
.realiiz-md--fs .realiiz-md__ta,.realiiz-md--fs .realiiz-md__preview{flex:1;min-height:0;overflow:auto;resize:none}
|
|
89
|
+
.realiiz-prose{max-width:68ch;line-height:1.65}
|
|
90
|
+
.realiiz-chips{display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:40px;padding:5px 8px;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius)}
|
|
91
|
+
.realiiz-chips:focus-within{border-color:var(--_accent);box-shadow:var(--_ring)}
|
|
92
|
+
.realiiz-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 9px;border:1px solid var(--_border);border-radius:999px;font-size:.8rem}
|
|
93
|
+
.realiiz-chip button{font:inherit;line-height:1;width:18px;height:18px;border-radius:50%;border:0;background:transparent;color:var(--_muted);cursor:pointer}
|
|
94
|
+
.realiiz-chips__input{flex:1;min-width:120px;border:0;background:transparent;font:inherit;color:inherit;outline:none;padding:4px}
|
|
95
|
+
.realiiz-chips__count{margin-left:auto;color:var(--_muted);font-size:.75rem}
|
|
96
|
+
.realiiz-gauge{display:inline-flex;align-items:center;gap:10px;font-size:.75rem;color:var(--_muted)}
|
|
97
|
+
.realiiz-gauge__bar{position:relative;width:140px;height:6px;border-radius:3px;background:var(--_border);overflow:hidden}
|
|
98
|
+
.realiiz-gauge__zone{position:absolute;top:0;bottom:0;background:rgba(21,128,61,.28)}
|
|
99
|
+
.realiiz-gauge__fill{position:absolute;top:0;bottom:0;left:0;background:var(--_muted);border-radius:3px;transition:width .12s}
|
|
100
|
+
.realiiz-gauge__text b{font-weight:600;color:inherit}
|
|
101
|
+
.realiiz-gauge--ok{color:#15803d}.realiiz-gauge--ok .realiiz-gauge__fill{background:#15803d}
|
|
102
|
+
.realiiz-gauge--over{color:var(--_danger)}.realiiz-gauge--over .realiiz-gauge__fill{background:var(--_danger)}
|
|
47
103
|
`;
|
|
48
104
|
var UNINVITED_MESSAGE = "This email address isn't set up for this site yet. Ask the site owner to send you an invite.";
|
|
49
105
|
function isUninvitedError(message) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/forms-ui/styles.ts","../../src/auth-ui/MagicLinkForm.tsx","../../src/auth-ui/SignOutButton.tsx"],"names":["useMemo","createBrowserClient","useState","jsxs","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Theming hooks, same convention as BookingWidget: a root class, BEM elements,\n * and --realiiz-form-* custom properties with fallbacks so the form is usable\n * with zero host CSS and fully themeable with a dozen variables.\n */\n\nexport const FORM_CSS = `\n.realiiz-form{\n --_fg:var(--realiiz-form-fg,#111);\n --_muted:var(--realiiz-form-muted,#666);\n --_border:var(--realiiz-form-border,#cfcfcf);\n --_accent:var(--realiiz-form-accent,#111);\n --_accent-fg:var(--realiiz-form-accent-fg,#fff);\n --_danger:var(--realiiz-form-danger,#b3261e);\n --_radius:var(--realiiz-form-radius,6px);\n --_font:var(--realiiz-form-font,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif);\n --_ring:var(--realiiz-form-focus-ring,0 0 0 3px rgba(0,0,0,.15));\n box-sizing:border-box;max-width:100%;color:var(--_fg);font-family:var(--_font);font-size:15px;line-height:1.4;\n}\n.realiiz-form *,.realiiz-form *::before,.realiiz-form *::after{box-sizing:inherit}\n.realiiz-form fieldset{border:0;margin:0 0 20px;padding:0;min-width:0}\n.realiiz-form legend{font-weight:600;font-size:13px;letter-spacing:.02em;text-transform:uppercase;color:var(--_muted);margin-bottom:12px;padding:0}\n.realiiz-form__field{display:block;margin:0 0 16px}\n.realiiz-form__label{display:block;font-weight:500;margin-bottom:6px}\n.realiiz-form__required{color:var(--_danger);margin-left:3px}\n.realiiz-form__control{display:block;width:100%;max-width:100%;font:inherit;color:inherit;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius);padding:9px 11px;min-height:40px}\n.realiiz-form__control:focus{outline:none;border-color:var(--_accent);box-shadow:var(--_ring)}\n.realiiz-form__control--textarea{min-height:110px;resize:vertical}\n.realiiz-form__control--body{min-height:280px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px}\n.realiiz-form__control--invalid{border-color:var(--_danger)}\n.realiiz-form__check{display:flex;align-items:center;gap:8px;font-weight:500}\n.realiiz-form__check input{width:18px;height:18px;margin:0}\n.realiiz-form__helper{display:flex;justify-content:space-between;gap:12px;font-size:12px;color:var(--_muted);margin-top:4px;min-height:1em}\n.realiiz-form__count{margin-left:auto;font-variant-numeric:tabular-nums}\n.realiiz-form__error{color:var(--_danger);font-size:13px;margin-top:4px}\n.realiiz-form__current{font-size:12px;color:var(--_muted);margin-top:4px;word-break:break-all}\n.realiiz-form__alert{border:1px solid var(--_danger);border-radius:var(--_radius);padding:12px 14px;margin:0 0 20px;color:var(--_danger)}\n.realiiz-form__alert ul{margin:6px 0 0;padding-left:18px}\n.realiiz-form__actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:8px}\n.realiiz-form__button{font:inherit;font-weight:600;border-radius:var(--_radius);padding:10px 16px;border:1px solid var(--_border);background:#fff;color:var(--_fg);cursor:pointer;min-height:40px}\n.realiiz-form__button--primary{background:var(--_accent);color:var(--_accent-fg);border-color:var(--_accent)}\n.realiiz-form__button:disabled{opacity:.6;cursor:default}\n`;\n","/**\n * MagicLinkForm — one field, one button, and the right words for each outcome.\n *\n * The audience is a non-technical client. Two outcomes matter:\n * sent → tell them where the link went and that it expires in an hour\n * uninvited → signups are off, so Supabase refuses unknown emails with a\n * \"Signups not allowed\" error. That string is a support ticket;\n * \"this email isn't set up for this site\" is not.\n *\n * `shouldCreateUser: false` restates the dashboard setting in code — the flag\n * a reviewer greps for.\n */\n\nimport { createBrowserClient } from \"@supabase/ssr\";\nimport { useMemo, useState, type FormEvent } from \"react\";\nimport { FORM_CSS } from \"../forms-ui/styles\";\n\nexport interface MagicLinkFormProps {\n url: string;\n anonKey: string;\n /** The site's callback, e.g. https://5degrees.org/admin/auth/callback?next=/admin */\n redirectTo: string;\n /** Shown in the heading: \"Sign in to {siteName}\". */\n siteName: string;\n className?: string;\n}\n\ntype State = { kind: \"idle\" } | { kind: \"sending\" } | { kind: \"sent\"; email: string } | { kind: \"error\"; message: string; uninvited: boolean };\n\nexport const UNINVITED_MESSAGE =\n \"This email address isn't set up for this site yet. Ask the site owner to send you an invite.\";\n\nexport function isUninvitedError(message: string): boolean {\n return /signups? not allowed|not allowed|user not found|invalid login/i.test(message);\n}\n\nexport function MagicLinkForm({ url, anonKey, redirectTo, siteName, className }: MagicLinkFormProps) {\n const supabase = useMemo(() => createBrowserClient(url, anonKey), [url, anonKey]);\n const [email, setEmail] = useState(\"\");\n const [state, setState] = useState<State>({ kind: \"idle\" });\n\n const submit = async (e: FormEvent) => {\n e.preventDefault();\n if (state.kind === \"sending\") return;\n const address = email.trim().toLowerCase();\n setState({ kind: \"sending\" });\n const { error } = await supabase.auth.signInWithOtp({\n email: address,\n options: { emailRedirectTo: redirectTo, shouldCreateUser: false },\n });\n if (error) {\n const uninvited = isUninvitedError(error.message);\n setState({ kind: \"error\", message: uninvited ? UNINVITED_MESSAGE : error.message, uninvited });\n return;\n }\n setState({ kind: \"sent\", email: address });\n };\n\n const root = [\"realiiz-form\", \"realiiz-signin\", className].filter(Boolean).join(\" \");\n\n if (state.kind === \"sent\") {\n return (\n <div className={root} data-realiiz-signin=\"sent\">\n <style>{FORM_CSS}</style>\n <h2 className=\"realiiz-signin__heading\">Check your email</h2>\n <p>\n We sent a sign-in link to <strong>{state.email}</strong>. It expires in an hour.\n </p>\n <button type=\"button\" className=\"realiiz-form__button\" onClick={() => setState({ kind: \"idle\" })}>\n Use a different address\n </button>\n </div>\n );\n }\n\n const sending = state.kind === \"sending\";\n const fieldError = state.kind === \"error\" && !state.uninvited ? state.message : null;\n\n return (\n <form className={root} onSubmit={submit} noValidate data-realiiz-signin=\"form\">\n <style>{FORM_CSS}</style>\n <h2 className=\"realiiz-signin__heading\">Sign in to {siteName}</h2>\n\n {state.kind === \"error\" && state.uninvited && (\n <div className=\"realiiz-form__alert\" role=\"alert\">{state.message}</div>\n )}\n\n <div className=\"realiiz-form__field\">\n <label className=\"realiiz-form__label\" htmlFor=\"realiiz-signin-email\">Email address</label>\n <input\n id=\"realiiz-signin-email\"\n className={[\"realiiz-form__control\", fieldError && \"realiiz-form__control--invalid\"].filter(Boolean).join(\" \")}\n type=\"email\"\n name=\"email\"\n autoComplete=\"email\"\n required\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n aria-invalid={fieldError ? true : undefined}\n aria-describedby={fieldError ? \"realiiz-signin-email-error\" : undefined}\n />\n {fieldError && (\n <div className=\"realiiz-form__error\" id=\"realiiz-signin-email-error\">{fieldError}</div>\n )}\n </div>\n\n <div className=\"realiiz-form__actions\">\n <button type=\"submit\" className=\"realiiz-form__button realiiz-form__button--primary\" disabled={sending || email.trim() === \"\"}>\n {sending ? \"Sending…\" : \"Send me a sign-in link\"}\n </button>\n </div>\n </form>\n );\n}\n","/**\n * SignOutButton — a plain POST form. No JavaScript needed, so it works before\n * hydration and inside a server component. The site's route (ADMIN-04) calls\n * signOut() from @realiizlabs/admin/auth and redirects.\n */\n\nexport interface SignOutButtonProps {\n /** Default \"/admin/auth/signout\". */\n actionPath?: string;\n className?: string;\n label?: string;\n}\n\nexport function SignOutButton({ actionPath = \"/admin/auth/signout\", className, label = \"Sign out\" }: SignOutButtonProps) {\n return (\n <form method=\"post\" action={actionPath} className={[\"realiiz-signout\", className].filter(Boolean).join(\" \")}>\n <button type=\"submit\" className=\"realiiz-form__button\">{label}</button>\n </form>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/forms-ui/styles.ts","../../src/auth-ui/MagicLinkForm.tsx","../../src/auth-ui/SignOutButton.tsx"],"names":["useMemo","createBrowserClient","useState","jsxs","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Theming hooks, same convention as BookingWidget: a root class, BEM elements,\n * and --realiiz-form-* custom properties with fallbacks so the form is usable\n * with zero host CSS and fully themeable with a dozen variables.\n */\n\nexport const FORM_CSS = `\n.realiiz-form{\n --_fg:var(--realiiz-form-fg,#111);\n --_muted:var(--realiiz-form-muted,#666);\n --_border:var(--realiiz-form-border,#cfcfcf);\n --_accent:var(--realiiz-form-accent,#111);\n --_accent-fg:var(--realiiz-form-accent-fg,#fff);\n --_danger:var(--realiiz-form-danger,#b3261e);\n --_radius:var(--realiiz-form-radius,6px);\n --_font:var(--realiiz-form-font,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif);\n --_ring:var(--realiiz-form-focus-ring,0 0 0 3px rgba(0,0,0,.15));\n box-sizing:border-box;max-width:100%;color:var(--_fg);font-family:var(--_font);font-size:15px;line-height:1.4;\n}\n.realiiz-form *,.realiiz-form *::before,.realiiz-form *::after{box-sizing:inherit}\n.realiiz-form fieldset{border:0;margin:0 0 20px;padding:0;min-width:0}\n.realiiz-form legend{font-weight:600;font-size:13px;letter-spacing:.02em;text-transform:uppercase;color:var(--_muted);margin-bottom:12px;padding:0}\n.realiiz-form__field{display:block;margin:0 0 16px}\n.realiiz-form__label{display:block;font-weight:500;margin-bottom:6px}\n.realiiz-form__required{color:var(--_danger);margin-left:3px}\n.realiiz-form__control{display:block;width:100%;max-width:100%;font:inherit;color:inherit;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius);padding:9px 11px;min-height:40px}\n.realiiz-form__control:focus{outline:none;border-color:var(--_accent);box-shadow:var(--_ring)}\n.realiiz-form__control--textarea{min-height:110px;resize:vertical}\n.realiiz-form__control--body{min-height:280px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px}\n.realiiz-form__control--invalid{border-color:var(--_danger)}\n.realiiz-form__check{display:flex;align-items:center;gap:8px;font-weight:500}\n.realiiz-form__check input{width:18px;height:18px;margin:0}\n.realiiz-form__helper{display:flex;justify-content:space-between;gap:12px;font-size:12px;color:var(--_muted);margin-top:4px;min-height:1em}\n.realiiz-form__count{margin-left:auto;font-variant-numeric:tabular-nums}\n.realiiz-form__error{color:var(--_danger);font-size:13px;margin-top:4px}\n.realiiz-form__current{font-size:12px;color:var(--_muted);margin-top:4px;word-break:break-all}\n.realiiz-form__alert{border:1px solid var(--_danger);border-radius:var(--_radius);padding:12px 14px;margin:0 0 20px;color:var(--_danger)}\n.realiiz-form__alert ul{margin:6px 0 0;padding-left:18px}\n.realiiz-form__actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:8px}\n.realiiz-form__help{text-decoration:underline dotted;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:4px;cursor:help}\n.realiiz-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n.realiiz-form__footer{max-width:920px}\n.realiiz-form__bar{display:flex;align-items:center;gap:10px;margin-top:16px;padding:12px 0;border-top:1px solid var(--_border);background:#fff}\n.realiiz-form__status{margin-right:auto;font-size:.85rem;color:var(--_muted)}\n.realiiz-form__bar[data-dirty] .realiiz-form__status{color:var(--_fg)}\n.realiiz-form__button{font:inherit;font-weight:600;border-radius:var(--_radius);padding:10px 16px;border:1px solid var(--_border);background:#fff;color:var(--_fg);cursor:pointer;min-height:40px}\n.realiiz-form__button--primary{background:var(--_accent);color:var(--_accent-fg);border-color:var(--_accent)}\n.realiiz-form__button:disabled{opacity:.6;cursor:default}\n.realiiz-md{--_md-head:#fafbfd;--_md-hover:#f4f8fd;--_md-hover-line:#bcd0ea;--_md-on:#eef4fb;--_md-tip:#1f2933;position:relative}\n.realiiz-md__mode{display:inline-flex;align-self:flex-start;width:max-content;gap:2px;padding:3px;background:color-mix(in srgb,var(--_border) 40%,transparent);border-radius:8px;margin-bottom:8px}\n.realiiz-md__mode button{font:inherit;font-size:.8rem;padding:5px 13px;border:0;border-radius:6px;background:transparent;color:var(--_muted);cursor:pointer}\n.realiiz-md__mode button[aria-selected=\"true\"]{background:#fff;color:var(--_fg);box-shadow:0 1px 2px rgba(0,0,0,.12)}\n.realiiz-md__panel{position:relative;z-index:0;display:flex;flex-direction:column;border:1px solid var(--_border);border-radius:10px;background:#fff;overflow:hidden}\n.realiiz-md__panel:focus-within{border-color:var(--_md-hover-line)}\n.realiiz-md__head{position:relative;z-index:5;display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding:5px 7px;background:var(--_md-head);border-bottom:1px solid var(--_border);flex-shrink:0}\n.realiiz-md__tools{display:flex;align-items:center;gap:3px;flex-wrap:wrap}\n.realiiz-md__spacer{flex:1}\n.realiiz-md__head button{position:relative;min-width:31px;height:28px;padding:0 9px;display:inline-flex;align-items:center;justify-content:center;background:#fff;border:1px solid var(--_border);border-radius:6px;font-family:inherit;font-size:.82rem;color:var(--_fg);cursor:pointer;line-height:1}\n.realiiz-md__head button:hover:not(:disabled){border-color:var(--_md-hover-line);background:var(--_md-hover)}\n.realiiz-md__head button:active{background:var(--_md-on)}\n.realiiz-md__head button.on{background:var(--_md-on);border-color:var(--_accent);color:var(--_accent);font-weight:600}\n.realiiz-md__ico{width:15px;height:15px;display:block}\n.realiiz-md__dot{font-size:1.05rem;line-height:1}\n.realiiz-md__sep{width:1px;height:17px;background:var(--_border);margin:0 5px}\n.realiiz-md__insert{display:inline-flex;align-items:center;gap:3px;border-left:1px solid var(--_border);padding-left:8px;margin-left:6px}\n.realiiz-md__insert button{background:#f6f8fa;color:var(--_muted);padding:0;width:31px}\n.realiiz-md__insert button:hover{color:var(--_accent)}\n.realiiz-md__lab{font-size:.74rem;color:var(--_muted);margin-right:3px}\n.realiiz-md__head button[data-tip]::after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);left:0;background:var(--_md-tip);color:#fff;font-size:.72rem;padding:4px 8px;border-radius:5px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;z-index:20}\n.realiiz-md__head button[data-tip]:hover::after,.realiiz-md__head button[data-tip]:focus-visible::after{opacity:1}\n.realiiz-md__expand[data-tip]::after{left:auto;right:0}\n.realiiz-md__tgwrap{position:relative;display:inline-flex}\n.realiiz-md__tgrid{position:absolute;top:calc(100% + 6px);left:0;background:#fff;border:1px solid var(--_border);border-radius:9px;padding:9px;box-shadow:0 10px 28px rgba(0,0,0,.14);z-index:7;display:block}\n.realiiz-md__tgcells{display:grid;grid-template-columns:repeat(6,17px);gap:3px}\n.realiiz-md__tgcells i{width:17px;height:15px;border:1px solid var(--_border);border-radius:2px;background:#fff;cursor:pointer;display:block}\n.realiiz-md__tgcells i.hot{background:#dbe9fb;border-color:var(--_accent)}\n.realiiz-md__tglab{display:block;margin-top:8px;font-size:.74rem;color:var(--_muted);text-align:center;white-space:nowrap}\n.realiiz-md .realiiz-md__ta{flex:1 1 auto;border:0;border-radius:0;resize:vertical;background:#fff;max-width:none;padding:16px 18px;line-height:1.65}\n.realiiz-md .realiiz-md__ta:focus{outline:none;box-shadow:none}\n.realiiz-md__preview{padding:20px 24px;background:#fff}\n.realiiz-md__note{padding:4px 2px}\n.realiiz-md--fs{position:fixed;inset:0;z-index:60;background:#fff;padding:14px 22px 22px;overflow:auto;display:flex;flex-direction:column}\n.realiiz-md--fs .realiiz-md__panel{flex:1;min-height:0}\n.realiiz-md--fs .realiiz-md__ta,.realiiz-md--fs .realiiz-md__preview{flex:1;min-height:0;overflow:auto;resize:none}\n.realiiz-prose{max-width:68ch;line-height:1.65}\n.realiiz-chips{display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:40px;padding:5px 8px;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius)}\n.realiiz-chips:focus-within{border-color:var(--_accent);box-shadow:var(--_ring)}\n.realiiz-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 9px;border:1px solid var(--_border);border-radius:999px;font-size:.8rem}\n.realiiz-chip button{font:inherit;line-height:1;width:18px;height:18px;border-radius:50%;border:0;background:transparent;color:var(--_muted);cursor:pointer}\n.realiiz-chips__input{flex:1;min-width:120px;border:0;background:transparent;font:inherit;color:inherit;outline:none;padding:4px}\n.realiiz-chips__count{margin-left:auto;color:var(--_muted);font-size:.75rem}\n.realiiz-gauge{display:inline-flex;align-items:center;gap:10px;font-size:.75rem;color:var(--_muted)}\n.realiiz-gauge__bar{position:relative;width:140px;height:6px;border-radius:3px;background:var(--_border);overflow:hidden}\n.realiiz-gauge__zone{position:absolute;top:0;bottom:0;background:rgba(21,128,61,.28)}\n.realiiz-gauge__fill{position:absolute;top:0;bottom:0;left:0;background:var(--_muted);border-radius:3px;transition:width .12s}\n.realiiz-gauge__text b{font-weight:600;color:inherit}\n.realiiz-gauge--ok{color:#15803d}.realiiz-gauge--ok .realiiz-gauge__fill{background:#15803d}\n.realiiz-gauge--over{color:var(--_danger)}.realiiz-gauge--over .realiiz-gauge__fill{background:var(--_danger)}\n`;\n","/**\n * MagicLinkForm — one field, one button, and the right words for each outcome.\n *\n * The audience is a non-technical client. Two outcomes matter:\n * sent → tell them where the link went and that it expires in an hour\n * uninvited → signups are off, so Supabase refuses unknown emails with a\n * \"Signups not allowed\" error. That string is a support ticket;\n * \"this email isn't set up for this site\" is not.\n *\n * `shouldCreateUser: false` restates the dashboard setting in code — the flag\n * a reviewer greps for.\n */\n\nimport { createBrowserClient } from \"@supabase/ssr\";\nimport { useMemo, useState, type FormEvent } from \"react\";\nimport { FORM_CSS } from \"../forms-ui/styles\";\n\nexport interface MagicLinkFormProps {\n url: string;\n anonKey: string;\n /** The site's callback, e.g. https://5degrees.org/admin/auth/callback?next=/admin */\n redirectTo: string;\n /** Shown in the heading: \"Sign in to {siteName}\". */\n siteName: string;\n className?: string;\n}\n\ntype State = { kind: \"idle\" } | { kind: \"sending\" } | { kind: \"sent\"; email: string } | { kind: \"error\"; message: string; uninvited: boolean };\n\nexport const UNINVITED_MESSAGE =\n \"This email address isn't set up for this site yet. Ask the site owner to send you an invite.\";\n\nexport function isUninvitedError(message: string): boolean {\n return /signups? not allowed|not allowed|user not found|invalid login/i.test(message);\n}\n\nexport function MagicLinkForm({ url, anonKey, redirectTo, siteName, className }: MagicLinkFormProps) {\n const supabase = useMemo(() => createBrowserClient(url, anonKey), [url, anonKey]);\n const [email, setEmail] = useState(\"\");\n const [state, setState] = useState<State>({ kind: \"idle\" });\n\n const submit = async (e: FormEvent) => {\n e.preventDefault();\n if (state.kind === \"sending\") return;\n const address = email.trim().toLowerCase();\n setState({ kind: \"sending\" });\n const { error } = await supabase.auth.signInWithOtp({\n email: address,\n options: { emailRedirectTo: redirectTo, shouldCreateUser: false },\n });\n if (error) {\n const uninvited = isUninvitedError(error.message);\n setState({ kind: \"error\", message: uninvited ? UNINVITED_MESSAGE : error.message, uninvited });\n return;\n }\n setState({ kind: \"sent\", email: address });\n };\n\n const root = [\"realiiz-form\", \"realiiz-signin\", className].filter(Boolean).join(\" \");\n\n if (state.kind === \"sent\") {\n return (\n <div className={root} data-realiiz-signin=\"sent\">\n <style>{FORM_CSS}</style>\n <h2 className=\"realiiz-signin__heading\">Check your email</h2>\n <p>\n We sent a sign-in link to <strong>{state.email}</strong>. It expires in an hour.\n </p>\n <button type=\"button\" className=\"realiiz-form__button\" onClick={() => setState({ kind: \"idle\" })}>\n Use a different address\n </button>\n </div>\n );\n }\n\n const sending = state.kind === \"sending\";\n const fieldError = state.kind === \"error\" && !state.uninvited ? state.message : null;\n\n return (\n <form className={root} onSubmit={submit} noValidate data-realiiz-signin=\"form\">\n <style>{FORM_CSS}</style>\n <h2 className=\"realiiz-signin__heading\">Sign in to {siteName}</h2>\n\n {state.kind === \"error\" && state.uninvited && (\n <div className=\"realiiz-form__alert\" role=\"alert\">{state.message}</div>\n )}\n\n <div className=\"realiiz-form__field\">\n <label className=\"realiiz-form__label\" htmlFor=\"realiiz-signin-email\">Email address</label>\n <input\n id=\"realiiz-signin-email\"\n className={[\"realiiz-form__control\", fieldError && \"realiiz-form__control--invalid\"].filter(Boolean).join(\" \")}\n type=\"email\"\n name=\"email\"\n autoComplete=\"email\"\n required\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n aria-invalid={fieldError ? true : undefined}\n aria-describedby={fieldError ? \"realiiz-signin-email-error\" : undefined}\n />\n {fieldError && (\n <div className=\"realiiz-form__error\" id=\"realiiz-signin-email-error\">{fieldError}</div>\n )}\n </div>\n\n <div className=\"realiiz-form__actions\">\n <button type=\"submit\" className=\"realiiz-form__button realiiz-form__button--primary\" disabled={sending || email.trim() === \"\"}>\n {sending ? \"Sending…\" : \"Send me a sign-in link\"}\n </button>\n </div>\n </form>\n );\n}\n","/**\n * SignOutButton — a plain POST form. No JavaScript needed, so it works before\n * hydration and inside a server component. The site's route (ADMIN-04) calls\n * signOut() from @realiizlabs/admin/auth and redirects.\n */\n\nexport interface SignOutButtonProps {\n /** Default \"/admin/auth/signout\". */\n actionPath?: string;\n className?: string;\n label?: string;\n}\n\nexport function SignOutButton({ actionPath = \"/admin/auth/signout\", className, label = \"Sign out\" }: SignOutButtonProps) {\n return (\n <form method=\"post\" action={actionPath} className={[\"realiiz-signout\", className].filter(Boolean).join(\" \")}>\n <button type=\"submit\" className=\"realiiz-form__button\">{label}</button>\n </form>\n );\n}\n"]}
|
package/dist/auth-ui/index.js
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/forms-ui/styles.ts
|
|
2
|
+
var FORM_CSS = `
|
|
3
|
+
.realiiz-form{
|
|
4
|
+
--_fg:var(--realiiz-form-fg,#111);
|
|
5
|
+
--_muted:var(--realiiz-form-muted,#666);
|
|
6
|
+
--_border:var(--realiiz-form-border,#cfcfcf);
|
|
7
|
+
--_accent:var(--realiiz-form-accent,#111);
|
|
8
|
+
--_accent-fg:var(--realiiz-form-accent-fg,#fff);
|
|
9
|
+
--_danger:var(--realiiz-form-danger,#b3261e);
|
|
10
|
+
--_radius:var(--realiiz-form-radius,6px);
|
|
11
|
+
--_font:var(--realiiz-form-font,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif);
|
|
12
|
+
--_ring:var(--realiiz-form-focus-ring,0 0 0 3px rgba(0,0,0,.15));
|
|
13
|
+
box-sizing:border-box;max-width:100%;color:var(--_fg);font-family:var(--_font);font-size:15px;line-height:1.4;
|
|
14
|
+
}
|
|
15
|
+
.realiiz-form *,.realiiz-form *::before,.realiiz-form *::after{box-sizing:inherit}
|
|
16
|
+
.realiiz-form fieldset{border:0;margin:0 0 20px;padding:0;min-width:0}
|
|
17
|
+
.realiiz-form legend{font-weight:600;font-size:13px;letter-spacing:.02em;text-transform:uppercase;color:var(--_muted);margin-bottom:12px;padding:0}
|
|
18
|
+
.realiiz-form__field{display:block;margin:0 0 16px}
|
|
19
|
+
.realiiz-form__label{display:block;font-weight:500;margin-bottom:6px}
|
|
20
|
+
.realiiz-form__required{color:var(--_danger);margin-left:3px}
|
|
21
|
+
.realiiz-form__control{display:block;width:100%;max-width:100%;font:inherit;color:inherit;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius);padding:9px 11px;min-height:40px}
|
|
22
|
+
.realiiz-form__control:focus{outline:none;border-color:var(--_accent);box-shadow:var(--_ring)}
|
|
23
|
+
.realiiz-form__control--textarea{min-height:110px;resize:vertical}
|
|
24
|
+
.realiiz-form__control--body{min-height:280px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px}
|
|
25
|
+
.realiiz-form__control--invalid{border-color:var(--_danger)}
|
|
26
|
+
.realiiz-form__check{display:flex;align-items:center;gap:8px;font-weight:500}
|
|
27
|
+
.realiiz-form__check input{width:18px;height:18px;margin:0}
|
|
28
|
+
.realiiz-form__helper{display:flex;justify-content:space-between;gap:12px;font-size:12px;color:var(--_muted);margin-top:4px;min-height:1em}
|
|
29
|
+
.realiiz-form__count{margin-left:auto;font-variant-numeric:tabular-nums}
|
|
30
|
+
.realiiz-form__error{color:var(--_danger);font-size:13px;margin-top:4px}
|
|
31
|
+
.realiiz-form__current{font-size:12px;color:var(--_muted);margin-top:4px;word-break:break-all}
|
|
32
|
+
.realiiz-form__alert{border:1px solid var(--_danger);border-radius:var(--_radius);padding:12px 14px;margin:0 0 20px;color:var(--_danger)}
|
|
33
|
+
.realiiz-form__alert ul{margin:6px 0 0;padding-left:18px}
|
|
34
|
+
.realiiz-form__actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:8px}
|
|
35
|
+
.realiiz-form__help{text-decoration:underline dotted;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:4px;cursor:help}
|
|
36
|
+
.realiiz-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
|
37
|
+
.realiiz-form__footer{max-width:920px}
|
|
38
|
+
.realiiz-form__bar{display:flex;align-items:center;gap:10px;margin-top:16px;padding:12px 0;border-top:1px solid var(--_border);background:#fff}
|
|
39
|
+
.realiiz-form__status{margin-right:auto;font-size:.85rem;color:var(--_muted)}
|
|
40
|
+
.realiiz-form__bar[data-dirty] .realiiz-form__status{color:var(--_fg)}
|
|
41
|
+
.realiiz-form__button{font:inherit;font-weight:600;border-radius:var(--_radius);padding:10px 16px;border:1px solid var(--_border);background:#fff;color:var(--_fg);cursor:pointer;min-height:40px}
|
|
42
|
+
.realiiz-form__button--primary{background:var(--_accent);color:var(--_accent-fg);border-color:var(--_accent)}
|
|
43
|
+
.realiiz-form__button:disabled{opacity:.6;cursor:default}
|
|
44
|
+
.realiiz-md{--_md-head:#fafbfd;--_md-hover:#f4f8fd;--_md-hover-line:#bcd0ea;--_md-on:#eef4fb;--_md-tip:#1f2933;position:relative}
|
|
45
|
+
.realiiz-md__mode{display:inline-flex;align-self:flex-start;width:max-content;gap:2px;padding:3px;background:color-mix(in srgb,var(--_border) 40%,transparent);border-radius:8px;margin-bottom:8px}
|
|
46
|
+
.realiiz-md__mode button{font:inherit;font-size:.8rem;padding:5px 13px;border:0;border-radius:6px;background:transparent;color:var(--_muted);cursor:pointer}
|
|
47
|
+
.realiiz-md__mode button[aria-selected="true"]{background:#fff;color:var(--_fg);box-shadow:0 1px 2px rgba(0,0,0,.12)}
|
|
48
|
+
.realiiz-md__panel{position:relative;z-index:0;display:flex;flex-direction:column;border:1px solid var(--_border);border-radius:10px;background:#fff;overflow:hidden}
|
|
49
|
+
.realiiz-md__panel:focus-within{border-color:var(--_md-hover-line)}
|
|
50
|
+
.realiiz-md__head{position:relative;z-index:5;display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding:5px 7px;background:var(--_md-head);border-bottom:1px solid var(--_border);flex-shrink:0}
|
|
51
|
+
.realiiz-md__tools{display:flex;align-items:center;gap:3px;flex-wrap:wrap}
|
|
52
|
+
.realiiz-md__spacer{flex:1}
|
|
53
|
+
.realiiz-md__head button{position:relative;min-width:31px;height:28px;padding:0 9px;display:inline-flex;align-items:center;justify-content:center;background:#fff;border:1px solid var(--_border);border-radius:6px;font-family:inherit;font-size:.82rem;color:var(--_fg);cursor:pointer;line-height:1}
|
|
54
|
+
.realiiz-md__head button:hover:not(:disabled){border-color:var(--_md-hover-line);background:var(--_md-hover)}
|
|
55
|
+
.realiiz-md__head button:active{background:var(--_md-on)}
|
|
56
|
+
.realiiz-md__head button.on{background:var(--_md-on);border-color:var(--_accent);color:var(--_accent);font-weight:600}
|
|
57
|
+
.realiiz-md__ico{width:15px;height:15px;display:block}
|
|
58
|
+
.realiiz-md__dot{font-size:1.05rem;line-height:1}
|
|
59
|
+
.realiiz-md__sep{width:1px;height:17px;background:var(--_border);margin:0 5px}
|
|
60
|
+
.realiiz-md__insert{display:inline-flex;align-items:center;gap:3px;border-left:1px solid var(--_border);padding-left:8px;margin-left:6px}
|
|
61
|
+
.realiiz-md__insert button{background:#f6f8fa;color:var(--_muted);padding:0;width:31px}
|
|
62
|
+
.realiiz-md__insert button:hover{color:var(--_accent)}
|
|
63
|
+
.realiiz-md__lab{font-size:.74rem;color:var(--_muted);margin-right:3px}
|
|
64
|
+
.realiiz-md__head button[data-tip]::after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);left:0;background:var(--_md-tip);color:#fff;font-size:.72rem;padding:4px 8px;border-radius:5px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;z-index:20}
|
|
65
|
+
.realiiz-md__head button[data-tip]:hover::after,.realiiz-md__head button[data-tip]:focus-visible::after{opacity:1}
|
|
66
|
+
.realiiz-md__expand[data-tip]::after{left:auto;right:0}
|
|
67
|
+
.realiiz-md__tgwrap{position:relative;display:inline-flex}
|
|
68
|
+
.realiiz-md__tgrid{position:absolute;top:calc(100% + 6px);left:0;background:#fff;border:1px solid var(--_border);border-radius:9px;padding:9px;box-shadow:0 10px 28px rgba(0,0,0,.14);z-index:7;display:block}
|
|
69
|
+
.realiiz-md__tgcells{display:grid;grid-template-columns:repeat(6,17px);gap:3px}
|
|
70
|
+
.realiiz-md__tgcells i{width:17px;height:15px;border:1px solid var(--_border);border-radius:2px;background:#fff;cursor:pointer;display:block}
|
|
71
|
+
.realiiz-md__tgcells i.hot{background:#dbe9fb;border-color:var(--_accent)}
|
|
72
|
+
.realiiz-md__tglab{display:block;margin-top:8px;font-size:.74rem;color:var(--_muted);text-align:center;white-space:nowrap}
|
|
73
|
+
.realiiz-md .realiiz-md__ta{flex:1 1 auto;border:0;border-radius:0;resize:vertical;background:#fff;max-width:none;padding:16px 18px;line-height:1.65}
|
|
74
|
+
.realiiz-md .realiiz-md__ta:focus{outline:none;box-shadow:none}
|
|
75
|
+
.realiiz-md__preview{padding:20px 24px;background:#fff}
|
|
76
|
+
.realiiz-md__note{padding:4px 2px}
|
|
77
|
+
.realiiz-md--fs{position:fixed;inset:0;z-index:60;background:#fff;padding:14px 22px 22px;overflow:auto;display:flex;flex-direction:column}
|
|
78
|
+
.realiiz-md--fs .realiiz-md__panel{flex:1;min-height:0}
|
|
79
|
+
.realiiz-md--fs .realiiz-md__ta,.realiiz-md--fs .realiiz-md__preview{flex:1;min-height:0;overflow:auto;resize:none}
|
|
80
|
+
.realiiz-prose{max-width:68ch;line-height:1.65}
|
|
81
|
+
.realiiz-chips{display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:40px;padding:5px 8px;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius)}
|
|
82
|
+
.realiiz-chips:focus-within{border-color:var(--_accent);box-shadow:var(--_ring)}
|
|
83
|
+
.realiiz-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 9px;border:1px solid var(--_border);border-radius:999px;font-size:.8rem}
|
|
84
|
+
.realiiz-chip button{font:inherit;line-height:1;width:18px;height:18px;border-radius:50%;border:0;background:transparent;color:var(--_muted);cursor:pointer}
|
|
85
|
+
.realiiz-chips__input{flex:1;min-width:120px;border:0;background:transparent;font:inherit;color:inherit;outline:none;padding:4px}
|
|
86
|
+
.realiiz-chips__count{margin-left:auto;color:var(--_muted);font-size:.75rem}
|
|
87
|
+
.realiiz-gauge{display:inline-flex;align-items:center;gap:10px;font-size:.75rem;color:var(--_muted)}
|
|
88
|
+
.realiiz-gauge__bar{position:relative;width:140px;height:6px;border-radius:3px;background:var(--_border);overflow:hidden}
|
|
89
|
+
.realiiz-gauge__zone{position:absolute;top:0;bottom:0;background:rgba(21,128,61,.28)}
|
|
90
|
+
.realiiz-gauge__fill{position:absolute;top:0;bottom:0;left:0;background:var(--_muted);border-radius:3px;transition:width .12s}
|
|
91
|
+
.realiiz-gauge__text b{font-weight:600;color:inherit}
|
|
92
|
+
.realiiz-gauge--ok{color:#15803d}.realiiz-gauge--ok .realiiz-gauge__fill{background:#15803d}
|
|
93
|
+
.realiiz-gauge--over{color:var(--_danger)}.realiiz-gauge--over .realiiz-gauge__fill{background:var(--_danger)}
|
|
94
|
+
`;
|
|
95
|
+
|
|
96
|
+
export { FORM_CSS };
|
|
97
|
+
//# sourceMappingURL=chunk-CE2DRQBD.js.map
|
|
98
|
+
//# sourceMappingURL=chunk-CE2DRQBD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms-ui/styles.ts"],"names":[],"mappings":";AAMO,IAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA","file":"chunk-CE2DRQBD.js","sourcesContent":["/**\n * Theming hooks, same convention as BookingWidget: a root class, BEM elements,\n * and --realiiz-form-* custom properties with fallbacks so the form is usable\n * with zero host CSS and fully themeable with a dozen variables.\n */\n\nexport const FORM_CSS = `\n.realiiz-form{\n --_fg:var(--realiiz-form-fg,#111);\n --_muted:var(--realiiz-form-muted,#666);\n --_border:var(--realiiz-form-border,#cfcfcf);\n --_accent:var(--realiiz-form-accent,#111);\n --_accent-fg:var(--realiiz-form-accent-fg,#fff);\n --_danger:var(--realiiz-form-danger,#b3261e);\n --_radius:var(--realiiz-form-radius,6px);\n --_font:var(--realiiz-form-font,system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif);\n --_ring:var(--realiiz-form-focus-ring,0 0 0 3px rgba(0,0,0,.15));\n box-sizing:border-box;max-width:100%;color:var(--_fg);font-family:var(--_font);font-size:15px;line-height:1.4;\n}\n.realiiz-form *,.realiiz-form *::before,.realiiz-form *::after{box-sizing:inherit}\n.realiiz-form fieldset{border:0;margin:0 0 20px;padding:0;min-width:0}\n.realiiz-form legend{font-weight:600;font-size:13px;letter-spacing:.02em;text-transform:uppercase;color:var(--_muted);margin-bottom:12px;padding:0}\n.realiiz-form__field{display:block;margin:0 0 16px}\n.realiiz-form__label{display:block;font-weight:500;margin-bottom:6px}\n.realiiz-form__required{color:var(--_danger);margin-left:3px}\n.realiiz-form__control{display:block;width:100%;max-width:100%;font:inherit;color:inherit;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius);padding:9px 11px;min-height:40px}\n.realiiz-form__control:focus{outline:none;border-color:var(--_accent);box-shadow:var(--_ring)}\n.realiiz-form__control--textarea{min-height:110px;resize:vertical}\n.realiiz-form__control--body{min-height:280px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px}\n.realiiz-form__control--invalid{border-color:var(--_danger)}\n.realiiz-form__check{display:flex;align-items:center;gap:8px;font-weight:500}\n.realiiz-form__check input{width:18px;height:18px;margin:0}\n.realiiz-form__helper{display:flex;justify-content:space-between;gap:12px;font-size:12px;color:var(--_muted);margin-top:4px;min-height:1em}\n.realiiz-form__count{margin-left:auto;font-variant-numeric:tabular-nums}\n.realiiz-form__error{color:var(--_danger);font-size:13px;margin-top:4px}\n.realiiz-form__current{font-size:12px;color:var(--_muted);margin-top:4px;word-break:break-all}\n.realiiz-form__alert{border:1px solid var(--_danger);border-radius:var(--_radius);padding:12px 14px;margin:0 0 20px;color:var(--_danger)}\n.realiiz-form__alert ul{margin:6px 0 0;padding-left:18px}\n.realiiz-form__actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:8px}\n.realiiz-form__help{text-decoration:underline dotted;text-decoration-color:color-mix(in srgb,currentColor 45%,transparent);text-underline-offset:4px;cursor:help}\n.realiiz-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n.realiiz-form__footer{max-width:920px}\n.realiiz-form__bar{display:flex;align-items:center;gap:10px;margin-top:16px;padding:12px 0;border-top:1px solid var(--_border);background:#fff}\n.realiiz-form__status{margin-right:auto;font-size:.85rem;color:var(--_muted)}\n.realiiz-form__bar[data-dirty] .realiiz-form__status{color:var(--_fg)}\n.realiiz-form__button{font:inherit;font-weight:600;border-radius:var(--_radius);padding:10px 16px;border:1px solid var(--_border);background:#fff;color:var(--_fg);cursor:pointer;min-height:40px}\n.realiiz-form__button--primary{background:var(--_accent);color:var(--_accent-fg);border-color:var(--_accent)}\n.realiiz-form__button:disabled{opacity:.6;cursor:default}\n.realiiz-md{--_md-head:#fafbfd;--_md-hover:#f4f8fd;--_md-hover-line:#bcd0ea;--_md-on:#eef4fb;--_md-tip:#1f2933;position:relative}\n.realiiz-md__mode{display:inline-flex;align-self:flex-start;width:max-content;gap:2px;padding:3px;background:color-mix(in srgb,var(--_border) 40%,transparent);border-radius:8px;margin-bottom:8px}\n.realiiz-md__mode button{font:inherit;font-size:.8rem;padding:5px 13px;border:0;border-radius:6px;background:transparent;color:var(--_muted);cursor:pointer}\n.realiiz-md__mode button[aria-selected=\"true\"]{background:#fff;color:var(--_fg);box-shadow:0 1px 2px rgba(0,0,0,.12)}\n.realiiz-md__panel{position:relative;z-index:0;display:flex;flex-direction:column;border:1px solid var(--_border);border-radius:10px;background:#fff;overflow:hidden}\n.realiiz-md__panel:focus-within{border-color:var(--_md-hover-line)}\n.realiiz-md__head{position:relative;z-index:5;display:flex;align-items:center;gap:2px;flex-wrap:wrap;padding:5px 7px;background:var(--_md-head);border-bottom:1px solid var(--_border);flex-shrink:0}\n.realiiz-md__tools{display:flex;align-items:center;gap:3px;flex-wrap:wrap}\n.realiiz-md__spacer{flex:1}\n.realiiz-md__head button{position:relative;min-width:31px;height:28px;padding:0 9px;display:inline-flex;align-items:center;justify-content:center;background:#fff;border:1px solid var(--_border);border-radius:6px;font-family:inherit;font-size:.82rem;color:var(--_fg);cursor:pointer;line-height:1}\n.realiiz-md__head button:hover:not(:disabled){border-color:var(--_md-hover-line);background:var(--_md-hover)}\n.realiiz-md__head button:active{background:var(--_md-on)}\n.realiiz-md__head button.on{background:var(--_md-on);border-color:var(--_accent);color:var(--_accent);font-weight:600}\n.realiiz-md__ico{width:15px;height:15px;display:block}\n.realiiz-md__dot{font-size:1.05rem;line-height:1}\n.realiiz-md__sep{width:1px;height:17px;background:var(--_border);margin:0 5px}\n.realiiz-md__insert{display:inline-flex;align-items:center;gap:3px;border-left:1px solid var(--_border);padding-left:8px;margin-left:6px}\n.realiiz-md__insert button{background:#f6f8fa;color:var(--_muted);padding:0;width:31px}\n.realiiz-md__insert button:hover{color:var(--_accent)}\n.realiiz-md__lab{font-size:.74rem;color:var(--_muted);margin-right:3px}\n.realiiz-md__head button[data-tip]::after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);left:0;background:var(--_md-tip);color:#fff;font-size:.72rem;padding:4px 8px;border-radius:5px;white-space:nowrap;opacity:0;pointer-events:none;transition:opacity .12s;z-index:20}\n.realiiz-md__head button[data-tip]:hover::after,.realiiz-md__head button[data-tip]:focus-visible::after{opacity:1}\n.realiiz-md__expand[data-tip]::after{left:auto;right:0}\n.realiiz-md__tgwrap{position:relative;display:inline-flex}\n.realiiz-md__tgrid{position:absolute;top:calc(100% + 6px);left:0;background:#fff;border:1px solid var(--_border);border-radius:9px;padding:9px;box-shadow:0 10px 28px rgba(0,0,0,.14);z-index:7;display:block}\n.realiiz-md__tgcells{display:grid;grid-template-columns:repeat(6,17px);gap:3px}\n.realiiz-md__tgcells i{width:17px;height:15px;border:1px solid var(--_border);border-radius:2px;background:#fff;cursor:pointer;display:block}\n.realiiz-md__tgcells i.hot{background:#dbe9fb;border-color:var(--_accent)}\n.realiiz-md__tglab{display:block;margin-top:8px;font-size:.74rem;color:var(--_muted);text-align:center;white-space:nowrap}\n.realiiz-md .realiiz-md__ta{flex:1 1 auto;border:0;border-radius:0;resize:vertical;background:#fff;max-width:none;padding:16px 18px;line-height:1.65}\n.realiiz-md .realiiz-md__ta:focus{outline:none;box-shadow:none}\n.realiiz-md__preview{padding:20px 24px;background:#fff}\n.realiiz-md__note{padding:4px 2px}\n.realiiz-md--fs{position:fixed;inset:0;z-index:60;background:#fff;padding:14px 22px 22px;overflow:auto;display:flex;flex-direction:column}\n.realiiz-md--fs .realiiz-md__panel{flex:1;min-height:0}\n.realiiz-md--fs .realiiz-md__ta,.realiiz-md--fs .realiiz-md__preview{flex:1;min-height:0;overflow:auto;resize:none}\n.realiiz-prose{max-width:68ch;line-height:1.65}\n.realiiz-chips{display:flex;flex-wrap:wrap;gap:6px;align-items:center;min-height:40px;padding:5px 8px;background:#fff;border:1px solid var(--_border);border-radius:var(--_radius)}\n.realiiz-chips:focus-within{border-color:var(--_accent);box-shadow:var(--_ring)}\n.realiiz-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 9px;border:1px solid var(--_border);border-radius:999px;font-size:.8rem}\n.realiiz-chip button{font:inherit;line-height:1;width:18px;height:18px;border-radius:50%;border:0;background:transparent;color:var(--_muted);cursor:pointer}\n.realiiz-chips__input{flex:1;min-width:120px;border:0;background:transparent;font:inherit;color:inherit;outline:none;padding:4px}\n.realiiz-chips__count{margin-left:auto;color:var(--_muted);font-size:.75rem}\n.realiiz-gauge{display:inline-flex;align-items:center;gap:10px;font-size:.75rem;color:var(--_muted)}\n.realiiz-gauge__bar{position:relative;width:140px;height:6px;border-radius:3px;background:var(--_border);overflow:hidden}\n.realiiz-gauge__zone{position:absolute;top:0;bottom:0;background:rgba(21,128,61,.28)}\n.realiiz-gauge__fill{position:absolute;top:0;bottom:0;left:0;background:var(--_muted);border-radius:3px;transition:width .12s}\n.realiiz-gauge__text b{font-weight:600;color:inherit}\n.realiiz-gauge--ok{color:#15803d}.realiiz-gauge--ok .realiiz-gauge__fill{background:#15803d}\n.realiiz-gauge--over{color:var(--_danger)}.realiiz-gauge--over .realiiz-gauge__fill{background:var(--_danger)}\n`;\n"]}
|
|
@@ -135,12 +135,26 @@ function readMeta(schema) {
|
|
|
135
135
|
const s = schema;
|
|
136
136
|
const raw = typeof s.meta === "function" ? s.meta() ?? {} : {};
|
|
137
137
|
const pick = (k) => typeof raw[k] === "string" ? raw[k] : void 0;
|
|
138
|
+
const rec = raw.recommended;
|
|
139
|
+
const recommended = Array.isArray(rec) && rec.length === 2 && rec.every((n) => typeof n === "number") ? [rec[0], rec[1]] : void 0;
|
|
140
|
+
const INPUTS = ["text", "textarea", "date", "number", "boolean", "select", "tags", "image", "url"];
|
|
141
|
+
const input = typeof raw.input === "string" && INPUTS.includes(raw.input) ? raw.input : void 0;
|
|
138
142
|
return {
|
|
139
143
|
label: pick("label"),
|
|
140
144
|
placeholder: pick("placeholder"),
|
|
141
|
-
description: pick("description") ?? (typeof s.description === "string" ? s.description : void 0)
|
|
145
|
+
description: pick("description") ?? (typeof s.description === "string" ? s.description : void 0),
|
|
146
|
+
recommended,
|
|
147
|
+
suffix: pick("suffix"),
|
|
148
|
+
help: pick("help"),
|
|
149
|
+
input
|
|
142
150
|
};
|
|
143
151
|
}
|
|
152
|
+
function inputOverrideFor(name, schema, entry) {
|
|
153
|
+
return entry?.inputs?.[name] ?? readMeta(schema).input;
|
|
154
|
+
}
|
|
155
|
+
function recommendedFor(name, schema, entry) {
|
|
156
|
+
return entry?.recommended?.[name] ?? readMeta(schema).recommended;
|
|
157
|
+
}
|
|
144
158
|
function titlecase(name) {
|
|
145
159
|
const words = name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").toLowerCase().trim();
|
|
146
160
|
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
@@ -154,6 +168,9 @@ function labelFor(name, schema, entry) {
|
|
|
154
168
|
function placeholderFor(name, schema, entry) {
|
|
155
169
|
return entry?.placeholders?.[name] ?? readMeta(schema).placeholder;
|
|
156
170
|
}
|
|
171
|
+
function helpFor(name, schema, entry) {
|
|
172
|
+
return entry?.help?.[name] ?? readMeta(schema).help;
|
|
173
|
+
}
|
|
157
174
|
|
|
158
175
|
// src/forms/walk.ts
|
|
159
176
|
function walkSchema(schema, entry = {}) {
|
|
@@ -168,11 +185,14 @@ function walkSchema(schema, entry = {}) {
|
|
|
168
185
|
return {
|
|
169
186
|
name,
|
|
170
187
|
label: labelFor(name, raw, entry),
|
|
171
|
-
input: role === "image" ? "image" : info.input,
|
|
188
|
+
input: role === "image" ? "image" : inputOverrideFor(name, raw, entry) ?? info.input,
|
|
172
189
|
required,
|
|
173
190
|
constraints: info.constraints,
|
|
174
191
|
messages: info.messages,
|
|
175
192
|
placeholder: placeholderFor(name, raw, entry),
|
|
193
|
+
recommended: recommendedFor(name, raw, entry),
|
|
194
|
+
suffix: readMeta(raw).suffix,
|
|
195
|
+
help: helpFor(name, raw, entry),
|
|
176
196
|
order: 0,
|
|
177
197
|
role,
|
|
178
198
|
options: entry.options?.[name] ?? info.options
|
|
@@ -233,7 +253,14 @@ function defineContentType(entry) {
|
|
|
233
253
|
check(entry.hidden, "hidden");
|
|
234
254
|
check(Object.keys(entry.labels ?? {}), "labels");
|
|
235
255
|
check(Object.keys(entry.placeholders ?? {}), "placeholders");
|
|
256
|
+
check(Object.keys(entry.recommended ?? {}), "recommended");
|
|
257
|
+
check(Object.keys(entry.inputs ?? {}), "inputs");
|
|
258
|
+
check(Object.keys(entry.help ?? {}), "help");
|
|
236
259
|
check(Object.keys(entry.options ?? {}), "options");
|
|
260
|
+
for (const g of entry.groups ?? []) {
|
|
261
|
+
if (typeof g.label !== "string" || g.label.length === 0) throw new TypeError(`${where}: every group needs a label`);
|
|
262
|
+
check(g.fields, `groups["${g.label}"]`);
|
|
263
|
+
}
|
|
237
264
|
return entry;
|
|
238
265
|
}
|
|
239
266
|
function findShape(root) {
|
|
@@ -255,5 +282,5 @@ function navFromContentTypes(entries, opts = {}) {
|
|
|
255
282
|
}
|
|
256
283
|
|
|
257
284
|
export { defineContentType, navFromContentTypes, titlecase, walkSchema };
|
|
258
|
-
//# sourceMappingURL=chunk-
|
|
259
|
-
//# sourceMappingURL=chunk-
|
|
285
|
+
//# sourceMappingURL=chunk-J6FI73PF.js.map
|
|
286
|
+
//# sourceMappingURL=chunk-J6FI73PF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/forms/internals.ts","../src/forms/checks.ts","../src/forms/unwrap.ts","../src/forms/inputs.ts","../src/forms/labels.ts","../src/forms/walk.ts","../src/forms/registry.ts","../src/forms/nav.ts"],"names":[],"mappings":"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","file":"chunk-J6FI73PF.js","sourcesContent":["/**\n * The slice of zod 4's `_zod.def` surface this module reads, typed loosely.\n *\n * Tested against zod 4.5.4. These are semi-public internals (the v4 \"core\"\n * shape), stable across 4.x so far but not covered by semver promises — hence\n * the peer-dep range and the fixture tests. No zod value is imported here.\n */\n\nexport interface ZodCheckDef {\n check?: string;\n format?: string;\n minimum?: number;\n maximum?: number;\n length?: number;\n value?: number;\n inclusive?: boolean;\n pattern?: RegExp;\n error?: string | ((issue: unknown) => string | { message?: string } | undefined);\n}\n\nexport interface ZodDef {\n type: string;\n shape?: Record<string, ZodNode>;\n innerType?: ZodNode;\n in?: ZodNode;\n out?: ZodNode;\n element?: ZodNode;\n entries?: Record<string, string | number>;\n checks?: Array<{ _zod: { def: ZodCheckDef } }>;\n coerce?: boolean;\n}\n\nexport interface ZodNode {\n _zod: { def: ZodDef };\n description?: string;\n}\n\n/** Narrow an unknown schema to the internal node shape, or throw a clear error. */\nexport function asNode(schema: unknown, what = \"schema\"): ZodNode {\n const n = schema as Partial<ZodNode> | null;\n if (!n || typeof n !== \"object\" || !n._zod?.def?.type) {\n throw new TypeError(`walkSchema: ${what} is not a zod 4 schema`);\n }\n return n as ZodNode;\n}\n\n/** Resolve a check's error to a plain string, if it has one. */\nexport function checkMessage(def: ZodCheckDef): string | undefined {\n const e = def.error;\n if (!e) return undefined;\n if (typeof e === \"string\") return e;\n const out = e({});\n if (typeof out === \"string\") return out;\n return out?.message;\n}\n","/**\n * checks[] → constraints + messages.\n *\n * Messages are keyed PER CHECK. The spike's walker wrote `out.message = …` on\n * every check, so a field with min and max kept only the max message and\n * showed the wrong error for a too-short value. Here each check kind gets its\n * own key; a renderer maps a failed issue to its message by that key.\n *\n * Unknown check kinds (e.g. a per-field `.refine`, which is `custom`) are kept\n * as a message when they carry one and otherwise skipped — never fatal.\n */\n\nimport type { Constraints, Messages } from \"./types\";\nimport type { ZodNode } from \"./internals\";\nimport { checkMessage } from \"./internals\";\n\nexport function readChecks(node: ZodNode): { constraints: Constraints; messages: Messages } {\n const constraints: Constraints = {};\n const messages: Messages = {};\n\n for (const c of node._zod.def.checks ?? []) {\n const d = c._zod.def;\n const msg = checkMessage(d);\n let key: string | undefined;\n\n switch (d.check) {\n case \"min_length\":\n constraints.min = d.minimum;\n key = \"min_length\";\n break;\n case \"max_length\":\n constraints.max = d.maximum;\n key = \"max_length\";\n break;\n case \"length_equals\":\n constraints.exact = d.length;\n key = \"length_equals\";\n break;\n case \"greater_than\":\n constraints.min = d.inclusive ? d.value : (d.value ?? 0) + 1;\n key = \"greater_than\";\n break;\n case \"less_than\":\n constraints.max = d.inclusive ? d.value : (d.value ?? 0) - 1;\n key = \"less_than\";\n break;\n case \"string_format\":\n if (d.format === \"regex\" && d.pattern) {\n constraints.pattern = d.pattern.source;\n constraints.format = \"regex\";\n key = \"regex\";\n } else if (d.format === \"url\" || d.format === \"email\") {\n constraints.format = d.format;\n key = d.format;\n } else {\n key = d.format;\n }\n break;\n case \"number_format\":\n if (d.format === \"safeint\" || d.format === \"int32\") {\n constraints.format = \"int\";\n key = \"int\";\n }\n break;\n case \"custom\":\n key = \"custom\";\n break;\n default:\n key = d.check;\n }\n\n if (key && msg) messages[key] = msg;\n }\n\n return { constraints, messages };\n}\n","/**\n * Peel wrapper types off a field until the real type is reached.\n *\n * optional / nullable / default → the field is not required.\n * pipe → follow `out` (older 4.x wrapped z.coerce.date in a pipe; 4.5 marks\n * the date itself with `coerce: true` — both land on the same node here).\n */\n\nimport type { ZodNode } from \"./internals\";\n\nexport interface Unwrapped {\n node: ZodNode;\n type: string;\n required: boolean;\n}\n\nexport function unwrap(start: ZodNode): Unwrapped {\n let node = start;\n let required = true;\n // Bounded so a malformed schema can't loop forever.\n for (let i = 0; i < 16; i++) {\n const def = node._zod.def;\n if (def.type === \"optional\" || def.type === \"nullable\" || def.type === \"default\") {\n required = false;\n if (!def.innerType) break;\n node = def.innerType;\n } else if (def.type === \"pipe\") {\n const next = def.out ?? def.in;\n if (!next) break;\n node = next;\n } else {\n break;\n }\n }\n return { node, type: node._zod.def.type, required };\n}\n","/**\n * zod type → InputKind, plus the extras some kinds carry (enum options, the\n * array item's constraints).\n *\n * Long strings become textareas by a simple rule: a max over 120 chars. That\n * is a heuristic, and the registry can't override it today — if a site needs\n * to, that is a one-line change here, not a per-site branch.\n */\n\nimport type { Constraints, InputKind, Messages } from \"./types\";\nimport type { ZodNode } from \"./internals\";\nimport { readChecks } from \"./checks\";\nimport { unwrap } from \"./unwrap\";\n\nconst TEXTAREA_MIN_MAX = 120;\n\nexport interface InputInfo {\n input: InputKind;\n constraints: Constraints;\n messages: Messages;\n options?: string[];\n}\n\nexport function inputFor(node: ZodNode): InputInfo {\n const def = node._zod.def;\n const { constraints, messages } = readChecks(node);\n\n switch (def.type) {\n case \"string\": {\n if (constraints.format === \"url\") return { input: \"url\", constraints, messages };\n const long = (constraints.max ?? 0) > TEXTAREA_MIN_MAX;\n return { input: long ? \"textarea\" : \"text\", constraints, messages };\n }\n case \"date\":\n return { input: \"date\", constraints, messages };\n case \"number\":\n case \"int\":\n return { input: \"number\", constraints, messages };\n case \"boolean\":\n return { input: \"boolean\", constraints, messages };\n case \"enum\":\n case \"literal\": {\n const options = Object.values(def.entries ?? {}).map(String);\n return { input: \"select\", constraints, messages, options };\n }\n case \"array\": {\n if (def.element) {\n const item = unwrap(def.element);\n const inner = readChecks(item.node);\n constraints.item = inner;\n }\n return { input: \"tags\", constraints, messages };\n }\n default:\n // Anything unrecognised (object, union, …) is presented as text so the\n // value can at least be carried; a renderer may choose to treat it as hidden.\n return { input: \"text\", constraints, messages };\n }\n}\n","/**\n * Labels and placeholders.\n *\n * Precedence (decided 2026-09-08):\n * label: registry.labels[name] → .meta({ label }) → .describe() → titlecase(name)\n * placeholder: registry.placeholders[name] → .meta({ placeholder }) → undefined\n *\n * The registry tier exists for schemas that can't be edited yet (5degrees\n * until its repo transfer). The meta tier is the intended home — one source of\n * truth beside the validation rules. Titlecase is the floor, and it is naive on\n * purpose: an acronym coming out as \"Rsvp url\" is the signal that a real label\n * is missing.\n *\n * Meta is read from zod's global registry via the schema's own `meta()` /\n * `description` accessors, so no zod value is imported here.\n */\n\nimport type { ContentTypeEntry, InputKind } from \"./types\";\n\ninterface MetaBearing {\n meta?: () => Record<string, unknown> | undefined;\n description?: string;\n}\n\ninterface FieldMeta {\n label?: string;\n placeholder?: string;\n description?: string;\n recommended?: [number, number];\n suffix?: string;\n help?: string;\n input?: InputKind;\n}\n\nexport function readMeta(schema: unknown): FieldMeta {\n const s = schema as MetaBearing;\n const raw = typeof s.meta === \"function\" ? (s.meta() ?? {}) : {};\n const pick = (k: keyof FieldMeta) => (typeof raw[k] === \"string\" ? (raw[k] as string) : undefined);\n const rec = raw.recommended;\n const recommended =\n Array.isArray(rec) && rec.length === 2 && rec.every((n) => typeof n === \"number\") ? ([rec[0], rec[1]] as [number, number]) : undefined;\n const INPUTS: InputKind[] = [\"text\", \"textarea\", \"date\", \"number\", \"boolean\", \"select\", \"tags\", \"image\", \"url\"];\n const input = typeof raw.input === \"string\" && (INPUTS as string[]).includes(raw.input) ? (raw.input as InputKind) : undefined;\n return {\n label: pick(\"label\"),\n placeholder: pick(\"placeholder\"),\n description: pick(\"description\") ?? (typeof s.description === \"string\" ? s.description : undefined),\n recommended,\n suffix: pick(\"suffix\"),\n help: pick(\"help\"),\n input,\n };\n}\n\nexport function inputOverrideFor(\n name: string,\n schema: unknown,\n entry?: Pick<ContentTypeEntry, \"inputs\">,\n): InputKind | undefined {\n return entry?.inputs?.[name] ?? readMeta(schema).input;\n}\n\nexport function recommendedFor(\n name: string,\n schema: unknown,\n entry?: Pick<ContentTypeEntry, \"recommended\">,\n): [number, number] | undefined {\n return entry?.recommended?.[name] ?? readMeta(schema).recommended;\n}\n\nexport function titlecase(name: string): string {\n const words = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/[_-]+/g, \" \")\n .toLowerCase()\n .trim();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\nexport function labelFor(name: string, schema: unknown, entry?: Pick<ContentTypeEntry, \"labels\">): string {\n const fromRegistry = entry?.labels?.[name];\n if (fromRegistry) return fromRegistry;\n const meta = readMeta(schema);\n return meta.label ?? meta.description ?? titlecase(name);\n}\n\nexport function placeholderFor(\n name: string,\n schema: unknown,\n entry?: Pick<ContentTypeEntry, \"placeholders\">,\n): string | undefined {\n return entry?.placeholders?.[name] ?? readMeta(schema).placeholder;\n}\n\nexport function helpFor(name: string, schema: unknown, entry?: Pick<ContentTypeEntry, \"help\">): string | undefined {\n return entry?.help?.[name] ?? readMeta(schema).help;\n}\n","/**\n * walkSchema — a zod object schema (+ optional registry entry) → FieldSpec[].\n *\n * Synchronous and pure. Reads the schema's shape and checks; never parses a\n * value, never calls an options resolver, never imports zod at runtime.\n *\n * Roles from the registry override the schema-derived input kind: a field the\n * entry names as an image is `role: \"image\"` even though zod sees a string.\n * Hidden fields are still emitted so a renderer can carry their values through.\n */\n\nimport type { ContentTypeEntry, FieldRole, FieldSpec } from \"./types\";\nimport type { ZodNode } from \"./internals\";\nimport { asNode } from \"./internals\";\nimport { inputFor } from \"./inputs\";\nimport { helpFor, inputOverrideFor, labelFor, placeholderFor, readMeta, recommendedFor } from \"./labels\";\nimport { unwrap } from \"./unwrap\";\n\ntype Entry = Partial<Omit<ContentTypeEntry, \"schema\" | \"filename\" | \"id\" | \"label\" | \"folder\">>;\n\nexport function walkSchema(schema: unknown, entry: Entry = {}): FieldSpec[] {\n const root = asNode(schema);\n const shape = shapeOf(root);\n const names = Object.keys(shape);\n\n const specs = names.map((name): FieldSpec => {\n const raw = shape[name];\n const { node, required } = unwrap(raw);\n const info = inputFor(node);\n const role = roleFor(name, entry);\n\n return {\n name,\n label: labelFor(name, raw, entry),\n input: role === \"image\" ? \"image\" : (inputOverrideFor(name, raw, entry) ?? info.input),\n required,\n constraints: info.constraints,\n messages: info.messages,\n placeholder: placeholderFor(name, raw, entry),\n recommended: recommendedFor(name, raw, entry),\n suffix: readMeta(raw).suffix,\n help: helpFor(name, raw, entry),\n order: 0,\n role,\n options: entry.options?.[name] ?? info.options,\n };\n });\n\n return applyOrder(specs, entry.order ?? []);\n}\n\n/** `.strict()` and object-level `.refine()` both leave `shape` on the object def. */\nfunction shapeOf(root: ZodNode): Record<string, ZodNode> {\n let node = root;\n for (let i = 0; i < 8 && !node._zod.def.shape; i++) {\n const def = node._zod.def;\n const next = def.innerType ?? def.in;\n if (!next) break;\n node = next;\n }\n const shape = node._zod.def.shape;\n if (!shape) throw new TypeError(`walkSchema: expected an object schema, got \"${root._zod.def.type}\"`);\n return shape;\n}\n\nfunction roleFor(name: string, entry: Entry): FieldRole {\n if (entry.hidden?.includes(name)) return \"hidden\";\n if (entry.body === name) return \"body\";\n if (entry.images?.includes(name)) return \"image\";\n return \"field\";\n}\n\n/** Named fields first in the given order; the rest keep schema key order. */\nfunction applyOrder(specs: FieldSpec[], order: string[]): FieldSpec[] {\n const rank = new Map(order.map((n, i) => [n, i]));\n const named = specs.filter((s) => rank.has(s.name)).sort((a, b) => rank.get(a.name)! - rank.get(b.name)!);\n const rest = specs.filter((s) => !rank.has(s.name));\n return [...named, ...rest].map((s, i) => ({ ...s, order: i }));\n}\n","/**\n * defineContentType — validate a registry entry against the schema it describes.\n *\n * Validation is hand-rolled rather than a zod schema on purpose: this module\n * must not import zod at runtime (the host's instance is the only one that\n * should exist). The checks are small and the errors name the bad key.\n */\n\nimport type { ZodType } from \"zod\";\nimport type { ContentTypeEntry } from \"./types\";\nimport { asNode } from \"./internals\";\n\nexport function defineContentType<S extends ZodType>(entry: ContentTypeEntry<S>): ContentTypeEntry<S> {\n const where = `defineContentType(\"${entry.id}\")`;\n\n for (const key of [\"id\", \"label\", \"folder\"] as const) {\n if (typeof entry[key] !== \"string\" || entry[key].length === 0) {\n throw new TypeError(`${where}: \"${key}\" must be a non-empty string`);\n }\n }\n if (typeof entry.filename !== \"function\") {\n throw new TypeError(`${where}: \"filename\" must be a function (frontmatter) => string`);\n }\n if (entry.body !== null && typeof entry.body !== \"string\") {\n throw new TypeError(`${where}: \"body\" must be a field name or null`);\n }\n\n const root = asNode(entry.schema, `${where}: schema`);\n const shape = findShape(root);\n const known = new Set(Object.keys(shape));\n\n const check = (list: string[] | undefined, key: string) => {\n for (const name of list ?? []) {\n if (!known.has(name)) throw new TypeError(`${where}: ${key} names \"${name}\", which is not a field of the schema`);\n }\n };\n\n if (entry.body !== null) check([entry.body], \"body\");\n check(entry.images, \"images\");\n check(entry.order, \"order\");\n check(entry.hidden, \"hidden\");\n check(Object.keys(entry.labels ?? {}), \"labels\");\n check(Object.keys(entry.placeholders ?? {}), \"placeholders\");\n check(Object.keys(entry.recommended ?? {}), \"recommended\");\n check(Object.keys(entry.inputs ?? {}), \"inputs\");\n check(Object.keys(entry.help ?? {}), \"help\");\n check(Object.keys(entry.options ?? {}), \"options\");\n for (const g of entry.groups ?? []) {\n if (typeof g.label !== \"string\" || g.label.length === 0) throw new TypeError(`${where}: every group needs a label`);\n check(g.fields, `groups[\"${g.label}\"]`);\n }\n\n return entry;\n}\n\nfunction findShape(root: ReturnType<typeof asNode>): Record<string, unknown> {\n let node = root;\n for (let i = 0; i < 8 && !node._zod.def.shape; i++) {\n const next = node._zod.def.innerType ?? node._zod.def.in;\n if (!next) break;\n node = next;\n }\n if (!node._zod.def.shape) throw new TypeError(\"defineContentType: schema must be a zod object\");\n return node._zod.def.shape;\n}\n","/**\n * navFromContentTypes — the sidebar derives from the registry.\n *\n * Adding a content type to a site (one defineContentType entry) puts it in\n * the nav with no shell change. Pure; lives in /forms so the server layout\n * can compute it without importing the client bundle.\n */\n\nimport type { ContentTypeEntry } from \"./types\";\n\nexport interface NavEntry {\n id: string;\n label: string;\n href: string;\n icon: string;\n}\n\nexport function navFromContentTypes(\n entries: Record<string, ContentTypeEntry> | ContentTypeEntry[],\n opts: { basePath?: string } = {},\n): NavEntry[] {\n const base = (opts.basePath ?? \"/admin\").replace(/\\/+$/, \"\");\n const list = Array.isArray(entries) ? entries : Object.values(entries);\n return list.map((e) => ({ id: e.id, label: e.label, href: `${base}/${e.id}`, icon: e.id }));\n}\n"]}
|
package/dist/forms/index.cjs
CHANGED
|
@@ -137,12 +137,26 @@ function readMeta(schema) {
|
|
|
137
137
|
const s = schema;
|
|
138
138
|
const raw = typeof s.meta === "function" ? s.meta() ?? {} : {};
|
|
139
139
|
const pick = (k) => typeof raw[k] === "string" ? raw[k] : void 0;
|
|
140
|
+
const rec = raw.recommended;
|
|
141
|
+
const recommended = Array.isArray(rec) && rec.length === 2 && rec.every((n) => typeof n === "number") ? [rec[0], rec[1]] : void 0;
|
|
142
|
+
const INPUTS = ["text", "textarea", "date", "number", "boolean", "select", "tags", "image", "url"];
|
|
143
|
+
const input = typeof raw.input === "string" && INPUTS.includes(raw.input) ? raw.input : void 0;
|
|
140
144
|
return {
|
|
141
145
|
label: pick("label"),
|
|
142
146
|
placeholder: pick("placeholder"),
|
|
143
|
-
description: pick("description") ?? (typeof s.description === "string" ? s.description : void 0)
|
|
147
|
+
description: pick("description") ?? (typeof s.description === "string" ? s.description : void 0),
|
|
148
|
+
recommended,
|
|
149
|
+
suffix: pick("suffix"),
|
|
150
|
+
help: pick("help"),
|
|
151
|
+
input
|
|
144
152
|
};
|
|
145
153
|
}
|
|
154
|
+
function inputOverrideFor(name, schema, entry) {
|
|
155
|
+
return entry?.inputs?.[name] ?? readMeta(schema).input;
|
|
156
|
+
}
|
|
157
|
+
function recommendedFor(name, schema, entry) {
|
|
158
|
+
return entry?.recommended?.[name] ?? readMeta(schema).recommended;
|
|
159
|
+
}
|
|
146
160
|
function titlecase(name) {
|
|
147
161
|
const words = name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").toLowerCase().trim();
|
|
148
162
|
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
@@ -156,6 +170,9 @@ function labelFor(name, schema, entry) {
|
|
|
156
170
|
function placeholderFor(name, schema, entry) {
|
|
157
171
|
return entry?.placeholders?.[name] ?? readMeta(schema).placeholder;
|
|
158
172
|
}
|
|
173
|
+
function helpFor(name, schema, entry) {
|
|
174
|
+
return entry?.help?.[name] ?? readMeta(schema).help;
|
|
175
|
+
}
|
|
159
176
|
|
|
160
177
|
// src/forms/walk.ts
|
|
161
178
|
function walkSchema(schema, entry = {}) {
|
|
@@ -170,11 +187,14 @@ function walkSchema(schema, entry = {}) {
|
|
|
170
187
|
return {
|
|
171
188
|
name,
|
|
172
189
|
label: labelFor(name, raw, entry),
|
|
173
|
-
input: role === "image" ? "image" : info.input,
|
|
190
|
+
input: role === "image" ? "image" : inputOverrideFor(name, raw, entry) ?? info.input,
|
|
174
191
|
required,
|
|
175
192
|
constraints: info.constraints,
|
|
176
193
|
messages: info.messages,
|
|
177
194
|
placeholder: placeholderFor(name, raw, entry),
|
|
195
|
+
recommended: recommendedFor(name, raw, entry),
|
|
196
|
+
suffix: readMeta(raw).suffix,
|
|
197
|
+
help: helpFor(name, raw, entry),
|
|
178
198
|
order: 0,
|
|
179
199
|
role,
|
|
180
200
|
options: entry.options?.[name] ?? info.options
|
|
@@ -235,7 +255,14 @@ function defineContentType(entry) {
|
|
|
235
255
|
check(entry.hidden, "hidden");
|
|
236
256
|
check(Object.keys(entry.labels ?? {}), "labels");
|
|
237
257
|
check(Object.keys(entry.placeholders ?? {}), "placeholders");
|
|
258
|
+
check(Object.keys(entry.recommended ?? {}), "recommended");
|
|
259
|
+
check(Object.keys(entry.inputs ?? {}), "inputs");
|
|
260
|
+
check(Object.keys(entry.help ?? {}), "help");
|
|
238
261
|
check(Object.keys(entry.options ?? {}), "options");
|
|
262
|
+
for (const g of entry.groups ?? []) {
|
|
263
|
+
if (typeof g.label !== "string" || g.label.length === 0) throw new TypeError(`${where}: every group needs a label`);
|
|
264
|
+
check(g.fields, `groups["${g.label}"]`);
|
|
265
|
+
}
|
|
239
266
|
return entry;
|
|
240
267
|
}
|
|
241
268
|
function findShape(root) {
|