@fieldia/react 0.0.0-stage → 0.2.0
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/LICENSE +21 -0
- package/README.md +22 -2
- package/package.json +41 -3
- package/src/index.d.mts +2 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +7 -0
- package/src/index.js.map +1 -0
- package/src/index.mjs +2 -0
- package/src/index.mjs.map +1 -0
- package/src/lib/fieldia-form.d.mts +47 -0
- package/src/lib/fieldia-form.d.ts +47 -0
- package/src/lib/fieldia-form.js +109 -0
- package/src/lib/fieldia-form.js.map +1 -0
- package/src/lib/fieldia-form.mjs +105 -0
- package/src/lib/fieldia-form.mjs.map +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fieldia-dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @fieldia/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Fieldia](https://fieldia.dev) forms in React 18 and 19: a thin shell over
|
|
4
|
+
`@fieldia/viewer`, so a page looks and behaves the same as in any other framework.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npm install @fieldia/react
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { FieldiaForm } from '@fieldia/react';
|
|
12
|
+
import { createMemoryDataSource } from '@fieldia/core';
|
|
13
|
+
import page from './customer.page.json';
|
|
14
|
+
|
|
15
|
+
const dataSource = createMemoryDataSource();
|
|
16
|
+
|
|
17
|
+
export function Customer() {
|
|
18
|
+
return <FieldiaForm page={page} dataSource={dataSource} recordId={1} skin="underline" />;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Custom fields and slot content can be React components (`fieldTypes`, `slots`);
|
|
23
|
+
`useFormState(form)` gives you a form's state as React state. MIT licensed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fieldia/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "React binding for Fieldia: <FieldiaForm> over the plain-DOM viewer, with custom fields and slots as React components.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://fieldia.dev",
|
|
7
|
+
"type": "commonjs",
|
|
8
|
+
"main": "./src/index.js",
|
|
9
|
+
"module": "./src/index.mjs",
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": {
|
|
14
|
+
"import": "./src/index.d.mts",
|
|
15
|
+
"require": "./src/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"import": "./src/index.mjs",
|
|
18
|
+
"require": "./src/index.js",
|
|
19
|
+
"default": "./src/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@fieldia/core": "0.2.0",
|
|
25
|
+
"@fieldia/viewer": "0.2.0",
|
|
26
|
+
"@fieldia/widgets": "0.2.0",
|
|
27
|
+
"tslib": "^2.8.1"
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/fieldia-dev/fieldia",
|
|
33
|
+
"directory": "libs/react"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"src",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
42
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
43
|
+
}
|
|
6
44
|
}
|
package/src/index.d.mts
ADDED
package/src/index.d.ts
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFormState = exports.FieldiaForm = void 0;
|
|
4
|
+
var fieldia_form_1 = require("./lib/fieldia-form");
|
|
5
|
+
Object.defineProperty(exports, "FieldiaForm", { enumerable: true, get: function () { return fieldia_form_1.FieldiaForm; } });
|
|
6
|
+
Object.defineProperty(exports, "useFormState", { enumerable: true, get: function () { return fieldia_form_1.useFormState; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/react/src/index.ts"],"names":[],"mappings":";;;AAAA,mDAAyI;AAAhI,2GAAA,WAAW,OAAA;AAAE,4GAAA,YAAY,OAAA"}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../libs/react/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAA4E,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Field, FieldNode, Form, FormState, Value } from '@fieldia/core';
|
|
2
|
+
import { type ViewerHandle, type ViewerOptions } from '@fieldia/viewer';
|
|
3
|
+
import type { WidgetState } from '@fieldia/widgets';
|
|
4
|
+
import { type ComponentType, type CSSProperties } from 'react';
|
|
5
|
+
/**
|
|
6
|
+
* `<FieldiaForm>` — the React shell.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately thin, in the same sense as Quantia's React binding: every
|
|
9
|
+
* decision a form makes lives in `mountViewer` and `createForm`, which are
|
|
10
|
+
* framework-neutral and tested without React. This file owns four things:
|
|
11
|
+
*
|
|
12
|
+
* 1. a `<div>` React never renders into, handed to `mountViewer`,
|
|
13
|
+
* 2. props forwarded onto the handle without mounting again,
|
|
14
|
+
* 3. custom fields and slots written as React components, rendered into
|
|
15
|
+
* the viewer's own elements through portals,
|
|
16
|
+
* 4. teardown.
|
|
17
|
+
*
|
|
18
|
+
* `mountViewer` runs only in an effect, so the component renders on a server.
|
|
19
|
+
*/
|
|
20
|
+
/** What a custom field component receives. Call `onChange` to write the value. */
|
|
21
|
+
export interface FieldComponentProps extends Omit<WidgetState, 'value'> {
|
|
22
|
+
value: Value | undefined;
|
|
23
|
+
name: string;
|
|
24
|
+
field: Field;
|
|
25
|
+
node: FieldNode;
|
|
26
|
+
/** The id the field's label points at; put it on your input. */
|
|
27
|
+
id: string;
|
|
28
|
+
form: Form;
|
|
29
|
+
onChange(value: Value): void;
|
|
30
|
+
}
|
|
31
|
+
export interface SlotComponentProps {
|
|
32
|
+
form: Form;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
export interface FieldiaFormProps extends Omit<ViewerOptions, 'slots'> {
|
|
36
|
+
/** Custom fields as React components, by `type.widget` or `type`. */
|
|
37
|
+
fieldTypes?: Record<string, ComponentType<FieldComponentProps>>;
|
|
38
|
+
/** Slot content as React components, by slot name. */
|
|
39
|
+
slots?: Record<string, ComponentType<SlotComponentProps>>;
|
|
40
|
+
className?: string;
|
|
41
|
+
style?: CSSProperties;
|
|
42
|
+
/** Called once per mount with the viewer's handle. */
|
|
43
|
+
onReady?: (handle: ViewerHandle) => void;
|
|
44
|
+
}
|
|
45
|
+
/** A form's state as React state: the component re-renders on every change. */
|
|
46
|
+
export declare function useFormState(form: Form): FormState;
|
|
47
|
+
export declare const FieldiaForm: import("react").ForwardRefExoticComponent<FieldiaFormProps & import("react").RefAttributes<ViewerHandle | null>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Field, FieldNode, Form, FormState, Value } from '@fieldia/core';
|
|
2
|
+
import { type ViewerHandle, type ViewerOptions } from '@fieldia/viewer';
|
|
3
|
+
import type { WidgetState } from '@fieldia/widgets';
|
|
4
|
+
import { type ComponentType, type CSSProperties } from 'react';
|
|
5
|
+
/**
|
|
6
|
+
* `<FieldiaForm>` — the React shell.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately thin, in the same sense as Quantia's React binding: every
|
|
9
|
+
* decision a form makes lives in `mountViewer` and `createForm`, which are
|
|
10
|
+
* framework-neutral and tested without React. This file owns four things:
|
|
11
|
+
*
|
|
12
|
+
* 1. a `<div>` React never renders into, handed to `mountViewer`,
|
|
13
|
+
* 2. props forwarded onto the handle without mounting again,
|
|
14
|
+
* 3. custom fields and slots written as React components, rendered into
|
|
15
|
+
* the viewer's own elements through portals,
|
|
16
|
+
* 4. teardown.
|
|
17
|
+
*
|
|
18
|
+
* `mountViewer` runs only in an effect, so the component renders on a server.
|
|
19
|
+
*/
|
|
20
|
+
/** What a custom field component receives. Call `onChange` to write the value. */
|
|
21
|
+
export interface FieldComponentProps extends Omit<WidgetState, 'value'> {
|
|
22
|
+
value: Value | undefined;
|
|
23
|
+
name: string;
|
|
24
|
+
field: Field;
|
|
25
|
+
node: FieldNode;
|
|
26
|
+
/** The id the field's label points at; put it on your input. */
|
|
27
|
+
id: string;
|
|
28
|
+
form: Form;
|
|
29
|
+
onChange(value: Value): void;
|
|
30
|
+
}
|
|
31
|
+
export interface SlotComponentProps {
|
|
32
|
+
form: Form;
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
export interface FieldiaFormProps extends Omit<ViewerOptions, 'slots'> {
|
|
36
|
+
/** Custom fields as React components, by `type.widget` or `type`. */
|
|
37
|
+
fieldTypes?: Record<string, ComponentType<FieldComponentProps>>;
|
|
38
|
+
/** Slot content as React components, by slot name. */
|
|
39
|
+
slots?: Record<string, ComponentType<SlotComponentProps>>;
|
|
40
|
+
className?: string;
|
|
41
|
+
style?: CSSProperties;
|
|
42
|
+
/** Called once per mount with the viewer's handle. */
|
|
43
|
+
onReady?: (handle: ViewerHandle) => void;
|
|
44
|
+
}
|
|
45
|
+
/** A form's state as React state: the component re-renders on every change. */
|
|
46
|
+
export declare function useFormState(form: Form): FormState;
|
|
47
|
+
export declare const FieldiaForm: import("react").ForwardRefExoticComponent<FieldiaFormProps & import("react").RefAttributes<ViewerHandle | null>>;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FieldiaForm = void 0;
|
|
4
|
+
exports.useFormState = useFormState;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const viewer_1 = require("@fieldia/viewer");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const react_dom_1 = require("react-dom");
|
|
9
|
+
/** A form's state as React state: the component re-renders on every change. */
|
|
10
|
+
function useFormState(form) {
|
|
11
|
+
return (0, react_1.useSyncExternalStore)(form.subscribe, form.getState, form.getState);
|
|
12
|
+
}
|
|
13
|
+
function store(initial) {
|
|
14
|
+
let state = initial;
|
|
15
|
+
const listeners = new Set();
|
|
16
|
+
return {
|
|
17
|
+
get: () => state,
|
|
18
|
+
set(next) {
|
|
19
|
+
state = next;
|
|
20
|
+
for (const listener of listeners)
|
|
21
|
+
listener();
|
|
22
|
+
},
|
|
23
|
+
subscribe(listener) {
|
|
24
|
+
listeners.add(listener);
|
|
25
|
+
return () => listeners.delete(listener);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function CustomField(props) {
|
|
30
|
+
const state = (0, react_1.useSyncExternalStore)(props.state.subscribe, props.state.get, props.state.get);
|
|
31
|
+
const Component = props.component();
|
|
32
|
+
const { context } = props;
|
|
33
|
+
if (!Component)
|
|
34
|
+
return null;
|
|
35
|
+
return ((0, jsx_runtime_1.jsx)(Component, { ...state, name: context.name, field: context.field, node: context.node, id: context.id, form: context.form, onChange: (value) => context.form.setValue(context.name, value) }));
|
|
36
|
+
}
|
|
37
|
+
function SlotContent(props) {
|
|
38
|
+
const Component = props.component();
|
|
39
|
+
return Component ? (0, jsx_runtime_1.jsx)(Component, { form: props.form, name: props.name }) : null;
|
|
40
|
+
}
|
|
41
|
+
const EMPTY_STATE = { value: undefined, values: {}, readonly: false, required: false, invalid: false };
|
|
42
|
+
exports.FieldiaForm = (0, react_1.forwardRef)(function FieldiaForm(props, ref) {
|
|
43
|
+
const host = (0, react_1.useRef)(null);
|
|
44
|
+
const latest = (0, react_1.useRef)(props);
|
|
45
|
+
latest.current = props;
|
|
46
|
+
const [handle, setHandle] = (0, react_1.useState)(null);
|
|
47
|
+
const [portals, setPortals] = (0, react_1.useState)([]);
|
|
48
|
+
(0, react_1.useImperativeHandle)(ref, () => handle, [handle]);
|
|
49
|
+
// Mount again only when the record or what the page is changes. Callbacks
|
|
50
|
+
// and components are read through `latest`, so a new function each render
|
|
51
|
+
// costs nothing.
|
|
52
|
+
const fieldKeys = Object.keys(props.fieldTypes ?? {}).join('|');
|
|
53
|
+
const slotKeys = Object.keys(props.slots ?? {}).join('|');
|
|
54
|
+
const labelsKey = JSON.stringify(props.labels ?? {});
|
|
55
|
+
(0, react_1.useEffect)(() => {
|
|
56
|
+
const element = host.current;
|
|
57
|
+
if (!element)
|
|
58
|
+
return;
|
|
59
|
+
const found = [];
|
|
60
|
+
const widgets = { ...latest.current.widgets };
|
|
61
|
+
for (const key of Object.keys(latest.current.fieldTypes ?? {})) {
|
|
62
|
+
widgets[key] = (context) => {
|
|
63
|
+
const box = context.document.createElement('div');
|
|
64
|
+
box.className = 'fd-custom';
|
|
65
|
+
const state = store(EMPTY_STATE);
|
|
66
|
+
found.push({
|
|
67
|
+
key: `field:${context.node.id}`,
|
|
68
|
+
element: box,
|
|
69
|
+
node: (0, jsx_runtime_1.jsx)(CustomField, { state: state, context: context, component: () => latest.current.fieldTypes?.[key] }),
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
element: box,
|
|
73
|
+
update: (next) => state.set(next),
|
|
74
|
+
focus: () => box.querySelector('input, select, textarea, button, [tabindex]')?.focus(),
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const slots = {};
|
|
79
|
+
for (const name of Object.keys(latest.current.slots ?? {})) {
|
|
80
|
+
slots[name] = (box, context) => {
|
|
81
|
+
found.push({
|
|
82
|
+
key: `slot:${name}:${found.length}`,
|
|
83
|
+
element: box,
|
|
84
|
+
node: (0, jsx_runtime_1.jsx)(SlotContent, { name: name, form: context.form, component: () => latest.current.slots?.[name] }),
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const { fieldTypes: _fields, slots: _slots, className: _class, style: _style, onReady: _ready, ...options } = latest.current;
|
|
89
|
+
const mounted = (0, viewer_1.mountViewer)(element, {
|
|
90
|
+
...options,
|
|
91
|
+
widgets,
|
|
92
|
+
slots,
|
|
93
|
+
onAction: (request) => latest.current.onAction?.(request),
|
|
94
|
+
});
|
|
95
|
+
setHandle(mounted);
|
|
96
|
+
setPortals(found);
|
|
97
|
+
latest.current.onReady?.(mounted);
|
|
98
|
+
return () => {
|
|
99
|
+
mounted.destroy();
|
|
100
|
+
setHandle(null);
|
|
101
|
+
setPortals([]);
|
|
102
|
+
};
|
|
103
|
+
}, [props.page, props.form, props.dataSource, props.recordId, props.dir, labelsKey, fieldKeys, slotKeys]);
|
|
104
|
+
(0, react_1.useEffect)(() => {
|
|
105
|
+
handle?.setSkin(props.skin ?? 'underline');
|
|
106
|
+
}, [handle, props.skin]);
|
|
107
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { ref: host, className: props.className, style: props.style }), portals.map((portal) => (0, react_dom_1.createPortal)(portal.node, portal.element, portal.key))] }));
|
|
108
|
+
});
|
|
109
|
+
//# sourceMappingURL=fieldia-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fieldia-form.js","sourceRoot":"","sources":["../../../../../libs/react/src/lib/fieldia-form.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { mountViewer } from '@fieldia/viewer';
|
|
3
|
+
import { forwardRef, useEffect, useImperativeHandle, useRef, useState, useSyncExternalStore, } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
/** A form's state as React state: the component re-renders on every change. */
|
|
6
|
+
export function useFormState(form) {
|
|
7
|
+
return useSyncExternalStore(form.subscribe, form.getState, form.getState);
|
|
8
|
+
}
|
|
9
|
+
function store(initial) {
|
|
10
|
+
let state = initial;
|
|
11
|
+
const listeners = new Set();
|
|
12
|
+
return {
|
|
13
|
+
get: () => state,
|
|
14
|
+
set(next) {
|
|
15
|
+
state = next;
|
|
16
|
+
for (const listener of listeners)
|
|
17
|
+
listener();
|
|
18
|
+
},
|
|
19
|
+
subscribe(listener) {
|
|
20
|
+
listeners.add(listener);
|
|
21
|
+
return () => listeners.delete(listener);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function CustomField(props) {
|
|
26
|
+
const state = useSyncExternalStore(props.state.subscribe, props.state.get, props.state.get);
|
|
27
|
+
const Component = props.component();
|
|
28
|
+
const { context } = props;
|
|
29
|
+
if (!Component)
|
|
30
|
+
return null;
|
|
31
|
+
return (_jsx(Component, { ...state, name: context.name, field: context.field, node: context.node, id: context.id, form: context.form, onChange: (value) => context.form.setValue(context.name, value) }));
|
|
32
|
+
}
|
|
33
|
+
function SlotContent(props) {
|
|
34
|
+
const Component = props.component();
|
|
35
|
+
return Component ? _jsx(Component, { form: props.form, name: props.name }) : null;
|
|
36
|
+
}
|
|
37
|
+
const EMPTY_STATE = { value: undefined, values: {}, readonly: false, required: false, invalid: false };
|
|
38
|
+
export const FieldiaForm = forwardRef(function FieldiaForm(props, ref) {
|
|
39
|
+
const host = useRef(null);
|
|
40
|
+
const latest = useRef(props);
|
|
41
|
+
latest.current = props;
|
|
42
|
+
const [handle, setHandle] = useState(null);
|
|
43
|
+
const [portals, setPortals] = useState([]);
|
|
44
|
+
useImperativeHandle(ref, () => handle, [handle]);
|
|
45
|
+
// Mount again only when the record or what the page is changes. Callbacks
|
|
46
|
+
// and components are read through `latest`, so a new function each render
|
|
47
|
+
// costs nothing.
|
|
48
|
+
const fieldKeys = Object.keys(props.fieldTypes ?? {}).join('|');
|
|
49
|
+
const slotKeys = Object.keys(props.slots ?? {}).join('|');
|
|
50
|
+
const labelsKey = JSON.stringify(props.labels ?? {});
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
const element = host.current;
|
|
53
|
+
if (!element)
|
|
54
|
+
return;
|
|
55
|
+
const found = [];
|
|
56
|
+
const widgets = { ...latest.current.widgets };
|
|
57
|
+
for (const key of Object.keys(latest.current.fieldTypes ?? {})) {
|
|
58
|
+
widgets[key] = (context) => {
|
|
59
|
+
const box = context.document.createElement('div');
|
|
60
|
+
box.className = 'fd-custom';
|
|
61
|
+
const state = store(EMPTY_STATE);
|
|
62
|
+
found.push({
|
|
63
|
+
key: `field:${context.node.id}`,
|
|
64
|
+
element: box,
|
|
65
|
+
node: _jsx(CustomField, { state: state, context: context, component: () => latest.current.fieldTypes?.[key] }),
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
element: box,
|
|
69
|
+
update: (next) => state.set(next),
|
|
70
|
+
focus: () => box.querySelector('input, select, textarea, button, [tabindex]')?.focus(),
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const slots = {};
|
|
75
|
+
for (const name of Object.keys(latest.current.slots ?? {})) {
|
|
76
|
+
slots[name] = (box, context) => {
|
|
77
|
+
found.push({
|
|
78
|
+
key: `slot:${name}:${found.length}`,
|
|
79
|
+
element: box,
|
|
80
|
+
node: _jsx(SlotContent, { name: name, form: context.form, component: () => latest.current.slots?.[name] }),
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const { fieldTypes: _fields, slots: _slots, className: _class, style: _style, onReady: _ready, ...options } = latest.current;
|
|
85
|
+
const mounted = mountViewer(element, {
|
|
86
|
+
...options,
|
|
87
|
+
widgets,
|
|
88
|
+
slots,
|
|
89
|
+
onAction: (request) => latest.current.onAction?.(request),
|
|
90
|
+
});
|
|
91
|
+
setHandle(mounted);
|
|
92
|
+
setPortals(found);
|
|
93
|
+
latest.current.onReady?.(mounted);
|
|
94
|
+
return () => {
|
|
95
|
+
mounted.destroy();
|
|
96
|
+
setHandle(null);
|
|
97
|
+
setPortals([]);
|
|
98
|
+
};
|
|
99
|
+
}, [props.page, props.form, props.dataSource, props.recordId, props.dir, labelsKey, fieldKeys, slotKeys]);
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
handle?.setSkin(props.skin ?? 'underline');
|
|
102
|
+
}, [handle, props.skin]);
|
|
103
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: host, className: props.className, style: props.style }), portals.map((portal) => createPortal(portal.node, portal.element, portal.key))] }));
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=fieldia-form.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fieldia-form.mjs","sourceRoot":"","sources":["../../../../../libs/react/src/lib/fieldia-form.tsx"],"names":[],"mappings":"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"}
|