gridsmith-ui 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/chat.js +3 -3
  2. package/dist/chunk-2RV23OBK.js +1349 -0
  3. package/dist/chunk-2RV23OBK.js.map +1 -0
  4. package/dist/chunk-7TOJ4G7S.js +197 -0
  5. package/dist/chunk-7TOJ4G7S.js.map +1 -0
  6. package/dist/{chunk-6MXHGH3D.js → chunk-AAYCQXZQ.js} +90 -161
  7. package/dist/chunk-AAYCQXZQ.js.map +1 -0
  8. package/dist/{chunk-ILIODA7W.js → chunk-CXMV7SXJ.js} +4 -3
  9. package/dist/chunk-CXMV7SXJ.js.map +1 -0
  10. package/dist/{chunk-EQDR57AM.js → chunk-EYMGLK4M.js} +3 -3
  11. package/dist/{chunk-EQDR57AM.js.map → chunk-EYMGLK4M.js.map} +1 -1
  12. package/dist/chunk-IVCVNAXG.js +115 -0
  13. package/dist/chunk-IVCVNAXG.js.map +1 -0
  14. package/dist/chunk-RG4KUCRS.js +9 -0
  15. package/dist/chunk-RG4KUCRS.js.map +1 -0
  16. package/dist/{chunk-JXANCXK6.js → chunk-RT7RYGC3.js} +39 -4
  17. package/dist/chunk-RT7RYGC3.js.map +1 -0
  18. package/dist/{chunk-XYDIBW3J.js → chunk-SBTBMAIU.js} +4 -3
  19. package/dist/chunk-SBTBMAIU.js.map +1 -0
  20. package/dist/data-grid.d.ts +38 -4
  21. package/dist/data-grid.js +304 -264
  22. package/dist/data-grid.js.map +1 -1
  23. package/dist/editor.d.ts +6 -5
  24. package/dist/editor.js +47 -11
  25. package/dist/editor.js.map +1 -1
  26. package/dist/index.d.ts +120 -153
  27. package/dist/index.js +1156 -1814
  28. package/dist/index.js.map +1 -1
  29. package/dist/kanban.js +2 -2
  30. package/dist/resizable.js +9 -8
  31. package/dist/resizable.js.map +1 -1
  32. package/dist/roots.css +10 -0
  33. package/dist/{table-utils-GounRE6s.d.ts → table-utils-BkjNEWts.d.ts} +5 -1
  34. package/dist/use-pagination-DiJo0aW5.d.ts +153 -0
  35. package/dist/virtualized.d.ts +11 -1
  36. package/dist/virtualized.js +67 -18
  37. package/dist/virtualized.js.map +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-6MXHGH3D.js.map +0 -1
  40. package/dist/chunk-ILIODA7W.js.map +0 -1
  41. package/dist/chunk-JN37OVTP.js +0 -67
  42. package/dist/chunk-JN37OVTP.js.map +0 -1
  43. package/dist/chunk-JXANCXK6.js.map +0 -1
  44. package/dist/chunk-TKVTZWBN.js +0 -50
  45. package/dist/chunk-TKVTZWBN.js.map +0 -1
  46. package/dist/chunk-XVB55M3N.js +0 -42
  47. package/dist/chunk-XVB55M3N.js.map +0 -1
  48. package/dist/chunk-XYDIBW3J.js.map +0 -1
