@genesislcap/foundation-react-utils 14.481.2-alpha-829ad82.0 → 14.482.1-FUI-2575.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.
@@ -2,6 +2,129 @@
2
2
  "schemaVersion": "1.0.0",
3
3
  "readme": "",
4
4
  "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/create-grid-pro-cell-renderer.ts",
8
+ "declarations": [
9
+ {
10
+ "kind": "mixin",
11
+ "description": "Wraps a React component as an AG Grid cell renderer component class for use with\n`grid-pro` / `grid-pro-beta` (`<foundation-grid-pro>` / `<rapid-grid-pro>`).\n\nGrid Pro is a framework-agnostic Web Component, so AG Grid inside it only understands\nplain-JS component classes. This helper bridges the gap: it returns a class implementing\n`ICellRendererComp` that mounts the React component into the cell with its own React root,\nre-renders it on `refresh` (so value changes and cell flashing keep working without\nremounting), and unmounts it when the cell is destroyed.\n\nThe component receives the full AG Grid `ICellRendererParams` object as props — including\n`value`, `data`, `node`, `api` and anything supplied via the column's `cellRendererParams`.\nHooks and local state inside the component work as normal.\n\nNote on React Context/Redux: by default each cell is rendered into its own independent\nReact root, so renderers do NOT inherit contexts (Redux providers, theme context, React\nRouter, etc.) from the application tree hosting the grid. Either pass data/callbacks\nexplicitly via `cellRendererParams`, or opt into portal mode with the `portals` option\n(see GridProCellRendererOptions.portals and `createGridProCellPortals`) — portal\ncells share the application tree and inherit its contexts.\n\nNote on `key`: props are passed by spreading the AG Grid params object, and React reserves\n`key` — a `cellRendererParams` entry named `key` is consumed as the element key and never\nreaches the component, so avoid that name. (`ref` is fine: React 19 forwards it to function\ncomponents as a regular prop.)\n\nNote on styling: cells render inside grid-pro's shadow root, so document-level stylesheets\n(CSS files imported by your app/page) do NOT reach the rendered component. Style renderers\nwith inline styles or CSS-in-JS. Design-system tokens remain usable either way — CSS custom\nproperties inherit across shadow boundaries (e.g. `color: 'var(--accent-fill-rest)'`).",
12
+ "name": "createGridProCellRenderer",
13
+ "members": [
14
+ {
15
+ "kind": "field",
16
+ "name": "container",
17
+ "type": {
18
+ "text": "HTMLElement"
19
+ },
20
+ "privacy": "private"
21
+ },
22
+ {
23
+ "kind": "field",
24
+ "name": "root",
25
+ "type": {
26
+ "text": "Root | null"
27
+ },
28
+ "privacy": "private",
29
+ "default": "null"
30
+ },
31
+ {
32
+ "kind": "field",
33
+ "name": "portalId",
34
+ "type": {
35
+ "text": "number | null"
36
+ },
37
+ "privacy": "private",
38
+ "default": "null"
39
+ },
40
+ {
41
+ "kind": "method",
42
+ "name": "init",
43
+ "privacy": "public",
44
+ "return": {
45
+ "type": {
46
+ "text": "void"
47
+ }
48
+ },
49
+ "parameters": [
50
+ {
51
+ "name": "params",
52
+ "type": {
53
+ "text": "P"
54
+ }
55
+ }
56
+ ]
57
+ },
58
+ {
59
+ "kind": "method",
60
+ "name": "getGui",
61
+ "privacy": "public",
62
+ "return": {
63
+ "type": {
64
+ "text": "HTMLElement"
65
+ }
66
+ }
67
+ },
68
+ {
69
+ "kind": "method",
70
+ "name": "refresh",
71
+ "privacy": "public",
72
+ "return": {
73
+ "type": {
74
+ "text": "boolean"
75
+ }
76
+ },
77
+ "parameters": [
78
+ {
79
+ "name": "params",
80
+ "type": {
81
+ "text": "P"
82
+ }
83
+ }
84
+ ]
85
+ },
86
+ {
87
+ "kind": "method",
88
+ "name": "destroy",
89
+ "privacy": "public",
90
+ "return": {
91
+ "type": {
92
+ "text": "void"
93
+ }
94
+ }
95
+ }
96
+ ],
97
+ "parameters": [
98
+ {
99
+ "name": "Component",
100
+ "type": {
101
+ "text": "ComponentType<P>"
102
+ },
103
+ "description": "The React component to render inside the cell."
104
+ },
105
+ {
106
+ "name": "options",
107
+ "default": "{}",
108
+ "type": {
109
+ "text": "GridProCellRendererOptions"
110
+ },
111
+ "description": "Optional {@link GridProCellRendererOptions}to tune the wrapper behaviour.\n * "
112
+ }
113
+ ],
114
+ "privacy": "public"
115
+ }
116
+ ],
117
+ "exports": [
118
+ {
119
+ "kind": "js",
120
+ "name": "createGridProCellRenderer",
121
+ "declaration": {
122
+ "name": "createGridProCellRenderer",
123
+ "module": "src/create-grid-pro-cell-renderer.ts"
124
+ }
125
+ }
126
+ ]
127
+ },
5
128
  {
6
129
  "kind": "javascript-module",
7
130
  "path": "src/create-react-renderer.ts",
@@ -83,6 +206,54 @@
83
206
  "module": "./create-react-renderer"
84
207
  }
