@fayz-ai/plugin-forms 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{FormBuilder-KDANEL6Z.js → FormBuilder-7SWZQKFN.js} +130 -23
- package/dist/FormBuilder-7SWZQKFN.js.map +1 -0
- package/dist/{FormBuilder-4VKYVZAC.cjs → FormBuilder-YB75LEEH.cjs} +129 -22
- package/dist/FormBuilder-YB75LEEH.cjs.map +1 -0
- package/dist/agent-tools.d.ts +4 -0
- package/dist/agent-tools.d.ts.map +1 -0
- package/dist/chunk-QM2AF3DZ.cjs +446 -0
- package/dist/chunk-QM2AF3DZ.cjs.map +1 -0
- package/dist/chunk-W2ZNJGQC.js +438 -0
- package/dist/chunk-W2ZNJGQC.js.map +1 -0
- package/dist/components/DocumentFormDialog.d.ts +3 -1
- package/dist/components/DocumentFormDialog.d.ts.map +1 -1
- package/dist/components/DocumentList.d.ts.map +1 -1
- package/dist/components/FieldConfigDialog.d.ts.map +1 -1
- package/dist/components/FormBuilder.d.ts.map +1 -1
- package/dist/components/FormViewer.d.ts.map +1 -1
- package/dist/components/PersonDocumentsWidget.d.ts.map +1 -1
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/index.cjs +142 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +142 -54
- package/dist/index.js.map +1 -1
- package/dist/lib/person-fields.d.ts +16 -0
- package/dist/lib/person-fields.d.ts.map +1 -0
- package/dist/lib/print.d.ts +17 -0
- package/dist/lib/print.d.ts.map +1 -0
- package/dist/lib/tenant.d.ts.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/views/CustomFormsSettingsTab.d.ts.map +1 -1
- package/dist/views/TemplateListView.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/agent-tools.ts +73 -0
- package/src/components/DocumentFormDialog.tsx +37 -16
- package/src/components/DocumentList.tsx +12 -8
- package/src/components/FieldConfigDialog.tsx +40 -0
- package/src/components/FormBuilder.tsx +104 -22
- package/src/components/FormViewer.tsx +11 -1
- package/src/components/PersonDocumentsWidget.tsx +10 -1
- package/src/data/supabase.ts +2 -0
- package/src/index.ts +21 -0
- package/src/lib/person-fields.ts +67 -0
- package/src/lib/print.ts +207 -0
- package/src/lib/tenant.ts +6 -2
- package/src/locales/en.ts +20 -0
- package/src/locales/pt-BR.ts +20 -0
- package/src/migrations/003_agent_rpcs.sql +174 -0
- package/src/migrations/index.ts +178 -1
- package/src/types.ts +14 -0
- package/src/views/CustomFormsSettingsTab.tsx +23 -16
- package/src/views/TemplateListView.tsx +29 -18
- package/dist/FormBuilder-4VKYVZAC.cjs.map +0 -1
- package/dist/FormBuilder-KDANEL6Z.js.map +0 -1
- package/dist/chunk-32I43T37.js +0 -198
- package/dist/chunk-32I43T37.js.map +0 -1
- package/dist/chunk-XLUULIVL.cjs +0 -200
- package/dist/chunk-XLUULIVL.cjs.map +0 -1
package/dist/chunk-XLUULIVL.cjs
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var react = require('react');
|
|
4
|
-
var ui = require('@fayz-ai/ui');
|
|
5
|
-
var core = require('@fayz-ai/core');
|
|
6
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
-
|
|
8
|
-
// src/components/FormRenderer.tsx
|
|
9
|
-
function FieldRenderer({
|
|
10
|
-
field,
|
|
11
|
-
value,
|
|
12
|
-
onChange,
|
|
13
|
-
readOnly
|
|
14
|
-
}) {
|
|
15
|
-
core.useTranslation();
|
|
16
|
-
switch (field.type) {
|
|
17
|
-
case "title":
|
|
18
|
-
return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold pt-2 pb-1 border-b", children: field.label });
|
|
19
|
-
case "text":
|
|
20
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
21
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
22
|
-
field.label,
|
|
23
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
24
|
-
] }),
|
|
25
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
26
|
-
ui.Input,
|
|
27
|
-
{
|
|
28
|
-
value: value ?? "",
|
|
29
|
-
onChange: (e) => onChange(e.target.value),
|
|
30
|
-
placeholder: field.placeholder,
|
|
31
|
-
className: "h-9 text-sm",
|
|
32
|
-
readOnly
|
|
33
|
-
}
|
|
34
|
-
)
|
|
35
|
-
] });
|
|
36
|
-
case "memo":
|
|
37
|
-
case "richtext":
|
|
38
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
39
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
40
|
-
field.label,
|
|
41
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
42
|
-
] }),
|
|
43
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
44
|
-
"textarea",
|
|
45
|
-
{
|
|
46
|
-
value: value ?? "",
|
|
47
|
-
onChange: (e) => onChange(e.target.value),
|
|
48
|
-
placeholder: field.placeholder,
|
|
49
|
-
className: "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 min-h-[100px]",
|
|
50
|
-
readOnly
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
] });
|
|
54
|
-
case "date":
|
|
55
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
56
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
57
|
-
field.label,
|
|
58
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
59
|
-
] }),
|
|
60
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
61
|
-
ui.Input,
|
|
62
|
-
{
|
|
63
|
-
type: "date",
|
|
64
|
-
value: value ?? "",
|
|
65
|
-
onChange: (e) => onChange(e.target.value),
|
|
66
|
-
className: "h-9 text-sm",
|
|
67
|
-
readOnly
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
] });
|
|
71
|
-
case "select":
|
|
72
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
73
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
74
|
-
field.label,
|
|
75
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
76
|
-
] }),
|
|
77
|
-
readOnly ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm py-1", children: value ?? "-" }) : /* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: value ?? "", onValueChange: onChange, children: [
|
|
78
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.SelectTrigger, { className: "h-9 text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(ui.SelectValue, { placeholder: field.placeholder ?? "..." }) }),
|
|
79
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.SelectContent, { children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
|
|
80
|
-
] })
|
|
81
|
-
] });
|
|
82
|
-
case "radio":
|
|
83
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
84
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
85
|
-
field.label,
|
|
86
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
87
|
-
] }),
|
|
88
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
89
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
90
|
-
"input",
|
|
91
|
-
{
|
|
92
|
-
type: "radio",
|
|
93
|
-
name: field.id,
|
|
94
|
-
value: opt.value,
|
|
95
|
-
checked: value === opt.value,
|
|
96
|
-
onChange: () => onChange(opt.value),
|
|
97
|
-
disabled: readOnly,
|
|
98
|
-
className: "text-primary"
|
|
99
|
-
}
|
|
100
|
-
),
|
|
101
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: opt.label })
|
|
102
|
-
] }, opt.value)) })
|
|
103
|
-
] });
|
|
104
|
-
case "tags": {
|
|
105
|
-
const selectedTags = Array.isArray(value) ? value : [];
|
|
106
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
107
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
108
|
-
field.label,
|
|
109
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
110
|
-
] }),
|
|
111
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5", children: (field.options ?? []).map((opt) => {
|
|
112
|
-
const active = selectedTags.includes(opt.value);
|
|
113
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
114
|
-
ui.Badge,
|
|
115
|
-
{
|
|
116
|
-
variant: active ? "default" : "outline",
|
|
117
|
-
className: `cursor-pointer text-xs ${readOnly ? "pointer-events-none" : ""}`,
|
|
118
|
-
onClick: () => {
|
|
119
|
-
if (readOnly) return;
|
|
120
|
-
onChange(
|
|
121
|
-
active ? selectedTags.filter((t2) => t2 !== opt.value) : [...selectedTags, opt.value]
|
|
122
|
-
);
|
|
123
|
-
},
|
|
124
|
-
children: opt.label
|
|
125
|
-
},
|
|
126
|
-
opt.value
|
|
127
|
-
);
|
|
128
|
-
}) })
|
|
129
|
-
] });
|
|
130
|
-
}
|
|
131
|
-
case "checkbox":
|
|
132
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 cursor-pointer py-1", children: [
|
|
133
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
134
|
-
"input",
|
|
135
|
-
{
|
|
136
|
-
type: "checkbox",
|
|
137
|
-
checked: !!value,
|
|
138
|
-
onChange: (e) => onChange(e.target.checked),
|
|
139
|
-
disabled: readOnly,
|
|
140
|
-
className: "rounded border-input"
|
|
141
|
-
}
|
|
142
|
-
),
|
|
143
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium", children: [
|
|
144
|
-
field.label,
|
|
145
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
146
|
-
] })
|
|
147
|
-
] });
|
|
148
|
-
case "image":
|
|
149
|
-
case "gallery":
|
|
150
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
151
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
152
|
-
field.label,
|
|
153
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
154
|
-
] }),
|
|
155
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center rounded-lg border-2 border-dashed py-8 text-sm text-muted-foreground", children: [
|
|
156
|
-
field.type === "gallery" ? "Gallery upload" : "Image upload",
|
|
157
|
-
" \u2014 v2"
|
|
158
|
-
] })
|
|
159
|
-
] });
|
|
160
|
-
case "budget":
|
|
161
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
162
|
-
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-xs font-medium block", children: [
|
|
163
|
-
field.label,
|
|
164
|
-
field.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
165
|
-
] }),
|
|
166
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center rounded-lg border-2 border-dashed py-8 text-sm text-muted-foreground", children: "Budget / line items \u2014 v2" })
|
|
167
|
-
] });
|
|
168
|
-
default:
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
function FormRenderer({ schema, data, onChange, readOnly }) {
|
|
173
|
-
const sortedFields = [...schema.fields].sort((a, b) => a.row - b.row || a.col - b.col);
|
|
174
|
-
const handleFieldChange = react.useCallback(
|
|
175
|
-
(fieldId, value) => {
|
|
176
|
-
onChange({ ...data, [fieldId]: value });
|
|
177
|
-
},
|
|
178
|
-
[data, onChange]
|
|
179
|
-
);
|
|
180
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
-
"div",
|
|
182
|
-
{
|
|
183
|
-
className: "grid gap-x-4 gap-y-3",
|
|
184
|
-
style: { gridTemplateColumns: "repeat(12, 1fr)" },
|
|
185
|
-
children: sortedFields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { gridColumn: `span ${field.colSpan}` }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
186
|
-
FieldRenderer,
|
|
187
|
-
{
|
|
188
|
-
field,
|
|
189
|
-
value: data[field.id],
|
|
190
|
-
onChange: (v) => handleFieldChange(field.id, v),
|
|
191
|
-
readOnly
|
|
192
|
-
}
|
|
193
|
-
) }, field.id))
|
|
194
|
-
}
|
|
195
|
-
);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
exports.FormRenderer = FormRenderer;
|
|
199
|
-
//# sourceMappingURL=chunk-XLUULIVL.cjs.map
|
|
200
|
-
//# sourceMappingURL=chunk-XLUULIVL.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/FormRenderer.tsx"],"names":["useTranslation","jsx","jsxs","Input","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","Badge","t","useCallback"],"mappings":"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","file":"chunk-XLUULIVL.cjs","sourcesContent":["import React, { useCallback } from 'react'\nimport { Input } from '@fayz-ai/ui'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@fayz-ai/ui'\nimport { Badge } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport type { FormFieldDef, FormSchema } from '../types'\n\ninterface FormRendererProps {\n schema: FormSchema\n data: Record<string, unknown>\n onChange: (data: Record<string, unknown>) => void\n readOnly?: boolean\n}\n\nfunction FieldRenderer({\n field,\n value,\n onChange,\n readOnly,\n}: {\n field: FormFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly?: boolean\n}) {\n const t = useTranslation()\n\n switch (field.type) {\n case 'title':\n return (\n <h3 className=\"text-base font-semibold pt-2 pb-1 border-b\">\n {field.label}\n </h3>\n )\n\n case 'text':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <Input\n value={(value as string) ?? ''}\n onChange={(e) => onChange(e.target.value)}\n placeholder={field.placeholder}\n className=\"h-9 text-sm\"\n readOnly={readOnly}\n />\n </div>\n )\n\n case 'memo':\n case 'richtext':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <textarea\n value={(value as string) ?? ''}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)}\n placeholder={field.placeholder}\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 min-h-[100px]\"\n readOnly={readOnly}\n />\n </div>\n )\n\n case 'date':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <Input\n type=\"date\"\n value={(value as string) ?? ''}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-9 text-sm\"\n readOnly={readOnly}\n />\n </div>\n )\n\n case 'select':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {readOnly ? (\n <p className=\"text-sm py-1\">{(value as string) ?? '-'}</p>\n ) : (\n <Select value={(value as string) ?? ''} onValueChange={onChange}>\n <SelectTrigger className=\"h-9 text-sm\">\n <SelectValue placeholder={field.placeholder ?? '...'} />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n )\n\n case 'radio':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"space-y-1\">\n {(field.options ?? []).map((opt) => (\n <label key={opt.value} className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"radio\"\n name={field.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={() => onChange(opt.value)}\n disabled={readOnly}\n className=\"text-primary\"\n />\n <span className=\"text-sm\">{opt.label}</span>\n </label>\n ))}\n </div>\n </div>\n )\n\n case 'tags': {\n const selectedTags = Array.isArray(value) ? (value as string[]) : []\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"flex flex-wrap gap-1.5\">\n {(field.options ?? []).map((opt) => {\n const active = selectedTags.includes(opt.value)\n return (\n <Badge\n key={opt.value}\n variant={active ? 'default' : 'outline'}\n className={`cursor-pointer text-xs ${readOnly ? 'pointer-events-none' : ''}`}\n onClick={() => {\n if (readOnly) return\n onChange(\n active\n ? selectedTags.filter((t) => t !== opt.value)\n : [...selectedTags, opt.value],\n )\n }}\n >\n {opt.label}\n </Badge>\n )\n })}\n </div>\n </div>\n )\n }\n\n case 'checkbox':\n return (\n <label className=\"flex items-center gap-2 cursor-pointer py-1\">\n <input\n type=\"checkbox\"\n checked={!!value}\n onChange={(e) => onChange(e.target.checked)}\n disabled={readOnly}\n className=\"rounded border-input\"\n />\n <span className=\"text-sm font-medium\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </span>\n </label>\n )\n\n case 'image':\n case 'gallery':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"flex items-center justify-center rounded-lg border-2 border-dashed py-8 text-sm text-muted-foreground\">\n {field.type === 'gallery' ? 'Gallery upload' : 'Image upload'} — v2\n </div>\n </div>\n )\n\n case 'budget':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"flex items-center justify-center rounded-lg border-2 border-dashed py-8 text-sm text-muted-foreground\">\n Budget / line items — v2\n </div>\n </div>\n )\n\n default:\n return null\n }\n}\n\nexport function FormRenderer({ schema, data, onChange, readOnly }: FormRendererProps) {\n const sortedFields = [...schema.fields].sort((a, b) => a.row - b.row || a.col - b.col)\n\n const handleFieldChange = useCallback(\n (fieldId: string, value: unknown) => {\n onChange({ ...data, [fieldId]: value })\n },\n [data, onChange],\n )\n\n return (\n <div\n className=\"grid gap-x-4 gap-y-3\"\n style={{ gridTemplateColumns: 'repeat(12, 1fr)' }}\n >\n {sortedFields.map((field) => (\n <div key={field.id} style={{ gridColumn: `span ${field.colSpan}` }}>\n <FieldRenderer\n field={field}\n value={data[field.id]}\n onChange={(v) => handleFieldChange(field.id, v)}\n readOnly={readOnly}\n />\n </div>\n ))}\n </div>\n )\n}\n"]}
|