@opencorestack/opengridx 3.6.0 → 3.7.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 (74) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/ai.cjs +3 -3
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.es.js +3 -3
  5. package/dist/ai.es.js.map +1 -1
  6. package/dist/index.d.ts +30 -0
  7. package/dist/opengridx.css +1 -1
  8. package/dist/opengridx.es.js +8756 -8244
  9. package/dist/opengridx.es.js.map +1 -1
  10. package/dist/opengridx.umd.js +15 -15
  11. package/dist/opengridx.umd.js.map +1 -1
  12. package/docs/API_REFERENCE.md +3 -2
  13. package/docs/architecture/datagrid-orchestration.md +46 -29
  14. package/docs/architecture/grid-row-meta.md +1 -1
  15. package/docs/customization/slots-api.md +1 -1
  16. package/docs/customization/theming.md +43 -0
  17. package/docs/features/virtualization.md +16 -2
  18. package/docs/performance.md +3 -1
  19. package/lib/components/AiAssistant/GridAiAssistantPanel.css +3 -1
  20. package/lib/components/Cell/Cell.css +4 -2
  21. package/lib/components/ColumnGroupHeader/ColumnGroupHeader.css +2 -2
  22. package/lib/components/ColumnVisibilityPanel/ColumnVisibilityPanel.css +3 -1
  23. package/lib/components/DataGrid/DataGrid.css +9 -12
  24. package/lib/components/DataGrid/DataGrid.tsx +163 -671
  25. package/lib/components/DataGrid/GridRoot.tsx +239 -0
  26. package/lib/components/DataGrid/GridViewport.tsx +314 -0
  27. package/lib/components/FilterPanel/FilterPanel.css +9 -8
  28. package/lib/components/Header/ColumnMenu.css +4 -3
  29. package/lib/components/Header/Header.css +5 -4
  30. package/lib/components/HeaderFilter/HeaderFilter.css +1 -1
  31. package/lib/components/ListView/ListView.css +4 -4
  32. package/lib/components/Pagination/Pagination.css +1 -1
  33. package/lib/components/Row/Row.css +2 -2
  34. package/lib/components/Toolbar/GridToolbar.css +8 -7
  35. package/lib/components/Toolbar/PivotPanel.css +3 -3
  36. package/lib/hooks/core/useGridDevWarnings.ts +3 -1
  37. package/lib/hooks/core/useGridEditPipeline.ts +55 -0
  38. package/lib/hooks/core/useGridRangeEditing.ts +129 -0
  39. package/lib/hooks/core/useGridRenderWindow.ts +66 -0
  40. package/lib/hooks/core/useGridScrollViewport.ts +42 -0
  41. package/lib/hooks/core/useGridSelectionAndStateApi.ts +61 -0
  42. package/lib/hooks/core/useGridToolbarStack.ts +49 -0
  43. package/lib/hooks/core/useGridViewApis.ts +46 -0
  44. package/lib/hooks/core/useLayout.ts +34 -24
  45. package/lib/styles/base/reset.css +5 -3
  46. package/lib/styles/base/variables.css +12 -0
  47. package/lib/theme/DataGridThemeProvider.tsx +15 -0
  48. package/lib/theme/__baseline__/default-theme.darwin.chromium.json +1503 -0
  49. package/lib/theme/__baseline__/default-theme.darwin.firefox.json +1503 -0
  50. package/lib/theme/__baseline__/default-theme.darwin.webkit.json +1503 -0
  51. package/lib/theme/types.ts +31 -0
  52. package/lib/types/ai.ts +109 -0
  53. package/lib/types/api.ts +169 -0
  54. package/lib/types/columns.ts +341 -0
  55. package/lib/types/dataSource.ts +40 -0
  56. package/lib/types/editing.ts +77 -0
  57. package/lib/types/export.ts +164 -0
  58. package/lib/types/filtering.ts +52 -0
  59. package/lib/types/grouping.ts +27 -0
  60. package/lib/types/index.ts +18 -1702
  61. package/lib/types/locale.ts +51 -0
  62. package/lib/types/props.ts +405 -0
  63. package/lib/types/rows.ts +132 -0
  64. package/lib/types/selection.ts +66 -0
  65. package/lib/types/slots.ts +56 -0
  66. package/lib/types/sorting.ts +25 -0
  67. package/lib/types/state.ts +35 -0
  68. package/lib/utils/export/exportShared.ts +22 -4
  69. package/lib/utils/export/index.ts +8 -4
  70. package/lib/utils/filtering/index.ts +8 -2
  71. package/lib/utils/parsing.ts +24 -1
  72. package/lib/utils/values.ts +31 -0
  73. package/llms.txt +1 -1
  74. package/package.json +4 -2
package/CHANGELOG.md CHANGED
@@ -5,6 +5,44 @@
5
5
 
6
6
  ---
7
7
 
