@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.
- package/dist/custom-elements.json +171 -0
- package/dist/dts/create-grid-pro-cell-portals.d.ts +81 -0
- package/dist/dts/create-grid-pro-cell-portals.d.ts.map +1 -0
- package/dist/dts/create-grid-pro-cell-renderer.d.ts +140 -0
- package/dist/dts/create-grid-pro-cell-renderer.d.ts.map +1 -0
- package/dist/dts/index.d.ts +7 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/create-grid-pro-cell-portals.js +138 -0
- package/dist/esm/create-grid-pro-cell-renderer.js +141 -0
- package/dist/esm/index.js +5 -0
- package/dist/foundation-react-utils.api.json +763 -0
- package/dist/foundation-react-utils.d.ts +223 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -13
- package/src/create-grid-pro-cell-portals.tsx +216 -0
- package/src/create-grid-pro-cell-renderer.ts +235 -0
- package/src/index.ts +11 -0
|
@@ -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"}
|
package/dist/dts/index.d.ts
CHANGED
|
@@ -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
|
package/dist/dts/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA
|
|
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
|
+
}
|