@dynamic-field-kit/react 1.1.1 → 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 +77 -30
- package/dist/index.d.mts +12 -11
- package/dist/index.d.ts +12 -11
- package/dist/index.js +216 -97
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +232 -122
- package/dist/index.mjs.map +1 -1
- package/package.json +68 -47
package/dist/index.mjs
CHANGED
|
@@ -1,72 +1,3 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
24
|
-
mod
|
|
25
|
-
));
|
|
26
|
-
|
|
27
|
-
// ../core/dist/index.js
|
|
28
|
-
var require_dist = __commonJS({
|
|
29
|
-
"../core/dist/index.js"(exports, module) {
|
|
30
|
-
"use strict";
|
|
31
|
-
var __defProp2 = Object.defineProperty;
|
|
32
|
-
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
33
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
34
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
35
|
-
var __export = (target, all) => {
|
|
36
|
-
for (var name in all)
|
|
37
|
-
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
38
|
-
};
|
|
39
|
-
var __copyProps2 = (to, from, except, desc) => {
|
|
40
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
41
|
-
for (let key of __getOwnPropNames2(from))
|
|
42
|
-
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
43
|
-
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
44
|
-
}
|
|
45
|
-
return to;
|
|
46
|
-
};
|
|
47
|
-
var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
48
|
-
var index_exports = {};
|
|
49
|
-
__export(index_exports, {
|
|
50
|
-
FieldRegistry: () => FieldRegistry,
|
|
51
|
-
fieldRegistry: () => fieldRegistry2
|
|
52
|
-
});
|
|
53
|
-
module.exports = __toCommonJS(index_exports);
|
|
54
|
-
var FieldRegistry = class {
|
|
55
|
-
constructor() {
|
|
56
|
-
this.registry = {};
|
|
57
|
-
}
|
|
58
|
-
// ✅ Type safety API
|
|
59
|
-
register(type, renderer) {
|
|
60
|
-
this.registry[type] = renderer;
|
|
61
|
-
}
|
|
62
|
-
get(type) {
|
|
63
|
-
return this.registry[type];
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
var fieldRegistry2 = new FieldRegistry();
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
1
|
// src/layout/layoutRegistry.ts
|
|
71
2
|
var LayoutRegistry = class {
|
|
72
3
|
constructor() {
|
|
@@ -121,6 +52,7 @@ layoutRegistry.register("grid", ({ children, config }) => /* @__PURE__ */ jsx(
|
|
|
121
52
|
));
|
|
122
53
|
|
|
123
54
|
// src/layout/responsiveLayout.tsx
|
|
55
|
+
import { useEffect, useState } from "react";
|
|
124
56
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
125
57
|
function resolve(layout) {
|
|
126
58
|
if (typeof layout === "string") {
|
|
@@ -128,94 +60,272 @@ function resolve(layout) {
|
|
|
128
60
|
}
|
|
129
61
|
return { type: layout.type, config: layout };
|
|
130
62
|
}
|
|
63
|
+
function checkIsMobile(breakpoint) {
|
|
64
|
+
return typeof window !== "undefined" && window.innerWidth < breakpoint;
|
|
65
|
+
}
|
|
131
66
|
layoutRegistry.register("responsive", ({ children, config }) => {
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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;
|
|
77
|
+
if (!current) {
|
|
78
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
79
|
+
children,
|
|
80
|
+
" "
|
|
81
|
+
] });
|
|
82
|
+
}
|
|
138
83
|
const { type, config: childConfig } = resolve(current);
|
|
139
84
|
const Renderer = layoutRegistry.get(type);
|
|
140
|
-
if (!Renderer)
|
|
141
|
-
children
|
|
142
|
-
|
|
143
|
-
|
|
85
|
+
if (!Renderer) {
|
|
86
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
87
|
+
children,
|
|
88
|
+
" "
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
144
91
|
return /* @__PURE__ */ jsx2(Renderer, { config: childConfig, children });
|
|
145
92
|
});
|
|
146
93
|
|
|
94
|
+
// src/components/DynamicInput.tsx
|
|
95
|
+
import React2, { useMemo } from "react";
|
|
96
|
+
|
|
147
97
|
// src/fieldRegistry.ts
|
|
148
|
-
|
|
149
|
-
|
|
98
|
+
import {
|
|
99
|
+
fieldRegistry as coreFieldRegistry
|
|
100
|
+
} from "@dynamic-field-kit/core";
|
|
101
|
+
var fieldRegistry = coreFieldRegistry;
|
|
150
102
|
|
|
151
103
|
// src/components/DynamicInput.tsx
|
|
152
|
-
import {
|
|
153
|
-
var
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
104
|
+
import { jsxs as jsxs2 } from "react/jsx-runtime";
|
|
105
|
+
var DynamicInputInner = ({
|
|
106
|
+
type,
|
|
107
|
+
value,
|
|
108
|
+
onChange,
|
|
109
|
+
label,
|
|
110
|
+
options,
|
|
111
|
+
className,
|
|
112
|
+
description
|
|
113
|
+
}) => {
|
|
114
|
+
const Renderer = useMemo(
|
|
115
|
+
() => fieldRegistry.get(type),
|
|
116
|
+
[type]
|
|
117
|
+
);
|
|
118
|
+
if (!Renderer) {
|
|
119
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
120
|
+
"Unknown field type: ",
|
|
121
|
+
type
|
|
122
|
+
] });
|
|
123
|
+
}
|
|
124
|
+
return React2.createElement(Renderer, {
|
|
125
|
+
value,
|
|
126
|
+
onValueChange: onChange,
|
|
127
|
+
label,
|
|
128
|
+
options,
|
|
129
|
+
className,
|
|
130
|
+
description
|
|
131
|
+
});
|
|
160
132
|
};
|
|
133
|
+
var DynamicInput = React2.memo(
|
|
134
|
+
DynamicInputInner
|
|
135
|
+
);
|
|
161
136
|
var DynamicInput_default = DynamicInput;
|
|
162
137
|
|
|
163
138
|
// src/components/FieldInput.tsx
|
|
164
|
-
import {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
options,
|
|
174
|
-
className,
|
|
175
|
-
description,
|
|
176
|
-
onChange: (v) => onValueChangeField(v, name)
|
|
177
|
-
}
|
|
178
|
-
);
|
|
179
|
-
};
|
|
180
|
-
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";
|
|
181
148
|
|
|
182
149
|
// src/components/MultiFieldInput.tsx
|
|
183
|
-
import {
|
|
184
|
-
|
|
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";
|
|
185
161
|
function resolveLayout(layout) {
|
|
186
|
-
if (!layout)
|
|
187
|
-
|
|
162
|
+
if (!layout) {
|
|
163
|
+
return { type: "column", config: {} };
|
|
164
|
+
}
|
|
165
|
+
if (typeof layout === "string") {
|
|
166
|
+
return { type: layout, config: {} };
|
|
167
|
+
}
|
|
188
168
|
return { type: layout.type, config: layout };
|
|
189
169
|
}
|
|
190
|
-
var MultiFieldInput = ({
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
170
|
+
var MultiFieldInput = ({
|
|
171
|
+
fieldDescriptions,
|
|
172
|
+
properties,
|
|
173
|
+
onChange,
|
|
174
|
+
layout
|
|
175
|
+
}) => {
|
|
176
|
+
const [data, setData] = useState2({});
|
|
177
|
+
useEffect2(() => {
|
|
178
|
+
if (properties) {
|
|
179
|
+
setData(applyComputedValues(fieldDescriptions, properties));
|
|
180
|
+
}
|
|
194
181
|
}, [properties]);
|
|
195
|
-
const visibleFields =
|
|
196
|
-
() => fieldDescriptions.filter(
|
|
182
|
+
const visibleFields = useMemo2(
|
|
183
|
+
() => fieldDescriptions.filter(
|
|
184
|
+
(f) => !f.appearCondition || f.appearCondition(data)
|
|
185
|
+
),
|
|
197
186
|
[fieldDescriptions, data]
|
|
198
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
|
+
}, []);
|
|
199
203
|
const { type, config } = resolveLayout(layout);
|
|
200
204
|
const Layout = layoutRegistry.get(type);
|
|
201
205
|
if (!Layout) {
|
|
202
206
|
throw new Error(`Unknown layout: ${type}`);
|
|
203
207
|
}
|
|
204
|
-
return /* @__PURE__ */
|
|
208
|
+
return /* @__PURE__ */ jsx3(Layout, { config, children: visibleFields.map((f) => /* @__PURE__ */ jsx3(
|
|
205
209
|
FieldInput_default,
|
|
206
210
|
{
|
|
207
211
|
fieldDescription: f,
|
|
208
212
|
renderInfos: data,
|
|
209
|
-
onValueChangeField:
|
|
210
|
-
const next = { ...data, [key]: value };
|
|
211
|
-
setData(next);
|
|
212
|
-
onChange?.(next);
|
|
213
|
-
}
|
|
213
|
+
onValueChangeField: handleValueChangeField
|
|
214
214
|
},
|
|
215
215
|
f.name
|
|
216
216
|
)) });
|
|
217
217
|
};
|
|
218
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;
|
|
219
329
|
export {
|
|
220
330
|
DynamicInput_default as DynamicInput,
|
|
221
331
|
FieldInput_default as FieldInput,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../core/src/index.ts","../../core/src/FieldRegistry.ts","../src/layout/layoutRegistry.ts","../src/layout/defaultLayouts.tsx","../src/layout/responsiveLayout.tsx","../src/fieldRegistry.ts","../src/components/DynamicInput.tsx","../src/components/FieldInput.tsx","../src/components/MultiFieldInput.tsx"],"sourcesContent":["export * from \"./types\"\r\nexport * from \"./FieldRegistry\"\r\n","import type { FieldRendererProps, FieldTypeMap } from \"./types\"\n\nexport type FieldRenderer<T = any, TResult = unknown> = (\n props: FieldRendererProps<T>\n) => TResult\n\r\nexport class FieldRegistry {\r\n // ❗ INTERNAL = string, not constrain\r\n private registry: Record<string, FieldRenderer<any>> = {}\r\n\r\n // ✅ Type safety API\r\n register<K extends keyof FieldTypeMap>(\r\n type: K,\r\n renderer: FieldRenderer<FieldTypeMap[K]>\r\n ) {\r\n this.registry[type as string] = renderer\r\n }\r\n\r\n get<K extends keyof FieldTypeMap>(\r\n type: K\r\n ): FieldRenderer<FieldTypeMap[K]> | undefined {\r\n return this.registry[type as string]\r\n }\r\n}\r\n\r\nexport const fieldRegistry = new FieldRegistry()\r\n","import React from \"react\"\r\n\r\nexport type LayoutRenderer<C = any> = (props: {\r\n children: React.ReactNode\r\n config?: C\r\n}) => React.ReactElement\r\n\r\nexport class LayoutRegistry {\r\n private layouts = new Map<string, LayoutRenderer>()\r\n\r\n register(type: string, renderer: LayoutRenderer) {\r\n if (this.layouts.has(type)) {\r\n console.warn(`[dynamic-field-kit] Layout \"${type}\" already exists`)\r\n }\r\n this.layouts.set(type, renderer)\r\n }\r\n\r\n get(type: string): LayoutRenderer | undefined {\r\n return this.layouts.get(type)\r\n }\r\n}\r\n\r\nexport const layoutRegistry = new LayoutRegistry()\r\n","import { layoutRegistry } from \"./layoutRegistry\"\r\n\r\nlayoutRegistry.register(\"column\", ({ children, config }) => (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n gap: config?.gap ?? 12,\r\n }}\r\n >\r\n {children}\r\n </div>\r\n))\r\n\r\nlayoutRegistry.register(\"row\", ({ children, config }) => (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n flexDirection: \"row\",\r\n gap: config?.gap ?? 12,\r\n }}\r\n >\r\n {children}\r\n </div>\r\n))\r\n\r\nlayoutRegistry.register(\"grid\", ({ children, config }) => (\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: `repeat(${config?.columns ?? 2}, 1fr)`,\r\n gap: config?.gap ?? 12,\r\n }}\r\n >\r\n {children}\r\n </div>\r\n))","import { layoutRegistry } from \"./layoutRegistry\"\r\nimport { LayoutConfig } from \"../types/layout\"\r\n\r\nfunction resolve(layout: LayoutConfig) {\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\nlayoutRegistry.register(\"responsive\", ({ children, config }) => {\r\n const isMobile =\r\n typeof window !== \"undefined\" && window.innerWidth < 768\r\n\r\n const current = isMobile ? config.mobile : config.desktop\r\n if (!current) return <>{ children } </>\r\n\r\n const { type, config: childConfig } = resolve(current)\r\n const Renderer = layoutRegistry.get(type)\r\n\r\n if (!Renderer) return <>{ children } </>\r\n\r\n return (\r\n <Renderer config= { childConfig } >\r\n { children }\r\n </Renderer>\r\n )\r\n})\r\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 { FieldTypeKey, Properties } from \"@dynamic-field-kit/core\"\nimport { ReactNode } from \"react\"\nimport { fieldRegistry } from \"../fieldRegistry\"\n\r\ninterface Props<T extends FieldTypeKey> {\r\n type: T\r\n value?: any\r\n onChange?: (value: any) => void\r\n label?: string\r\n options?: Properties[]\r\n className?: string\r\n description?: ReactNode\r\n}\r\n\r\n\r\nconst DynamicInput = <T extends FieldTypeKey>({ type, value, onChange, label, options, className, description }: Props<T>) => {\r\n const Renderer = fieldRegistry.get(type)\r\n\r\n\r\n if (!Renderer) return <div>Unknown field type: {type}</div>\r\n\r\n\r\n return <Renderer value={value} onValueChange={onChange} label={label} options={options} className={className} description={description} />\r\n}\r\n\r\n\r\nexport default DynamicInput\n","import { FieldDescription, Properties } from \"@dynamic-field-kit/core\"\r\nimport DynamicInput from \"./DynamicInput\"\r\n\r\ninterface Props {\r\n fieldDescription: FieldDescription\r\n renderInfos: Properties\r\n onValueChangeField: (value: any, key: string) => void\r\n}\r\n\r\n\r\nconst FieldInput = ({ fieldDescription, renderInfos, onValueChangeField }: Props) => {\r\n const { name, type, label, options, className, description } = fieldDescription\r\n\r\n\r\n return (\r\n <DynamicInput\r\n type={type}\r\n label={label}\r\n value={renderInfos[name]}\r\n options={options}\r\n className={className}\r\n description={description}\r\n onChange={(v) => onValueChangeField(v, name)}\r\n />\r\n )\r\n}\r\n\r\n\r\nexport default FieldInput\r\n","import { FieldDescription, Properties } from \"@dynamic-field-kit/core\"\r\nimport { Fragment, useEffect, useMemo, useState } from \"react\"\r\nimport FieldInput from \"./FieldInput\"\r\nimport { layoutRegistry } from \"../layout\"\r\nimport { LayoutConfig } from \"../types/layout\"\r\n\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\n\r\nfunction resolveLayout(layout?: LayoutConfig) {\r\n if (!layout) return { type: \"column\", config: {} }\r\n if (typeof layout === \"string\") return { type: layout, config: {} }\r\n return { type: layout.type, config: layout }\r\n}\r\n\r\n\r\nconst MultiFieldInput = ({ fieldDescriptions, properties, onChange, layout }: Props) => {\r\n const [data, setData] = useState<Properties>({})\r\n\r\n useEffect(() => {\r\n if (properties) setData(properties)\r\n }, [properties])\r\n\r\n const visibleFields = useMemo(\r\n () => fieldDescriptions.filter((f) => !f.appearCondition || f.appearCondition(data)),\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\n\r\nexport default MultiFieldInput\r\n"],"mappings":"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","names":["fieldRegistry","jsx","coreFieldRegistry","jsx","jsxs","jsx","jsx"]}
|
|
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,47 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@dynamic-field-kit/react",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "React renderer for dynamic-field-kit",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"sideEffects": [
|
|
10
|
+
"./dist/index.js",
|
|
11
|
+
"./dist/index.mjs",
|
|
12
|
+
"./dist/index.d.ts",
|
|
13
|
+
"./src/layout/defaultLayouts.tsx",
|
|
14
|
+
"./src/layout/responsiveLayout.tsx"
|
|
15
|
+
],
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"peerDependencies": {
|
|
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"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@dynamic-field-kit/core": "^1.2.0",
|
|
26
|
+
"react": "^19.2.4",
|
|
27
|
+
"react-dom": "^19.2.4"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
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"
|
|
40
|
+
},
|
|
41
|
+
"exports": {
|
|
42
|
+
".": {
|
|
43
|
+
"types": "./dist/index.d.ts",
|
|
44
|
+
"import": "./dist/index.mjs",
|
|
45
|
+
"require": "./dist/index.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "npx tsup",
|
|
50
|
+
"clean": "rimraf dist",
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:watch": "vitest",
|
|
53
|
+
"test:coverage": "vitest run --coverage",
|
|
54
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
55
|
+
"release:patch": "npm version patch && npm publish",
|
|
56
|
+
"release:minor": "npm version minor && npm publish",
|
|
57
|
+
"release:major": "npm version major && npm publish"
|
|
58
|
+
},
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "git+https://github.com/vannt-dev/dynamic-field-kit.git"
|
|
62
|
+
},
|
|
63
|
+
"keywords": [
|
|
64
|
+
"dynamic-field",
|
|
65
|
+
"dynamic-field-kit",
|
|
66
|
+
"dynamic-field-kit/react"
|
|
67
|
+
]
|
|
68
|
+
}
|