8
+ ## [3.7.1] — 2026-10-13
9
+
10
+ ### Fixed
11
+
12
+ - **Exports no longer crash when a column's `valueGetter` throws.** CSV, Excel (HTML and `exportToExcelAdvanced`), JSON, print and PDF read cell values through `getCellValue`, as the grid does: a throwing getter exports an empty value with a one-time development warning.
13
+ - **Formula escaping covers `valueFormatter` text on number, date and boolean columns** (security). A formatter returning `=HYPERLINK(...)` for a number column was written to CSV and HTML-Excel unescaped, because only the raw value's type was checked. Formatter text is now left unescaped only when it reads as a plain formatted number (digits, signs, separators, brackets, `%`, currency symbols), so `-$3` stays as is.
14
+ - **The quick filter matches the text the grid shows** for `singleSelect` (option label), `boolean` (Yes / No) and `date` (locale date) columns without a `valueFormatter`, in addition to the raw value.
15
+ - **Free text is no longer read as a date.** `Date.parse` accepts text such as `hello 5` (a 2001 date in V8); pasting it into a date column stored that date. Date text may now only contain month and weekday names, `T`, `Z`, `AM`/`PM`, `GMT`/`UTC` besides digits and punctuation. The same rule applies to date filters and sorting of date strings.
16
+ - **Pasting a date into a cell that holds a UTC date-time** (`…Z` or `±hh:mm`) kept the time part but changed the zone meaning, so west of UTC the cell showed the day before. The pasted day now keeps the cell's local time of day and is written as UTC.
17
+ - **List view follows the theme.** Its row text read the undeclared `--ogx-grid-cell-text`, and hover / selection used fixed colours; they now use `--ogx-grid-row-text`, `--ogx-grid-row-hover-background`, `--ogx-grid-row-selected-background` and `--ogx-grid-row-selected-hover-background` (`--ogx-selection-bg` / `--ogx-selection-hover-bg` still win when set).
18
+ - **The stylesheet no longer changes the host page.** The `box-sizing: border-box` reset applied to every element on the page; it now applies only to elements with an `ogx` class and their descendants (including portalled menus and panels), at zero specificity. A page that relied on it for its own elements (for example a padded container with a fixed width around the grid) may need its own `box-sizing: border-box` rule.
19
+
20
+ ### Changed
21
+
22
+ - The grid no longer draws a shadow on hover (`.ogx:hover`), which repainted the whole grid on every pointer enter and leave. Add `.ogx:hover { box-shadow: var(--ogx-shadow-md); }` to keep it.
23
+
24
+ ### Performance
25
+
26
+ - `useLayout` computes row heights and column widths in separate memos: resizing a column no longer walks every row, and sorting or filtering no longer recomputes column widths.
27
+
28
+ ---
29
+
30
+ ## [3.7.0] — 2026-10-13
31
+
32
+ ### Added
33
+
34
+ - **16 theme keys for fonts, dividers and corners** (additive; every one defaults to exactly what the grid drew before). `grid.headerFontFamily` / `headerFontWeight` / `cellFontFamily` / `cellFontWeight` (`--ogx-grid-header-font-family`, `--ogx-grid-header-font-weight` default 600, `--ogx-grid-cell-font-family`, `--ogx-grid-cell-font-weight`), `grid.headerPaddingX` (`--ogx-grid-header-padding-x`, defaults to the cell padding), `grid.borderWidth` (`--ogx-grid-border-width`, 1px) and `grid.borderRadius` (`--ogx-grid-border-radius`, defaults to `--ogx-border-radius-lg`), `grid.columnDividerWidth` / `headerColumnDividerWidth` / `rowDividerWidth` (`--ogx-grid-column-divider-width`, `--ogx-grid-header-column-divider-width`, `--ogx-grid-row-divider-width`, 1px; `0` hides them) and `grid.columnDividerColor` / `rowDividerColor` (`--ogx-grid-column-divider-color`, `--ogx-grid-row-divider-color`, default the grid border colour), and `overlays.fontFamily` / `fontWeight` / `fontSize` (`--ogx-overlay-font-*`) for the column menu, header filter menu, toolbar panels and AI panel. The hard-coded 1px divider borders of cells, rows, header rows, column-group rows, the header filter row, aggregation footer cells and the right-pinned edge now read these variables (logical `border-inline-*` properties kept). A new browser test (`lib/theme/defaultThemeBaseline.browser.test.tsx`) compares computed styles and element boxes of eleven grids (plain, pinned with column groups and selection, dark and compact presets, header filters and their menu, aggregation footer, toolbar panels, column menu) with a baseline captured before the change, in Chromium, Firefox and WebKit: no differences. Guide: *Fonts, dividers and corners* and the *hide the dividers* recipe in `docs/customization/theming.md`.
35
+ - **Theme Builder demo page** (`/theme-builder`, under Customization, linked from the Theming page). Grouped, collapsible controls with a reset each: colour picker plus text field, font family (presets or custom), weight 300–800 and size, sliders for heights, padding, widths and radius, and show/hide switches for body column dividers, header dividers and row dividers (they set the width to 0). A live preview grid (toolbar, pinned column, selected row, row grouping, density switch, a button that opens the column menu) in `DataGridThemeProvider`. A Light / Dark switch picks which theme is edited and previewed; "Start from" loads a built-in preset. Copy theme (TypeScript, only values that differ from the defaults, light, dark or both; clipboard API with a fallback), Download `.ts`, Share via URL (`#theme=…`, restored on load). WCAG AA contrast hints for seven text/background pairs (warnings only) and a collapsed Advanced JSON editor for every theme key. Controls move into a drawer when the page is narrower than about 1,060 px. The demo smoke test also runs it in Firefox and WebKit.
36
+
37
+ ### Internal
38
+
39
+ - **`DataGrid.tsx` split up** (1,128 → 620 lines), with no change to the public API, the rendered DOM, attributes, class names, event order or hook order. The JSX moved into `GridRoot` (root element, toolbar, panels, list view, footer, live region, overlays) and `GridViewport` (the `role="grid"` viewport and the shared row renderer props). Seven composite hooks each wrap a contiguous run of the documented hook order and call it unchanged: `useGridEditPipeline` (12a–13), `useGridSelectionAndStateApi` (23–24), `useGridViewApis` (30–31a), `useGridScrollViewport` (32–33), `useGridRangeEditing` (36a–36d), `useGridRenderWindow` (38–41) and `useGridToolbarStack` (44–46). `docs/architecture/datagrid-orchestration.md` lists each hook with its composite. React DevTools shows the two new components (`GridRoot`, `GridViewport`) under `DataGrid`; each renders once per grid render.
40
+ - **Demo-site smoke test** (`npm run test:demo`, `e2e/demo.spec.ts`, `e2e/playwright.demo.config.ts`). Builds the demo and serves it with `vite preview` on port 4322 under `/OpenGridX/`, then loads every route of `demo/App.tsx` (read from the source; 55 routes, checked against the built sidebar) in Chromium, and seven heavy pages (cell selection, AI assistant, full feature test, RTL, theming, pivot, infinite scroll) also in Firefox and WebKit. Each page must log no console error or warning and no page error, replace the loading skeleton, show text, and every grid must show a row or an intentional empty / loading / error state. Runs in `ci.yml` after the package smoke suite and in `deploy.yml` in place of the bare demo build, so a broken demo page is never deployed. No demo page was broken.
41
+ - **Height-limit guidance.** The development warning for content taller than the browser lays out now names `dataSource` (server-side pages or infinite scroll) with `docs/features/data-source.md`, then `pagination` and compact density, and links the new *The browser height limit* section of `docs/features/virtualization.md`. That section opens with a decision guide: up to about 300,000 rows at 52 px fit in every browser, up to about 600,000 in Chromium and WebKit only, beyond that use a `dataSource` or pagination; `density="compact"` stretches each limit about 1.6×. `docs/performance.md` links it. New unit test `useGridDevWarnings.test.ts` covers the warning text.
42
+ - **`source-map-js` pinned to 1.2.2** through `overrides` in the root and in the e2e and bench fixtures (GHSA-68fv-2mgg-jv7q, high, dev toolchain only; the root lockfile had 1.2.1). The `sprintf-js` advisory (GHSA-hp3w-g68c-fv3c, no patched release) stays open: it comes from `@microsoft/api-extractor` → `@rushstack/ts-command-line` → `argparse@1`, which `vite-plugin-dts` v5 still needs to bundle `dist/index.d.ts` and `dist/ai.d.ts` (api-extractor 7.59.4 still depends on `argparse ~1.0.9`), so upgrading to v5 would not remove it. It only runs at build time on this repository's own sources.
43
+
44
+ ---
45
+
8
46
  ## [3.6.0] — 2026-10-12
9
47
 
10
48
  ### Added
@@ -40,6 +78,7 @@
40
78
  ### Internal
41
79
 
42
80
  - `docs/superpowers/specs/2026-10-12-nonblocking-pipeline-proposal.md`: a proposal for time-sliced sorting, filtering and grouping (not implemented).
81
+ - `lib/types/index.ts` is split into one file per domain (`rows`, `columns`, `sorting`, `filtering`, `editing`, `export`, `dataSource`, `selection`, `grouping`, `state`, `locale`, `props`, `slots`, `api`, `ai`); `index.ts` re-exports them. A move only: the published `index.d.ts` and `ai.d.ts` declare the same types with the same doc comments.
43
82
 
44
83
  ## [3.5.1] — 2026-10-12
45
84
 
