@genesislcap/foundation-react-utils 15.31.0 → 15.32.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.
|
@@ -47,6 +47,18 @@ import type { ComponentType } from 'react';
|
|
|
47
47
|
* // form.additionalRenderers = [priceRendererEntry];
|
|
48
48
|
* ```
|
|
49
49
|
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* `uischema.options` may carry function values (e.g. AG-Grid `valueFormatter`, `comparator`,
|
|
52
|
+
* `cellRenderer`, however deeply nested — inside `columnDefs`, for instance) and they will
|
|
53
|
+
* reach your component intact, whether `uischema` is assigned before or after the element is
|
|
54
|
+
* connected to the DOM.
|
|
55
|
+
*
|
|
56
|
+
* The `props.uischema` your component receives is the *same object instance* JSON Forms holds
|
|
57
|
+
* internally, not a copy — treat it as read-only. Mutating it (e.g.
|
|
58
|
+
* `props.uischema.options.columnDefs.forEach(c => { c.width = measured })`) corrupts state shared
|
|
59
|
+
* with every sibling control and with subsequent reducer runs, since there is no serialization
|
|
60
|
+
* step to isolate your copy from the source.
|
|
61
|
+
*
|
|
50
62
|
* @public
|
|
51
63
|
*/
|
|
52
64
|
export declare function createReactRenderer(Component: ComponentType<RendererControlProps>, options: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-react-renderer.d.ts","sourceRoot":"","sources":["../../src/create-react-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"create-react-renderer.d.ts","sourceRoot":"","sources":["../../src/create-react-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAI3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,aAAa,CAAC,oBAAoB,CAAC,EAC9C,OAAO,EAAE;IACP;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,KAAK,mBAAmB,CAAC;IACrF;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,GACA,aAAa,CAoFf"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { controlWrapperTemplate, } from '@genesislcap/foundation-forms';
|
|
2
|
+
import { createLogger } from '@genesislcap/foundation-logger';
|
|
2
3
|
import { html } from '@genesislcap/web-core';
|
|
3
4
|
import { mapStateToControlProps, } from '@jsonforms/core';
|
|
4
5
|
import r2wc from '@r2wc/react-to-web-component';
|
|
6
|
+
const logger = createLogger('foundation-react-utils');
|
|
5
7
|
/**
|
|
6
8
|
* Converts a React component into a `RendererEntry` for use with `foundation-form`'s
|
|
7
9
|
* `additionalRenderers` property.
|
|
@@ -48,6 +50,18 @@ import r2wc from '@r2wc/react-to-web-component';
|
|
|
48
50
|
* // form.additionalRenderers = [priceRendererEntry];
|
|
49
51
|
* ```
|
|
50
52
|
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* `uischema.options` may carry function values (e.g. AG-Grid `valueFormatter`, `comparator`,
|
|
55
|
+
* `cellRenderer`, however deeply nested — inside `columnDefs`, for instance) and they will
|
|
56
|
+
* reach your component intact, whether `uischema` is assigned before or after the element is
|
|
57
|
+
* connected to the DOM.
|
|
58
|
+
*
|
|
59
|
+
* The `props.uischema` your component receives is the *same object instance* JSON Forms holds
|
|
60
|
+
* internally, not a copy — treat it as read-only. Mutating it (e.g.
|
|
61
|
+
* `props.uischema.options.columnDefs.forEach(c => { c.width = measured })`) corrupts state shared
|
|
62
|
+
* with every sibling control and with subsequent reducer runs, since there is no serialization
|
|
63
|
+
* step to isolate your copy from the source.
|
|
64
|
+
*
|
|
51
65
|
* @public
|
|
52
66
|
*/
|
|
53
67
|
export function createReactRenderer(Component, options) {
|
|
@@ -61,7 +75,38 @@ export function createReactRenderer(Component, options) {
|
|
|
61
75
|
enabled: 'boolean',
|
|
62
76
|
required: 'boolean',
|
|
63
77
|
handleChange: 'method',
|
|
64
|
-
|
|
78
|
+
// 'uischema' is intentionally NOT declared here — see the property definition below.
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
// r2wc's 'json' prop type round-trips every assignment through
|
|
82
|
+
// JSON.stringify -> setAttribute -> JSON.parse, which silently drops any function-valued
|
|
83
|
+
// uischema.options properties (AG-Grid valueFormatter/comparator/cellRenderer/etc, however
|
|
84
|
+
// deeply nested, e.g. inside columnDefs). uischema is only ever assigned programmatically as a
|
|
85
|
+
// JS object — never authored as an HTML attribute — so attribute reflection provides no
|
|
86
|
+
// benefit here and is actively lossy. Bypass r2wc's declarative round trip and read/write its
|
|
87
|
+
// internal props store directly via its own globally-registered symbols. These are
|
|
88
|
+
// Symbol.for(...) (registry-based, not private Symbol()) so they're stable across realms, but
|
|
89
|
+
// this is still coupled to @r2wc/core's current internal implementation.
|
|
90
|
+
const R2WC_PROPS = Symbol.for('r2wc.props');
|
|
91
|
+
const R2WC_RENDER = Symbol.for('r2wc.render');
|
|
92
|
+
Object.defineProperty(WebComponent.prototype, 'uischema', {
|
|
93
|
+
configurable: true,
|
|
94
|
+
enumerable: true,
|
|
95
|
+
get() {
|
|
96
|
+
var _a;
|
|
97
|
+
return (_a = this[R2WC_PROPS]) === null || _a === void 0 ? void 0 : _a.uischema;
|
|
98
|
+
},
|
|
99
|
+
set(value) {
|
|
100
|
+
var _a;
|
|
101
|
+
if (!this[R2WC_PROPS]) {
|
|
102
|
+
logger.error(`[${options.name}] r2wc internal props store (Symbol.for('r2wc.props')) was not ` +
|
|
103
|
+
'found on this element — uischema was dropped and the wrapped component will not ' +
|
|
104
|
+
'receive it. This means @r2wc/core no longer matches the internal shape this ' +
|
|
105
|
+
'workaround depends on; check the resolved @r2wc/core version.');
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this[R2WC_PROPS].uischema = value;
|
|
109
|
+
(_a = this[R2WC_RENDER]) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
65
110
|
},
|
|
66
111
|
});
|
|
67
112
|
if (!customElements.get(options.name)) {
|
|
@@ -307,7 +307,7 @@
|
|
|
307
307
|
{
|
|
308
308
|
"kind": "Function",
|
|
309
309
|
"canonicalReference": "@genesislcap/foundation-react-utils!createReactRenderer:function(1)",
|
|
310
|
-
"docComment": "/**\n * Converts a React component into a `RendererEntry` for use with `foundation-form`'s `additionalRenderers` property.\n *\n * The component is registered as a custom element via `r2wc` and wrapped in a FAST `html` template so it integrates with the JSON Forms dispatch renderer.\n *\n * **Important — use platform web components for inputs, not native HTML elements.** The React component runs inside an `r2wc` custom element inside a FAST template, creating a three-layer shadow DOM boundary. React's synthetic event system does not cross shadow boundaries, so `onChange` on a plain `<input>` will never fire. Use `rapid-number-field`, `rapid-text-field`, etc. and attach listeners via `addEventListener` in a `useEffect` instead.\n *\n * @example\n * ```tsx\n * import { useEffect, useRef } from 'react';\n * import { createReactRenderer, type RendererControlProps } from '@genesislcap/foundation-react-utils';\n * import { isNumberControl, rankWith } from '@jsonforms/core';\n *\n * function PriceRenderer({ data, path, enabled, handleChange }: RendererControlProps) {\n * const ref = useRef<HTMLElement>(null);\n *\n * useEffect(() => {\n * const el = ref.current as any;\n * if (!el) return;\n * const onChange = (e: CustomEvent) => {\n * const val = (e.target as any).value;\n * handleChange(path, val === '' ? undefined : Number(val));\n * };\n * el.addEventListener('change', onChange);\n * return () => el.removeEventListener('change', onChange);\n * }, [path, handleChange]);\n *\n * return <rapid-number-field ref={ref} value={data ?? ''} disabled={!enabled || undefined} />;\n * }\n *\n * export const priceRendererEntry = createReactRenderer(PriceRenderer, {\n * name: 'my-price-renderer',\n * tester: rankWith(6, isNumberControl),\n * });\n *\n * // On the form element:\n * // form.additionalRenderers = [priceRendererEntry];\n * ```\n *\n * @public\n */\n",
|
|
310
|
+
"docComment": "/**\n * Converts a React component into a `RendererEntry` for use with `foundation-form`'s `additionalRenderers` property.\n *\n * The component is registered as a custom element via `r2wc` and wrapped in a FAST `html` template so it integrates with the JSON Forms dispatch renderer.\n *\n * **Important — use platform web components for inputs, not native HTML elements.** The React component runs inside an `r2wc` custom element inside a FAST template, creating a three-layer shadow DOM boundary. React's synthetic event system does not cross shadow boundaries, so `onChange` on a plain `<input>` will never fire. Use `rapid-number-field`, `rapid-text-field`, etc. and attach listeners via `addEventListener` in a `useEffect` instead.\n *\n * @remarks\n *\n * `uischema.options` may carry function values (e.g. AG-Grid `valueFormatter`, `comparator`, `cellRenderer`, however deeply nested — inside `columnDefs`, for instance) and they will reach your component intact, whether `uischema` is assigned before or after the element is connected to the DOM.\n *\n * The `props.uischema` your component receives is the *same object instance* JSON Forms holds internally, not a copy — treat it as read-only. Mutating it (e.g. `props.uischema.options.columnDefs.forEach(c => { c.width = measured })`) corrupts state shared with every sibling control and with subsequent reducer runs, since there is no serialization step to isolate your copy from the source.\n *\n * @example\n * ```tsx\n * import { useEffect, useRef } from 'react';\n * import { createReactRenderer, type RendererControlProps } from '@genesislcap/foundation-react-utils';\n * import { isNumberControl, rankWith } from '@jsonforms/core';\n *\n * function PriceRenderer({ data, path, enabled, handleChange }: RendererControlProps) {\n * const ref = useRef<HTMLElement>(null);\n *\n * useEffect(() => {\n * const el = ref.current as any;\n * if (!el) return;\n * const onChange = (e: CustomEvent) => {\n * const val = (e.target as any).value;\n * handleChange(path, val === '' ? undefined : Number(val));\n * };\n * el.addEventListener('change', onChange);\n * return () => el.removeEventListener('change', onChange);\n * }, [path, handleChange]);\n *\n * return <rapid-number-field ref={ref} value={data ?? ''} disabled={!enabled || undefined} />;\n * }\n *\n * export const priceRendererEntry = createReactRenderer(PriceRenderer, {\n * name: 'my-price-renderer',\n * tester: rankWith(6, isNumberControl),\n * });\n *\n * // On the form element:\n * // form.additionalRenderers = [priceRendererEntry];\n * ```\n *\n * @public\n */\n",
|
|
311
311
|
"excerptTokens": [
|
|
312
312
|
{
|
|
313
313
|
"kind": "Content",
|
|
@@ -158,6 +158,18 @@ export declare function createGridProCellRenderer<P extends GridProCellRendererP
|
|
|
158
158
|
* // form.additionalRenderers = [priceRendererEntry];
|
|
159
159
|
* ```
|
|
160
160
|
*
|
|
161
|
+
* @remarks
|
|
162
|
+
* `uischema.options` may carry function values (e.g. AG-Grid `valueFormatter`, `comparator`,
|
|
163
|
+
* `cellRenderer`, however deeply nested — inside `columnDefs`, for instance) and they will
|
|
164
|
+
* reach your component intact, whether `uischema` is assigned before or after the element is
|
|
165
|
+
* connected to the DOM.
|
|
166
|
+
*
|
|
167
|
+
* The `props.uischema` your component receives is the *same object instance* JSON Forms holds
|
|
168
|
+
* internally, not a copy — treat it as read-only. Mutating it (e.g.
|
|
169
|
+
* `props.uischema.options.columnDefs.forEach(c => { c.width = measured })`) corrupts state shared
|
|
170
|
+
* with every sibling control and with subsequent reducer runs, since there is no serialization
|
|
171
|
+
* step to isolate your copy from the source.
|
|
172
|
+
*
|
|
161
173
|
* @public
|
|
162
174
|
*/
|
|
163
175
|
export declare function createReactRenderer(Component: ComponentType<RendererControlProps>, options: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@genesislcap/foundation-react-utils",
|
|
3
3
|
"description": "Genesis Foundation React Utils",
|
|
4
|
-
"version": "15.
|
|
4
|
+
"version": "15.32.1",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"./dist/esm/flexlayout/index.js"
|
|
7
7
|
],
|
|
@@ -56,13 +56,13 @@
|
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@genesislcap/foundation-testing": "15.
|
|
60
|
-
"@genesislcap/genx": "15.
|
|
61
|
-
"@genesislcap/rollup-builder": "15.
|
|
62
|
-
"@genesislcap/ts-builder": "15.
|
|
63
|
-
"@genesislcap/uvu-playwright-builder": "15.
|
|
64
|
-
"@genesislcap/vite-builder": "15.
|
|
65
|
-
"@genesislcap/webpack-builder": "15.
|
|
59
|
+
"@genesislcap/foundation-testing": "15.32.1",
|
|
60
|
+
"@genesislcap/genx": "15.32.1",
|
|
61
|
+
"@genesislcap/rollup-builder": "15.32.1",
|
|
62
|
+
"@genesislcap/ts-builder": "15.32.1",
|
|
63
|
+
"@genesislcap/uvu-playwright-builder": "15.32.1",
|
|
64
|
+
"@genesislcap/vite-builder": "15.32.1",
|
|
65
|
+
"@genesislcap/webpack-builder": "15.32.1",
|
|
66
66
|
"react-router-dom": "^7.1.3"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
@@ -76,12 +76,13 @@
|
|
|
76
76
|
}
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@genesislcap/foundation-forms": "15.
|
|
80
|
-
"@genesislcap/foundation-layout": "15.
|
|
81
|
-
"@genesislcap/foundation-logger": "15.
|
|
82
|
-
"@genesislcap/rapid-design-system": "15.
|
|
83
|
-
"@genesislcap/web-core": "15.
|
|
79
|
+
"@genesislcap/foundation-forms": "15.32.1",
|
|
80
|
+
"@genesislcap/foundation-layout": "15.32.1",
|
|
81
|
+
"@genesislcap/foundation-logger": "15.32.1",
|
|
82
|
+
"@genesislcap/rapid-design-system": "15.32.1",
|
|
83
|
+
"@genesislcap/web-core": "15.32.1",
|
|
84
84
|
"@jsonforms/core": "^3.2.1",
|
|
85
|
+
"@r2wc/core": "1.3.1",
|
|
85
86
|
"@r2wc/react-to-web-component": "^2.0.2",
|
|
86
87
|
"flexlayout-react": "0.10.8"
|
|
87
88
|
},
|