cursedbelt 5.0.0 → 5.0.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.
Files changed (63) hide show
  1. package/dist/react/emoji/EmojiPicker.d.ts.map +1 -1
  2. package/dist/react/emoji/EmojiPicker.js +49 -8
  3. package/dist/react/emoji/EmojiPicker.js.map +1 -1
  4. package/dist/react/lib/form.d.ts +2 -2
  5. package/dist/react/lib/form.d.ts.map +1 -1
  6. package/dist/react/lib/form.js +4 -41
  7. package/dist/react/lib/form.js.map +1 -1
  8. package/dist/react/lib/zodResolver.d.ts +9 -0
  9. package/dist/react/lib/zodResolver.d.ts.map +1 -0
  10. package/dist/react/lib/zodResolver.js +105 -0
  11. package/dist/react/lib/zodResolver.js.map +1 -0
  12. package/dist/styles-areas/analytics.css +1 -1
  13. package/dist/styles-areas/auth.css +1 -1
  14. package/dist/styles-areas/charts.css +1 -1
  15. package/dist/styles-areas/chat.css +1 -1
  16. package/dist/styles-areas/core.css +1 -1
  17. package/dist/styles-areas/dashboard-grid.css +1 -1
  18. package/dist/styles-areas/data-table.css +1 -1
  19. package/dist/styles-areas/deep-link.css +1 -1
  20. package/dist/styles-areas/emoji.css +1 -1
  21. package/dist/styles-areas/fields.css +1 -1
  22. package/dist/styles-areas/file-tree.css +1 -1
  23. package/dist/styles-areas/keep-awake.css +1 -1
  24. package/dist/styles-areas/layout-engine.css +1 -1
  25. package/dist/styles-areas/markdown.css +1 -1
  26. package/dist/styles-areas/media-gallery.css +1 -1
  27. package/dist/styles-areas/media.css +1 -1
  28. package/dist/styles-areas/nav.css +1 -1
  29. package/dist/styles-areas/overlays.css +1 -1
  30. package/dist/styles-areas/palette.css +1 -1
  31. package/dist/styles-areas/stats.css +1 -1
  32. package/dist/styles-areas/virtual.css +1 -1
  33. package/dist/styles-areas/wizard.css +1 -1
  34. package/dist/styles-areas/workbench.css +1 -1
  35. package/package.json +16 -5
  36. package/src/react/emoji/EmojiPicker.tsx +70 -19
  37. package/src/react/lib/form.ts +5 -48
  38. package/src/react/lib/zodResolver.spec.ts +82 -0
  39. package/src/react/lib/zodResolver.ts +136 -0
  40. package/src/styles-areas/analytics.css +1 -1
  41. package/src/styles-areas/auth.css +1 -1
  42. package/src/styles-areas/charts.css +1 -1
  43. package/src/styles-areas/chat.css +1 -1
  44. package/src/styles-areas/core.css +1 -1
  45. package/src/styles-areas/dashboard-grid.css +1 -1
  46. package/src/styles-areas/data-table.css +1 -1
  47. package/src/styles-areas/deep-link.css +1 -1
  48. package/src/styles-areas/emoji.css +1 -1
  49. package/src/styles-areas/fields.css +1 -1
  50. package/src/styles-areas/file-tree.css +1 -1
  51. package/src/styles-areas/keep-awake.css +1 -1
  52. package/src/styles-areas/layout-engine.css +1 -1
  53. package/src/styles-areas/markdown.css +1 -1
  54. package/src/styles-areas/media-gallery.css +1 -1
  55. package/src/styles-areas/media.css +1 -1
  56. package/src/styles-areas/nav.css +1 -1
  57. package/src/styles-areas/overlays.css +1 -1
  58. package/src/styles-areas/palette.css +1 -1
  59. package/src/styles-areas/stats.css +1 -1
  60. package/src/styles-areas/virtual.css +1 -1
  61. package/src/styles-areas/wizard.css +1 -1
  62. package/src/styles-areas/workbench.css +1 -1
  63. package/src/unpeeredStaysOffTheBarrel.spec.ts +99 -0
