@evanschleret/formforgeclient 1.1.0 → 1.1.3
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/module.json
CHANGED
|
@@ -137,12 +137,55 @@ function getResolvedZodSchema() {
|
|
|
137
137
|
}
|
|
138
138
|
return internalForm.zodSchema.value;
|
|
139
139
|
}
|
|
140
|
+
function resolveSchemaFieldNames(schema) {
|
|
141
|
+
const names = /* @__PURE__ */ new Set();
|
|
142
|
+
if (Array.isArray(schema.fields)) {
|
|
143
|
+
for (const field of schema.fields) {
|
|
144
|
+
if (typeof field.name === "string" && field.name !== "") {
|
|
145
|
+
names.add(field.name);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (Array.isArray(schema.pages)) {
|
|
150
|
+
for (const page of schema.pages) {
|
|
151
|
+
if (!Array.isArray(page.fields)) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
for (const field of page.fields) {
|
|
155
|
+
if (typeof field.name === "string" && field.name !== "") {
|
|
156
|
+
names.add(field.name);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return names;
|
|
162
|
+
}
|
|
163
|
+
function sanitizePayloadWithSchema(value, schema) {
|
|
164
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
165
|
+
return {};
|
|
166
|
+
}
|
|
167
|
+
const allowedFieldNames = resolveSchemaFieldNames(schema);
|
|
168
|
+
const sanitizedPayload = {};
|
|
169
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
170
|
+
if (!allowedFieldNames.has(key)) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
sanitizedPayload[key] = entryValue;
|
|
174
|
+
}
|
|
175
|
+
return sanitizedPayload;
|
|
176
|
+
}
|
|
140
177
|
const formState = computed({
|
|
141
178
|
get: () => {
|
|
142
179
|
const value = usesExternalModel.value ? unwrapModelValueProp(props.modelValue) : internalForm.state.value;
|
|
143
180
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
144
181
|
return {};
|
|
145
182
|
}
|
|
183
|
+
if (usesExternalModel.value) {
|
|
184
|
+
const schema = getResolvedSchema();
|
|
185
|
+
if (schema !== null) {
|
|
186
|
+
return sanitizePayloadWithSchema(value, schema);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
146
189
|
return value;
|
|
147
190
|
},
|
|
148
191
|
set: (value) => {
|
|
@@ -153,6 +196,23 @@ const formState = computed({
|
|
|
153
196
|
internalForm.replaceState(value);
|
|
154
197
|
}
|
|
155
198
|
});
|
|
199
|
+
watch(
|
|
200
|
+
() => [usesExternalModel.value, getResolvedSchema(), unwrapModelValueProp(props.modelValue)],
|
|
201
|
+
([externalModel, schema, modelValue]) => {
|
|
202
|
+
if (!externalModel || schema === null) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const sanitizedValue = sanitizePayloadWithSchema(modelValue, schema);
|
|
206
|
+
if (areValuesEqual(modelValue, sanitizedValue)) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
emit("update:modelValue", sanitizedValue);
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
immediate: true,
|
|
213
|
+
deep: true
|
|
214
|
+
}
|
|
215
|
+
);
|
|
156
216
|
const displayPages = computed(() => {
|
|
157
217
|
const schema = getResolvedSchema();
|
|
158
218
|
if (schema === null) {
|
|
@@ -861,6 +921,20 @@ function getFieldMetaUi(field) {
|
|
|
861
921
|
component: componentUi
|
|
862
922
|
};
|
|
863
923
|
}
|
|
924
|
+
function mergeUiClass(defaultClass, value) {
|
|
925
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
926
|
+
return defaultClass;
|
|
927
|
+
}
|
|
928
|
+
return `${defaultClass} ${value}`;
|
|
929
|
+
}
|
|
930
|
+
function getResolvedFormFieldUi(field) {
|
|
931
|
+
const metaUi = getFieldMetaUi(field).formField;
|
|
932
|
+
return {
|
|
933
|
+
...metaUi,
|
|
934
|
+
label: mergeUiClass("text-default", metaUi?.label),
|
|
935
|
+
help: mergeUiClass("text-muted", metaUi?.help)
|
|
936
|
+
};
|
|
937
|
+
}
|
|
864
938
|
function getFieldValue(field) {
|
|
865
939
|
return formState.value[field.name];
|
|
866
940
|
}
|
|
@@ -1098,7 +1172,7 @@ async function onSubmit() {
|
|
|
1098
1172
|
>
|
|
1099
1173
|
<h3
|
|
1100
1174
|
v-if="page.title !== ''"
|
|
1101
|
-
class="text-base font-semibold"
|
|
1175
|
+
class="text-base font-semibold text-default"
|
|
1102
1176
|
>
|
|
1103
1177
|
{{ page.title }}
|
|
1104
1178
|
</h3>
|
|
@@ -1119,7 +1193,7 @@ async function onSubmit() {
|
|
|
1119
1193
|
:label="field.label"
|
|
1120
1194
|
:help="field.help_text"
|
|
1121
1195
|
:required="isFieldRequired(field)"
|
|
1122
|
-
:ui="
|
|
1196
|
+
:ui="getResolvedFormFieldUi(field)"
|
|
1123
1197
|
@focusout="() => onFieldBlur(field.name)"
|
|
1124
1198
|
>
|
|
1125
1199
|
<UInput
|
|
@@ -468,7 +468,7 @@ watch(
|
|
|
468
468
|
<div class="w-full">
|
|
469
469
|
<p
|
|
470
470
|
v-if="loading"
|
|
471
|
-
class="text-sm text-
|
|
471
|
+
class="text-sm text-default"
|
|
472
472
|
>
|
|
473
473
|
{{ t("response.loading") }}
|
|
474
474
|
</p>
|
|
@@ -482,7 +482,7 @@ watch(
|
|
|
482
482
|
|
|
483
483
|
<p
|
|
484
484
|
v-else-if="responsePages.length === 0"
|
|
485
|
-
class="text-sm text-
|
|
485
|
+
class="text-sm text-default"
|
|
486
486
|
>
|
|
487
487
|
{{ t("response.empty") }}
|
|
488
488
|
</p>
|
|
@@ -504,12 +504,12 @@ watch(
|
|
|
504
504
|
class="space-y-4"
|
|
505
505
|
>
|
|
506
506
|
<div class="space-y-1">
|
|
507
|
-
<h3 class="text-base font-semibold text-
|
|
507
|
+
<h3 class="text-base font-semibold text-default">
|
|
508
508
|
{{ page.title || t("response.page.fallback", { index: pageIndex + 1 }) }}
|
|
509
509
|
</h3>
|
|
510
510
|
<p
|
|
511
511
|
v-if="typeof page.description === 'string' && page.description.trim() !== ''"
|
|
512
|
-
class="text-sm text-
|
|
512
|
+
class="text-sm text-default"
|
|
513
513
|
>
|
|
514
514
|
{{ page.description }}
|
|
515
515
|
</p>
|
|
@@ -525,13 +525,13 @@ watch(
|
|
|
525
525
|
v-if="isLineLayout"
|
|
526
526
|
class="grid grid-cols-1 gap-2 md:grid-cols-[minmax(0,1fr)_minmax(0,2fr)] md:gap-6"
|
|
527
527
|
>
|
|
528
|
-
<p class="whitespace-pre-wrap text-sm font-medium text-
|
|
528
|
+
<p class="whitespace-pre-wrap text-sm font-medium text-default">
|
|
529
529
|
{{ item.question }}
|
|
530
530
|
</p>
|
|
531
531
|
|
|
532
532
|
<div
|
|
533
533
|
v-if="item.answer.kind === 'text'"
|
|
534
|
-
class="whitespace-pre-wrap text-sm text-
|
|
534
|
+
class="whitespace-pre-wrap text-sm text-default"
|
|
535
535
|
>
|
|
536
536
|
{{ item.answer.value }}
|
|
537
537
|
</div>
|
|
@@ -561,16 +561,16 @@ watch(
|
|
|
561
561
|
<UIcon
|
|
562
562
|
v-else
|
|
563
563
|
name="i-lucide-file"
|
|
564
|
-
class="h-5 w-5 shrink-0 text-
|
|
564
|
+
class="h-5 w-5 shrink-0 text-default"
|
|
565
565
|
/>
|
|
566
566
|
|
|
567
567
|
<div class="min-w-0 flex-1">
|
|
568
|
-
<p class="truncate text-sm text-
|
|
568
|
+
<p class="truncate text-sm text-default">
|
|
569
569
|
{{ file.name }}
|
|
570
570
|
</p>
|
|
571
571
|
<p
|
|
572
572
|
v-if="file.mimeType"
|
|
573
|
-
class="text-xs text-
|
|
573
|
+
class="text-xs text-default"
|
|
574
574
|
>
|
|
575
575
|
{{ file.mimeType }}
|
|
576
576
|
</p>
|
|
@@ -622,13 +622,13 @@ watch(
|
|
|
622
622
|
v-else
|
|
623
623
|
class="space-y-1"
|
|
624
624
|
>
|
|
625
|
-
<p class="whitespace-pre-wrap text-sm font-medium text-
|
|
625
|
+
<p class="whitespace-pre-wrap text-sm font-medium text-default">
|
|
626
626
|
{{ item.question }}
|
|
627
627
|
</p>
|
|
628
628
|
|
|
629
629
|
<p
|
|
630
630
|
v-if="item.answer.kind === 'text'"
|
|
631
|
-
class="whitespace-pre-wrap text-sm text-
|
|
631
|
+
class="whitespace-pre-wrap text-sm text-default"
|
|
632
632
|
>
|
|
633
633
|
{{ item.answer.value }}
|
|
634
634
|
</p>
|
|
@@ -658,16 +658,16 @@ watch(
|
|
|
658
658
|
<UIcon
|
|
659
659
|
v-else
|
|
660
660
|
name="i-lucide-file"
|
|
661
|
-
class="h-5 w-5 shrink-0 text-
|
|
661
|
+
class="h-5 w-5 shrink-0 text-default"
|
|
662
662
|
/>
|
|
663
663
|
|
|
664
664
|
<div class="min-w-0 flex-1">
|
|
665
|
-
<p class="truncate text-sm text-
|
|
665
|
+
<p class="truncate text-sm text-default">
|
|
666
666
|
{{ file.name }}
|
|
667
667
|
</p>
|
|
668
668
|
<p
|
|
669
669
|
v-if="file.mimeType"
|
|
670
|
-
class="text-xs text-
|
|
670
|
+
class="text-xs text-default"
|
|
671
671
|
>
|
|
672
672
|
{{ file.mimeType }}
|
|
673
673
|
</p>
|