package/dist/ai.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Q=new Set;function de(e,t,r){process.env.NODE_ENV==="production"||Q.has(e)||(Q.add(e),console.warn(`[OpenGridX] ${t}.`,r))}function pe(e,t,r){const n=e[t];if(!r?.valueGetter)return{value:n};try{return{value:r.valueGetter({row:e,field:t,value:n})}}catch(o){return{value:void 0,error:o??new Error("valueGetter failed")}}}function ge(e,t,r){if(!r?.valueGetter)return e[t];const{value:n,error:o}=pe(e,t,r);return o!==void 0&&de(`valueGetter:${t}`,`valueGetter for column "${t}" threw; the value is read as undefined`,o),n}const me=/^(\d{4})-(\d{2})-(\d{2})$/;function ee(e){if(e==null)return null;let t;if(e instanceof Date)t=e;else if(typeof e=="number")t=new Date(e);else if(typeof e=="string"){const r=e.trim();if(r==="")return null;const n=me.exec(r);if(n){const o=Number(n[1]),i=Number(n[2])-1,s=Number(n[3]);if(t=new Date(o,i,s),t.getMonth()!==i||t.getDate()!==s)return null}else t=new Date(r)}else return null;return Number.isNaN(t.getTime())?null:t}function ye(e){const t=ee(e);if(!t)return"";const r=String(t.getFullYear()).padStart(4,"0"),n=String(t.getMonth()+1).padStart(2,"0"),o=String(t.getDate()).padStart(2,"0");return`${r}-${n}-${o}`}function be(e){switch(e){case"number":return["=","!=",">",">=","<","<=","isEmpty","isNotEmpty"];case"date":return["is","not","after","onOrAfter","before","onOrBefore","isEmpty","isNotEmpty"];case"boolean":return["is"];case"singleSelect":return["isAnyOf","is","not"];default:return["contains","equals","startsWith","endsWith","isEmpty","isNotEmpty"]}}const he=["sum","avg","count","min","max","unique"],X=["sum","avg","count","min","max"],te=["isEmpty","isNotEmpty"],I=3,U=["filter","sort","grouping","aggregation","pivot","columnVisibility"],H={filter:"filterModel",sort:"sortModel",grouping:"rowGroupingModel",aggregation:"aggregationModel",pivot:"pivotModel",columnVisibility:"columnVisibilityModel"};function S(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function $(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function re(e){const t=Array.isArray(e?.include)?e.include:U,r=Array.isArray(e?.exclude)?e.exclude:[];return U.filter(n=>t.includes(n)&&!r.includes(n))}function J(e){if(!Array.isArray(e))return[];const t=new Set,r=[];for(const n of e){if(!$(n))continue;const o=n.field;typeof o!="string"||o===""||o.startsWith("__")||n.isSpacer===!0||t.has(o)||(t.add(o),r.push(n))}return r}function ne(e){return be(e.type)}const ie=e=>e.filterable!==!1,oe=e=>e.sortable!==!1,G=e=>e.groupable!==!1,se=e=>e.hideable!==!1;function F(e,t=he){if(e.aggregable===!1)return[];const r=e.type==="number"||e.aggregable===!0?t:t.filter(o=>o==="count"),n=e.availableAggregationFunctions;return Array.isArray(n)?r.filter(o=>n.includes(o)):[...r]}function $e(e){const t=[];if(!Array.isArray(e.valueOptions))return t;for(const r of e.valueOptions){const n=r!==null&&typeof r=="object"?r.value:r;(typeof n=="string"||typeof n=="number"&&Number.isFinite(n))&&!t.includes(n)&&t.push(n)}return t}const Ae="OpenGridX grid state",Se=10;function j(e){const t=typeof e.headerName=="string"&&e.headerName!==""?e.headerName:e.field,r=typeof e.description=="string"&&e.description!==""?` (${e.description})`:"";return`${t}${r}`}function O(e,t,r){return r.descriptions?{...e,description:t}:e}function Oe(e,t){return!t.examples||!Array.isArray(e.aiExamples)?[]:e.aiExamples.filter(r=>typeof r=="string"||typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r)).slice(0,Se)}function ve(e,t){let r;switch(e.type){case"number":r={type:"number"};break;case"date":r={type:"string",format:"date"};break;case"boolean":r={type:"boolean"};break;case"singleSelect":{const o=$e(e),i=o.length>0?{enum:o}:{type:"string"};r={anyOf:[i,{type:"array",items:i}]};break}default:r={type:"string"}}const n=Oe(e,t);return n.length>0?{...r,examples:n}:r}function Me(e,t){const r=ne(e),n=r.filter(s=>te.includes(s)),o=e.type==="singleSelect"?"; isAnyOf takes an array":"",i=n.length>0?`${n.join(" and ")} take no value${o}`:o.slice(2);return O({type:"object",properties:{field:{const:e.field},operator:{enum:r},value:ve(e,t)},required:["field","operator"],additionalProperties:!1},i?`${j(e)}: ${i}`:j(e),t)}function Ee(e,t,r){const n=e.filter(ie),o={},i={enum:["and","or"]};if(n.length>0){r.filterItem={oneOf:n.map(s=>Me(s,t))};for(let s=I;s>=1;s--){const l=s===I?{$ref:"#/$defs/filterItem"}:{anyOf:[{$ref:"#/$defs/filterItem"},{$ref:`#/$defs/filterGroup${s+1}`}]};r[`filterGroup${s}`]={type:"object",properties:{logicOperator:i,items:{type:"array",items:l}},required:["logicOperator","items"],additionalProperties:!1}}o.items={type:"array",items:{anyOf:[{$ref:"#/$defs/filterItem"},{$ref:"#/$defs/filterGroup1"}]}},o.logicOperator=i}return o.quickFilterValues=O({type:"array",items:{type:"string"}},"Words a row must contain, in any column",t),{type:"object",properties:o,additionalProperties:!1}}function q(e){return{enum:e.map(t=>t.field)}}function we(e,t,r,n){switch(e){case"filter":return Ee(t,r,n);case"sort":{const o=t.filter(oe);return o.length===0?null:O({type:"array",items:{type:"object",properties:{field:q(o),sort:{enum:["asc","desc"]}},required:["field","sort"],additionalProperties:!1}},"Most significant first",r)}case"grouping":{const o=t.filter(G);return o.length===0?null:O({type:"array",items:q(o),uniqueItems:!0},"Outermost first",r)}case"aggregation":{const o={};for(const i of t){const s=F(i);s.length>0&&(o[i.field]=O({enum:s},j(i),r))}return Object.keys(o).length===0?null:{type:"object",properties:o,additionalProperties:!1}}case"pivot":{const o=t.filter(G),i=t.map(l=>({col:l,fns:F(l,X)})).filter(l=>l.fns.length>0).map(({col:l,fns:a})=>O({type:"object",properties:{field:{const:l.field},aggFn:{enum:a}},required:["field","aggFn"],additionalProperties:!1},j(l),r));if(o.length===0||i.length===0)return null;const s={type:"array",items:q(o),uniqueItems:!0};return{type:"object",properties:{rowFields:s,columnFields:s,valueFields:{type:"array",items:{oneOf:i}}},required:["rowFields","columnFields","valueFields"],additionalProperties:!1}}case"columnVisibility":{const o={};for(const i of t.filter(se))o[i.field]=O({type:"boolean"},j(i),r);return Object.keys(o).length===0?null:O({type:"object",properties:o,additionalProperties:!1},"false hides a column",r)}}}function Y(e,t={}){const r={descriptions:t.descriptions!==!1,examples:t.examples!==!1},n=J(e),o={},i={};for(const l of re(t)){const a=we(l,n,r,o);a&&(i[H[l]]=a)}const s={$schema:"https://json-schema.org/draft/2020-12/schema",schemaVersion:1,title:Ae,type:"object",properties:i,additionalProperties:!1};return r.descriptions&&(s.description="Grid state to apply. Include only the parts the user asked to change."),Object.keys(o).length>0&&(s.$defs=o),s}const Fe=Symbol.for("opengridx.ai.validated");function D(e){return Object.defineProperty(e,Fe,{value:!0,enumerable:!1}),e}const M={ok:!1},h=e=>({ok:!0,value:e}),Ne=/^\d+(?:\.\d*)?(?:e[+-]?\d+)?$/i,_e=/^\.\d+(?:e[+-]?\d+)?$/i,ke=/^\d{1,3}(?:,\d{3})+(?:\.\d*)?$/,je=/[\p{Sc}\s]/gu;function Ge(e){let t=e.replace(je,"");if(t==="")return e.trim()===""?h(null):M;let r=!1;t.startsWith("(")&&t.endsWith(")")&&(r=!0,t=t.slice(1,-1)),(t.startsWith("-")||t.startsWith("+")||t.startsWith("\u2212"))&&(t[0]!=="+"&&(r=!r),t=t.slice(1));let n=!1;if(t.endsWith("%")&&(n=!0,t=t.slice(0,-1)),ke.test(t))t=t.split(",").join("");else if(!Ne.test(t)&&!_e.test(t))return M;let o=Number(t);return Number.isFinite(o)?(n&&(o/=100),r&&(o=-o),h(o)):M}function Te(e,t){const r=e.trim();if(r==="")return h(null);const n=ee(r);return n?h(n):M}const Ve=new Set(["true","yes","1"]),Pe=new Set(["false","no","0"]);function Re(e,t){const r=e.trim().toLowerCase();return r===""?h(null):Ve.has(r)?h(!0):Pe.has(r)?h(!1):M}function Ie(e,t){const r=e.trim();if(r==="")return h(null);if(!t||t.length===0)return M;const n=r.toLowerCase();for(const o of t){const i=typeof o=="object"?o.value:o;if(String(i).toLowerCase()===n)return h(i)}for(const o of t)if(typeof o=="object"&&o.label.toLowerCase()===n)return h(o.value);return M}const p=e=>({ok:!0,value:e}),A={ok:!1,reason:"invalidValue"},L=e=>e.ok?p(e.value):A;function C(e){return e==null||typeof e=="string"&&e.trim()===""}function De(e){return e==null?p(""):typeof e=="string"?p(e):typeof e=="number"||typeof e=="boolean"?p(String(e)):A}function Le(e){return C(e)?p(null):typeof e=="number"?Number.isFinite(e)?p(e):A:typeof e!="string"?A:L(Ge(e))}function Ce(e){return C(e)?p(null):e instanceof Date?Number.isNaN(e.getTime())?A:p(e):typeof e=="number"?Number.isFinite(e)?p(new Date(e)):A:typeof e!="string"?A:L(Te(e))}function le(e){return C(e)?p(null):typeof e=="boolean"?p(e):typeof e!="string"&&typeof e!="number"?A:L(Re(String(e)))}function qe(e,t){if(C(e))return p(null);if(typeof e!="string"&&typeof e!="number"&&typeof e!="boolean")return A;const r=t.valueOptions;return!r||r.length===0?p(e):L(Ie(String(e),r))}function We(e,t){switch(t.type){case"number":return Le(e);case"date":return Ce(e);case"boolean":return le(e);case"singleSelect":return qe(e,t);default:return De(e)}}const W=200,Ue=100;function u(e,t,r){return e.errors.length<Ue&&e.errors.push({path:t,message:r}),null}function c(e){return typeof e=="string"?JSON.stringify(e.slice(0,60)):e===null||typeof e!="object"?String(e):Array.isArray(e)?"a list":"an object"}function ae(e){return typeof e=="string"?e.trim().toLowerCase():null}function K(e){return Object.keys(e).filter(t=>t!=="__proto__")}function N(e,t,r,n,o){const i=typeof t=="string"?e.byField.get(t):void 0;return i?n(i)?i:u(e,r,`Field ${c(t)} cannot be ${o}`):u(e,r,`Unknown field ${c(t)}`)}function _(e,t,r){if(t==null)return[];const n=Array.isArray(t)?t:[t];return n.length>W&&u(e,r,`Only the first ${W} entries are read`),n.slice(0,W)}function T(e,t,r,n){const o=ae(t);return n.find(i=>i.toLowerCase()===o)??u(e,r,`${c(t)} is not one of ${n.join(", ")}`)}function Z(e,t,r,n){const o=We(t,r);if(!o.ok)return u(e,n,`${c(t)} is not a valid ${r.type??"string"} value`);const i=o.value instanceof Date?ye(o.value):o.value;return i==null||i===""?u(e,n,"Missing value"):{v:i}}function Be(e,t,r){const n=N(e,t.field,`${r}.field`,ie,"filtered");if(!n)return null;const o=T(e,t.operator,`${r}.operator`,ne(n));if(o===null)return null;const i={field:n.field,operator:o};if(te.includes(i.operator))return i;const s=S(t,"value")?t.value:void 0;if(i.operator==="isAnyOf"){const a=[];return _(e,s,`${r}.value`).forEach((f,v)=>{const g=Z(e,f,n,`${r}.value[${v}]`);g&&!a.includes(g.v)&&a.push(g.v)}),a.length===0?u(e,`${r}.value`,"No valid values"):(i.value=a,i)}if(Array.isArray(s))return u(e,`${r}.value`,"Expected one value, not a list");const l=Z(e,s,n,`${r}.value`);return l?(i.value=l.v,i):null}function ue(e,t,r){return t===void 0?null:T(e,t,r,["and","or"])}function fe(e,t,r,n){const o=[];return _(e,t,r).forEach((i,s)=>{const l=`${r}[${s}]`;if(!$(i))u(e,l,`Expected a filter, got ${c(i)}`);else if(S(i,"items")||S(i,"logicOperator")){if(n>=I){u(e,l,`Groups nest at most ${I} levels`);return}const a=fe(e,i.items,`${l}.items`,n+1);a.length===0?u(e,l,"Empty group removed"):o.push({logicOperator:ue(e,i.logicOperator,`${l}.logicOperator`)??"and",items:a})}else{const a=Be(e,i,l);a&&o.push(a)}}),o}function Xe(e,t,r){const n={};S(t,"items")&&(n.items=fe(e,t.items,`${r}.items`,0));const o=ue(e,t.logicOperator,`${r}.logicOperator`);return o&&(n.logicOperator=o),S(t,"quickFilterValues")&&(n.quickFilterValues=[],_(e,t.quickFilterValues,`${r}.quickFilterValues`).forEach((i,s)=>{const l=typeof i=="string"||typeof i=="number"?String(i).trim():null;l===null?u(e,`${r}.quickFilterValues[${s}]`,`Expected text, got ${c(i)}`):l!==""&&n.quickFilterValues?.push(l)})),n}function He(e,t,r){const n=[];return _(e,t,r).forEach((o,i)=>{const s=`${r}[${i}]`;if(!$(o))return u(e,s,`Expected { field, sort }, got ${c(o)}`);const l=N(e,o.field,`${s}.field`,oe,"sorted"),a=l&&T(e,o.sort,`${s}.sort`,["asc","desc"]);!l||!a||(n.some(f=>f.field===l.field)?u(e,s,`${c(l.field)} is sorted twice`):n.push({field:l.field,sort:a}))}),n}function B(e,t,r,n,o){const i=[];return _(e,t,r).forEach((s,l)=>{const a=N(e,s,`${r}[${l}]`,n,o);a&&!i.includes(a.field)&&i.push(a.field)}),i}const Je=e=>F(e).length>0,Ye=e=>F(e,X).length>0;function Ke(e,t,r){const n={};for(const o of K(t)){if(ae(t[o])==="none")continue;const i=N(e,o,`${r}.${o}`,Je,"aggregated"),s=i&&T(e,t[o],`${r}.${o}`,F(i));i&&s&&(n[i.field]=s)}return n}function ze(e,t,r){const n=[];return _(e,t.valueFields,`${r}.valueFields`).forEach((o,i)=>{const s=`${r}.valueFields[${i}]`;if(!$(o))return u(e,s,`Expected { field, aggFn }, got ${c(o)}`);const l=N(e,o.field,`${s}.field`,Ye,"a pivot value"),a=l&&T(e,o.aggFn,`${s}.aggFn`,F(l,X));l&&a&&!n.some(f=>f.field===l.field&&f.aggFn===a)&&n.push({field:l.field,aggFn:a})}),{rowFields:B(e,t.rowFields,`${r}.rowFields`,G,"a pivot label"),columnFields:B(e,t.columnFields,`${r}.columnFields`,G,"a pivot label"),valueFields:n}}function Qe(e,t,r){const n={};for(const o of K(t)){const i=N(e,o,`${r}.${o}`,se,"hidden"),s=le(t[o]);i&&(s.ok&&s.value!==null?n[i.field]=s.value:u(e,`${r}.${o}`,`Expected true or false, got ${c(t[o])}`))}return n}function Ze(e,t,r,n,o){t==="sort"?o.sortModel=He(e,r,n):t==="grouping"?o.rowGroupingModel=B(e,r,n,G,"grouped"):$(r)?t==="filter"?o.filterModel=Xe(e,r,n):t==="aggregation"?o.aggregationModel=Ke(e,r,n):t==="pivot"?o.pivotModel=ze(e,r,n):o.columnVisibilityModel=Qe(e,r,n):u(e,n,`Expected an object, got ${c(r)}`)}function z(e,t,r={}){const n=xe(e,t,r);return D(n.state),D(n)}function xe(e,t,r){const n={errors:[],byField:new Map},o={};try{for(const l of J(t))n.byField.set(l.field,l);let i=e;if(typeof e=="string")try{i=JSON.parse(e)}catch{return u(n,"","Not valid JSON"),{state:o,errors:n.errors}}if(!$(i))return u(n,"",`Expected an object, got ${c(i)}`),{state:o,errors:n.errors};const s=re(r);for(const l of K(i)){const a=U.find(f=>H[f]===l);l==="schemaVersion"?i[l]!==1&&u(n,l,`Unsupported schemaVersion ${c(i[l])}`):l==="message"?typeof i[l]!="string"&&u(n,l,`Expected text, got ${c(i[l])}`):a?s.includes(a)?Ze(n,a,i[l],l,o):u(n,l,"Part not allowed"):u(n,l,"Unknown part")}}catch{return u(n,"","Could not read the input"),{state:{},errors:n.errors}}return{state:o,errors:n.errors}}const k="```";function V(){return typeof DOMException=="function"?new DOMException("The operation was aborted.","AbortError"):Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function et(e){const t=e.trim();if(t.startsWith("{"))return{json:t,message:""};const r=e.indexOf(k),n=r<0?-1:e.indexOf(`
2
- `,r+k.length),o=n<0?-1:e.indexOf(k,n+1),i=o<0?"":e.slice(r+k.length,n).trim().toLowerCase();return o<0||i!==""&&i!=="json"?{json:null,message:t}:{json:e.slice(n+1,o),message:`${e.slice(0,r)}${e.slice(o+k.length)}`.trim()}}function tt(e){return e instanceof Error&&e.message?e.message:typeof e=="string"&&e?e:"Unknown error"}function ce(e,t){const r={state:D({}),errors:e};return t&&(r.message=t),D(r)}function rt(e,t,r){let n=e,o="";if(typeof e=="string"){const a=et(e);if(a.json===null)return ce([],a.message||void 0);o=a.message;try{n=JSON.parse(a.json)}catch{n=a.json}}const i=$(n)&&S(n,"message")&&typeof n.message=="string"?n.message.trim():"",s=[o,i].filter(Boolean).join(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Q=new Set;function de(e,t,r){process.env.NODE_ENV==="production"||Q.has(e)||(Q.add(e),console.warn(`[OpenGridX] ${t}.`,r))}function pe(e,t,r){const n=e[t];if(!r?.valueGetter)return{value:n};try{return{value:r.valueGetter({row:e,field:t,value:n})}}catch(o){return{value:void 0,error:o??new Error("valueGetter failed")}}}function me(e,t,r){if(!r?.valueGetter)return e[t];const{value:n,error:o}=pe(e,t,r);return o!==void 0&&de(`valueGetter:${t}`,`valueGetter for column "${t}" threw; the value is read as undefined`,o),n}const ge=/^(\d{4})-(\d{2})-(\d{2})$/;function ee(e){if(e==null)return null;let t;if(e instanceof Date)t=e;else if(typeof e=="number")t=new Date(e);else if(typeof e=="string"){const r=e.trim();if(r==="")return null;const n=ge.exec(r);if(n){const o=Number(n[1]),i=Number(n[2])-1,s=Number(n[3]);if(t=new Date(o,i,s),t.getMonth()!==i||t.getDate()!==s)return null}else{if(!$e(r))return null;t=new Date(r)}}else return null;return Number.isNaN(t.getTime())?null:t}const ye=["january","february","march","april","may","june","july","august","september","october","november","december","monday","tuesday","wednesday","thursday","friday","saturday","sunday"],be=new Set(["t","z","am","pm","gmt","utc","sept"]);function he(e){return be.has(e)?!0:e.length>=3&&ye.some(t=>t.startsWith(e))}function $e(e){let t="";for(let r=0;r<=e.length;r++){const n=r<e.length?e[r].toLowerCase():"";if(n>="a"&&n<="z"){t+=n;continue}if(t!==""&&!he(t))return!1;t=""}return!0}function Ae(e){const t=ee(e);if(!t)return"";const r=String(t.getFullYear()).padStart(4,"0"),n=String(t.getMonth()+1).padStart(2,"0"),o=String(t.getDate()).padStart(2,"0");return`${r}-${n}-${o}`}function Se(e){switch(e){case"number":return["=","!=",">",">=","<","<=","isEmpty","isNotEmpty"];case"date":return["is","not","after","onOrAfter","before","onOrBefore","isEmpty","isNotEmpty"];case"boolean":return["is"];case"singleSelect":return["isAnyOf","is","not"];default:return["contains","equals","startsWith","endsWith","isEmpty","isNotEmpty"]}}const Oe=["sum","avg","count","min","max","unique"],X=["sum","avg","count","min","max"],te=["isEmpty","isNotEmpty"],R=3,U=["filter","sort","grouping","aggregation","pivot","columnVisibility"],H={filter:"filterModel",sort:"sortModel",grouping:"rowGroupingModel",aggregation:"aggregationModel",pivot:"pivotModel",columnVisibility:"columnVisibilityModel"};function S(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function $(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function re(e){const t=Array.isArray(e?.include)?e.include:U,r=Array.isArray(e?.exclude)?e.exclude:[];return U.filter(n=>t.includes(n)&&!r.includes(n))}function J(e){if(!Array.isArray(e))return[];const t=new Set,r=[];for(const n of e){if(!$(n))continue;const o=n.field;typeof o!="string"||o===""||o.startsWith("__")||n.isSpacer===!0||t.has(o)||(t.add(o),r.push(n))}return r}function ne(e){return Se(e.type)}const ie=e=>e.filterable!==!1,oe=e=>e.sortable!==!1,T=e=>e.groupable!==!1,se=e=>e.hideable!==!1;function N(e,t=Oe){if(e.aggregable===!1)return[];const r=e.type==="number"||e.aggregable===!0?t:t.filter(o=>o==="count"),n=e.availableAggregationFunctions;return Array.isArray(n)?r.filter(o=>n.includes(o)):[...r]}function ve(e){const t=[];if(!Array.isArray(e.valueOptions))return t;for(const r of e.valueOptions){const n=r!==null&&typeof r=="object"?r.value:r;(typeof n=="string"||typeof n=="number"&&Number.isFinite(n))&&!t.includes(n)&&t.push(n)}return t}const Ee="OpenGridX grid state",Me=10;function k(e){const t=typeof e.headerName=="string"&&e.headerName!==""?e.headerName:e.field,r=typeof e.description=="string"&&e.description!==""?` (${e.description})`:"";return`${t}${r}`}function O(e,t,r){return r.descriptions?{...e,description:t}:e}function we(e,t){return!t.examples||!Array.isArray(e.aiExamples)?[]:e.aiExamples.filter(r=>typeof r=="string"||typeof r=="boolean"||typeof r=="number"&&Number.isFinite(r)).slice(0,Me)}function Ne(e,t){let r;switch(e.type){case"number":r={type:"number"};break;case"date":r={type:"string",format:"date"};break;case"boolean":r={type:"boolean"};break;case"singleSelect":{const o=ve(e),i=o.length>0?{enum:o}:{type:"string"};r={anyOf:[i,{type:"array",items:i}]};break}default:r={type:"string"}}const n=we(e,t);return n.length>0?{...r,examples:n}:r}function _e(e,t){const r=ne(e),n=r.filter(s=>te.includes(s)),o=e.type==="singleSelect"?"; isAnyOf takes an array":"",i=n.length>0?`${n.join(" and ")} take no value${o}`:o.slice(2);return O({type:"object",properties:{field:{const:e.field},operator:{enum:r},value:Ne(e,t)},required:["field","operator"],additionalProperties:!1},i?`${k(e)}: ${i}`:k(e),t)}function Fe(e,t,r){const n=e.filter(ie),o={},i={enum:["and","or"]};if(n.length>0){r.filterItem={oneOf:n.map(s=>_e(s,t))};for(let s=R;s>=1;s--){const l=s===R?{$ref:"#/$defs/filterItem"}:{anyOf:[{$ref:"#/$defs/filterItem"},{$ref:`#/$defs/filterGroup${s+1}`}]};r[`filterGroup${s}`]={type:"object",properties:{logicOperator:i,items:{type:"array",items:l}},required:["logicOperator","items"],additionalProperties:!1}}o.items={type:"array",items:{anyOf:[{$ref:"#/$defs/filterItem"},{$ref:"#/$defs/filterGroup1"}]}},o.logicOperator=i}return o.quickFilterValues=O({type:"array",items:{type:"string"}},"Words a row must contain, in any column",t),{type:"object",properties:o,additionalProperties:!1}}function q(e){return{enum:e.map(t=>t.field)}}function je(e,t,r,n){switch(e){case"filter":return Fe(t,r,n);case"sort":{const o=t.filter(oe);return o.length===0?null:O({type:"array",items:{type:"object",properties:{field:q(o),sort:{enum:["asc","desc"]}},required:["field","sort"],additionalProperties:!1}},"Most significant first",r)}case"grouping":{const o=t.filter(T);return o.length===0?null:O({type:"array",items:q(o),uniqueItems:!0},"Outermost first",r)}case"aggregation":{const o={};for(const i of t){const s=N(i);s.length>0&&(o[i.field]=O({enum:s},k(i),r))}return Object.keys(o).length===0?null:{type:"object",properties:o,additionalProperties:!1}}case"pivot":{const o=t.filter(T),i=t.map(l=>({col:l,fns:N(l,X)})).filter(l=>l.fns.length>0).map(({col:l,fns:a})=>O({type:"object",properties:{field:{const:l.field},aggFn:{enum:a}},required:["field","aggFn"],additionalProperties:!1},k(l),r));if(o.length===0||i.length===0)return null;const s={type:"array",items:q(o),uniqueItems:!0};return{type:"object",properties:{rowFields:s,columnFields:s,valueFields:{type:"array",items:{oneOf:i}}},required:["rowFields","columnFields","valueFields"],additionalProperties:!1}}case"columnVisibility":{const o={};for(const i of t.filter(se))o[i.field]=O({type:"boolean"},k(i),r);return Object.keys(o).length===0?null:O({type:"object",properties:o,additionalProperties:!1},"false hides a column",r)}}}function Y(e,t={}){const r={descriptions:t.descriptions!==!1,examples:t.examples!==!1},n=J(e),o={},i={};for(const l of re(t)){const a=je(l,n,r,o);a&&(i[H[l]]=a)}const s={$schema:"https://json-schema.org/draft/2020-12/schema",schemaVersion:1,title:Ee,type:"object",properties:i,additionalProperties:!1};return r.descriptions&&(s.description="Grid state to apply. Include only the parts the user asked to change."),Object.keys(o).length>0&&(s.$defs=o),s}const ke=Symbol.for("opengridx.ai.validated");function I(e){return Object.defineProperty(e,ke,{value:!0,enumerable:!1}),e}const E={ok:!1},h=e=>({ok:!0,value:e}),Te=/^\d+(?:\.\d*)?(?:e[+-]?\d+)?$/i,Ge=/^\.\d+(?:e[+-]?\d+)?$/i,Ve=/^\d{1,3}(?:,\d{3})+(?:\.\d*)?$/,De=/[\p{Sc}\s]/gu;function Pe(e){let t=e.replace(De,"");if(t==="")return e.trim()===""?h(null):E;let r=!1;t.startsWith("(")&&t.endsWith(")")&&(r=!0,t=t.slice(1,-1)),(t.startsWith("-")||t.startsWith("+")||t.startsWith("\u2212"))&&(t[0]!=="+"&&(r=!r),t=t.slice(1));let n=!1;if(t.endsWith("%")&&(n=!0,t=t.slice(0,-1)),Ve.test(t))t=t.split(",").join("");else if(!Te.test(t)&&!Ge.test(t))return E;let o=Number(t);return Number.isFinite(o)?(n&&(o/=100),r&&(o=-o),h(o)):E}function Re(e,t){const r=e.trim();if(r==="")return h(null);const n=ee(r);return n?h(n):E}const Ie=new Set(["true","yes","1"]),Le=new Set(["false","no","0"]);function Ce(e,t){const r=e.trim().toLowerCase();return r===""?h(null):Ie.has(r)?h(!0):Le.has(r)?h(!1):E}function qe(e,t){const r=e.trim();if(r==="")return h(null);if(!t||t.length===0)return E;const n=r.toLowerCase();for(const o of t){const i=typeof o=="object"?o.value:o;if(String(i).toLowerCase()===n)return h(i)}for(const o of t)if(typeof o=="object"&&o.label.toLowerCase()===n)return h(o.value);return E}const p=e=>({ok:!0,value:e}),A={ok:!1,reason:"invalidValue"},L=e=>e.ok?p(e.value):A;function C(e){return e==null||typeof e=="string"&&e.trim()===""}function We(e){return e==null?p(""):typeof e=="string"?p(e):typeof e=="number"||typeof e=="boolean"?p(String(e)):A}function Ue(e){return C(e)?p(null):typeof e=="number"?Number.isFinite(e)?p(e):A:typeof e!="string"?A:L(Pe(e))}function Be(e){return C(e)?p(null):e instanceof Date?Number.isNaN(e.getTime())?A:p(e):typeof e=="number"?Number.isFinite(e)?p(new Date(e)):A:typeof e!="string"?A:L(Re(e))}function le(e){return C(e)?p(null):typeof e=="boolean"?p(e):typeof e!="string"&&typeof e!="number"?A:L(Ce(String(e)))}function Xe(e,t){if(C(e))return p(null);if(typeof e!="string"&&typeof e!="number"&&typeof e!="boolean")return A;const r=t.valueOptions;return!r||r.length===0?p(e):L(qe(String(e),r))}function He(e,t){switch(t.type){case"number":return Ue(e);case"date":return Be(e);case"boolean":return le(e);case"singleSelect":return Xe(e,t);default:return We(e)}}const W=200,Je=100;function u(e,t,r){return e.errors.length<Je&&e.errors.push({path:t,message:r}),null}function c(e){return typeof e=="string"?JSON.stringify(e.slice(0,60)):e===null||typeof e!="object"?String(e):Array.isArray(e)?"a list":"an object"}function ae(e){return typeof e=="string"?e.trim().toLowerCase():null}function z(e){return Object.keys(e).filter(t=>t!=="__proto__")}function _(e,t,r,n,o){const i=typeof t=="string"?e.byField.get(t):void 0;return i?n(i)?i:u(e,r,`Field ${c(t)} cannot be ${o}`):u(e,r,`Unknown field ${c(t)}`)}function F(e,t,r){if(t==null)return[];const n=Array.isArray(t)?t:[t];return n.length>W&&u(e,r,`Only the first ${W} entries are read`),n.slice(0,W)}function G(e,t,r,n){const o=ae(t);return n.find(i=>i.toLowerCase()===o)??u(e,r,`${c(t)} is not one of ${n.join(", ")}`)}function Z(e,t,r,n){const o=He(t,r);if(!o.ok)return u(e,n,`${c(t)} is not a valid ${r.type??"string"} value`);const i=o.value instanceof Date?Ae(o.value):o.value;return i==null||i===""?u(e,n,"Missing value"):{v:i}}function Ye(e,t,r){const n=_(e,t.field,`${r}.field`,ie,"filtered");if(!n)return null;const o=G(e,t.operator,`${r}.operator`,ne(n));if(o===null)return null;const i={field:n.field,operator:o};if(te.includes(i.operator))return i;const s=S(t,"value")?t.value:void 0;if(i.operator==="isAnyOf"){const a=[];return F(e,s,`${r}.value`).forEach((f,v)=>{const g=Z(e,f,n,`${r}.value[${v}]`);g&&!a.includes(g.v)&&a.push(g.v)}),a.length===0?u(e,`${r}.value`,"No valid values"):(i.value=a,i)}if(Array.isArray(s))return u(e,`${r}.value`,"Expected one value, not a list");const l=Z(e,s,n,`${r}.value`);return l?(i.value=l.v,i):null}function ue(e,t,r){return t===void 0?null:G(e,t,r,["and","or"])}function fe(e,t,r,n){const o=[];return F(e,t,r).forEach((i,s)=>{const l=`${r}[${s}]`;if(!$(i))u(e,l,`Expected a filter, got ${c(i)}`);else if(S(i,"items")||S(i,"logicOperator")){if(n>=R){u(e,l,`Groups nest at most ${R} levels`);return}const a=fe(e,i.items,`${l}.items`,n+1);a.length===0?u(e,l,"Empty group removed"):o.push({logicOperator:ue(e,i.logicOperator,`${l}.logicOperator`)??"and",items:a})}else{const a=Ye(e,i,l);a&&o.push(a)}}),o}function ze(e,t,r){const n={};S(t,"items")&&(n.items=fe(e,t.items,`${r}.items`,0));const o=ue(e,t.logicOperator,`${r}.logicOperator`);return o&&(n.logicOperator=o),S(t,"quickFilterValues")&&(n.quickFilterValues=[],F(e,t.quickFilterValues,`${r}.quickFilterValues`).forEach((i,s)=>{const l=typeof i=="string"||typeof i=="number"?String(i).trim():null;l===null?u(e,`${r}.quickFilterValues[${s}]`,`Expected text, got ${c(i)}`):l!==""&&n.quickFilterValues?.push(l)})),n}function Ke(e,t,r){const n=[];return F(e,t,r).forEach((o,i)=>{const s=`${r}[${i}]`;if(!$(o))return u(e,s,`Expected { field, sort }, got ${c(o)}`);const l=_(e,o.field,`${s}.field`,oe,"sorted"),a=l&&G(e,o.sort,`${s}.sort`,["asc","desc"]);!l||!a||(n.some(f=>f.field===l.field)?u(e,s,`${c(l.field)} is sorted twice`):n.push({field:l.field,sort:a}))}),n}function B(e,t,r,n,o){const i=[];return F(e,t,r).forEach((s,l)=>{const a=_(e,s,`${r}[${l}]`,n,o);a&&!i.includes(a.field)&&i.push(a.field)}),i}const Qe=e=>N(e).length>0,Ze=e=>N(e,X).length>0;function xe(e,t,r){const n={};for(const o of z(t)){if(ae(t[o])==="none")continue;const i=_(e,o,`${r}.${o}`,Qe,"aggregated"),s=i&&G(e,t[o],`${r}.${o}`,N(i));i&&s&&(n[i.field]=s)}return n}function et(e,t,r){const n=[];return F(e,t.valueFields,`${r}.valueFields`).forEach((o,i)=>{const s=`${r}.valueFields[${i}]`;if(!$(o))return u(e,s,`Expected { field, aggFn }, got ${c(o)}`);const l=_(e,o.field,`${s}.field`,Ze,"a pivot value"),a=l&&G(e,o.aggFn,`${s}.aggFn`,N(l,X));l&&a&&!n.some(f=>f.field===l.field&&f.aggFn===a)&&n.push({field:l.field,aggFn:a})}),{rowFields:B(e,t.rowFields,`${r}.rowFields`,T,"a pivot label"),columnFields:B(e,t.columnFields,`${r}.columnFields`,T,"a pivot label"),valueFields:n}}function tt(e,t,r){const n={};for(const o of z(t)){const i=_(e,o,`${r}.${o}`,se,"hidden"),s=le(t[o]);i&&(s.ok&&s.value!==null?n[i.field]=s.value:u(e,`${r}.${o}`,`Expected true or false, got ${c(t[o])}`))}return n}function rt(e,t,r,n,o){t==="sort"?o.sortModel=Ke(e,r,n):t==="grouping"?o.rowGroupingModel=B(e,r,n,T,"grouped"):$(r)?t==="filter"?o.filterModel=ze(e,r,n):t==="aggregation"?o.aggregationModel=xe(e,r,n):t==="pivot"?o.pivotModel=et(e,r,n):o.columnVisibilityModel=tt(e,r,n):u(e,n,`Expected an object, got ${c(r)}`)}function K(e,t,r={}){const n=nt(e,t,r);return I(n.state),I(n)}function nt(e,t,r){const n={errors:[],byField:new Map},o={};try{for(const l of J(t))n.byField.set(l.field,l);let i=e;if(typeof e=="string")try{i=JSON.parse(e)}catch{return u(n,"","Not valid JSON"),{state:o,errors:n.errors}}if(!$(i))return u(n,"",`Expected an object, got ${c(i)}`),{state:o,errors:n.errors};const s=re(r);for(const l of z(i)){const a=U.find(f=>H[f]===l);l==="schemaVersion"?i[l]!==1&&u(n,l,`Unsupported schemaVersion ${c(i[l])}`):l==="message"?typeof i[l]!="string"&&u(n,l,`Expected text, got ${c(i[l])}`):a?s.includes(a)?rt(n,a,i[l],l,o):u(n,l,"Part not allowed"):u(n,l,"Unknown part")}}catch{return u(n,"","Could not read the input"),{state:{},errors:n.errors}}return{state:o,errors:n.errors}}const j="```";function V(){return typeof DOMException=="function"?new DOMException("The operation was aborted.","AbortError"):Object.assign(new Error("The operation was aborted."),{name:"AbortError"})}function it(e){const t=e.trim();if(t.startsWith("{"))return{json:t,message:""};const r=e.indexOf(j),n=r<0?-1:e.indexOf(`
2
+ `,r+j.length),o=n<0?-1:e.indexOf(j,n+1),i=o<0?"":e.slice(r+j.length,n).trim().toLowerCase();return o<0||i!==""&&i!=="json"?{json:null,message:t}:{json:e.slice(n+1,o),message:`${e.slice(0,r)}${e.slice(o+j.length)}`.trim()}}function ot(e){return e instanceof Error&&e.message?e.message:typeof e=="string"&&e?e:"Unknown error"}function ce(e,t){const r={state:I({}),errors:e};return t&&(r.message=t),I(r)}function st(e,t,r){let n=e,o="";if(typeof e=="string"){const a=it(e);if(a.json===null)return ce([],a.message||void 0);o=a.message;try{n=JSON.parse(a.json)}catch{n=a.json}}const i=$(n)&&S(n,"message")&&typeof n.message=="string"?n.message.trim():"",s=[o,i].filter(Boolean).join(`
3
3
 
4
- `),l=z(n,t,r);return s&&(l.message=s),l}function nt(e){const{columns:t,callModel:r,parts:n,schemaOptions:o={}}=e,i={include:n??o.include,exclude:o.exclude},s=Y(t,{...o,...i});return async(l,a)=>{const f=a?.signal??new AbortController().signal;if(f.aborted)throw V();const v=new Promise((m,y)=>{f.addEventListener("abort",()=>y(V()),{once:!0})});v.catch(()=>{});let g;try{const m={prompt:String(l),schema:s,currentState:a?.currentState??{},history:Array.isArray(a?.history)?a.history:[]};g=await Promise.race([r(m,{signal:f}),v])}catch(m){if(f.aborted)throw V();return ce([{path:"",message:`The model call failed: ${tt(m)}`}])}if(f.aborted)throw V();return rt(g,t,i)}}const it=20,ot=1e3,st=[{name:"set_filter",part:"filter",description:"Replace the filter model of the grid (filters and quick-filter words)."},{name:"set_sort",part:"sort",description:"Replace the sort model of the grid, most significant field first. An empty list clears sorting."},{name:"set_grouping",part:"grouping",description:"Group the rows by these fields, outermost first. An empty list removes grouping."},{name:"set_aggregation",part:"aggregation",description:"Replace the summaries: field to aggregation function. An empty object removes them."},{name:"set_column_visibility",part:"columnVisibility",description:"Show (true) or hide (false) columns. Columns not listed keep their visibility."}];function w(e,t=""){return{ok:!1,errors:[{path:t,message:e}]}}async function P(e){try{return e()}catch(t){return w(t instanceof Error&&t.message?t.message:"The tool failed")}}function R(e){const t=e?.current;return t&&typeof t.getGridAiState=="function"?t:null}function lt(e){return e instanceof Date?Number.isNaN(e.getTime())?null:e.toISOString():typeof e=="number"?Number.isFinite(e)?e:null:typeof e=="string"||typeof e=="boolean"?e:null}function at(e,t,r,n,o){const i=H[n],s=Y(t,{include:[n]});if(!S(s.properties,i))return null;const{$schema:l,schemaVersion:a,title:f,description:v,...g}=s;return{name:r,description:o,inputSchema:{...g,required:[i]},execute:m=>P(()=>{const y=R(e);if(!y)return w("The grid is not ready");if(!$(m)||!S(m,i))return w(`Expected an object with "${i}"`,i);const{state:d,errors:E}=z({[i]:m[i]},t,{include:[n]});if(E.length>0)return{ok:!1,errors:E};const b={};return d.filterModel&&y.setFilterModel(b.filterModel=d.filterModel),d.sortModel&&y.setSortModel(b.sortModel=d.sortModel),d.rowGroupingModel&&y.setRowGroupingModel(b.rowGroupingModel=d.rowGroupingModel),d.aggregationModel&&y.setAggregationModel(b.aggregationModel=d.aggregationModel),d.columnVisibilityModel&&(b.columnVisibilityModel={...y.getGridAiState().columnVisibilityModel,...d.columnVisibilityModel},y.setColumnVisibilityModel(b.columnVisibilityModel)),{ok:!0,applied:b}})}}const x={type:"object",properties:{},additionalProperties:!1};function ut(e,t,r={}){const n=J(t),o=[{name:"get_grid_state",description:"Read the current filter, sort, grouping, aggregation, pivot and column visibility of the grid, and its columns.",inputSchema:x,execute:()=>P(()=>{const i=R(e);return i?{ok:!0,state:i.getGridAiState(),columns:n.map(s=>({field:s.field,headerName:typeof s.headerName=="string"?s.headerName:s.field,type:typeof s.type=="string"?s.type:"string"}))}:w("The grid is not ready")})}];for(const{name:i,part:s,description:l}of st){const a=at(e,n,i,s,l);a&&o.push(a)}if(o.push({name:"clear_filters",description:"Remove every filter and the quick-filter words.",inputSchema:x,execute:()=>P(()=>{const i=R(e);if(!i)return w("The grid is not ready");const s={items:[]};return i.setFilterModel(s),{ok:!0,applied:{filterModel:s}}})}),r.allowRowAccess===!0){const i=typeof r.maxRows=="number"&&r.maxRows>=1?Math.min(Math.floor(r.maxRows),ot):it,s=Array.isArray(r.fields)?n.filter(l=>r.fields?.includes(l.field)):n;o.push({name:"get_row_summary",description:`Count the rows that pass the current filter and read the first ones (at most ${i}, fields: ${s.map(l=>l.field).join(", ")}).`,inputSchema:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:i}},additionalProperties:!1},execute:l=>P(()=>{const a=R(e);if(!a)return w("The grid is not ready");const f=$(l)&&S(l,"limit")?l.limit:i,v=typeof f=="number"&&f>=1?Math.min(Math.floor(f),i):i,g=a.getAllFilteredRows(),m=Array.isArray(g)?g:[],y=m.slice(0,v).map(d=>{const E={};if(!$(d))return E;for(const b of s)E[b.field]=lt(ge(d,b.field,b));return E});return{ok:!0,rowCount:m.length,rows:y}})})}return o}exports.createGridAgentTools=ut,exports.createGridAiPromptHandler=nt,exports.getGridAiSchema=Y,exports.validateGridAiState=z;
4
+ `),l=K(n,t,r);return s&&(l.message=s),l}function lt(e){const{columns:t,callModel:r,parts:n,schemaOptions:o={}}=e,i={include:n??o.include,exclude:o.exclude},s=Y(t,{...o,...i});return async(l,a)=>{const f=a?.signal??new AbortController().signal;if(f.aborted)throw V();const v=new Promise((m,y)=>{f.addEventListener("abort",()=>y(V()),{once:!0})});v.catch(()=>{});let g;try{const m={prompt:String(l),schema:s,currentState:a?.currentState??{},history:Array.isArray(a?.history)?a.history:[]};g=await Promise.race([r(m,{signal:f}),v])}catch(m){if(f.aborted)throw V();return ce([{path:"",message:`The model call failed: ${ot(m)}`}])}if(f.aborted)throw V();return st(g,t,i)}}const at=20,ut=1e3,ft=[{name:"set_filter",part:"filter",description:"Replace the filter model of the grid (filters and quick-filter words)."},{name:"set_sort",part:"sort",description:"Replace the sort model of the grid, most significant field first. An empty list clears sorting."},{name:"set_grouping",part:"grouping",description:"Group the rows by these fields, outermost first. An empty list removes grouping."},{name:"set_aggregation",part:"aggregation",description:"Replace the summaries: field to aggregation function. An empty object removes them."},{name:"set_column_visibility",part:"columnVisibility",description:"Show (true) or hide (false) columns. Columns not listed keep their visibility."}];function w(e,t=""){return{ok:!1,errors:[{path:t,message:e}]}}async function D(e){try{return e()}catch(t){return w(t instanceof Error&&t.message?t.message:"The tool failed")}}function P(e){const t=e?.current;return t&&typeof t.getGridAiState=="function"?t:null}function ct(e){return e instanceof Date?Number.isNaN(e.getTime())?null:e.toISOString():typeof e=="number"?Number.isFinite(e)?e:null:typeof e=="string"||typeof e=="boolean"?e:null}function dt(e,t,r,n,o){const i=H[n],s=Y(t,{include:[n]});if(!S(s.properties,i))return null;const{$schema:l,schemaVersion:a,title:f,description:v,...g}=s;return{name:r,description:o,inputSchema:{...g,required:[i]},execute:m=>D(()=>{const y=P(e);if(!y)return w("The grid is not ready");if(!$(m)||!S(m,i))return w(`Expected an object with "${i}"`,i);const{state:d,errors:M}=K({[i]:m[i]},t,{include:[n]});if(M.length>0)return{ok:!1,errors:M};const b={};return d.filterModel&&y.setFilterModel(b.filterModel=d.filterModel),d.sortModel&&y.setSortModel(b.sortModel=d.sortModel),d.rowGroupingModel&&y.setRowGroupingModel(b.rowGroupingModel=d.rowGroupingModel),d.aggregationModel&&y.setAggregationModel(b.aggregationModel=d.aggregationModel),d.columnVisibilityModel&&(b.columnVisibilityModel={...y.getGridAiState().columnVisibilityModel,...d.columnVisibilityModel},y.setColumnVisibilityModel(b.columnVisibilityModel)),{ok:!0,applied:b}})}}const x={type:"object",properties:{},additionalProperties:!1};function pt(e,t,r={}){const n=J(t),o=[{name:"get_grid_state",description:"Read the current filter, sort, grouping, aggregation, pivot and column visibility of the grid, and its columns.",inputSchema:x,execute:()=>D(()=>{const i=P(e);return i?{ok:!0,state:i.getGridAiState(),columns:n.map(s=>({field:s.field,headerName:typeof s.headerName=="string"?s.headerName:s.field,type:typeof s.type=="string"?s.type:"string"}))}:w("The grid is not ready")})}];for(const{name:i,part:s,description:l}of ft){const a=dt(e,n,i,s,l);a&&o.push(a)}if(o.push({name:"clear_filters",description:"Remove every filter and the quick-filter words.",inputSchema:x,execute:()=>D(()=>{const i=P(e);if(!i)return w("The grid is not ready");const s={items:[]};return i.setFilterModel(s),{ok:!0,applied:{filterModel:s}}})}),r.allowRowAccess===!0){const i=typeof r.maxRows=="number"&&r.maxRows>=1?Math.min(Math.floor(r.maxRows),ut):at,s=Array.isArray(r.fields)?n.filter(l=>r.fields?.includes(l.field)):n;o.push({name:"get_row_summary",description:`Count the rows that pass the current filter and read the first ones (at most ${i}, fields: ${s.map(l=>l.field).join(", ")}).`,inputSchema:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:i}},additionalProperties:!1},execute:l=>D(()=>{const a=P(e);if(!a)return w("The grid is not ready");const f=$(l)&&S(l,"limit")?l.limit:i,v=typeof f=="number"&&f>=1?Math.min(Math.floor(f),i):i,g=a.getAllFilteredRows(),m=Array.isArray(g)?g:[],y=m.slice(0,v).map(d=>{const M={};if(!$(d))return M;for(const b of s)M[b.field]=ct(me(d,b.field,b));return M});return{ok:!0,rowCount:m.length,rows:y}})})}return o}exports.createGridAgentTools=pt,exports.createGridAiPromptHandler=lt,exports.getGridAiSchema=Y,exports.validateGridAiState=K;