@@ -1,50 +0,0 @@
1
- import { createContext, useMemo, useContext } from 'react';
2
-
3
- // ../../showcase/src/lib/preferences.ts
4
- var PreferencesContext = createContext(null);
5
- var HOUSE_DEFAULTS = {
6
- validationTiming: "onBlur",
7
- formActions: { align: "end", placement: "auto" },
8
- itemsPerPage: 25,
9
- paginationStyle: "pagination",
10
- tableToCardsBreakpoint: "md",
11
- emptyStyle: "illustration-cta",
12
- loadingStyle: "skeleton",
13
- destructiveMode: "dialog",
14
- highSeverityActions: ["delete_account", "remove_team_member"],
15
- typeToConfirmActions: ["delete_account"],
16
- undoWindowSeconds: 5
17
- };
18
- var PREFERENCE_HOUSE_DEFAULTS = Object.freeze(HOUSE_DEFAULTS);
19
- function usePreferences() {
20
- const raw = useShellPreferences();
21
- return useMemo(() => resolvePreferences(raw), [raw]);
22
- }
23
- function resolvePreferences(raw) {
24
- const d = PREFERENCE_HOUSE_DEFAULTS;
25
- const out = { ...d, formActions: { ...d.formActions }, highSeverityActions: [...d.highSeverityActions], typeToConfirmActions: [...d.typeToConfirmActions] };
26
- for (const [key, value] of Object.entries(raw)) {
27
- if (value === void 0) continue;
28
- if (key === "formActions") {
29
- const actions = value;
30
- if (actions?.align !== void 0) out.formActions.align = actions.align;
31
- if (actions?.placement !== void 0) out.formActions.placement = actions.placement;
32
- continue;
33
- }
34
- out[key] = value;
35
- }
36
- return out;
37
- }
38
- function useShellPreferences() {
39
- return useContext(PreferencesContext) ?? EMPTY;
40
- }
41
- var EMPTY = Object.freeze({});
42
- function preferenceActionKey(label) {
43
- return label.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
44
- }
45
- var SplitPaneCtx = createContext(false);
46
- var TableCardCtx = createContext(false);
47
-
48
- export { PREFERENCE_HOUSE_DEFAULTS, PreferencesContext, SplitPaneCtx, TableCardCtx, preferenceActionKey, usePreferences, useShellPreferences };
49
- //# sourceMappingURL=chunk-TKVTZWBN.js.map
50
- //# sourceMappingURL=chunk-TKVTZWBN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/preferences.ts","../../../showcase/src/lib/surface-context.ts"],"names":["createContext"],"mappings":";;;AA8CO,IAAM,kBAAA,GAAqB,cAA0C,IAAI;AAqBhF,IAAM,cAAA,GAAsC;AAAA,EAC1C,gBAAA,EAAkB,QAAA;AAAA,EAClB,WAAA,EAAa,EAAE,KAAA,EAAO,KAAA,EAAO,WAAW,MAAA,EAAO;AAAA,EAC/C,YAAA,EAAc,EAAA;AAAA,EACd,eAAA,EAAiB,YAAA;AAAA,EACjB,sBAAA,EAAwB,IAAA;AAAA,EACxB,UAAA,EAAY,kBAAA;AAAA,EACZ,YAAA,EAAc,UAAA;AAAA,EACd,eAAA,EAAiB,QAAA;AAAA,EACjB,mBAAA,EAAqB,CAAC,gBAAA,EAAkB,oBAAoB,CAAA;AAAA,EAC5D,oBAAA,EAAsB,CAAC,gBAAgB,CAAA;AAAA,EACvC,iBAAA,EAAmB;AACrB,CAAA;AACO,IAAM,yBAAA,GAA2D,MAAA,CAAO,MAAA,CAAO,cAAc;AAQ7F,SAAS,cAAA,GAAsC;AACpD,EAAA,MAAM,MAAM,mBAAA,EAAoB;AAChC,EAAA,OAAO,QAAQ,MAAM,kBAAA,CAAmB,GAAG,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AACrD;AAGO,SAAS,mBAAmB,GAAA,EAA+C;AAChF,EAAA,MAAM,CAAA,GAAI,yBAAA;AACV,EAAA,MAAM,GAAA,GAA2B,EAAE,GAAG,CAAA,EAAG,aAAa,EAAE,GAAG,EAAE,WAAA,EAAY,EAAG,qBAAqB,CAAC,GAAG,EAAE,mBAAmB,CAAA,EAAG,sBAAsB,CAAC,GAAG,CAAA,CAAE,oBAAoB,CAAA,EAAE;AAC/K,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAkD;AAC7F,IAAA,IAAI,UAAU,MAAA,EAAW;AACzB,IAAA,IAAI,QAAQ,aAAA,EAAe;AACzB,MAAA,MAAM,OAAA,GAAU,KAAA;AAChB,MAAA,IAAI,SAAS,KAAA,KAAU,MAAA,EAAW,GAAA,CAAI,WAAA,CAAY,QAAQ,OAAA,CAAQ,KAAA;AAClE,MAAA,IAAI,SAAS,SAAA,KAAc,MAAA,EAAW,GAAA,CAAI,WAAA,CAAY,YAAY,OAAA,CAAQ,SAAA;AAC1E,MAAA;AAAA,IACF;AACA,IAAC,GAAA,CAA2C,GAAG,CAAA,GAAI,KAAA;AAAA,EACrD;AACA,EAAA,OAAO,GAAA;AACT;AAMO,SAAS,mBAAA,GAA2C;AACzD,EAAA,OAAO,UAAA,CAAW,kBAAkB,CAAA,IAAK,KAAA;AAC3C;AAEA,IAAM,KAAA,GAA6B,MAAA,CAAO,MAAA,CAAO,EAAE,CAAA;AAM5C,SAAS,oBAAoB,KAAA,EAAuB;AACzD,EAAA,OAAO,KAAA,CAAM,IAAA,EAAK,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,aAAA,EAAe,GAAG,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AACpF;ACxHO,IAAM,YAAA,GAAeA,cAAc,KAAK;AAOxC,IAAM,YAAA,GAAeA,cAAc,KAAK","file":"chunk-TKVTZWBN.js","sourcesContent":["/**\n * The customer's UX preferences, carried once by AppShell the way the theme is (Sprint 25.6 B9).\n *\n * The generated shell passes the object the template emits from the profile's rules; the builder preview passes the\n * same values from the theme state. Components default from it when no prop is passed — FormWrapper's validation mode\n * and actions alignment, Table and DataGrid's mobile breakpoint, Pagination's page size, EmptyState's style, and the\n * destructive-action helper's mode, lists and undo window — so a page gets the customer's value by doing nothing. A\n * prop always wins; a component outside any shell keeps the default it always had (components read\n * `useShellPreferences`). App code reads `usePreferences`, which fills every field (round 21); a paged list reads its\n * page size through `usePagination`.\n */\nimport { createContext, useContext, useMemo } from \"react\";\n\nexport type PreferenceValidationTiming = \"onBlur\" | \"onSubmit\" | \"onChange\";\nexport type PreferenceBreakpoint = \"sm\" | \"md\" | \"lg\";\nexport type PreferenceEmptyStyle = \"illustration-cta\" | \"text-cta\" | \"redirect\";\nexport type PreferenceLoadingStyle = \"skeleton\" | \"spinner\" | \"progress-bar\";\nexport type PreferenceDestructiveMode = \"dialog\" | \"undo\";\n/** dataDisplay.paginationStyle — how a long list shows more: page numbers, a Load more button, or loading as the user scrolls. */\nexport type PreferencePaginationStyle = \"pagination\" | \"load-more\" | \"infinite-scroll\";\n\nexport interface AppShellPreferences {\n /** forms.validationTiming — when a field first shows its error. */\n validationTiming?: PreferenceValidationTiming;\n /** forms.actions — where a form's buttons sit and how they align. */\n formActions?: { align?: \"start\" | \"end\"; placement?: \"auto\" | \"inline\" };\n /** dataDisplay.itemsPerPage — the page size of a paged or load-more list. */\n itemsPerPage?: number;\n /** dataDisplay.paginationStyle — page numbers, a Load more button, or loading on scroll; usePagination and Pagination follow it (round 22). */\n paginationStyle?: PreferencePaginationStyle;\n /** responsive.tableToCardsBreakpoint — below this width a Table becomes stacked cards. */\n tableToCardsBreakpoint?: PreferenceBreakpoint;\n /** emptyStates.emptyStyle — illustration with an action, text with an action, or redirect to creation. */\n emptyStyle?: PreferenceEmptyStyle;\n /** emptyStates.loadingStyle — what a page shows while data loads. */\n loadingStyle?: PreferenceLoadingStyle;\n /** destructiveActions.mode — confirm in a dialog, or act now with an Undo toast. */\n destructiveMode?: PreferenceDestructiveMode;\n /** destructiveActions.highSeverityActions — always confirm in a dialog, even in undo mode. */\n highSeverityActions?: string[];\n /** destructiveActions.typeToConfirmActions — the user types the name before the confirm enables. */\n typeToConfirmActions?: string[];\n /** destructiveActions.undoWindowSeconds — how long the Undo toast stays. */\n undoWindowSeconds?: number;\n}\n\nexport const PreferencesContext = createContext<AppShellPreferences | null>(null);\n\n/** Every preference in force, the shell's value or the house default — what app code reads. */\nexport interface ResolvedPreferences {\n validationTiming: PreferenceValidationTiming;\n formActions: { align: \"start\" | \"end\"; placement: \"auto\" | \"inline\" };\n itemsPerPage: number;\n paginationStyle: PreferencePaginationStyle;\n tableToCardsBreakpoint: PreferenceBreakpoint;\n emptyStyle: PreferenceEmptyStyle;\n loadingStyle: PreferenceLoadingStyle;\n destructiveMode: PreferenceDestructiveMode;\n highSeverityActions: string[];\n typeToConfirmActions: string[];\n undoWindowSeconds: number;\n}\n\n/**\n * The house defaults for the fields the shell carries: the platform's preference-defaults.ts, mirrored in\n * decisions-schema.ts (DEFAULT_PATTERN_DECISIONS); a test keeps the three equal.\n */\nconst HOUSE_DEFAULTS: ResolvedPreferences = {\n validationTiming: \"onBlur\",\n formActions: { align: \"end\", placement: \"auto\" },\n itemsPerPage: 25,\n paginationStyle: \"pagination\",\n tableToCardsBreakpoint: \"md\",\n emptyStyle: \"illustration-cta\",\n loadingStyle: \"skeleton\",\n destructiveMode: \"dialog\",\n highSeverityActions: [\"delete_account\", \"remove_team_member\"],\n typeToConfirmActions: [\"delete_account\"],\n undoWindowSeconds: 5,\n};\nexport const PREFERENCE_HOUSE_DEFAULTS: Readonly<ResolvedPreferences> = Object.freeze(HOUSE_DEFAULTS);\n\n/**\n * For app code: every preference in force — the shell's value, else the house default — so a page never writes a\n * fallback of its own. Round 21 (run 58): with every field optional, TypeScript made the builder write\n * `const { itemsPerPage = 20 } = usePreferences()`, a second copy of the preference it then edited by hand when the\n * rule changed. Paged lists use `usePagination`, which reads the page size itself.\n */\nexport function usePreferences(): ResolvedPreferences {\n const raw = useShellPreferences();\n return useMemo(() => resolvePreferences(raw), [raw]);\n}\n\n/** The shell's values over the house defaults; a field the shell leaves undefined keeps its default. */\nexport function resolvePreferences(raw: AppShellPreferences): ResolvedPreferences {\n const d = PREFERENCE_HOUSE_DEFAULTS;\n const out: ResolvedPreferences = { ...d, formActions: { ...d.formActions }, highSeverityActions: [...d.highSeverityActions], typeToConfirmActions: [...d.typeToConfirmActions] };\n for (const [key, value] of Object.entries(raw) as Array<[keyof AppShellPreferences, unknown]>) {\n if (value === undefined) continue;\n if (key === \"formActions\") {\n const actions = value as AppShellPreferences[\"formActions\"];\n if (actions?.align !== undefined) out.formActions.align = actions.align;\n if (actions?.placement !== undefined) out.formActions.placement = actions.placement;\n continue;\n }\n (out as unknown as Record<string, unknown>)[key] = value;\n }\n return out;\n}\n\n/**\n * For components: only what the shell passed, or an empty object outside any shell — a component with no prop takes\n * the shell's value, and a bare component keeps the default it always had.\n */\nexport function useShellPreferences(): AppShellPreferences {\n return useContext(PreferencesContext) ?? EMPTY;\n}\n\nconst EMPTY: AppShellPreferences = Object.freeze({});\n\n/**\n * \"Remove range\" → \"remove_range\": the key the high-severity and type-to-confirm lists use. The engine's `actionKey`\n * (platform/src/lib/destructive-mode.ts) is the same rule for compliance; a platform test keeps the two identical.\n */\nexport function preferenceActionKey(label: string): string {\n return label.trim().toLowerCase().replace(/[^a-z0-9]+/g, \"_\").replace(/^_|_$/g, \"\");\n}\n","import { createContext } from \"react\";\n\n/**\n * True inside a SplitView pane (list, detail, aside). A StackedList reads it to take its inset from the pane\n * (Sprint 25.4 C-5): rows keep their padding so the selection rail sits at the pane's edge and never touches content.\n */\nexport const SplitPaneCtx = createContext(false);\n\n/**\n * True inside a Table or DataGrid card (the phone layout below mobileBreakpoint). An EntityCell reads it to keep\n * the avatar beside the text and align to the value column (Sprint 25.4, round 7: the stacked cell made the card\n * three lines taller than it needed to be).\n */\nexport const TableCardCtx = createContext(false);\n"]}
@@ -1,42 +0,0 @@
1
- import { createContext, useContext, useRef, useCallback } from 'react';
2
-
3
- // ../../showcase/src/lib/form-context.ts
4
- var FormCtx = createContext(null);
5
- function useFormContext() {
6
- const ctx = useContext(FormCtx);
7
- if (!ctx) throw new Error("useFormContext must be used within FormWrapper");
8
- return ctx;
9
- }
10
- function useOptionalFormContext() {
11
- return useContext(FormCtx);
12
- }
13
- var FormChangeCtx = createContext(null);
14
- function sameValue(a, b) {
15
- if (Object.is(a, b)) return true;
16
- if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
17
- if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => sameValue(x, b[i]));
18
- if (a && b && typeof a === "object" && typeof b === "object" && Object.getPrototypeOf(a) === Object.prototype && Object.getPrototypeOf(b) === Object.prototype) {
19
- const ka = Object.keys(a);
20
- const kb = Object.keys(b);
21
- return ka.length === kb.length && ka.every((k) => sameValue(a[k], b[k]));
22
- }
23
- if (a === "" && (b === void 0 || b === null) || b === "" && (a === void 0 || a === null)) return true;
24
- return false;
25
- }
26
- function useReportedChange(onChange, current, read = (...args) => args[0]) {
27
- const report = useContext(FormChangeCtx);
28
- const currentRef = useRef(current);
29
- currentRef.current = current;
30
- const onChangeRef = useRef(onChange);
31
- onChangeRef.current = onChange;
32
- const readRef = useRef(read);
33
- readRef.current = read;
34
- return useCallback((...args) => {
35
- if (report && !sameValue(currentRef.current, readRef.current(...args))) report();
36
- onChangeRef.current?.(...args);
37
- }, [report]);
38
- }
39
-
40
- export { FormChangeCtx, FormCtx, useFormContext, useOptionalFormContext, useReportedChange };
41
- //# sourceMappingURL=chunk-XVB55M3N.js.map
42
- //# sourceMappingURL=chunk-XVB55M3N.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/form-context.ts"],"names":[],"mappings":";;;AA0BO,IAAM,OAAA,GAAU,cAAuC,IAAI;AAE3D,SAAS,cAAA,GAAmC;AACjD,EAAA,MAAM,GAAA,GAAM,WAAW,OAAO,CAAA;AAC9B,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAC1E,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,sBAAA,GAAkD;AAChE,EAAA,OAAO,WAAW,OAAO,CAAA;AAC3B;AAOO,IAAM,aAAA,GAAgB,cAAmC,IAAI;AAG7D,SAAS,SAAA,CAAU,GAAY,CAAA,EAAqB;AACzD,EAAA,IAAI,MAAA,CAAO,EAAA,CAAG,CAAA,EAAG,CAAC,GAAG,OAAO,IAAA;AAC5B,EAAA,IAAI,CAAA,YAAa,QAAQ,CAAA,YAAa,IAAA,SAAa,CAAA,CAAE,OAAA,EAAQ,KAAM,CAAA,CAAE,OAAA,EAAQ;AAC7E,EAAA,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA,IAAK,MAAM,OAAA,CAAQ,CAAC,CAAA,EAAG,OAAO,CAAA,CAAE,MAAA,KAAW,EAAE,MAAA,IAAU,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,UAAU,CAAA,EAAG,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC9G,EAAA,IAAI,KAAK,CAAA,IAAK,OAAO,MAAM,QAAA,IAAY,OAAO,MAAM,QAAA,IAAY,MAAA,CAAO,eAAe,CAAC,CAAA,KAAM,OAAO,SAAA,IAAa,MAAA,CAAO,eAAe,CAAC,CAAA,KAAM,OAAO,SAAA,EAAW;AAC9J,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,CAA4B,CAAA;AACnD,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,IAAA,CAAK,CAA4B,CAAA;AACnD,IAAA,OAAO,EAAA,CAAG,MAAA,KAAW,EAAA,CAAG,MAAA,IAAU,GAAG,KAAA,CAAM,CAAC,CAAA,KAAM,SAAA,CAAW,EAA8B,CAAC,CAAA,EAAI,CAAA,CAA8B,CAAC,CAAC,CAAC,CAAA;AAAA,EACnI;AAEA,EAAA,IAAK,CAAA,KAAM,EAAA,KAAO,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,CAAA,IAAW,CAAA,KAAM,EAAA,KAAO,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,CAAA,EAAQ,OAAO,IAAA;AAC3G,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,iBAAA,CACd,UACA,OAAA,EACA,IAAA,GAAgC,IAAI,IAAA,KAAY,IAAA,CAAK,CAAC,CAAA,EAChC;AACtB,EAAA,MAAM,MAAA,GAAS,WAAW,aAAa,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAA,MAAM,WAAA,GAAc,OAAO,QAAQ,CAAA;AACnC,EAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AACtB,EAAA,MAAM,OAAA,GAAU,OAAO,IAAI,CAAA;AAC3B,EAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,EAAA,OAAO,WAAA,CAAY,IAAI,IAAA,KAAY;AACjC,IAAA,IAAI,MAAA,IAAU,CAAC,SAAA,CAAU,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,OAAA,CAAQ,GAAG,IAAI,CAAC,CAAA,EAAG,MAAA,EAAO;AAC/E,IAAA,WAAA,CAAY,OAAA,GAAU,GAAG,IAAI,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACb","file":"chunk-XVB55M3N.js","sourcesContent":["import { createContext, useCallback, useContext, useRef } from \"react\";\n\n/** When a form's fields check themselves: the project's forms.validationTiming, through FormWrapper. */\nexport type ValidationMode = \"onBlur\" | \"onSubmit\" | \"onChange\";\n\nexport interface FormErrors {\n [field: string]: string | undefined;\n}\n\n/** A field's check: the message for what is wrong with its value now, or nothing. */\nexport type FieldCheck = () => string | undefined;\n\nexport interface FormContextValue {\n errors: FormErrors;\n setError: (field: string, message: string | undefined) => void;\n clearErrors: () => void;\n validationMode: ValidationMode;\n submitted: boolean;\n /**\n * A Field given `validate` registers its check under its id, and the form runs every check on each submit (round 26,\n * R26-2: the forms of both runs checked their fields only on submit, although the project said on blur). Returns\n * the unregister.\n */\n register: (field: string, check: FieldCheck) => () => void;\n}\n\nexport const FormCtx = createContext<FormContextValue | null>(null);\n\nexport function useFormContext(): FormContextValue {\n const ctx = useContext(FormCtx);\n if (!ctx) throw new Error(\"useFormContext must be used within FormWrapper\");\n return ctx;\n}\n\n/** The FormWrapper a component sits in, or null. */\nexport function useOptionalFormContext(): FormContextValue | null {\n return useContext(FormCtx);\n}\n\n/**\n * Sprint 25.12 A15 (R28-25): the nearest FormWrapper's change reporter. A control calls it when the user gives it a new\n * value; the form passes it on to the overlay that holds it, so the overlay asks before discarding only after a change.\n * Null outside a FormWrapper: controls there never mark anything (a page that saves as you go has nothing to discard).\n */\nexport const FormChangeCtx = createContext<(() => void) | null>(null);\n\n/** Whether two control values are the same value: dates by time, arrays and plain objects by their parts. */\nexport function sameValue(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((x, i) => sameValue(x, b[i]));\n if (a && b && typeof a === \"object\" && typeof b === \"object\" && Object.getPrototypeOf(a) === Object.prototype && Object.getPrototypeOf(b) === Object.prototype) {\n const ka = Object.keys(a as Record<string, unknown>);\n const kb = Object.keys(b as Record<string, unknown>);\n return ka.length === kb.length && ka.every((k) => sameValue((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]));\n }\n // an empty text field and an unset value are the same answer: a control that commits \"\" over undefined changed nothing\n if ((a === \"\" && (b === undefined || b === null)) || (b === \"\" && (a === undefined || a === null))) return true;\n return false;\n}\n\n/**\n * Sprint 25.12 A15: a control's `onChange`, wrapped so a new value the user gives it reports a change to the nearest\n * FormWrapper before the page hears of it. `current` is the control's value now (its prop, or its own state when it\n * keeps one); `read` takes the new value from onChange's arguments (the first argument by default; an event's\n * `target.value` for native inputs). Only a different value reports: NumberInput committing the same number on blur,\n * or a search inside a Dropdown, changes nothing. Call it only from the user's own actions, never from an effect, so a\n * value the page sets, or one a control settles on by itself, never counts.\n */\nexport function useReportedChange<A extends unknown[]>(\n onChange: ((...args: A) => void) | undefined,\n current: unknown,\n read: (...args: A) => unknown = (...args: A) => args[0],\n): (...args: A) => void {\n const report = useContext(FormChangeCtx);\n const currentRef = useRef(current);\n currentRef.current = current;\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const readRef = useRef(read);\n readRef.current = read;\n return useCallback((...args: A) => {\n if (report && !sameValue(currentRef.current, readRef.current(...args))) report();\n onChangeRef.current?.(...args);\n }, [report]);\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/components/Badge.tsx"],"names":[],"mappings":";;;;;AAsBA,IAAM,iBAAA,GAAyD;AAAA,EAC7D,IAAA,EAAM,SAAA;AAAA,EACN,GAAA,EAAK,cAAA;AAAA,EACL,MAAA,EAAQ,cAAA;AAAA,EACR,IAAA,EAAM,YAAA;AAAA,EACN,QAAA,EAAU;AACZ,CAAA;AAEA,IAAM,aAAA,GAA8C;AAAA,EAClD,OAAA,EAAS,sGAAA;AAAA,EACT,OAAA,EAAS,kEAAA;AAAA,EACT,MAAA,EAAQ,yDAAA;AAAA,EACR,OAAA,EAAS,gEAAA;AAAA,EACT,cAAA,EAAgB,iJAAA;AAAA,EAChB,OAAA,EAAS,gEAAA;AAAA,EACT,cAAA,EAAgB,sJAAA;AAAA,EAChB,KAAA,EAAO,4DAAA;AAAA,EACP,YAAA,EAAc,2IAAA;AAAA,EACd,OAAA,EAAS;AACX,CAAA;AAEA,IAAM,UAAA,GAAwC;AAAA,EAC5C,EAAA,EAAI,iDAAA;AAAA,EACJ,EAAA,EAAI,iEAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,IAAM,SAAA,GAAuC;AAAA,EAC3C,EAAA,EAAI,EAAA;AAAA,EACJ,EAAA,EAAI,EAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAIA,IAAM,gBAAA,GAAmD;AAAA,EACvD,OAAA,EAAS,CAAC,CAAA,KAAM,cAAA,CAAe,CAAC,CAAA;AAAA,EAChC,OAAA,EAAS,CAAC,CAAA,KAAM,aAAA,CAAc,CAAC,CAAA;AAAA,EAC/B,MAAA,EAAQ,CAAC,CAAA,KAAM,aAAA,CAAc,CAAC,CAAA;AAAA,EAC9B,OAAA,EAAS,CAAC,CAAA,KAAM,cAAA,CAAe,CAAC;AAClC,CAAA;AAEA,IAAM,cAAA,GAAoD;AAAA,EACxD,CAAA,EAAG,kEAAA;AAAA,EACH,CAAA,EAAG,kEAAA;AAAA,EACH,CAAA,EAAG,kEAAA;AAAA,EACH,CAAA,EAAG,kEAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAEA,IAAM,aAAA,GAAmD;AAAA,EACvD,CAAA,EAAG,6DAAA;AAAA,EACH,CAAA,EAAG,6DAAA;AAAA,EACH,CAAA,EAAG,6DAAA;AAAA,EACH,CAAA,EAAG,6DAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAEA,IAAM,cAAA,GAAoD;AAAA,EACxD,CAAA,EAAG,yHAAA;AAAA,EACH,CAAA,EAAG,yHAAA;AAAA,EACH,CAAA,EAAG,yHAAA;AAAA,EACH,CAAA,EAAG,yHAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAEA,SAAS,iBAAA,CAAkB,OAA0B,OAAA,EAA+B;AAClF,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,OAAO,CAAA,IAAK,gBAAA,CAAiB,OAAA;AAC9D,EAAA,OAAO,QAAQ,KAAK,CAAA;AACtB;AAmBO,SAAS,KAAA,CAAM,EAAE,OAAA,GAAU,SAAA,EAAW,QAAA,EAAU,IAAA,GAAO,IAAA,EAAM,KAAA,EAAO,QAAA,EAAU,SAAA,EAAW,QAAA,EAAU,SAAA,EAAW,UAAS,EAAe;AAE3I,EAAA,MAAM,eAAA,GAAkB,QAAA,GAAW,iBAAA,CAAkB,QAAQ,CAAA,GAAI,OAAA;AACjE,EAAA,MAAM,EAAE,GAAA,EAAK,QAAA,EAAU,WAAA,EAAY,GAAI,eAAA,CAAgB,EAAE,KAAA,EAAO,CAAA,EAAG,QAAA,EAAU,CAAC,QAAA,EAAU,CAAA;AACxF,EAAA,MAAM,QAAA,GAAW,UAAU,IAAI,CAAA;AAC/B,EAAA,MAAM,UAAA,GAAA,CAAc,QAAA,IAAY,SAAA,KAAc,CAAC,QAAA;AAE/C,EAAA,MAAM,eAAe,KAAA,GACjB,iBAAA,CAAkB,OAAO,eAAe,CAAA,GACxC,cAAc,eAAe,CAAA;AAEjC,EAAA,MAAM,KAAA,mBACJ,IAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,4EAAA;AAAA,QACA,iCAAA;AAAA,QACA,WAAW,IAAI,CAAA;AAAA,QACf,UAAA,IAAc,SAAS,IAAA,IAAQ,UAAA;AAAA,QAC/B,UAAA,IAAc,SAAS,IAAA,IAAQ,SAAA;AAAA,QAC/B,UAAA,IAAc,SAAS,IAAA,IAAQ,WAAA;AAAA,QAC/B,YAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,KAAA,EAAO,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI,MAAA;AAAA,MAEhC,QAAA,EAAA;AAAA,QAAA,QAAA,wBAAa,IAAA,EAAA,EAAK,IAAA,EAAM,UAAU,IAAA,EAAM,QAAA,EAAU,WAAU,UAAA,EAAW,CAAA;AAAA,QACvE,QAAA,uBACE,MAAA,EAAA,EAAK,GAAA,EAAK,UAAU,SAAA,EAAU,UAAA,EAAY,UAAS,CAAA,GAEpD,QAAA;AAAA,QAED,SAAA,wBAAc,IAAA,EAAA,EAAK,IAAA,EAAM,WAAW,IAAA,EAAM,QAAA,EAAU,WAAU,UAAA,EAAW;AAAA;AAAA;AAAA,GAC5E;AAGF,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,uBAAO,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAA,EAAS,QAAA,EAAW,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,KAAA;AACT","file":"chunk-XYDIBW3J.js","sourcesContent":["import { cn } from \"../lib/utils\";\nimport { Icon, type IconName } from \"../lib/icons\";\nimport { Tooltip } from \"./Tooltip\";\nimport { useTextOverflow } from \"../lib/use-text-overflow\";\nimport type { ReactNode } from \"react\";\n\nexport type BadgeVariant =\n | \"default\"\n | \"neutral\"\n | \"subtle\"\n | \"success\"\n | \"success-soft\"\n | \"warning\"\n | \"warning-soft\"\n | \"error\"\n | \"error-soft\"\n | \"outline\";\n\nexport type BadgeSize = \"xs\" | \"sm\" | \"md\";\nexport type BadgePaletteColor = 1 | 2 | 3 | 4 | 5;\nexport type BadgeSeverity = \"info\" | \"low\" | \"medium\" | \"high\" | \"critical\";\n\nconst severityToVariant: Record<BadgeSeverity, BadgeVariant> = {\n info: \"neutral\",\n low: \"success-soft\",\n medium: \"warning-soft\",\n high: \"error-soft\",\n critical: \"error\",\n};\n\nconst variantStyles: Record<BadgeVariant, string> = {\n default: \"bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] text-[var(--ds-text-on-primary)]\",\n neutral: \"bg-[var(--ds-text-muted)]/[0.12] text-[var(--ds-text-secondary)]\",\n subtle: \"bg-[var(--ds-bg-muted)] text-[var(--ds-text-secondary)]\",\n success: \"bg-[var(--ds-status-success)] text-[var(--ds-text-on-success)]\",\n \"success-soft\": \"bg-[var(--ds-status-success-bg)] text-[var(--ds-status-success)] border-[length:var(--ds-border-width)] border-[var(--ds-status-success)]/[0.2]\",\n warning: \"bg-[var(--ds-status-warning)] text-[var(--ds-text-on-warning)]\",\n \"warning-soft\": \"bg-[var(--ds-status-warning-bg)] text-[var(--ds-status-warning-text)] border-[length:var(--ds-border-width)] border-[var(--ds-status-warning)]/[0.2]\",\n error: \"bg-[var(--ds-status-error)] text-[var(--ds-text-on-error)]\",\n \"error-soft\": \"bg-[var(--ds-status-error-bg)] text-[var(--ds-status-error)] border-[length:var(--ds-border-width)] border-[var(--ds-status-error)]/[0.2]\",\n outline: \"bg-transparent text-[var(--ds-text-primary)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n};\n\nconst sizeStyles: Record<BadgeSize, string> = {\n xs: \"px-ds-1.5 py-[1px] text-[length:10px] gap-[3px]\",\n sm: \"px-ds-2 py-ds-0.5 text-[length:var(--ds-font-size-xs)] gap-ds-1\",\n md: \"px-ds-2.5 py-ds-0.5 text-[length:var(--ds-font-size-xs)] gap-ds-1\",\n};\n\nconst iconSizes: Record<BadgeSize, number> = {\n xs: 10,\n sm: 12,\n md: 12,\n};\n\ntype PaletteStyleFn = (n: BadgePaletteColor) => string;\n\nconst paletteByVariant: Record<string, PaletteStyleFn> = {\n default: (n) => paletteDefault[n],\n neutral: (n) => paletteSubtle[n],\n subtle: (n) => paletteSubtle[n],\n outline: (n) => paletteOutline[n],\n};\n\nconst paletteDefault: Record<BadgePaletteColor, string> = {\n 1: \"bg-[var(--ds-palette-1-bold)] text-[var(--ds-palette-1-on-bold)]\",\n 2: \"bg-[var(--ds-palette-2-bold)] text-[var(--ds-palette-2-on-bold)]\",\n 3: \"bg-[var(--ds-palette-3-bold)] text-[var(--ds-palette-3-on-bold)]\",\n 4: \"bg-[var(--ds-palette-4-bold)] text-[var(--ds-palette-4-on-bold)]\",\n 5: \"bg-[var(--ds-palette-5-bold)] text-[var(--ds-palette-5-on-bold)]\",\n};\n\nconst paletteSubtle: Record<BadgePaletteColor, string> = {\n 1: \"bg-[var(--ds-palette-1-bg)] text-[var(--ds-palette-1-text)]\",\n 2: \"bg-[var(--ds-palette-2-bg)] text-[var(--ds-palette-2-text)]\",\n 3: \"bg-[var(--ds-palette-3-bg)] text-[var(--ds-palette-3-text)]\",\n 4: \"bg-[var(--ds-palette-4-bg)] text-[var(--ds-palette-4-text)]\",\n 5: \"bg-[var(--ds-palette-5-bg)] text-[var(--ds-palette-5-text)]\",\n};\n\nconst paletteOutline: Record<BadgePaletteColor, string> = {\n 1: \"bg-transparent text-[var(--ds-palette-1-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-1-bold)]\",\n 2: \"bg-transparent text-[var(--ds-palette-2-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-2-bold)]\",\n 3: \"bg-transparent text-[var(--ds-palette-3-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-3-bold)]\",\n 4: \"bg-transparent text-[var(--ds-palette-4-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-4-bold)]\",\n 5: \"bg-transparent text-[var(--ds-palette-5-bold)] border-[length:var(--ds-border-width)] border-[var(--ds-palette-5-bold)]\",\n};\n\nfunction getPaletteClasses(color: BadgePaletteColor, variant: BadgeVariant): string {\n const styleFn = paletteByVariant[variant] ?? paletteByVariant.default;\n return styleFn(color);\n}\n\ninterface BadgeProps {\n variant?: BadgeVariant;\n /** Severity shorthand — maps to a variant. When set, overrides `variant`. */\n severity?: BadgeSeverity;\n size?: BadgeSize;\n /** Palette colour (1-5). Overrides variant colour with decorative palette tokens. */\n color?: BadgePaletteColor;\n /** Icon to show before the label */\n iconLeft?: IconName;\n /** Icon to show after the label */\n iconRight?: IconName;\n /** Max width before truncation (e.g. \"120px\", \"16ch\"). Shows tooltip when truncated. */\n maxWidth?: string;\n className?: string;\n children?: ReactNode;\n}\n\nexport function Badge({ variant = \"default\", severity, size = \"md\", color, iconLeft, iconRight, maxWidth, className, children }: BadgeProps) {\n // severity sets the variant and variant is ignored when both are written\n const resolvedVariant = severity ? severityToVariant[severity] : variant;\n const { ref: truncRef, isTruncated } = useTextOverflow({ lines: 1, disabled: !maxWidth });\n const iconSize = iconSizes[size];\n const isIconOnly = (iconLeft || iconRight) && !children;\n\n const colorClasses = color\n ? getPaletteClasses(color, resolvedVariant)\n : variantStyles[resolvedVariant];\n\n const badge = (\n <span\n className={cn(\n \"inline-flex items-center font-medium max-w-full whitespace-nowrap shrink-0\",\n \"rounded-[var(--ds-radius-full)]\",\n sizeStyles[size],\n isIconOnly && size === \"xs\" && \"px-[3px]\",\n isIconOnly && size === \"sm\" && \"px-ds-1\",\n isIconOnly && size === \"md\" && \"px-ds-1.5\",\n colorClasses,\n className\n )}\n style={maxWidth ? { maxWidth } : undefined}\n >\n {iconLeft && <Icon name={iconLeft} size={iconSize} className=\"shrink-0\" />}\n {maxWidth ? (\n <span ref={truncRef} className=\"truncate\">{children}</span>\n ) : (\n children\n )}\n {iconRight && <Icon name={iconRight} size={iconSize} className=\"shrink-0\" />}\n </span>\n );\n\n if (isTruncated) {\n return <Tooltip content={children}>{badge}</Tooltip>;\n }\n return badge;\n}\n"]}