@@ -1 +1 @@
1
- {"version":3,"file":"EmojiPicker.d.ts","sourceRoot":"","sources":["../../../src/react/emoji/EmojiPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAkBhE,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5C,gFAAgF;IAChF,GAAG,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;IAC7D;8EAC0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mFAAmF;IACnF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAyCD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAO,EACP,KAAc,EACd,MAAa,EACb,eAAwB,EACxB,GAAc,EACd,MAAc,EACd,OAAO,EACP,IAAI,EACJ,YAAY,GACb,EAAE,gBAAgB,+BA4BlB"}
1
+ {"version":3,"file":"EmojiPicker.d.ts","sourceRoot":"","sources":["../../../src/react/emoji/EmojiPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAC;AAuE7E,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC5C,gFAAgF;IAChF,GAAG,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;IAC7D;8EAC0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mFAAmF;IACnF,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAO,EACP,KAAc,EACd,MAAa,EACb,eAAwB,EACxB,GAAc,EACd,MAAc,EACd,OAAO,EACP,IAAI,EACJ,YAAY,GACb,EAAE,gBAAgB,+BA4BlB"}
@@ -1,18 +1,59 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { lazy, Suspense, useMemo } from 'react';
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { IconButton } from '../components/IconButton.js';
4
4
  import { Popover } from '../components/Popover.js';
5
5
  import { Skeleton } from '../components/Skeleton.js';
6
6
  import { resolveEmojiTheme } from './emojiSearch.js';
7
- // The emoji-mart React picker + its data are BOTH lazy: the component code-splits
8
- // (only loaded when the panel first mounts) and the ~300 KB data is fetched via the
9
- // async `data` loader (never statically imported — that would tax every page).
10
- const Picker = lazy(() => import('@emoji-mart/react'));
7
+ // The emoji-mart engine and its ~300 KB data are BOTH lazy: nothing loads until the panel
8
+ // first mounts, and the data is fetched through emoji-mart's async `data` loader.
11
9
  const loadEmojiData = () => import('@emoji-mart/data').then((m) => m.default);
12
- /** The emoji-mart grid itself, themed + lazy, behind a Suspense skeleton. */
10
+ /**
11
+ * 🔴 emoji-mart's `Picker` custom element, mounted directly — NOT through `@emoji-mart/react`
12
+ * (cursedbelt 5.0.1). That wrapper is twenty lines (`new Picker({ ...props, ref })` into a div),
13
+ * and depending on it cost every consumer something either way: as an optional peer it made
14
+ * `npm install cursedbelt` fail ERESOLVE (it peers `react <=18`; task 2087), and as `unpeered`
15
+ * (5.0.0) a literal `import('@emoji-mart/react')` broke every clean-install `vite build` that
16
+ * imports `cursedbelt/react`, because Vite stubs a missing import only for a DECLARED optional
17
+ * peer. `emoji-mart` itself IS a declared optional peer, so a consumer that never renders this
18
+ * builds green with it absent, and one that does gets a named error rather than a blank panel.
19
+ */
20
+ function EmojiMartPanel(props) {
21
+ const host = useRef(null);
22
+ const picker = useRef(null);
23
+ const latest = useRef(props);
24
+ latest.current = props;
25
+ const [ready, setReady] = useState(false);
26
+ const [failed, setFailed] = useState(null);
27
+ useEffect(() => {
28
+ let live = true;
29
+ import('emoji-mart').then(({ Picker }) => {
30
+ if (!live || !host.current)
31
+ return;
32
+ picker.current = new Picker({ ...latest.current, ref: host });
33
+ setReady(true);
34
+ }, (cause) => {
35
+ if (live) {
36
+ setFailed(new Error("cursedbelt: EmojiPicker needs the optional peer 'emoji-mart' (and '@emoji-mart/data') — run `bun add emoji-mart @emoji-mart/data` in the app that renders it.", { cause }));
37
+ }
38
+ });
39
+ return () => {
40
+ live = false;
41
+ picker.current = null;
42
+ host.current?.replaceChildren();
43
+ };
44
+ }, []);
45
+ // The wrapper's contract: every render pushes the current props into the live element.
46
+ useEffect(() => {
47
+ picker.current?.update?.(props);
48
+ });
49
+ if (failed)
50
+ throw failed;
51
+ return (_jsxs(_Fragment, { children: [!ready && _jsx(Skeleton, { className: 'h-[420px] w-[352px]' }), _jsx("div", { ref: host })] }));
52
+ }
53
+ /** The emoji-mart grid itself, themed + lazy, behind a skeleton until the engine has loaded. */
13
54
  function EmojiPanel({ onSelect, theme = 'auto', locale = 'en', previewPosition = 'none', set = 'native', }) {
14
55
  const resolvedTheme = useMemo(() => resolveEmojiTheme(theme), [theme]);
15
- return (_jsx(Suspense, { fallback: _jsx(Skeleton, { className: 'h-[420px] w-[352px]' }), children: _jsx(Picker, { data: loadEmojiData, onEmojiSelect: (e) => onSelect(e.native), theme: resolvedTheme, locale: locale, previewPosition: previewPosition, set: set, navPosition: 'top', skinTonePosition: 'search', dynamicWidth: false }) }));
56
+ return (_jsx(EmojiMartPanel, { data: loadEmojiData, onEmojiSelect: (e) => onSelect(e.native), theme: resolvedTheme, locale: locale, previewPosition: previewPosition, set: set, navPosition: 'top', skinTonePosition: 'search', dynamicWidth: false }));
16
57
  }
17
58
  /** A neutral default trigger when none is supplied. */
18
59
  function DefaultTrigger() {
@@ -1 +1 @@
1
- {"version":3,"file":"EmojiPicker.js","sourceRoot":"","sources":["../../../src/react/emoji/EmojiPicker.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAkB,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,kFAAkF;AAClF,oFAAoF;AACpF,+EAA+E;AAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC;AACvD,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AA6B9E,6EAA6E;AAC7E,SAAS,UAAU,CAAC,EAClB,QAAQ,EACR,KAAK,GAAG,MAAM,EACd,MAAM,GAAG,IAAI,EACb,eAAe,GAAG,MAAM,EACxB,GAAG,GAAG,QAAQ,GACsE;IACpF,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACvE,OAAO,CACL,KAAC,QAAQ,IAAC,QAAQ,EAAE,KAAC,QAAQ,IAAC,SAAS,EAAC,qBAAqB,GAAG,YAC9D,KAAC,MAAM,IACL,IAAI,EAAE,aAAa,EACnB,aAAa,EAAE,CAAC,CAAuB,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAC9D,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,EAChC,GAAG,EAAE,GAAG,EACR,WAAW,EAAC,KAAK,EACjB,gBAAgB,EAAC,QAAQ,EACzB,YAAY,EAAE,KAAK,GACnB,GACO,CACZ,CAAC;AACJ,CAAC;AAED,uDAAuD;AACvD,SAAS,cAAc;IACrB,OAAO,CACL,KAAC,UAAU,IACT,KAAK,EAAC,eAAe,EACrB,OAAO,EAAC,WAAW,EACnB,SAAS,EAAC,uIAAuI,YAEjJ,+DAA2B,GAChB,CACd,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAO,EACP,KAAK,GAAG,MAAM,EACd,MAAM,GAAG,IAAI,EACb,eAAe,GAAG,MAAM,EACxB,GAAG,GAAG,QAAQ,EACd,MAAM,GAAG,KAAK,EACd,OAAO,EACP,IAAI,EACJ,YAAY,GACK;IACjB,MAAM,KAAK,GAAG,CACZ,KAAC,UAAU,IACT,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,eAAe,EAChC,GAAG,EAAE,GAAG,GACR,CACH,CAAC;IAEF,IAAI,MAAM;QAAE,OAAO,KAAK,CAAC;IAEzB,OAAO,CACL,KAAC,OAAO,IACN,OAAO,EAAE,OAAO,IAAI,KAAC,cAAc,KAAG,EACtC,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;YAClB,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,EAAE,CAAC;QACtB,CAAC,EACD,KAAK,EAAE,KAAK;QACZ,+EAA+E;QAC/E,SAAS,EAAC,KAAK,YAEd,KAAK,GACE,CACX,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"EmojiPicker.js","sourceRoot":"","sources":["../../../src/react/emoji/EmojiPicker.tsx"],"names":[],"mappings":"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"}
@@ -21,8 +21,8 @@ import type { z } from 'zod';
21
21
  * const form = useForm<Values>(makeFormConfig(schema, { name: '', tags: [] }));
22
22
  * ```
23
23
  *
24
- * 🔴 Needs the optional peer `@hookform/resolvers` installed in the app — RHF resolvers
25
- * are already async, so the load happens on the first validation rather than at import.
24
+ * The resolver is this package's own (`./zodResolver.ts`, 5.0.1) — there is nothing for the
25
+ * app to install, and nothing for a bundler to fail to resolve.
26
26
  */
27
27
  export declare function makeFormConfig<TFieldValues extends FieldValues>(schema: z.ZodType, defaults: TFieldValues): UseFormProps<TFieldValues>;
28
28
  //# sourceMappingURL=form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/react/lib/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,WAAW,EAAY,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiC7B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,YAAY,SAAS,WAAW,EAC7D,MAAM,EAAE,CAAC,CAAC,OAAO,EACjB,QAAQ,EAAE,YAAY,GACrB,YAAY,CAAC,YAAY,CAAC,CAsB5B"}
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../../../src/react/lib/form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,YAAY,SAAS,WAAW,EAC7D,MAAM,EAAE,CAAC,CAAC,OAAO,EACjB,QAAQ,EAAE,YAAY,GACrB,YAAY,CAAC,YAAY,CAAC,CAS5B"}
@@ -1,30 +1,4 @@
1
- /**
2
- * 🔴 `@hookform/resolvers` is an OPTIONAL peer, and this dynamic import is what makes it
3
- * one (task 149). `cursedbelt/react` is the barrel all eight apps import; a static
4
- * `import { zodResolver } from '@hookform/resolvers/zod'` at the top of this file put the
5
- * package — and its own dependency tree — into every one of those installs, to serve the
6
- * one function below. `src/barrelsReachNoOptionalPeer.spec.ts` is the check that keeps it
7
- * out, and a `await import(...)` inside the function that needs it is the shape that spec
8
- * blesses.
9
- *
10
- * Resolved once per process and memoized: RHF calls the resolver on every validation
11
- * pass, and `zodResolver(schema)` is cheap but the module load is not.
12
- */
13
- let zodResolverModule;
14
- const loadZodResolver = async () => {
15
- zodResolverModule ??= import('@hookform/resolvers/zod');
16
- try {
17
- return await zodResolverModule;
18
- }
19
- catch (cause) {
20
- // 🔴 Loud and actionable, not an unhandled rejection three frames into RHF. A missing
21
- // optional peer surfaces here as "the form never validates", which is the worst
22
- // possible thing to debug without the package name in the message.
23
- zodResolverModule = undefined;
24
- throw new Error("cursedbelt: makeFormConfig() needs the optional peer '@hookform/resolvers' — " +
25
- 'run `bun add @hookform/resolvers` in the app that renders this form.', { cause });
26
- }
27
- };
1
+ import { zodResolver } from './zodResolver.js';
28
2
  /**
29
3
  * The canonical react-hook-form config for every cursedbelt form (Wizard,
30
4
  * RecordPanel, modal forms). One zod schema drives validation; the validation mode
@@ -46,22 +20,11 @@ const loadZodResolver = async () => {
46
20
  * const form = useForm<Values>(makeFormConfig(schema, { name: '', tags: [] }));
47
21
  * ```
48
22
  *
49
- * 🔴 Needs the optional peer `@hookform/resolvers` installed in the app — RHF resolvers
50
- * are already async, so the load happens on the first validation rather than at import.
23
+ * The resolver is this package's own (`./zodResolver.ts`, 5.0.1) — there is nothing for the
24
+ * app to install, and nothing for a bundler to fail to resolve.
51
25
  */
52
26
  export function makeFormConfig(schema, defaults) {
53
- // Built once per form, then reused across every validation pass.
54
- let resolved;
55
- const resolver = async (values, context, options) => {
56
- if (!resolved) {
57
- const { zodResolver } = await loadZodResolver();
58
- // zodResolver's generics don't line up with the caller's value type (the schema
59
- // input/output may differ from TFieldValues); the runtime resolver is correct, so
60
- // cast through the overload's param/return types rather than over-genericize.
61
- resolved = zodResolver(schema);
62
- }
63
- return resolved(values, context, options);
64
- };
27
+ const resolver = zodResolver(schema);
65
28
  return {
66
29
  resolver,
67
30
  defaultValues: defaults,
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sourceRoot":"","sources":["../../../src/react/lib/form.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,IAAI,iBAAgF,CAAC;AAErF,MAAM,eAAe,GAAG,KAAK,IAAuD,EAAE;IACpF,iBAAiB,KAAK,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,sFAAsF;QACtF,gFAAgF;QAChF,mEAAmE;QACnE,iBAAiB,GAAG,SAAS,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,+EAA+E;YAC7E,sEAAsE,EACxE,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAiB,EACjB,QAAsB;IAEtB,iEAAiE;IACjE,IAAI,QAA4C,CAAC;IACjD,MAAM,QAAQ,GAA2B,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAC1E,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,eAAe,EAAE,CAAC;YAChD,gFAAgF;YAChF,kFAAkF;YAClF,8EAA8E;YAC9E,QAAQ,GAAG,WAAW,CACpB,MAA2C,CACP,CAAC;QACzC,CAAC;QACD,OAAO,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,OAAO;QACL,QAAQ;QACR,aAAa,EAAE,QAAuC;QACtD,IAAI,EAAE,QAAQ;QACd,cAAc,EAAE,UAAU;KAC3B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../../../src/react/lib/form.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAiB,EACjB,QAAsB;IAEtB,MAAM,QAAQ,GAAG,WAAW,CAAe,MAAM,CAAC,CAAC;IAEnD,OAAO;QACL,QAAQ;QACR,aAAa,EAAE,QAAuC;QACtD,IAAI,EAAE,QAAQ;QACd,cAAc,EAAE,UAAU;KAC3B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type FieldValues, type Resolver } from 'react-hook-form';
2
+ import type { z } from 'zod';
3
+ /**
4
+ * A react-hook-form {@link Resolver} for a zod 4 schema: `parseAsync`, parsed output as the
5
+ * form's values on success, react-hook-form's nested error shape on a `ZodError`. Anything
6
+ * else a schema throws is not a validation result and is rethrown.
7
+ */
8
+ export declare function zodResolver<TFieldValues extends FieldValues>(schema: z.ZodType): Resolver<TFieldValues>;
9
+ //# sourceMappingURL=zodResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zodResolver.d.ts","sourceRoot":"","sources":["../../../src/react/lib/zodResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmD,KAAK,WAAW,EAAO,KAAK,QAAQ,EAA6B,MAAM,iBAAiB,CAAC;AACnJ,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmH7B;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,YAAY,SAAS,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAcvG"}
@@ -0,0 +1,105 @@
1
+ import { appendErrors, get, set } from 'react-hook-form';
2
+ /** zod 4 marks its errors with a trait, not a prototype chain a bundler could duplicate. */
3
+ function isZodError(error) {
4
+ return !!error?._zod?.traits?.has('$ZodError');
5
+ }
6
+ function parseIssues(input, validateAllFieldCriteria) {
7
+ const issues = [...input];
8
+ // A null prototype, so a field named `toString` or `constructor` is not already "set".
9
+ const errors = Object.create(null);
10
+ while (issues.length > 0) {
11
+ const issue = issues[0];
12
+ const { code, message, path } = issue;
13
+ const key = path.join('.');
14
+ if (!errors[key]) {
15
+ if (issue.code === 'invalid_union' && issue.errors.length > 0) {
16
+ // The branch that came CLOSEST to matching speaks for the union, not the first one.
17
+ const closest = issue.errors.reduce((best, branch) => (branch.length < best.length ? branch : best));
18
+ const first = closest[0];
19
+ errors[key] = { message: first?.message ?? message, type: first?.code ?? code };
20
+ }
21
+ else {
22
+ errors[key] = { message, type: code };
23
+ }
24
+ }
25
+ if (issue.code === 'invalid_union') {
26
+ for (const branch of issue.errors)
27
+ for (const nested of branch)
28
+ issues.push({ ...nested, path: [...issue.path, ...nested.path] });
29
+ }
30
+ if (validateAllFieldCriteria) {
31
+ const types = errors[key].types;
32
+ const messages = types?.[issue.code];
33
+ errors[key] = appendErrors(key, validateAllFieldCriteria, errors, code, messages ? [].concat(messages, issue.message) : issue.message);
34
+ }
35
+ issues.shift();
36
+ }
37
+ return errors;
38
+ }
39
+ function reportNative(ref, name, errors) {
40
+ const el = ref;
41
+ if (el && typeof el.reportValidity === 'function' && typeof el.setCustomValidity === 'function') {
42
+ const error = get(errors, name);
43
+ el.setCustomValidity(error?.message || '');
44
+ el.reportValidity();
45
+ }
46
+ }
47
+ function validateFieldsNatively(errors, fields) {
48
+ for (const name in fields) {
49
+ const field = fields[name];
50
+ if (field?.ref && typeof field.ref.reportValidity === 'function')
51
+ reportNative(field.ref, name, errors);
52
+ else
53
+ for (const ref of field?.refs ?? [])
54
+ reportNative(ref, name, errors);
55
+ }
56
+ }
57
+ /** `a[0].b` and `a.0.b` are one path. */
58
+ const dotted = (name) => name.replace(/\[(\d+)]/g, '.$1').replace(/[[\]]/g, '');
59
+ /** Is `name` the ROOT of a field array — some registered name is `name.<index>…`? */
60
+ function isFieldArrayRoot(names, name) {
61
+ const escaped = dotted(name).replace(/[.*+?^${}()|\\]/g, '\\$&');
62
+ return names.some((n) => new RegExp(`^${escaped}\\.\\d+`).test(dotted(n)));
63
+ }
64
+ function toNestErrors(flat, options) {
65
+ if (options.shouldUseNativeValidation)
66
+ validateFieldsNatively(flat, options.fields);
67
+ const nested = {};
68
+ for (const path in flat) {
69
+ const field = get(options.fields, path);
70
+ const error = Object.assign(flat[path] || {}, { ref: field?.refs ? field.refs[0] : field?.ref });
71
+ if (isFieldArrayRoot(options.names ?? Object.keys(flat), path)) {
72
+ const existing = Object.assign({}, get(nested, path));
73
+ set(existing, 'root', error);
74
+ set(nested, path, existing);
75
+ }
76
+ else {
77
+ set(nested, path, error);
78
+ }
79
+ }
80
+ return nested;
81
+ }
82
+ /**
83
+ * A react-hook-form {@link Resolver} for a zod 4 schema: `parseAsync`, parsed output as the
84
+ * form's values on success, react-hook-form's nested error shape on a `ZodError`. Anything
85
+ * else a schema throws is not a validation result and is rethrown.
86
+ */
87
+ export function zodResolver(schema) {
88
+ return async (values, _context, options) => {
89
+ try {
90
+ const data = await schema.parseAsync(values);
91
+ if (options.shouldUseNativeValidation)
92
+ validateFieldsNatively({}, options.fields);
93
+ return { errors: {}, values: data };
94
+ }
95
+ catch (error) {
96
+ if (!isZodError(error))
97
+ throw error;
98
+ return {
99
+ values: {},
100
+ errors: toNestErrors(parseIssues(error.issues, !options.shouldUseNativeValidation && options.criteriaMode === 'all'), options),
101
+ };
102
+ }
103
+ };
104
+ }
105
+ //# sourceMappingURL=zodResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zodResolver.js","sourceRoot":"","sources":["../../../src/react/lib/zodResolver.ts"],"names":[],"mappings":"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"}
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 1312 candidate(s) scanned.
18
+ * when this file is stale. 1317 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 303 candidate(s) scanned.
18
+ * when this file is stale. 302 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 462 candidate(s) scanned.
18
+ * when this file is stale. 464 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 388 candidate(s) scanned.
18
+ * when this file is stale. 390 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
15
15
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
16
- * when this file is stale. 5197 candidate(s) scanned.
16
+ * when this file is stale. 5214 candidate(s) scanned.
17
17
  *
18
18
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
19
19
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 208 candidate(s) scanned.
18
+ * when this file is stale. 209 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 1350 candidate(s) scanned.
18
+ * when this file is stale. 1355 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 188 candidate(s) scanned.
18
+ * when this file is stale. 190 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 100 candidate(s) scanned.
18
+ * when this file is stale. 103 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 616 candidate(s) scanned.
18
+ * when this file is stale. 619 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 574 candidate(s) scanned.
18
+ * when this file is stale. 573 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 154 candidate(s) scanned.
18
+ * when this file is stale. 155 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 243 candidate(s) scanned.
18
+ * when this file is stale. 245 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 110 candidate(s) scanned.
18
+ * when this file is stale. 112 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2159 candidate(s) scanned.
18
+ * when this file is stale. 2157 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 2777 candidate(s) scanned.
18
+ * when this file is stale. 2775 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 799 candidate(s) scanned.
18
+ * when this file is stale. 801 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 117 candidate(s) scanned.
18
+ * when this file is stale. 119 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 212 candidate(s) scanned.
18
+ * when this file is stale. 213 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 360 candidate(s) scanned.
18
+ * when this file is stale. 361 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 161 candidate(s) scanned.
18
+ * when this file is stale. 160 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 392 candidate(s) scanned.
18
+ * when this file is stale. 395 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -15,7 +15,7 @@
15
15
  *
16
16
  * An app that imports every area gets exactly what `cursedbelt/styles-utilities.css`
17
17
  * emits — proved rule by rule in src/stylesAreas.spec.ts, which is also what fails
18
- * when this file is stale. 770 candidate(s) scanned.
18
+ * when this file is stale. 776 candidate(s) scanned.
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "license": "ISC",
5
5
  "type": "module",
6
6
  "description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
@@ -40,12 +40,24 @@
40
40
  ]
41
41
  },
42
42
  "unpeered": {
43
- "why": "Packages some subpaths import that are deliberately NOT in peerDependencies, because npm cannot resolve them beside this package's own peers: npm checks an optional peer's OWN peer ranges even when nobody installs it, so `npm install cursedbelt` failed ERESOLVE (task 2087, measured on 4.7.0 and on packed probes). @glideapps/glide-data-grid@6 peers react <=18 and marked ^4 (this package: react ^19, marked >=14); @emoji-mart/react@1 peers react <=18; @hookform/resolvers@5 dragged zod 3 against zod ^4. lodash is glide's own peer, which glide does not declare as a dependency. An app that renders ./react/spreadsheet, ./react/workbook-viewer or ./react/media-gallery installs glide + lodash itself; EmojiPicker and makeFormConfig load theirs lazily and name the package when it is missing. Bun installs these without complaint; npm needs --legacy-peer-deps for them, which is the truth about those packages rather than about this one.",
43
+ "why": "Packages some subpaths import that are deliberately NOT in peerDependencies, because npm cannot resolve them beside this package's own peers: npm checks an optional peer's OWN peer ranges even when nobody installs it, so `npm install cursedbelt` failed ERESOLVE (task 2087, measured on 4.7.0 and on packed probes). @glideapps/glide-data-grid@6 peers react <=18 and marked ^4 (this package: react ^19, marked >=14). lodash is glide's own peer, which glide does not declare as a dependency. An app that renders ./react/spreadsheet, ./react/workbook-viewer or ./react/media-gallery installs glide + lodash itself. 🔴 Nothing the cursedbelt/react barrel reaches may import an unpeered package: Vite stubs only DECLARED optional peers, so 5.0.0 — which listed @emoji-mart/react and @hookform/resolvers here while EmojiPicker and makeFormConfig imported them — failed every consumer's clean-install vite build. 5.0.1 mounts emoji-mart's Picker directly and owns its zod resolver; src/unpeeredStaysOffTheBarrel.spec.ts is the check.",
44
44
  "packages": {
45
- "@emoji-mart/react": ">=1",
46
45
  "@glideapps/glide-data-grid": ">=6",
47
- "@hookform/resolvers": ">=5",
48
46
  "lodash": ">=4.17.19"
47
+ },
48
+ "subpaths": {
49
+ "./react/spreadsheet": [
50
+ "@glideapps/glide-data-grid",
51
+ "lodash"
52
+ ],
53
+ "./react/workbook-viewer": [
54
+ "@glideapps/glide-data-grid",
55
+ "lodash"
56
+ ],
57
+ "./react/media-gallery": [
58
+ "@glideapps/glide-data-grid",
59
+ "lodash"
60
+ ]
49
61
  }
50
62
  },
51
63
  "scripts": {
@@ -629,7 +641,6 @@
629
641
  "@codemirror/state": "^6.7.0",
630
642
  "@codemirror/view": "^6.43.4",
631
643
  "@emoji-mart/data": "^1.2.1",
632
- "@emoji-mart/react": "^1.1.1",
633
644
  "@ffmpeg/ffmpeg": "^0.12.15",
634
645
  "@ffmpeg/util": "^0.12.2",
635
646
  "@git-diff-view/react": "^0.1.6",