apex-grid 3.5.0 → 4.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +573 -0
- package/LICENSE.md +125 -0
- package/README.md +143 -23
- package/components/cell.d.ts +43 -5
- package/components/cell.js +225 -64
- package/components/cell.js.map +1 -1
- package/components/filter-row.d.ts +2 -0
- package/components/filter-row.js +82 -28
- package/components/filter-row.js.map +1 -1
- package/components/grid.d.ts +281 -49
- package/components/grid.js +600 -159
- package/components/grid.js.map +1 -1
- package/components/group-header-row.js +28 -25
- package/components/group-header-row.js.map +1 -1
- package/components/header-row.d.ts +6 -10
- package/components/header-row.js +12 -28
- package/components/header-row.js.map +1 -1
- package/components/header.js +71 -22
- package/components/header.js.map +1 -1
- package/components/paginator.d.ts +20 -5
- package/components/paginator.js +54 -17
- package/components/paginator.js.map +1 -1
- package/components/row.d.ts +19 -3
- package/components/row.js +211 -56
- package/components/row.js.map +1 -1
- package/components/toolbar.d.ts +5 -1
- package/components/toolbar.js +6 -2
- package/components/toolbar.js.map +1 -1
- package/components/virtualize-rows.d.ts +38 -0
- package/components/virtualize-rows.js +286 -0
- package/components/virtualize-rows.js.map +1 -0
- package/components/virtualizer.d.ts +111 -1
- package/components/virtualizer.js +192 -5
- package/components/virtualizer.js.map +1 -1
- package/controllers/dom.d.ts +14 -7
- package/controllers/dom.js +45 -27
- package/controllers/dom.js.map +1 -1
- package/controllers/editing.d.ts +104 -37
- package/controllers/editing.js +230 -78
- package/controllers/editing.js.map +1 -1
- package/controllers/expansion.d.ts +14 -5
- package/controllers/expansion.js +24 -1
- package/controllers/expansion.js.map +1 -1
- package/controllers/filter.d.ts +10 -2
- package/controllers/filter.js +62 -17
- package/controllers/filter.js.map +1 -1
- package/controllers/history.d.ts +45 -8
- package/controllers/history.js +58 -20
- package/controllers/history.js.map +1 -1
- package/controllers/navigation.d.ts +130 -13
- package/controllers/navigation.js +474 -60
- package/controllers/navigation.js.map +1 -1
- package/controllers/pagination.d.ts +13 -6
- package/controllers/pagination.js +29 -22
- package/controllers/pagination.js.map +1 -1
- package/controllers/reorder.js +38 -22
- package/controllers/reorder.js.map +1 -1
- package/controllers/resize.d.ts +17 -2
- package/controllers/resize.js +16 -6
- package/controllers/resize.js.map +1 -1
- package/controllers/row-pin.d.ts +26 -2
- package/controllers/row-pin.js +24 -11
- package/controllers/row-pin.js.map +1 -1
- package/controllers/row-reorder.d.ts +40 -12
- package/controllers/row-reorder.js +137 -43
- package/controllers/row-reorder.js.map +1 -1
- package/controllers/selection.d.ts +33 -4
- package/controllers/selection.js +49 -11
- package/controllers/selection.js.map +1 -1
- package/controllers/sort.d.ts +22 -2
- package/controllers/sort.js +30 -25
- package/controllers/sort.js.map +1 -1
- package/controllers/state.d.ts +74 -7
- package/controllers/state.js +117 -36
- package/controllers/state.js.map +1 -1
- package/controllers/tree.d.ts +15 -10
- package/controllers/tree.js +0 -0
- package/controllers/tree.js.map +1 -1
- package/custom-elements.json +5091 -1023
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/highlight.css +15 -8
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/ApexGrid.html +233 -87
- package/docs/classes/ApexGridPaginator.html +39 -8
- package/docs/classes/ApexGridToolbar.html +11 -7
- package/docs/functions/localize.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +159 -26
- package/docs/interfaces/ApexCellValidationFailedEvent.html +3 -2
- package/docs/interfaces/ApexCellValueChangedEvent.html +4 -2
- package/docs/interfaces/ApexCellValueChangingEvent.html +3 -2
- package/docs/interfaces/ApexGridEventMap.html +5 -2
- package/docs/interfaces/ApexPageChangedEvent.html +3 -1
- package/docs/interfaces/ApexRowEditEndedEvent.html +2 -1
- package/docs/interfaces/ApexRowEditStartedEvent.html +2 -1
- package/docs/interfaces/ApexRowMovingEvent.html +9 -3
- package/docs/interfaces/ApexRowPinningEvent.html +1 -1
- package/docs/interfaces/ApexTreeRowExpandedEvent.html +4 -1
- package/docs/interfaces/ApexTreeRowExpandingEvent.html +4 -1
- package/docs/interfaces/BaseApexCellContext.html +18 -5
- package/docs/interfaces/BaseApexEditorContext.html +20 -5
- package/docs/interfaces/BaseFilterExpression.html +3 -3
- package/docs/interfaces/CSVExportOptions.html +12 -4
- package/docs/interfaces/DataPipelineConfiguration.html +4 -9
- package/docs/interfaces/ExportOptions.html +5 -3
- package/docs/interfaces/GridExpansionConfiguration.html +6 -2
- package/docs/interfaces/GridRowReorderingConfiguration.html +1 -1
- package/docs/interfaces/GridSelectionConfiguration.html +19 -4
- package/docs/interfaces/PaginationConfiguration.html +11 -4
- package/docs/interfaces/PaginationState.html +4 -2
- package/docs/interfaces/SetStateResult.html +3 -2
- package/docs/interfaces/ValidatorContext.html +7 -2
- package/docs/media/_token-values.scss +118 -0
- package/docs/media/package.json +9 -5
- package/docs/modules.html +1 -1
- package/docs/types/DataPipelineParams.html +2 -2
- package/docs/types/ExportSource.html +6 -4
- package/docs/types/OperandKeys.html +9 -0
- package/docs/types/PaginationMode.html +5 -4
- package/docs/variables/EN_LOCALE.html +2 -2
- package/i18n/en.d.ts +7 -0
- package/i18n/en.js +7 -0
- package/i18n/en.js.map +1 -1
- package/i18n/es.js +7 -0
- package/i18n/es.js.map +1 -1
- package/internal/column-types.d.ts +38 -2
- package/internal/column-types.js +83 -55
- package/internal/column-types.js.map +1 -1
- package/internal/constants.d.ts +1 -2
- package/internal/constants.js +0 -4
- package/internal/constants.js.map +1 -1
- package/internal/document-styles.d.ts +30 -0
- package/internal/document-styles.js +48 -0
- package/internal/document-styles.js.map +1 -0
- package/internal/export.d.ts +45 -7
- package/internal/export.js +39 -34
- package/internal/export.js.map +1 -1
- package/internal/feature-module.d.ts +67 -3
- package/internal/feature-module.js +6 -0
- package/internal/feature-module.js.map +1 -1
- package/internal/flip.d.ts +28 -16
- package/internal/flip.js +42 -10
- package/internal/flip.js.map +1 -1
- package/internal/index.d.ts +7 -5
- package/internal/index.js +6 -4
- package/internal/index.js.map +1 -1
- package/internal/normalize-case.d.ts +8 -1
- package/internal/normalize-case.js +3 -2
- package/internal/normalize-case.js.map +1 -1
- package/internal/state-snapshot.d.ts +60 -8
- package/internal/state-snapshot.js +87 -19
- package/internal/state-snapshot.js.map +1 -1
- package/internal/types.d.ts +92 -21
- package/internal/types.js.map +1 -1
- package/internal/utils.d.ts +34 -6
- package/internal/utils.js +30 -21
- package/internal/utils.js.map +1 -1
- package/internal/validators.js +1 -0
- package/internal/validators.js.map +1 -1
- package/operations/filter/operands/number.js +9 -6
- package/operations/filter/operands/number.js.map +1 -1
- package/operations/filter/operands/string.js +2 -3
- package/operations/filter/operands/string.js.map +1 -1
- package/operations/filter/types.d.ts +14 -2
- package/operations/filter/types.js.map +1 -1
- package/operations/filter.d.ts +6 -0
- package/operations/filter.js +23 -7
- package/operations/filter.js.map +1 -1
- package/operations/quick-filter.js +2 -5
- package/operations/quick-filter.js.map +1 -1
- package/operations/sort.d.ts +21 -2
- package/operations/sort.js +41 -14
- package/operations/sort.js.map +1 -1
- package/package.json +9 -4
- package/setup.d.ts +11 -0
- package/setup.js +9 -19
- package/setup.js.map +1 -1
- package/styles/_token-values.css.d.ts +1 -0
- package/styles/_token-values.css.js +3 -0
- package/styles/_token-values.css.js.map +1 -0
- package/styles/_tokens.css.js +1 -1
- package/styles/_tokens.css.js.map +1 -1
- package/styles/body-cell/body-cell.css.js +1 -1
- package/styles/body-cell/body-cell.css.js.map +1 -1
- package/styles/body-cell/cell-renderers.css.js +1 -1
- package/styles/body-cell/cell-renderers.css.js.map +1 -1
- package/styles/body-row/body-row.css.js +1 -1
- package/styles/body-row/body-row.css.js.map +1 -1
- package/styles/document-tokens.css.d.ts +1 -0
- package/styles/document-tokens.css.js +3 -0
- package/styles/document-tokens.css.js.map +1 -0
- package/styles/filter-row/filter-row.css.js +1 -1
- package/styles/filter-row/filter-row.css.js.map +1 -1
- package/styles/grid/_grid.base.css.js +1 -1
- package/styles/grid/_grid.base.css.js.map +1 -1
- package/styles/grid/grid.css.js +1 -1
- package/styles/grid/grid.css.js.map +1 -1
- package/styles/group-header-row/group-header-row.css.js +1 -1
- package/styles/group-header-row/group-header-row.css.js.map +1 -1
- package/styles/header-cell/header-cell.css.js +1 -1
- package/styles/header-cell/header-cell.css.js.map +1 -1
- package/styles/header-row/header-row.base.css.js +1 -1
- package/styles/header-row/header-row.base.css.js.map +1 -1
- package/styles/paginator/paginator.css.js +1 -1
- package/styles/paginator/paginator.css.js.map +1 -1
- package/styles/toolbar/toolbar.css.js +1 -1
- package/styles/toolbar/toolbar.css.js.map +1 -1
- package/tokens.css +78 -0
- package/LICENSE +0 -80
- package/docs/media/LICENSE +0 -80
- package/docs/media/_tokens.scss +0 -214
- package/operations/pagination.d.ts +0 -19
- package/operations/pagination.js +0 -12
- package/operations/pagination.js.map +0 -1
package/internal/flip.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flip.js","sourceRoot":"","sources":["../../src/internal/flip.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Lightweight FLIP (First / Last / Invert / Play) helpers for animating\n * element re-positioning during column reorder + row sort.\n *\n * @remarks\n * Uses the Web Animations API with `composite: 'add'` so the FLIP delta\n * stacks ON TOP of whatever inline `transform` the virtualizer already set\n * on row elements — without `'add'` our keyframe would clobber the\n * virtualizer's `translate(...)` and rows would jump to the origin before\n * settling.\n *\n * Respects `prefers-reduced-motion: reduce` and bails out entirely when the\n * user has opted out of motion.\n */\n\nconst FLIP_DURATION_MS = 220;\nconst FLIP_EASING = 'cubic-bezier(0.2, 0, 0.2, 1)';\nconst MIN_DELTA_PX = 0.5;\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || !window.matchMedia) return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * One element to FLIP, captured at its \"first\" (pre-mutation) position.\n */\nexport interface FlipEntry {\n element: HTMLElement;\n rect: DOMRect;\n}\n\n/**\n * Plays the FLIP animation for every captured element by computing the\n * delta against its current (post-mutation) bounding rect and animating it\n * back to identity.\n *\n * @param entries - Elements captured by {@link captureRect}.\n * @param axis - `'x'` for horizontal motion (column reorder), `'y'` for\n * vertical motion (row sort), `'both'` for diagonal motion if either axis\n * could move.\n */\nexport function playFlip(entries: ReadonlyArray<FlipEntry>, axis: 'x' | 'y' | 'both' = 'both') {\n if (prefersReducedMotion() || entries.length === 0) return;\n\n for (const { element, rect: oldRect } of entries) {\n if (!element.isConnected) continue;\n const newRect = element.getBoundingClientRect();\n const dx = axis === 'y' ? 0 : oldRect.left - newRect.left;\n const dy = axis === 'x' ? 0 : oldRect.top - newRect.top;\n if (Math.abs(dx) < MIN_DELTA_PX && Math.abs(dy) < MIN_DELTA_PX) continue;\n\n // `composite: 'add'` stacks our delta on top of any inline transform\n // (e.g. the virtualizer's `translate(0, Ypx)` on row elements).\n element.animate(\n [{ transform: `translate(${dx}px, ${dy}px)` }, { transform: 'translate(0, 0)' }],\n {\n duration: FLIP_DURATION_MS,\n easing: FLIP_EASING,\n composite: 'add',\n }\n );\n }\n}\n\n/**\n * Convenience: capture a rect for an element, returning a {@link FlipEntry}.\n */\nexport function captureRect(element: HTMLElement): FlipEntry {\n return { element, rect: element.getBoundingClientRect() };\n}\n\n/**\n * A subset of `LitElement` needed for {@link awaitChildUpdates}.\n */\ninterface UpdatableElement {\n updateComplete: Promise<unknown>;\n}\n\n/**\n * Awaits a set of child elements' `updateComplete` promises.\n *\n * @remarks\n * The grid's `updateComplete` only resolves the grid's own update — child\n * components (header row, body rows, cells) schedule their updates one\n * microtask later. FLIP needs every relevant child to have its new DOM\n * committed before computing the \"Last\" rect; without this wait the\n * captured-before and measured-after rects match and the animation\n * silently no-ops.\n */\nexport async function awaitChildUpdates(\n elements: ReadonlyArray<UpdatableElement | null | undefined>\n) {\n await Promise.all(\n elements.filter((el): el is UpdatableElement => el != null).map((el) => el.updateComplete)\n );\n}\n\n/**\n * Keyed FLIP entry — pairs an arbitrary identity key with a captured rect.\n *\n * @remarks\n * Used for row sort animation: the virtualizer recycles `<apex-grid-row>`\n * DOM elements so the same element holds different row data before and\n * after a sort. We capture rects keyed by row data identity, then resolve\n * the new DOM element after the sort via the `resolveElement` callback.\n */\nexport interface KeyedFlipEntry<K> {\n key: K;\n rect: DOMRect;\n}\n\n/**\n * Plays a FLIP animation against elements located by key after a DOM\n * mutation has settled. Used for row sort, where DOM elements get recycled\n * across the mutation and can only be found by data identity.\n *\n * @param before - Rects captured before the mutation, keyed by data\n * identity (or any other stable key).\n * @param resolveElement - Function that returns the current DOM element\n * representing `key`, or `null` if the keyed row is no longer in view.\n * @param axis - Same semantics as {@link playFlip}.\n */\nexport function playKeyedFlip<K>(\n before: ReadonlyArray<KeyedFlipEntry<K>>,\n resolveElement: (key: K) => HTMLElement | null,\n axis: 'x' | 'y' | 'both' = 'both'\n) {\n if (prefersReducedMotion() || before.length === 0) return;\n\n for (const { key, rect: oldRect } of before) {\n const element = resolveElement(key);\n if (!element?.isConnected) continue;\n const newRect = element.getBoundingClientRect();\n const dx = axis === 'y' ? 0 : oldRect.left - newRect.left;\n const dy = axis === 'x' ? 0 : oldRect.top - newRect.top;\n if (Math.abs(dx) < MIN_DELTA_PX && Math.abs(dy) < MIN_DELTA_PX) continue;\n\n element.animate(\n [{ transform: `translate(${dx}px, ${dy}px)` }, { transform: 'translate(0, 0)' }],\n {\n duration: FLIP_DURATION_MS,\n easing: FLIP_EASING,\n composite: 'add',\n }\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"flip.js","sourceRoot":"","sources":["../../src/internal/flip.ts"],"names":[],"mappings":"AAiBA,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,WAAW,GAAG,8BAA8B,CAAC;AACnD,MAAM,YAAY,GAAG,GAAG,CAAC;AAGzB,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,CAAC;AAEvC,MAAM,CAAC,MAAM,SAAS,GAAG,aAAa,CAAC;AAEvC,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC;AAIxC,MAAM,QAAQ,GAA6B,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AAO9F,IAAI,aAAa,GAAG,CAAC,CAAC;AAGtB,MAAM,UAAU,gBAAgB;IAC9B,OAAO,aAAa,GAAG,CAAC,CAAC;AAC3B,CAAC;AAGD,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,EAAU;IACtD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAChD,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE;YAAE,SAAS,CAAC,MAAM,EAAE,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB;IAC3B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IACtE,OAAO,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAC;AACvE,CAAC;AAMD,SAAS,WAAW,CAAC,OAAoB,EAAE,EAAU,EAAE,EAAU,EAAE,IAAc;IAG/E,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAC/B,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,EAChF;QACE,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC;QAClB,QAAQ,EAAE,gBAAgB;QAC1B,MAAM,EAAE,WAAW;QACnB,SAAS,EAAE,KAAK;KACjB,CACF,CAAC;IACF,aAAa,EAAE,CAAC;IAChB,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,OAAO,GAAG,KAAK,CAAC;QAChB,aAAa,EAAE,CAAC;IAClB,CAAC,CAAC;IACF,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC3C,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC7C,CAAC;AAoBD,MAAM,UAAU,QAAQ,CAAC,OAAiC,EAAE,OAAiB,MAAM;IACjF,IAAI,oBAAoB,EAAE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE3D,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,CAAC,WAAW;YAAE,SAAS;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;QAChD,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1D,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxD,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY;YAAE,SAAS;QACzE,WAAW,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAKD,MAAM,UAAU,WAAW,CAAC,OAAoB;IAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;AAC5D,CAAC;AAoBD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAA4D;IAE5D,MAAM,OAAO,CAAC,GAAG,CACf,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAA0B,EAAE,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAC3F,CAAC;AACJ,CAAC;AAgBD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAmB,IAAiB;IACzE,MAAM,IAAI,GAAG,IAAiC,CAAC;IAC/C,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;IAC7B,MAAM,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE,CAAC;IACvC,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAiCD,MAAM,UAAU,aAAa,CAC3B,MAAwC,EACxC,cAA8C,EAC9C,OAAiB,MAAM;IAEvB,IAAI,oBAAoB,EAAE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE1D,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,MAAM,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,WAAW;YAAE,SAAS;QACpC,IAAI,aAAa,GAAG,CAAC;YAAE,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;QAChD,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1D,MAAM,EAAE,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxD,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY;YAAE,SAAS;QACzE,WAAW,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;AACH,CAAC","sourcesContent":["import type { GridHost } from './types.js';\n\n/**\n * Lightweight FLIP (First / Last / Invert / Play) helpers for animating\n * element re-positioning during column reorder + row sort.\n *\n * @remarks\n * Uses the Web Animations API with `composite: 'add'` so the FLIP delta\n * stacks ON TOP of whatever inline `transform` the virtualizer already set\n * on row elements — without `'add'` our keyframe would clobber the\n * virtualizer's `translate(...)` and rows would jump to the origin before\n * settling.\n *\n * Respects `prefers-reduced-motion: reduce` and bails out entirely when the\n * user has opted out of motion.\n */\n\nconst FLIP_DURATION_MS = 220;\nconst FLIP_EASING = 'cubic-bezier(0.2, 0, 0.2, 1)';\nconst MIN_DELTA_PX = 0.5;\n\n/** Animation id of a vertical (row) FLIP. */\nexport const FLIP_ID_Y = 'apex-flip-y';\n/** Animation id of a horizontal (column) FLIP. */\nexport const FLIP_ID_X = 'apex-flip-x';\n/** Animation id of a FLIP that may move on both axes. */\nexport const FLIP_ID_BOTH = 'apex-flip';\n\ntype FlipAxis = 'x' | 'y' | 'both';\n\nconst FLIP_IDS: Record<FlipAxis, string> = { x: FLIP_ID_X, y: FLIP_ID_Y, both: FLIP_ID_BOTH };\n\n/**\n * FLIP animations started and not yet finished or cancelled, across every\n * grid on the page. A row re-bound to another record cancels its running\n * FLIP only while this is non-zero, so ordinary scroll re-binds pay nothing.\n */\nlet flipsInFlight = 0;\n\n/** Whether any FLIP animation is running right now. */\nexport function hasFlipsInFlight(): boolean {\n return flipsInFlight > 0;\n}\n\n/** Cancels the running FLIP animations with `id` on `element` (not its subtree). */\nexport function cancelFlips(element: Element, id: string): void {\n for (const animation of element.getAnimations()) {\n if (animation.id === id) animation.cancel();\n }\n}\n\nfunction prefersReducedMotion(): boolean {\n if (typeof window === 'undefined' || !window.matchMedia) return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Starts one FLIP on `element`, tagged with the axis id and counted in\n * {@link hasFlipsInFlight} until it finishes or is cancelled.\n */\nfunction animateFlip(element: HTMLElement, dx: number, dy: number, axis: FlipAxis): void {\n // `composite: 'add'` stacks our delta on top of any inline transform\n // (e.g. the virtualizer's `translate(0, Ypx)` on row elements).\n const animation = element.animate(\n [{ transform: `translate(${dx}px, ${dy}px)` }, { transform: 'translate(0, 0)' }],\n {\n id: FLIP_IDS[axis],\n duration: FLIP_DURATION_MS,\n easing: FLIP_EASING,\n composite: 'add',\n }\n );\n flipsInFlight++;\n let counted = true;\n const done = () => {\n if (!counted) return;\n counted = false;\n flipsInFlight--;\n };\n animation.addEventListener('finish', done);\n animation.addEventListener('cancel', done);\n}\n\n/**\n * One element to FLIP, captured at its \"first\" (pre-mutation) position.\n */\nexport interface FlipEntry {\n element: HTMLElement;\n rect: DOMRect;\n}\n\n/**\n * Plays the FLIP animation for every captured element by computing the\n * delta against its current (post-mutation) bounding rect and animating it\n * back to identity.\n *\n * @param entries - Elements captured by {@link captureRect}.\n * @param axis - `'x'` for horizontal motion (column reorder), `'y'` for\n * vertical motion (row sort), `'both'` for diagonal motion if either axis\n * could move.\n */\nexport function playFlip(entries: ReadonlyArray<FlipEntry>, axis: FlipAxis = 'both') {\n if (prefersReducedMotion() || entries.length === 0) return;\n\n for (const { element, rect: oldRect } of entries) {\n if (!element.isConnected) continue;\n const newRect = element.getBoundingClientRect();\n const dx = axis === 'y' ? 0 : oldRect.left - newRect.left;\n const dy = axis === 'x' ? 0 : oldRect.top - newRect.top;\n if (Math.abs(dx) < MIN_DELTA_PX && Math.abs(dy) < MIN_DELTA_PX) continue;\n animateFlip(element, dx, dy, axis);\n }\n}\n\n/**\n * Convenience: capture a rect for an element, returning a {@link FlipEntry}.\n */\nexport function captureRect(element: HTMLElement): FlipEntry {\n return { element, rect: element.getBoundingClientRect() };\n}\n\n/**\n * A subset of `LitElement` needed for {@link awaitChildUpdates}.\n */\ninterface UpdatableElement {\n updateComplete: Promise<unknown>;\n}\n\n/**\n * Awaits a set of child elements' `updateComplete` promises.\n *\n * @remarks\n * The grid's `updateComplete` only resolves the grid's own update — child\n * components (header row, body rows, cells) schedule their updates one\n * microtask later. FLIP needs every relevant child to have its new DOM\n * committed before computing the \"Last\" rect; without this wait the\n * captured-before and measured-after rects match and the animation\n * silently no-ops.\n */\nexport async function awaitChildUpdates(\n elements: ReadonlyArray<UpdatableElement | null | undefined>\n) {\n await Promise.all(\n elements.filter((el): el is UpdatableElement => el != null).map((el) => el.updateComplete)\n );\n}\n\n/** What {@link settleRowsForFlip} needs of the grid; the first two are protected there. */\ninterface FlipSettleHost {\n pipelineSettled(): Promise<void>;\n scrollContainer?: { rendered(): Promise<void> } | null;\n rows: ReadonlyArray<UpdatableElement>;\n}\n\n/**\n * Waits until the rows can be measured for a row FLIP's \"Last\" rects, after\n * a sort or a row move: the pipeline run it started and the grid's render of\n * the result, then the body's rows render (new items reach the rows only once\n * the layout reports the range) and update. Rows outside the body (pinned\n * rows) are awaited too. Sort and row reorder both use this one wait.\n */\nexport async function settleRowsForFlip<T extends object>(host: GridHost<T>): Promise<void> {\n const grid = host as unknown as FlipSettleHost;\n await grid.pipelineSettled();\n await grid.scrollContainer?.rendered();\n await awaitChildUpdates(grid.rows);\n}\n\n/**\n * Keyed FLIP entry — pairs an arbitrary identity key with a captured rect.\n *\n * @remarks\n * Used for row sort animation: the virtualizer recycles `<apex-grid-row>`\n * DOM elements so the same element holds different row data before and\n * after a sort. We capture rects keyed by row data identity, then resolve\n * the new DOM element after the sort via the `resolveElement` callback.\n */\nexport interface KeyedFlipEntry<K> {\n key: K;\n rect: DOMRect;\n}\n\n/**\n * Plays a FLIP animation against elements located by key after a DOM\n * mutation has settled. Used for row sort, where DOM elements get recycled\n * across the mutation and can only be found by data identity.\n *\n * @param before - Rects captured before the mutation, keyed by data\n * identity (or any other stable key).\n * @param resolveElement - Function that returns the current DOM element\n * representing `key`, or `null` if the keyed row is no longer in view.\n * @param axis - Same semantics as {@link playFlip}.\n *\n * @remarks\n * A FLIP of the same axis still running on an element is cancelled before\n * its new rect is measured, so a quick second move replaces the first\n * rather than stacking on it. Motion stays continuous: the captured \"First\"\n * rect already includes the cancelled animation's offset.\n */\nexport function playKeyedFlip<K>(\n before: ReadonlyArray<KeyedFlipEntry<K>>,\n resolveElement: (key: K) => HTMLElement | null,\n axis: FlipAxis = 'both'\n) {\n if (prefersReducedMotion() || before.length === 0) return;\n\n for (const { key, rect: oldRect } of before) {\n const element = resolveElement(key);\n if (!element?.isConnected) continue;\n if (flipsInFlight > 0) cancelFlips(element, FLIP_IDS[axis]);\n const newRect = element.getBoundingClientRect();\n const dx = axis === 'y' ? 0 : oldRect.left - newRect.left;\n const dy = axis === 'x' ? 0 : oldRect.top - newRect.top;\n if (Math.abs(dx) < MIN_DELTA_PX && Math.abs(dy) < MIN_DELTA_PX) continue;\n animateFlip(element, dx, dy, axis);\n }\n}\n"]}
|
package/internal/index.d.ts
CHANGED
|
@@ -11,14 +11,16 @@
|
|
|
11
11
|
* minor releases. Do not depend on them from third-party code.
|
|
12
12
|
*/
|
|
13
13
|
export { ApexGrid } from '../components/grid.js';
|
|
14
|
+
export { viewIndexer } from '../controllers/history.js';
|
|
14
15
|
export { gridStateContext, StateController } from '../controllers/state.js';
|
|
16
|
+
export { clampRating, commitDateInSameShape, getColumnTypeRenderer, getRatingMax, getSelectOptions, parseDate, } from './column-types.js';
|
|
15
17
|
export { PIPELINE } from './constants.js';
|
|
16
18
|
export type { ExportCellValue, ExportFormat, ExportOptions } from './export.js';
|
|
17
|
-
export { downloadBlob, getColumnLabel, resolveExportColumns, resolveExportRows, resolveExportValue, } from './export.js';
|
|
18
|
-
export type { CellDecoration, CellDecorator, CellDecoratorContext, CellInteraction, CellInteractionHandler, CellInteractionKind, ColumnMenuProvider, GridFeatureModule, PresentedRow, RowAria, RowAriaProvider, RowPresenter, RowPresenterContext, RowTransformer, SerializableModule, } from './feature-module.js';
|
|
19
|
-
export { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowAriaProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from './feature-module.js';
|
|
19
|
+
export { downloadBlob, escapeCSVCell, escapeFormula, formatDisplayText, getColumnLabel, resolveExportColumns, resolveExportRows, resolveExportValue, } from './export.js';
|
|
20
|
+
export type { CellDecoration, CellDecorator, CellDecoratorContext, CellInteraction, CellInteractionHandler, CellInteractionKind, ColumnMenuProvider, CoordinateLabeler, GridFeatureModule, PresentedRow, RowAria, RowAriaProvider, RowPresenter, RowPresenterContext, RowTransformer, SerializableModule, } from './feature-module.js';
|
|
21
|
+
export { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isCoordinateLabeler, isRowAriaProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from './feature-module.js';
|
|
20
22
|
export { registerComponent } from './register.js';
|
|
21
23
|
export type { ColumnLayoutState, FilterStateSnapshot, GetStateOptions, GridState, RowRef, SetStateOptions, SortStateSnapshot, } from './state-snapshot.js';
|
|
22
|
-
export { applyColumnLayout, deserializeFilter, resolveRowRefs, serializeColumnLayout, serializeFilter, serializeRowRefs, serializeSort, } from './state-snapshot.js';
|
|
24
|
+
export { applyColumnLayout, deserializeFilter, mergeColumnLayout, registerFilterOperand, resolveFilterOperand, resolveRowRefs, serializeColumnLayout, serializeFilter, serializeRowRefs, serializeSort, } from './state-snapshot.js';
|
|
23
25
|
export type { ActiveNode, ColumnConfiguration, GridHost, Keys, ToolbarAction } from './types.js';
|
|
24
|
-
export { getDisplayColumns } from './utils.js';
|
|
26
|
+
export { getDisplayColumns, isRTL } from './utils.js';
|
package/internal/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export { ApexGrid } from '../components/grid.js';
|
|
2
|
+
export { viewIndexer } from '../controllers/history.js';
|
|
2
3
|
export { gridStateContext, StateController } from '../controllers/state.js';
|
|
4
|
+
export { clampRating, commitDateInSameShape, getColumnTypeRenderer, getRatingMax, getSelectOptions, parseDate, } from './column-types.js';
|
|
3
5
|
export { PIPELINE } from './constants.js';
|
|
4
|
-
export { downloadBlob, getColumnLabel, resolveExportColumns, resolveExportRows, resolveExportValue, } from './export.js';
|
|
5
|
-
export { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowAriaProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from './feature-module.js';
|
|
6
|
+
export { downloadBlob, escapeCSVCell, escapeFormula, formatDisplayText, getColumnLabel, resolveExportColumns, resolveExportRows, resolveExportValue, } from './export.js';
|
|
7
|
+
export { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isCoordinateLabeler, isRowAriaProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from './feature-module.js';
|
|
6
8
|
export { registerComponent } from './register.js';
|
|
7
|
-
export { applyColumnLayout, deserializeFilter, resolveRowRefs, serializeColumnLayout, serializeFilter, serializeRowRefs, serializeSort, } from './state-snapshot.js';
|
|
8
|
-
export { getDisplayColumns } from './utils.js';
|
|
9
|
+
export { applyColumnLayout, deserializeFilter, mergeColumnLayout, registerFilterOperand, resolveFilterOperand, resolveRowRefs, serializeColumnLayout, serializeFilter, serializeRowRefs, serializeSort, } from './state-snapshot.js';
|
|
10
|
+
export { getDisplayColumns, isRTL } from './utils.js';
|
|
9
11
|
//# sourceMappingURL=index.js.map
|
package/internal/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EACL,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/internal/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAmBrB,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAUlD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC","sourcesContent":["/**\n * Unstable, first-party extension surface for `apex-grid`.\n *\n * This entry point (`apex-grid/internal`) exposes the internals that the\n * first-party `@apexcharts/grid-enterprise` package builds on: the grid class,\n * its state controller, the component registration helper, and the feature\n * module contract. It is intentionally separate from the public `.` barrel.\n *\n * @remarks\n * No semver guarantees are made for these exports. They may change between\n * minor releases. Do not depend on them from third-party code.\n */\nexport { ApexGrid } from '../components/grid.js';\nexport { viewIndexer } from '../controllers/history.js';\nexport { gridStateContext, StateController } from '../controllers/state.js';\nexport {\n clampRating,\n commitDateInSameShape,\n getColumnTypeRenderer,\n getRatingMax,\n getSelectOptions,\n parseDate,\n} from './column-types.js';\nexport { PIPELINE } from './constants.js';\nexport type { ExportCellValue, ExportFormat, ExportOptions } from './export.js';\nexport {\n downloadBlob,\n escapeCSVCell,\n escapeFormula,\n formatDisplayText,\n getColumnLabel,\n resolveExportColumns,\n resolveExportRows,\n resolveExportValue,\n} from './export.js';\nexport type {\n CellDecoration,\n CellDecorator,\n CellDecoratorContext,\n CellInteraction,\n CellInteractionHandler,\n CellInteractionKind,\n ColumnMenuProvider,\n CoordinateLabeler,\n GridFeatureModule,\n PresentedRow,\n RowAria,\n RowAriaProvider,\n RowPresenter,\n RowPresenterContext,\n RowTransformer,\n SerializableModule,\n} from './feature-module.js';\nexport {\n isCellDecorator,\n isCellInteractionHandler,\n isColumnMenuProvider,\n isCoordinateLabeler,\n isRowAriaProvider,\n isRowPresenter,\n isRowTransformer,\n isSerializableModule,\n} from './feature-module.js';\nexport { registerComponent } from './register.js';\nexport type {\n ColumnLayoutState,\n FilterStateSnapshot,\n GetStateOptions,\n GridState,\n RowRef,\n SetStateOptions,\n SortStateSnapshot,\n} from './state-snapshot.js';\nexport {\n applyColumnLayout,\n deserializeFilter,\n mergeColumnLayout,\n registerFilterOperand,\n resolveFilterOperand,\n resolveRowRefs,\n serializeColumnLayout,\n serializeFilter,\n serializeRowRefs,\n serializeSort,\n} from './state-snapshot.js';\nexport type { ActiveNode, ColumnConfiguration, GridHost, Keys, ToolbarAction } from './types.js';\nexport { getDisplayColumns, isRTL } from './utils.js';\n"]}
|
|
@@ -1 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The text a string filter operand compares: strings as they are, `null` and
|
|
3
|
+
* `undefined` as `''`, any other value (number, Date, array) through `String`,
|
|
4
|
+
* case-folded unless `caseSensitive`. Total, so a cell of any type can be
|
|
5
|
+
* matched by a string condition without throwing. A string cell allocates
|
|
6
|
+
* nothing beyond the case fold.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeCase(value: unknown, caseSensitive?: boolean): string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export function normalizeCase(
|
|
2
|
-
|
|
1
|
+
export function normalizeCase(value, caseSensitive) {
|
|
2
|
+
const text = typeof value === 'string' ? value : value == null ? '' : String(value);
|
|
3
|
+
return caseSensitive ? text : text.toLowerCase();
|
|
3
4
|
}
|
|
4
5
|
//# sourceMappingURL=normalize-case.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize-case.js","sourceRoot":"","sources":["../../src/internal/normalize-case.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"normalize-case.js","sourceRoot":"","sources":["../../src/internal/normalize-case.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,aAAuB;IACnE,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpF,OAAO,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;AACnD,CAAC","sourcesContent":["/**\n * The text a string filter operand compares: strings as they are, `null` and\n * `undefined` as `''`, any other value (number, Date, array) through `String`,\n * case-folded unless `caseSensitive`. Total, so a cell of any type can be\n * matched by a string condition without throwing. A string cell allocates\n * nothing beyond the case fold.\n */\nexport function normalizeCase(value: unknown, caseSensitive?: boolean): string {\n const text = typeof value === 'string' ? value : value == null ? '' : String(value);\n return caseSensitive ? text : text.toLowerCase();\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FilterCriteria, FilterExpression } from '../operations/filter/types.js';
|
|
1
|
+
import type { FilterCriteria, FilterExpression, FilterOperation } from '../operations/filter/types.js';
|
|
2
2
|
import type { SortExpression, SortingDirection } from '../operations/sort/types.js';
|
|
3
3
|
import type { ColumnConfiguration, PinPosition } from './types.js';
|
|
4
4
|
/**
|
|
@@ -105,6 +105,27 @@ export interface SetStateOptions<T extends object> {
|
|
|
105
105
|
*/
|
|
106
106
|
strict?: boolean;
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* The `setState` slices in the order `setState` applies them, each mapped to
|
|
110
|
+
* the {@link GridState} keys it restores (`tree` restores both tree keys).
|
|
111
|
+
*/
|
|
112
|
+
export declare const SET_STATE_SLICE_KEYS: {
|
|
113
|
+
readonly columns: readonly ["columns"];
|
|
114
|
+
readonly sort: readonly ["sort"];
|
|
115
|
+
readonly filter: readonly ["filter"];
|
|
116
|
+
readonly quickFilter: readonly ["quickFilter"];
|
|
117
|
+
readonly modules: readonly ["modules"];
|
|
118
|
+
readonly rowOrder: readonly ["rowOrder"];
|
|
119
|
+
readonly tree: readonly ["treeExpanded", "treeExpandedKeys"];
|
|
120
|
+
readonly expansion: readonly ["expansion"];
|
|
121
|
+
readonly rowPinning: readonly ["rowPinning"];
|
|
122
|
+
readonly selection: readonly ["selection"];
|
|
123
|
+
readonly pagination: readonly ["pagination"];
|
|
124
|
+
};
|
|
125
|
+
/** A `setState` slice name, as reported in {@link SetStateResult}. */
|
|
126
|
+
export type SetStateSlice = keyof typeof SET_STATE_SLICE_KEYS;
|
|
127
|
+
/** Every slice name, in apply order. */
|
|
128
|
+
export declare const SET_STATE_SLICES: SetStateSlice[];
|
|
108
129
|
/**
|
|
109
130
|
* The outcome of an {@link SetStateOptions} apply. `setState` never throws on
|
|
110
131
|
* malformed input (unless `strict`): it applies recognized slices, skips the
|
|
@@ -112,9 +133,12 @@ export interface SetStateOptions<T extends object> {
|
|
|
112
133
|
* clamped, or unresolved.
|
|
113
134
|
*/
|
|
114
135
|
export interface SetStateResult {
|
|
115
|
-
/**
|
|
136
|
+
/**
|
|
137
|
+
* Slice names that were present and applied (e.g. `'sort'`, `'columns'`); see
|
|
138
|
+
* {@link SET_STATE_SLICE_KEYS} for the {@link GridState} keys of each.
|
|
139
|
+
*/
|
|
116
140
|
applied: string[];
|
|
117
|
-
/** Known slice names that were absent
|
|
141
|
+
/** Known slice names ({@link SetStateSlice}) that were absent or not applied. */
|
|
118
142
|
skipped: string[];
|
|
119
143
|
/** What was dropped / clamped / unresolved, one message each. */
|
|
120
144
|
warnings: string[];
|
|
@@ -125,28 +149,56 @@ export declare function serializeColumnLayout<T extends object>(columns: Readonl
|
|
|
125
149
|
* Return a new columns array reordered to match `layout`, with width / pinning /
|
|
126
150
|
* visibility applied. Column objects are shallow-cloned so non-layout
|
|
127
151
|
* properties (templates, comparers, type config) are preserved. Columns absent
|
|
128
|
-
* from `layout` are appended unchanged; layout entries with no matching column
|
|
129
|
-
* are ignored.
|
|
152
|
+
* from `layout` are appended unchanged; layout entries with no matching column,
|
|
153
|
+
* a repeated key, or no string `key` are ignored. This is the full-layout
|
|
154
|
+
* restorer: to change a few fields in place, overlay them with
|
|
155
|
+
* {@link mergeColumnLayout} first.
|
|
130
156
|
*/
|
|
131
157
|
export declare function applyColumnLayout<T extends object>(columns: ReadonlyArray<ColumnConfiguration<T>>, layout: ReadonlyArray<ColumnLayoutState>): ColumnConfiguration<T>[];
|
|
158
|
+
/**
|
|
159
|
+
* Overlay a partial layout onto `current` (a full {@link serializeColumnLayout}
|
|
160
|
+
* result): each `partial` entry changes only the fields it defines on the
|
|
161
|
+
* column with the same key, and the order of `current` is kept. `null` clears
|
|
162
|
+
* a field (e.g. `pinned: null` unpins). Entries for unknown keys are ignored.
|
|
163
|
+
* Returns a new full layout to hand to `setState({ columns })`.
|
|
164
|
+
*/
|
|
165
|
+
export declare function mergeColumnLayout(current: ReadonlyArray<ColumnLayoutState>, partial: ReadonlyArray<Partial<Record<keyof ColumnLayoutState, unknown>>>): ColumnLayoutState[];
|
|
132
166
|
export declare function serializeSort<T extends object>(expressions: ReadonlyArray<SortExpression<T>>): SortStateSnapshot[];
|
|
133
167
|
export declare function serializeFilter<T extends object>(expressions: ReadonlyArray<FilterExpression<T>>): FilterStateSnapshot[];
|
|
168
|
+
/**
|
|
169
|
+
* Make `operation` resolvable by its `name` on every column, after the
|
|
170
|
+
* column type's own operands. For first-party filter UIs (the enterprise set
|
|
171
|
+
* filter) whose expressions must survive `setState(getState())`. The
|
|
172
|
+
* operation must be stateless: everything it needs travels in `searchTerm`.
|
|
173
|
+
*/
|
|
174
|
+
export declare function registerFilterOperand(operation: FilterOperation<unknown>): void;
|
|
175
|
+
/**
|
|
176
|
+
* Resolve a filter operand name (e.g. `'contains'`) to the live
|
|
177
|
+
* {@link FilterOperation} of `column`'s type, else to one registered with
|
|
178
|
+
* {@link registerFilterOperand}. Only the tables' own names resolve, so
|
|
179
|
+
* `'toString'` or `'constructor'` never pass as operands.
|
|
180
|
+
*/
|
|
181
|
+
export declare function resolveFilterOperand<T extends object>(column: ColumnConfiguration<T>, name: unknown): FilterOperation<unknown> | undefined;
|
|
134
182
|
/**
|
|
135
183
|
* Rebuild filter expressions from a snapshot, resolving each operand name back
|
|
136
184
|
* to a live {@link FilterOperation} via the target column's operand set.
|
|
137
|
-
* Entries whose column or operand can't be
|
|
138
|
-
*
|
|
185
|
+
* Entries that are not keyed objects, whose column or operand can't be
|
|
186
|
+
* resolved, or whose binary operand has no `searchTerm` are dropped; `onDrop`
|
|
187
|
+
* (when given) is called with the dropped entry and a reason.
|
|
139
188
|
*/
|
|
140
189
|
export declare function deserializeFilter<T extends object>(snapshots: ReadonlyArray<FilterStateSnapshot>, getColumn: (key: string) => ColumnConfiguration<T> | undefined, onDrop?: (snapshot: FilterStateSnapshot, reason: string) => void): FilterExpression<T>[];
|
|
141
190
|
/**
|
|
142
191
|
* Serialize a set of rows to {@link RowRef}s. With a `rowId` resolver each row
|
|
143
192
|
* is captured by id; otherwise by its positional index in `universe`
|
|
144
193
|
* (`ApexGrid.data`). Rows not found in `universe` (index mode) are skipped.
|
|
194
|
+
* Index mode builds one position map per call, so it is linear in the sizes
|
|
195
|
+
* of `rows` and `universe` rather than their product.
|
|
145
196
|
*/
|
|
146
197
|
export declare function serializeRowRefs<T extends object>(rows: ReadonlyArray<T>, universe: ReadonlyArray<T>, rowId?: (row: T) => string | number): RowRef[];
|
|
147
198
|
/**
|
|
148
199
|
* Resolve {@link RowRef}s back to rows in `universe`. `id` refs require a
|
|
149
200
|
* `rowId` resolver (otherwise they're skipped); `index` refs resolve
|
|
150
|
-
* positionally.
|
|
201
|
+
* positionally and must be non-negative integers. Refs that are not objects,
|
|
202
|
+
* and unresolvable refs, are dropped.
|
|
151
203
|
*/
|
|
152
204
|
export declare function resolveRowRefs<T extends object>(refs: ReadonlyArray<RowRef>, universe: ReadonlyArray<T>, rowId?: (row: T) => string | number): T[];
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import { getFilterOperandsFor } from './utils.js';
|
|
2
|
+
export const SET_STATE_SLICE_KEYS = {
|
|
3
|
+
columns: ['columns'],
|
|
4
|
+
sort: ['sort'],
|
|
5
|
+
filter: ['filter'],
|
|
6
|
+
quickFilter: ['quickFilter'],
|
|
7
|
+
modules: ['modules'],
|
|
8
|
+
rowOrder: ['rowOrder'],
|
|
9
|
+
tree: ['treeExpanded', 'treeExpandedKeys'],
|
|
10
|
+
expansion: ['expansion'],
|
|
11
|
+
rowPinning: ['rowPinning'],
|
|
12
|
+
selection: ['selection'],
|
|
13
|
+
pagination: ['pagination'],
|
|
14
|
+
};
|
|
15
|
+
export const SET_STATE_SLICES = Object.keys(SET_STATE_SLICE_KEYS);
|
|
16
|
+
const _everyKeyHasASlice = true;
|
|
17
|
+
void _everyKeyHasASlice;
|
|
18
|
+
function isKeyed(value) {
|
|
19
|
+
return typeof value === 'object' && value !== null && typeof value.key === 'string';
|
|
20
|
+
}
|
|
2
21
|
export function serializeColumnLayout(columns) {
|
|
3
22
|
return columns.map((column) => ({
|
|
4
23
|
key: String(column.key),
|
|
@@ -14,6 +33,8 @@ export function applyColumnLayout(columns, layout) {
|
|
|
14
33
|
const used = new Set();
|
|
15
34
|
const ordered = [];
|
|
16
35
|
for (const entry of layout) {
|
|
36
|
+
if (!isKeyed(entry) || used.has(entry.key))
|
|
37
|
+
continue;
|
|
17
38
|
const column = byKey.get(entry.key);
|
|
18
39
|
if (!column)
|
|
19
40
|
continue;
|
|
@@ -31,6 +52,24 @@ export function applyColumnLayout(columns, layout) {
|
|
|
31
52
|
}
|
|
32
53
|
return ordered;
|
|
33
54
|
}
|
|
55
|
+
export function mergeColumnLayout(current, partial) {
|
|
56
|
+
const patches = new Map();
|
|
57
|
+
for (const entry of partial) {
|
|
58
|
+
if (isKeyed(entry))
|
|
59
|
+
patches.set(entry.key, entry);
|
|
60
|
+
}
|
|
61
|
+
return current.map((column) => {
|
|
62
|
+
const next = { ...column };
|
|
63
|
+
const patch = patches.get(column.key);
|
|
64
|
+
if (patch) {
|
|
65
|
+
for (const field of ['width', 'pinned', 'hidden']) {
|
|
66
|
+
if (patch[field] !== undefined)
|
|
67
|
+
next[field] = patch[field] ?? undefined;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return next;
|
|
71
|
+
});
|
|
72
|
+
}
|
|
34
73
|
export function serializeSort(expressions) {
|
|
35
74
|
return expressions.map((expression) => ({
|
|
36
75
|
key: String(expression.key),
|
|
@@ -38,53 +77,80 @@ export function serializeSort(expressions) {
|
|
|
38
77
|
caseSensitive: expression.caseSensitive,
|
|
39
78
|
}));
|
|
40
79
|
}
|
|
80
|
+
function copyTerm(term) {
|
|
81
|
+
return Array.isArray(term) ? [...term] : term;
|
|
82
|
+
}
|
|
41
83
|
export function serializeFilter(expressions) {
|
|
42
84
|
return expressions.map((expression) => {
|
|
43
85
|
const condition = expression.condition;
|
|
44
86
|
return {
|
|
45
87
|
key: String(expression.key),
|
|
46
88
|
operand: typeof condition === 'string' ? condition : condition.name,
|
|
47
|
-
searchTerm: expression.searchTerm,
|
|
89
|
+
searchTerm: copyTerm(expression.searchTerm),
|
|
48
90
|
criteria: expression.criteria,
|
|
49
91
|
caseSensitive: expression.caseSensitive,
|
|
50
92
|
};
|
|
51
93
|
});
|
|
52
94
|
}
|
|
95
|
+
const registeredOperands = new Map();
|
|
96
|
+
export function registerFilterOperand(operation) {
|
|
97
|
+
registeredOperands.set(operation.name, operation);
|
|
98
|
+
}
|
|
99
|
+
export function resolveFilterOperand(column, name) {
|
|
100
|
+
if (typeof name !== 'string')
|
|
101
|
+
return undefined;
|
|
102
|
+
const operands = getFilterOperandsFor(column);
|
|
103
|
+
return Object.hasOwn(operands, name) ? operands[name] : registeredOperands.get(name);
|
|
104
|
+
}
|
|
53
105
|
export function deserializeFilter(snapshots, getColumn, onDrop) {
|
|
54
106
|
const expressions = [];
|
|
55
107
|
for (const snapshot of snapshots) {
|
|
108
|
+
if (!isKeyed(snapshot)) {
|
|
109
|
+
onDrop?.({ key: String(snapshot) }, 'not a filter entry');
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
56
112
|
const column = getColumn(snapshot.key);
|
|
57
113
|
if (!column) {
|
|
58
114
|
onDrop?.(snapshot, 'unknown column');
|
|
59
115
|
continue;
|
|
60
116
|
}
|
|
61
|
-
const
|
|
62
|
-
const condition = operands[snapshot.operand];
|
|
117
|
+
const condition = resolveFilterOperand(column, snapshot.operand);
|
|
63
118
|
if (!condition) {
|
|
64
119
|
onDrop?.(snapshot, `unknown operand "${snapshot.operand}"`);
|
|
65
120
|
continue;
|
|
66
121
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
if (!condition.unary && (snapshot.searchTerm === undefined || snapshot.searchTerm === null)) {
|
|
123
|
+
onDrop?.(snapshot, `operand "${snapshot.operand}" needs a searchTerm`);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const expression = { key: snapshot.key, condition };
|
|
127
|
+
if (snapshot.searchTerm !== undefined)
|
|
128
|
+
expression.searchTerm = copyTerm(snapshot.searchTerm);
|
|
129
|
+
if (snapshot.criteria !== undefined)
|
|
130
|
+
expression.criteria = snapshot.criteria;
|
|
131
|
+
if (snapshot.caseSensitive !== undefined)
|
|
132
|
+
expression.caseSensitive = snapshot.caseSensitive;
|
|
133
|
+
expressions.push(expression);
|
|
74
134
|
}
|
|
75
135
|
return expressions;
|
|
76
136
|
}
|
|
77
137
|
export function serializeRowRefs(rows, universe, rowId) {
|
|
138
|
+
if (rowId)
|
|
139
|
+
return rows.map((row) => ({ id: rowId(row) }));
|
|
140
|
+
if (rows.length < 2) {
|
|
141
|
+
const index = rows.length ? universe.indexOf(rows[0]) : -1;
|
|
142
|
+
return index === -1 ? [] : [{ index }];
|
|
143
|
+
}
|
|
144
|
+
const positions = new Map();
|
|
145
|
+
universe.forEach((row, index) => {
|
|
146
|
+
if (!positions.has(row))
|
|
147
|
+
positions.set(row, index);
|
|
148
|
+
});
|
|
78
149
|
const refs = [];
|
|
79
150
|
for (const row of rows) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
else {
|
|
84
|
-
const index = universe.indexOf(row);
|
|
85
|
-
if (index !== -1)
|
|
86
|
-
refs.push({ index });
|
|
87
|
-
}
|
|
151
|
+
const index = positions.get(row);
|
|
152
|
+
if (index !== undefined)
|
|
153
|
+
refs.push({ index });
|
|
88
154
|
}
|
|
89
155
|
return refs;
|
|
90
156
|
}
|
|
@@ -92,6 +158,8 @@ export function resolveRowRefs(refs, universe, rowId) {
|
|
|
92
158
|
const out = [];
|
|
93
159
|
let byId = null;
|
|
94
160
|
for (const ref of refs) {
|
|
161
|
+
if (typeof ref !== 'object' || ref === null)
|
|
162
|
+
continue;
|
|
95
163
|
if ('id' in ref) {
|
|
96
164
|
if (!rowId)
|
|
97
165
|
continue;
|
|
@@ -104,7 +172,7 @@ export function resolveRowRefs(refs, universe, rowId) {
|
|
|
104
172
|
if (row)
|
|
105
173
|
out.push(row);
|
|
106
174
|
}
|
|
107
|
-
else {
|
|
175
|
+
else if (Number.isInteger(ref.index) && ref.index >= 0) {
|
|
108
176
|
const row = universe[ref.index];
|
|
109
177
|
if (row)
|
|
110
178
|
out.push(row);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-snapshot.js","sourceRoot":"","sources":["../../src/internal/state-snapshot.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n FilterCriteria,\n FilterExpression,\n FilterOperation,\n} from '../operations/filter/types.js';\nimport type { SortExpression, SortingDirection } from '../operations/sort/types.js';\nimport type { ColumnConfiguration, Keys, PinPosition } from './types.js';\nimport { getFilterOperandsFor } from './utils.js';\n\n/**\n * A serializable, JSON-safe snapshot of the grid's restorable state, produced by\n * `ApexGrid.getState` and consumed by `ApexGrid.setState`.\n *\n * @remarks\n * Functions and templates are never serialized — sort comparers, filter\n * condition functions, and cell/header/editor templates are re-bound from the\n * live column configuration on restore. Filter conditions are captured as\n * operand name strings (e.g. `'contains'`). Selection / expansion / tree rows\n * are captured as {@link RowRef}s (a stable `id` when an `ApexGrid.rowId`\n * resolver is configured, otherwise a positional `index` into `ApexGrid.data`,\n * which round-trips within a session but not across a data reload).\n */\nexport interface GridState {\n /** Snapshot schema version. */\n version: 1;\n /** Per-column layout (order, width, pinning, visibility). */\n columns: ColumnLayoutState[];\n /** Active sort expressions (comparer functions omitted). */\n sort: SortStateSnapshot[];\n /** Active per-column filter expressions (condition captured by operand name). */\n filter: FilterStateSnapshot[];\n /** Global quick-filter term. */\n quickFilter: string;\n /** Pagination position. */\n pagination: { page: number; pageSize: number };\n /** Selected rows. */\n selection: RowRef[];\n /** Expanded (master-detail) rows. */\n expansion: RowRef[];\n /** Expanded tree rows that have backing data. */\n treeExpanded: RowRef[];\n /** Expanded synthesized tree parents (path-keyed; already string-stable). */\n treeExpandedKeys: string[];\n /**\n * Pinned rows (F4) by {@link RowRef}, per band. Optional: absent on snapshots\n * produced before row pinning existed; `getState` always emits it (empty bands\n * when nothing is pinned).\n */\n rowPinning?: { top: RowRef[]; bottom: RowRef[] };\n /**\n * Manual drag-reorder order (F5) as a full {@link RowRef} list, or `null` for\n * the derived (filter → sort) order. Optional for back-compat; `getState`\n * always emits it (`null` when no manual order is active). Mutually exclusive\n * with `sort`: a snapshot carrying both drops `rowOrder` on restore.\n */\n rowOrder?: RowRef[] | null;\n /** Per-module serialized state, keyed by module id. */\n modules: Record<string, unknown>;\n}\n\n/** Layout state for a single column. Order is implied by array position. */\nexport interface ColumnLayoutState {\n key: string;\n width?: string;\n pinned?: PinPosition;\n hidden?: boolean;\n}\n\n/** A single sort expression, stripped of its (non-serializable) comparer. */\nexport interface SortStateSnapshot {\n key: string;\n direction: SortingDirection;\n caseSensitive?: boolean;\n}\n\n/** A single filter expression with its condition captured by operand name. */\nexport interface FilterStateSnapshot {\n key: string;\n /** Operand name, e.g. `'contains'` / `'greaterThan'` (see the `*Operands`). */\n operand: string;\n searchTerm?: unknown;\n criteria?: FilterCriteria;\n caseSensitive?: boolean;\n}\n\n/**\n * A reference to a row in `ApexGrid.data`: a stable `id` (when an\n * `ApexGrid.rowId` resolver is configured) or a positional `index`.\n */\nexport type RowRef = { readonly id: string | number } | { readonly index: number };\n\n/** Options for `ApexGrid.getState`. */\nexport interface GetStateOptions<T extends object> {\n /** Row-identity resolver; overrides `ApexGrid.rowId` for this call. */\n rowId?: (row: T) => string | number;\n}\n\n/** Options for `ApexGrid.setState`. */\nexport interface SetStateOptions<T extends object> {\n /** Row-identity resolver; overrides `ApexGrid.rowId` for this call. */\n rowId?: (row: T) => string | number;\n /**\n * Throw on the first problem instead of degrading. Off by default: `setState`\n * applies what it can and reports the rest via {@link SetStateResult.warnings}\n * (the right behavior for LLM-produced or persisted-and-possibly-stale input).\n * Turn on for tests / development to fail loudly.\n */\n strict?: boolean;\n}\n\n/**\n * The outcome of an {@link SetStateOptions} apply. `setState` never throws on\n * malformed input (unless `strict`): it applies recognized slices, skips the\n * rest, and records human-readable {@link warnings} for anything dropped,\n * clamped, or unresolved.\n */\nexport interface SetStateResult {\n /** Slice names that were present and applied (e.g. `'sort'`, `'columns'`). */\n applied: string[];\n /** Known slice names that were absent (left untouched). */\n skipped: string[];\n /** What was dropped / clamped / unresolved, one message each. */\n warnings: string[];\n}\n\n// --- columns ---------------------------------------------------------------\n\n/** Capture the layout-managed properties of each column, in array order. */\nexport function serializeColumnLayout<T extends object>(\n columns: ReadonlyArray<ColumnConfiguration<T>>\n): ColumnLayoutState[] {\n return columns.map((column) => ({\n key: String(column.key),\n width: column.width,\n pinned: column.pinned ?? undefined,\n hidden: column.hidden ?? undefined,\n }));\n}\n\n/**\n * Return a new columns array reordered to match `layout`, with width / pinning /\n * visibility applied. Column objects are shallow-cloned so non-layout\n * properties (templates, comparers, type config) are preserved. Columns absent\n * from `layout` are appended unchanged; layout entries with no matching column\n * are ignored.\n */\nexport function applyColumnLayout<T extends object>(\n columns: ReadonlyArray<ColumnConfiguration<T>>,\n layout: ReadonlyArray<ColumnLayoutState>\n): ColumnConfiguration<T>[] {\n const byKey = new Map<string, ColumnConfiguration<T>>();\n for (const column of columns) byKey.set(String(column.key), column);\n\n const used = new Set<string>();\n const ordered: ColumnConfiguration<T>[] = [];\n for (const entry of layout) {\n const column = byKey.get(entry.key);\n if (!column) continue;\n used.add(entry.key);\n ordered.push({\n ...column,\n width: entry.width,\n pinned: entry.pinned ?? undefined,\n hidden: entry.hidden ?? false,\n } as ColumnConfiguration<T>);\n }\n for (const column of columns) {\n if (!used.has(String(column.key))) ordered.push(column);\n }\n return ordered;\n}\n\n// --- sort ------------------------------------------------------------------\n\nexport function serializeSort<T extends object>(\n expressions: ReadonlyArray<SortExpression<T>>\n): SortStateSnapshot[] {\n return expressions.map((expression) => ({\n key: String(expression.key),\n direction: expression.direction,\n caseSensitive: expression.caseSensitive,\n }));\n}\n\n// --- filter ----------------------------------------------------------------\n\nexport function serializeFilter<T extends object>(\n expressions: ReadonlyArray<FilterExpression<T>>\n): FilterStateSnapshot[] {\n return expressions.map((expression) => {\n const condition = expression.condition as FilterOperation<unknown> | string;\n return {\n key: String(expression.key),\n operand: typeof condition === 'string' ? condition : condition.name,\n searchTerm: expression.searchTerm,\n criteria: expression.criteria,\n caseSensitive: expression.caseSensitive,\n };\n });\n}\n\n/**\n * Rebuild filter expressions from a snapshot, resolving each operand name back\n * to a live {@link FilterOperation} via the target column's operand set.\n * Entries whose column or operand can't be resolved are dropped; `onDrop` (when\n * given) is called with the dropped entry and a reason.\n */\nexport function deserializeFilter<T extends object>(\n snapshots: ReadonlyArray<FilterStateSnapshot>,\n getColumn: (key: string) => ColumnConfiguration<T> | undefined,\n onDrop?: (snapshot: FilterStateSnapshot, reason: string) => void\n): FilterExpression<T>[] {\n const expressions: FilterExpression<T>[] = [];\n for (const snapshot of snapshots) {\n const column = getColumn(snapshot.key);\n if (!column) {\n onDrop?.(snapshot, 'unknown column');\n continue;\n }\n const operands = getFilterOperandsFor(column) as unknown as Record<\n string,\n FilterOperation<unknown>\n >;\n const condition = operands[snapshot.operand];\n if (!condition) {\n onDrop?.(snapshot, `unknown operand \"${snapshot.operand}\"`);\n continue;\n }\n expressions.push({\n key: snapshot.key as Keys<T>,\n condition,\n searchTerm: snapshot.searchTerm,\n criteria: snapshot.criteria,\n caseSensitive: snapshot.caseSensitive,\n } as unknown as FilterExpression<T>);\n }\n return expressions;\n}\n\n// --- row references --------------------------------------------------------\n\n/**\n * Serialize a set of rows to {@link RowRef}s. With a `rowId` resolver each row\n * is captured by id; otherwise by its positional index in `universe`\n * (`ApexGrid.data`). Rows not found in `universe` (index mode) are skipped.\n */\nexport function serializeRowRefs<T extends object>(\n rows: ReadonlyArray<T>,\n universe: ReadonlyArray<T>,\n rowId?: (row: T) => string | number\n): RowRef[] {\n const refs: RowRef[] = [];\n for (const row of rows) {\n if (rowId) {\n refs.push({ id: rowId(row) });\n } else {\n const index = universe.indexOf(row);\n if (index !== -1) refs.push({ index });\n }\n }\n return refs;\n}\n\n/**\n * Resolve {@link RowRef}s back to rows in `universe`. `id` refs require a\n * `rowId` resolver (otherwise they're skipped); `index` refs resolve\n * positionally. Unresolvable refs are dropped.\n */\nexport function resolveRowRefs<T extends object>(\n refs: ReadonlyArray<RowRef>,\n universe: ReadonlyArray<T>,\n rowId?: (row: T) => string | number\n): T[] {\n const out: T[] = [];\n let byId: Map<string | number, T> | null = null;\n for (const ref of refs) {\n if ('id' in ref) {\n if (!rowId) continue;\n if (!byId) {\n byId = new Map();\n for (const row of universe) byId.set(rowId(row), row);\n }\n const row = byId.get(ref.id);\n if (row) out.push(row);\n } else {\n const row = universe[ref.index];\n if (row) out.push(row);\n }\n }\n return out;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"state-snapshot.js","sourceRoot":"","sources":["../../src/internal/state-snapshot.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n FilterCriteria,\n FilterExpression,\n FilterOperation,\n} from '../operations/filter/types.js';\nimport type { SortExpression, SortingDirection } from '../operations/sort/types.js';\nimport type { ColumnConfiguration, Keys, PinPosition } from './types.js';\nimport { getFilterOperandsFor } from './utils.js';\n\n/**\n * A serializable, JSON-safe snapshot of the grid's restorable state, produced by\n * `ApexGrid.getState` and consumed by `ApexGrid.setState`.\n *\n * @remarks\n * Functions and templates are never serialized — sort comparers, filter\n * condition functions, and cell/header/editor templates are re-bound from the\n * live column configuration on restore. Filter conditions are captured as\n * operand name strings (e.g. `'contains'`). Selection / expansion / tree rows\n * are captured as {@link RowRef}s (a stable `id` when an `ApexGrid.rowId`\n * resolver is configured, otherwise a positional `index` into `ApexGrid.data`,\n * which round-trips within a session but not across a data reload).\n */\nexport interface GridState {\n /** Snapshot schema version. */\n version: 1;\n /** Per-column layout (order, width, pinning, visibility). */\n columns: ColumnLayoutState[];\n /** Active sort expressions (comparer functions omitted). */\n sort: SortStateSnapshot[];\n /** Active per-column filter expressions (condition captured by operand name). */\n filter: FilterStateSnapshot[];\n /** Global quick-filter term. */\n quickFilter: string;\n /** Pagination position. */\n pagination: { page: number; pageSize: number };\n /** Selected rows. */\n selection: RowRef[];\n /** Expanded (master-detail) rows. */\n expansion: RowRef[];\n /** Expanded tree rows that have backing data. */\n treeExpanded: RowRef[];\n /** Expanded synthesized tree parents (path-keyed; already string-stable). */\n treeExpandedKeys: string[];\n /**\n * Pinned rows (F4) by {@link RowRef}, per band. Optional: absent on snapshots\n * produced before row pinning existed; `getState` always emits it (empty bands\n * when nothing is pinned).\n */\n rowPinning?: { top: RowRef[]; bottom: RowRef[] };\n /**\n * Manual drag-reorder order (F5) as a full {@link RowRef} list, or `null` for\n * the derived (filter → sort) order. Optional for back-compat; `getState`\n * always emits it (`null` when no manual order is active). Mutually exclusive\n * with `sort`: a snapshot carrying both drops `rowOrder` on restore.\n */\n rowOrder?: RowRef[] | null;\n /** Per-module serialized state, keyed by module id. */\n modules: Record<string, unknown>;\n}\n\n/** Layout state for a single column. Order is implied by array position. */\nexport interface ColumnLayoutState {\n key: string;\n width?: string;\n pinned?: PinPosition;\n hidden?: boolean;\n}\n\n/** A single sort expression, stripped of its (non-serializable) comparer. */\nexport interface SortStateSnapshot {\n key: string;\n direction: SortingDirection;\n caseSensitive?: boolean;\n}\n\n/** A single filter expression with its condition captured by operand name. */\nexport interface FilterStateSnapshot {\n key: string;\n /** Operand name, e.g. `'contains'` / `'greaterThan'` (see the `*Operands`). */\n operand: string;\n searchTerm?: unknown;\n criteria?: FilterCriteria;\n caseSensitive?: boolean;\n}\n\n/**\n * A reference to a row in `ApexGrid.data`: a stable `id` (when an\n * `ApexGrid.rowId` resolver is configured) or a positional `index`.\n */\nexport type RowRef = { readonly id: string | number } | { readonly index: number };\n\n/** Options for `ApexGrid.getState`. */\nexport interface GetStateOptions<T extends object> {\n /** Row-identity resolver; overrides `ApexGrid.rowId` for this call. */\n rowId?: (row: T) => string | number;\n}\n\n/** Options for `ApexGrid.setState`. */\nexport interface SetStateOptions<T extends object> {\n /** Row-identity resolver; overrides `ApexGrid.rowId` for this call. */\n rowId?: (row: T) => string | number;\n /**\n * Throw on the first problem instead of degrading. Off by default: `setState`\n * applies what it can and reports the rest via {@link SetStateResult.warnings}\n * (the right behavior for LLM-produced or persisted-and-possibly-stale input).\n * Turn on for tests / development to fail loudly.\n */\n strict?: boolean;\n}\n\n/**\n * The `setState` slices in the order `setState` applies them, each mapped to\n * the {@link GridState} keys it restores (`tree` restores both tree keys).\n */\nexport const SET_STATE_SLICE_KEYS = {\n columns: ['columns'],\n sort: ['sort'],\n filter: ['filter'],\n quickFilter: ['quickFilter'],\n modules: ['modules'],\n rowOrder: ['rowOrder'],\n tree: ['treeExpanded', 'treeExpandedKeys'],\n expansion: ['expansion'],\n rowPinning: ['rowPinning'],\n selection: ['selection'],\n pagination: ['pagination'],\n} as const satisfies Record<string, ReadonlyArray<keyof GridState>>;\n\n/** A `setState` slice name, as reported in {@link SetStateResult}. */\nexport type SetStateSlice = keyof typeof SET_STATE_SLICE_KEYS;\n\n/** Every slice name, in apply order. */\nexport const SET_STATE_SLICES = Object.keys(SET_STATE_SLICE_KEYS) as SetStateSlice[];\n\n// Compile-time check: a new GridState key cannot be added without a slice.\nconst _everyKeyHasASlice: Exclude<\n keyof GridState,\n 'version' | (typeof SET_STATE_SLICE_KEYS)[SetStateSlice][number]\n> extends never\n ? true\n : never = true;\nvoid _everyKeyHasASlice;\n\n/**\n * The outcome of an {@link SetStateOptions} apply. `setState` never throws on\n * malformed input (unless `strict`): it applies recognized slices, skips the\n * rest, and records human-readable {@link warnings} for anything dropped,\n * clamped, or unresolved.\n */\nexport interface SetStateResult {\n /**\n * Slice names that were present and applied (e.g. `'sort'`, `'columns'`); see\n * {@link SET_STATE_SLICE_KEYS} for the {@link GridState} keys of each.\n */\n applied: string[];\n /** Known slice names ({@link SetStateSlice}) that were absent or not applied. */\n skipped: string[];\n /** What was dropped / clamped / unresolved, one message each. */\n warnings: string[];\n}\n\n/** A non-null object with a string `key`: the shape every keyed entry needs. */\nfunction isKeyed(value: unknown): value is { key: string } {\n return typeof value === 'object' && value !== null && typeof (value as any).key === 'string';\n}\n\n// --- columns ---------------------------------------------------------------\n\n/** Capture the layout-managed properties of each column, in array order. */\nexport function serializeColumnLayout<T extends object>(\n columns: ReadonlyArray<ColumnConfiguration<T>>\n): ColumnLayoutState[] {\n return columns.map((column) => ({\n key: String(column.key),\n width: column.width,\n pinned: column.pinned ?? undefined,\n hidden: column.hidden ?? undefined,\n }));\n}\n\n/**\n * Return a new columns array reordered to match `layout`, with width / pinning /\n * visibility applied. Column objects are shallow-cloned so non-layout\n * properties (templates, comparers, type config) are preserved. Columns absent\n * from `layout` are appended unchanged; layout entries with no matching column,\n * a repeated key, or no string `key` are ignored. This is the full-layout\n * restorer: to change a few fields in place, overlay them with\n * {@link mergeColumnLayout} first.\n */\nexport function applyColumnLayout<T extends object>(\n columns: ReadonlyArray<ColumnConfiguration<T>>,\n layout: ReadonlyArray<ColumnLayoutState>\n): ColumnConfiguration<T>[] {\n const byKey = new Map<string, ColumnConfiguration<T>>();\n for (const column of columns) byKey.set(String(column.key), column);\n\n const used = new Set<string>();\n const ordered: ColumnConfiguration<T>[] = [];\n for (const entry of layout) {\n if (!isKeyed(entry) || used.has(entry.key)) continue;\n const column = byKey.get(entry.key);\n if (!column) continue;\n used.add(entry.key);\n ordered.push({\n ...column,\n width: entry.width,\n pinned: entry.pinned ?? undefined,\n hidden: entry.hidden ?? false,\n } as ColumnConfiguration<T>);\n }\n for (const column of columns) {\n if (!used.has(String(column.key))) ordered.push(column);\n }\n return ordered;\n}\n\n/**\n * Overlay a partial layout onto `current` (a full {@link serializeColumnLayout}\n * result): each `partial` entry changes only the fields it defines on the\n * column with the same key, and the order of `current` is kept. `null` clears\n * a field (e.g. `pinned: null` unpins). Entries for unknown keys are ignored.\n * Returns a new full layout to hand to `setState({ columns })`.\n */\nexport function mergeColumnLayout(\n current: ReadonlyArray<ColumnLayoutState>,\n partial: ReadonlyArray<Partial<Record<keyof ColumnLayoutState, unknown>>>\n): ColumnLayoutState[] {\n const patches = new Map<string, Record<string, unknown>>();\n for (const entry of partial) {\n if (isKeyed(entry)) patches.set(entry.key, entry);\n }\n return current.map((column) => {\n const next: Record<string, unknown> = { ...column };\n const patch = patches.get(column.key);\n if (patch) {\n for (const field of ['width', 'pinned', 'hidden'] as const) {\n if (patch[field] !== undefined) next[field] = patch[field] ?? undefined;\n }\n }\n return next as unknown as ColumnLayoutState;\n });\n}\n\n// --- sort ------------------------------------------------------------------\n\nexport function serializeSort<T extends object>(\n expressions: ReadonlyArray<SortExpression<T>>\n): SortStateSnapshot[] {\n return expressions.map((expression) => ({\n key: String(expression.key),\n direction: expression.direction,\n caseSensitive: expression.caseSensitive,\n }));\n}\n\n// --- filter ----------------------------------------------------------------\n\nfunction copyTerm(term: unknown): unknown {\n return Array.isArray(term) ? [...term] : term;\n}\n\nexport function serializeFilter<T extends object>(\n expressions: ReadonlyArray<FilterExpression<T>>\n): FilterStateSnapshot[] {\n return expressions.map((expression) => {\n const condition = expression.condition as FilterOperation<unknown> | string;\n return {\n key: String(expression.key),\n operand: typeof condition === 'string' ? condition : condition.name,\n // A copied array term, so editing a snapshot never edits the live filter.\n searchTerm: copyTerm(expression.searchTerm),\n criteria: expression.criteria,\n caseSensitive: expression.caseSensitive,\n };\n });\n}\n\n/** Operands a first-party filter UI registered, resolvable on any column. */\nconst registeredOperands = new Map<string, FilterOperation<unknown>>();\n\n/**\n * Make `operation` resolvable by its `name` on every column, after the\n * column type's own operands. For first-party filter UIs (the enterprise set\n * filter) whose expressions must survive `setState(getState())`. The\n * operation must be stateless: everything it needs travels in `searchTerm`.\n */\nexport function registerFilterOperand(operation: FilterOperation<unknown>): void {\n registeredOperands.set(operation.name, operation);\n}\n\n/**\n * Resolve a filter operand name (e.g. `'contains'`) to the live\n * {@link FilterOperation} of `column`'s type, else to one registered with\n * {@link registerFilterOperand}. Only the tables' own names resolve, so\n * `'toString'` or `'constructor'` never pass as operands.\n */\nexport function resolveFilterOperand<T extends object>(\n column: ColumnConfiguration<T>,\n name: unknown\n): FilterOperation<unknown> | undefined {\n if (typeof name !== 'string') return undefined;\n const operands = getFilterOperandsFor(column) as unknown as Record<\n string,\n FilterOperation<unknown>\n >;\n return Object.hasOwn(operands, name) ? operands[name] : registeredOperands.get(name);\n}\n\n/**\n * Rebuild filter expressions from a snapshot, resolving each operand name back\n * to a live {@link FilterOperation} via the target column's operand set.\n * Entries that are not keyed objects, whose column or operand can't be\n * resolved, or whose binary operand has no `searchTerm` are dropped; `onDrop`\n * (when given) is called with the dropped entry and a reason.\n */\nexport function deserializeFilter<T extends object>(\n snapshots: ReadonlyArray<FilterStateSnapshot>,\n getColumn: (key: string) => ColumnConfiguration<T> | undefined,\n onDrop?: (snapshot: FilterStateSnapshot, reason: string) => void\n): FilterExpression<T>[] {\n const expressions: FilterExpression<T>[] = [];\n for (const snapshot of snapshots) {\n if (!isKeyed(snapshot)) {\n onDrop?.({ key: String(snapshot) } as FilterStateSnapshot, 'not a filter entry');\n continue;\n }\n const column = getColumn(snapshot.key);\n if (!column) {\n onDrop?.(snapshot, 'unknown column');\n continue;\n }\n const condition = resolveFilterOperand(column, snapshot.operand);\n if (!condition) {\n onDrop?.(snapshot, `unknown operand \"${snapshot.operand}\"`);\n continue;\n }\n if (!condition.unary && (snapshot.searchTerm === undefined || snapshot.searchTerm === null)) {\n onDrop?.(snapshot, `operand \"${snapshot.operand}\" needs a searchTerm`);\n continue;\n }\n // Omitted fields stay absent so the column defaults (case sensitivity,\n // 'and' criteria) apply rather than an explicit undefined.\n const expression: Record<string, unknown> = { key: snapshot.key as Keys<T>, condition };\n if (snapshot.searchTerm !== undefined) expression.searchTerm = copyTerm(snapshot.searchTerm);\n if (snapshot.criteria !== undefined) expression.criteria = snapshot.criteria;\n if (snapshot.caseSensitive !== undefined) expression.caseSensitive = snapshot.caseSensitive;\n expressions.push(expression as unknown as FilterExpression<T>);\n }\n return expressions;\n}\n\n// --- row references --------------------------------------------------------\n\n/**\n * Serialize a set of rows to {@link RowRef}s. With a `rowId` resolver each row\n * is captured by id; otherwise by its positional index in `universe`\n * (`ApexGrid.data`). Rows not found in `universe` (index mode) are skipped.\n * Index mode builds one position map per call, so it is linear in the sizes\n * of `rows` and `universe` rather than their product.\n */\nexport function serializeRowRefs<T extends object>(\n rows: ReadonlyArray<T>,\n universe: ReadonlyArray<T>,\n rowId?: (row: T) => string | number\n): RowRef[] {\n if (rowId) return rows.map((row) => ({ id: rowId(row) }));\n if (rows.length < 2) {\n // A single lookup is cheaper than building the map.\n const index = rows.length ? universe.indexOf(rows[0]) : -1;\n return index === -1 ? [] : [{ index }];\n }\n const positions = new Map<T, number>();\n universe.forEach((row, index) => {\n if (!positions.has(row)) positions.set(row, index);\n });\n const refs: RowRef[] = [];\n for (const row of rows) {\n const index = positions.get(row);\n if (index !== undefined) refs.push({ index });\n }\n return refs;\n}\n\n/**\n * Resolve {@link RowRef}s back to rows in `universe`. `id` refs require a\n * `rowId` resolver (otherwise they're skipped); `index` refs resolve\n * positionally and must be non-negative integers. Refs that are not objects,\n * and unresolvable refs, are dropped.\n */\nexport function resolveRowRefs<T extends object>(\n refs: ReadonlyArray<RowRef>,\n universe: ReadonlyArray<T>,\n rowId?: (row: T) => string | number\n): T[] {\n const out: T[] = [];\n let byId: Map<string | number, T> | null = null;\n for (const ref of refs) {\n if (typeof ref !== 'object' || ref === null) continue;\n if ('id' in ref) {\n if (!rowId) continue;\n if (!byId) {\n byId = new Map();\n for (const row of universe) byId.set(rowId(row), row);\n }\n const row = byId.get(ref.id);\n if (row) out.push(row);\n } else if (Number.isInteger(ref.index) && ref.index >= 0) {\n const row = universe[ref.index];\n if (row) out.push(row);\n }\n }\n return out;\n}\n"]}
|