@dynamic-field-kit/react 1.2.0 → 1.4.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/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,39 @@ function resolve(layout) {
59
60
  }
60
61
  return { type: layout.type, config: layout };
61
62
  }
63
+ function checkIsMobile(breakpoint) {
64
+ if (typeof window === "undefined") {
65
+ return false;
66
+ }
67
+ if (typeof window.matchMedia === "function") {
68
+ return window.matchMedia(`(max-width: ${breakpoint - 1}px)`).matches;
69
+ }
70
+ return window.innerWidth < breakpoint;
71
+ }
62
72
  layoutRegistry.register("responsive", ({ children, config }) => {
63
- const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
64
- const current = isMobile ? config.mobile : config.desktop;
73
+ const responsiveConfig = config;
74
+ const breakpoint = responsiveConfig.breakpoint ?? 768;
75
+ const [isMobile, setIsMobile] = useState(() => checkIsMobile(breakpoint));
76
+ useEffect(() => {
77
+ if (typeof window === "undefined") {
78
+ return;
79
+ }
80
+ if (typeof window.matchMedia !== "function") {
81
+ const handleResize = () => setIsMobile(checkIsMobile(breakpoint));
82
+ window.addEventListener("resize", handleResize);
83
+ return () => window.removeEventListener("resize", handleResize);
84
+ }
85
+ const mediaQuery = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
86
+ const handleChange = (e) => setIsMobile(e.matches);
87
+ setIsMobile(mediaQuery.matches);
88
+ if (mediaQuery.addEventListener) {
89
+ mediaQuery.addEventListener("change", handleChange);
90
+ return () => mediaQuery.removeEventListener("change", handleChange);
91
+ }
92
+ mediaQuery.addListener(handleChange);
93
+ return () => mediaQuery.removeListener(handleChange);
94
+ }, [breakpoint]);
95
+ const current = isMobile ? responsiveConfig.mobile : responsiveConfig.desktop;
65
96
  if (!current) {
66
97
  return /* @__PURE__ */ jsxs(Fragment, { children: [
67
98
  children,
@@ -80,7 +111,10 @@ layoutRegistry.register("responsive", ({ children, config }) => {
80
111
  });
81
112
 
82
113
  // src/components/DynamicInput.tsx
83
- import React, { useMemo } from "react";
114
+ import React3, { useMemo } from "react";
115
+
116
+ // src/FieldRegistryContext.tsx
117
+ import { createContext, useContext } from "react";
84
118
 
85
119
  // src/fieldRegistry.ts
86
120
  import {
@@ -88,61 +122,106 @@ import {
88
122
  } from "@dynamic-field-kit/core";
89
123
  var fieldRegistry = coreFieldRegistry;
90
124
 
125
+ // src/FieldRegistryContext.tsx
126
+ import { jsx as jsx3 } from "react/jsx-runtime";
127
+ var FieldRegistryContext = createContext(fieldRegistry);
128
+ var FieldRegistryProvider = ({
129
+ registry,
130
+ children
131
+ }) => /* @__PURE__ */ jsx3(FieldRegistryContext.Provider, { value: registry, children });
132
+ function useFieldRegistry() {
133
+ return useContext(FieldRegistryContext);
134
+ }
135
+
91
136
  // src/components/DynamicInput.tsx
92
137
  import { jsxs as jsxs2 } from "react/jsx-runtime";
93
- var DynamicInput = ({
138
+ var DynamicInputInner = ({
94
139
  type,
95
140
  value,
96
141
  onChange,
142
+ onBlur,
97
143
  label,
98
144
  options,
99
145
  className,
100
- description
146
+ description,
147
+ disabled,
148
+ readOnly,
149
+ required,
150
+ touched,
151
+ dirty,
152
+ error,
153
+ id,
154
+ ariaInvalid,
155
+ ariaDescribedBy,
156
+ ariaRequired,
157
+ extraProps
101
158
  }) => {
102
- const Renderer = useMemo(() => fieldRegistry.get(type), [type]);
159
+ const registry = useFieldRegistry();
160
+ const Renderer = useMemo(
161
+ () => registry.get(type),
162
+ [registry, type]
163
+ );
103
164
  if (!Renderer) {
104
165
  return /* @__PURE__ */ jsxs2("div", { children: [
105
166
  "Unknown field type: ",
106
167
  type
107
168
  ] });
108
169
  }
109
- const RendererEl = Renderer;
110
- return React.createElement(RendererEl, {
170
+ return React3.createElement(Renderer, {
171
+ ...extraProps,
111
172
  value,
112
173
  onValueChange: onChange,
174
+ onBlur,
113
175
  label,
114
176
  options,
115
177
  className,
116
- description
178
+ description,
179
+ disabled,
180
+ readOnly,
181
+ required,
182
+ touched,
183
+ dirty,
184
+ error,
185
+ id,
186
+ ariaInvalid,
187
+ ariaDescribedBy,
188
+ ariaRequired
117
189
  });
118
190
  };
191
+ var DynamicInput = React3.memo(
192
+ DynamicInputInner
193
+ );
119
194
  var DynamicInput_default = DynamicInput;
120
195
 
121
196
  // src/components/FieldInput.tsx
122
- import { jsx as jsx3 } from "react/jsx-runtime";
123
- var FieldInput = ({
124
- fieldDescription,
125
- renderInfos,
126
- onValueChangeField
127
- }) => {
128
- const { name, type, label, options, className, description } = fieldDescription;
129
- return /* @__PURE__ */ jsx3(
130
- DynamicInput_default,
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;
197
+ import {
198
+ resolveDisabled,
199
+ resolveOptions,
200
+ resolveReadOnly,
201
+ validateField
202
+ } from "@dynamic-field-kit/core";
203
+ import React6, { useCallback as useCallback3 } from "react";
204
+
205
+ // src/components/FieldGroupInput.tsx
206
+ import {
207
+ canAddGroupItem,
208
+ canRemoveGroupItem,
209
+ createGroupItem
210
+ } from "@dynamic-field-kit/core";
211
+ import { useCallback as useCallback2 } from "react";
143
212
 
144
213
  // src/components/MultiFieldInput.tsx
145
- import { useEffect, useMemo as useMemo2, useState } from "react";
214
+ import {
215
+ applyComputedValues,
216
+ validateFields
217
+ } from "@dynamic-field-kit/core";
218
+ import {
219
+ useCallback,
220
+ useEffect as useEffect2,
221
+ useMemo as useMemo2,
222
+ useRef,
223
+ useState as useState2
224
+ } from "react";
146
225
  import { jsx as jsx4 } from "react/jsx-runtime";
147
226
  function resolveLayout(layout) {
148
227
  if (!layout) {
@@ -157,20 +236,56 @@ var MultiFieldInput = ({
157
236
  fieldDescriptions,
158
237
  properties,
159
238
  onChange,
160
- layout
239
+ layout,
240
+ rootData,
241
+ onValidityChange
161
242
  }) => {
162
- const [data, setData] = useState({});
163
- useEffect(() => {
243
+ const [data, setData] = useState2({});
244
+ const [touchedFields, setTouchedFields] = useState2(
245
+ {}
246
+ );
247
+ const initialPropertiesRef = useRef(properties ?? {});
248
+ useEffect2(() => {
164
249
  if (properties) {
165
- setData(properties);
250
+ setData(applyComputedValues(fieldDescriptions, properties, rootData));
166
251
  }
167
252
  }, [properties]);
253
+ const effectiveRoot = rootData ?? data;
168
254
  const visibleFields = useMemo2(
169
255
  () => fieldDescriptions.filter(
170
- (f) => !f.appearCondition || f.appearCondition(data)
256
+ (f) => !f.appearCondition || f.appearCondition(data, effectiveRoot)
171
257
  ),
172
- [fieldDescriptions, data]
258
+ [fieldDescriptions, data, effectiveRoot]
173
259
  );
260
+ const dataRef = useRef(data);
261
+ dataRef.current = data;
262
+ const onChangeRef = useRef(onChange);
263
+ onChangeRef.current = onChange;
264
+ const fieldDescriptionsRef = useRef(fieldDescriptions);
265
+ fieldDescriptionsRef.current = fieldDescriptions;
266
+ const rootDataRef = useRef(rootData);
267
+ rootDataRef.current = rootData;
268
+ const onValidityChangeRef = useRef(onValidityChange);
269
+ onValidityChangeRef.current = onValidityChange;
270
+ useEffect2(() => {
271
+ onValidityChangeRef.current?.(
272
+ validateFields(fieldDescriptions, data, rootData)
273
+ );
274
+ }, [data, fieldDescriptions, rootData]);
275
+ const handleValueChangeField = useCallback((value, key) => {
276
+ const merged = { ...dataRef.current, [key]: value };
277
+ const next = applyComputedValues(
278
+ fieldDescriptionsRef.current,
279
+ merged,
280
+ rootDataRef.current
281
+ );
282
+ dataRef.current = next;
283
+ setData(next);
284
+ onChangeRef.current?.(next);
285
+ }, []);
286
+ const handleBlurField = useCallback((key) => {
287
+ setTouchedFields((prev) => prev[key] ? prev : { ...prev, [key]: true });
288
+ }, []);
174
289
  const { type, config } = resolveLayout(layout);
175
290
  const Layout = layoutRegistry.get(type);
176
291
  if (!Layout) {
@@ -181,21 +296,207 @@ var MultiFieldInput = ({
181
296
  {
182
297
  fieldDescription: f,
183
298
  renderInfos: data,
184
- onValueChangeField: (value, key) => {
185
- const next = { ...data, [key]: value };
186
- setData(next);
187
- onChange?.(next);
188
- }
299
+ rootData: effectiveRoot,
300
+ touched: Boolean(touchedFields[f.name]),
301
+ dirty: data[f.name] !== initialPropertiesRef.current[f.name],
302
+ onBlurField: handleBlurField,
303
+ onValueChangeField: handleValueChangeField
189
304
  },
190
305
  f.name
191
306
  )) });
192
307
  };
193
308
  var MultiFieldInput_default = MultiFieldInput;
309
+
310
+ // src/components/FieldGroupInput.tsx
311
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
312
+ var FieldGroupInput = ({
313
+ fieldDescription,
314
+ items,
315
+ rootData,
316
+ onChange
317
+ }) => {
318
+ const {
319
+ fields = [],
320
+ label,
321
+ addLabel,
322
+ removeLabel,
323
+ keyField
324
+ } = fieldDescription;
325
+ const itemKey = (item, index) => keyField ? item[keyField] ?? index : index;
326
+ const addText = addLabel ?? "Add";
327
+ const removeText = removeLabel ?? "Remove";
328
+ const groupName = label ?? fieldDescription.name;
329
+ const handleItemChange = useCallback2(
330
+ (index, next) => {
331
+ const nextItems = items.slice();
332
+ nextItems[index] = next;
333
+ onChange(nextItems);
334
+ },
335
+ [items, onChange]
336
+ );
337
+ const handleAdd = useCallback2(() => {
338
+ if (!canAddGroupItem(fieldDescription, items)) {
339
+ return;
340
+ }
341
+ onChange([...items, createGroupItem(fieldDescription)]);
342
+ }, [fieldDescription, items, onChange]);
343
+ const handleRemove = useCallback2(
344
+ (index) => {
345
+ if (!canRemoveGroupItem(fieldDescription, items)) {
346
+ return;
347
+ }
348
+ onChange(items.filter((_, i) => i !== index));
349
+ },
350
+ [fieldDescription, items, onChange]
351
+ );
352
+ return /* @__PURE__ */ jsxs3("div", { className: fieldDescription.className, children: [
353
+ label && /* @__PURE__ */ jsx5("div", { children: label }),
354
+ items.map((item, index) => /* @__PURE__ */ jsxs3(
355
+ "div",
356
+ {
357
+ style: { display: "flex", alignItems: "flex-start", gap: 8 },
358
+ children: [
359
+ /* @__PURE__ */ jsx5("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsx5(
360
+ MultiFieldInput_default,
361
+ {
362
+ fieldDescriptions: fields,
363
+ properties: item,
364
+ rootData,
365
+ onChange: (next) => handleItemChange(index, next)
366
+ }
367
+ ) }),
368
+ /* @__PURE__ */ jsx5(
369
+ "button",
370
+ {
371
+ type: "button",
372
+ "aria-label": `${removeText} ${groupName} ${index + 1}`,
373
+ onClick: () => handleRemove(index),
374
+ disabled: !canRemoveGroupItem(fieldDescription, items),
375
+ children: removeText
376
+ }
377
+ )
378
+ ]
379
+ },
380
+ itemKey(item, index)
381
+ )),
382
+ /* @__PURE__ */ jsx5(
383
+ "button",
384
+ {
385
+ type: "button",
386
+ "aria-label": `${addText} ${groupName}`,
387
+ onClick: handleAdd,
388
+ disabled: !canAddGroupItem(fieldDescription, items),
389
+ children: addText
390
+ }
391
+ )
392
+ ] });
393
+ };
394
+ var FieldGroupInput_default = FieldGroupInput;
395
+
396
+ // src/components/FieldInput.tsx
397
+ import { jsx as jsx6 } from "react/jsx-runtime";
398
+ var FieldInputInner = ({
399
+ fieldDescription,
400
+ renderInfos,
401
+ rootData,
402
+ touched,
403
+ dirty,
404
+ onBlurField,
405
+ onValueChangeField
406
+ }) => {
407
+ const { name, type, label, className, description, props, fields, required } = fieldDescription;
408
+ const handleChange = useCallback3(
409
+ (v) => onValueChangeField(v, name),
410
+ [onValueChangeField, name]
411
+ );
412
+ const handleBlur = useCallback3(
413
+ () => onBlurField?.(name),
414
+ [onBlurField, name]
415
+ );
416
+ if (fields) {
417
+ const items = Array.isArray(renderInfos[name]) ? renderInfos[name] : [];
418
+ return /* @__PURE__ */ jsx6(
419
+ FieldGroupInput_default,
420
+ {
421
+ fieldDescription,
422
+ items,
423
+ rootData,
424
+ onChange: handleChange
425
+ }
426
+ );
427
+ }
428
+ const effectiveDisabled = resolveDisabled(
429
+ fieldDescription,
430
+ renderInfos,
431
+ rootData
432
+ );
433
+ const readOnly = resolveReadOnly(fieldDescription, renderInfos, rootData);
434
+ const resolvedOptionsList = resolveOptions(
435
+ fieldDescription,
436
+ renderInfos,
437
+ rootData
438
+ );
439
+ const errors = effectiveDisabled ? [] : validateField(fieldDescription, renderInfos[name], renderInfos, rootData);
440
+ const error = errors.length > 0 ? errors : void 0;
441
+ const fieldId = `dfk-field-${name}`;
442
+ return /* @__PURE__ */ jsx6(
443
+ DynamicInput_default,
444
+ {
445
+ id: fieldId,
446
+ type,
447
+ label,
448
+ value: renderInfos[name],
449
+ options: resolvedOptionsList,
450
+ className,
451
+ description,
452
+ disabled: effectiveDisabled,
453
+ readOnly,
454
+ required,
455
+ touched,
456
+ dirty,
457
+ error,
458
+ ariaInvalid: Boolean(error),
459
+ ariaRequired: Boolean(required),
460
+ extraProps: props,
461
+ onChange: handleChange,
462
+ onBlur: handleBlur
463
+ }
464
+ );
465
+ };
466
+ var FieldInput = React6.memo(FieldInputInner, (prev, next) => {
467
+ const name = prev.fieldDescription.name;
468
+ return prev.fieldDescription === next.fieldDescription && prev.onValueChangeField === next.onValueChangeField && prev.onBlurField === next.onBlurField && prev.rootData === next.rootData && prev.touched === next.touched && prev.dirty === next.dirty && prev.renderInfos[name] === next.renderInfos[name];
469
+ });
470
+ var FieldInput_default = FieldInput;
471
+
472
+ // src/index.ts
473
+ import { FieldRegistry } from "@dynamic-field-kit/core";
474
+ import {
475
+ validateField as validateField2,
476
+ validateFieldAsync,
477
+ validateFields as validateFields2,
478
+ validateFieldsAsync,
479
+ resolveDisabled as resolveDisabled2,
480
+ resolveReadOnly as resolveReadOnly2,
481
+ resolveOptions as resolveOptions2,
482
+ validators
483
+ } from "@dynamic-field-kit/core";
194
484
  export {
195
485
  DynamicInput_default as DynamicInput,
196
486
  FieldInput_default as FieldInput,
487
+ FieldRegistry,
488
+ FieldRegistryProvider,
197
489
  MultiFieldInput_default as MultiFieldInput,
198
490
  fieldRegistry,
199
- layoutRegistry
491
+ layoutRegistry,
492
+ resolveDisabled2 as resolveDisabled,
493
+ resolveOptions2 as resolveOptions,
494
+ resolveReadOnly2 as resolveReadOnly,
495
+ useFieldRegistry,
496
+ validateField2 as validateField,
497
+ validateFieldAsync,
498
+ validateFields2 as validateFields,
499
+ validateFieldsAsync,
500
+ validators
200
501
  };
201
502
  //# sourceMappingURL=index.mjs.map
@@ -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":";AAOO,IAAM,iBAAN,MAAqB;AAAA,EAArB;AACL,SAAQ,UAAU,oBAAI,IAA4B;AAAA;AAAA,EAElD,SAAS,MAAc,UAA0B;AAC/C,QAAI,KAAK,QAAQ,IAAI,IAAI,GAAG;AAC1B,cAAQ,KAAK,+BAA+B,IAAI,kBAAkB;AAAA,IACpE;AACA,SAAK,QAAQ,IAAI,MAAM,QAAQ;AAAA,EACjC;AAAA,EAEA,IAAI,MAA0C;AAC5C,WAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC9B;AACF;AAEO,IAAM,iBAAiB,IAAI,eAAe;;;ACnB/C;AADF,eAAe,SAAS,UAAU,CAAC,EAAE,UAAU,OAAO,MACpD;AAAA,EAAC;AAAA;AAAA,IACC,OAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,KAAK,QAAQ,OAAO;AAAA,IACtB;AAAA,IAEC;AAAA;AACH,CACD;AAED,eAAe,SAAS,OAAO,CAAC,EAAE,UAAU,OAAO,MACjD;AAAA,EAAC;AAAA;AAAA,IACC,OAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,KAAK,QAAQ,OAAO;AAAA,IACtB;AAAA,IAEC;AAAA;AACH,CACD;AAED,eAAe,SAAS,QAAQ,CAAC,EAAE,UAAU,OAAO,MAClD;AAAA,EAAC;AAAA;AAAA,IACC,OAAO;AAAA,MACL,SAAS;AAAA,MACT,qBAAqB,UAAU,QAAQ,WAAW,CAAC;AAAA,MACnD,KAAK,QAAQ,OAAO;AAAA,IACtB;AAAA,IAEC;AAAA;AACH,CACD;;;ACpBU,mBAUF,OAAAA,MAVE;AAZX,SAAS,QAAQ,QAAsB;AACrC,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,EAAE,MAAM,QAAQ,QAAQ,CAAC,EAAE;AAAA,EACpC;AACA,SAAO,EAAE,MAAM,OAAO,MAAM,QAAQ,OAAO;AAC7C;AAEA,eAAe,SAAS,cAAc,CAAC,EAAE,UAAU,OAAO,MAAM;AAC9D,QAAM,WAAW,OAAO,WAAW,eAAe,OAAO,aAAa;AAEtE,QAAM,UAAU,WAAW,OAAO,SAAS,OAAO;AAClD,MAAI,CAAC,SAAS;AACZ,WAAO,iCAAG;AAAA;AAAA,MAAS;AAAA,OAAC;AAAA,EACtB;AAEA,QAAM,EAAE,MAAM,QAAQ,YAAY,IAAI,QAAQ,OAAO;AACrD,QAAM,WAAW,eAAe,IAAI,IAAI;AAExC,MAAI,CAAC,UAAU;AACb,WAAO,iCAAG;AAAA;AAAA,MAAS;AAAA,OAAC;AAAA,EACtB;AAEA,SAAO,gBAAAA,KAAC,YAAS,QAAQ,aAAc,UAAS;AAClD,CAAC;;;AC1BD,OAAO,SAAoB,eAAe;;;ACD1C;AAAA,EACE,iBAAiB;AAAA,OAGZ;AAeA,IAAM,gBAAgB;;;ADQlB,iBAAAC,aAAA;AAbX,IAAM,eAAe,CAAyB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAgB;AAEd,QAAM,WAAW,QAAQ,MAAM,cAAc,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC;AAE9D,MAAI,CAAC,UAAU;AACb,WAAO,gBAAAA,MAAC,SAAI;AAAA;AAAA,MAAqB;AAAA,OAAK;AAAA,EACxC;AAGA,QAAM,aAAa;AACnB,SAAO,MAAM,cAAc,YAAY;AAAA,IACrC;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,IAAO,uBAAQ;;;AExBX,gBAAAC,YAAA;AATJ,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,MAAa;AACX,QAAM,EAAE,MAAM,MAAM,OAAO,SAAS,WAAW,YAAY,IACzD;AAEF,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,YAAY,IAAI;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,CAAC,MAAM,mBAAmB,GAAG,IAAI;AAAA;AAAA,EAC7C;AAEJ;AAEA,IAAO,qBAAQ;;;AC7Bf,SAAgB,WAAW,WAAAC,UAAS,gBAAgB;AAwD5C,gBAAAC,YAAA;AA3CR,SAAS,cAAc,QAAuB;AAC5C,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,MAAM,UAAU,QAAQ,CAAC,EAAE;AAAA,EACtC;AACA,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,EAAE,MAAM,QAAQ,QAAQ,CAAC,EAAE;AAAA,EACpC;AACA,SAAO,EAAE,MAAM,OAAO,MAAM,QAAQ,OAAO;AAC7C;AAEA,IAAM,kBAAkB,CAAC;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAa;AACX,QAAM,CAAC,MAAM,OAAO,IAAI,SAAqB,CAAC,CAAC;AAE/C,YAAU,MAAM;AACd,QAAI,YAAY;AACd,cAAQ,UAAU;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,gBAAgBC;AAAA,IACpB,MACE,kBAAkB;AAAA,MAChB,CAAC,MAAM,CAAC,EAAE,mBAAmB,EAAE,gBAAgB,IAAI;AAAA,IACrD;AAAA,IACF,CAAC,mBAAmB,IAAI;AAAA,EAC1B;AAEA,QAAM,EAAE,MAAM,OAAO,IAAI,cAAc,MAAM;AAE7C,QAAM,SAAS,eAAe,IAAI,IAAI;AAEtC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,mBAAmB,IAAI,EAAE;AAAA,EAC3C;AAEA,SACE,gBAAAD,KAAC,UAAO,QACL,wBAAc,IAAI,CAAC,MAClB,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEC,kBAAkB;AAAA,MAClB,aAAa;AAAA,MACb,oBAAoB,CAAC,OAAO,QAAQ;AAClC,cAAM,OAAO,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM;AACrC,gBAAQ,IAAI;AACZ,mBAAW,IAAI;AAAA,MACjB;AAAA;AAAA,IAPK,EAAE;AAAA,EAQT,CACD,GACH;AAEJ;AAEA,IAAO,0BAAQ;","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/FieldRegistryContext.tsx","../src/fieldRegistry.ts","../src/components/FieldInput.tsx","../src/components/FieldGroupInput.tsx","../src/components/MultiFieldInput.tsx","../src/index.ts"],"sourcesContent":["import React from 'react';\n\n// Single source of truth for layout config shapes.\nexport type {\n BaseLayout,\n ResponsiveLayout,\n LayoutConfig,\n} from '@dynamic-field-kit/core';\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 if (typeof window === 'undefined') {\n return false;\n }\n if (typeof window.matchMedia === 'function') {\n return window.matchMedia(`(max-width: ${breakpoint - 1}px)`).matches;\n }\n return 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 if (typeof window === 'undefined') {\n return;\n }\n if (typeof window.matchMedia !== 'function') {\n const handleResize = () => setIsMobile(checkIsMobile(breakpoint));\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }\n const mediaQuery = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n const handleChange = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n setIsMobile(mediaQuery.matches);\n\n if (mediaQuery.addEventListener) {\n mediaQuery.addEventListener('change', handleChange);\n return () => mediaQuery.removeEventListener('change', handleChange);\n }\n mediaQuery.addListener(handleChange);\n return () => mediaQuery.removeListener(handleChange);\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 { useFieldRegistry } from '../FieldRegistryContext';\n\ninterface Props<T extends FieldTypeKey> {\n type: T;\n value?: unknown;\n onChange?: (value: unknown) => void;\n onBlur?: () => void;\n label?: string;\n options?: Properties[];\n className?: string;\n description?: ReactNode;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n touched?: boolean;\n dirty?: boolean;\n error?: string | string[];\n id?: string;\n ariaInvalid?: boolean;\n ariaDescribedBy?: string;\n ariaRequired?: boolean;\n /** Extra, framework-agnostic props forwarded verbatim to the renderer. */\n extraProps?: Properties;\n}\n\nconst DynamicInputInner = <T extends FieldTypeKey>({\n type,\n value,\n onChange,\n onBlur,\n label,\n options,\n className,\n description,\n disabled,\n readOnly,\n required,\n touched,\n dirty,\n error,\n id,\n ariaInvalid,\n ariaDescribedBy,\n ariaRequired,\n extraProps,\n}: Props<T>) => {\n const registry = useFieldRegistry();\n\n // Memoize renderer lookup to avoid unnecessary work on re-renders\n const Renderer = useMemo(\n () => registry.get(type) as React.ComponentType<FieldRendererProps>,\n [registry, type]\n );\n\n if (!Renderer) {\n return <div>Unknown field type: {type}</div>;\n }\n\n return React.createElement(Renderer, {\n ...extraProps,\n value,\n onValueChange: onChange,\n onBlur,\n label,\n options,\n className,\n description,\n disabled,\n readOnly,\n required,\n touched,\n dirty,\n error,\n id,\n ariaInvalid,\n ariaDescribedBy,\n ariaRequired,\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 React, { createContext, useContext } from 'react';\nimport { fieldRegistry, type ReactFieldRegistry } from './fieldRegistry';\n\n// Defaults to the process-wide singleton so existing code that never wraps a\n// provider keeps working. Wrap a subtree in <FieldRegistryProvider> to give it\n// an isolated set of renderers (e.g. two design systems in one app).\nconst FieldRegistryContext = createContext<ReactFieldRegistry>(fieldRegistry);\n\nexport interface FieldRegistryProviderProps {\n registry: ReactFieldRegistry;\n children: React.ReactNode;\n}\n\nexport const FieldRegistryProvider = ({\n registry,\n children,\n}: FieldRegistryProviderProps): React.ReactElement => (\n <FieldRegistryContext.Provider value={registry}>\n {children}\n </FieldRegistryContext.Provider>\n);\n\n/** The registry for the nearest provider, or the global singleton. */\nexport function useFieldRegistry(): ReactFieldRegistry {\n return useContext(FieldRegistryContext);\n}\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 {\n resolveDisabled,\n resolveOptions,\n resolveReadOnly,\n validateField,\n FieldDescription,\n Properties,\n} 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 rootData?: Properties;\n touched?: boolean;\n dirty?: boolean;\n onBlurField?: (key: string) => void;\n onValueChangeField: (value: unknown, key: string) => void;\n}\n\nconst FieldInputInner = ({\n fieldDescription,\n renderInfos,\n rootData,\n touched,\n dirty,\n onBlurField,\n onValueChangeField,\n}: Props) => {\n const { name, type, label, className, description, props, fields, required } =\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 const handleBlur = useCallback(\n () => onBlurField?.(name),\n [onBlurField, 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 rootData={rootData}\n onChange={handleChange}\n />\n );\n }\n\n const effectiveDisabled = resolveDisabled(\n fieldDescription,\n renderInfos,\n rootData\n );\n const readOnly = resolveReadOnly(fieldDescription, renderInfos, rootData);\n const resolvedOptionsList = resolveOptions(\n fieldDescription,\n renderInfos,\n rootData\n );\n const errors = effectiveDisabled\n ? []\n : validateField(fieldDescription, renderInfos[name], renderInfos, rootData);\n const error = errors.length > 0 ? errors : undefined;\n const fieldId = `dfk-field-${name}`;\n\n return (\n <DynamicInput\n id={fieldId}\n type={type}\n label={label}\n value={renderInfos[name]}\n options={resolvedOptionsList}\n className={className}\n description={description as React.ReactNode}\n disabled={effectiveDisabled}\n readOnly={readOnly}\n required={required}\n touched={touched}\n dirty={dirty}\n error={error}\n ariaInvalid={Boolean(error)}\n ariaRequired={Boolean(required)}\n extraProps={props}\n onChange={handleChange}\n onBlur={handleBlur}\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.onBlurField === next.onBlurField &&\n prev.rootData === next.rootData &&\n prev.touched === next.touched &&\n prev.dirty === next.dirty &&\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 rootData?: Properties;\n onChange: (items: Properties[]) => void;\n}\n\nconst FieldGroupInput = ({\n fieldDescription,\n items,\n rootData,\n onChange,\n}: Props) => {\n const {\n fields = [],\n label,\n addLabel,\n removeLabel,\n keyField,\n } = fieldDescription;\n\n const itemKey = (item: Properties, index: number): string | number =>\n keyField ? (item[keyField] as string | number) ?? index : index;\n\n const addText = addLabel ?? 'Add';\n const removeText = removeLabel ?? 'Remove';\n const groupName = label ?? fieldDescription.name;\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={itemKey(item, 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 rootData={rootData}\n onChange={(next) => handleItemChange(index, next)}\n />\n </div>\n <button\n type=\"button\"\n aria-label={`${removeText} ${groupName} ${index + 1}`}\n onClick={() => handleRemove(index)}\n disabled={!canRemoveGroupItem(fieldDescription, items)}\n >\n {removeText}\n </button>\n </div>\n ))}\n <button\n type=\"button\"\n aria-label={`${addText} ${groupName}`}\n onClick={handleAdd}\n disabled={!canAddGroupItem(fieldDescription, items)}\n >\n {addText}\n </button>\n </div>\n );\n};\n\nexport default FieldGroupInput;\n","import {\r\n applyComputedValues,\r\n validateFields,\r\n FieldDescription,\r\n Properties,\r\n type ValidationResult,\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 * Top-level form data, threaded down through repeatable groups so a nested\r\n * field's `appearCondition`/`computeValue` can read the root form. Omitted at\r\n * the top level, where the form's own data is the root.\r\n */\r\n rootData?: Properties;\r\n /**\r\n * Called with the recursive validation result ({ valid, errors }) on every\r\n * change. On the top-level component this covers the whole form (groups\r\n * included).\r\n */\r\n onValidityChange?: (result: ValidationResult) => void;\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 rootData,\r\n onValidityChange,\r\n}: Props) => {\r\n const [data, setData] = useState<Properties>({});\r\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>(\r\n {}\r\n );\r\n const initialPropertiesRef = useRef<Properties>(properties ?? {});\r\n\r\n useEffect(() => {\r\n if (properties) {\r\n setData(applyComputedValues(fieldDescriptions, properties, rootData));\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 // The root data seen by this level: the prop when nested in a group, else\r\n // this form's own data at the top level.\r\n const effectiveRoot = rootData ?? data;\r\n\r\n const visibleFields = useMemo(\r\n () =>\r\n fieldDescriptions.filter(\r\n (f) => !f.appearCondition || f.appearCondition(data, effectiveRoot)\r\n ),\r\n [fieldDescriptions, data, effectiveRoot]\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 const rootDataRef = useRef(rootData);\r\n rootDataRef.current = rootData;\r\n const onValidityChangeRef = useRef(onValidityChange);\r\n onValidityChangeRef.current = onValidityChange;\r\n\r\n useEffect(() => {\r\n onValidityChangeRef.current?.(\r\n validateFields(fieldDescriptions, data, rootData)\r\n );\r\n }, [data, fieldDescriptions, rootData]);\r\n\r\n const handleValueChangeField = useCallback((value: unknown, key: string) => {\r\n const merged = { ...dataRef.current, [key]: value };\r\n const next = applyComputedValues(\r\n fieldDescriptionsRef.current,\r\n merged,\r\n rootDataRef.current\r\n );\r\n dataRef.current = next;\r\n setData(next);\r\n onChangeRef.current?.(next);\r\n }, []);\r\n\r\n const handleBlurField = useCallback((key: string) => {\r\n setTouchedFields((prev) => (prev[key] ? prev : { ...prev, [key]: true }));\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 rootData={effectiveRoot}\r\n touched={Boolean(touchedFields[f.name])}\r\n dirty={data[f.name] !== initialPropertiesRef.current[f.name]}\r\n onBlurField={handleBlurField}\r\n onValueChangeField={handleValueChangeField}\r\n />\r\n ))}\r\n </Layout>\r\n );\r\n};\r\n\r\nexport default MultiFieldInput;\r\n","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';\nexport {\n FieldRegistryProvider,\n useFieldRegistry,\n type FieldRegistryProviderProps,\n} from './FieldRegistryContext';\nexport { FieldRegistry } from '@dynamic-field-kit/core';\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';\nexport {\n validateField,\n validateFieldAsync,\n validateFields,\n validateFieldsAsync,\n resolveDisabled,\n resolveReadOnly,\n resolveOptions,\n validators,\n type ValidationResult,\n} from '@dynamic-field-kit/core';\n"],"mappings":"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","names":["jsx","React","jsx","jsxs","React","React","useCallback","useCallback","useEffect","useMemo","useState","jsx","useState","useEffect","useMemo","jsx","jsxs","useCallback","jsx","useCallback","React","validateField","validateFields","resolveDisabled","resolveReadOnly","resolveOptions"]}
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@dynamic-field-kit/react",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "React renderer for dynamic-field-kit",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
8
- "types": "dist/index.d.ts",
9
8
  "sideEffects": [
10
9
  "./dist/index.js",
11
10
  "./dist/index.mjs",
@@ -13,18 +12,31 @@
13
12
  "./src/layout/defaultLayouts.tsx",
14
13
  "./src/layout/responsiveLayout.tsx"
15
14
  ],
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
16
18
  "files": [
17
19
  "dist"
18
20
  ],
19
21
  "peerDependencies": {
20
- "@dynamic-field-kit/core": "^1.1.0"
21
- },
22
- "dependencies": {
23
- "@dynamic-field-kit/core": "^1.1.0",
24
- "react": "^18.2.0"
22
+ "@dynamic-field-kit/core": "^1.3.0",
23
+ "react": "^18.0.0 || ^19.0.0",
24
+ "react-dom": "^18.0.0 || ^19.0.0"
25
25
  },
26
26
  "devDependencies": {
27
- "tsup": "^8.0.1"
27
+ "@dynamic-field-kit/core": "^1.3.0",
28
+ "@testing-library/dom": "^10.0.0",
29
+ "@testing-library/jest-dom": "^6.4.0",
30
+ "@testing-library/react": "^16.0.0",
31
+ "@testing-library/user-event": "^14.5.0",
32
+ "@vitest/coverage-v8": "^1.6.0",
33
+ "@vitejs/plugin-react": "^4.2.0",
34
+ "jsdom": "^24.0.0",
35
+ "react": "^19.2.4",
36
+ "react-dom": "^19.2.4",
37
+ "tsup": "^8.0.1",
38
+ "vite": "^5.4.0",
39
+ "vitest": "^1.6.0"
28
40
  },
29
41
  "exports": {
30
42
  ".": {
@@ -36,7 +48,11 @@
36
48
  "scripts": {
37
49
  "build": "npx tsup",
38
50
  "clean": "rimraf dist",
39
- "prepublishOnly": "npm run clean && npm run build",
51
+ "test": "vitest run",
52
+ "test:watch": "vitest",
53
+ "typecheck": "tsc -p tsconfig.json --noEmit",
54
+ "test:coverage": "vitest run --coverage",
55
+ "prepublishOnly": "npm run build",
40
56
  "release:patch": "npm version patch && npm publish",
41
57
  "release:minor": "npm version minor && npm publish",
42
58
  "release:major": "npm version major && npm publish"