@evanschleret/formforgeclient 1.2.4 → 2.0.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 +10 -0
- package/dist/module.cjs +1 -0
- package/dist/module.d.cts +1 -0
- package/dist/module.d.mts +1 -0
- package/dist/module.d.ts +1 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -0
- package/dist/runtime/api/client.js +4 -2
- package/dist/runtime/api/request.d.ts +1 -0
- package/dist/runtime/api/schema.js +4 -4
- package/dist/runtime/assets/formforge.css +1 -0
- package/dist/runtime/composables/index.d.ts +1 -1
- package/dist/runtime/composables/useFormForgeBuilder.d.ts +24 -2
- package/dist/runtime/composables/useFormForgeBuilder.js +299 -43
- package/dist/runtime/composables/useFormForgeForm.js +15 -5
- package/dist/runtime/composables/useFormForgeI18n.d.ts +245 -19
- package/dist/runtime/composables/useFormForgeI18n.js +245 -19
- package/dist/runtime/composables/useFormForgeSubmit.js +31 -9
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/renderers/default/FormForgeBuilder.d.vue.ts +21 -2
- package/dist/runtime/renderers/default/FormForgeBuilder.vue +689 -738
- package/dist/runtime/renderers/default/FormForgeBuilder.vue.d.ts +21 -2
- package/dist/runtime/renderers/default/FormForgeBuilderBlockSettingsModal.d.vue.ts +17 -0
- package/dist/runtime/renderers/default/FormForgeBuilderBlockSettingsModal.vue +32 -0
- package/dist/runtime/renderers/default/FormForgeBuilderBlockSettingsModal.vue.d.ts +17 -0
- package/dist/runtime/renderers/default/FormForgeRenderer.d.vue.ts +3 -4
- package/dist/runtime/renderers/default/FormForgeRenderer.vue +344 -294
- package/dist/runtime/renderers/default/FormForgeRenderer.vue.d.ts +3 -4
- package/dist/runtime/renderers/default/FormForgeRendererField.d.vue.ts +22 -0
- package/dist/runtime/renderers/default/FormForgeRendererField.vue +237 -0
- package/dist/runtime/renderers/default/FormForgeRendererField.vue.d.ts +22 -0
- package/dist/runtime/renderers/default/FormForgeRendererPage.d.vue.ts +18 -0
- package/dist/runtime/renderers/default/FormForgeRendererPage.vue +31 -0
- package/dist/runtime/renderers/default/FormForgeRendererPage.vue.d.ts +18 -0
- package/dist/runtime/renderers/default/FormForgeResponse.vue +4 -3
- package/dist/runtime/renderers/default/builder/FormForgeBuilderAddressFieldsCard.d.vue.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderAddressFieldsCard.vue +118 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderAddressFieldsCard.vue.d.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderBlockCard.d.vue.ts +46 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderBlockCard.vue +205 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderBlockCard.vue.d.ts +46 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderChoiceDisplayField.d.vue.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderChoiceDisplayField.vue +37 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderChoiceDisplayField.vue.d.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderChoiceOptionsField.d.vue.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderChoiceOptionsField.vue +195 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderChoiceOptionsField.vue.d.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderDescriptionField.d.vue.ts +14 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderDescriptionField.vue +91 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderDescriptionField.vue.d.ts +14 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderLogicPanel.d.vue.ts +13 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderLogicPanel.vue +387 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderLogicPanel.vue.d.ts +13 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderQuestionRow.d.vue.ts +44 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderQuestionRow.vue +328 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderQuestionRow.vue.d.ts +44 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderTemporalModeField.d.vue.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderTemporalModeField.vue +47 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderTemporalModeField.vue.d.ts +11 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderValidationRulesSection.d.vue.ts +14 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderValidationRulesSection.vue +595 -0
- package/dist/runtime/renderers/default/builder/FormForgeBuilderValidationRulesSection.vue.d.ts +14 -0
- package/dist/runtime/renderers/default/builder/builderFieldHelpers.d.ts +3 -0
- package/dist/runtime/renderers/default/builder/builderFieldHelpers.js +4 -0
- package/dist/runtime/types/index.d.ts +1 -1
- package/dist/runtime/types/management.d.ts +12 -0
- package/dist/runtime/types/schema.d.ts +72 -4
- package/dist/runtime/utils/defaults.d.ts +7 -0
- package/dist/runtime/utils/defaults.js +86 -0
- package/dist/runtime/utils/page-logic.d.ts +24 -0
- package/dist/runtime/utils/page-logic.js +351 -0
- package/dist/runtime/utils/rich-text.d.ts +3 -0
- package/dist/runtime/utils/rich-text.js +72 -0
- package/dist/runtime/utils/schema.d.ts +1 -1
- package/dist/runtime/utils/schema.js +70 -16
- package/dist/runtime/utils/temporal.d.ts +10 -0
- package/dist/runtime/utils/temporal.js +28 -0
- package/dist/runtime/utils/validation.d.ts +5 -0
- package/dist/runtime/utils/validation.js +36 -0
- package/dist/runtime/validation/zod.d.ts +5 -2
- package/dist/runtime/validation/zod.js +563 -54
- package/dist/types.d.mts +2 -0
- package/package.json +18 -14
|
@@ -4,7 +4,6 @@ interface FormForgeValidationError {
|
|
|
4
4
|
message: string;
|
|
5
5
|
}
|
|
6
6
|
type FormForgeValidationHandler = (state: FormForgeSubmissionPayload) => FormForgeValidationError[] | Promise<FormForgeValidationError[]>;
|
|
7
|
-
type FormForgeProgressVariant = 'stepper' | 'progress';
|
|
8
7
|
type FormForgeValidateEvent = 'input' | 'change' | 'blur';
|
|
9
8
|
interface FormForgeExposedError {
|
|
10
9
|
id?: string;
|
|
@@ -34,10 +33,10 @@ interface Props {
|
|
|
34
33
|
uploadMode?: FormForgeUploadMode;
|
|
35
34
|
clearAfterSubmit?: boolean;
|
|
36
35
|
showProgress?: boolean;
|
|
37
|
-
progressVariant?: FormForgeProgressVariant;
|
|
38
36
|
showAlertOnError?: boolean;
|
|
39
37
|
validateOn?: FormForgeValidateEvent[];
|
|
40
38
|
validateOnBlur?: boolean;
|
|
39
|
+
previewPageKey?: string | null;
|
|
41
40
|
}
|
|
42
41
|
type FormForgeValidateOptions = {
|
|
43
42
|
name?: string | string[];
|
|
@@ -73,10 +72,10 @@ declare const __VLS_export: import("vue").DefineComponent<Props, {
|
|
|
73
72
|
datetimeMode: FormForgeDatetimeMode;
|
|
74
73
|
endpoint: string;
|
|
75
74
|
clientConfig: FormForgeClientConfig;
|
|
76
|
-
formKey: string;
|
|
77
75
|
modelValue: FormForgeSubmissionPayload | {
|
|
78
76
|
value: FormForgeSubmissionPayload;
|
|
79
77
|
};
|
|
78
|
+
formKey: string;
|
|
80
79
|
zodSchema: object | {
|
|
81
80
|
value: object | undefined;
|
|
82
81
|
};
|
|
@@ -87,10 +86,10 @@ declare const __VLS_export: import("vue").DefineComponent<Props, {
|
|
|
87
86
|
simulation: boolean;
|
|
88
87
|
clearAfterSubmit: boolean;
|
|
89
88
|
showProgress: boolean;
|
|
90
|
-
progressVariant: FormForgeProgressVariant;
|
|
91
89
|
showAlertOnError: boolean;
|
|
92
90
|
validateOn: FormForgeValidateEvent[];
|
|
93
91
|
validateOnBlur: boolean;
|
|
92
|
+
previewPageKey: string | null;
|
|
94
93
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
95
94
|
declare const _default: typeof __VLS_export;
|
|
96
95
|
export default _default;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DateValue, Time } from '@internationalized/date';
|
|
2
|
+
import type { FormForgeAddressFieldSchema, FormForgeFieldSchema } from '../../types/index.js';
|
|
3
|
+
type FormForgeDynamicValue = string | number | boolean | null | undefined | DateValue | Time | File | File[] | Record<string, unknown> | Array<unknown>;
|
|
4
|
+
interface Props {
|
|
5
|
+
field: FormForgeFieldSchema;
|
|
6
|
+
modelValue: unknown;
|
|
7
|
+
componentProps: Record<string, unknown>;
|
|
8
|
+
fieldUi: Record<string, unknown>;
|
|
9
|
+
addressFields: FormForgeAddressFieldSchema[];
|
|
10
|
+
required: boolean;
|
|
11
|
+
disabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
|
+
"update:modelValue": (value: FormForgeDynamicValue) => any;
|
|
15
|
+
blur: () => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
17
|
+
"onUpdate:modelValue"?: ((value: FormForgeDynamicValue) => any) | undefined;
|
|
18
|
+
onBlur?: (() => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
22
|
+
//# sourceMappingURL=FormForgeRendererField.vue.d.ts.map
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "#imports";
|
|
3
|
+
import { sanitizeFormForgeInlineRichText, sanitizeFormForgeRichText } from "../../utils/rich-text";
|
|
4
|
+
import { resolveTemporalMode } from "../../utils/temporal";
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
field: { type: Object, required: true },
|
|
7
|
+
modelValue: { type: null, required: true },
|
|
8
|
+
componentProps: { type: Object, required: true },
|
|
9
|
+
fieldUi: { type: Object, required: true },
|
|
10
|
+
addressFields: { type: Array, required: true },
|
|
11
|
+
required: { type: Boolean, required: true },
|
|
12
|
+
disabled: { type: Boolean, required: true }
|
|
13
|
+
});
|
|
14
|
+
const emit = defineEmits(["update:modelValue", "blur"]);
|
|
15
|
+
const temporalMode = computed(() => resolveTemporalMode(props.field));
|
|
16
|
+
const temporalHourCycle = computed(() => props.field.hour_cycle === 12 ? 12 : 24);
|
|
17
|
+
const temporalInputProps = computed(() => {
|
|
18
|
+
const { placeholder, ...rest } = props.componentProps;
|
|
19
|
+
void placeholder;
|
|
20
|
+
return rest;
|
|
21
|
+
});
|
|
22
|
+
function fullWidthUi(ui) {
|
|
23
|
+
if (ui === null || typeof ui !== "object" || Array.isArray(ui)) {
|
|
24
|
+
return {
|
|
25
|
+
base: "w-full",
|
|
26
|
+
root: "w-full"
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
...ui,
|
|
31
|
+
base: "w-full"
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function choiceDisplayValue() {
|
|
35
|
+
if (props.field.display === "list" || props.field.display === "menu") {
|
|
36
|
+
return props.field.display;
|
|
37
|
+
}
|
|
38
|
+
if (props.field.type === "radio" || props.field.type === "checkbox_group") {
|
|
39
|
+
return "list";
|
|
40
|
+
}
|
|
41
|
+
return "menu";
|
|
42
|
+
}
|
|
43
|
+
function addressFieldValue(key) {
|
|
44
|
+
if (typeof props.modelValue !== "object" || props.modelValue === null || Array.isArray(props.modelValue)) {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
const candidate = props.modelValue[key];
|
|
48
|
+
return typeof candidate === "string" ? candidate : "";
|
|
49
|
+
}
|
|
50
|
+
function updateAddressFieldValue(key, value) {
|
|
51
|
+
const currentValue = typeof props.modelValue === "object" && props.modelValue !== null && !Array.isArray(props.modelValue) ? { ...props.modelValue } : {};
|
|
52
|
+
currentValue[key] = value;
|
|
53
|
+
emit("update:modelValue", currentValue);
|
|
54
|
+
}
|
|
55
|
+
function isTemporalDateInput() {
|
|
56
|
+
return props.field.type === "temporal" ? temporalMode.value === "date" : props.field.type === "date";
|
|
57
|
+
}
|
|
58
|
+
function isTemporalTimeInput() {
|
|
59
|
+
return props.field.type === "temporal" ? temporalMode.value === "time" : props.field.type === "time";
|
|
60
|
+
}
|
|
61
|
+
function labelHtml() {
|
|
62
|
+
if (typeof props.field.label !== "string" || props.field.label.trim() === "") {
|
|
63
|
+
return "";
|
|
64
|
+
}
|
|
65
|
+
return sanitizeFormForgeInlineRichText(props.field.label);
|
|
66
|
+
}
|
|
67
|
+
function helpTextHtml() {
|
|
68
|
+
if (typeof props.field.help_text !== "string" || props.field.help_text.trim() === "") {
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
return sanitizeFormForgeRichText(props.field.help_text);
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<template>
|
|
76
|
+
<div @focusout="emit('blur')">
|
|
77
|
+
<UFormField
|
|
78
|
+
:name="field.name"
|
|
79
|
+
:label="field.label"
|
|
80
|
+
:required="field.type === 'address' ? false : required"
|
|
81
|
+
:ui="fieldUi"
|
|
82
|
+
>
|
|
83
|
+
<template #label>
|
|
84
|
+
<span v-html="labelHtml()" />
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<UInput
|
|
88
|
+
v-if="field.type === 'text' || field.type === 'email'"
|
|
89
|
+
:model-value="modelValue"
|
|
90
|
+
v-bind="componentProps"
|
|
91
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
92
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
93
|
+
/>
|
|
94
|
+
|
|
95
|
+
<UTextarea
|
|
96
|
+
v-else-if="field.type === 'textarea'"
|
|
97
|
+
:model-value="modelValue"
|
|
98
|
+
v-bind="componentProps"
|
|
99
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
100
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
101
|
+
/>
|
|
102
|
+
|
|
103
|
+
<UInputNumber
|
|
104
|
+
v-else-if="field.type === 'number'"
|
|
105
|
+
:model-value="modelValue"
|
|
106
|
+
v-bind="componentProps"
|
|
107
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
108
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
<USelect
|
|
112
|
+
v-else-if="field.type === 'select' && choiceDisplayValue() === 'menu'"
|
|
113
|
+
:model-value="modelValue"
|
|
114
|
+
v-bind="componentProps"
|
|
115
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
116
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
117
|
+
/>
|
|
118
|
+
|
|
119
|
+
<URadioGroup
|
|
120
|
+
v-else-if="field.type === 'select' && choiceDisplayValue() === 'list'"
|
|
121
|
+
:model-value="modelValue"
|
|
122
|
+
v-bind="componentProps"
|
|
123
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
124
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
125
|
+
/>
|
|
126
|
+
|
|
127
|
+
<USelectMenu
|
|
128
|
+
v-else-if="field.type === 'select_menu'"
|
|
129
|
+
:model-value="modelValue"
|
|
130
|
+
v-bind="componentProps"
|
|
131
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
132
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
<URadioGroup
|
|
136
|
+
v-else-if="field.type === 'radio' && choiceDisplayValue() === 'list'"
|
|
137
|
+
:model-value="modelValue"
|
|
138
|
+
v-bind="componentProps"
|
|
139
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
140
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
141
|
+
/>
|
|
142
|
+
|
|
143
|
+
<USelect
|
|
144
|
+
v-else-if="field.type === 'radio' && choiceDisplayValue() === 'menu'"
|
|
145
|
+
:model-value="modelValue"
|
|
146
|
+
v-bind="componentProps"
|
|
147
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
148
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
149
|
+
/>
|
|
150
|
+
|
|
151
|
+
<UCheckbox
|
|
152
|
+
v-else-if="field.type === 'checkbox' || field.type === 'consent'"
|
|
153
|
+
:model-value="modelValue"
|
|
154
|
+
v-bind="componentProps"
|
|
155
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
156
|
+
/>
|
|
157
|
+
|
|
158
|
+
<UCheckboxGroup
|
|
159
|
+
v-else-if="field.type === 'checkbox_group' && choiceDisplayValue() === 'list'"
|
|
160
|
+
:model-value="modelValue"
|
|
161
|
+
v-bind="componentProps"
|
|
162
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
163
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
164
|
+
/>
|
|
165
|
+
|
|
166
|
+
<USelectMenu
|
|
167
|
+
v-else-if="field.type === 'checkbox_group' && choiceDisplayValue() === 'menu'"
|
|
168
|
+
:model-value="modelValue"
|
|
169
|
+
v-bind="componentProps"
|
|
170
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
171
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
<div
|
|
175
|
+
v-else-if="field.type === 'address'"
|
|
176
|
+
class="grid gap-4 w-full"
|
|
177
|
+
>
|
|
178
|
+
<div class="grid gap-3">
|
|
179
|
+
<UFormField
|
|
180
|
+
v-for="addressField in addressFields"
|
|
181
|
+
v-show="addressField.visible"
|
|
182
|
+
:key="addressField.key"
|
|
183
|
+
:label="addressField.label"
|
|
184
|
+
:required="addressField.required"
|
|
185
|
+
>
|
|
186
|
+
<UInput
|
|
187
|
+
:model-value="addressFieldValue(addressField.key)"
|
|
188
|
+
:disabled="disabled"
|
|
189
|
+
:placeholder="addressField.label"
|
|
190
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
191
|
+
@update:model-value="(nextValue) => updateAddressFieldValue(addressField.key, typeof nextValue === 'string' ? nextValue : '')"
|
|
192
|
+
/>
|
|
193
|
+
</UFormField>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<USwitch
|
|
198
|
+
v-else-if="field.type === 'switch'"
|
|
199
|
+
:model-value="modelValue"
|
|
200
|
+
v-bind="componentProps"
|
|
201
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
202
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
203
|
+
/>
|
|
204
|
+
|
|
205
|
+
<UInputDate
|
|
206
|
+
v-else-if="isTemporalDateInput()"
|
|
207
|
+
:model-value="modelValue"
|
|
208
|
+
v-bind="temporalInputProps"
|
|
209
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
210
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
211
|
+
/>
|
|
212
|
+
|
|
213
|
+
<UInputTime
|
|
214
|
+
v-else-if="isTemporalTimeInput()"
|
|
215
|
+
:model-value="modelValue"
|
|
216
|
+
:hour-cycle="temporalHourCycle"
|
|
217
|
+
v-bind="temporalInputProps"
|
|
218
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
219
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
220
|
+
/>
|
|
221
|
+
|
|
222
|
+
<UFileUpload
|
|
223
|
+
v-else
|
|
224
|
+
:model-value="modelValue"
|
|
225
|
+
v-bind="componentProps"
|
|
226
|
+
:ui="fullWidthUi(componentProps.ui)"
|
|
227
|
+
@update:model-value="(nextValue) => emit('update:modelValue', nextValue)"
|
|
228
|
+
/>
|
|
229
|
+
|
|
230
|
+
<div
|
|
231
|
+
v-if="typeof field.help_text === 'string' && field.help_text.trim() !== ''"
|
|
232
|
+
class="formforge-rich-text mt-2 text-sm text-muted"
|
|
233
|
+
v-html="helpTextHtml()"
|
|
234
|
+
/>
|
|
235
|
+
</UFormField>
|
|
236
|
+
</div>
|
|
237
|
+
</template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DateValue, Time } from '@internationalized/date';
|
|
2
|
+
import type { FormForgeAddressFieldSchema, FormForgeFieldSchema } from '../../types/index.js';
|
|
3
|
+
type FormForgeDynamicValue = string | number | boolean | null | undefined | DateValue | Time | File | File[] | Record<string, unknown> | Array<unknown>;
|
|
4
|
+
interface Props {
|
|
5
|
+
field: FormForgeFieldSchema;
|
|
6
|
+
modelValue: unknown;
|
|
7
|
+
componentProps: Record<string, unknown>;
|
|
8
|
+
fieldUi: Record<string, unknown>;
|
|
9
|
+
addressFields: FormForgeAddressFieldSchema[];
|
|
10
|
+
required: boolean;
|
|
11
|
+
disabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
|
+
"update:modelValue": (value: FormForgeDynamicValue) => any;
|
|
15
|
+
blur: () => any;
|
|
16
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
17
|
+
"onUpdate:modelValue"?: ((value: FormForgeDynamicValue) => any) | undefined;
|
|
18
|
+
onBlur?: (() => any) | undefined;
|
|
19
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
declare const _default: typeof __VLS_export;
|
|
21
|
+
export default _default;
|
|
22
|
+
//# sourceMappingURL=FormForgeRendererField.vue.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FormForgePageSchema } from '../../types/index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
page: FormForgePageSchema;
|
|
4
|
+
}
|
|
5
|
+
declare var __VLS_1: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_1) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
11
|
+
declare const _default: typeof __VLS_export;
|
|
12
|
+
export default _default;
|
|
13
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
14
|
+
new (): {
|
|
15
|
+
$slots: S;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=FormForgeRendererPage.vue.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { sanitizeFormForgeRichText } from "../../utils/rich-text";
|
|
3
|
+
defineProps({
|
|
4
|
+
page: { type: Object, required: true }
|
|
5
|
+
});
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div class="space-y-4">
|
|
10
|
+
<div
|
|
11
|
+
v-if="page.title !== '' || typeof page.description === 'string' && page.description !== ''"
|
|
12
|
+
class="space-y-1"
|
|
13
|
+
>
|
|
14
|
+
<h3
|
|
15
|
+
v-if="page.title !== ''"
|
|
16
|
+
class="text-base font-semibold text-default"
|
|
17
|
+
>
|
|
18
|
+
{{ page.title }}
|
|
19
|
+
</h3>
|
|
20
|
+
<div
|
|
21
|
+
v-if="typeof page.description === 'string' && page.description !== ''"
|
|
22
|
+
class="formforge-rich-text text-sm text-muted"
|
|
23
|
+
v-html="sanitizeFormForgeRichText(page.description)"
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="space-y-4">
|
|
28
|
+
<slot />
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FormForgePageSchema } from '../../types/index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
page: FormForgePageSchema;
|
|
4
|
+
}
|
|
5
|
+
declare var __VLS_1: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_1) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_base: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
11
|
+
declare const _default: typeof __VLS_export;
|
|
12
|
+
export default _default;
|
|
13
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
14
|
+
new (): {
|
|
15
|
+
$slots: S;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=FormForgeRendererPage.vue.d.ts.map
|
|
@@ -3,6 +3,7 @@ import { computed, ref, useRoute, watch } from "#imports";
|
|
|
3
3
|
import { useFormForgeGetForm } from "../../composables/useFormForgeGetForm";
|
|
4
4
|
import { useFormForgeI18n } from "../../composables/useFormForgeI18n";
|
|
5
5
|
import { useFormForgeResponses } from "../../composables/useFormForgeResponses";
|
|
6
|
+
import { sanitizeFormForgeInlineRichText } from "../../utils/rich-text";
|
|
6
7
|
const props = defineProps({
|
|
7
8
|
responseUuid: { type: String, required: true },
|
|
8
9
|
formKey: { type: String, required: false, default: void 0 },
|
|
@@ -351,7 +352,7 @@ function createPagesFromSchema(schemaValue) {
|
|
|
351
352
|
description: page.description,
|
|
352
353
|
items: page.fields.map((field, fieldIndex) => ({
|
|
353
354
|
id: field.fieldKey,
|
|
354
|
-
question: typeof field.label === "string" && field.label.trim() !== "" ? field.label : t("response.question.fallback", { index: fieldIndex + 1 }),
|
|
355
|
+
question: typeof field.label === "string" && field.label.trim() !== "" ? sanitizeFormForgeInlineRichText(field.label) : t("response.question.fallback", { index: fieldIndex + 1 }),
|
|
355
356
|
answer: makeAnswer(
|
|
356
357
|
mapFieldAnswerValue(field, payload.value[field.name]),
|
|
357
358
|
field.type === "file"
|
|
@@ -526,7 +527,7 @@ watch(
|
|
|
526
527
|
class="grid grid-cols-1 gap-2 md:grid-cols-[minmax(0,1fr)_minmax(0,2fr)] md:gap-6"
|
|
527
528
|
>
|
|
528
529
|
<p class="whitespace-pre-wrap text-sm font-medium text-default">
|
|
529
|
-
|
|
530
|
+
<span v-html="item.question" />
|
|
530
531
|
</p>
|
|
531
532
|
|
|
532
533
|
<div
|
|
@@ -623,7 +624,7 @@ watch(
|
|
|
623
624
|
class="space-y-1"
|
|
624
625
|
>
|
|
625
626
|
<p class="whitespace-pre-wrap text-sm font-medium text-default">
|
|
626
|
-
|
|
627
|
+
<span v-html="item.question" />
|
|
627
628
|
</p>
|
|
628
629
|
|
|
629
630
|
<p
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FormForgeFieldSchema } from '../../../types/index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
field: FormForgeFieldSchema;
|
|
4
|
+
readonly?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
7
|
+
readonly: boolean;
|
|
8
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=FormForgeBuilderAddressFieldsCard.vue.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { toRef } from "#imports";
|
|
3
|
+
import { useFormForgeI18n } from "../../../composables/useFormForgeI18n";
|
|
4
|
+
import { defaultAddressFields } from "./builderFieldHelpers";
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
field: { type: Object, required: true },
|
|
7
|
+
readonly: { type: Boolean, required: false, default: false }
|
|
8
|
+
});
|
|
9
|
+
const field = toRef(props, "field");
|
|
10
|
+
const { t, locale } = useFormForgeI18n();
|
|
11
|
+
const addressFieldsGridStyle = {
|
|
12
|
+
gridTemplateColumns: "minmax(0, 1.1fr) 4rem 4rem minmax(0, 1.6fr)"
|
|
13
|
+
};
|
|
14
|
+
function addressFieldLabelKey(key) {
|
|
15
|
+
return `builder.address.${key}`;
|
|
16
|
+
}
|
|
17
|
+
function ensureAddressFields() {
|
|
18
|
+
if (!Array.isArray(field.value.address_fields) || field.value.address_fields.length === 0) {
|
|
19
|
+
field.value.address_fields = defaultAddressFields(locale.value);
|
|
20
|
+
}
|
|
21
|
+
return field.value.address_fields;
|
|
22
|
+
}
|
|
23
|
+
function addressFields() {
|
|
24
|
+
if (!Array.isArray(field.value.address_fields) || field.value.address_fields.length === 0) {
|
|
25
|
+
return defaultAddressFields(locale.value);
|
|
26
|
+
}
|
|
27
|
+
return field.value.address_fields;
|
|
28
|
+
}
|
|
29
|
+
function setAddressFieldVisible(index, visible) {
|
|
30
|
+
const addressFields2 = ensureAddressFields();
|
|
31
|
+
const candidate = addressFields2[index];
|
|
32
|
+
if (candidate === void 0) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
addressFields2[index] = {
|
|
36
|
+
...candidate,
|
|
37
|
+
visible
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function setAddressFieldRequired(index, required) {
|
|
41
|
+
const addressFields2 = ensureAddressFields();
|
|
42
|
+
const candidate = addressFields2[index];
|
|
43
|
+
if (candidate === void 0) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
addressFields2[index] = {
|
|
47
|
+
...candidate,
|
|
48
|
+
required
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function setAddressFieldLabel(index, label) {
|
|
52
|
+
const addressFields2 = ensureAddressFields();
|
|
53
|
+
const candidate = addressFields2[index];
|
|
54
|
+
if (candidate === void 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
addressFields2[index] = {
|
|
58
|
+
...candidate,
|
|
59
|
+
label
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<template>
|
|
65
|
+
<UCard :ui="{ body: 'grid gap-4' }">
|
|
66
|
+
<div class="grid gap-4">
|
|
67
|
+
<div
|
|
68
|
+
class="hidden lg:grid lg:items-center lg:gap-x-6"
|
|
69
|
+
:style="addressFieldsGridStyle"
|
|
70
|
+
>
|
|
71
|
+
<span class="min-w-0 text-sm font-medium text-default">{{ t("builder.addressFields") }}</span>
|
|
72
|
+
<span class="text-sm font-medium text-default">
|
|
73
|
+
{{ t("builder.address.show") }}
|
|
74
|
+
</span>
|
|
75
|
+
<span class="text-sm font-medium text-default">
|
|
76
|
+
{{ t("builder.address.required") }}
|
|
77
|
+
</span>
|
|
78
|
+
<span class="min-w-0 text-sm font-medium text-default">
|
|
79
|
+
{{ t("builder.address.label") }}
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div class="grid gap-3">
|
|
84
|
+
<div
|
|
85
|
+
v-for="(addressField, addressIndex) in addressFields()"
|
|
86
|
+
:key="addressField.key"
|
|
87
|
+
class="grid gap-2 lg:items-center lg:gap-x-6"
|
|
88
|
+
:style="addressFieldsGridStyle"
|
|
89
|
+
>
|
|
90
|
+
<span class="min-w-0 text-sm text-default">
|
|
91
|
+
{{ t(addressFieldLabelKey(addressField.key)) }}
|
|
92
|
+
</span>
|
|
93
|
+
<USwitch
|
|
94
|
+
:model-value="addressField.visible"
|
|
95
|
+
:disabled="readonly"
|
|
96
|
+
class="justify-self-start"
|
|
97
|
+
@update:model-value="(value) => setAddressFieldVisible(addressIndex, value)"
|
|
98
|
+
/>
|
|
99
|
+
<USwitch
|
|
100
|
+
:model-value="addressField.required"
|
|
101
|
+
:disabled="readonly || !addressField.visible"
|
|
102
|
+
class="justify-self-start"
|
|
103
|
+
@update:model-value="(value) => setAddressFieldRequired(addressIndex, value)"
|
|
104
|
+
/>
|
|
105
|
+
<div class="min-w-0">
|
|
106
|
+
<UInput
|
|
107
|
+
:model-value="addressField.label"
|
|
108
|
+
:disabled="readonly"
|
|
109
|
+
:placeholder="t(addressFieldLabelKey(addressField.key))"
|
|
110
|
+
class="w-full"
|
|
111
|
+
@update:model-value="(value) => setAddressFieldLabel(addressIndex, value)"
|
|
112
|
+
/>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</UCard>
|
|
118
|
+
</template>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FormForgeFieldSchema } from '../../../types/index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
field: FormForgeFieldSchema;
|
|
4
|
+
readonly?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
7
|
+
readonly: boolean;
|
|
8
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
9
|
+
declare const _default: typeof __VLS_export;
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=FormForgeBuilderAddressFieldsCard.vue.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { FormForgeFieldType, FormForgePageSchema } from '../../../types/index.js';
|
|
2
|
+
interface QuestionTypeItem {
|
|
3
|
+
label: string;
|
|
4
|
+
value: FormForgeFieldType;
|
|
5
|
+
icon?: string;
|
|
6
|
+
}
|
|
7
|
+
interface Props {
|
|
8
|
+
page: FormForgePageSchema;
|
|
9
|
+
pages: FormForgePageSchema[];
|
|
10
|
+
pageIndex: number;
|
|
11
|
+
totalPages: number;
|
|
12
|
+
selectedFieldKey?: string | null;
|
|
13
|
+
readonly?: boolean;
|
|
14
|
+
fieldTypeItems: QuestionTypeItem[];
|
|
15
|
+
}
|
|
16
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
17
|
+
"select-field": (pageKey: string, fieldKey: string) => any;
|
|
18
|
+
"move-page": (pageKey: string, direction: 1 | -1) => any;
|
|
19
|
+
"duplicate-page": (pageKey: string) => any;
|
|
20
|
+
"remove-page": (pageKey: string) => any;
|
|
21
|
+
"add-question": (pageKey: string, type: FormForgeFieldType) => any;
|
|
22
|
+
"move-field": (pageKey: string, fieldKey: string, direction: 1 | -1) => any;
|
|
23
|
+
"duplicate-field": (pageKey: string, fieldKey: string) => any;
|
|
24
|
+
"remove-field": (pageKey: string, fieldKey: string) => any;
|
|
25
|
+
"change-field-type": (pageKey: string, fieldKey: string, type: FormForgeFieldType) => any;
|
|
26
|
+
"add-field-below": (pageKey: string, fieldKey: string, type: FormForgeFieldType) => any;
|
|
27
|
+
"move-field-to-block": (pageKey: string, fieldKey: string, targetPageKey: string) => any;
|
|
28
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
29
|
+
"onSelect-field"?: ((pageKey: string, fieldKey: string) => any) | undefined;
|
|
30
|
+
"onMove-page"?: ((pageKey: string, direction: 1 | -1) => any) | undefined;
|
|
31
|
+
"onDuplicate-page"?: ((pageKey: string) => any) | undefined;
|
|
32
|
+
"onRemove-page"?: ((pageKey: string) => any) | undefined;
|
|
33
|
+
"onAdd-question"?: ((pageKey: string, type: FormForgeFieldType) => any) | undefined;
|
|
34
|
+
"onMove-field"?: ((pageKey: string, fieldKey: string, direction: 1 | -1) => any) | undefined;
|
|
35
|
+
"onDuplicate-field"?: ((pageKey: string, fieldKey: string) => any) | undefined;
|
|
36
|
+
"onRemove-field"?: ((pageKey: string, fieldKey: string) => any) | undefined;
|
|
37
|
+
"onChange-field-type"?: ((pageKey: string, fieldKey: string, type: FormForgeFieldType) => any) | undefined;
|
|
38
|
+
"onAdd-field-below"?: ((pageKey: string, fieldKey: string, type: FormForgeFieldType) => any) | undefined;
|
|
39
|
+
"onMove-field-to-block"?: ((pageKey: string, fieldKey: string, targetPageKey: string) => any) | undefined;
|
|
40
|
+
}>, {
|
|
41
|
+
readonly: boolean;
|
|
42
|
+
selectedFieldKey: string | null;
|
|
43
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
44
|
+
declare const _default: typeof __VLS_export;
|
|
45
|
+
export default _default;
|
|
46
|
+
//# sourceMappingURL=FormForgeBuilderBlockCard.vue.d.ts.map
|