85
208
  },
209
+ {
210
+ "kind": "js",
211
+ "name": "createGridProCellRenderer",
212
+ "declaration": {
213
+ "name": "createGridProCellRenderer",
214
+ "module": "./create-grid-pro-cell-renderer"
215
+ }
216
+ },
217
+ {
218
+ "kind": "js",
219
+ "name": "createGridProCellPortals",
220
+ "declaration": {
221
+ "name": "createGridProCellPortals",
222
+ "module": "./create-grid-pro-cell-portals"
223
+ }
224
+ },
225
+ {
226
+ "kind": "js",
227
+ "name": "GridProCellPortals",
228
+ "declaration": {
229
+ "name": "GridProCellPortals",
230
+ "module": "./create-grid-pro-cell-portals"
231
+ }
232
+ },
233
+ {
234
+ "kind": "js",
235
+ "name": "GridProCellRendererOptions",
236
+ "declaration": {
237
+ "name": "GridProCellRendererOptions",
238
+ "module": "./create-grid-pro-cell-renderer"
239
+ }
240
+ },
241
+ {
242
+ "kind": "js",
243
+ "name": "GridProCellRendererProps",
244
+ "declaration": {
245
+ "name": "GridProCellRendererProps",
246
+ "module": "./create-grid-pro-cell-renderer"
247
+ }
248
+ },
249
+ {
250
+ "kind": "js",
251
+ "name": "GridProReactCellRenderer",
252
+ "declaration": {
253
+ "name": "GridProReactCellRenderer",
254
+ "module": "./create-grid-pro-cell-renderer"
255
+ }
256
+ },
86
257
  {
87
258
  "kind": "js",
88
259
  "name": "RendererControlProps",
@@ -0,0 +1,81 @@
1
+ import { type ComponentType } from 'react';
2
+ /**
3
+ * Shared portal manager for Grid Pro React cell renderers.
4
+ *
5
+ * Created with {@link createGridProCellPortals}. Render the {@link GridProCellPortals.Portals}
6
+ * component exactly once inside your React tree — cells rendered through this manager become
7
+ * part of that tree, so they inherit React Context (Redux providers, theme, router, etc.) from
8
+ * wherever `Portals` sits. Pass the manager to {@link createGridProCellRenderer} via the
9
+ * `portals` option to opt a renderer into portal mode.
10
+ *
11
+ * @public
12
+ */
13
+ export interface GridProCellPortals {
14
+ /**
15
+ * Host component for all cells rendered through this manager. Render it exactly once,
16
+ * inside every provider the cell renderers should inherit, and keep it mounted for as
17
+ * long as the grid is on screen — unmounting it blanks all portal-rendered cells.
18
+ */
19
+ Portals: ComponentType;
20
+ /**
21
+ * Mounts a component into a cell container and returns the entry id.
22
+ * Called by the cell renderer wrapper — not intended for direct use.
23
+ * @internal
24
+ */
25
+ mount(container: HTMLElement, Component: ComponentType<any>, params: any): number;
26
+ /**
27
+ * Re-renders a mounted cell with new params.
28
+ * Called by the cell renderer wrapper — not intended for direct use.
29
+ * @internal
30
+ */
31
+ update(id: number, params: any): void;
32
+ /**
33
+ * Removes a mounted cell.
34
+ * Called by the cell renderer wrapper — not intended for direct use.
35
+ * @internal
36
+ */
37
+ remove(id: number): void;
38
+ }
39
+ /**
40
+ * Creates a {@link GridProCellPortals} manager: a single React root shared by every cell
41
+ * renderer registered with it, with each cell rendered into its grid cell via a portal.
42
+ *
43
+ * Use this instead of the default one-root-per-cell mode when cell renderers need to
44
+ * inherit React Context from the application tree (Redux, theme, router, query clients...)
45
+ * — portal-rendered cells live in the tree where `Portals` is rendered, so context updates
46
+ * propagate into visible cells like any other React state.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * const cellPortals = createGridProCellPortals();
51
+ *
52
+ * const gridOptions = {
53
+ * components: {
54
+ * priceCell: createGridProCellRenderer(PriceCell, { portals: cellPortals }),
55
+ * },
56
+ * columnDefs: [{ field: 'price', cellRenderer: 'priceCell' }],
57
+ * };
58
+ *
59
+ * function Page() {
60
+ * return (
61
+ * <SomeProvider>
62
+ * <cellPortals.Portals />
63
+ * <RapidGridPro gridOptions={gridOptions} />
64
+ * </SomeProvider>
65
+ * );
66
+ * }
67
+ * ```
68
+ *
69
+ * @remarks
70
+ * Trade-offs versus the default per-cell roots: all cells registered with one manager share
71
+ * a React tree, so a renderer that throws is contained by a per-cell error boundary (the
72
+ * failing cell renders empty rather than crashing the rest), and unmounting `Portals` while
73
+ * the grid is alive blanks every portal-rendered cell. Cell mounts are committed
74
+ * synchronously (so AG Grid measures real content), which re-renders the manager once per
75
+ * created cell — the per-cell portals are memoised, keeping that cheap at grid-pro's
76
+ * virtualised cell counts.
77
+ *
78
+ * @public
79
+ */
80
+ export declare function createGridProCellPortals(): GridProCellPortals;
81
+ //# sourceMappingURL=create-grid-pro-cell-portals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-grid-pro-cell-portals.d.ts","sourceRoot":"","sources":["../../src/create-grid-pro-cell-portals.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AAgBf;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,EAAE,aAAa,CAAC;IACvB;;;;OAIG;IACH,KAAK,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC;IAClF;;;;OAIG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC;IACtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAyCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,CAyE7D"}
@@ -0,0 +1,140 @@
1
+ import { type ComponentType } from 'react';
2
+ import type { GridProCellPortals } from './create-grid-pro-cell-portals';
3
+ /**
4
+ * Props passed to a React component used as a Grid Pro cell renderer.
5
+ *
6
+ * This is a structural subset of AG Grid's `ICellRendererParams` — the full params object
7
+ * (including any custom `cellRendererParams` from the column definition) is spread onto the
8
+ * component as props on every render, so anything available on `ICellRendererParams` is
9
+ * available here. Declared locally to avoid coupling this package to a specific
10
+ * `ag-grid-community` version.
11
+ *
12
+ * @public
13
+ */
14
+ export interface GridProCellRendererProps<TData = any, TValue = any> {
15
+ /** The cell value. */
16
+ value: TValue;
17
+ /** Value formatted by the column's value formatter, if any. */
18
+ valueFormatted?: string | null;
19
+ /** The full row data. */
20
+ data: TData;
21
+ /** The AG Grid row node. */
22
+ node: any;
23
+ /** The AG Grid api. */
24
+ api: any;
25
+ /** The row index of the cell. */
26
+ rowIndex: number;
27
+ /** The grid context object, as supplied via `gridOptions.context`. */
28
+ context?: any;
29
+ /** The column this cell belongs to. */
30
+ column?: any;
31
+ /** The column definition. */
32
+ colDef?: any;
33
+ /** Custom params from `cellRendererParams` and any other AG Grid params. */
34
+ [key: string]: any;
35
+ }
36
+ /**
37
+ * Options for {@link createGridProCellRenderer}.
38
+ *
39
+ * @public
40
+ */
41
+ export interface GridProCellRendererOptions {
42
+ /**
43
+ * When true (the default), the cell container is styled as a full-size flex row
44
+ * (`display: flex; align-items: center; height: 100%; width: 100%`) so content is
45
+ * vertically centred like grid-pro's built-in renderers.
46
+ *
47
+ * Set to false to leave the container unstyled and let the cell's own layout apply.
48
+ * Do this when the forced flex/height layout gets in the way, e.g.:
49
+ * - `autoHeight`/`wrapText` columns — `height: 100%` is circular when the row height
50
+ * derives from the content, so the cell can collapse instead of growing;
51
+ * - right-aligned numeric cells relying on `text-align` (a flex item packs to the start);
52
+ * - content using `text-overflow: ellipsis` (a flex item won't truncate without
53
+ * `min-width: 0`).
54
+ */
55
+ fillCell?: boolean;
56
+ /**
57
+ * Render cells through a shared {@link GridProCellPortals} manager instead of giving each
58
+ * cell its own React root. Portal-rendered cells become part of the React tree where the
59
+ * manager's `Portals` component is rendered, so they inherit React Context (Redux, theme,
60
+ * router, etc.) from the application — the main limitation of the default mode.
61
+ *
62
+ * Create one with `createGridProCellPortals()` and render `<manager.Portals />` once,
63
+ * inside the providers the cells should see. When omitted (the default), each cell gets
64
+ * its own isolated root.
65
+ */
66
+ portals?: GridProCellPortals;
67
+ }
68
+ /**
69
+ * The subset of AG Grid's `ICellRendererComp` contract implemented by the wrapper class
70
+ * returned from {@link createGridProCellRenderer}.
71
+ *
72
+ * @public
73
+ */
74
+ export interface GridProReactCellRenderer {
75
+ init(params: GridProCellRendererProps): void;
76
+ getGui(): HTMLElement;
77
+ refresh(params: GridProCellRendererProps): boolean;
78
+ destroy(): void;
79
+ }
80
+ /**
81
+ * Wraps a React component as an AG Grid cell renderer component class for use with
82
+ * `grid-pro` / `grid-pro-beta` (`<foundation-grid-pro>` / `<rapid-grid-pro>`).
83
+ *
84
+ * Grid Pro is a framework-agnostic Web Component, so AG Grid inside it only understands
85
+ * plain-JS component classes. This helper bridges the gap: it returns a class implementing
86
+ * `ICellRendererComp` that mounts the React component into the cell with its own React root,
87
+ * re-renders it on `refresh` (so value changes and cell flashing keep working without
88
+ * remounting), and unmounts it when the cell is destroyed.
89
+ *
90
+ * The component receives the full AG Grid `ICellRendererParams` object as props — including
91
+ * `value`, `data`, `node`, `api` and anything supplied via the column's `cellRendererParams`.
92
+ * Hooks and local state inside the component work as normal.
93
+ *
94
+ * Note on React Context/Redux: by default each cell is rendered into its own independent
95
+ * React root, so renderers do NOT inherit contexts (Redux providers, theme context, React
96
+ * Router, etc.) from the application tree hosting the grid. Either pass data/callbacks
97
+ * explicitly via `cellRendererParams`, or opt into portal mode with the `portals` option
98
+ * (see {@link GridProCellRendererOptions.portals} and `createGridProCellPortals`) — portal
99
+ * cells share the application tree and inherit its contexts.
100
+ *
101
+ * Note on `key`: props are passed by spreading the AG Grid params object, and React reserves
102
+ * `key` — a `cellRendererParams` entry named `key` is consumed as the element key and never
103
+ * reaches the component, so avoid that name. (`ref` is fine: React 19 forwards it to function
104
+ * components as a regular prop.)
105
+ *
106
+ * Note on styling: cells render inside grid-pro's shadow root, so document-level stylesheets
107
+ * (CSS files imported by your app/page) do NOT reach the rendered component. Style renderers
108
+ * with inline styles or CSS-in-JS. Design-system tokens remain usable either way — CSS custom
109
+ * properties inherit across shadow boundaries (e.g. `color: 'var(--accent-fill-rest)'`).
110
+ *
111
+ * @example
112
+ * ```tsx
113
+ * import { createGridProCellRenderer, type GridProCellRendererProps } from '@genesislcap/foundation-react-utils';
114
+ *
115
+ * function PriceCell({ value }: GridProCellRendererProps) {
116
+ * return <span style={{ color: value >= 0 ? 'green' : 'red' }}>{value}</span>;
117
+ * }
118
+ *
119
+ * const gridOptions = {
120
+ * components: {
121
+ * priceCell: createGridProCellRenderer(PriceCell),
122
+ * },
123
+ * columnDefs: [
124
+ * { field: 'price', cellRenderer: 'priceCell' },
125
+ * ],
126
+ * };
127
+ *
128
+ * // <rapid-grid-pro gridOptions={gridOptions} /> — or register via the grid's
129
+ * // `gridComponents` property to make the renderer available across all columns.
130
+ * ```
131
+ *
132
+ * @param Component - The React component to render inside the cell.
133
+ * @param options - Optional {@link GridProCellRendererOptions} to tune the wrapper behaviour.
134
+ * @returns A cell renderer component class registrable via `gridOptions.components`,
135
+ * the grid's `gridComponents` property, or directly as a column's `cellRenderer`.
136
+ *
137
+ * @public
138
+ */
139
+ export declare function createGridProCellRenderer<P extends GridProCellRendererProps = GridProCellRendererProps>(Component: ComponentType<P>, options?: GridProCellRendererOptions): new () => GridProReactCellRenderer;
140
+ //# sourceMappingURL=create-grid-pro-cell-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-grid-pro-cell-renderer.d.ts","sourceRoot":"","sources":["../../src/create-grid-pro-cell-renderer.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAG1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAIzE;;;;;;;;;;GAUG;AACH,MAAM,WAAW,wBAAwB,CAAC,KAAK,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG;IACjE,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,yBAAyB;IACzB,IAAI,EAAE,KAAK,CAAC;IACZ,4BAA4B;IAC5B,IAAI,EAAE,GAAG,CAAC;IACV,uBAAuB;IACvB,GAAG,EAAE,GAAG,CAAC;IACT,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,uCAAuC;IACvC,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,6BAA6B;IAC7B,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,4EAA4E;IAC5E,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,IAAI,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC7C,MAAM,IAAI,WAAW,CAAC;IACtB,OAAO,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC;IACnD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAgB,yBAAyB,CACvC,CAAC,SAAS,wBAAwB,GAAG,wBAAwB,EAE7D,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE,0BAA+B,GACvC,UAAU,wBAAwB,CAiFpC"}
@@ -7,10 +7,17 @@
7
7
  * - `createReactRenderer` — wraps a React component as a `RendererEntry` for use with
8
8
  * `foundation-forms` `additionalRenderers`. Use this instead of writing raw FAST templates
9
9
  * when your custom form renderer is authored in React/JSX.
10
+ * - `createGridProCellRenderer` — wraps a React component as an AG Grid cell renderer
11
+ * component class for use with `grid-pro` (register via `gridOptions.components` or the
12
+ * grid's `gridComponents` property).
10
13
  * - `reactFactory` / `reactFactoryWithProvider` — mount React component trees into
11
14
  * Genesis Foundation layout regions.
12
15
  */
13
16
  export { reactFactory, reactFactoryWithProvider } from './react-layout-factory';
14
17
  export { createReactRenderer } from './create-react-renderer';
18
+ export { createGridProCellRenderer } from './create-grid-pro-cell-renderer';
19
+ export { createGridProCellPortals } from './create-grid-pro-cell-portals';
20
+ export type { GridProCellPortals } from './create-grid-pro-cell-portals';
21
+ export type { GridProCellRendererOptions, GridProCellRendererProps, GridProReactCellRenderer, } from './create-grid-pro-cell-renderer';
15
22
  export type { RendererControlProps } from '@genesislcap/foundation-forms';
16
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACzE,YAAY,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,iCAAiC,CAAC;AACzC,YAAY,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,138 @@
1
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { createLogger } from '@genesislcap/foundation-logger';
3
+ import { Component as ReactClassComponent, memo, useEffect, useSyncExternalStore, } from 'react';
4
+ import { createPortal, flushSync } from 'react-dom';
5
+ const logger = createLogger('foundation-react-utils');
6
+ /**
7
+ * Error boundary around each portal-rendered cell. A shared React tree means one throwing
8
+ * renderer would otherwise unmount every portal cell in the grid — this contains the blast
9
+ * radius to the failing cell (which renders empty).
10
+ * @internal
11
+ */
12
+ class CellPortalErrorBoundary extends ReactClassComponent {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.state = { failed: false };
16
+ }
17
+ static getDerivedStateFromError() {
18
+ return { failed: true };
19
+ }
20
+ componentDidCatch(error) {
21
+ logger.error('Grid Pro portal cell renderer threw during render:', error);
22
+ }
23
+ render() {
24
+ return this.state.failed ? null : this.props.children;
25
+ }
26
+ }
27
+ /**
28
+ * One portal per cell. Memoised on the entry object — `update()` swaps the entry, so only
29
+ * the changed cell reconciles when the manager re-renders.
30
+ * @internal
31
+ */
32
+ const CellPortal = memo(function GridProCellPortal({ entry }) {
33
+ return createPortal(_jsx(CellPortalErrorBoundary, { children: _jsx(entry.Component, Object.assign({}, entry.params)) }), entry.container);
34
+ });
35
+ /**
36
+ * Creates a {@link GridProCellPortals} manager: a single React root shared by every cell
37
+ * renderer registered with it, with each cell rendered into its grid cell via a portal.
38
+ *
39
+ * Use this instead of the default one-root-per-cell mode when cell renderers need to
40
+ * inherit React Context from the application tree (Redux, theme, router, query clients...)
41
+ * — portal-rendered cells live in the tree where `Portals` is rendered, so context updates
42
+ * propagate into visible cells like any other React state.
43
+ *
44
+ * @example
45
+ * ```tsx
46
+ * const cellPortals = createGridProCellPortals();
47
+ *
48
+ * const gridOptions = {
49
+ * components: {
50
+ * priceCell: createGridProCellRenderer(PriceCell, { portals: cellPortals }),
51
+ * },
52
+ * columnDefs: [{ field: 'price', cellRenderer: 'priceCell' }],
53
+ * };
54
+ *
55
+ * function Page() {
56
+ * return (
57
+ * <SomeProvider>
58
+ * <cellPortals.Portals />
59
+ * <RapidGridPro gridOptions={gridOptions} />
60
+ * </SomeProvider>
61
+ * );
62
+ * }
63
+ * ```
64
+ *
65
+ * @remarks
66
+ * Trade-offs versus the default per-cell roots: all cells registered with one manager share
67
+ * a React tree, so a renderer that throws is contained by a per-cell error boundary (the
68
+ * failing cell renders empty rather than crashing the rest), and unmounting `Portals` while
69
+ * the grid is alive blanks every portal-rendered cell. Cell mounts are committed
70
+ * synchronously (so AG Grid measures real content), which re-renders the manager once per
71
+ * created cell — the per-cell portals are memoised, keeping that cheap at grid-pro's
72
+ * virtualised cell counts.
73
+ *
74
+ * @public
75
+ */
76
+ export function createGridProCellPortals() {
77
+ let entries = [];
78
+ let nextId = 0;
79
+ let portalsMounted = false;
80
+ const listeners = new Set();
81
+ const emit = () => {
82
+ listeners.forEach((listener) => listener());
83
+ };
84
+ /**
85
+ * Commits a store change synchronously so the cell content exists in the DOM before
86
+ * AG Grid measures the container (autoHeight, autoSizeColumns, sizeColumnsToFit).
87
+ * Mount runs from AG Grid's own (non-React) call stack, so flushing is safe; if it
88
+ * ever runs inside a host React render, React warns and defers the flush instead.
89
+ */
90
+ const emitSync = () => {
91
+ if (!portalsMounted) {
92
+ emit();
93
+ return;
94
+ }
95
+ flushSync(emit);
96
+ };
97
+ const subscribe = (listener) => {
98
+ listeners.add(listener);
99
+ return () => {
100
+ listeners.delete(listener);
101
+ };
102
+ };
103
+ const getSnapshot = () => entries;
104
+ const Portals = () => {
105
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot);
106
+ useEffect(() => {
107
+ portalsMounted = true;
108
+ return () => {
109
+ portalsMounted = false;
110
+ };
111
+ }, []);
112
+ return (_jsx(_Fragment, { children: snapshot.map((entry) => (_jsx(CellPortal, { entry: entry }, entry.id))) }));
113
+ };
114
+ return {
115
+ Portals,
116
+ mount(container, Component, params) {
117
+ nextId += 1;
118
+ const id = nextId;
119
+ entries = [...entries, { id, container, Component, params }];
120
+ emitSync();
121
+ return id;
122
+ },
123
+ update(id, params) {
124
+ entries = entries.map((entry) => (entry.id === id ? Object.assign(Object.assign({}, entry), { params }) : entry));
125
+ // Async on purpose: refresh() has already returned true and AG Grid does not
126
+ // re-measure on refresh, so there is nothing to commit synchronously for.
127
+ emit();
128
+ },
129
+ remove(id) {
130
+ entries = entries.filter((entry) => entry.id !== id);
131
+ // AG Grid can destroy cells synchronously while React is rendering (e.g. React
132
+ // Router unmounting the page hosting the grid); notifying subscribers there would
133
+ // set state mid-render, so defer with a macrotask — the container is already
134
+ // detached by AG Grid, so the portal lingering one tick is invisible.
135
+ setTimeout(emit);
136
+ },
137
+ };
138
+ }