@dynamic-field-kit/react 1.2.0 → 1.3.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/README.md +44 -1
- package/dist/index.d.mts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +163 -40
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +20 -5
package/README.md
CHANGED
|
@@ -29,6 +29,8 @@ Note: Core is shared runtime. Install core separately and ensure a single versio
|
|
|
29
29
|
- `FieldTypeKey`
|
|
30
30
|
- `FieldRendererProps`
|
|
31
31
|
|
|
32
|
+
`FieldGroupInput` (repeatable field groups) is used internally by `FieldInput` and doesn't need to be imported directly - see "Repeatable field groups" below.
|
|
33
|
+
|
|
32
34
|
Default layouts are registered automatically when you import the package root.
|
|
33
35
|
|
|
34
36
|
Built-in layouts:
|
|
@@ -132,6 +134,46 @@ layoutRegistry.register('stack-tight', ({ children }) => (
|
|
|
132
134
|
));
|
|
133
135
|
```
|
|
134
136
|
|
|
137
|
+
## Derived fields with `computeValue`
|
|
138
|
+
|
|
139
|
+
Give a field a `computeValue` to derive its value from the rest of the form data whenever any field changes:
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
const fields: FieldDescription[] = [
|
|
143
|
+
{ name: 'firstName', type: 'text' },
|
|
144
|
+
{ name: 'lastName', type: 'text' },
|
|
145
|
+
{
|
|
146
|
+
name: 'fullName',
|
|
147
|
+
type: 'text',
|
|
148
|
+
computeValue: (data) =>
|
|
149
|
+
`${data.firstName ?? ''} ${data.lastName ?? ''}`.trim(),
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Repeatable field groups
|
|
155
|
+
|
|
156
|
+
A field with `fields` renders as a repeatable group: `data[name]` becomes an array of items, each shaped by the nested `fields`, with "Add"/"Remove" controls rendered automatically.
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
const fields: FieldDescription[] = [
|
|
160
|
+
{
|
|
161
|
+
name: 'contacts',
|
|
162
|
+
type: 'group',
|
|
163
|
+
label: 'Contacts',
|
|
164
|
+
fields: [
|
|
165
|
+
{ name: 'email', type: 'text', label: 'Email' },
|
|
166
|
+
{ name: 'phone', type: 'text', label: 'Phone' },
|
|
167
|
+
],
|
|
168
|
+
defaultItem: { email: '', phone: '' },
|
|
169
|
+
minItems: 1,
|
|
170
|
+
maxItems: 5,
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
<MultiFieldInput fieldDescriptions={fields} />;
|
|
175
|
+
```
|
|
176
|
+
|
|
135
177
|
## Type augmentation
|
|
136
178
|
|
|
137
179
|
Add your app's field types through module augmentation:
|
|
@@ -151,8 +193,9 @@ declare module '@dynamic-field-kit/core' {
|
|
|
151
193
|
|
|
152
194
|
- `@dynamic-field-kit/core` stays framework-agnostic and does not export React-specific JSX types.
|
|
153
195
|
- `@dynamic-field-kit/react` narrows the shared registry to React component types so `fieldRegistry.get(type)` can be rendered safely in TSX.
|
|
154
|
-
- `MultiFieldInput` filters fields using `appearCondition`.
|
|
196
|
+
- `MultiFieldInput` filters fields using `appearCondition` and derives fields using `computeValue`.
|
|
155
197
|
- `DynamicInput` renders `Unknown field type: ...` when a renderer is missing.
|
|
198
|
+
- Fields with `fields` render as repeatable groups instead of going through `fieldRegistry`.
|
|
156
199
|
|
|
157
200
|
## License
|
|
158
201
|
|
package/dist/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
3
3
|
import { FieldTypeKey, Properties, FieldDescription, FieldTypeMap, FieldRendererProps } from '@dynamic-field-kit/core';
|
|
4
4
|
export { FieldDescription, FieldRendererProps, FieldTypeKey } from '@dynamic-field-kit/core';
|
|
5
5
|
|
|
6
|
-
type LayoutRenderer<C =
|
|
6
|
+
type LayoutRenderer<C = unknown> = (props: {
|
|
7
7
|
children: React.ReactNode;
|
|
8
8
|
config?: C;
|
|
9
9
|
}) => React.ReactElement;
|
|
@@ -27,21 +27,22 @@ type LayoutConfig = BaseLayout | {
|
|
|
27
27
|
|
|
28
28
|
interface Props$2<T extends FieldTypeKey> {
|
|
29
29
|
type: T;
|
|
30
|
-
value?:
|
|
31
|
-
onChange?: (value:
|
|
30
|
+
value?: unknown;
|
|
31
|
+
onChange?: (value: unknown) => void;
|
|
32
32
|
label?: string;
|
|
33
33
|
options?: Properties[];
|
|
34
34
|
className?: string;
|
|
35
35
|
description?: ReactNode;
|
|
36
36
|
}
|
|
37
|
-
declare const
|
|
37
|
+
declare const DynamicInputInner: <T extends FieldTypeKey>({ type, value, onChange, label, options, className, description, }: Props$2<T>) => react_jsx_runtime.JSX.Element;
|
|
38
|
+
declare const DynamicInput: typeof DynamicInputInner;
|
|
38
39
|
|
|
39
40
|
interface Props$1 {
|
|
40
41
|
fieldDescription: FieldDescription;
|
|
41
42
|
renderInfos: Properties;
|
|
42
|
-
onValueChangeField: (value:
|
|
43
|
+
onValueChangeField: (value: unknown, key: string) => void;
|
|
43
44
|
}
|
|
44
|
-
declare const FieldInput: ({ fieldDescription, renderInfos, onValueChangeField, }: Props$1) => react_jsx_runtime.JSX.Element
|
|
45
|
+
declare const FieldInput: React.MemoExoticComponent<({ fieldDescription, renderInfos, onValueChangeField, }: Props$1) => react_jsx_runtime.JSX.Element>;
|
|
45
46
|
|
|
46
47
|
interface Props {
|
|
47
48
|
fieldDescriptions: FieldDescription[];
|
|
@@ -51,7 +52,7 @@ interface Props {
|
|
|
51
52
|
}
|
|
52
53
|
declare const MultiFieldInput: ({ fieldDescriptions, properties, onChange, layout, }: Props) => react_jsx_runtime.JSX.Element;
|
|
53
54
|
|
|
54
|
-
type ReactFieldRenderer<T =
|
|
55
|
+
type ReactFieldRenderer<T = unknown> = ComponentType<FieldRendererProps<T>>;
|
|
55
56
|
interface ReactFieldRegistry {
|
|
56
57
|
register<K extends keyof FieldTypeMap>(type: K, renderer: ReactFieldRenderer<FieldTypeMap[K]>): void;
|
|
57
58
|
get<K extends keyof FieldTypeMap>(type: K): ReactFieldRenderer<FieldTypeMap[K]> | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
3
3
|
import { FieldTypeKey, Properties, FieldDescription, FieldTypeMap, FieldRendererProps } from '@dynamic-field-kit/core';
|
|
4
4
|
export { FieldDescription, FieldRendererProps, FieldTypeKey } from '@dynamic-field-kit/core';
|
|
5
5
|
|
|
6
|
-
type LayoutRenderer<C =
|
|
6
|
+
type LayoutRenderer<C = unknown> = (props: {
|
|
7
7
|
children: React.ReactNode;
|
|
8
8
|
config?: C;
|
|
9
9
|
}) => React.ReactElement;
|
|
@@ -27,21 +27,22 @@ type LayoutConfig = BaseLayout | {
|
|
|
27
27
|
|
|
28
28
|
interface Props$2<T extends FieldTypeKey> {
|
|
29
29
|
type: T;
|
|
30
|
-
value?:
|
|
31
|
-
onChange?: (value:
|
|
30
|
+
value?: unknown;
|
|
31
|
+
onChange?: (value: unknown) => void;
|
|
32
32
|
label?: string;
|
|
33
33
|
options?: Properties[];
|
|
34
34
|
className?: string;
|
|
35
35
|
description?: ReactNode;
|
|
36
36
|
}
|
|
37
|
-
declare const
|
|
37
|
+
declare const DynamicInputInner: <T extends FieldTypeKey>({ type, value, onChange, label, options, className, description, }: Props$2<T>) => react_jsx_runtime.JSX.Element;
|
|
38
|
+
declare const DynamicInput: typeof DynamicInputInner;
|
|
38
39
|
|
|
39
40
|
interface Props$1 {
|
|
40
41
|
fieldDescription: FieldDescription;
|
|
41
42
|
renderInfos: Properties;
|
|
42
|
-
onValueChangeField: (value:
|
|
43
|
+
onValueChangeField: (value: unknown, key: string) => void;
|
|
43
44
|
}
|
|
44
|
-
declare const FieldInput: ({ fieldDescription, renderInfos, onValueChangeField, }: Props$1) => react_jsx_runtime.JSX.Element
|
|
45
|
+
declare const FieldInput: React.MemoExoticComponent<({ fieldDescription, renderInfos, onValueChangeField, }: Props$1) => react_jsx_runtime.JSX.Element>;
|
|
45
46
|
|
|
46
47
|
interface Props {
|
|
47
48
|
fieldDescriptions: FieldDescription[];
|
|
@@ -51,7 +52,7 @@ interface Props {
|
|
|
51
52
|
}
|
|
52
53
|
declare const MultiFieldInput: ({ fieldDescriptions, properties, onChange, layout, }: Props) => react_jsx_runtime.JSX.Element;
|
|
53
54
|
|
|
54
|
-
type ReactFieldRenderer<T =
|
|
55
|
+
type ReactFieldRenderer<T = unknown> = ComponentType<FieldRendererProps<T>>;
|
|
55
56
|
interface ReactFieldRegistry {
|
|
56
57
|
register<K extends keyof FieldTypeMap>(type: K, renderer: ReactFieldRenderer<FieldTypeMap[K]>): void;
|
|
57
58
|
get<K extends keyof FieldTypeMap>(type: K): ReactFieldRenderer<FieldTypeMap[K]> | undefined;
|
package/dist/index.js
CHANGED
|
@@ -92,6 +92,7 @@ layoutRegistry.register("grid", ({ children, config }) => /* @__PURE__ */ (0, im
|
|
|
92
92
|
));
|
|
93
93
|
|
|
94
94
|
// src/layout/responsiveLayout.tsx
|
|
95
|
+
var import_react = require("react");
|
|
95
96
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
96
97
|
function resolve(layout) {
|
|
97
98
|
if (typeof layout === "string") {
|
|
@@ -99,9 +100,20 @@ function resolve(layout) {
|
|
|
99
100
|
}
|
|
100
101
|
return { type: layout.type, config: layout };
|
|
101
102
|
}
|
|
103
|
+
function checkIsMobile(breakpoint) {
|
|
104
|
+
return typeof window !== "undefined" && window.innerWidth < breakpoint;
|
|
105
|
+
}
|
|
102
106
|
layoutRegistry.register("responsive", ({ children, config }) => {
|
|
103
|
-
const
|
|
104
|
-
const
|
|
107
|
+
const responsiveConfig = config;
|
|
108
|
+
const breakpoint = responsiveConfig.breakpoint ?? 768;
|
|
109
|
+
const [isMobile, setIsMobile] = (0, import_react.useState)(() => checkIsMobile(breakpoint));
|
|
110
|
+
(0, import_react.useEffect)(() => {
|
|
111
|
+
const handleResize = () => setIsMobile(checkIsMobile(breakpoint));
|
|
112
|
+
handleResize();
|
|
113
|
+
window.addEventListener("resize", handleResize);
|
|
114
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
115
|
+
}, [breakpoint]);
|
|
116
|
+
const current = isMobile ? responsiveConfig.mobile : responsiveConfig.desktop;
|
|
105
117
|
if (!current) {
|
|
106
118
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
107
119
|
children,
|
|
@@ -120,7 +132,7 @@ layoutRegistry.register("responsive", ({ children, config }) => {
|
|
|
120
132
|
});
|
|
121
133
|
|
|
122
134
|
// src/components/DynamicInput.tsx
|
|
123
|
-
var
|
|
135
|
+
var import_react2 = __toESM(require("react"));
|
|
124
136
|
|
|
125
137
|
// src/fieldRegistry.ts
|
|
126
138
|
var import_core = require("@dynamic-field-kit/core");
|
|
@@ -128,7 +140,7 @@ var fieldRegistry = import_core.fieldRegistry;
|
|
|
128
140
|
|
|
129
141
|
// src/components/DynamicInput.tsx
|
|
130
142
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
131
|
-
var
|
|
143
|
+
var DynamicInputInner = ({
|
|
132
144
|
type,
|
|
133
145
|
value,
|
|
134
146
|
onChange,
|
|
@@ -137,15 +149,17 @@ var DynamicInput = ({
|
|
|
137
149
|
className,
|
|
138
150
|
description
|
|
139
151
|
}) => {
|
|
140
|
-
const Renderer = (0,
|
|
152
|
+
const Renderer = (0, import_react2.useMemo)(
|
|
153
|
+
() => fieldRegistry.get(type),
|
|
154
|
+
[type]
|
|
155
|
+
);
|
|
141
156
|
if (!Renderer) {
|
|
142
157
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
143
158
|
"Unknown field type: ",
|
|
144
159
|
type
|
|
145
160
|
] });
|
|
146
161
|
}
|
|
147
|
-
|
|
148
|
-
return import_react.default.createElement(RendererEl, {
|
|
162
|
+
return import_react2.default.createElement(Renderer, {
|
|
149
163
|
value,
|
|
150
164
|
onValueChange: onChange,
|
|
151
165
|
label,
|
|
@@ -154,34 +168,22 @@ var DynamicInput = ({
|
|
|
154
168
|
description
|
|
155
169
|
});
|
|
156
170
|
};
|
|
171
|
+
var DynamicInput = import_react2.default.memo(
|
|
172
|
+
DynamicInputInner
|
|
173
|
+
);
|
|
157
174
|
var DynamicInput_default = DynamicInput;
|
|
158
175
|
|
|
159
176
|
// src/components/FieldInput.tsx
|
|
160
|
-
var
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}) => {
|
|
166
|
-
const { name, type, label, options, className, description } = fieldDescription;
|
|
167
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
168
|
-
DynamicInput_default,
|
|
169
|
-
{
|
|
170
|
-
type,
|
|
171
|
-
label,
|
|
172
|
-
value: renderInfos[name],
|
|
173
|
-
options,
|
|
174
|
-
className,
|
|
175
|
-
description,
|
|
176
|
-
onChange: (v) => onValueChangeField(v, name)
|
|
177
|
-
}
|
|
178
|
-
);
|
|
179
|
-
};
|
|
180
|
-
var FieldInput_default = FieldInput;
|
|
177
|
+
var import_react5 = __toESM(require("react"));
|
|
178
|
+
|
|
179
|
+
// src/components/FieldGroupInput.tsx
|
|
180
|
+
var import_core3 = require("@dynamic-field-kit/core");
|
|
181
|
+
var import_react4 = require("react");
|
|
181
182
|
|
|
182
183
|
// src/components/MultiFieldInput.tsx
|
|
183
|
-
var
|
|
184
|
-
var
|
|
184
|
+
var import_core2 = require("@dynamic-field-kit/core");
|
|
185
|
+
var import_react3 = require("react");
|
|
186
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
185
187
|
function resolveLayout(layout) {
|
|
186
188
|
if (!layout) {
|
|
187
189
|
return { type: "column", config: {} };
|
|
@@ -197,38 +199,159 @@ var MultiFieldInput = ({
|
|
|
197
199
|
onChange,
|
|
198
200
|
layout
|
|
199
201
|
}) => {
|
|
200
|
-
const [data, setData] = (0,
|
|
201
|
-
(0,
|
|
202
|
+
const [data, setData] = (0, import_react3.useState)({});
|
|
203
|
+
(0, import_react3.useEffect)(() => {
|
|
202
204
|
if (properties) {
|
|
203
|
-
setData(properties);
|
|
205
|
+
setData((0, import_core2.applyComputedValues)(fieldDescriptions, properties));
|
|
204
206
|
}
|
|
205
207
|
}, [properties]);
|
|
206
|
-
const visibleFields = (0,
|
|
208
|
+
const visibleFields = (0, import_react3.useMemo)(
|
|
207
209
|
() => fieldDescriptions.filter(
|
|
208
210
|
(f) => !f.appearCondition || f.appearCondition(data)
|
|
209
211
|
),
|
|
210
212
|
[fieldDescriptions, data]
|
|
211
213
|
);
|
|
214
|
+
const dataRef = (0, import_react3.useRef)(data);
|
|
215
|
+
dataRef.current = data;
|
|
216
|
+
const onChangeRef = (0, import_react3.useRef)(onChange);
|
|
217
|
+
onChangeRef.current = onChange;
|
|
218
|
+
const fieldDescriptionsRef = (0, import_react3.useRef)(fieldDescriptions);
|
|
219
|
+
fieldDescriptionsRef.current = fieldDescriptions;
|
|
220
|
+
const handleValueChangeField = (0, import_react3.useCallback)((value, key) => {
|
|
221
|
+
const next = (0, import_core2.applyComputedValues)(fieldDescriptionsRef.current, {
|
|
222
|
+
...dataRef.current,
|
|
223
|
+
[key]: value
|
|
224
|
+
});
|
|
225
|
+
dataRef.current = next;
|
|
226
|
+
setData(next);
|
|
227
|
+
onChangeRef.current?.(next);
|
|
228
|
+
}, []);
|
|
212
229
|
const { type, config } = resolveLayout(layout);
|
|
213
230
|
const Layout = layoutRegistry.get(type);
|
|
214
231
|
if (!Layout) {
|
|
215
232
|
throw new Error(`Unknown layout: ${type}`);
|
|
216
233
|
}
|
|
217
|
-
return /* @__PURE__ */ (0,
|
|
234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Layout, { config, children: visibleFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
218
235
|
FieldInput_default,
|
|
219
236
|
{
|
|
220
237
|
fieldDescription: f,
|
|
221
238
|
renderInfos: data,
|
|
222
|
-
onValueChangeField:
|
|
223
|
-
const next = { ...data, [key]: value };
|
|
224
|
-
setData(next);
|
|
225
|
-
onChange?.(next);
|
|
226
|
-
}
|
|
239
|
+
onValueChangeField: handleValueChangeField
|
|
227
240
|
},
|
|
228
241
|
f.name
|
|
229
242
|
)) });
|
|
230
243
|
};
|
|
231
244
|
var MultiFieldInput_default = MultiFieldInput;
|
|
245
|
+
|
|
246
|
+
// src/components/FieldGroupInput.tsx
|
|
247
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
248
|
+
var FieldGroupInput = ({ fieldDescription, items, onChange }) => {
|
|
249
|
+
const { fields = [], label, addLabel, removeLabel } = fieldDescription;
|
|
250
|
+
const handleItemChange = (0, import_react4.useCallback)(
|
|
251
|
+
(index, next) => {
|
|
252
|
+
const nextItems = items.slice();
|
|
253
|
+
nextItems[index] = next;
|
|
254
|
+
onChange(nextItems);
|
|
255
|
+
},
|
|
256
|
+
[items, onChange]
|
|
257
|
+
);
|
|
258
|
+
const handleAdd = (0, import_react4.useCallback)(() => {
|
|
259
|
+
if (!(0, import_core3.canAddGroupItem)(fieldDescription, items)) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
onChange([...items, (0, import_core3.createGroupItem)(fieldDescription)]);
|
|
263
|
+
}, [fieldDescription, items, onChange]);
|
|
264
|
+
const handleRemove = (0, import_react4.useCallback)(
|
|
265
|
+
(index) => {
|
|
266
|
+
if (!(0, import_core3.canRemoveGroupItem)(fieldDescription, items)) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
onChange(items.filter((_, i) => i !== index));
|
|
270
|
+
},
|
|
271
|
+
[fieldDescription, items, onChange]
|
|
272
|
+
);
|
|
273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: fieldDescription.className, children: [
|
|
274
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { children: label }),
|
|
275
|
+
items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
276
|
+
"div",
|
|
277
|
+
{
|
|
278
|
+
style: { display: "flex", alignItems: "flex-start", gap: 8 },
|
|
279
|
+
children: [
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
281
|
+
MultiFieldInput_default,
|
|
282
|
+
{
|
|
283
|
+
fieldDescriptions: fields,
|
|
284
|
+
properties: item,
|
|
285
|
+
onChange: (next) => handleItemChange(index, next)
|
|
286
|
+
}
|
|
287
|
+
) }),
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
289
|
+
"button",
|
|
290
|
+
{
|
|
291
|
+
type: "button",
|
|
292
|
+
onClick: () => handleRemove(index),
|
|
293
|
+
disabled: !(0, import_core3.canRemoveGroupItem)(fieldDescription, items),
|
|
294
|
+
children: removeLabel ?? "Remove"
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
index
|
|
300
|
+
)),
|
|
301
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
302
|
+
"button",
|
|
303
|
+
{
|
|
304
|
+
type: "button",
|
|
305
|
+
onClick: handleAdd,
|
|
306
|
+
disabled: !(0, import_core3.canAddGroupItem)(fieldDescription, items),
|
|
307
|
+
children: addLabel ?? "Add"
|
|
308
|
+
}
|
|
309
|
+
)
|
|
310
|
+
] });
|
|
311
|
+
};
|
|
312
|
+
var FieldGroupInput_default = FieldGroupInput;
|
|
313
|
+
|
|
314
|
+
// src/components/FieldInput.tsx
|
|
315
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
316
|
+
var FieldInputInner = ({
|
|
317
|
+
fieldDescription,
|
|
318
|
+
renderInfos,
|
|
319
|
+
onValueChangeField
|
|
320
|
+
}) => {
|
|
321
|
+
const { name, type, label, options, className, description, fields } = fieldDescription;
|
|
322
|
+
const handleChange = (0, import_react5.useCallback)(
|
|
323
|
+
(v) => onValueChangeField(v, name),
|
|
324
|
+
[onValueChangeField, name]
|
|
325
|
+
);
|
|
326
|
+
if (fields) {
|
|
327
|
+
const items = Array.isArray(renderInfos[name]) ? renderInfos[name] : [];
|
|
328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
329
|
+
FieldGroupInput_default,
|
|
330
|
+
{
|
|
331
|
+
fieldDescription,
|
|
332
|
+
items,
|
|
333
|
+
onChange: handleChange
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
338
|
+
DynamicInput_default,
|
|
339
|
+
{
|
|
340
|
+
type,
|
|
341
|
+
label,
|
|
342
|
+
value: renderInfos[name],
|
|
343
|
+
options,
|
|
344
|
+
className,
|
|
345
|
+
description,
|
|
346
|
+
onChange: handleChange
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
};
|
|
350
|
+
var FieldInput = import_react5.default.memo(FieldInputInner, (prev, next) => {
|
|
351
|
+
const name = prev.fieldDescription.name;
|
|
352
|
+
return prev.fieldDescription === next.fieldDescription && prev.onValueChangeField === next.onValueChangeField && prev.renderInfos[name] === next.renderInfos[name];
|
|
353
|
+
});
|
|
354
|
+
var FieldInput_default = FieldInput;
|
|
232
355
|
// Annotate the CommonJS export names for ESM import in node:
|
|
233
356
|
0 && (module.exports = {
|
|
234
357
|
DynamicInput,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/layout/layoutRegistry.ts","../src/layout/defaultLayouts.tsx","../src/layout/responsiveLayout.tsx","../src/components/DynamicInput.tsx","../src/fieldRegistry.ts","../src/components/FieldInput.tsx","../src/components/MultiFieldInput.tsx"],"sourcesContent":["import './layout/defaultLayouts';\nimport './layout/responsiveLayout';\n\nexport { layoutRegistry } from './layout';\n\nexport { default as DynamicInput } from './components/DynamicInput';\nexport { default as FieldInput } from './components/FieldInput';\nexport { default as MultiFieldInput } from './components/MultiFieldInput';\nexport {\n fieldRegistry,\n type ReactFieldRenderer,\n type ReactFieldRegistry,\n} from './fieldRegistry';\n\nexport type { LayoutConfig } from './types/layout';\n// Re-export selected core APIs\nexport {\n type FieldTypeKey,\n type FieldDescription,\n type FieldRendererProps,\n} from '@dynamic-field-kit/core';\n","import React from 'react';\n\nexport type LayoutRenderer<C = any> = (props: {\n children: React.ReactNode;\n config?: C;\n}) => React.ReactElement;\n\nexport class LayoutRegistry {\n private layouts = new Map<string, LayoutRenderer>();\n\n register(type: string, renderer: LayoutRenderer) {\n if (this.layouts.has(type)) {\n console.warn(`[dynamic-field-kit] Layout \"${type}\" already exists`);\n }\n this.layouts.set(type, renderer);\n }\n\n get(type: string): LayoutRenderer | undefined {\n return this.layouts.get(type);\n }\n}\n\nexport const layoutRegistry = new LayoutRegistry();\n","import { layoutRegistry } from './layoutRegistry';\n\nlayoutRegistry.register('column', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: config?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('row', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'row',\n gap: config?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('grid', ({ children, config }) => (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${config?.columns ?? 2}, 1fr)`,\n gap: config?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n","import React from 'react';\nimport { LayoutConfig } from '../types/layout';\nimport { layoutRegistry } from './layoutRegistry';\n\nfunction resolve(layout: LayoutConfig) {\n if (typeof layout === 'string') {\n return { type: layout, config: {} };\n }\n return { type: layout.type, config: layout };\n}\n\nlayoutRegistry.register('responsive', ({ children, config }) => {\n const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;\n\n const current = isMobile ? config.mobile : config.desktop;\n if (!current) {\n return <>{children} </>;\n }\n\n const { type, config: childConfig } = resolve(current);\n const Renderer = layoutRegistry.get(type);\n\n if (!Renderer) {\n return <>{children} </>;\n }\n\n return <Renderer config={childConfig}>{children}</Renderer>;\n});\n","import { FieldTypeKey, Properties } from '@dynamic-field-kit/core';\nimport React, { ReactNode, useMemo } from 'react';\nimport { fieldRegistry } from '../fieldRegistry';\n\ninterface Props<T extends FieldTypeKey> {\n type: T;\n value?: any;\n onChange?: (value: any) => void;\n label?: string;\n options?: Properties[];\n className?: string;\n description?: ReactNode;\n}\n\nconst DynamicInput = <T extends FieldTypeKey>({\n type,\n value,\n onChange,\n label,\n options,\n className,\n description,\n}: Props<T>) => {\n // Memoize renderer lookup to avoid unnecessary work on re-renders\n const Renderer = useMemo(() => fieldRegistry.get(type), [type]) as any;\n\n if (!Renderer) {\n return <div>Unknown field type: {type}</div>;\n }\n\n // Use direct element creation to avoid TSX generic typing pitfalls\n const RendererEl = Renderer as any;\n return React.createElement(RendererEl, {\n value,\n onValueChange: onChange,\n label,\n options,\n className,\n description,\n });\n};\n\nexport default DynamicInput;\n","import {\n fieldRegistry as coreFieldRegistry,\n type FieldRendererProps,\n type FieldTypeMap,\n} from '@dynamic-field-kit/core';\nimport type { ComponentType } from 'react';\n\nexport type ReactFieldRenderer<T = any> = ComponentType<FieldRendererProps<T>>;\n\nexport interface ReactFieldRegistry {\n register<K extends keyof FieldTypeMap>(\n type: K,\n renderer: ReactFieldRenderer<FieldTypeMap[K]>\n ): void;\n get<K extends keyof FieldTypeMap>(\n type: K\n ): ReactFieldRenderer<FieldTypeMap[K]> | undefined;\n}\n\nexport const fieldRegistry = coreFieldRegistry as ReactFieldRegistry;\n","import { FieldDescription, Properties } from '@dynamic-field-kit/core';\nimport DynamicInput from './DynamicInput';\n\ninterface Props {\n fieldDescription: FieldDescription;\n renderInfos: Properties;\n onValueChangeField: (value: any, key: string) => void;\n}\n\nconst FieldInput = ({\n fieldDescription,\n renderInfos,\n onValueChangeField,\n}: Props) => {\n const { name, type, label, options, className, description } =\n fieldDescription;\n\n return (\n <DynamicInput\n type={type}\n label={label}\n value={renderInfos[name]}\n options={options}\n className={className}\n description={description}\n onChange={(v) => onValueChangeField(v, name)}\n />\n );\n};\n\nexport default FieldInput;\n","import { FieldDescription, Properties } from '@dynamic-field-kit/core';\r\nimport React, { useEffect, useMemo, useState } from 'react';\r\n\r\nimport { layoutRegistry } from '../layout';\r\nimport { LayoutConfig } from '../types/layout';\r\nimport FieldInput from './FieldInput';\r\n\r\ninterface Props {\r\n fieldDescriptions: FieldDescription[];\r\n properties?: Properties;\r\n onChange?: (data: Properties) => void;\r\n layout?: LayoutConfig;\r\n}\r\n\r\nfunction resolveLayout(layout?: LayoutConfig) {\r\n if (!layout) {\r\n return { type: 'column', config: {} };\r\n }\r\n if (typeof layout === 'string') {\r\n return { type: layout, config: {} };\r\n }\r\n return { type: layout.type, config: layout };\r\n}\r\n\r\nconst MultiFieldInput = ({\r\n fieldDescriptions,\r\n properties,\r\n onChange,\r\n layout,\r\n}: Props) => {\r\n const [data, setData] = useState<Properties>({});\r\n\r\n useEffect(() => {\r\n if (properties) {\r\n setData(properties);\r\n }\r\n }, [properties]);\r\n\r\n const visibleFields = useMemo(\r\n () =>\r\n fieldDescriptions.filter(\r\n (f) => !f.appearCondition || f.appearCondition(data)\r\n ),\r\n [fieldDescriptions, data]\r\n );\r\n\r\n const { type, config } = resolveLayout(layout);\r\n\r\n const Layout = layoutRegistry.get(type);\r\n\r\n if (!Layout) {\r\n throw new Error(`Unknown layout: ${type}`);\r\n }\r\n\r\n return (\r\n <Layout config={config}>\r\n {visibleFields.map((f) => (\r\n <FieldInput\r\n key={f.name}\r\n fieldDescription={f}\r\n renderInfos={data}\r\n onValueChangeField={(value, key) => {\r\n const next = { ...data, [key]: value };\r\n setData(next);\r\n onChange?.(next);\r\n }}\r\n />\r\n ))}\r\n </Layout>\r\n );\r\n};\r\n\r\nexport default MultiFieldInput;\r\n"],"mappings":"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","names":["import_jsx_runtime","coreFieldRegistry","import_jsx_runtime","React","import_jsx_runtime","import_react","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/layout/layoutRegistry.ts","../src/layout/defaultLayouts.tsx","../src/layout/responsiveLayout.tsx","../src/components/DynamicInput.tsx","../src/fieldRegistry.ts","../src/components/FieldInput.tsx","../src/components/FieldGroupInput.tsx","../src/components/MultiFieldInput.tsx"],"sourcesContent":["import './layout/defaultLayouts';\nimport './layout/responsiveLayout';\n\nexport { layoutRegistry } from './layout';\n\nexport { default as DynamicInput } from './components/DynamicInput';\nexport { default as FieldInput } from './components/FieldInput';\nexport { default as MultiFieldInput } from './components/MultiFieldInput';\nexport {\n fieldRegistry,\n type ReactFieldRenderer,\n type ReactFieldRegistry,\n} from './fieldRegistry';\n\nexport type { LayoutConfig } from './types/layout';\n// Re-export selected core APIs\nexport {\n type FieldTypeKey,\n type FieldDescription,\n type FieldRendererProps,\n} from '@dynamic-field-kit/core';\n","import React from 'react';\n\nexport type BaseLayout =\n | 'column'\n | 'row'\n | {\n type: 'grid';\n columns?: number;\n gap?: number;\n };\n\nexport type ResponsiveLayout = {\n type: 'responsive';\n mobile: BaseLayout;\n desktop: BaseLayout;\n breakpoint?: number;\n};\n\nexport type LayoutConfig = BaseLayout | ResponsiveLayout;\n\nexport type LayoutRenderer<C = unknown> = (props: {\n children: React.ReactNode;\n config?: C;\n}) => React.ReactElement;\n\nexport class LayoutRegistry {\n private layouts = new Map<string, LayoutRenderer>();\n\n register(type: string, renderer: LayoutRenderer) {\n if (this.layouts.has(type)) {\n console.warn(`[dynamic-field-kit] Layout \"${type}\" already exists`);\n }\n this.layouts.set(type, renderer);\n }\n\n get(type: string): LayoutRenderer | undefined {\n return this.layouts.get(type);\n }\n}\n\nexport const layoutRegistry = new LayoutRegistry();\n","import { layoutRegistry } from './layoutRegistry';\n\ninterface GridConfig {\n gap?: number;\n columns?: number;\n}\n\nlayoutRegistry.register('column', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: (config as { gap?: number })?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('row', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'row',\n gap: (config as { gap?: number })?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('grid', ({ children, config }) => (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${\n (config as GridConfig)?.columns ?? 2\n }, 1fr)`,\n gap: (config as GridConfig)?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n","import React, { useEffect, useState } from 'react';\nimport {\n LayoutConfig,\n ResponsiveLayout,\n layoutRegistry,\n} from './layoutRegistry';\n\nfunction resolve(layout: LayoutConfig) {\n if (typeof layout === 'string') {\n return { type: layout, config: {} };\n }\n return { type: layout.type, config: layout };\n}\n\nfunction checkIsMobile(breakpoint: number) {\n return typeof window !== 'undefined' && window.innerWidth < breakpoint;\n}\n\nlayoutRegistry.register('responsive', ({ children, config }) => {\n const responsiveConfig = config as ResponsiveLayout;\n const breakpoint = responsiveConfig.breakpoint ?? 768;\n\n // Registered as a real component (invoked via JSX in MultiFieldInput), so\n // hooks are safe here and let the layout react to viewport resizes instead\n // of freezing whatever the width happened to be on first render.\n const [isMobile, setIsMobile] = useState(() => checkIsMobile(breakpoint));\n\n useEffect(() => {\n const handleResize = () => setIsMobile(checkIsMobile(breakpoint));\n handleResize();\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [breakpoint]);\n\n const current = isMobile ? responsiveConfig.mobile : responsiveConfig.desktop;\n if (!current) {\n return <>{children} </>;\n }\n\n const { type, config: childConfig } = resolve(current);\n const Renderer = layoutRegistry.get(type);\n\n if (!Renderer) {\n return <>{children} </>;\n }\n\n return <Renderer config={childConfig}>{children}</Renderer>;\n});\n","import {\n FieldRendererProps,\n FieldTypeKey,\n Properties,\n} from '@dynamic-field-kit/core';\nimport React, { ReactNode, useMemo } from 'react';\nimport { fieldRegistry } from '../fieldRegistry';\n\ninterface Props<T extends FieldTypeKey> {\n type: T;\n value?: unknown;\n onChange?: (value: unknown) => void;\n label?: string;\n options?: Properties[];\n className?: string;\n description?: ReactNode;\n}\n\nconst DynamicInputInner = <T extends FieldTypeKey>({\n type,\n value,\n onChange,\n label,\n options,\n className,\n description,\n}: Props<T>) => {\n // Memoize renderer lookup to avoid unnecessary work on re-renders\n const Renderer = useMemo(\n () => fieldRegistry.get(type) as React.ComponentType<FieldRendererProps>,\n [type]\n );\n\n if (!Renderer) {\n return <div>Unknown field type: {type}</div>;\n }\n\n return React.createElement(Renderer, {\n value,\n onValueChange: onChange,\n label,\n options,\n className,\n description,\n });\n};\n\n// Skip re-render when none of the rendered props actually changed, so\n// unaffected fields don't re-render every time a sibling field's value changes.\n// React.memo erases the generic signature, so restore it via an `unknown`\n// round-trip (plain `as typeof DynamicInputInner` fails dts generation).\nconst DynamicInput = React.memo(\n DynamicInputInner\n) as unknown as typeof DynamicInputInner;\n\nexport default DynamicInput;\n","import {\n fieldRegistry as coreFieldRegistry,\n type FieldRendererProps,\n type FieldTypeMap,\n} from '@dynamic-field-kit/core';\nimport type { ComponentType } from 'react';\n\nexport type ReactFieldRenderer<T = unknown> = ComponentType<\n FieldRendererProps<T>\n>;\n\nexport interface ReactFieldRegistry {\n register<K extends keyof FieldTypeMap>(\n type: K,\n renderer: ReactFieldRenderer<FieldTypeMap[K]>\n ): void;\n get<K extends keyof FieldTypeMap>(\n type: K\n ): ReactFieldRenderer<FieldTypeMap[K]> | undefined;\n}\n\nexport const fieldRegistry = coreFieldRegistry as ReactFieldRegistry;\n","import { FieldDescription, Properties } from '@dynamic-field-kit/core';\nimport React, { useCallback } from 'react';\nimport DynamicInput from './DynamicInput';\nimport FieldGroupInput from './FieldGroupInput';\n\ninterface Props {\n fieldDescription: FieldDescription;\n renderInfos: Properties;\n onValueChangeField: (value: unknown, key: string) => void;\n}\n\nconst FieldInputInner = ({\n fieldDescription,\n renderInfos,\n onValueChangeField,\n}: Props) => {\n const { name, type, label, options, className, description, fields } =\n fieldDescription;\n\n // Stable per-field handler so DynamicInput's memoization isn't defeated\n // by a freshly-allocated closure on every parent render.\n const handleChange = useCallback(\n (v: unknown) => onValueChangeField(v, name),\n [onValueChangeField, name]\n );\n\n if (fields) {\n const items = Array.isArray(renderInfos[name])\n ? (renderInfos[name] as Properties[])\n : [];\n\n return (\n <FieldGroupInput\n fieldDescription={fieldDescription}\n items={items}\n onChange={handleChange}\n />\n );\n }\n\n return (\n <DynamicInput\n type={type}\n label={label}\n value={renderInfos[name]}\n options={options}\n className={className}\n description={description as React.ReactNode}\n onChange={handleChange}\n />\n );\n};\n\n// `renderInfos` covers every field, so the default shallow-prop compare would\n// re-render all fields whenever any one of them changes. Compare only the\n// slice this field actually reads instead.\nconst FieldInput = React.memo(FieldInputInner, (prev, next) => {\n const name = prev.fieldDescription.name;\n return (\n prev.fieldDescription === next.fieldDescription &&\n prev.onValueChangeField === next.onValueChangeField &&\n prev.renderInfos[name] === next.renderInfos[name]\n );\n});\n\nexport default FieldInput;\n","import {\n canAddGroupItem,\n canRemoveGroupItem,\n createGroupItem,\n FieldDescription,\n Properties,\n} from '@dynamic-field-kit/core';\nimport React, { useCallback } from 'react';\nimport MultiFieldInput from './MultiFieldInput';\n\ninterface Props {\n fieldDescription: FieldDescription;\n items: Properties[];\n onChange: (items: Properties[]) => void;\n}\n\nconst FieldGroupInput = ({ fieldDescription, items, onChange }: Props) => {\n const { fields = [], label, addLabel, removeLabel } = fieldDescription;\n\n const handleItemChange = useCallback(\n (index: number, next: Properties) => {\n const nextItems = items.slice();\n nextItems[index] = next;\n onChange(nextItems);\n },\n [items, onChange]\n );\n\n const handleAdd = useCallback(() => {\n if (!canAddGroupItem(fieldDescription, items)) {\n return;\n }\n onChange([...items, createGroupItem(fieldDescription)]);\n }, [fieldDescription, items, onChange]);\n\n const handleRemove = useCallback(\n (index: number) => {\n if (!canRemoveGroupItem(fieldDescription, items)) {\n return;\n }\n onChange(items.filter((_, i) => i !== index));\n },\n [fieldDescription, items, onChange]\n );\n\n return (\n <div className={fieldDescription.className}>\n {label && <div>{label}</div>}\n {items.map((item, index) => (\n <div\n key={index}\n style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}\n >\n <div style={{ flex: 1 }}>\n <MultiFieldInput\n fieldDescriptions={fields}\n properties={item}\n onChange={(next) => handleItemChange(index, next)}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => handleRemove(index)}\n disabled={!canRemoveGroupItem(fieldDescription, items)}\n >\n {removeLabel ?? 'Remove'}\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={handleAdd}\n disabled={!canAddGroupItem(fieldDescription, items)}\n >\n {addLabel ?? 'Add'}\n </button>\n </div>\n );\n};\n\nexport default FieldGroupInput;\n","import {\r\n applyComputedValues,\r\n FieldDescription,\r\n Properties,\r\n} from '@dynamic-field-kit/core';\r\nimport React, {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\n\r\nimport { layoutRegistry, LayoutConfig } from '../layout';\r\nimport FieldInput from './FieldInput';\r\n\r\ninterface Props {\r\n fieldDescriptions: FieldDescription[];\r\n properties?: Properties;\r\n onChange?: (data: Properties) => void;\r\n layout?: LayoutConfig;\r\n}\r\n\r\nfunction resolveLayout(layout?: LayoutConfig) {\r\n if (!layout) {\r\n return { type: 'column', config: {} };\r\n }\r\n if (typeof layout === 'string') {\r\n return { type: layout, config: {} };\r\n }\r\n return { type: layout.type, config: layout };\r\n}\r\n\r\nconst MultiFieldInput = ({\r\n fieldDescriptions,\r\n properties,\r\n onChange,\r\n layout,\r\n}: Props) => {\r\n const [data, setData] = useState<Properties>({});\r\n\r\n useEffect(() => {\r\n if (properties) {\r\n setData(applyComputedValues(fieldDescriptions, properties));\r\n }\r\n // Only re-run when `properties` itself changes; recomputing on every\r\n // fieldDescriptions identity change would fight user edits mid-session.\r\n }, [properties]);\r\n\r\n const visibleFields = useMemo(\r\n () =>\r\n fieldDescriptions.filter(\r\n (f) => !f.appearCondition || f.appearCondition(data)\r\n ),\r\n [fieldDescriptions, data]\r\n );\r\n\r\n // Keep the latest data/onChange in refs so handleValueChangeField can stay\r\n // referentially stable (empty deps) without defeating FieldInput's memoization,\r\n // and without calling onChange from inside a setState updater (must stay pure).\r\n const dataRef = useRef(data);\r\n dataRef.current = data;\r\n const onChangeRef = useRef(onChange);\r\n onChangeRef.current = onChange;\r\n const fieldDescriptionsRef = useRef(fieldDescriptions);\r\n fieldDescriptionsRef.current = fieldDescriptions;\r\n\r\n const handleValueChangeField = useCallback((value: unknown, key: string) => {\r\n const next = applyComputedValues(fieldDescriptionsRef.current, {\r\n ...dataRef.current,\r\n [key]: value,\r\n });\r\n dataRef.current = next;\r\n setData(next);\r\n onChangeRef.current?.(next);\r\n }, []);\r\n\r\n const { type, config } = resolveLayout(layout);\r\n\r\n const Layout = layoutRegistry.get(type);\r\n\r\n if (!Layout) {\r\n throw new Error(`Unknown layout: ${type}`);\r\n }\r\n\r\n return (\r\n <Layout config={config}>\r\n {visibleFields.map((f) => (\r\n <FieldInput\r\n key={f.name}\r\n fieldDescription={f}\r\n renderInfos={data}\r\n onValueChangeField={handleValueChangeField}\r\n />\r\n ))}\r\n </Layout>\r\n );\r\n};\r\n\r\nexport default MultiFieldInput;\r\n"],"mappings":"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","names":["import_jsx_runtime","import_react","coreFieldRegistry","import_jsx_runtime","React","import_react","import_core","import_react","import_core","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React"]}
|
package/dist/index.mjs
CHANGED
|
@@ -52,6 +52,7 @@ layoutRegistry.register("grid", ({ children, config }) => /* @__PURE__ */ jsx(
|
|
|
52
52
|
));
|
|
53
53
|
|
|
54
54
|
// src/layout/responsiveLayout.tsx
|
|
55
|
+
import { useEffect, useState } from "react";
|
|
55
56
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
56
57
|
function resolve(layout) {
|
|
57
58
|
if (typeof layout === "string") {
|
|
@@ -59,9 +60,20 @@ function resolve(layout) {
|
|
|
59
60
|
}
|
|
60
61
|
return { type: layout.type, config: layout };
|
|
61
62
|
}
|
|
63
|
+
function checkIsMobile(breakpoint) {
|
|
64
|
+
return typeof window !== "undefined" && window.innerWidth < breakpoint;
|
|
65
|
+
}
|
|
62
66
|
layoutRegistry.register("responsive", ({ children, config }) => {
|
|
63
|
-
const
|
|
64
|
-
const
|
|
67
|
+
const responsiveConfig = config;
|
|
68
|
+
const breakpoint = responsiveConfig.breakpoint ?? 768;
|
|
69
|
+
const [isMobile, setIsMobile] = useState(() => checkIsMobile(breakpoint));
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
const handleResize = () => setIsMobile(checkIsMobile(breakpoint));
|
|
72
|
+
handleResize();
|
|
73
|
+
window.addEventListener("resize", handleResize);
|
|
74
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
75
|
+
}, [breakpoint]);
|
|
76
|
+
const current = isMobile ? responsiveConfig.mobile : responsiveConfig.desktop;
|
|
65
77
|
if (!current) {
|
|
66
78
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
67
79
|
children,
|
|
@@ -80,7 +92,7 @@ layoutRegistry.register("responsive", ({ children, config }) => {
|
|
|
80
92
|
});
|
|
81
93
|
|
|
82
94
|
// src/components/DynamicInput.tsx
|
|
83
|
-
import
|
|
95
|
+
import React2, { useMemo } from "react";
|
|
84
96
|
|
|
85
97
|
// src/fieldRegistry.ts
|
|
86
98
|
import {
|
|
@@ -90,7 +102,7 @@ var fieldRegistry = coreFieldRegistry;
|
|
|
90
102
|
|
|
91
103
|
// src/components/DynamicInput.tsx
|
|
92
104
|
import { jsxs as jsxs2 } from "react/jsx-runtime";
|
|
93
|
-
var
|
|
105
|
+
var DynamicInputInner = ({
|
|
94
106
|
type,
|
|
95
107
|
value,
|
|
96
108
|
onChange,
|
|
@@ -99,15 +111,17 @@ var DynamicInput = ({
|
|
|
99
111
|
className,
|
|
100
112
|
description
|
|
101
113
|
}) => {
|
|
102
|
-
const Renderer = useMemo(
|
|
114
|
+
const Renderer = useMemo(
|
|
115
|
+
() => fieldRegistry.get(type),
|
|
116
|
+
[type]
|
|
117
|
+
);
|
|
103
118
|
if (!Renderer) {
|
|
104
119
|
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
105
120
|
"Unknown field type: ",
|
|
106
121
|
type
|
|
107
122
|
] });
|
|
108
123
|
}
|
|
109
|
-
|
|
110
|
-
return React.createElement(RendererEl, {
|
|
124
|
+
return React2.createElement(Renderer, {
|
|
111
125
|
value,
|
|
112
126
|
onValueChange: onChange,
|
|
113
127
|
label,
|
|
@@ -116,34 +130,34 @@ var DynamicInput = ({
|
|
|
116
130
|
description
|
|
117
131
|
});
|
|
118
132
|
};
|
|
133
|
+
var DynamicInput = React2.memo(
|
|
134
|
+
DynamicInputInner
|
|
135
|
+
);
|
|
119
136
|
var DynamicInput_default = DynamicInput;
|
|
120
137
|
|
|
121
138
|
// src/components/FieldInput.tsx
|
|
122
|
-
import {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
{
|
|
132
|
-
type,
|
|
133
|
-
label,
|
|
134
|
-
value: renderInfos[name],
|
|
135
|
-
options,
|
|
136
|
-
className,
|
|
137
|
-
description,
|
|
138
|
-
onChange: (v) => onValueChangeField(v, name)
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
};
|
|
142
|
-
var FieldInput_default = FieldInput;
|
|
139
|
+
import React5, { useCallback as useCallback3 } from "react";
|
|
140
|
+
|
|
141
|
+
// src/components/FieldGroupInput.tsx
|
|
142
|
+
import {
|
|
143
|
+
canAddGroupItem,
|
|
144
|
+
canRemoveGroupItem,
|
|
145
|
+
createGroupItem
|
|
146
|
+
} from "@dynamic-field-kit/core";
|
|
147
|
+
import { useCallback as useCallback2 } from "react";
|
|
143
148
|
|
|
144
149
|
// src/components/MultiFieldInput.tsx
|
|
145
|
-
import {
|
|
146
|
-
|
|
150
|
+
import {
|
|
151
|
+
applyComputedValues
|
|
152
|
+
} from "@dynamic-field-kit/core";
|
|
153
|
+
import {
|
|
154
|
+
useCallback,
|
|
155
|
+
useEffect as useEffect2,
|
|
156
|
+
useMemo as useMemo2,
|
|
157
|
+
useRef,
|
|
158
|
+
useState as useState2
|
|
159
|
+
} from "react";
|
|
160
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
147
161
|
function resolveLayout(layout) {
|
|
148
162
|
if (!layout) {
|
|
149
163
|
return { type: "column", config: {} };
|
|
@@ -159,10 +173,10 @@ var MultiFieldInput = ({
|
|
|
159
173
|
onChange,
|
|
160
174
|
layout
|
|
161
175
|
}) => {
|
|
162
|
-
const [data, setData] =
|
|
163
|
-
|
|
176
|
+
const [data, setData] = useState2({});
|
|
177
|
+
useEffect2(() => {
|
|
164
178
|
if (properties) {
|
|
165
|
-
setData(properties);
|
|
179
|
+
setData(applyComputedValues(fieldDescriptions, properties));
|
|
166
180
|
}
|
|
167
181
|
}, [properties]);
|
|
168
182
|
const visibleFields = useMemo2(
|
|
@@ -171,26 +185,147 @@ var MultiFieldInput = ({
|
|
|
171
185
|
),
|
|
172
186
|
[fieldDescriptions, data]
|
|
173
187
|
);
|
|
188
|
+
const dataRef = useRef(data);
|
|
189
|
+
dataRef.current = data;
|
|
190
|
+
const onChangeRef = useRef(onChange);
|
|
191
|
+
onChangeRef.current = onChange;
|
|
192
|
+
const fieldDescriptionsRef = useRef(fieldDescriptions);
|
|
193
|
+
fieldDescriptionsRef.current = fieldDescriptions;
|
|
194
|
+
const handleValueChangeField = useCallback((value, key) => {
|
|
195
|
+
const next = applyComputedValues(fieldDescriptionsRef.current, {
|
|
196
|
+
...dataRef.current,
|
|
197
|
+
[key]: value
|
|
198
|
+
});
|
|
199
|
+
dataRef.current = next;
|
|
200
|
+
setData(next);
|
|
201
|
+
onChangeRef.current?.(next);
|
|
202
|
+
}, []);
|
|
174
203
|
const { type, config } = resolveLayout(layout);
|
|
175
204
|
const Layout = layoutRegistry.get(type);
|
|
176
205
|
if (!Layout) {
|
|
177
206
|
throw new Error(`Unknown layout: ${type}`);
|
|
178
207
|
}
|
|
179
|
-
return /* @__PURE__ */
|
|
208
|
+
return /* @__PURE__ */ jsx3(Layout, { config, children: visibleFields.map((f) => /* @__PURE__ */ jsx3(
|
|
180
209
|
FieldInput_default,
|
|
181
210
|
{
|
|
182
211
|
fieldDescription: f,
|
|
183
212
|
renderInfos: data,
|
|
184
|
-
onValueChangeField:
|
|
185
|
-
const next = { ...data, [key]: value };
|
|
186
|
-
setData(next);
|
|
187
|
-
onChange?.(next);
|
|
188
|
-
}
|
|
213
|
+
onValueChangeField: handleValueChangeField
|
|
189
214
|
},
|
|
190
215
|
f.name
|
|
191
216
|
)) });
|
|
192
217
|
};
|
|
193
218
|
var MultiFieldInput_default = MultiFieldInput;
|
|
219
|
+
|
|
220
|
+
// src/components/FieldGroupInput.tsx
|
|
221
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
222
|
+
var FieldGroupInput = ({ fieldDescription, items, onChange }) => {
|
|
223
|
+
const { fields = [], label, addLabel, removeLabel } = fieldDescription;
|
|
224
|
+
const handleItemChange = useCallback2(
|
|
225
|
+
(index, next) => {
|
|
226
|
+
const nextItems = items.slice();
|
|
227
|
+
nextItems[index] = next;
|
|
228
|
+
onChange(nextItems);
|
|
229
|
+
},
|
|
230
|
+
[items, onChange]
|
|
231
|
+
);
|
|
232
|
+
const handleAdd = useCallback2(() => {
|
|
233
|
+
if (!canAddGroupItem(fieldDescription, items)) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
onChange([...items, createGroupItem(fieldDescription)]);
|
|
237
|
+
}, [fieldDescription, items, onChange]);
|
|
238
|
+
const handleRemove = useCallback2(
|
|
239
|
+
(index) => {
|
|
240
|
+
if (!canRemoveGroupItem(fieldDescription, items)) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
onChange(items.filter((_, i) => i !== index));
|
|
244
|
+
},
|
|
245
|
+
[fieldDescription, items, onChange]
|
|
246
|
+
);
|
|
247
|
+
return /* @__PURE__ */ jsxs3("div", { className: fieldDescription.className, children: [
|
|
248
|
+
label && /* @__PURE__ */ jsx4("div", { children: label }),
|
|
249
|
+
items.map((item, index) => /* @__PURE__ */ jsxs3(
|
|
250
|
+
"div",
|
|
251
|
+
{
|
|
252
|
+
style: { display: "flex", alignItems: "flex-start", gap: 8 },
|
|
253
|
+
children: [
|
|
254
|
+
/* @__PURE__ */ jsx4("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsx4(
|
|
255
|
+
MultiFieldInput_default,
|
|
256
|
+
{
|
|
257
|
+
fieldDescriptions: fields,
|
|
258
|
+
properties: item,
|
|
259
|
+
onChange: (next) => handleItemChange(index, next)
|
|
260
|
+
}
|
|
261
|
+
) }),
|
|
262
|
+
/* @__PURE__ */ jsx4(
|
|
263
|
+
"button",
|
|
264
|
+
{
|
|
265
|
+
type: "button",
|
|
266
|
+
onClick: () => handleRemove(index),
|
|
267
|
+
disabled: !canRemoveGroupItem(fieldDescription, items),
|
|
268
|
+
children: removeLabel ?? "Remove"
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
]
|
|
272
|
+
},
|
|
273
|
+
index
|
|
274
|
+
)),
|
|
275
|
+
/* @__PURE__ */ jsx4(
|
|
276
|
+
"button",
|
|
277
|
+
{
|
|
278
|
+
type: "button",
|
|
279
|
+
onClick: handleAdd,
|
|
280
|
+
disabled: !canAddGroupItem(fieldDescription, items),
|
|
281
|
+
children: addLabel ?? "Add"
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
] });
|
|
285
|
+
};
|
|
286
|
+
var FieldGroupInput_default = FieldGroupInput;
|
|
287
|
+
|
|
288
|
+
// src/components/FieldInput.tsx
|
|
289
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
290
|
+
var FieldInputInner = ({
|
|
291
|
+
fieldDescription,
|
|
292
|
+
renderInfos,
|
|
293
|
+
onValueChangeField
|
|
294
|
+
}) => {
|
|
295
|
+
const { name, type, label, options, className, description, fields } = fieldDescription;
|
|
296
|
+
const handleChange = useCallback3(
|
|
297
|
+
(v) => onValueChangeField(v, name),
|
|
298
|
+
[onValueChangeField, name]
|
|
299
|
+
);
|
|
300
|
+
if (fields) {
|
|
301
|
+
const items = Array.isArray(renderInfos[name]) ? renderInfos[name] : [];
|
|
302
|
+
return /* @__PURE__ */ jsx5(
|
|
303
|
+
FieldGroupInput_default,
|
|
304
|
+
{
|
|
305
|
+
fieldDescription,
|
|
306
|
+
items,
|
|
307
|
+
onChange: handleChange
|
|
308
|
+
}
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
return /* @__PURE__ */ jsx5(
|
|
312
|
+
DynamicInput_default,
|
|
313
|
+
{
|
|
314
|
+
type,
|
|
315
|
+
label,
|
|
316
|
+
value: renderInfos[name],
|
|
317
|
+
options,
|
|
318
|
+
className,
|
|
319
|
+
description,
|
|
320
|
+
onChange: handleChange
|
|
321
|
+
}
|
|
322
|
+
);
|
|
323
|
+
};
|
|
324
|
+
var FieldInput = React5.memo(FieldInputInner, (prev, next) => {
|
|
325
|
+
const name = prev.fieldDescription.name;
|
|
326
|
+
return prev.fieldDescription === next.fieldDescription && prev.onValueChangeField === next.onValueChangeField && prev.renderInfos[name] === next.renderInfos[name];
|
|
327
|
+
});
|
|
328
|
+
var FieldInput_default = FieldInput;
|
|
194
329
|
export {
|
|
195
330
|
DynamicInput_default as DynamicInput,
|
|
196
331
|
FieldInput_default as FieldInput,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/layout/layoutRegistry.ts","../src/layout/defaultLayouts.tsx","../src/layout/responsiveLayout.tsx","../src/components/DynamicInput.tsx","../src/fieldRegistry.ts","../src/components/FieldInput.tsx","../src/components/MultiFieldInput.tsx"],"sourcesContent":["import React from 'react';\n\nexport type LayoutRenderer<C = any> = (props: {\n children: React.ReactNode;\n config?: C;\n}) => React.ReactElement;\n\nexport class LayoutRegistry {\n private layouts = new Map<string, LayoutRenderer>();\n\n register(type: string, renderer: LayoutRenderer) {\n if (this.layouts.has(type)) {\n console.warn(`[dynamic-field-kit] Layout \"${type}\" already exists`);\n }\n this.layouts.set(type, renderer);\n }\n\n get(type: string): LayoutRenderer | undefined {\n return this.layouts.get(type);\n }\n}\n\nexport const layoutRegistry = new LayoutRegistry();\n","import { layoutRegistry } from './layoutRegistry';\n\nlayoutRegistry.register('column', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: config?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('row', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'row',\n gap: config?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('grid', ({ children, config }) => (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${config?.columns ?? 2}, 1fr)`,\n gap: config?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n","import React from 'react';\nimport { LayoutConfig } from '../types/layout';\nimport { layoutRegistry } from './layoutRegistry';\n\nfunction resolve(layout: LayoutConfig) {\n if (typeof layout === 'string') {\n return { type: layout, config: {} };\n }\n return { type: layout.type, config: layout };\n}\n\nlayoutRegistry.register('responsive', ({ children, config }) => {\n const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;\n\n const current = isMobile ? config.mobile : config.desktop;\n if (!current) {\n return <>{children} </>;\n }\n\n const { type, config: childConfig } = resolve(current);\n const Renderer = layoutRegistry.get(type);\n\n if (!Renderer) {\n return <>{children} </>;\n }\n\n return <Renderer config={childConfig}>{children}</Renderer>;\n});\n","import { FieldTypeKey, Properties } from '@dynamic-field-kit/core';\nimport React, { ReactNode, useMemo } from 'react';\nimport { fieldRegistry } from '../fieldRegistry';\n\ninterface Props<T extends FieldTypeKey> {\n type: T;\n value?: any;\n onChange?: (value: any) => void;\n label?: string;\n options?: Properties[];\n className?: string;\n description?: ReactNode;\n}\n\nconst DynamicInput = <T extends FieldTypeKey>({\n type,\n value,\n onChange,\n label,\n options,\n className,\n description,\n}: Props<T>) => {\n // Memoize renderer lookup to avoid unnecessary work on re-renders\n const Renderer = useMemo(() => fieldRegistry.get(type), [type]) as any;\n\n if (!Renderer) {\n return <div>Unknown field type: {type}</div>;\n }\n\n // Use direct element creation to avoid TSX generic typing pitfalls\n const RendererEl = Renderer as any;\n return React.createElement(RendererEl, {\n value,\n onValueChange: onChange,\n label,\n options,\n className,\n description,\n });\n};\n\nexport default DynamicInput;\n","import {\n fieldRegistry as coreFieldRegistry,\n type FieldRendererProps,\n type FieldTypeMap,\n} from '@dynamic-field-kit/core';\nimport type { ComponentType } from 'react';\n\nexport type ReactFieldRenderer<T = any> = ComponentType<FieldRendererProps<T>>;\n\nexport interface ReactFieldRegistry {\n register<K extends keyof FieldTypeMap>(\n type: K,\n renderer: ReactFieldRenderer<FieldTypeMap[K]>\n ): void;\n get<K extends keyof FieldTypeMap>(\n type: K\n ): ReactFieldRenderer<FieldTypeMap[K]> | undefined;\n}\n\nexport const fieldRegistry = coreFieldRegistry as ReactFieldRegistry;\n","import { FieldDescription, Properties } from '@dynamic-field-kit/core';\nimport DynamicInput from './DynamicInput';\n\ninterface Props {\n fieldDescription: FieldDescription;\n renderInfos: Properties;\n onValueChangeField: (value: any, key: string) => void;\n}\n\nconst FieldInput = ({\n fieldDescription,\n renderInfos,\n onValueChangeField,\n}: Props) => {\n const { name, type, label, options, className, description } =\n fieldDescription;\n\n return (\n <DynamicInput\n type={type}\n label={label}\n value={renderInfos[name]}\n options={options}\n className={className}\n description={description}\n onChange={(v) => onValueChangeField(v, name)}\n />\n );\n};\n\nexport default FieldInput;\n","import { FieldDescription, Properties } from '@dynamic-field-kit/core';\r\nimport React, { useEffect, useMemo, useState } from 'react';\r\n\r\nimport { layoutRegistry } from '../layout';\r\nimport { LayoutConfig } from '../types/layout';\r\nimport FieldInput from './FieldInput';\r\n\r\ninterface Props {\r\n fieldDescriptions: FieldDescription[];\r\n properties?: Properties;\r\n onChange?: (data: Properties) => void;\r\n layout?: LayoutConfig;\r\n}\r\n\r\nfunction resolveLayout(layout?: LayoutConfig) {\r\n if (!layout) {\r\n return { type: 'column', config: {} };\r\n }\r\n if (typeof layout === 'string') {\r\n return { type: layout, config: {} };\r\n }\r\n return { type: layout.type, config: layout };\r\n}\r\n\r\nconst MultiFieldInput = ({\r\n fieldDescriptions,\r\n properties,\r\n onChange,\r\n layout,\r\n}: Props) => {\r\n const [data, setData] = useState<Properties>({});\r\n\r\n useEffect(() => {\r\n if (properties) {\r\n setData(properties);\r\n }\r\n }, [properties]);\r\n\r\n const visibleFields = useMemo(\r\n () =>\r\n fieldDescriptions.filter(\r\n (f) => !f.appearCondition || f.appearCondition(data)\r\n ),\r\n [fieldDescriptions, data]\r\n );\r\n\r\n const { type, config } = resolveLayout(layout);\r\n\r\n const Layout = layoutRegistry.get(type);\r\n\r\n if (!Layout) {\r\n throw new Error(`Unknown layout: ${type}`);\r\n }\r\n\r\n return (\r\n <Layout config={config}>\r\n {visibleFields.map((f) => (\r\n <FieldInput\r\n key={f.name}\r\n fieldDescription={f}\r\n renderInfos={data}\r\n onValueChangeField={(value, key) => {\r\n const next = { ...data, [key]: value };\r\n setData(next);\r\n onChange?.(next);\r\n }}\r\n />\r\n ))}\r\n </Layout>\r\n );\r\n};\r\n\r\nexport default MultiFieldInput;\r\n"],"mappings":"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","names":["jsx","jsxs","jsx","useMemo","jsx","useMemo"]}
|
|
1
|
+
{"version":3,"sources":["../src/layout/layoutRegistry.ts","../src/layout/defaultLayouts.tsx","../src/layout/responsiveLayout.tsx","../src/components/DynamicInput.tsx","../src/fieldRegistry.ts","../src/components/FieldInput.tsx","../src/components/FieldGroupInput.tsx","../src/components/MultiFieldInput.tsx"],"sourcesContent":["import React from 'react';\n\nexport type BaseLayout =\n | 'column'\n | 'row'\n | {\n type: 'grid';\n columns?: number;\n gap?: number;\n };\n\nexport type ResponsiveLayout = {\n type: 'responsive';\n mobile: BaseLayout;\n desktop: BaseLayout;\n breakpoint?: number;\n};\n\nexport type LayoutConfig = BaseLayout | ResponsiveLayout;\n\nexport type LayoutRenderer<C = unknown> = (props: {\n children: React.ReactNode;\n config?: C;\n}) => React.ReactElement;\n\nexport class LayoutRegistry {\n private layouts = new Map<string, LayoutRenderer>();\n\n register(type: string, renderer: LayoutRenderer) {\n if (this.layouts.has(type)) {\n console.warn(`[dynamic-field-kit] Layout \"${type}\" already exists`);\n }\n this.layouts.set(type, renderer);\n }\n\n get(type: string): LayoutRenderer | undefined {\n return this.layouts.get(type);\n }\n}\n\nexport const layoutRegistry = new LayoutRegistry();\n","import { layoutRegistry } from './layoutRegistry';\n\ninterface GridConfig {\n gap?: number;\n columns?: number;\n}\n\nlayoutRegistry.register('column', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'column',\n gap: (config as { gap?: number })?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('row', ({ children, config }) => (\n <div\n style={{\n display: 'flex',\n flexDirection: 'row',\n gap: (config as { gap?: number })?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n\nlayoutRegistry.register('grid', ({ children, config }) => (\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: `repeat(${\n (config as GridConfig)?.columns ?? 2\n }, 1fr)`,\n gap: (config as GridConfig)?.gap ?? 12,\n }}\n >\n {children}\n </div>\n));\n","import React, { useEffect, useState } from 'react';\nimport {\n LayoutConfig,\n ResponsiveLayout,\n layoutRegistry,\n} from './layoutRegistry';\n\nfunction resolve(layout: LayoutConfig) {\n if (typeof layout === 'string') {\n return { type: layout, config: {} };\n }\n return { type: layout.type, config: layout };\n}\n\nfunction checkIsMobile(breakpoint: number) {\n return typeof window !== 'undefined' && window.innerWidth < breakpoint;\n}\n\nlayoutRegistry.register('responsive', ({ children, config }) => {\n const responsiveConfig = config as ResponsiveLayout;\n const breakpoint = responsiveConfig.breakpoint ?? 768;\n\n // Registered as a real component (invoked via JSX in MultiFieldInput), so\n // hooks are safe here and let the layout react to viewport resizes instead\n // of freezing whatever the width happened to be on first render.\n const [isMobile, setIsMobile] = useState(() => checkIsMobile(breakpoint));\n\n useEffect(() => {\n const handleResize = () => setIsMobile(checkIsMobile(breakpoint));\n handleResize();\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [breakpoint]);\n\n const current = isMobile ? responsiveConfig.mobile : responsiveConfig.desktop;\n if (!current) {\n return <>{children} </>;\n }\n\n const { type, config: childConfig } = resolve(current);\n const Renderer = layoutRegistry.get(type);\n\n if (!Renderer) {\n return <>{children} </>;\n }\n\n return <Renderer config={childConfig}>{children}</Renderer>;\n});\n","import {\n FieldRendererProps,\n FieldTypeKey,\n Properties,\n} from '@dynamic-field-kit/core';\nimport React, { ReactNode, useMemo } from 'react';\nimport { fieldRegistry } from '../fieldRegistry';\n\ninterface Props<T extends FieldTypeKey> {\n type: T;\n value?: unknown;\n onChange?: (value: unknown) => void;\n label?: string;\n options?: Properties[];\n className?: string;\n description?: ReactNode;\n}\n\nconst DynamicInputInner = <T extends FieldTypeKey>({\n type,\n value,\n onChange,\n label,\n options,\n className,\n description,\n}: Props<T>) => {\n // Memoize renderer lookup to avoid unnecessary work on re-renders\n const Renderer = useMemo(\n () => fieldRegistry.get(type) as React.ComponentType<FieldRendererProps>,\n [type]\n );\n\n if (!Renderer) {\n return <div>Unknown field type: {type}</div>;\n }\n\n return React.createElement(Renderer, {\n value,\n onValueChange: onChange,\n label,\n options,\n className,\n description,\n });\n};\n\n// Skip re-render when none of the rendered props actually changed, so\n// unaffected fields don't re-render every time a sibling field's value changes.\n// React.memo erases the generic signature, so restore it via an `unknown`\n// round-trip (plain `as typeof DynamicInputInner` fails dts generation).\nconst DynamicInput = React.memo(\n DynamicInputInner\n) as unknown as typeof DynamicInputInner;\n\nexport default DynamicInput;\n","import {\n fieldRegistry as coreFieldRegistry,\n type FieldRendererProps,\n type FieldTypeMap,\n} from '@dynamic-field-kit/core';\nimport type { ComponentType } from 'react';\n\nexport type ReactFieldRenderer<T = unknown> = ComponentType<\n FieldRendererProps<T>\n>;\n\nexport interface ReactFieldRegistry {\n register<K extends keyof FieldTypeMap>(\n type: K,\n renderer: ReactFieldRenderer<FieldTypeMap[K]>\n ): void;\n get<K extends keyof FieldTypeMap>(\n type: K\n ): ReactFieldRenderer<FieldTypeMap[K]> | undefined;\n}\n\nexport const fieldRegistry = coreFieldRegistry as ReactFieldRegistry;\n","import { FieldDescription, Properties } from '@dynamic-field-kit/core';\nimport React, { useCallback } from 'react';\nimport DynamicInput from './DynamicInput';\nimport FieldGroupInput from './FieldGroupInput';\n\ninterface Props {\n fieldDescription: FieldDescription;\n renderInfos: Properties;\n onValueChangeField: (value: unknown, key: string) => void;\n}\n\nconst FieldInputInner = ({\n fieldDescription,\n renderInfos,\n onValueChangeField,\n}: Props) => {\n const { name, type, label, options, className, description, fields } =\n fieldDescription;\n\n // Stable per-field handler so DynamicInput's memoization isn't defeated\n // by a freshly-allocated closure on every parent render.\n const handleChange = useCallback(\n (v: unknown) => onValueChangeField(v, name),\n [onValueChangeField, name]\n );\n\n if (fields) {\n const items = Array.isArray(renderInfos[name])\n ? (renderInfos[name] as Properties[])\n : [];\n\n return (\n <FieldGroupInput\n fieldDescription={fieldDescription}\n items={items}\n onChange={handleChange}\n />\n );\n }\n\n return (\n <DynamicInput\n type={type}\n label={label}\n value={renderInfos[name]}\n options={options}\n className={className}\n description={description as React.ReactNode}\n onChange={handleChange}\n />\n );\n};\n\n// `renderInfos` covers every field, so the default shallow-prop compare would\n// re-render all fields whenever any one of them changes. Compare only the\n// slice this field actually reads instead.\nconst FieldInput = React.memo(FieldInputInner, (prev, next) => {\n const name = prev.fieldDescription.name;\n return (\n prev.fieldDescription === next.fieldDescription &&\n prev.onValueChangeField === next.onValueChangeField &&\n prev.renderInfos[name] === next.renderInfos[name]\n );\n});\n\nexport default FieldInput;\n","import {\n canAddGroupItem,\n canRemoveGroupItem,\n createGroupItem,\n FieldDescription,\n Properties,\n} from '@dynamic-field-kit/core';\nimport React, { useCallback } from 'react';\nimport MultiFieldInput from './MultiFieldInput';\n\ninterface Props {\n fieldDescription: FieldDescription;\n items: Properties[];\n onChange: (items: Properties[]) => void;\n}\n\nconst FieldGroupInput = ({ fieldDescription, items, onChange }: Props) => {\n const { fields = [], label, addLabel, removeLabel } = fieldDescription;\n\n const handleItemChange = useCallback(\n (index: number, next: Properties) => {\n const nextItems = items.slice();\n nextItems[index] = next;\n onChange(nextItems);\n },\n [items, onChange]\n );\n\n const handleAdd = useCallback(() => {\n if (!canAddGroupItem(fieldDescription, items)) {\n return;\n }\n onChange([...items, createGroupItem(fieldDescription)]);\n }, [fieldDescription, items, onChange]);\n\n const handleRemove = useCallback(\n (index: number) => {\n if (!canRemoveGroupItem(fieldDescription, items)) {\n return;\n }\n onChange(items.filter((_, i) => i !== index));\n },\n [fieldDescription, items, onChange]\n );\n\n return (\n <div className={fieldDescription.className}>\n {label && <div>{label}</div>}\n {items.map((item, index) => (\n <div\n key={index}\n style={{ display: 'flex', alignItems: 'flex-start', gap: 8 }}\n >\n <div style={{ flex: 1 }}>\n <MultiFieldInput\n fieldDescriptions={fields}\n properties={item}\n onChange={(next) => handleItemChange(index, next)}\n />\n </div>\n <button\n type=\"button\"\n onClick={() => handleRemove(index)}\n disabled={!canRemoveGroupItem(fieldDescription, items)}\n >\n {removeLabel ?? 'Remove'}\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n onClick={handleAdd}\n disabled={!canAddGroupItem(fieldDescription, items)}\n >\n {addLabel ?? 'Add'}\n </button>\n </div>\n );\n};\n\nexport default FieldGroupInput;\n","import {\r\n applyComputedValues,\r\n FieldDescription,\r\n Properties,\r\n} from '@dynamic-field-kit/core';\r\nimport React, {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\n\r\nimport { layoutRegistry, LayoutConfig } from '../layout';\r\nimport FieldInput from './FieldInput';\r\n\r\ninterface Props {\r\n fieldDescriptions: FieldDescription[];\r\n properties?: Properties;\r\n onChange?: (data: Properties) => void;\r\n layout?: LayoutConfig;\r\n}\r\n\r\nfunction resolveLayout(layout?: LayoutConfig) {\r\n if (!layout) {\r\n return { type: 'column', config: {} };\r\n }\r\n if (typeof layout === 'string') {\r\n return { type: layout, config: {} };\r\n }\r\n return { type: layout.type, config: layout };\r\n}\r\n\r\nconst MultiFieldInput = ({\r\n fieldDescriptions,\r\n properties,\r\n onChange,\r\n layout,\r\n}: Props) => {\r\n const [data, setData] = useState<Properties>({});\r\n\r\n useEffect(() => {\r\n if (properties) {\r\n setData(applyComputedValues(fieldDescriptions, properties));\r\n }\r\n // Only re-run when `properties` itself changes; recomputing on every\r\n // fieldDescriptions identity change would fight user edits mid-session.\r\n }, [properties]);\r\n\r\n const visibleFields = useMemo(\r\n () =>\r\n fieldDescriptions.filter(\r\n (f) => !f.appearCondition || f.appearCondition(data)\r\n ),\r\n [fieldDescriptions, data]\r\n );\r\n\r\n // Keep the latest data/onChange in refs so handleValueChangeField can stay\r\n // referentially stable (empty deps) without defeating FieldInput's memoization,\r\n // and without calling onChange from inside a setState updater (must stay pure).\r\n const dataRef = useRef(data);\r\n dataRef.current = data;\r\n const onChangeRef = useRef(onChange);\r\n onChangeRef.current = onChange;\r\n const fieldDescriptionsRef = useRef(fieldDescriptions);\r\n fieldDescriptionsRef.current = fieldDescriptions;\r\n\r\n const handleValueChangeField = useCallback((value: unknown, key: string) => {\r\n const next = applyComputedValues(fieldDescriptionsRef.current, {\r\n ...dataRef.current,\r\n [key]: value,\r\n });\r\n dataRef.current = next;\r\n setData(next);\r\n onChangeRef.current?.(next);\r\n }, []);\r\n\r\n const { type, config } = resolveLayout(layout);\r\n\r\n const Layout = layoutRegistry.get(type);\r\n\r\n if (!Layout) {\r\n throw new Error(`Unknown layout: ${type}`);\r\n }\r\n\r\n return (\r\n <Layout config={config}>\r\n {visibleFields.map((f) => (\r\n <FieldInput\r\n key={f.name}\r\n fieldDescription={f}\r\n renderInfos={data}\r\n onValueChangeField={handleValueChangeField}\r\n />\r\n ))}\r\n </Layout>\r\n );\r\n};\r\n\r\nexport default MultiFieldInput;\r\n"],"mappings":"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","names":["jsx","React","jsxs","React","React","useCallback","useCallback","useEffect","useMemo","useState","jsx","useState","useEffect","useMemo","jsx","jsxs","useCallback","jsx","useCallback","React"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-field-kit/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "React renderer for dynamic-field-kit",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,14 +17,26 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@dynamic-field-kit/core": "^1.
|
|
20
|
+
"@dynamic-field-kit/core": "^1.2.0",
|
|
21
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
22
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
21
23
|
},
|
|
22
24
|
"dependencies": {
|
|
23
|
-
"@dynamic-field-kit/core": "^1.
|
|
24
|
-
"react": "^
|
|
25
|
+
"@dynamic-field-kit/core": "^1.2.0",
|
|
26
|
+
"react": "^19.2.4",
|
|
27
|
+
"react-dom": "^19.2.4"
|
|
25
28
|
},
|
|
26
29
|
"devDependencies": {
|
|
27
|
-
"
|
|
30
|
+
"@testing-library/dom": "^10.0.0",
|
|
31
|
+
"@testing-library/jest-dom": "^6.4.0",
|
|
32
|
+
"@testing-library/react": "^16.0.0",
|
|
33
|
+
"@testing-library/user-event": "^14.5.0",
|
|
34
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
35
|
+
"@vitejs/plugin-react": "^4.2.0",
|
|
36
|
+
"jsdom": "^24.0.0",
|
|
37
|
+
"tsup": "^8.0.1",
|
|
38
|
+
"vite": "^5.4.0",
|
|
39
|
+
"vitest": "^1.6.0"
|
|
28
40
|
},
|
|
29
41
|
"exports": {
|
|
30
42
|
".": {
|
|
@@ -36,6 +48,9 @@
|
|
|
36
48
|
"scripts": {
|
|
37
49
|
"build": "npx tsup",
|
|
38
50
|
"clean": "rimraf dist",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
39
54
|
"prepublishOnly": "npm run clean && npm run build",
|
|
40
55
|
"release:patch": "npm version patch && npm publish",
|
|
41
56
|
"release:minor": "npm version minor && npm publish",
|