@btst/plugin-form-builder 1.0.0-beta.0 → 1.2.0-beta.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/api/index.cjs +1 -0
- package/dist/api/index.d.cts +1 -1
- package/dist/api/index.d.mts +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.mjs +1 -1
- package/dist/api/operations.cjs +64 -4
- package/dist/api/operations.mjs +64 -5
- package/dist/api/plugin.cjs +8 -0
- package/dist/api/plugin.mjs +8 -0
- package/dist/api/submissions-csv.cjs +69 -0
- package/dist/api/submissions-csv.mjs +64 -0
- package/dist/client/components/forms/form-renderer.cjs +31 -2
- package/dist/client/components/forms/form-renderer.mjs +31 -2
- package/dist/client/components/forms/media-file-field.cjs +48 -0
- package/dist/client/components/forms/media-file-field.mjs +46 -0
- package/dist/client/components/index.d.cts +4 -2
- package/dist/client/components/index.d.mts +4 -2
- package/dist/client/components/index.d.ts +4 -2
- package/dist/client/components/pages/ai-schema.cjs +120 -0
- package/dist/client/components/pages/ai-schema.mjs +118 -0
- package/dist/client/components/pages/form-builder-page.internal.cjs +40 -1
- package/dist/client/components/pages/form-builder-page.internal.mjs +41 -2
- package/dist/client/components/pages/form-list-page.internal.cjs +1 -0
- package/dist/client/components/pages/form-list-page.internal.mjs +1 -0
- package/dist/client/components/pages/submissions-page.internal.cjs +40 -0
- package/dist/client/components/pages/submissions-page.internal.mjs +41 -1
- package/dist/client/components/shared/pagination.cjs +19 -0
- package/dist/client/components/shared/pagination.mjs +20 -1
- package/dist/client/hooks/form-builder-hooks.cjs +4 -0
- package/dist/client/hooks/form-builder-hooks.mjs +4 -1
- package/dist/client/hooks/index.cjs +1 -0
- package/dist/client/hooks/index.d.cts +7 -2
- package/dist/client/hooks/index.d.mts +7 -2
- package/dist/client/hooks/index.d.ts +7 -2
- package/dist/client/hooks/index.mjs +1 -1
- package/dist/client/index.d.cts +42 -3
- package/dist/client/index.d.mts +42 -3
- package/dist/client/index.d.ts +42 -3
- package/dist/permissions.cjs +8 -0
- package/dist/permissions.d.cts +6 -0
- package/dist/permissions.d.mts +6 -0
- package/dist/permissions.d.ts +6 -0
- package/dist/permissions.mjs +8 -0
- package/dist/query-keys.cjs +7 -0
- package/dist/query-keys.d.cts +29 -1
- package/dist/query-keys.d.mts +29 -1
- package/dist/query-keys.d.ts +29 -1
- package/dist/query-keys.mjs +7 -0
- package/dist/shared/{plugin-form-builder.CSP5HR2O.d.ts → plugin-form-builder.65tLgfcd.d.ts} +46 -29
- package/dist/shared/{plugin-form-builder.Bbl9NufB.d.cts → plugin-form-builder.DXdOj9vM.d.cts} +46 -29
- package/dist/shared/{plugin-form-builder.lp98rFNl.d.mts → plugin-form-builder.PWs25HN1.d.mts} +46 -29
- package/dist/shared/{plugin-form-builder.DWrQ3lRX.d.ts → plugin-form-builder.sdjcoJcH.d.cts} +15 -1
- package/dist/shared/{plugin-form-builder.DWrQ3lRX.d.cts → plugin-form-builder.sdjcoJcH.d.mts} +15 -1
- package/dist/shared/{plugin-form-builder.DWrQ3lRX.d.mts → plugin-form-builder.sdjcoJcH.d.ts} +15 -1
- package/dist/ui/src/components/auto-form/config.cjs +2 -0
- package/dist/ui/src/components/auto-form/config.mjs +2 -0
- package/dist/ui/src/components/auto-form/fields/file.cjs +68 -0
- package/dist/ui/src/components/auto-form/fields/file.mjs +63 -0
- package/dist/ui/src/components/auto-form/fields/object.cjs +9 -2
- package/dist/ui/src/components/auto-form/fields/object.mjs +9 -2
- package/dist/ui/src/components/auto-form/helpers.cjs +9 -0
- package/dist/ui/src/components/auto-form/helpers.mjs +9 -0
- package/dist/ui/src/components/auto-form/index.cjs +29 -4
- package/dist/ui/src/components/auto-form/index.mjs +31 -6
- package/dist/ui/src/components/auto-form/stepped-auto-form.cjs +34 -29
- package/dist/ui/src/components/auto-form/stepped-auto-form.mjs +35 -30
- package/dist/ui/src/components/form-builder/canvas.cjs +9 -0
- package/dist/ui/src/components/form-builder/canvas.mjs +9 -0
- package/dist/ui/src/components/form-builder/components/index.cjs +12 -0
- package/dist/ui/src/components/form-builder/components/index.mjs +12 -1
- package/dist/ui/src/components/form-builder/condition-editor.cjs +73 -0
- package/dist/ui/src/components/form-builder/condition-editor.mjs +71 -0
- package/dist/ui/src/components/form-builder/edit-field-dialog.cjs +6 -2
- package/dist/ui/src/components/form-builder/edit-field-dialog.mjs +6 -2
- package/dist/ui/src/components/form-builder/index.cjs +6 -1
- package/dist/ui/src/components/form-builder/index.mjs +6 -1
- package/dist/ui/src/components/form-builder/schema-utils.cjs +2 -0
- package/dist/ui/src/components/form-builder/schema-utils.mjs +2 -0
- package/dist/ui/src/components/form.mjs +1 -1
- package/dist/ui/src/lib/form-visibility.cjs +20 -0
- package/dist/ui/src/lib/form-visibility.mjs +18 -0
- package/dist/ui/src/lib/schema-converter.cjs +101 -0
- package/dist/ui/src/lib/schema-converter.mjs +100 -1
- package/package.json +4 -4
package/dist/api/index.cjs
CHANGED
|
@@ -11,6 +11,7 @@ const queryKeyDefs = require('./query-key-defs.cjs');
|
|
|
11
11
|
|
|
12
12
|
exports.formBuilderBackendPlugin = plugin.formBuilderBackendPlugin;
|
|
13
13
|
exports.FORM_BUILDER_LIFECYCLE_HOOK_MIGRATIONS = lifecycleMigrations.FORM_BUILDER_LIFECYCLE_HOOK_MIGRATIONS;
|
|
14
|
+
exports.ExportSubmissionsOperationInputSchema = operations.ExportSubmissionsOperationInputSchema;
|
|
14
15
|
exports.FormBuilderOperationError = operations.FormBuilderOperationError;
|
|
15
16
|
exports.createFormBuilderOperations = operations.createFormBuilderOperations;
|
|
16
17
|
exports.formBuilderPermissions = permissions.formBuilderPermissions;
|
package/dist/api/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FORM_QUERY_KEYS, a as FormBuilderApiRouter, b as FormBuilderOperationError, c as FormBuilderOperations, d as FormBuilderRouteKey, e as FormListOperationResult, S as SubmissionDetailOperationResult, f as SubmissionListOperationResult, g as SubmitOperationResult, h as createFormBuilderOperations, i as formBuilderBackendPlugin } from '../shared/plugin-form-builder.
|
|
1
|
+
export { E as ExportSubmissionsOperationInputSchema, F as FORM_QUERY_KEYS, a as FormBuilderApiRouter, b as FormBuilderOperationError, c as FormBuilderOperations, d as FormBuilderRouteKey, e as FormListOperationResult, S as SubmissionDetailOperationResult, f as SubmissionListOperationResult, g as SubmitOperationResult, h as createFormBuilderOperations, i as formBuilderBackendPlugin } from '../shared/plugin-form-builder.DXdOj9vM.cjs';
|
|
2
2
|
export { formBuilderPermissions } from '../permissions.cjs';
|
|
3
3
|
import { d as SerializedFormSubmissionSummary } from '../shared/plugin-form-builder.Cmk083dA.cjs';
|
|
4
4
|
import { SerializedForm, SerializedFormSubmissionWithData, Form, FormSubmission, SerializedFormSubmission, FormSubmissionWithForm } from '../types.cjs';
|
package/dist/api/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FORM_QUERY_KEYS, a as FormBuilderApiRouter, b as FormBuilderOperationError, c as FormBuilderOperations, d as FormBuilderRouteKey, e as FormListOperationResult, S as SubmissionDetailOperationResult, f as SubmissionListOperationResult, g as SubmitOperationResult, h as createFormBuilderOperations, i as formBuilderBackendPlugin } from '../shared/plugin-form-builder.
|
|
1
|
+
export { E as ExportSubmissionsOperationInputSchema, F as FORM_QUERY_KEYS, a as FormBuilderApiRouter, b as FormBuilderOperationError, c as FormBuilderOperations, d as FormBuilderRouteKey, e as FormListOperationResult, S as SubmissionDetailOperationResult, f as SubmissionListOperationResult, g as SubmitOperationResult, h as createFormBuilderOperations, i as formBuilderBackendPlugin } from '../shared/plugin-form-builder.PWs25HN1.mjs';
|
|
2
2
|
export { formBuilderPermissions } from '../permissions.mjs';
|
|
3
3
|
import { d as SerializedFormSubmissionSummary } from '../shared/plugin-form-builder.BZYGyFgT.mjs';
|
|
4
4
|
import { SerializedForm, SerializedFormSubmissionWithData, Form, FormSubmission, SerializedFormSubmission, FormSubmissionWithForm } from '../types.mjs';
|
package/dist/api/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { F as FORM_QUERY_KEYS, a as FormBuilderApiRouter, b as FormBuilderOperationError, c as FormBuilderOperations, d as FormBuilderRouteKey, e as FormListOperationResult, S as SubmissionDetailOperationResult, f as SubmissionListOperationResult, g as SubmitOperationResult, h as createFormBuilderOperations, i as formBuilderBackendPlugin } from '../shared/plugin-form-builder.
|
|
1
|
+
export { E as ExportSubmissionsOperationInputSchema, F as FORM_QUERY_KEYS, a as FormBuilderApiRouter, b as FormBuilderOperationError, c as FormBuilderOperations, d as FormBuilderRouteKey, e as FormListOperationResult, S as SubmissionDetailOperationResult, f as SubmissionListOperationResult, g as SubmitOperationResult, h as createFormBuilderOperations, i as formBuilderBackendPlugin } from '../shared/plugin-form-builder.65tLgfcd.js';
|
|
2
2
|
export { formBuilderPermissions } from '../permissions.js';
|
|
3
3
|
import { d as SerializedFormSubmissionSummary } from '../shared/plugin-form-builder.D258Qpb8.js';
|
|
4
4
|
import { SerializedForm, SerializedFormSubmissionWithData, Form, FormSubmission, SerializedFormSubmission, FormSubmissionWithForm } from '../types.js';
|
package/dist/api/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { formBuilderBackendPlugin } from './plugin.mjs';
|
|
2
2
|
export { FORM_BUILDER_LIFECYCLE_HOOK_MIGRATIONS } from './lifecycle-migrations.mjs';
|
|
3
|
-
export { FormBuilderOperationError, createFormBuilderOperations } from './operations.mjs';
|
|
3
|
+
export { ExportSubmissionsOperationInputSchema, FormBuilderOperationError, createFormBuilderOperations } from './operations.mjs';
|
|
4
4
|
export { formBuilderPermissions } from '../permissions.mjs';
|
|
5
5
|
export { getAllForms, getFormById, getFormBySlug, getFormSubmissions, serializeForm, serializeFormSubmission, serializeFormSubmissionSummary, serializeFormSubmissionWithData } from './getters.mjs';
|
|
6
6
|
export { FORM_QUERY_KEYS } from './query-key-defs.mjs';
|
package/dist/api/operations.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const submissionsCsv = require('./submissions-csv.cjs');
|
|
3
4
|
const api = require('@btst/stack/plugins/api');
|
|
4
5
|
const schemaConverter = require('../ui/src/lib/schema-converter.cjs');
|
|
5
6
|
const z = require('zod');
|
|
@@ -30,6 +31,9 @@ const ListSubmissionsOperationInputSchema = z.z.object({
|
|
|
30
31
|
formId: z.z.string(),
|
|
31
32
|
query: schemas.listSubmissionsQuerySchema
|
|
32
33
|
});
|
|
34
|
+
const ExportSubmissionsOperationInputSchema = z.z.object({
|
|
35
|
+
formId: z.z.string()
|
|
36
|
+
});
|
|
33
37
|
const GetSubmissionOperationInputSchema = z.z.object({
|
|
34
38
|
formId: z.z.string(),
|
|
35
39
|
submissionId: z.z.string()
|
|
@@ -749,6 +753,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
749
753
|
"FORM_NOT_ACTIVE"
|
|
750
754
|
);
|
|
751
755
|
}
|
|
756
|
+
let validatedData;
|
|
752
757
|
try {
|
|
753
758
|
const jsonSchema = JSON.parse(form.schema);
|
|
754
759
|
const validation = schemaConverter.formSchemaToZod(jsonSchema).safeParse(
|
|
@@ -762,6 +767,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
762
767
|
validation.error.issues
|
|
763
768
|
);
|
|
764
769
|
}
|
|
770
|
+
validatedData = validation.data;
|
|
765
771
|
} catch (error) {
|
|
766
772
|
if (error instanceof FormBuilderOperationError) throw error;
|
|
767
773
|
throw new FormBuilderOperationError(
|
|
@@ -775,9 +781,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
775
781
|
form.slug,
|
|
776
782
|
form.id
|
|
777
783
|
);
|
|
778
|
-
const submittedData = JSON.parse(
|
|
779
|
-
JSON.stringify(context.input.data)
|
|
780
|
-
);
|
|
784
|
+
const submittedData = JSON.parse(JSON.stringify(validatedData));
|
|
781
785
|
return adapter.transaction(async (tx) => {
|
|
782
786
|
const current = await findFormBySlug(tx, context.input.slug);
|
|
783
787
|
if (!sameFormSnapshot(current, authorized)) throw staleFormError();
|
|
@@ -796,7 +800,17 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
796
800
|
400,
|
|
797
801
|
"SUBMISSION_REJECTED"
|
|
798
802
|
);
|
|
799
|
-
const
|
|
803
|
+
const finalValidation = schemaConverter.formSchemaToZod(
|
|
804
|
+
JSON.parse(form.schema)
|
|
805
|
+
).safeParse(hookResult ?? submittedData);
|
|
806
|
+
if (!finalValidation.success)
|
|
807
|
+
throw new FormBuilderOperationError(
|
|
808
|
+
400,
|
|
809
|
+
"Validation failed",
|
|
810
|
+
"SUBMISSION_VALIDATION_FAILED",
|
|
811
|
+
finalValidation.error.issues
|
|
812
|
+
);
|
|
813
|
+
const finalData = finalValidation.data;
|
|
800
814
|
const claimed = await findFormById(tx, authorized.id);
|
|
801
815
|
if (!sameFormSnapshot(claimed, { ...authorized, updatedAt: claimedAt }) || claimed?.status !== "active") {
|
|
802
816
|
throw staleFormError();
|
|
@@ -856,6 +870,50 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
856
870
|
await notifyError(hooks, error, "submit", lifecycleContext);
|
|
857
871
|
}
|
|
858
872
|
});
|
|
873
|
+
const exportSubmissions = api.defineOperation({
|
|
874
|
+
input: ExportSubmissionsOperationInputSchema,
|
|
875
|
+
permission: permissions.formBuilderPermissions.submission.export,
|
|
876
|
+
facts: async ({ input }) => {
|
|
877
|
+
const form = await findFormById(adapter, input.formId);
|
|
878
|
+
formSnapshots.set(input, form ? snapshotForm(form) : null);
|
|
879
|
+
return {
|
|
880
|
+
formId: input.formId,
|
|
881
|
+
formExists: form !== null,
|
|
882
|
+
...form?.createdBy ? { ownerId: form.createdBy } : {}
|
|
883
|
+
};
|
|
884
|
+
},
|
|
885
|
+
execute: async ({ input }) => adapter.transaction(async (tx) => {
|
|
886
|
+
const expected = formSnapshots.get(input) ?? null;
|
|
887
|
+
const form = await findFormById(tx, input.formId);
|
|
888
|
+
if (!sameFormSnapshot(form, expected)) throw staleFormError();
|
|
889
|
+
if (!form) throw formNotFoundError();
|
|
890
|
+
const items = [];
|
|
891
|
+
let sourceCharacters = 0;
|
|
892
|
+
for (; ; ) {
|
|
893
|
+
const page = await getters.getFormSubmissions(tx, input.formId, {
|
|
894
|
+
limit: 100,
|
|
895
|
+
offset: items.length
|
|
896
|
+
});
|
|
897
|
+
if (page.total > submissionsCsv.CSV_EXPORT_MAX_ROWS) throw submissionsCsv.csvExportLimitError();
|
|
898
|
+
for (const item of page.items) {
|
|
899
|
+
sourceCharacters += item.data.length;
|
|
900
|
+
if (sourceCharacters > submissionsCsv.CSV_EXPORT_MAX_BYTES)
|
|
901
|
+
throw submissionsCsv.csvExportLimitError();
|
|
902
|
+
items.push(item);
|
|
903
|
+
}
|
|
904
|
+
if (!page.items.length || items.length >= page.total) break;
|
|
905
|
+
}
|
|
906
|
+
const current = await findFormById(tx, input.formId);
|
|
907
|
+
if (!sameFormSnapshot(current, expected)) throw staleFormError();
|
|
908
|
+
return {
|
|
909
|
+
csv: submissionsCsv.submissionsToCsv(
|
|
910
|
+
items,
|
|
911
|
+
Object.keys(JSON.parse(form.schema).properties ?? {})
|
|
912
|
+
),
|
|
913
|
+
filename: `${form.slug}-submissions.csv`
|
|
914
|
+
};
|
|
915
|
+
})
|
|
916
|
+
});
|
|
859
917
|
const listSubmissions = api.defineOperation({
|
|
860
918
|
input: ListSubmissionsOperationInputSchema,
|
|
861
919
|
permission: permissions.formBuilderPermissions.submission.read,
|
|
@@ -1067,6 +1125,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
1067
1125
|
onError: ({ error, ...context }) => notifyError(hooks, error, "deleteSubmission", hookContext(context))
|
|
1068
1126
|
});
|
|
1069
1127
|
return {
|
|
1128
|
+
exportSubmissions,
|
|
1070
1129
|
listForms,
|
|
1071
1130
|
getFormBySlug,
|
|
1072
1131
|
getFormById,
|
|
@@ -1082,6 +1141,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
1082
1141
|
}
|
|
1083
1142
|
|
|
1084
1143
|
exports.DeleteFormOperationInputSchema = DeleteFormOperationInputSchema;
|
|
1144
|
+
exports.ExportSubmissionsOperationInputSchema = ExportSubmissionsOperationInputSchema;
|
|
1085
1145
|
exports.FormBuilderOperationError = FormBuilderOperationError;
|
|
1086
1146
|
exports.GetFormByIdOperationInputSchema = GetFormByIdOperationInputSchema;
|
|
1087
1147
|
exports.GetFormBySlugOperationInputSchema = GetFormBySlugOperationInputSchema;
|
package/dist/api/operations.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CSV_EXPORT_MAX_ROWS, csvExportLimitError, CSV_EXPORT_MAX_BYTES, submissionsToCsv } from './submissions-csv.mjs';
|
|
1
2
|
import { OperationHttpError, defineOperation } from '@btst/stack/plugins/api';
|
|
2
3
|
import { formSchemaToZod } from '../ui/src/lib/schema-converter.mjs';
|
|
3
4
|
import { z } from 'zod';
|
|
@@ -28,6 +29,9 @@ const ListSubmissionsOperationInputSchema = z.object({
|
|
|
28
29
|
formId: z.string(),
|
|
29
30
|
query: listSubmissionsQuerySchema
|
|
30
31
|
});
|
|
32
|
+
const ExportSubmissionsOperationInputSchema = z.object({
|
|
33
|
+
formId: z.string()
|
|
34
|
+
});
|
|
31
35
|
const GetSubmissionOperationInputSchema = z.object({
|
|
32
36
|
formId: z.string(),
|
|
33
37
|
submissionId: z.string()
|
|
@@ -747,6 +751,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
747
751
|
"FORM_NOT_ACTIVE"
|
|
748
752
|
);
|
|
749
753
|
}
|
|
754
|
+
let validatedData;
|
|
750
755
|
try {
|
|
751
756
|
const jsonSchema = JSON.parse(form.schema);
|
|
752
757
|
const validation = formSchemaToZod(jsonSchema).safeParse(
|
|
@@ -760,6 +765,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
760
765
|
validation.error.issues
|
|
761
766
|
);
|
|
762
767
|
}
|
|
768
|
+
validatedData = validation.data;
|
|
763
769
|
} catch (error) {
|
|
764
770
|
if (error instanceof FormBuilderOperationError) throw error;
|
|
765
771
|
throw new FormBuilderOperationError(
|
|
@@ -773,9 +779,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
773
779
|
form.slug,
|
|
774
780
|
form.id
|
|
775
781
|
);
|
|
776
|
-
const submittedData = JSON.parse(
|
|
777
|
-
JSON.stringify(context.input.data)
|
|
778
|
-
);
|
|
782
|
+
const submittedData = JSON.parse(JSON.stringify(validatedData));
|
|
779
783
|
return adapter.transaction(async (tx) => {
|
|
780
784
|
const current = await findFormBySlug(tx, context.input.slug);
|
|
781
785
|
if (!sameFormSnapshot(current, authorized)) throw staleFormError();
|
|
@@ -794,7 +798,17 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
794
798
|
400,
|
|
795
799
|
"SUBMISSION_REJECTED"
|
|
796
800
|
);
|
|
797
|
-
const
|
|
801
|
+
const finalValidation = formSchemaToZod(
|
|
802
|
+
JSON.parse(form.schema)
|
|
803
|
+
).safeParse(hookResult ?? submittedData);
|
|
804
|
+
if (!finalValidation.success)
|
|
805
|
+
throw new FormBuilderOperationError(
|
|
806
|
+
400,
|
|
807
|
+
"Validation failed",
|
|
808
|
+
"SUBMISSION_VALIDATION_FAILED",
|
|
809
|
+
finalValidation.error.issues
|
|
810
|
+
);
|
|
811
|
+
const finalData = finalValidation.data;
|
|
798
812
|
const claimed = await findFormById(tx, authorized.id);
|
|
799
813
|
if (!sameFormSnapshot(claimed, { ...authorized, updatedAt: claimedAt }) || claimed?.status !== "active") {
|
|
800
814
|
throw staleFormError();
|
|
@@ -854,6 +868,50 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
854
868
|
await notifyError(hooks, error, "submit", lifecycleContext);
|
|
855
869
|
}
|
|
856
870
|
});
|
|
871
|
+
const exportSubmissions = defineOperation({
|
|
872
|
+
input: ExportSubmissionsOperationInputSchema,
|
|
873
|
+
permission: formBuilderPermissions.submission.export,
|
|
874
|
+
facts: async ({ input }) => {
|
|
875
|
+
const form = await findFormById(adapter, input.formId);
|
|
876
|
+
formSnapshots.set(input, form ? snapshotForm(form) : null);
|
|
877
|
+
return {
|
|
878
|
+
formId: input.formId,
|
|
879
|
+
formExists: form !== null,
|
|
880
|
+
...form?.createdBy ? { ownerId: form.createdBy } : {}
|
|
881
|
+
};
|
|
882
|
+
},
|
|
883
|
+
execute: async ({ input }) => adapter.transaction(async (tx) => {
|
|
884
|
+
const expected = formSnapshots.get(input) ?? null;
|
|
885
|
+
const form = await findFormById(tx, input.formId);
|
|
886
|
+
if (!sameFormSnapshot(form, expected)) throw staleFormError();
|
|
887
|
+
if (!form) throw formNotFoundError();
|
|
888
|
+
const items = [];
|
|
889
|
+
let sourceCharacters = 0;
|
|
890
|
+
for (; ; ) {
|
|
891
|
+
const page = await getFormSubmissions(tx, input.formId, {
|
|
892
|
+
limit: 100,
|
|
893
|
+
offset: items.length
|
|
894
|
+
});
|
|
895
|
+
if (page.total > CSV_EXPORT_MAX_ROWS) throw csvExportLimitError();
|
|
896
|
+
for (const item of page.items) {
|
|
897
|
+
sourceCharacters += item.data.length;
|
|
898
|
+
if (sourceCharacters > CSV_EXPORT_MAX_BYTES)
|
|
899
|
+
throw csvExportLimitError();
|
|
900
|
+
items.push(item);
|
|
901
|
+
}
|
|
902
|
+
if (!page.items.length || items.length >= page.total) break;
|
|
903
|
+
}
|
|
904
|
+
const current = await findFormById(tx, input.formId);
|
|
905
|
+
if (!sameFormSnapshot(current, expected)) throw staleFormError();
|
|
906
|
+
return {
|
|
907
|
+
csv: submissionsToCsv(
|
|
908
|
+
items,
|
|
909
|
+
Object.keys(JSON.parse(form.schema).properties ?? {})
|
|
910
|
+
),
|
|
911
|
+
filename: `${form.slug}-submissions.csv`
|
|
912
|
+
};
|
|
913
|
+
})
|
|
914
|
+
});
|
|
857
915
|
const listSubmissions = defineOperation({
|
|
858
916
|
input: ListSubmissionsOperationInputSchema,
|
|
859
917
|
permission: formBuilderPermissions.submission.read,
|
|
@@ -1065,6 +1123,7 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
1065
1123
|
onError: ({ error, ...context }) => notifyError(hooks, error, "deleteSubmission", hookContext(context))
|
|
1066
1124
|
});
|
|
1067
1125
|
return {
|
|
1126
|
+
exportSubmissions,
|
|
1068
1127
|
listForms,
|
|
1069
1128
|
getFormBySlug,
|
|
1070
1129
|
getFormById,
|
|
@@ -1079,4 +1138,4 @@ function createFormBuilderOperations(adapter, hooks) {
|
|
|
1079
1138
|
};
|
|
1080
1139
|
}
|
|
1081
1140
|
|
|
1082
|
-
export { DeleteFormOperationInputSchema, FormBuilderOperationError, GetFormByIdOperationInputSchema, GetFormBySlugOperationInputSchema, GetFormForUpdateOperationInputSchema, GetSubmissionOperationInputSchema, ListSubmissionsOperationInputSchema, SubmitFormOperationInputSchema, UpdateFormOperationInputSchema, createFormBuilderOperations };
|
|
1141
|
+
export { DeleteFormOperationInputSchema, ExportSubmissionsOperationInputSchema, FormBuilderOperationError, GetFormByIdOperationInputSchema, GetFormBySlugOperationInputSchema, GetFormForUpdateOperationInputSchema, GetSubmissionOperationInputSchema, ListSubmissionsOperationInputSchema, SubmitFormOperationInputSchema, UpdateFormOperationInputSchema, createFormBuilderOperations };
|
package/dist/api/plugin.cjs
CHANGED
|
@@ -158,6 +158,13 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
|
|
|
158
158
|
query: ctx.query
|
|
159
159
|
}))
|
|
160
160
|
);
|
|
161
|
+
const exportSubmissions = api.createEndpoint(
|
|
162
|
+
"/forms/:formId/submissions/export",
|
|
163
|
+
{ method: "POST", requireRequest: true },
|
|
164
|
+
operations$1.exportSubmissions.route((ctx) => ({
|
|
165
|
+
formId: ctx.params.formId
|
|
166
|
+
}))
|
|
167
|
+
);
|
|
161
168
|
const getSubmission = api.createEndpoint(
|
|
162
169
|
"/forms/:formId/submissions/:subId",
|
|
163
170
|
{ method: "GET", requireRequest: true },
|
|
@@ -175,6 +182,7 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
|
|
|
175
182
|
}))
|
|
176
183
|
);
|
|
177
184
|
return {
|
|
185
|
+
exportSubmissions,
|
|
178
186
|
listForms,
|
|
179
187
|
getFormBySlug: getFormBySlugEndpoint,
|
|
180
188
|
getFormById: getFormByIdEndpoint,
|
package/dist/api/plugin.mjs
CHANGED
|
@@ -157,6 +157,13 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
|
|
|
157
157
|
query: ctx.query
|
|
158
158
|
}))
|
|
159
159
|
);
|
|
160
|
+
const exportSubmissions = createEndpoint(
|
|
161
|
+
"/forms/:formId/submissions/export",
|
|
162
|
+
{ method: "POST", requireRequest: true },
|
|
163
|
+
operations.exportSubmissions.route((ctx) => ({
|
|
164
|
+
formId: ctx.params.formId
|
|
165
|
+
}))
|
|
166
|
+
);
|
|
160
167
|
const getSubmission = createEndpoint(
|
|
161
168
|
"/forms/:formId/submissions/:subId",
|
|
162
169
|
{ method: "GET", requireRequest: true },
|
|
@@ -174,6 +181,7 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
|
|
|
174
181
|
}))
|
|
175
182
|
);
|
|
176
183
|
return {
|
|
184
|
+
exportSubmissions,
|
|
177
185
|
listForms,
|
|
178
186
|
getFormBySlug: getFormBySlugEndpoint,
|
|
179
187
|
getFormById: getFormByIdEndpoint,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('@btst/stack/plugins/api');
|
|
4
|
+
|
|
5
|
+
const CSV_EXPORT_MAX_ROWS = 1e4;
|
|
6
|
+
const CSV_EXPORT_MAX_BYTES = 10 * 1024 * 1024;
|
|
7
|
+
const CSV_EXPORT_MAX_COLUMNS = 1e3;
|
|
8
|
+
const CSV_EXPORT_MAX_CELLS = 1e6;
|
|
9
|
+
function csvExportLimitError() {
|
|
10
|
+
return new api.OperationHttpError(
|
|
11
|
+
413,
|
|
12
|
+
"CSV export exceeds the supported row, column, cell or 10 MiB size limit.",
|
|
13
|
+
"FORM_EXPORT_TOO_LARGE"
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
function csvCell(value) {
|
|
17
|
+
let text = value == null ? "" : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
18
|
+
if (/^[\s]*[=+\-@]/.test(text) || /^[\t\r\n]/.test(text)) text = `'${text}`;
|
|
19
|
+
return `"${text.replaceAll('"', '""')}"`;
|
|
20
|
+
}
|
|
21
|
+
function submissionsToCsv(submissions, fieldNames) {
|
|
22
|
+
const encoder = new TextEncoder();
|
|
23
|
+
const columns = new Set(fieldNames);
|
|
24
|
+
const rows = [];
|
|
25
|
+
let sourceBytes = 0;
|
|
26
|
+
if (submissions.length > CSV_EXPORT_MAX_ROWS || columns.size > CSV_EXPORT_MAX_COLUMNS || columns.size * submissions.length > CSV_EXPORT_MAX_CELLS)
|
|
27
|
+
throw csvExportLimitError();
|
|
28
|
+
for (const submission of submissions) {
|
|
29
|
+
sourceBytes += encoder.encode(submission.data).byteLength;
|
|
30
|
+
if (sourceBytes > CSV_EXPORT_MAX_BYTES) throw csvExportLimitError();
|
|
31
|
+
const data = JSON.parse(submission.data);
|
|
32
|
+
for (const key of Object.keys(data)) {
|
|
33
|
+
columns.add(key);
|
|
34
|
+
if (columns.size > CSV_EXPORT_MAX_COLUMNS || columns.size * submissions.length > CSV_EXPORT_MAX_CELLS)
|
|
35
|
+
throw csvExportLimitError();
|
|
36
|
+
}
|
|
37
|
+
rows.push({ submission, data });
|
|
38
|
+
}
|
|
39
|
+
const fields = [...columns];
|
|
40
|
+
const lines = [];
|
|
41
|
+
let outputBytes = 0;
|
|
42
|
+
const appendRow = (values) => {
|
|
43
|
+
const line = values.map(csvCell).join(",") + "\r\n";
|
|
44
|
+
outputBytes += encoder.encode(line).byteLength;
|
|
45
|
+
if (outputBytes > CSV_EXPORT_MAX_BYTES) throw csvExportLimitError();
|
|
46
|
+
lines.push(line);
|
|
47
|
+
};
|
|
48
|
+
const header = [
|
|
49
|
+
"id",
|
|
50
|
+
"submittedAt",
|
|
51
|
+
...fields.map((field) => `data.${field}`)
|
|
52
|
+
];
|
|
53
|
+
appendRow(header);
|
|
54
|
+
for (const { submission, data } of rows) {
|
|
55
|
+
appendRow([
|
|
56
|
+
submission.id,
|
|
57
|
+
new Date(submission.submittedAt).toISOString(),
|
|
58
|
+
...fields.map(
|
|
59
|
+
(field) => Object.hasOwn(data, field) ? data[field] : void 0
|
|
60
|
+
)
|
|
61
|
+
]);
|
|
62
|
+
}
|
|
63
|
+
return lines.join("");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
exports.CSV_EXPORT_MAX_BYTES = CSV_EXPORT_MAX_BYTES;
|
|
67
|
+
exports.CSV_EXPORT_MAX_ROWS = CSV_EXPORT_MAX_ROWS;
|
|
68
|
+
exports.csvExportLimitError = csvExportLimitError;
|
|
69
|
+
exports.submissionsToCsv = submissionsToCsv;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { OperationHttpError } from '@btst/stack/plugins/api';
|
|
2
|
+
|
|
3
|
+
const CSV_EXPORT_MAX_ROWS = 1e4;
|
|
4
|
+
const CSV_EXPORT_MAX_BYTES = 10 * 1024 * 1024;
|
|
5
|
+
const CSV_EXPORT_MAX_COLUMNS = 1e3;
|
|
6
|
+
const CSV_EXPORT_MAX_CELLS = 1e6;
|
|
7
|
+
function csvExportLimitError() {
|
|
8
|
+
return new OperationHttpError(
|
|
9
|
+
413,
|
|
10
|
+
"CSV export exceeds the supported row, column, cell or 10 MiB size limit.",
|
|
11
|
+
"FORM_EXPORT_TOO_LARGE"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
function csvCell(value) {
|
|
15
|
+
let text = value == null ? "" : typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
16
|
+
if (/^[\s]*[=+\-@]/.test(text) || /^[\t\r\n]/.test(text)) text = `'${text}`;
|
|
17
|
+
return `"${text.replaceAll('"', '""')}"`;
|
|
18
|
+
}
|
|
19
|
+
function submissionsToCsv(submissions, fieldNames) {
|
|
20
|
+
const encoder = new TextEncoder();
|
|
21
|
+
const columns = new Set(fieldNames);
|
|
22
|
+
const rows = [];
|
|
23
|
+
let sourceBytes = 0;
|
|
24
|
+
if (submissions.length > CSV_EXPORT_MAX_ROWS || columns.size > CSV_EXPORT_MAX_COLUMNS || columns.size * submissions.length > CSV_EXPORT_MAX_CELLS)
|
|
25
|
+
throw csvExportLimitError();
|
|
26
|
+
for (const submission of submissions) {
|
|
27
|
+
sourceBytes += encoder.encode(submission.data).byteLength;
|
|
28
|
+
if (sourceBytes > CSV_EXPORT_MAX_BYTES) throw csvExportLimitError();
|
|
29
|
+
const data = JSON.parse(submission.data);
|
|
30
|
+
for (const key of Object.keys(data)) {
|
|
31
|
+
columns.add(key);
|
|
32
|
+
if (columns.size > CSV_EXPORT_MAX_COLUMNS || columns.size * submissions.length > CSV_EXPORT_MAX_CELLS)
|
|
33
|
+
throw csvExportLimitError();
|
|
34
|
+
}
|
|
35
|
+
rows.push({ submission, data });
|
|
36
|
+
}
|
|
37
|
+
const fields = [...columns];
|
|
38
|
+
const lines = [];
|
|
39
|
+
let outputBytes = 0;
|
|
40
|
+
const appendRow = (values) => {
|
|
41
|
+
const line = values.map(csvCell).join(",") + "\r\n";
|
|
42
|
+
outputBytes += encoder.encode(line).byteLength;
|
|
43
|
+
if (outputBytes > CSV_EXPORT_MAX_BYTES) throw csvExportLimitError();
|
|
44
|
+
lines.push(line);
|
|
45
|
+
};
|
|
46
|
+
const header = [
|
|
47
|
+
"id",
|
|
48
|
+
"submittedAt",
|
|
49
|
+
...fields.map((field) => `data.${field}`)
|
|
50
|
+
];
|
|
51
|
+
appendRow(header);
|
|
52
|
+
for (const { submission, data } of rows) {
|
|
53
|
+
appendRow([
|
|
54
|
+
submission.id,
|
|
55
|
+
new Date(submission.submittedAt).toISOString(),
|
|
56
|
+
...fields.map(
|
|
57
|
+
(field) => Object.hasOwn(data, field) ? data[field] : void 0
|
|
58
|
+
)
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
return lines.join("");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { CSV_EXPORT_MAX_BYTES, CSV_EXPORT_MAX_ROWS, csvExportLimitError, submissionsToCsv };
|
|
@@ -13,6 +13,7 @@ const formBuilderHooks = require('../../hooks/form-builder-hooks.cjs');
|
|
|
13
13
|
const permissions = require('../../../permissions.cjs');
|
|
14
14
|
const constants = require('../../constants.cjs');
|
|
15
15
|
const utils = require('../../../utils.cjs');
|
|
16
|
+
const mediaFileField = require('./media-file-field.cjs');
|
|
16
17
|
|
|
17
18
|
function DefaultLoadingComponent() {
|
|
18
19
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
@@ -49,6 +50,7 @@ function DefaultSuccessComponent({ message }) {
|
|
|
49
50
|
}
|
|
50
51
|
function FormRenderer({
|
|
51
52
|
slug,
|
|
53
|
+
onUpload: propOnUpload,
|
|
52
54
|
onSuccess,
|
|
53
55
|
onError,
|
|
54
56
|
fieldComponents: propFieldComponents,
|
|
@@ -61,6 +63,10 @@ function FormRenderer({
|
|
|
61
63
|
const t = context.useTranslate();
|
|
62
64
|
const {
|
|
63
65
|
fieldComponents: overrideFieldComponents,
|
|
66
|
+
onUpload: overrideOnUpload,
|
|
67
|
+
uploadFile,
|
|
68
|
+
imagePicker,
|
|
69
|
+
imageInputField,
|
|
64
70
|
localization,
|
|
65
71
|
classNames
|
|
66
72
|
} = context.usePluginOverrides(constants.FORM_BUILDER_PLUGIN_ID);
|
|
@@ -73,10 +79,17 @@ function FormRenderer({
|
|
|
73
79
|
);
|
|
74
80
|
const mergedFieldComponents = React.useMemo(
|
|
75
81
|
() => ({
|
|
82
|
+
...!propOnUpload && (imagePicker || imageInputField) ? { file: mediaFileField.MediaFileField } : {},
|
|
76
83
|
...overrideFieldComponents,
|
|
77
84
|
...propFieldComponents
|
|
78
85
|
}),
|
|
79
|
-
[
|
|
86
|
+
[
|
|
87
|
+
imagePicker,
|
|
88
|
+
imageInputField,
|
|
89
|
+
overrideFieldComponents,
|
|
90
|
+
propFieldComponents,
|
|
91
|
+
propOnUpload
|
|
92
|
+
]
|
|
80
93
|
);
|
|
81
94
|
const { zodSchema, fieldConfig } = React.useMemo(() => {
|
|
82
95
|
if (!form?.schema) {
|
|
@@ -89,11 +102,27 @@ function FormRenderer({
|
|
|
89
102
|
parsedSchema,
|
|
90
103
|
mergedFieldComponents
|
|
91
104
|
);
|
|
105
|
+
const applyUpload = (fields) => {
|
|
106
|
+
for (const field of Object.values(fields)) {
|
|
107
|
+
if (field.fieldType === "file")
|
|
108
|
+
field.onUpload = propOnUpload ?? uploadFile ?? overrideOnUpload;
|
|
109
|
+
for (const value of Object.values(field))
|
|
110
|
+
if (value && typeof value === "object" && !Array.isArray(value))
|
|
111
|
+
applyUpload({ child: value });
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
applyUpload(config);
|
|
92
115
|
return { zodSchema: zod, fieldConfig: config };
|
|
93
116
|
} catch {
|
|
94
117
|
return { zodSchema: null, fieldConfig: {} };
|
|
95
118
|
}
|
|
96
|
-
}, [
|
|
119
|
+
}, [
|
|
120
|
+
form?.schema,
|
|
121
|
+
mergedFieldComponents,
|
|
122
|
+
propOnUpload,
|
|
123
|
+
uploadFile,
|
|
124
|
+
overrideOnUpload
|
|
125
|
+
]);
|
|
97
126
|
const handleSubmit = async (data) => {
|
|
98
127
|
try {
|
|
99
128
|
const result = await submitMutation.mutateAsync({ data });
|
|
@@ -11,6 +11,7 @@ import { useFormBySlug, useSubmitForm } from '../../hooks/form-builder-hooks.mjs
|
|
|
11
11
|
import { formBuilderPermissions } from '../../../permissions.mjs';
|
|
12
12
|
import { FORM_BUILDER_PLUGIN_ID } from '../../constants.mjs';
|
|
13
13
|
import { cn } from '../../../utils.mjs';
|
|
14
|
+
import { MediaFileField } from './media-file-field.mjs';
|
|
14
15
|
|
|
15
16
|
function DefaultLoadingComponent() {
|
|
16
17
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
@@ -47,6 +48,7 @@ function DefaultSuccessComponent({ message }) {
|
|
|
47
48
|
}
|
|
48
49
|
function FormRenderer({
|
|
49
50
|
slug,
|
|
51
|
+
onUpload: propOnUpload,
|
|
50
52
|
onSuccess,
|
|
51
53
|
onError,
|
|
52
54
|
fieldComponents: propFieldComponents,
|
|
@@ -59,6 +61,10 @@ function FormRenderer({
|
|
|
59
61
|
const t = useTranslate();
|
|
60
62
|
const {
|
|
61
63
|
fieldComponents: overrideFieldComponents,
|
|
64
|
+
onUpload: overrideOnUpload,
|
|
65
|
+
uploadFile,
|
|
66
|
+
imagePicker,
|
|
67
|
+
imageInputField,
|
|
62
68
|
localization,
|
|
63
69
|
classNames
|
|
64
70
|
} = usePluginOverrides(FORM_BUILDER_PLUGIN_ID);
|
|
@@ -71,10 +77,17 @@ function FormRenderer({
|
|
|
71
77
|
);
|
|
72
78
|
const mergedFieldComponents = useMemo(
|
|
73
79
|
() => ({
|
|
80
|
+
...!propOnUpload && (imagePicker || imageInputField) ? { file: MediaFileField } : {},
|
|
74
81
|
...overrideFieldComponents,
|
|
75
82
|
...propFieldComponents
|
|
76
83
|
}),
|
|
77
|
-
[
|
|
84
|
+
[
|
|
85
|
+
imagePicker,
|
|
86
|
+
imageInputField,
|
|
87
|
+
overrideFieldComponents,
|
|
88
|
+
propFieldComponents,
|
|
89
|
+
propOnUpload
|
|
90
|
+
]
|
|
78
91
|
);
|
|
79
92
|
const { zodSchema, fieldConfig } = useMemo(() => {
|
|
80
93
|
if (!form?.schema) {
|
|
@@ -87,11 +100,27 @@ function FormRenderer({
|
|
|
87
100
|
parsedSchema,
|
|
88
101
|
mergedFieldComponents
|
|
89
102
|
);
|
|
103
|
+
const applyUpload = (fields) => {
|
|
104
|
+
for (const field of Object.values(fields)) {
|
|
105
|
+
if (field.fieldType === "file")
|
|
106
|
+
field.onUpload = propOnUpload ?? uploadFile ?? overrideOnUpload;
|
|
107
|
+
for (const value of Object.values(field))
|
|
108
|
+
if (value && typeof value === "object" && !Array.isArray(value))
|
|
109
|
+
applyUpload({ child: value });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
applyUpload(config);
|
|
90
113
|
return { zodSchema: zod, fieldConfig: config };
|
|
91
114
|
} catch {
|
|
92
115
|
return { zodSchema: null, fieldConfig: {} };
|
|
93
116
|
}
|
|
94
|
-
}, [
|
|
117
|
+
}, [
|
|
118
|
+
form?.schema,
|
|
119
|
+
mergedFieldComponents,
|
|
120
|
+
propOnUpload,
|
|
121
|
+
uploadFile,
|
|
122
|
+
overrideOnUpload
|
|
123
|
+
]);
|
|
95
124
|
const handleSubmit = async (data) => {
|
|
96
125
|
try {
|
|
97
126
|
const result = await submitMutation.mutateAsync({ data });
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const jsxRuntime = require('react/jsx-runtime');
|
|
5
|
+
const reactHookForm = require('react-hook-form');
|
|
6
|
+
const context = require('@btst/stack/context');
|
|
7
|
+
const form = require('../../../ui/src/components/form.cjs');
|
|
8
|
+
const label = require('../../../ui/src/components/auto-form/common/label.cjs');
|
|
9
|
+
const tooltip = require('../../../ui/src/components/auto-form/common/tooltip.cjs');
|
|
10
|
+
const constants = require('../../constants.cjs');
|
|
11
|
+
|
|
12
|
+
function MediaFileField({
|
|
13
|
+
field,
|
|
14
|
+
fieldProps,
|
|
15
|
+
fieldConfigItem,
|
|
16
|
+
label: label$1,
|
|
17
|
+
isRequired
|
|
18
|
+
}) {
|
|
19
|
+
const form$1 = reactHookForm.useFormContext();
|
|
20
|
+
const { imageInputField: ImageInput, imagePicker: ImagePicker } = context.usePluginOverrides(constants.FORM_BUILDER_PLUGIN_ID);
|
|
21
|
+
const select = (url) => {
|
|
22
|
+
if (fieldProps.disabled || form$1.formState.isSubmitting) return;
|
|
23
|
+
field.onChange(url);
|
|
24
|
+
void form$1.trigger(field.name);
|
|
25
|
+
};
|
|
26
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(form.FormItem, { children: [
|
|
27
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28
|
+
label,
|
|
29
|
+
{
|
|
30
|
+
label: fieldConfigItem.label || label$1,
|
|
31
|
+
isRequired
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
/* @__PURE__ */ jsxRuntime.jsx(form.FormControl, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
35
|
+
"div",
|
|
36
|
+
{
|
|
37
|
+
role: "group",
|
|
38
|
+
"aria-label": fieldConfigItem.label || label$1,
|
|
39
|
+
inert: fieldProps.disabled || form$1.formState.isSubmitting,
|
|
40
|
+
children: ImageInput ? /* @__PURE__ */ jsxRuntime.jsx(ImageInput, { value: field.value ?? "", onChange: select }) : ImagePicker ? /* @__PURE__ */ jsxRuntime.jsx(ImagePicker, { onSelect: select }) : null
|
|
41
|
+
}
|
|
42
|
+
) }),
|
|
43
|
+
/* @__PURE__ */ jsxRuntime.jsx(tooltip, { fieldConfigItem }),
|
|
44
|
+
/* @__PURE__ */ jsxRuntime.jsx(form.FormMessage, {})
|
|
45
|
+
] });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
exports.MediaFileField = MediaFileField;
|