@duke333/builder-ui 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -29,7 +29,8 @@ function createBuilderApiClient(rootTransport, options = {}) {
29
29
  get: (value, requestOptions) => rootTransport.get(path(value), requestOptions),
30
30
  post: (value, body, requestOptions) => rootTransport.post(path(value), body, requestOptions),
31
31
  patch: (value, body, requestOptions) => rootTransport.patch(path(value), body, requestOptions),
32
- delete: (value, requestOptions) => rootTransport.delete(path(value), requestOptions)
32
+ delete: (value, requestOptions) => rootTransport.delete(path(value), requestOptions),
33
+ upload: rootTransport.upload ? (value, body, requestOptions) => rootTransport.upload(path(value), body, requestOptions) : void 0
33
34
  };
34
35
  return {
35
36
  listBuilderForms: (query) => transport.get("/builder/forms", {
@@ -104,7 +105,23 @@ function createBuilderApiClient(rootTransport, options = {}) {
104
105
  ),
105
106
  deleteBuilderViewEntry: (viewId, id) => transport.delete(
106
107
  `/builder/runtime/views/${encodeURIComponent(viewId)}/entries/${encodeURIComponent(id)}`
107
- )
108
+ ),
109
+ presignRuntimeBuilderFile: (context, fieldKey, input) => {
110
+ const owner = context.viewId ? `views/${encodeURIComponent(context.viewId)}` : `forms/${encodeURIComponent(context.formId ?? "")}`;
111
+ return transport.post(
112
+ `/builder/runtime/${owner}/fields/${encodeURIComponent(fieldKey)}/files/presign`,
113
+ input
114
+ );
115
+ },
116
+ uploadRuntimeBuilderFile: (context, fieldKey, file) => {
117
+ if (!transport.upload) throw new Error("Builder transport server file upload \u0434\u044D\u043C\u0436\u0438\u0445\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
118
+ const owner = context.viewId ? `views/${encodeURIComponent(context.viewId)}` : `forms/${encodeURIComponent(context.formId ?? "")}`;
119
+ return transport.upload(
120
+ `/builder/runtime/${owner}/fields/${encodeURIComponent(fieldKey)}/files/upload`,
121
+ file,
122
+ { contentType: file.type }
123
+ );
124
+ }
108
125
  };
109
126
  }
110
127
 
@@ -136,12 +153,30 @@ function createBuilderKeys() {
136
153
  }
137
154
  function createBuilderHooks(client) {
138
155
  const builderKeys = createBuilderKeys();
156
+ function isRuntimeEntryListCache(value) {
157
+ return typeof value === "object" && value !== null && "items" in value && Array.isArray(value.items) && "total" in value;
158
+ }
159
+ function replaceCachedRuntimeViewEntry(queryClient, viewId, entry) {
160
+ queryClient.setQueriesData(
161
+ { queryKey: [...builderKeys.runtimeView(viewId), "entries"] },
162
+ (current) => {
163
+ if (!isRuntimeEntryListCache(current)) return current;
164
+ return {
165
+ ...current,
166
+ items: current.items.map((item) => item.id === entry.id ? entry : item)
167
+ };
168
+ }
169
+ );
170
+ }
139
171
  function invalidateRuntimeViewEntries(queryClient, viewId) {
140
172
  return Promise.all([
141
173
  queryClient.invalidateQueries({ queryKey: builderKeys.runtimeView(viewId) }),
142
174
  queryClient.invalidateQueries({ queryKey: [...builderKeys.runtimeView(viewId), "entries"] })
143
175
  ]);
144
176
  }
177
+ function invalidateAllRuntimeViewEntries(queryClient) {
178
+ return queryClient.invalidateQueries({ queryKey: ["builder", "runtime", "view"] });
179
+ }
145
180
  function useBuilderDbTables() {
146
181
  return useQuery({ queryKey: builderKeys.dbTables(), queryFn: client.listBuilderDbTables });
147
182
  }
@@ -352,14 +387,20 @@ function createBuilderHooks(client) {
352
387
  viewId,
353
388
  input
354
389
  ),
355
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
390
+ onSuccess: (entry) => {
391
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
392
+ return invalidateRuntimeViewEntries(queryClient, viewId);
393
+ }
356
394
  });
357
395
  }
358
396
  function useCreateCompositeBuilderViewEntry(viewId) {
359
397
  const queryClient = useQueryClient();
360
398
  return useMutation({
361
399
  mutationFn: (input) => client.createCompositeBuilderViewEntry(viewId, input),
362
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
400
+ onSuccess: (entry) => {
401
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
402
+ return invalidateAllRuntimeViewEntries(queryClient);
403
+ }
363
404
  });
364
405
  }
365
406
  function useUpdateCompositeBuilderViewEntry(viewId) {
@@ -369,7 +410,10 @@ function createBuilderHooks(client) {
369
410
  id,
370
411
  input
371
412
  }) => client.updateCompositeBuilderViewEntry(viewId, id, input),
372
- onSuccess: () => invalidateRuntimeViewEntries(queryClient, viewId)
413
+ onSuccess: (entry) => {
414
+ replaceCachedRuntimeViewEntry(queryClient, viewId, entry);
415
+ return invalidateAllRuntimeViewEntries(queryClient);
416
+ }
373
417
  });
374
418
  }
375
419
  function useDeleteBuilderViewEntry(id) {
@@ -470,11 +514,49 @@ function builderErrorMessage(error, fallback) {
470
514
  }
471
515
 
472
516
  // src/ready/BuilderRuntimeComponents.tsx
473
- import { useMemo as useMemo4, useState as useState5 } from "react";
517
+ import { useMemo as useMemo4, useRef as useRef7, useState as useState7 } from "react";
474
518
  import { FormProvider as FormProvider2, useForm as useForm2 } from "react-hook-form";
475
519
 
520
+ // src/richText.ts
521
+ var emptyDocument = { type: "doc", content: [{ type: "paragraph" }] };
522
+ function isRichTextDocument(value) {
523
+ return typeof value === "object" && value !== null && "type" in value && value.type === "doc";
524
+ }
525
+ function plainTextDocument(value) {
526
+ const lines = value.split(/\r?\n/);
527
+ return {
528
+ type: "doc",
529
+ content: lines.map(
530
+ (line) => line ? { type: "paragraph", content: [{ type: "text", text: line }] } : { type: "paragraph" }
531
+ )
532
+ };
533
+ }
534
+ function toRichTextDocument(value) {
535
+ if (isRichTextDocument(value)) return value;
536
+ if (typeof value !== "string" || !value.trim()) return emptyDocument;
537
+ try {
538
+ const parsed = JSON.parse(value);
539
+ if (isRichTextDocument(parsed)) return parsed;
540
+ } catch {
541
+ }
542
+ return plainTextDocument(value);
543
+ }
544
+ function collectPlainText(node, output) {
545
+ if (node.type === "text" && typeof node.text === "string") output.push(node.text);
546
+ if (node.type === "hardBreak") output.push("\n");
547
+ for (const child of node.content ?? []) collectPlainText(child, output);
548
+ if (["paragraph", "heading", "listItem", "blockquote"].includes(node.type)) output.push("\n");
549
+ }
550
+ function richTextToPlainText(value) {
551
+ const output = [];
552
+ for (const node of toRichTextDocument(value).content ?? []) collectPlainText(node, output);
553
+ return output.join("").replace(/\n{3,}/g, "\n\n").trim();
554
+ }
555
+
476
556
  // src/runtime/runtimeUtils.ts
477
557
  function emptyFieldValue(field) {
558
+ if (field.defaultValue !== void 0) return field.defaultValue;
559
+ if (field.type === "file" && field.multiple) return [];
478
560
  return field.type === "checkbox" ? false : "";
479
561
  }
480
562
  function createBuilderFormDefaultValues(schema) {
@@ -500,19 +582,277 @@ function formatBuilderRuntimeValue(value, locale = "mn-MN") {
500
582
  }
501
583
 
502
584
  // src/ready/ReadyFields.tsx
503
- import { useRef as useRef2 } from "react";
504
- import { useFormContext, useWatch } from "react-hook-form";
585
+ import { useId as useId2, useRef as useRef4, useState as useState3 } from "react";
586
+ import { useFormContext as useFormContext3, useWatch as useWatch3 } from "react-hook-form";
587
+
588
+ // src/ready/ReadyFileField.tsx
589
+ import { useId, useRef as useRef2, useState as useState2 } from "react";
590
+ import {
591
+ useFormContext,
592
+ useWatch
593
+ } from "react-hook-form";
505
594
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
595
+ function acceptedTypes(field) {
596
+ return field.contentKind === "image" ? "image/jpeg,image/png,image/webp,image/gif" : "application/pdf";
597
+ }
598
+ function urlsFrom(value) {
599
+ if (typeof value === "string" && value) return [value];
600
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
601
+ }
602
+ function ReadyFileField({ field, formId, viewId, name }) {
603
+ const { client, notify } = useBuilderRuntime();
604
+ const form = useFormContext();
605
+ const inputId = useId();
606
+ const inputRef = useRef2(null);
607
+ const [uploading, setUploading] = useState2(false);
608
+ const value = useWatch({ control: form.control, name });
609
+ const urls = urlsFrom(value);
610
+ const error = form.getFieldState(name, form.formState).error;
611
+ const setUrls = (next) => form.setValue(
612
+ name,
613
+ field.multiple ? next : next[0] ?? "",
614
+ { shouldDirty: true, shouldValidate: true }
615
+ );
616
+ async function upload(files) {
617
+ if (!files?.length || !field.storage || !field.contentKind || !formId && !viewId) return;
618
+ const selected = Array.from(files);
619
+ if (!field.multiple) selected.splice(1);
620
+ setUploading(true);
621
+ try {
622
+ const uploaded = [];
623
+ for (const file of selected) {
624
+ if (field.maxBytes && file.size > field.maxBytes) throw new Error("\u0424\u0430\u0439\u043B \u0437\u04E9\u0432\u0448\u04E9\u04E9\u0440\u04E9\u0433\u0434\u0441\u04E9\u043D \u0445\u044D\u043C\u0436\u044D\u044D\u043D\u044D\u044D\u0441 \u0442\u043E\u043C \u0431\u0430\u0439\u043D\u0430");
625
+ const context = viewId ? { viewId } : { formId };
626
+ if (field.storage === "s3") {
627
+ const presign = await client.presignRuntimeBuilderFile(context, field.key, { contentType: file.type, contentLength: file.size });
628
+ const response = await fetch(presign.uploadUrl, { method: "PUT", body: file, headers: { "Content-Type": file.type }, credentials: "omit" });
629
+ if (!response.ok) throw new Error("S3 upload \u0430\u043C\u0436\u0438\u043B\u0442\u0433\u04AF\u0439 \u0431\u043E\u043B\u043B\u043E\u043E");
630
+ uploaded.push(presign.url);
631
+ } else {
632
+ uploaded.push((await client.uploadRuntimeBuilderFile(context, field.key, file)).url);
633
+ }
634
+ }
635
+ setUrls(field.multiple ? [...urls, ...uploaded] : uploaded);
636
+ } catch (cause) {
637
+ notify({ type: "error", message: builderErrorMessage(cause, "\u0424\u0430\u0439\u043B upload \u0430\u043C\u0436\u0438\u043B\u0442\u0433\u04AF\u0439 \u0431\u043E\u043B\u043B\u043E\u043E") });
638
+ } finally {
639
+ setUploading(false);
640
+ if (inputRef.current) inputRef.current.value = "";
641
+ }
642
+ }
643
+ const chooseLabel = field.contentKind === "image" ? field.multiple ? "\u0417\u0443\u0440\u0430\u0433 \u043D\u044D\u043C\u044D\u0445" : "\u0417\u0443\u0440\u0430\u0433 \u0441\u043E\u043D\u0433\u043E\u0445" : "\u0424\u0430\u0439\u043B \u0441\u043E\u043D\u0433\u043E\u0445";
644
+ return /* @__PURE__ */ jsxs2("div", { className: "builder-field", children: [
645
+ /* @__PURE__ */ jsxs2("label", { className: "builder-field__label", htmlFor: inputId, children: [
646
+ field.label,
647
+ field.required ? /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: " *" }) : null
648
+ ] }),
649
+ /* @__PURE__ */ jsx2(
650
+ "input",
651
+ {
652
+ className: "builder-file-input",
653
+ ref: inputRef,
654
+ id: inputId,
655
+ type: "file",
656
+ accept: acceptedTypes(field),
657
+ multiple: field.multiple,
658
+ disabled: field.disabled || uploading || !formId && !viewId,
659
+ onChange: (event) => void upload(event.target.files)
660
+ }
661
+ ),
662
+ /* @__PURE__ */ jsx2(
663
+ "button",
664
+ {
665
+ className: "builder-button builder-button--secondary builder-file-choose",
666
+ disabled: field.disabled || uploading || !formId && !viewId,
667
+ onClick: () => inputRef.current?.click(),
668
+ type: "button",
669
+ children: uploading ? "Upload \u0445\u0438\u0439\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : chooseLabel
670
+ }
671
+ ),
672
+ urls.length > 0 ? /* @__PURE__ */ jsx2("div", { className: "builder-file-list", "data-kind": field.contentKind, children: urls.map((url, index) => /* @__PURE__ */ jsxs2("div", { className: "builder-file-item", children: [
673
+ field.contentKind === "image" ? /* @__PURE__ */ jsx2(
674
+ "a",
675
+ {
676
+ "aria-label": `${field.label} ${index + 1}-\u0433 \u043D\u044D\u044D\u0445`,
677
+ className: "builder-file-preview",
678
+ href: url,
679
+ rel: "noreferrer",
680
+ target: "_blank",
681
+ children: /* @__PURE__ */ jsx2("img", { alt: "", src: url })
682
+ }
683
+ ) : /* @__PURE__ */ jsxs2("a", { className: "builder-file-document", href: url, rel: "noreferrer", target: "_blank", children: [
684
+ "\u0424\u0430\u0439\u043B ",
685
+ index + 1
686
+ ] }),
687
+ /* @__PURE__ */ jsx2(
688
+ "button",
689
+ {
690
+ "aria-label": `${field.label} ${index + 1}-\u0433 \u0445\u0430\u0441\u0430\u0445`,
691
+ className: "builder-file-remove",
692
+ disabled: field.disabled || uploading,
693
+ onClick: () => setUrls(urls.filter((item) => item !== url)),
694
+ type: "button",
695
+ children: "\xD7"
696
+ }
697
+ )
698
+ ] }, url)) }) : null,
699
+ uploading ? /* @__PURE__ */ jsx2("small", { children: "Upload \u0445\u0438\u0439\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" }) : null,
700
+ typeof error?.message === "string" ? /* @__PURE__ */ jsx2("small", { className: "builder-field__error", children: error.message }) : null
701
+ ] });
702
+ }
703
+
704
+ // src/ready/ReadyRichTextField.tsx
705
+ import StarterKit from "@tiptap/starter-kit";
706
+ import { EditorContent, useEditor } from "@tiptap/react";
707
+ import { useEffect, useRef as useRef3 } from "react";
708
+ import { useFormContext as useFormContext2, useWatch as useWatch2 } from "react-hook-form";
709
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
710
+ function ToolbarButton({ active = false, children, disabled = false, onClick, title }) {
711
+ return /* @__PURE__ */ jsx3(
712
+ "button",
713
+ {
714
+ "aria-pressed": active,
715
+ className: "builder-richtext__button",
716
+ disabled,
717
+ onMouseDown: (event) => event.preventDefault(),
718
+ onClick,
719
+ title,
720
+ type: "button",
721
+ children
722
+ }
723
+ );
724
+ }
725
+ function ReadyRichTextField({ field, name }) {
726
+ const form = useFormContext2();
727
+ const value = useWatch2({ control: form.control, name });
728
+ const lastValue = useRef3(value);
729
+ const editor = useEditor({
730
+ content: toRichTextDocument(value),
731
+ extensions: [StarterKit.configure({ heading: { levels: [2, 3] } })],
732
+ immediatelyRender: false,
733
+ editable: !field.disabled,
734
+ editorProps: {
735
+ attributes: {
736
+ class: "builder-richtext__content",
737
+ "data-placeholder": field.placeholder ?? "\u0422\u0430\u0439\u043B\u0431\u0430\u0440 \u0431\u0438\u0447\u0438\u0445"
738
+ }
739
+ },
740
+ onUpdate: ({ editor: instance }) => {
741
+ const next = JSON.stringify(instance.getJSON());
742
+ lastValue.current = next;
743
+ form.setValue(name, next, {
744
+ shouldDirty: true,
745
+ shouldValidate: true
746
+ });
747
+ }
748
+ });
749
+ form.register(name, { required: field.required ? `${field.label} \u0448\u0430\u0430\u0440\u0434\u043B\u0430\u0433\u0430\u0442\u0430\u0439` : false });
750
+ useEffect(() => {
751
+ if (!editor || value === lastValue.current) return;
752
+ editor.commands.setContent(toRichTextDocument(value), { emitUpdate: false });
753
+ lastValue.current = value;
754
+ }, [editor, value]);
755
+ const error = form.getFieldState(name, form.formState).error;
756
+ return /* @__PURE__ */ jsxs3("div", { className: "builder-field", children: [
757
+ /* @__PURE__ */ jsxs3("span", { className: "builder-field__label", children: [
758
+ field.label,
759
+ field.required ? /* @__PURE__ */ jsx3("span", { "aria-hidden": "true", children: " *" }) : null
760
+ ] }),
761
+ /* @__PURE__ */ jsxs3("div", { className: "builder-richtext", children: [
762
+ /* @__PURE__ */ jsxs3("div", { "aria-label": `${field.label} formatting`, className: "builder-richtext__toolbar", role: "toolbar", children: [
763
+ /* @__PURE__ */ jsx3(
764
+ ToolbarButton,
765
+ {
766
+ active: editor?.isActive("heading", { level: 2 }),
767
+ disabled: !editor || field.disabled,
768
+ onClick: () => editor?.chain().focus().toggleHeading({ level: 2 }).run(),
769
+ title: "\u0413\u0430\u0440\u0447\u0438\u0433",
770
+ children: "H2"
771
+ }
772
+ ),
773
+ /* @__PURE__ */ jsx3(
774
+ ToolbarButton,
775
+ {
776
+ active: editor?.isActive("bold"),
777
+ disabled: !editor || field.disabled,
778
+ onClick: () => editor?.chain().focus().toggleBold().run(),
779
+ title: "\u0422\u043E\u0434",
780
+ children: "B"
781
+ }
782
+ ),
783
+ /* @__PURE__ */ jsx3(
784
+ ToolbarButton,
785
+ {
786
+ active: editor?.isActive("italic"),
787
+ disabled: !editor || field.disabled,
788
+ onClick: () => editor?.chain().focus().toggleItalic().run(),
789
+ title: "\u041D\u0430\u043B\u0443\u0443",
790
+ children: "I"
791
+ }
792
+ ),
793
+ /* @__PURE__ */ jsx3(
794
+ ToolbarButton,
795
+ {
796
+ active: editor?.isActive("bulletList"),
797
+ disabled: !editor || field.disabled,
798
+ onClick: () => editor?.chain().focus().toggleBulletList().run(),
799
+ title: "Bullet \u0436\u0430\u0433\u0441\u0430\u0430\u043B\u0442",
800
+ children: "\u2022"
801
+ }
802
+ ),
803
+ /* @__PURE__ */ jsx3(
804
+ ToolbarButton,
805
+ {
806
+ active: editor?.isActive("orderedList"),
807
+ disabled: !editor || field.disabled,
808
+ onClick: () => editor?.chain().focus().toggleOrderedList().run(),
809
+ title: "\u0414\u0443\u0433\u0430\u0430\u0440\u0442\u0430\u0439 \u0436\u0430\u0433\u0441\u0430\u0430\u043B\u0442",
810
+ children: "1."
811
+ }
812
+ ),
813
+ /* @__PURE__ */ jsx3(
814
+ ToolbarButton,
815
+ {
816
+ disabled: !editor || field.disabled || !editor.can().undo(),
817
+ onClick: () => editor?.chain().focus().undo().run(),
818
+ title: "\u0411\u0443\u0446\u0430\u0430\u0445",
819
+ children: "\u21B6"
820
+ }
821
+ ),
822
+ /* @__PURE__ */ jsx3(
823
+ ToolbarButton,
824
+ {
825
+ disabled: !editor || field.disabled || !editor.can().redo(),
826
+ onClick: () => editor?.chain().focus().redo().run(),
827
+ title: "\u0414\u0430\u0445\u0438\u043D \u0445\u0438\u0439\u0445",
828
+ children: "\u21B7"
829
+ }
830
+ )
831
+ ] }),
832
+ /* @__PURE__ */ jsx3(EditorContent, { editor })
833
+ ] }),
834
+ field.description ? /* @__PURE__ */ jsx3("small", { className: "builder-field__description", children: field.description }) : null,
835
+ typeof error?.message === "string" ? /* @__PURE__ */ jsx3("small", { className: "builder-field__error", children: error.message }) : null
836
+ ] });
837
+ }
838
+
839
+ // src/ready/ReadyFields.tsx
840
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
506
841
  function inputType(field) {
507
842
  if (field.type === "date") return "date";
508
843
  if (field.type === "number" || field.type === "money") return "number";
509
844
  return "text";
510
845
  }
511
- function ReadyField({ field, formId, viewId }) {
846
+ function ReadyField({
847
+ field,
848
+ formId,
849
+ viewId,
850
+ parentValues
851
+ }) {
512
852
  const { hooks, notify } = useBuilderRuntime();
513
- const form = useFormContext();
514
- const values = useWatch({ control: form.control, name: "values" }) ?? {};
515
- const timer = useRef2(null);
853
+ const form = useFormContext3();
854
+ const values = useWatch3({ control: form.control, name: "values" }) ?? {};
855
+ const timer = useRef4(null);
516
856
  const source = field.optionsSource;
517
857
  const dependencyValue = source?.filterBy ? values[source.filterBy.valueFromField] : void 0;
518
858
  const depends = source?.filterBy && dependencyValue != null ? { [source.filterBy.valueFromField]: String(dependencyValue) } : void 0;
@@ -525,6 +865,12 @@ function ReadyField({ field, formId, viewId }) {
525
865
  const trigger = hooks.useRunRuntimeBuilderFieldTrigger();
526
866
  const name = `values.${field.key}`;
527
867
  if (field.hidden) return null;
868
+ if (field.type === "file") {
869
+ return /* @__PURE__ */ jsx4(ReadyFileField, { field, formId, viewId, name });
870
+ }
871
+ if (field.type === "richtext") {
872
+ return /* @__PURE__ */ jsx4(ReadyRichTextField, { field, name });
873
+ }
528
874
  const runTrigger = (event, value) => {
529
875
  const definition = field.triggers.find((item) => item.enabled && item.event === event);
530
876
  if (!definition) return;
@@ -535,7 +881,7 @@ function ReadyField({ field, formId, viewId }) {
535
881
  viewId,
536
882
  fieldKey: field.key,
537
883
  event,
538
- input: { value, values: form.getValues("values") }
884
+ input: { value, values: form.getValues("values"), parentValues }
539
885
  });
540
886
  for (const [key, patchedValue] of Object.entries(response.valuesPatch)) {
541
887
  form.setValue(`values.${key}`, patchedValue, { shouldDirty: true, shouldValidate: true });
@@ -563,41 +909,89 @@ function ReadyField({ field, formId, viewId }) {
563
909
  });
564
910
  const error = form.formState.errors.values?.[field.key];
565
911
  const options = source ? optionsQuery.data ?? [] : field.options ?? [];
566
- return /* @__PURE__ */ jsxs2("label", { className: "builder-field", children: [
567
- /* @__PURE__ */ jsxs2("span", { className: "builder-field__label", children: [
912
+ return /* @__PURE__ */ jsxs4("label", { className: "builder-field", children: [
913
+ /* @__PURE__ */ jsxs4("span", { className: "builder-field__label", children: [
568
914
  field.label,
569
- field.required ? /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: " *" }) : null
915
+ field.required ? /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: " *" }) : null
570
916
  ] }),
571
- field.type === "textarea" ? /* @__PURE__ */ jsx2("textarea", { className: "builder-input builder-textarea", placeholder: field.placeholder, disabled: field.disabled, ...registration }) : field.type === "select" ? /* @__PURE__ */ jsxs2("select", { className: "builder-input", disabled: field.disabled || optionsQuery.isPending, ...registration, children: [
572
- /* @__PURE__ */ jsx2("option", { value: "", children: field.placeholder ?? "\u0421\u043E\u043D\u0433\u043E\u0445" }),
573
- options.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, children: option.label }, option.value))
574
- ] }) : field.type === "checkbox" ? /* @__PURE__ */ jsx2("input", { className: "builder-checkbox", type: "checkbox", disabled: field.disabled, ...registration }) : /* @__PURE__ */ jsx2("input", { className: "builder-input", type: inputType(field), placeholder: field.placeholder, disabled: field.disabled, ...registration }),
575
- field.description ? /* @__PURE__ */ jsx2("small", { className: "builder-field__description", children: field.description }) : null,
576
- typeof error?.message === "string" ? /* @__PURE__ */ jsx2("small", { className: "builder-field__error", children: error.message }) : null
917
+ field.type === "textarea" ? /* @__PURE__ */ jsx4("textarea", { className: "builder-input builder-textarea", placeholder: field.placeholder, disabled: field.disabled, ...registration }) : field.type === "select" ? /* @__PURE__ */ jsxs4("select", { className: "builder-input", disabled: field.disabled || optionsQuery.isPending, ...registration, children: [
918
+ /* @__PURE__ */ jsx4("option", { value: "", children: field.placeholder ?? "\u0421\u043E\u043D\u0433\u043E\u0445" }),
919
+ options.map((option) => /* @__PURE__ */ jsx4("option", { value: option.value, children: option.label }, option.value))
920
+ ] }) : field.type === "checkbox" ? /* @__PURE__ */ jsx4("input", { className: "builder-checkbox", type: "checkbox", disabled: field.disabled, ...registration }) : /* @__PURE__ */ jsx4("input", { className: "builder-input", type: inputType(field), placeholder: field.placeholder, disabled: field.disabled, ...registration }),
921
+ field.description ? /* @__PURE__ */ jsx4("small", { className: "builder-field__description", children: field.description }) : null,
922
+ typeof error?.message === "string" ? /* @__PURE__ */ jsx4("small", { className: "builder-field__error", children: error.message }) : null
577
923
  ] });
578
924
  }
579
- function ReadyFields({ formId, viewId, schema, extraItems = [] }) {
925
+ function ReadyFields({
926
+ formId,
927
+ viewId,
928
+ schema,
929
+ parentValues,
930
+ extraItems = []
931
+ }) {
580
932
  const fields = new Map(schema.fields.map((field) => [field.key, field]));
581
933
  const rendered = /* @__PURE__ */ new Set();
582
- return /* @__PURE__ */ jsxs2("div", { className: "builder-form-fields", children: [
583
- schema.layout?.groups.map((group) => /* @__PURE__ */ jsxs2("fieldset", { className: "builder-fieldset", children: [
584
- group.title ? /* @__PURE__ */ jsx2("legend", { children: group.title }) : null,
585
- /* @__PURE__ */ jsx2("div", { className: "builder-form-grid", children: group.fields.map((item) => {
586
- const field = fields.get(item.key);
587
- if (!field) return null;
588
- rendered.add(field.key);
589
- return /* @__PURE__ */ jsx2("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx2(ReadyField, { field, formId, viewId }) }, field.key);
590
- }) })
934
+ const groups = schema.layout?.groups ?? [];
935
+ const tabsId = useId2();
936
+ const [selectedGroupId, setSelectedGroupId] = useState3(groups[0]?.id ?? "");
937
+ const activeGroupId = groups.some((group) => group.id === selectedGroupId) ? selectedGroupId : groups[0]?.id ?? "";
938
+ const renderGroupFields = (group) => /* @__PURE__ */ jsx4("div", { className: "builder-form-grid", children: group.fields.map((item) => {
939
+ const field = fields.get(item.key);
940
+ if (!field) return null;
941
+ rendered.add(field.key);
942
+ return /* @__PURE__ */ jsx4("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx4(
943
+ ReadyField,
944
+ {
945
+ field,
946
+ formId,
947
+ viewId,
948
+ parentValues
949
+ }
950
+ ) }, field.key);
951
+ }) });
952
+ return /* @__PURE__ */ jsxs4("div", { className: "builder-form-fields", children: [
953
+ schema.layout?.presentation === "tabs" && groups.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "builder-form-tabs", children: [
954
+ /* @__PURE__ */ jsx4("div", { "aria-label": "Form sections", className: "builder-form-tabs__list", role: "tablist", children: groups.map((group, index) => {
955
+ const isActive = group.id === activeGroupId;
956
+ return /* @__PURE__ */ jsx4(
957
+ "button",
958
+ {
959
+ "aria-controls": `${tabsId}-panel-${group.id}`,
960
+ "aria-selected": isActive,
961
+ className: "builder-form-tabs__trigger",
962
+ id: `${tabsId}-tab-${group.id}`,
963
+ onClick: () => setSelectedGroupId(group.id),
964
+ role: "tab",
965
+ type: "button",
966
+ children: group.title ?? `Group ${index + 1}`
967
+ },
968
+ group.id
969
+ );
970
+ }) }),
971
+ groups.map((group) => /* @__PURE__ */ jsx4(
972
+ "div",
973
+ {
974
+ "aria-labelledby": `${tabsId}-tab-${group.id}`,
975
+ hidden: group.id !== activeGroupId,
976
+ id: `${tabsId}-panel-${group.id}`,
977
+ role: "tabpanel",
978
+ children: renderGroupFields(group)
979
+ },
980
+ group.id
981
+ ))
982
+ ] }) : groups.map((group) => /* @__PURE__ */ jsxs4("fieldset", { className: "builder-fieldset", children: [
983
+ group.title ? /* @__PURE__ */ jsx4("legend", { children: group.title }) : null,
984
+ renderGroupFields(group)
591
985
  ] }, group.id)),
592
- /* @__PURE__ */ jsx2("div", { className: "builder-form-grid", children: schema.fields.filter((field) => !rendered.has(field.key)).map((field) => /* @__PURE__ */ jsx2("div", { style: { gridColumn: "span 12" }, children: /* @__PURE__ */ jsx2(ReadyField, { field, formId, viewId }) }, field.key)) }),
593
- extraItems.map((item) => /* @__PURE__ */ jsx2("div", { children: item.render() }, item.key))
986
+ /* @__PURE__ */ jsx4("div", { className: "builder-form-grid", children: schema.fields.filter((field) => !rendered.has(field.key)).map((field) => /* @__PURE__ */ jsx4("div", { style: { gridColumn: "span 12" }, children: /* @__PURE__ */ jsx4(ReadyField, { field, formId, viewId, parentValues }) }, field.key)) }),
987
+ extraItems.map((item) => /* @__PURE__ */ jsx4("div", { children: item.render() }, item.key))
594
988
  ] });
595
989
  }
596
990
 
597
991
  // src/ready/ReadyOverlay.tsx
598
- import { useEffect, useId, useRef as useRef3, useState as useState2 } from "react";
992
+ import { useEffect as useEffect2, useId as useId3, useRef as useRef5, useState as useState4 } from "react";
599
993
  import { createPortal } from "react-dom";
600
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
994
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
601
995
  function ReadyOverlay({
602
996
  open,
603
997
  presentation = "dialog",
@@ -606,15 +1000,15 @@ function ReadyOverlay({
606
1000
  onClose,
607
1001
  children
608
1002
  }) {
609
- const panelRef = useRef3(null);
610
- const onCloseRef = useRef3(onClose);
611
- const [portalRoot, setPortalRoot] = useState2(null);
1003
+ const panelRef = useRef5(null);
1004
+ const onCloseRef = useRef5(onClose);
1005
+ const [portalRoot, setPortalRoot] = useState4(null);
612
1006
  onCloseRef.current = onClose;
613
- const titleId = useId();
614
- useEffect(() => {
1007
+ const titleId = useId3();
1008
+ useEffect2(() => {
615
1009
  setPortalRoot(document.body);
616
1010
  }, []);
617
- useEffect(() => {
1011
+ useEffect2(() => {
618
1012
  if (!open || !portalRoot) return;
619
1013
  const previous = document.activeElement;
620
1014
  panelRef.current?.focus();
@@ -648,7 +1042,7 @@ function ReadyOverlay({
648
1042
  }, [open, portalRoot]);
649
1043
  if (!open || !portalRoot) return null;
650
1044
  return createPortal(
651
- /* @__PURE__ */ jsx3("div", { className: "builder-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs3(
1045
+ /* @__PURE__ */ jsx5("div", { className: "builder-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs5(
652
1046
  "div",
653
1047
  {
654
1048
  ref: panelRef,
@@ -658,14 +1052,14 @@ function ReadyOverlay({
658
1052
  "aria-labelledby": titleId,
659
1053
  tabIndex: -1,
660
1054
  children: [
661
- /* @__PURE__ */ jsxs3("header", { className: "builder-overlay__header", children: [
662
- /* @__PURE__ */ jsxs3("div", { children: [
663
- /* @__PURE__ */ jsx3("h2", { id: titleId, className: "builder-title", children: title }),
664
- description ? /* @__PURE__ */ jsx3("p", { className: "builder-description", children: description }) : null
1055
+ /* @__PURE__ */ jsxs5("header", { className: "builder-overlay__header", children: [
1056
+ /* @__PURE__ */ jsxs5("div", { children: [
1057
+ /* @__PURE__ */ jsx5("h2", { id: titleId, className: "builder-title", children: title }),
1058
+ description ? /* @__PURE__ */ jsx5("p", { className: "builder-description", children: description }) : null
665
1059
  ] }),
666
- /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-icon-button", "aria-label": "\u0425\u0430\u0430\u0445", onClick: onClose, children: "\xD7" })
1060
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-icon-button", "aria-label": "\u0425\u0430\u0430\u0445", onClick: onClose, children: "\xD7" })
667
1061
  ] }),
668
- /* @__PURE__ */ jsx3("div", { className: "builder-overlay__body", children })
1062
+ /* @__PURE__ */ jsx5("div", { className: "builder-overlay__body", children })
669
1063
  ]
670
1064
  }
671
1065
  ) }),
@@ -681,29 +1075,29 @@ function ReadyConfirmDialog({
681
1075
  onClose,
682
1076
  onConfirm
683
1077
  }) {
684
- return /* @__PURE__ */ jsx3(ReadyOverlay, { open, title, description, onClose, children: /* @__PURE__ */ jsxs3("div", { className: "builder-actions", children: [
685
- /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-button builder-button--ghost", onClick: onClose, children: "\u0411\u043E\u043B\u0438\u0445" }),
686
- /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-button builder-button--danger", disabled: isPending, onClick: onConfirm, children: isPending ? "\u0422\u04AF\u0440 \u0445\u04AF\u043B\u044D\u044D\u043D\u044D \u04AF\u04AF\u2026" : confirmLabel })
1078
+ return /* @__PURE__ */ jsx5(ReadyOverlay, { open, title, description, onClose, children: /* @__PURE__ */ jsxs5("div", { className: "builder-actions", children: [
1079
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-button builder-button--ghost", onClick: onClose, children: "\u0411\u043E\u043B\u0438\u0445" }),
1080
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-button builder-button--danger", disabled: isPending, onClick: onConfirm, children: isPending ? "\u0422\u04AF\u0440 \u0445\u04AF\u043B\u044D\u044D\u043D\u044D \u04AF\u04AF\u2026" : confirmLabel })
687
1081
  ] }) });
688
1082
  }
689
1083
  function ReadyErrorState({ title, description }) {
690
- return /* @__PURE__ */ jsxs3("div", { className: "builder-state builder-state--error", role: "alert", children: [
691
- /* @__PURE__ */ jsx3("strong", { children: title }),
692
- /* @__PURE__ */ jsx3("span", { children: description })
1084
+ return /* @__PURE__ */ jsxs5("div", { className: "builder-state builder-state--error", role: "alert", children: [
1085
+ /* @__PURE__ */ jsx5("strong", { children: title }),
1086
+ /* @__PURE__ */ jsx5("span", { children: description })
693
1087
  ] });
694
1088
  }
695
1089
 
696
1090
  // src/ready/ReadySubform.tsx
697
- import { useEffect as useEffect2, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
698
- import { FormProvider, useForm } from "react-hook-form";
1091
+ import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef6, useState as useState6 } from "react";
1092
+ import { FormProvider, useForm, useFormContext as useFormContext4, useWatch as useWatch4 } from "react-hook-form";
699
1093
 
700
1094
  // src/ready/ReadyTable.tsx
701
- import { useMemo as useMemo2, useState as useState3 } from "react";
702
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1095
+ import { useMemo as useMemo2, useState as useState5 } from "react";
1096
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
703
1097
  function useReadyTableState({ pageSize = 20 } = {}) {
704
- const [page, setPage] = useState3(1);
705
- const [search, setSearchValue] = useState3("");
706
- const [sort, setSort] = useState3();
1098
+ const [page, setPage] = useState5(1);
1099
+ const [search, setSearchValue] = useState5("");
1100
+ const [sort, setSort] = useState5();
707
1101
  return {
708
1102
  query: { page, pageSize, search: search || void 0, sort },
709
1103
  page,
@@ -722,7 +1116,7 @@ function useReadyTableState({ pageSize = 20 } = {}) {
722
1116
  };
723
1117
  }
724
1118
  function useReadyTable(args) {
725
- const [selectedIds, setSelectedIds] = useState3([]);
1119
+ const [selectedIds, setSelectedIds] = useState5([]);
726
1120
  return useMemo2(
727
1121
  () => ({
728
1122
  ...args,
@@ -756,14 +1150,14 @@ function ReadyDataGrid({
756
1150
  selectable = false
757
1151
  }) {
758
1152
  const totalPages = Math.max(1, Math.ceil(controller.rowCount / controller.state.pageSize));
759
- return /* @__PURE__ */ jsxs4("section", { className: "builder-card builder-grid", "aria-busy": isLoading || void 0, children: [
760
- /* @__PURE__ */ jsxs4("header", { className: "builder-grid__header", children: [
761
- /* @__PURE__ */ jsxs4("div", { children: [
762
- title ? /* @__PURE__ */ jsx4("h2", { className: "builder-title", children: title }) : null,
763
- description ? /* @__PURE__ */ jsx4("p", { className: "builder-description", children: description }) : null
1153
+ return /* @__PURE__ */ jsxs6("section", { className: "builder-card builder-grid", "aria-busy": isLoading || void 0, children: [
1154
+ /* @__PURE__ */ jsxs6("header", { className: "builder-grid__header", children: [
1155
+ /* @__PURE__ */ jsxs6("div", { children: [
1156
+ title ? /* @__PURE__ */ jsx6("h2", { className: "builder-title", children: title }) : null,
1157
+ description ? /* @__PURE__ */ jsx6("p", { className: "builder-description", children: description }) : null
764
1158
  ] }),
765
- /* @__PURE__ */ jsxs4("div", { className: "builder-grid__toolbar", children: [
766
- /* @__PURE__ */ jsx4(
1159
+ /* @__PURE__ */ jsxs6("div", { className: "builder-grid__toolbar", children: [
1160
+ /* @__PURE__ */ jsx6(
767
1161
  "input",
768
1162
  {
769
1163
  className: "builder-input builder-grid__search",
@@ -777,19 +1171,19 @@ function ReadyDataGrid({
777
1171
  toolbarExtra
778
1172
  ] })
779
1173
  ] }),
780
- /* @__PURE__ */ jsxs4("div", { className: "builder-table-wrap", children: [
781
- /* @__PURE__ */ jsxs4("table", { className: "builder-table", children: [
782
- /* @__PURE__ */ jsx4("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
783
- selectable ? /* @__PURE__ */ jsx4("th", { "aria-label": "\u0421\u043E\u043D\u0433\u043E\u043B\u0442" }) : null,
784
- controller.columns.map((column) => /* @__PURE__ */ jsx4("th", { className: `builder-align-${column.align}`, children: column.sortable ? /* @__PURE__ */ jsx4("button", { type: "button", className: "builder-sort", onClick: () => controller.state.toggleSort(column.key), children: column.label }) : column.label }, column.key))
1174
+ /* @__PURE__ */ jsxs6("div", { className: "builder-table-wrap", children: [
1175
+ /* @__PURE__ */ jsxs6("table", { className: "builder-table", children: [
1176
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs6("tr", { children: [
1177
+ selectable ? /* @__PURE__ */ jsx6("th", { "aria-label": "\u0421\u043E\u043D\u0433\u043E\u043B\u0442" }) : null,
1178
+ controller.columns.map((column) => /* @__PURE__ */ jsx6("th", { className: `builder-align-${column.align}`, children: column.sortable ? /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-sort", onClick: () => controller.state.toggleSort(column.key), children: column.label }) : column.label }, column.key))
785
1179
  ] }) }),
786
- /* @__PURE__ */ jsx4("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs4(
1180
+ /* @__PURE__ */ jsx6("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs6(
787
1181
  "tr",
788
1182
  {
789
1183
  className: onRowClick ? "builder-row-clickable" : void 0,
790
1184
  onClick: (event) => onRowClick?.(entry, event),
791
1185
  children: [
792
- selectable ? /* @__PURE__ */ jsx4("td", { children: /* @__PURE__ */ jsx4(
1186
+ selectable ? /* @__PURE__ */ jsx6("td", { children: /* @__PURE__ */ jsx6(
793
1187
  "input",
794
1188
  {
795
1189
  type: "checkbox",
@@ -799,31 +1193,31 @@ function ReadyDataGrid({
799
1193
  onChange: () => controller.toggleSelected(entry.id)
800
1194
  }
801
1195
  ) }) : null,
802
- controller.columns.map((column) => /* @__PURE__ */ jsx4("td", { className: `builder-align-${column.align}`, children: cellValue(entry, column) }, column.key))
1196
+ controller.columns.map((column) => /* @__PURE__ */ jsx6("td", { className: `builder-align-${column.align}`, children: cellValue(entry, column) }, column.key))
803
1197
  ]
804
1198
  },
805
1199
  entry.id
806
1200
  )) })
807
1201
  ] }),
808
- isLoading ? /* @__PURE__ */ jsx4("div", { className: "builder-state", children: "\u0423\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" }) : null,
809
- !isLoading && controller.data.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "builder-state", children: [
810
- /* @__PURE__ */ jsx4("strong", { children: emptyTitle }),
811
- emptyDescription ? /* @__PURE__ */ jsx4("span", { children: emptyDescription }) : null
1202
+ isLoading ? /* @__PURE__ */ jsx6("div", { className: "builder-state", children: "\u0423\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" }) : null,
1203
+ !isLoading && controller.data.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "builder-state", children: [
1204
+ /* @__PURE__ */ jsx6("strong", { children: emptyTitle }),
1205
+ emptyDescription ? /* @__PURE__ */ jsx6("span", { children: emptyDescription }) : null
812
1206
  ] }) : null
813
1207
  ] }),
814
- /* @__PURE__ */ jsxs4("footer", { className: "builder-pagination", children: [
815
- /* @__PURE__ */ jsxs4("span", { children: [
1208
+ /* @__PURE__ */ jsxs6("footer", { className: "builder-pagination", children: [
1209
+ /* @__PURE__ */ jsxs6("span", { children: [
816
1210
  controller.rowCount,
817
1211
  " \u043C\u04E9\u0440"
818
1212
  ] }),
819
- /* @__PURE__ */ jsxs4("div", { children: [
820
- /* @__PURE__ */ jsx4("button", { type: "button", className: "builder-button builder-button--ghost", disabled: controller.state.page <= 1, onClick: () => controller.state.setPage(controller.state.page - 1), children: "\u04E8\u043C\u043D\u04E9\u0445" }),
821
- /* @__PURE__ */ jsxs4("span", { children: [
1213
+ /* @__PURE__ */ jsxs6("div", { children: [
1214
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", disabled: controller.state.page <= 1, onClick: () => controller.state.setPage(controller.state.page - 1), children: "\u04E8\u043C\u043D\u04E9\u0445" }),
1215
+ /* @__PURE__ */ jsxs6("span", { children: [
822
1216
  controller.state.page,
823
1217
  " / ",
824
1218
  totalPages
825
1219
  ] }),
826
- /* @__PURE__ */ jsx4("button", { type: "button", className: "builder-button builder-button--ghost", disabled: controller.state.page >= totalPages, onClick: () => controller.state.setPage(controller.state.page + 1), children: "\u0414\u0430\u0440\u0430\u0430\u0445" })
1220
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", disabled: controller.state.page >= totalPages, onClick: () => controller.state.setPage(controller.state.page + 1), children: "\u0414\u0430\u0440\u0430\u0430\u0445" })
827
1221
  ] })
828
1222
  ] })
829
1223
  ] });
@@ -833,7 +1227,7 @@ function readyColumns(columns) {
833
1227
  }
834
1228
 
835
1229
  // src/ready/ReadySubform.tsx
836
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1230
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
837
1231
  function linkedValue(entry, field) {
838
1232
  if (!entry) return void 0;
839
1233
  const value = field === "id" ? entry.id : entry.values[field];
@@ -847,7 +1241,7 @@ function makeDraftEntry(viewId, values, editing) {
847
1241
  return {
848
1242
  id: editing?.id ?? (globalThis.crypto?.randomUUID?.() ?? `draft-${Date.now()}`),
849
1243
  viewId,
850
- values: editing ? values.values : { ...values.values, _draftNew: true },
1244
+ values: editing ? { ...values.values, _draftDirty: true } : { ...values.values, _draftNew: true },
851
1245
  version: editing?.version ?? 0,
852
1246
  createdAt: editing?.createdAt ?? now,
853
1247
  updatedAt: now
@@ -855,9 +1249,12 @@ function makeDraftEntry(viewId, values, editing) {
855
1249
  }
856
1250
  function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
857
1251
  const { hooks, notify } = useBuilderRuntime();
858
- const [open, setOpen] = useState4(false);
859
- const [editing, setEditing] = useState4(null);
860
- const initialized = useRef4(false);
1252
+ const parentForm = useFormContext4();
1253
+ const watchedParentValues = useWatch4({ control: parentForm.control, name: "values" });
1254
+ const parentValues = watchedParentValues && typeof watchedParentValues === "object" && !Array.isArray(watchedParentValues) ? watchedParentValues : void 0;
1255
+ const [open, setOpen] = useState6(false);
1256
+ const [editing, setEditing] = useState6(null);
1257
+ const initialized = useRef6(false);
861
1258
  const parentValue = linkedValue(parentEntry, subform.parentField);
862
1259
  const viewQuery = hooks.useRuntimeBuilderView(subform.viewId, Boolean(subform.viewId));
863
1260
  const tableState = useReadyTableState({ pageSize: 100 });
@@ -868,7 +1265,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
868
1265
  const entriesQuery = hooks.useBuilderViewEntries(subform.viewId, filterQuery, Boolean(parentValue));
869
1266
  const view = viewQuery.data;
870
1267
  const source = view?.list?.source?.type === "dbTable" ? view.list.source.tableName : void 0;
871
- useEffect2(() => {
1268
+ useEffect3(() => {
872
1269
  if (initialized.current || !view || !entriesQuery.data || !parentValue) return;
873
1270
  initialized.current = true;
874
1271
  onRowsChange({ key: subform.key, dataKey: dataKey(view.id, source), rows: entriesQuery.data.items });
@@ -888,7 +1285,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
888
1285
  sortable: false,
889
1286
  hidden: false,
890
1287
  align: "right",
891
- render: (row) => /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-link builder-link--danger", onClick: (event) => {
1288
+ render: (row) => /* @__PURE__ */ jsx7("button", { type: "button", className: "builder-link builder-link--danger", onClick: (event) => {
892
1289
  event.stopPropagation();
893
1290
  removeRow(row);
894
1291
  }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
@@ -922,12 +1319,12 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
922
1319
  close();
923
1320
  });
924
1321
  if (viewQuery.isError) {
925
- return /* @__PURE__ */ jsx5("div", { className: "builder-state builder-state--error", children: builderErrorMessage(viewQuery.error, `${subform.label} \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439`) });
1322
+ return /* @__PURE__ */ jsx7("div", { className: "builder-state builder-state--error", children: builderErrorMessage(viewQuery.error, `${subform.label} \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439`) });
926
1323
  }
927
- return /* @__PURE__ */ jsxs5("section", { className: "builder-subform", children: [
928
- /* @__PURE__ */ jsxs5("div", { className: "builder-subform__header", children: [
929
- /* @__PURE__ */ jsx5("strong", { children: subform.label }),
930
- /* @__PURE__ */ jsxs5("button", { type: "button", className: "builder-button builder-button--secondary", disabled: !view?.form, onClick: () => {
1324
+ return /* @__PURE__ */ jsxs7("section", { className: "builder-subform", children: [
1325
+ /* @__PURE__ */ jsxs7("div", { className: "builder-subform__header", children: [
1326
+ /* @__PURE__ */ jsx7("strong", { children: subform.label }),
1327
+ /* @__PURE__ */ jsxs7("button", { type: "button", className: "builder-button builder-button--secondary", disabled: !view?.form, onClick: () => {
931
1328
  setEditing(null);
932
1329
  setOpen(true);
933
1330
  }, children: [
@@ -935,7 +1332,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
935
1332
  subform.buttonLabel ?? "\u041D\u044D\u043C\u044D\u0445"
936
1333
  ] })
937
1334
  ] }),
938
- visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx5(
1335
+ visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx7(
939
1336
  ReadyDataGrid,
940
1337
  {
941
1338
  controller: table,
@@ -947,26 +1344,34 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
947
1344
  emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430"
948
1345
  }
949
1346
  ) : null,
950
- view?.form ? /* @__PURE__ */ jsx5(ReadyOverlay, { open, presentation: subform.presentation, title: subform.label, description: view.title, onClose: close, children: /* @__PURE__ */ jsx5(FormProvider, { ...form, children: /* @__PURE__ */ jsxs5("form", { className: "builder-form", onSubmit: save, noValidate: true, children: [
951
- /* @__PURE__ */ jsx5(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
952
- /* @__PURE__ */ jsxs5("div", { className: "builder-actions", children: [
953
- /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
954
- /* @__PURE__ */ jsx5("button", { type: "submit", className: "builder-button builder-button--primary", children: editing ? "\u0428\u0438\u043D\u044D\u0447\u043B\u044D\u0445" : "\u041D\u044D\u043C\u044D\u0445" })
1347
+ view?.form ? /* @__PURE__ */ jsx7(ReadyOverlay, { open, presentation: subform.presentation, title: subform.label, description: view.title, onClose: close, children: /* @__PURE__ */ jsx7(FormProvider, { ...form, children: /* @__PURE__ */ jsxs7("form", { className: "builder-form", onSubmit: save, noValidate: true, children: [
1348
+ /* @__PURE__ */ jsx7(
1349
+ ReadyFields,
1350
+ {
1351
+ formId: view.form.id,
1352
+ viewId: view.id,
1353
+ schema: view.form.schema,
1354
+ parentValues
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ jsxs7("div", { className: "builder-actions", children: [
1358
+ /* @__PURE__ */ jsx7("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1359
+ /* @__PURE__ */ jsx7("button", { type: "submit", className: "builder-button builder-button--primary", children: editing ? "\u0428\u0438\u043D\u044D\u0447\u043B\u044D\u0445" : "\u041D\u044D\u043C\u044D\u0445" })
955
1360
  ] })
956
1361
  ] }) }) }) : null
957
1362
  ] });
958
1363
  }
959
1364
 
960
1365
  // src/ready/BuilderRuntimeComponents.tsx
961
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1366
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
962
1367
  function DefaultBuilderForm({ formId }) {
963
1368
  const { hooks, notify } = useBuilderRuntime();
964
1369
  const query = hooks.useRuntimeBuilderForm(formId);
965
1370
  const save = hooks.useSaveRuntimeBuilderFormEntry(formId);
966
1371
  const defaults = useMemo4(() => createBuilderFormDefaultValues(query.data?.schema), [query.data]);
967
1372
  const form = useForm2({ defaultValues: defaults, values: query.data ? defaults : void 0 });
968
- if (query.isError) return /* @__PURE__ */ jsx6(ReadyErrorState, { title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(query.error, `\xAB${formId}\xBB form \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
969
- if (!query.data) return /* @__PURE__ */ jsx6("div", { className: "builder-state", children: "Form \u0443\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" });
1373
+ if (query.isError) return /* @__PURE__ */ jsx8(ReadyErrorState, { title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(query.error, `\xAB${formId}\xBB form \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
1374
+ if (!query.data) return /* @__PURE__ */ jsx8("div", { className: "builder-state", children: "Form \u0443\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" });
970
1375
  const submit = form.handleSubmit(async (input) => {
971
1376
  try {
972
1377
  await save.mutateAsync(input);
@@ -976,12 +1381,12 @@ function DefaultBuilderForm({ formId }) {
976
1381
  notify({ type: "error", message: builderErrorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430") });
977
1382
  }
978
1383
  });
979
- return /* @__PURE__ */ jsxs6("section", { className: "builder-card", children: [
980
- /* @__PURE__ */ jsx6("h2", { className: "builder-title", children: query.data.title }),
981
- query.data.description ? /* @__PURE__ */ jsx6("p", { className: "builder-description", children: query.data.description }) : null,
982
- /* @__PURE__ */ jsx6(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs6("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
983
- /* @__PURE__ */ jsx6(ReadyFields, { formId, schema: query.data.schema }),
984
- /* @__PURE__ */ jsx6("div", { className: "builder-actions", children: /* @__PURE__ */ jsx6("button", { className: "builder-button builder-button--primary", type: "submit", disabled: save.isPending, children: save.isPending ? "\u0425\u0430\u0434\u0433\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" }) })
1384
+ return /* @__PURE__ */ jsxs8("section", { className: "builder-card", children: [
1385
+ /* @__PURE__ */ jsx8("h2", { className: "builder-title", children: query.data.title }),
1386
+ query.data.description ? /* @__PURE__ */ jsx8("p", { className: "builder-description", children: query.data.description }) : null,
1387
+ /* @__PURE__ */ jsx8(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs8("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
1388
+ /* @__PURE__ */ jsx8(ReadyFields, { formId, schema: query.data.schema }),
1389
+ /* @__PURE__ */ jsx8("div", { className: "builder-actions", children: /* @__PURE__ */ jsx8("button", { className: "builder-button builder-button--primary", type: "submit", disabled: save.isPending, children: save.isPending ? "\u0425\u0430\u0434\u0433\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" }) })
985
1390
  ] }) })
986
1391
  ] });
987
1392
  }
@@ -997,8 +1402,8 @@ function DefaultBuilderGrid({ listId }) {
997
1402
  state,
998
1403
  getRowId: (row) => row.id
999
1404
  });
1000
- if (listQuery.isError) return /* @__PURE__ */ jsx6(ReadyErrorState, { title: "Grid \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(listQuery.error, `\xAB${listId}\xBB list \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
1001
- return /* @__PURE__ */ jsx6(ReadyDataGrid, { title: listQuery.data?.title ?? "Grid", description: listQuery.data?.description, controller: table, isLoading: listQuery.isPending || entriesQuery.isPending });
1405
+ if (listQuery.isError) return /* @__PURE__ */ jsx8(ReadyErrorState, { title: "Grid \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(listQuery.error, `\xAB${listId}\xBB list \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
1406
+ return /* @__PURE__ */ jsx8(ReadyDataGrid, { title: listQuery.data?.title ?? "Grid", description: listQuery.data?.description, controller: table, isLoading: listQuery.isPending || entriesQuery.isPending });
1002
1407
  }
1003
1408
  function dbTableName(view) {
1004
1409
  if (view.list?.source?.type === "dbTable") return view.list.source.tableName;
@@ -1009,9 +1414,16 @@ function childPayload(row, includeIdentity) {
1009
1414
  const values = Object.fromEntries(Object.entries(row.values).filter(([key]) => key === "_delete" || !key.startsWith("_")));
1010
1415
  return includeIdentity && row.values._draftNew !== true ? { id: row.id, version: row.version, ...values } : values;
1011
1416
  }
1417
+ function hasSubformChange(row) {
1418
+ return row.values._delete === true || row.values._draftNew === true || row.values._draftDirty === true;
1419
+ }
1420
+ function changedSubformPayloads(rows, includeIdentity) {
1421
+ return rows.filter(hasSubformChange).filter((row) => includeIdentity || row.values._delete !== true).map((row) => childPayload(row, includeIdentity));
1422
+ }
1012
1423
  function BuilderEntryEditor({ view, editing, open, onClose }) {
1013
1424
  const { hooks, notify } = useBuilderRuntime();
1014
- const [subforms, setSubforms] = useState5({});
1425
+ const [subforms, setSubforms] = useState7({});
1426
+ const isSubmittingRef = useRef7(false);
1015
1427
  const save = hooks.useSaveBuilderViewEntry(view.id);
1016
1428
  const createComposite = hooks.useCreateCompositeBuilderViewEntry(view.id);
1017
1429
  const updateComposite = hooks.useUpdateCompositeBuilderViewEntry(view.id);
@@ -1022,11 +1434,13 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1022
1434
  onClose();
1023
1435
  };
1024
1436
  const submit = form.handleSubmit(async (input) => {
1437
+ if (isSubmittingRef.current) return;
1438
+ isSubmittingRef.current = true;
1025
1439
  try {
1026
1440
  const mainKey = dbTableName(view);
1027
- const hasSubformRows = Object.values(subforms).some((item) => item.rows.length > 0);
1028
- if (hasSubformRows && mainKey) {
1029
- const children = Object.fromEntries(Object.values(subforms).map((item) => [item.dataKey, item.rows.map((row) => childPayload(row, Boolean(editing)))]));
1441
+ const hasSubformChanges = Object.values(subforms).some((item) => item.rows.some(hasSubformChange));
1442
+ if (hasSubformChanges && mainKey) {
1443
+ const children = Object.fromEntries(Object.values(subforms).map((item) => [item.dataKey, changedSubformPayloads(item.rows, Boolean(editing))]));
1030
1444
  if (editing) {
1031
1445
  await updateComposite.mutateAsync({ id: editing.id, input: { data: { [mainKey]: { id: editing.id, version: input.version, ...input.values }, ...children } } });
1032
1446
  } else {
@@ -1039,24 +1453,26 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1039
1453
  close();
1040
1454
  } catch (error) {
1041
1455
  notify({ type: "error", message: builderErrorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430") });
1456
+ } finally {
1457
+ isSubmittingRef.current = false;
1042
1458
  }
1043
1459
  });
1044
1460
  const saving = save.isPending || createComposite.isPending || updateComposite.isPending;
1045
1461
  const updateRows = ({ key, dataKey: dataKey2, rows }) => setSubforms((current) => ({ ...current, [key]: { dataKey: dataKey2, rows } }));
1046
- return /* @__PURE__ */ jsx6(ReadyOverlay, { open, presentation: view.form?.schema.presentation, title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445", description: view.title, onClose: close, children: view.form ? /* @__PURE__ */ jsx6(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs6("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
1047
- /* @__PURE__ */ jsx6(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
1048
- view.form.schema.subforms.map((subform) => /* @__PURE__ */ jsx6(ReadySubform, { subform, parentEntry: editing, rows: subforms[subform.key]?.rows ?? [], onRowsChange: updateRows }, subform.key)),
1049
- /* @__PURE__ */ jsxs6("div", { className: "builder-actions builder-actions--sticky", children: [
1050
- /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1051
- /* @__PURE__ */ jsx6("button", { type: "submit", className: "builder-button builder-button--primary", disabled: saving, children: saving ? "\u0425\u0430\u0434\u0433\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" })
1462
+ return /* @__PURE__ */ jsx8(ReadyOverlay, { open, presentation: view.form?.schema.presentation, title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445", description: view.title, onClose: close, children: view.form ? /* @__PURE__ */ jsx8(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs8("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
1463
+ /* @__PURE__ */ jsx8(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
1464
+ view.form.schema.subforms.map((subform) => /* @__PURE__ */ jsx8(ReadySubform, { subform, parentEntry: editing, rows: subforms[subform.key]?.rows ?? [], onRowsChange: updateRows }, subform.key)),
1465
+ /* @__PURE__ */ jsxs8("div", { className: "builder-actions builder-actions--sticky", children: [
1466
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1467
+ /* @__PURE__ */ jsx8("button", { type: "submit", className: "builder-button builder-button--primary", disabled: saving, children: saving ? "\u0425\u0430\u0434\u0433\u0430\u043B\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" : "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445" })
1052
1468
  ] })
1053
- ] }) }) : /* @__PURE__ */ jsx6(ReadyErrorState, { title: "Form \u0445\u043E\u043B\u0431\u043E\u043E\u0433\u04AF\u0439", description: "\u042D\u043D\u044D view-\u0434 form \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430." }) });
1469
+ ] }) }) : /* @__PURE__ */ jsx8(ReadyErrorState, { title: "Form \u0445\u043E\u043B\u0431\u043E\u043E\u0433\u04AF\u0439", description: "\u042D\u043D\u044D view-\u0434 form \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430." }) });
1054
1470
  }
1055
1471
  function DefaultBuilderView({ viewId }) {
1056
1472
  const { hooks, notify } = useBuilderRuntime();
1057
- const [editing, setEditing] = useState5(null);
1058
- const [editorOpen, setEditorOpen] = useState5(false);
1059
- const [pendingDelete, setPendingDelete] = useState5(null);
1473
+ const [editing, setEditing] = useState7(null);
1474
+ const [editorOpen, setEditorOpen] = useState7(false);
1475
+ const [pendingDelete, setPendingDelete] = useState7(null);
1060
1476
  const viewQuery = hooks.useRuntimeBuilderView(viewId);
1061
1477
  const state = useReadyTableState();
1062
1478
  const entriesQuery = hooks.useBuilderViewEntries(viewId, state.query);
@@ -1071,13 +1487,13 @@ function DefaultBuilderView({ viewId }) {
1071
1487
  sortable: false,
1072
1488
  hidden: false,
1073
1489
  align: "right",
1074
- render: (entry) => /* @__PURE__ */ jsxs6("div", { className: "builder-row-actions", "data-builder-row-action": true, children: [
1075
- /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", onClick: (event) => {
1490
+ render: (entry) => /* @__PURE__ */ jsxs8("div", { className: "builder-row-actions", "data-builder-row-action": true, children: [
1491
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--ghost", onClick: (event) => {
1076
1492
  event.stopPropagation();
1077
1493
  setEditing(entry);
1078
1494
  setEditorOpen(true);
1079
1495
  }, children: "\u0417\u0430\u0441\u0430\u0445" }),
1080
- /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--danger", onClick: (event) => {
1496
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--danger", onClick: (event) => {
1081
1497
  event.stopPropagation();
1082
1498
  setPendingDelete(entry);
1083
1499
  }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
@@ -1086,9 +1502,9 @@ function DefaultBuilderView({ viewId }) {
1086
1502
  return result;
1087
1503
  }, [view]);
1088
1504
  const table = useReadyTable({ columns, data: entriesQuery.data?.items ?? [], rowCount: entriesQuery.data?.total ?? 0, state, getRowId: (row) => row.id });
1089
- if (viewQuery.isError) return /* @__PURE__ */ jsx6(ReadyErrorState, { title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(viewQuery.error, `\xAB${viewId}\xBB view \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
1090
- return /* @__PURE__ */ jsxs6("div", { className: "builder-runtime", children: [
1091
- /* @__PURE__ */ jsx6(
1505
+ if (viewQuery.isError) return /* @__PURE__ */ jsx8(ReadyErrorState, { title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439", description: builderErrorMessage(viewQuery.error, `\xAB${viewId}\xBB view \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439`) });
1506
+ return /* @__PURE__ */ jsxs8("div", { className: "builder-runtime", children: [
1507
+ /* @__PURE__ */ jsx8(
1092
1508
  ReadyDataGrid,
1093
1509
  {
1094
1510
  title: view?.title ?? "View",
@@ -1099,14 +1515,14 @@ function DefaultBuilderView({ viewId }) {
1099
1515
  setEditing(entry);
1100
1516
  setEditorOpen(true);
1101
1517
  },
1102
- toolbarExtra: /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--primary", disabled: !view?.form, onClick: () => {
1518
+ toolbarExtra: /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--primary", disabled: !view?.form, onClick: () => {
1103
1519
  setEditing(null);
1104
1520
  setEditorOpen(true);
1105
1521
  }, children: "+ \u041D\u044D\u043C\u044D\u0445" })
1106
1522
  }
1107
1523
  ),
1108
- view ? /* @__PURE__ */ jsx6(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1109
- /* @__PURE__ */ jsx6(
1524
+ view ? /* @__PURE__ */ jsx8(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1525
+ /* @__PURE__ */ jsx8(
1110
1526
  ReadyConfirmDialog,
1111
1527
  {
1112
1528
  open: Boolean(pendingDelete),
@@ -1131,17 +1547,52 @@ function DefaultBuilderView({ viewId }) {
1131
1547
  function BuilderForm(props) {
1132
1548
  const { components } = useBuilderRuntime();
1133
1549
  const Component = components.Form;
1134
- return Component ? /* @__PURE__ */ jsx6(Component, { ...props }) : /* @__PURE__ */ jsx6(DefaultBuilderForm, { ...props });
1550
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderForm, { ...props });
1135
1551
  }
1136
1552
  function BuilderGrid(props) {
1137
1553
  const { components } = useBuilderRuntime();
1138
1554
  const Component = components.Grid;
1139
- return Component ? /* @__PURE__ */ jsx6(Component, { ...props }) : /* @__PURE__ */ jsx6(DefaultBuilderGrid, { ...props });
1555
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderGrid, { ...props });
1140
1556
  }
1141
1557
  function BuilderView(props) {
1142
1558
  const { components } = useBuilderRuntime();
1143
1559
  const Component = components.View;
1144
- return Component ? /* @__PURE__ */ jsx6(Component, { ...props }) : /* @__PURE__ */ jsx6(DefaultBuilderView, { ...props });
1560
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderView, { ...props });
1561
+ }
1562
+
1563
+ // src/RichTextContent.tsx
1564
+ import { Fragment } from "react";
1565
+ import { jsx as jsx9 } from "react/jsx-runtime";
1566
+ function renderChildren(node) {
1567
+ return (node.content ?? []).map((child, index) => renderNode(child, index));
1568
+ }
1569
+ function renderText(node, key) {
1570
+ let value = node.text ?? "";
1571
+ for (const mark of node.marks ?? []) {
1572
+ if (mark.type === "bold") value = /* @__PURE__ */ jsx9("strong", { children: value });
1573
+ if (mark.type === "italic") value = /* @__PURE__ */ jsx9("em", { children: value });
1574
+ if (mark.type === "strike") value = /* @__PURE__ */ jsx9("s", { children: value });
1575
+ }
1576
+ return /* @__PURE__ */ jsx9(Fragment, { children: value }, key);
1577
+ }
1578
+ function renderNode(node, key) {
1579
+ if (node.type === "text") return renderText(node, key);
1580
+ if (node.type === "hardBreak") return /* @__PURE__ */ jsx9("br", {}, key);
1581
+ if (node.type === "paragraph") return /* @__PURE__ */ jsx9("p", { children: renderChildren(node) }, key);
1582
+ if (node.type === "heading") {
1583
+ const level = node.attrs?.level;
1584
+ if (level === 3) return /* @__PURE__ */ jsx9("h3", { children: renderChildren(node) }, key);
1585
+ return /* @__PURE__ */ jsx9("h2", { children: renderChildren(node) }, key);
1586
+ }
1587
+ if (node.type === "bulletList") return /* @__PURE__ */ jsx9("ul", { children: renderChildren(node) }, key);
1588
+ if (node.type === "orderedList") return /* @__PURE__ */ jsx9("ol", { children: renderChildren(node) }, key);
1589
+ if (node.type === "listItem") return /* @__PURE__ */ jsx9("li", { children: renderChildren(node) }, key);
1590
+ if (node.type === "blockquote") return /* @__PURE__ */ jsx9("blockquote", { children: renderChildren(node) }, key);
1591
+ return /* @__PURE__ */ jsx9(Fragment, { children: renderChildren(node) }, key);
1592
+ }
1593
+ function RichTextContent({ className, value }) {
1594
+ const document2 = toRichTextDocument(value);
1595
+ return /* @__PURE__ */ jsx9("div", { className, children: (document2.content ?? []).map((node, index) => renderNode(node, index)) });
1145
1596
  }
1146
1597
 
1147
1598
  // src/admin/editorState.ts
@@ -1189,7 +1640,7 @@ function clampLayoutSpan(span, columns) {
1189
1640
  return Math.max(1, Math.min(columns, Math.trunc(span)));
1190
1641
  }
1191
1642
  function builderFormEditorDefaultSpan(field) {
1192
- if (field.type === "textarea" || field.type === "checkbox") return 12;
1643
+ if (field.type === "textarea" || field.type === "richtext" || field.type === "checkbox") return 12;
1193
1644
  return 6;
1194
1645
  }
1195
1646
  function builderFormEditorDefaultLayoutGroups(fields, subforms = []) {
@@ -1256,6 +1707,10 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
1256
1707
  required: field.required,
1257
1708
  hidden: field.hidden ?? false,
1258
1709
  disabled: field.disabled ?? false,
1710
+ storage: field.storage ?? "s3",
1711
+ contentKind: field.contentKind ?? "image",
1712
+ multiple: field.multiple ?? false,
1713
+ maxMegabytes: field.maxBytes ? field.maxBytes / (1024 * 1024) : 10,
1259
1714
  placeholder: field.placeholder ?? "",
1260
1715
  optionsText: builderEditorOptionsToText(field.options),
1261
1716
  optionsMode: field.optionsSource?.type === "dbTable" ? "table" : "static",
@@ -1285,6 +1740,7 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
1285
1740
  sourceTable: source?.type === "dbTable" ? source.tableName : BUILDER_EDITOR_NONE_VALUE,
1286
1741
  apiBasePath: source?.type === "apiEndpoint" ? source.basePath : "",
1287
1742
  fields,
1743
+ layoutPresentation: form.schema.layout?.presentation ?? "stacked",
1288
1744
  layoutGroups: normalizeBuilderFormEditorLayoutGroups(
1289
1745
  form.schema.layout?.groups,
1290
1746
  fields,
@@ -1338,6 +1794,10 @@ function builderFormEditorFieldsFromTable(table) {
1338
1794
  required: !column.nullable,
1339
1795
  hidden: false,
1340
1796
  disabled: false,
1797
+ storage: "s3",
1798
+ contentKind: "image",
1799
+ multiple: false,
1800
+ maxMegabytes: 10,
1341
1801
  placeholder: column.label,
1342
1802
  optionsText: "",
1343
1803
  optionsMode: "static",
@@ -1374,6 +1834,10 @@ function builderFormEditorInputFromValues(values) {
1374
1834
  required: field.required,
1375
1835
  hidden: field.hidden,
1376
1836
  disabled: field.disabled,
1837
+ storage: field.type === "file" ? field.storage : void 0,
1838
+ contentKind: field.type === "file" ? field.contentKind : void 0,
1839
+ multiple: field.type === "file" ? field.multiple : void 0,
1840
+ maxBytes: field.type === "file" && typeof field.maxMegabytes === "number" && field.maxMegabytes > 0 ? Math.round(field.maxMegabytes * 1024 * 1024) : void 0,
1377
1841
  placeholder: field.placeholder?.trim() || field.label,
1378
1842
  options: field.type === "select" && field.optionsMode === "static" ? builderEditorTextToOptions(field.optionsText) : void 0,
1379
1843
  optionsSource: field.type === "select" && field.optionsMode === "table" && field.optionsTable !== BUILDER_EDITOR_NONE_VALUE && field.optionsValueField !== BUILDER_EDITOR_NONE_VALUE && field.optionsLabelField !== BUILDER_EDITOR_NONE_VALUE ? {
@@ -1396,6 +1860,7 @@ function builderFormEditorInputFromValues(values) {
1396
1860
  }))
1397
1861
  })),
1398
1862
  layout: {
1863
+ presentation: values.layoutPresentation,
1399
1864
  groups: normalizeBuilderFormEditorLayoutGroups(
1400
1865
  values.layoutGroups,
1401
1866
  values.fields,
@@ -1464,7 +1929,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
1464
1929
  }
1465
1930
 
1466
1931
  // src/admin/BuilderDefaultEditorBodies.tsx
1467
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1932
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1468
1933
  var styles = {
1469
1934
  page: {
1470
1935
  display: "grid",
@@ -1585,7 +2050,7 @@ var styles = {
1585
2050
  }
1586
2051
  };
1587
2052
  function optionItems(options) {
1588
- return options.map((option) => /* @__PURE__ */ jsx7("option", { value: option.value, children: option.label }, option.value));
2053
+ return options.map((option) => /* @__PURE__ */ jsx10("option", { value: option.value, children: option.label }, option.value));
1589
2054
  }
1590
2055
  function createBuilderDefaultFormEditorBody(options) {
1591
2056
  return function BuilderDefaultFormEditorBody({
@@ -1603,63 +2068,63 @@ function createBuilderDefaultFormEditorBody(options) {
1603
2068
  isSaving,
1604
2069
  importFieldsFromTable
1605
2070
  }) {
1606
- return /* @__PURE__ */ jsxs7("div", { style: styles.page, children: [
1607
- /* @__PURE__ */ jsxs7("div", { style: styles.header, children: [
1608
- /* @__PURE__ */ jsxs7("div", { children: [
1609
- /* @__PURE__ */ jsx7("h1", { style: styles.title, children: formId ? "Edit Dynamic Form" : "New Dynamic Form" }),
1610
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Configure fields, source mapping, layout, and triggers." })
2071
+ return /* @__PURE__ */ jsxs9("div", { style: styles.page, children: [
2072
+ /* @__PURE__ */ jsxs9("div", { style: styles.header, children: [
2073
+ /* @__PURE__ */ jsxs9("div", { children: [
2074
+ /* @__PURE__ */ jsx10("h1", { style: styles.title, children: formId ? "Edit Dynamic Form" : "New Dynamic Form" }),
2075
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Configure fields, source mapping, layout, and triggers." })
1611
2076
  ] }),
1612
- /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
1613
- /* @__PURE__ */ jsx7("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
1614
- /* @__PURE__ */ jsx7("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
2077
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2078
+ /* @__PURE__ */ jsx10("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
2079
+ /* @__PURE__ */ jsx10("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
1615
2080
  ] })
1616
2081
  ] }),
1617
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1618
- /* @__PURE__ */ jsx7("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Details" }) }),
1619
- /* @__PURE__ */ jsxs7("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
1620
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1621
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Title" }),
1622
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("title", { required: true }) })
2082
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2083
+ /* @__PURE__ */ jsx10("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Details" }) }),
2084
+ /* @__PURE__ */ jsxs9("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
2085
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2086
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Title" }),
2087
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("title", { required: true }) })
1623
2088
  ] }),
1624
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1625
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Description" }),
1626
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("description") })
2089
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2090
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Description" }),
2091
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("description") })
1627
2092
  ] }),
1628
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1629
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1630
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("presentation"), children: [
1631
- /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1632
- /* @__PURE__ */ jsx7("option", { value: "drawer", children: "Drawer" })
2093
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2094
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Presentation" }),
2095
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("presentation"), children: [
2096
+ /* @__PURE__ */ jsx10("option", { value: "dialog", children: "Dialog" }),
2097
+ /* @__PURE__ */ jsx10("option", { value: "drawer", children: "Drawer" })
1633
2098
  ] })
1634
2099
  ] }),
1635
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1636
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Datasource" }),
1637
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceType"), children: [
1638
- /* @__PURE__ */ jsx7("option", { value: "none", children: "None" }),
1639
- /* @__PURE__ */ jsx7("option", { value: "dbTable", children: "DB table" }),
1640
- /* @__PURE__ */ jsx7("option", { value: "apiEndpoint", children: "API endpoint" })
2100
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2101
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Datasource" }),
2102
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("sourceType"), children: [
2103
+ /* @__PURE__ */ jsx10("option", { value: "none", children: "None" }),
2104
+ /* @__PURE__ */ jsx10("option", { value: "dbTable", children: "DB table" }),
2105
+ /* @__PURE__ */ jsx10("option", { value: "apiEndpoint", children: "API endpoint" })
1641
2106
  ] })
1642
2107
  ] }),
1643
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1644
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1645
- /* @__PURE__ */ jsxs7(
2108
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2109
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Table" }),
2110
+ /* @__PURE__ */ jsxs9(
1646
2111
  "select",
1647
2112
  {
1648
2113
  style: styles.input,
1649
2114
  value: sourceTable,
1650
2115
  ...form.register("sourceTable"),
1651
2116
  children: [
1652
- /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
1653
- tables.map((table) => /* @__PURE__ */ jsx7("option", { value: table.name, children: table.label ?? table.name }, table.name))
2117
+ /* @__PURE__ */ jsx10("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
2118
+ tables.map((table) => /* @__PURE__ */ jsx10("option", { value: table.name, children: table.label ?? table.name }, table.name))
1654
2119
  ]
1655
2120
  }
1656
2121
  )
1657
2122
  ] }) : null,
1658
- sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1659
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "API base path" }),
1660
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("apiBasePath") })
2123
+ sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2124
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "API base path" }),
2125
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("apiBasePath") })
1661
2126
  ] }) : null,
1662
- sourceType === "dbTable" ? /* @__PURE__ */ jsx7("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx7(
2127
+ sourceType === "dbTable" ? /* @__PURE__ */ jsx10("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx10(
1663
2128
  "button",
1664
2129
  {
1665
2130
  type: "button",
@@ -1671,13 +2136,13 @@ function createBuilderDefaultFormEditorBody(options) {
1671
2136
  ) }) : null
1672
2137
  ] })
1673
2138
  ] }),
1674
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1675
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1676
- /* @__PURE__ */ jsxs7("div", { children: [
1677
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Fields" }),
1678
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Runtime form inputs." })
2139
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2140
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2141
+ /* @__PURE__ */ jsxs9("div", { children: [
2142
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Fields" }),
2143
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Runtime form inputs." })
1679
2144
  ] }),
1680
- /* @__PURE__ */ jsx7(
2145
+ /* @__PURE__ */ jsx10(
1681
2146
  "button",
1682
2147
  {
1683
2148
  type: "button",
@@ -1695,18 +2160,18 @@ function createBuilderDefaultFormEditorBody(options) {
1695
2160
  }
1696
2161
  )
1697
2162
  ] }),
1698
- fieldArray.fields.map((field, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1699
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1700
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1701
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`fields.${index}.key`) })
2163
+ fieldArray.fields.map((field, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2164
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2165
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Key" }),
2166
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`fields.${index}.key`) })
1702
2167
  ] }),
1703
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1704
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1705
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`fields.${index}.label`) })
2168
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2169
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Label" }),
2170
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`fields.${index}.label`) })
1706
2171
  ] }),
1707
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1708
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Type" }),
1709
- /* @__PURE__ */ jsx7(
2172
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2173
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Type" }),
2174
+ /* @__PURE__ */ jsx10(
1710
2175
  "select",
1711
2176
  {
1712
2177
  style: styles.input,
@@ -1715,27 +2180,51 @@ function createBuilderDefaultFormEditorBody(options) {
1715
2180
  }
1716
2181
  )
1717
2182
  ] }),
1718
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1719
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.required`) }),
2183
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2184
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.required`) }),
1720
2185
  "Required"
1721
2186
  ] }),
1722
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1723
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.hidden`) }),
2187
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2188
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.hidden`) }),
1724
2189
  "Hidden"
1725
2190
  ] }),
1726
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1727
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
2191
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2192
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
1728
2193
  "Disabled"
1729
2194
  ] }),
1730
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1731
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Placeholder" }),
1732
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
2195
+ fields[index]?.type === "file" ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
2196
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2197
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Storage" }),
2198
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`fields.${index}.storage`), children: [
2199
+ /* @__PURE__ */ jsx10("option", { value: "s3", children: "S3" }),
2200
+ /* @__PURE__ */ jsx10("option", { value: "server", children: "Server" })
2201
+ ] })
2202
+ ] }),
2203
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2204
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Content type" }),
2205
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`fields.${index}.contentKind`), children: [
2206
+ /* @__PURE__ */ jsx10("option", { value: "image", children: "Image" }),
2207
+ /* @__PURE__ */ jsx10("option", { value: "file", children: "File" })
2208
+ ] })
2209
+ ] }),
2210
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2211
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.multiple`) }),
2212
+ "Multiple"
2213
+ ] }),
2214
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2215
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Max size (MB)" }),
2216
+ /* @__PURE__ */ jsx10("input", { type: "number", min: "1", max: "100", style: styles.input, ...form.register(`fields.${index}.maxMegabytes`, { valueAsNumber: true }) })
2217
+ ] })
2218
+ ] }) : null,
2219
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2220
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Placeholder" }),
2221
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
1733
2222
  ] }),
1734
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1735
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Static options" }),
1736
- /* @__PURE__ */ jsx7("textarea", { style: styles.textarea, ...form.register(`fields.${index}.optionsText`) })
2223
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2224
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Static options" }),
2225
+ /* @__PURE__ */ jsx10("textarea", { style: styles.textarea, ...form.register(`fields.${index}.optionsText`) })
1737
2226
  ] }),
1738
- /* @__PURE__ */ jsx7("div", { style: styles.actions, children: /* @__PURE__ */ jsx7(
2227
+ /* @__PURE__ */ jsx10("div", { style: styles.actions, children: /* @__PURE__ */ jsx10(
1739
2228
  "button",
1740
2229
  {
1741
2230
  type: "button",
@@ -1747,13 +2236,13 @@ function createBuilderDefaultFormEditorBody(options) {
1747
2236
  ) })
1748
2237
  ] }, field.id))
1749
2238
  ] }),
1750
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1751
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1752
- /* @__PURE__ */ jsxs7("div", { children: [
1753
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Layout" }),
1754
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Default layout can be regenerated from current fields." })
2239
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2240
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2241
+ /* @__PURE__ */ jsxs9("div", { children: [
2242
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Layout" }),
2243
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Default layout can be regenerated from current fields." })
1755
2244
  ] }),
1756
- /* @__PURE__ */ jsx7(
2245
+ /* @__PURE__ */ jsx10(
1757
2246
  "button",
1758
2247
  {
1759
2248
  type: "button",
@@ -1765,14 +2254,21 @@ function createBuilderDefaultFormEditorBody(options) {
1765
2254
  }
1766
2255
  )
1767
2256
  ] }),
1768
- form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1769
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1770
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Group title" }),
1771
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`layoutGroups.${groupIndex}.title`) })
2257
+ /* @__PURE__ */ jsx10("div", { style: styles.grid, children: /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2258
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Group presentation" }),
2259
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("layoutPresentation"), children: [
2260
+ /* @__PURE__ */ jsx10("option", { value: "stacked", children: "Stacked sections" }),
2261
+ /* @__PURE__ */ jsx10("option", { value: "tabs", children: "Tabs" })
2262
+ ] })
2263
+ ] }) }),
2264
+ form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2265
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2266
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Group title" }),
2267
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`layoutGroups.${groupIndex}.title`) })
1772
2268
  ] }),
1773
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1774
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Columns" }),
1775
- /* @__PURE__ */ jsxs7(
2269
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2270
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Columns" }),
2271
+ /* @__PURE__ */ jsxs9(
1776
2272
  "select",
1777
2273
  {
1778
2274
  style: styles.input,
@@ -1783,16 +2279,16 @@ function createBuilderDefaultFormEditorBody(options) {
1783
2279
  { shouldDirty: true }
1784
2280
  ),
1785
2281
  children: [
1786
- /* @__PURE__ */ jsx7("option", { value: 6, children: "6" }),
1787
- /* @__PURE__ */ jsx7("option", { value: 8, children: "8" }),
1788
- /* @__PURE__ */ jsx7("option", { value: 12, children: "12" })
2282
+ /* @__PURE__ */ jsx10("option", { value: 6, children: "6" }),
2283
+ /* @__PURE__ */ jsx10("option", { value: 8, children: "8" }),
2284
+ /* @__PURE__ */ jsx10("option", { value: 12, children: "12" })
1789
2285
  ]
1790
2286
  }
1791
2287
  )
1792
2288
  ] }),
1793
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1794
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Fields" }),
1795
- /* @__PURE__ */ jsx7(
2289
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2290
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Fields" }),
2291
+ /* @__PURE__ */ jsx10(
1796
2292
  "input",
1797
2293
  {
1798
2294
  style: styles.input,
@@ -1803,13 +2299,13 @@ function createBuilderDefaultFormEditorBody(options) {
1803
2299
  ] })
1804
2300
  ] }, group.id))
1805
2301
  ] }),
1806
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1807
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1808
- /* @__PURE__ */ jsxs7("div", { children: [
1809
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Subforms" }),
1810
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Optional nested runtime view bindings." })
2302
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2303
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2304
+ /* @__PURE__ */ jsxs9("div", { children: [
2305
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Subforms" }),
2306
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Optional nested runtime view bindings." })
1811
2307
  ] }),
1812
- /* @__PURE__ */ jsx7(
2308
+ /* @__PURE__ */ jsx10(
1813
2309
  "button",
1814
2310
  {
1815
2311
  type: "button",
@@ -1828,56 +2324,56 @@ function createBuilderDefaultFormEditorBody(options) {
1828
2324
  }
1829
2325
  )
1830
2326
  ] }),
1831
- subformArray.fields.map((subform, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1832
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1833
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1834
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.key`) })
2327
+ subformArray.fields.map((subform, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2328
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2329
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Key" }),
2330
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.key`) })
1835
2331
  ] }),
1836
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1837
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1838
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.label`) })
2332
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2333
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Label" }),
2334
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.label`) })
1839
2335
  ] }),
1840
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1841
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "View ID" }),
1842
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.viewId`) })
2336
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2337
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "View ID" }),
2338
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.viewId`) })
1843
2339
  ] }),
1844
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1845
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Parent field" }),
1846
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.parentField`) })
2340
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2341
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Parent field" }),
2342
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.parentField`) })
1847
2343
  ] }),
1848
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1849
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Child field" }),
1850
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`subforms.${index}.childField`) })
2344
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2345
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Child field" }),
2346
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.childField`) })
1851
2347
  ] }),
1852
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1853
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1854
- /* @__PURE__ */ jsxs7(
2348
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2349
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Presentation" }),
2350
+ /* @__PURE__ */ jsxs9(
1855
2351
  "select",
1856
2352
  {
1857
2353
  style: styles.input,
1858
2354
  ...form.register(`subforms.${index}.presentation`),
1859
2355
  children: [
1860
- /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1861
- /* @__PURE__ */ jsx7("option", { value: "drawer", children: "Drawer" })
2356
+ /* @__PURE__ */ jsx10("option", { value: "dialog", children: "Dialog" }),
2357
+ /* @__PURE__ */ jsx10("option", { value: "drawer", children: "Drawer" })
1862
2358
  ]
1863
2359
  }
1864
2360
  )
1865
2361
  ] }),
1866
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => subformArray.remove(index), children: "Remove" })
2362
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => subformArray.remove(index), children: "Remove" })
1867
2363
  ] }, subform.id))
1868
2364
  ] }),
1869
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1870
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1871
- /* @__PURE__ */ jsxs7("div", { children: [
1872
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Form Triggers" }),
1873
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Optional API callbacks for lifecycle events." })
2365
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2366
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2367
+ /* @__PURE__ */ jsxs9("div", { children: [
2368
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Form Triggers" }),
2369
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Optional API callbacks for lifecycle events." })
1874
2370
  ] }),
1875
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
2371
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
1876
2372
  ] }),
1877
- triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1878
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1879
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Event" }),
1880
- /* @__PURE__ */ jsx7(
2373
+ triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2374
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2375
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Event" }),
2376
+ /* @__PURE__ */ jsx10(
1881
2377
  "select",
1882
2378
  {
1883
2379
  style: styles.input,
@@ -1888,19 +2384,19 @@ function createBuilderDefaultFormEditorBody(options) {
1888
2384
  }
1889
2385
  )
1890
2386
  ] }),
1891
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1892
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Route" }),
1893
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
2387
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2388
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Route" }),
2389
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
1894
2390
  ] }),
1895
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1896
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2391
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2392
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
1897
2393
  "Enabled"
1898
2394
  ] }),
1899
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1900
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2395
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2396
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
1901
2397
  "Blocking"
1902
2398
  ] }),
1903
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2399
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
1904
2400
  ] }, trigger.id))
1905
2401
  ] })
1906
2402
  ] });
@@ -1923,56 +2419,56 @@ function createBuilderDefaultListEditorBody(options) {
1923
2419
  }) {
1924
2420
  const selectedTable = tables.find((table) => table.name === sourceTable);
1925
2421
  const orderByColumns = selectedTable?.columns.filter((column) => column.sortable) ?? [];
1926
- return /* @__PURE__ */ jsxs7("div", { style: styles.page, children: [
1927
- /* @__PURE__ */ jsxs7("div", { style: styles.header, children: [
1928
- /* @__PURE__ */ jsxs7("div", { children: [
1929
- /* @__PURE__ */ jsx7("h1", { style: styles.title, children: listId ? "Edit Dynamic List" : "New Dynamic List" }),
1930
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Configure list columns, source mapping, and triggers." })
2422
+ return /* @__PURE__ */ jsxs9("div", { style: styles.page, children: [
2423
+ /* @__PURE__ */ jsxs9("div", { style: styles.header, children: [
2424
+ /* @__PURE__ */ jsxs9("div", { children: [
2425
+ /* @__PURE__ */ jsx10("h1", { style: styles.title, children: listId ? "Edit Dynamic List" : "New Dynamic List" }),
2426
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Configure list columns, source mapping, and triggers." })
1931
2427
  ] }),
1932
- /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
1933
- /* @__PURE__ */ jsx7("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
1934
- /* @__PURE__ */ jsx7("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
2428
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2429
+ /* @__PURE__ */ jsx10("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
2430
+ /* @__PURE__ */ jsx10("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
1935
2431
  ] })
1936
2432
  ] }),
1937
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1938
- /* @__PURE__ */ jsx7("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Details" }) }),
1939
- /* @__PURE__ */ jsxs7("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
1940
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1941
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Title" }),
1942
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("title", { required: true }) })
2433
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2434
+ /* @__PURE__ */ jsx10("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Details" }) }),
2435
+ /* @__PURE__ */ jsxs9("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
2436
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2437
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Title" }),
2438
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("title", { required: true }) })
1943
2439
  ] }),
1944
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1945
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Description" }),
1946
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("description") })
2440
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2441
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Description" }),
2442
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("description") })
1947
2443
  ] }),
1948
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1949
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Datasource" }),
1950
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceType"), children: [
1951
- /* @__PURE__ */ jsx7("option", { value: "none", children: "None" }),
1952
- /* @__PURE__ */ jsx7("option", { value: "dbTable", children: "DB table" }),
1953
- /* @__PURE__ */ jsx7("option", { value: "apiEndpoint", children: "API endpoint" })
2444
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2445
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Datasource" }),
2446
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("sourceType"), children: [
2447
+ /* @__PURE__ */ jsx10("option", { value: "none", children: "None" }),
2448
+ /* @__PURE__ */ jsx10("option", { value: "dbTable", children: "DB table" }),
2449
+ /* @__PURE__ */ jsx10("option", { value: "apiEndpoint", children: "API endpoint" })
1954
2450
  ] })
1955
2451
  ] }),
1956
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1957
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1958
- /* @__PURE__ */ jsxs7(
2452
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2453
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Table" }),
2454
+ /* @__PURE__ */ jsxs9(
1959
2455
  "select",
1960
2456
  {
1961
2457
  style: styles.input,
1962
2458
  value: sourceTable,
1963
2459
  ...form.register("sourceTable"),
1964
2460
  children: [
1965
- /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
1966
- tables.map((table) => /* @__PURE__ */ jsx7("option", { value: table.name, children: table.label ?? table.name }, table.name))
2461
+ /* @__PURE__ */ jsx10("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
2462
+ tables.map((table) => /* @__PURE__ */ jsx10("option", { value: table.name, children: table.label ?? table.name }, table.name))
1967
2463
  ]
1968
2464
  }
1969
2465
  )
1970
2466
  ] }) : null,
1971
- sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1972
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "API base path" }),
1973
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register("apiBasePath") })
2467
+ sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2468
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "API base path" }),
2469
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("apiBasePath") })
1974
2470
  ] }) : null,
1975
- sourceType === "dbTable" ? /* @__PURE__ */ jsx7("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx7(
2471
+ sourceType === "dbTable" ? /* @__PURE__ */ jsx10("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx10(
1976
2472
  "button",
1977
2473
  {
1978
2474
  type: "button",
@@ -1984,13 +2480,13 @@ function createBuilderDefaultListEditorBody(options) {
1984
2480
  ) }) : null
1985
2481
  ] })
1986
2482
  ] }),
1987
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1988
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1989
- /* @__PURE__ */ jsxs7("div", { children: [
1990
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Default ordering" }),
1991
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Rules are applied from top to bottom." })
2483
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2484
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2485
+ /* @__PURE__ */ jsxs9("div", { children: [
2486
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Default ordering" }),
2487
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Rules are applied from top to bottom." })
1992
2488
  ] }),
1993
- /* @__PURE__ */ jsx7(
2489
+ /* @__PURE__ */ jsx10(
1994
2490
  "button",
1995
2491
  {
1996
2492
  type: "button",
@@ -2004,17 +2500,17 @@ function createBuilderDefaultListEditorBody(options) {
2004
2500
  }
2005
2501
  )
2006
2502
  ] }),
2007
- orderByArray.fields.length === 0 ? /* @__PURE__ */ jsx7("div", { style: styles.grid, children: /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Automatic ordering is used." }) }) : null,
2008
- orderByArray.fields.map((rule, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
2009
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2010
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Order by field" }),
2011
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register(`orderBy.${index}.field`), children: [
2012
- /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select field" }),
2013
- orderByColumns.map((column) => /* @__PURE__ */ jsx7("option", { value: column.name, children: column.label }, column.name))
2503
+ orderByArray.fields.length === 0 ? /* @__PURE__ */ jsx10("div", { style: styles.grid, children: /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Automatic ordering is used." }) }) : null,
2504
+ orderByArray.fields.map((rule, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2505
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2506
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Order by field" }),
2507
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`orderBy.${index}.field`), children: [
2508
+ /* @__PURE__ */ jsx10("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select field" }),
2509
+ orderByColumns.map((column) => /* @__PURE__ */ jsx10("option", { value: column.name, children: column.label }, column.name))
2014
2510
  ] })
2015
- ] }) : /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2016
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Order by field" }),
2017
- /* @__PURE__ */ jsx7(
2511
+ ] }) : /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2512
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Order by field" }),
2513
+ /* @__PURE__ */ jsx10(
2018
2514
  "input",
2019
2515
  {
2020
2516
  style: styles.input,
@@ -2023,15 +2519,15 @@ function createBuilderDefaultListEditorBody(options) {
2023
2519
  }
2024
2520
  )
2025
2521
  ] }),
2026
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2027
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Direction" }),
2028
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register(`orderBy.${index}.direction`), children: [
2029
- /* @__PURE__ */ jsx7("option", { value: "asc", children: "Ascending" }),
2030
- /* @__PURE__ */ jsx7("option", { value: "desc", children: "Descending" })
2522
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2523
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Direction" }),
2524
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`orderBy.${index}.direction`), children: [
2525
+ /* @__PURE__ */ jsx10("option", { value: "asc", children: "Ascending" }),
2526
+ /* @__PURE__ */ jsx10("option", { value: "desc", children: "Descending" })
2031
2527
  ] })
2032
2528
  ] }),
2033
- /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
2034
- /* @__PURE__ */ jsx7(
2529
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2530
+ /* @__PURE__ */ jsx10(
2035
2531
  "button",
2036
2532
  {
2037
2533
  type: "button",
@@ -2041,7 +2537,7 @@ function createBuilderDefaultListEditorBody(options) {
2041
2537
  children: "Move up"
2042
2538
  }
2043
2539
  ),
2044
- /* @__PURE__ */ jsx7(
2540
+ /* @__PURE__ */ jsx10(
2045
2541
  "button",
2046
2542
  {
2047
2543
  type: "button",
@@ -2051,7 +2547,7 @@ function createBuilderDefaultListEditorBody(options) {
2051
2547
  children: "Move down"
2052
2548
  }
2053
2549
  ),
2054
- /* @__PURE__ */ jsx7(
2550
+ /* @__PURE__ */ jsx10(
2055
2551
  "button",
2056
2552
  {
2057
2553
  type: "button",
@@ -2063,13 +2559,13 @@ function createBuilderDefaultListEditorBody(options) {
2063
2559
  ] })
2064
2560
  ] }, rule.id))
2065
2561
  ] }),
2066
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
2067
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
2068
- /* @__PURE__ */ jsxs7("div", { children: [
2069
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Columns" }),
2070
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Runtime list columns." })
2562
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2563
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2564
+ /* @__PURE__ */ jsxs9("div", { children: [
2565
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Columns" }),
2566
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Runtime list columns." })
2071
2567
  ] }),
2072
- /* @__PURE__ */ jsx7(
2568
+ /* @__PURE__ */ jsx10(
2073
2569
  "button",
2074
2570
  {
2075
2571
  type: "button",
@@ -2083,44 +2579,44 @@ function createBuilderDefaultListEditorBody(options) {
2083
2579
  }
2084
2580
  )
2085
2581
  ] }),
2086
- columnArray.fields.map((column, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
2087
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2088
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
2089
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`columns.${index}.key`) })
2582
+ columnArray.fields.map((column, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2583
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2584
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Key" }),
2585
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`columns.${index}.key`) })
2090
2586
  ] }),
2091
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2092
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
2093
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`columns.${index}.label`) })
2587
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2588
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Label" }),
2589
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`columns.${index}.label`) })
2094
2590
  ] }),
2095
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2096
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Align" }),
2097
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register(`columns.${index}.align`), children: [
2098
- /* @__PURE__ */ jsx7("option", { value: "left", children: "Left" }),
2099
- /* @__PURE__ */ jsx7("option", { value: "right", children: "Right" })
2591
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2592
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Align" }),
2593
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`columns.${index}.align`), children: [
2594
+ /* @__PURE__ */ jsx10("option", { value: "left", children: "Left" }),
2595
+ /* @__PURE__ */ jsx10("option", { value: "right", children: "Right" })
2100
2596
  ] })
2101
2597
  ] }),
2102
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2103
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
2598
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2599
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
2104
2600
  "Sortable"
2105
2601
  ] }),
2106
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2107
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`columns.${index}.hidden`) }),
2602
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2603
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`columns.${index}.hidden`) }),
2108
2604
  "Hidden"
2109
2605
  ] })
2110
2606
  ] }, column.id))
2111
2607
  ] }),
2112
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
2113
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
2114
- /* @__PURE__ */ jsxs7("div", { children: [
2115
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "List Triggers" }),
2116
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Optional API callbacks for list lifecycle events." })
2608
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2609
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2610
+ /* @__PURE__ */ jsxs9("div", { children: [
2611
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "List Triggers" }),
2612
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Optional API callbacks for list lifecycle events." })
2117
2613
  ] }),
2118
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
2614
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
2119
2615
  ] }),
2120
- triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
2121
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2122
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Event" }),
2123
- /* @__PURE__ */ jsx7(
2616
+ triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2617
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2618
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Event" }),
2619
+ /* @__PURE__ */ jsx10(
2124
2620
  "select",
2125
2621
  {
2126
2622
  style: styles.input,
@@ -2131,19 +2627,19 @@ function createBuilderDefaultListEditorBody(options) {
2131
2627
  }
2132
2628
  )
2133
2629
  ] }),
2134
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2135
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Route" }),
2136
- /* @__PURE__ */ jsx7("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
2630
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2631
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Route" }),
2632
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
2137
2633
  ] }),
2138
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2139
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2634
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2635
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2140
2636
  "Enabled"
2141
2637
  ] }),
2142
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2143
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2638
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2639
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2144
2640
  "Blocking"
2145
2641
  ] }),
2146
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2642
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2147
2643
  ] }, trigger.id))
2148
2644
  ] })
2149
2645
  ] });
@@ -2151,8 +2647,8 @@ function createBuilderDefaultListEditorBody(options) {
2151
2647
  }
2152
2648
 
2153
2649
  // src/admin/BuilderDefaultEntityManager.tsx
2154
- import { useMemo as useMemo5, useState as useState6 } from "react";
2155
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2650
+ import { useMemo as useMemo5, useState as useState8 } from "react";
2651
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2156
2652
  var styles2 = {
2157
2653
  page: {
2158
2654
  display: "grid",
@@ -2248,7 +2744,7 @@ var styles2 = {
2248
2744
  };
2249
2745
  function createBuilderDefaultEntityManagerComponent(deps) {
2250
2746
  return function BuilderDefaultEntityManager() {
2251
- const [state, setState] = useState6({
2747
+ const [state, setState] = useState8({
2252
2748
  page: 1,
2253
2749
  pageSize: 20,
2254
2750
  search: ""
@@ -2269,16 +2765,16 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2269
2765
  if (!window.confirm(deps.labels.deleteConfirm(entity))) return;
2270
2766
  await remove.mutateAsync(entity.id);
2271
2767
  };
2272
- return /* @__PURE__ */ jsxs8("section", { style: styles2.page, children: [
2273
- /* @__PURE__ */ jsxs8("div", { style: styles2.header, children: [
2274
- /* @__PURE__ */ jsxs8("div", { children: [
2275
- /* @__PURE__ */ jsx8("h1", { style: styles2.title, children: deps.labels.title }),
2276
- /* @__PURE__ */ jsx8("p", { style: styles2.description, children: deps.labels.description })
2768
+ return /* @__PURE__ */ jsxs10("section", { style: styles2.page, children: [
2769
+ /* @__PURE__ */ jsxs10("div", { style: styles2.header, children: [
2770
+ /* @__PURE__ */ jsxs10("div", { children: [
2771
+ /* @__PURE__ */ jsx11("h1", { style: styles2.title, children: deps.labels.title }),
2772
+ /* @__PURE__ */ jsx11("p", { style: styles2.description, children: deps.labels.description })
2277
2773
  ] }),
2278
- deps.createHref ? /* @__PURE__ */ jsx8("a", { href: deps.createHref, style: styles2.primaryButton, children: deps.labels.addLabel }) : null
2774
+ deps.createHref ? /* @__PURE__ */ jsx11("a", { href: deps.createHref, style: styles2.primaryButton, children: deps.labels.addLabel }) : null
2279
2775
  ] }),
2280
- /* @__PURE__ */ jsxs8("div", { style: styles2.card, children: [
2281
- /* @__PURE__ */ jsx8("div", { style: styles2.toolbar, children: /* @__PURE__ */ jsx8(
2776
+ /* @__PURE__ */ jsxs10("div", { style: styles2.card, children: [
2777
+ /* @__PURE__ */ jsx11("div", { style: styles2.toolbar, children: /* @__PURE__ */ jsx11(
2282
2778
  "input",
2283
2779
  {
2284
2780
  style: styles2.input,
@@ -2287,21 +2783,21 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2287
2783
  onChange: (event) => setState((current) => ({ ...current, page: 1, search: event.target.value }))
2288
2784
  }
2289
2785
  ) }),
2290
- /* @__PURE__ */ jsx8("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs8("table", { style: styles2.table, children: [
2291
- /* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
2292
- /* @__PURE__ */ jsx8("th", { style: styles2.th, children: deps.labels.title }),
2293
- /* @__PURE__ */ jsx8("th", { style: styles2.th, children: "Detail" }),
2294
- /* @__PURE__ */ jsx8("th", { style: styles2.th, children: "Description" }),
2295
- /* @__PURE__ */ jsx8("th", { style: { ...styles2.th, textAlign: "right" }, children: "Actions" })
2786
+ /* @__PURE__ */ jsx11("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs10("table", { style: styles2.table, children: [
2787
+ /* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
2788
+ /* @__PURE__ */ jsx11("th", { style: styles2.th, children: deps.labels.title }),
2789
+ /* @__PURE__ */ jsx11("th", { style: styles2.th, children: "Detail" }),
2790
+ /* @__PURE__ */ jsx11("th", { style: styles2.th, children: "Description" }),
2791
+ /* @__PURE__ */ jsx11("th", { style: { ...styles2.th, textAlign: "right" }, children: "Actions" })
2296
2792
  ] }) }),
2297
- /* @__PURE__ */ jsx8("tbody", { children: items.map((entity) => /* @__PURE__ */ jsxs8("tr", { children: [
2298
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: /* @__PURE__ */ jsx8("a", { href: deps.editHref(entity), children: entity.title }) }),
2299
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: deps.getDetail?.(entity) ?? "-" }),
2300
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: entity.description || "-" }),
2301
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: /* @__PURE__ */ jsxs8("div", { style: styles2.actions, children: [
2302
- deps.runtimeHref ? /* @__PURE__ */ jsx8("a", { href: deps.runtimeHref(entity), style: styles2.button, children: deps.labels.runtimeLabel }) : null,
2303
- /* @__PURE__ */ jsx8("a", { href: deps.editHref(entity), style: styles2.button, children: deps.labels.editLabel }),
2304
- /* @__PURE__ */ jsx8(
2793
+ /* @__PURE__ */ jsx11("tbody", { children: items.map((entity) => /* @__PURE__ */ jsxs10("tr", { children: [
2794
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: /* @__PURE__ */ jsx11("a", { href: deps.editHref(entity), children: entity.title }) }),
2795
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: deps.getDetail?.(entity) ?? "-" }),
2796
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: entity.description || "-" }),
2797
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: /* @__PURE__ */ jsxs10("div", { style: styles2.actions, children: [
2798
+ deps.runtimeHref ? /* @__PURE__ */ jsx11("a", { href: deps.runtimeHref(entity), style: styles2.button, children: deps.labels.runtimeLabel }) : null,
2799
+ /* @__PURE__ */ jsx11("a", { href: deps.editHref(entity), style: styles2.button, children: deps.labels.editLabel }),
2800
+ /* @__PURE__ */ jsx11(
2305
2801
  "button",
2306
2802
  {
2307
2803
  type: "button",
@@ -2310,7 +2806,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2310
2806
  children: deps.labels.replicateLabel
2311
2807
  }
2312
2808
  ),
2313
- /* @__PURE__ */ jsx8(
2809
+ /* @__PURE__ */ jsx11(
2314
2810
  "button",
2315
2811
  {
2316
2812
  type: "button",
@@ -2323,11 +2819,11 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2323
2819
  ] }) })
2324
2820
  ] }, entity.id)) })
2325
2821
  ] }) }),
2326
- query.isPending ? /* @__PURE__ */ jsx8("div", { style: styles2.empty, children: "Loading..." }) : null,
2327
- query.isError ? /* @__PURE__ */ jsx8("div", { style: styles2.empty, children: "Failed to load." }) : null,
2328
- !query.isPending && !query.isError && items.length === 0 ? /* @__PURE__ */ jsxs8("div", { style: styles2.empty, children: [
2329
- /* @__PURE__ */ jsx8("strong", { children: deps.labels.emptyTitle }),
2330
- /* @__PURE__ */ jsx8("div", { children: deps.labels.emptyDescription })
2822
+ query.isPending ? /* @__PURE__ */ jsx11("div", { style: styles2.empty, children: "Loading..." }) : null,
2823
+ query.isError ? /* @__PURE__ */ jsx11("div", { style: styles2.empty, children: "Failed to load." }) : null,
2824
+ !query.isPending && !query.isError && items.length === 0 ? /* @__PURE__ */ jsxs10("div", { style: styles2.empty, children: [
2825
+ /* @__PURE__ */ jsx11("strong", { children: deps.labels.emptyTitle }),
2826
+ /* @__PURE__ */ jsx11("div", { children: deps.labels.emptyDescription })
2331
2827
  ] }) : null
2332
2828
  ] })
2333
2829
  ] });
@@ -2335,9 +2831,9 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2335
2831
  }
2336
2832
 
2337
2833
  // src/admin/BuilderDefaultViewEditorPage.tsx
2338
- import { useEffect as useEffect3 } from "react";
2834
+ import { useEffect as useEffect4 } from "react";
2339
2835
  import { useForm as useForm3 } from "react-hook-form";
2340
- import { Fragment, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2836
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2341
2837
  var styles3 = {
2342
2838
  page: {
2343
2839
  display: "grid",
@@ -2454,7 +2950,7 @@ function createBuilderDefaultViewEditorPage(options) {
2454
2950
  permissionWrite: defaultPermission
2455
2951
  }
2456
2952
  });
2457
- useEffect3(() => {
2953
+ useEffect4(() => {
2458
2954
  if (viewId && !view.data) return;
2459
2955
  form.reset(
2460
2956
  builderViewEditorValuesFromEntity(
@@ -2485,64 +2981,64 @@ function createBuilderDefaultViewEditorPage(options) {
2485
2981
  }
2486
2982
  });
2487
2983
  if (viewId && view.isPending) {
2488
- return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Loading..." });
2984
+ return /* @__PURE__ */ jsx12("div", { style: styles3.state, children: "Loading..." });
2489
2985
  }
2490
2986
  if (viewId && view.isError) {
2491
- return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Failed to load view." });
2987
+ return /* @__PURE__ */ jsx12("div", { style: styles3.state, children: "Failed to load view." });
2492
2988
  }
2493
- return /* @__PURE__ */ jsxs9("form", { onSubmit, noValidate: true, style: styles3.page, children: [
2494
- /* @__PURE__ */ jsxs9("div", { style: styles3.header, children: [
2495
- /* @__PURE__ */ jsxs9("div", { children: [
2496
- /* @__PURE__ */ jsx9("h1", { style: styles3.title, children: viewId ? "Edit Dynamic View" : "New Dynamic View" }),
2497
- /* @__PURE__ */ jsx9("p", { style: styles3.description, children: "Connect a form and list into a runtime screen." })
2989
+ return /* @__PURE__ */ jsxs11("form", { onSubmit, noValidate: true, style: styles3.page, children: [
2990
+ /* @__PURE__ */ jsxs11("div", { style: styles3.header, children: [
2991
+ /* @__PURE__ */ jsxs11("div", { children: [
2992
+ /* @__PURE__ */ jsx12("h1", { style: styles3.title, children: viewId ? "Edit Dynamic View" : "New Dynamic View" }),
2993
+ /* @__PURE__ */ jsx12("p", { style: styles3.description, children: "Connect a form and list into a runtime screen." })
2498
2994
  ] }),
2499
- /* @__PURE__ */ jsxs9("div", { style: styles3.actions, children: [
2500
- /* @__PURE__ */ jsx9("a", { href: options.backHref, style: styles3.button, children: "Cancel" }),
2501
- /* @__PURE__ */ jsx9("button", { type: "submit", disabled: save.isPending, style: styles3.primaryButton, children: save.isPending ? "Saving..." : "Save" })
2995
+ /* @__PURE__ */ jsxs11("div", { style: styles3.actions, children: [
2996
+ /* @__PURE__ */ jsx12("a", { href: options.backHref, style: styles3.button, children: "Cancel" }),
2997
+ /* @__PURE__ */ jsx12("button", { type: "submit", disabled: save.isPending, style: styles3.primaryButton, children: save.isPending ? "Saving..." : "Save" })
2502
2998
  ] })
2503
2999
  ] }),
2504
- /* @__PURE__ */ jsx9("section", { style: styles3.section, children: /* @__PURE__ */ jsxs9("div", { style: styles3.grid, children: [
2505
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2506
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Title" }),
2507
- /* @__PURE__ */ jsx9("input", { style: styles3.input, ...form.register("title", { required: true }) })
3000
+ /* @__PURE__ */ jsx12("section", { style: styles3.section, children: /* @__PURE__ */ jsxs11("div", { style: styles3.grid, children: [
3001
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
3002
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Title" }),
3003
+ /* @__PURE__ */ jsx12("input", { style: styles3.input, ...form.register("title", { required: true }) })
2508
3004
  ] }),
2509
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2510
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Description" }),
2511
- /* @__PURE__ */ jsx9("input", { style: styles3.input, ...form.register("description") })
3005
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
3006
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Description" }),
3007
+ /* @__PURE__ */ jsx12("input", { style: styles3.input, ...form.register("description") })
2512
3008
  ] }),
2513
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2514
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Form" }),
2515
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("formId"), children: [
2516
- /* @__PURE__ */ jsx9("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No form" }),
2517
- (forms.data ?? []).map((item) => /* @__PURE__ */ jsx9("option", { value: item.id, children: item.title }, item.id))
3009
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
3010
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Form" }),
3011
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("formId"), children: [
3012
+ /* @__PURE__ */ jsx12("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No form" }),
3013
+ (forms.data ?? []).map((item) => /* @__PURE__ */ jsx12("option", { value: item.id, children: item.title }, item.id))
2518
3014
  ] })
2519
3015
  ] }),
2520
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2521
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "List" }),
2522
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("listId"), children: [
2523
- /* @__PURE__ */ jsx9("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No list" }),
2524
- (lists.data ?? []).map((item) => /* @__PURE__ */ jsx9("option", { value: item.id, children: item.title }, item.id))
3016
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
3017
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "List" }),
3018
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("listId"), children: [
3019
+ /* @__PURE__ */ jsx12("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No list" }),
3020
+ (lists.data ?? []).map((item) => /* @__PURE__ */ jsx12("option", { value: item.id, children: item.title }, item.id))
2525
3021
  ] })
2526
3022
  ] }),
2527
- showPermissions ? /* @__PURE__ */ jsxs9(Fragment, { children: [
2528
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2529
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Read permission" }),
2530
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("permissionRead"), children: [
2531
- /* @__PURE__ */ jsx9("option", { value: "", children: "Authenticated users" }),
2532
- options.permissionOptions.map((permission) => /* @__PURE__ */ jsx9("option", { value: permission.value, children: permission.label }, permission.value))
3023
+ showPermissions ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
3024
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
3025
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Read permission" }),
3026
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("permissionRead"), children: [
3027
+ /* @__PURE__ */ jsx12("option", { value: "", children: "Authenticated users" }),
3028
+ options.permissionOptions.map((permission) => /* @__PURE__ */ jsx12("option", { value: permission.value, children: permission.label }, permission.value))
2533
3029
  ] })
2534
3030
  ] }),
2535
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2536
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Write permission" }),
2537
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("permissionWrite"), children: [
2538
- /* @__PURE__ */ jsx9("option", { value: "", children: "Authenticated users" }),
2539
- options.permissionOptions.map((permission) => /* @__PURE__ */ jsx9("option", { value: permission.value, children: permission.label }, permission.value))
3031
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
3032
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Write permission" }),
3033
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("permissionWrite"), children: [
3034
+ /* @__PURE__ */ jsx12("option", { value: "", children: "Authenticated users" }),
3035
+ options.permissionOptions.map((permission) => /* @__PURE__ */ jsx12("option", { value: permission.value, children: permission.label }, permission.value))
2540
3036
  ] })
2541
3037
  ] })
2542
3038
  ] }) : null,
2543
- /* @__PURE__ */ jsxs9("label", { style: { ...styles3.field, gridColumn: "1 / -1" }, children: [
2544
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Triggers JSON" }),
2545
- /* @__PURE__ */ jsx9("textarea", { style: styles3.textarea, ...form.register("triggersText") })
3039
+ /* @__PURE__ */ jsxs11("label", { style: { ...styles3.field, gridColumn: "1 / -1" }, children: [
3040
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Triggers JSON" }),
3041
+ /* @__PURE__ */ jsx12("textarea", { style: styles3.textarea, ...form.register("triggersText") })
2546
3042
  ] })
2547
3043
  ] }) })
2548
3044
  ] });
@@ -2550,14 +3046,14 @@ function createBuilderDefaultViewEditorPage(options) {
2550
3046
  }
2551
3047
 
2552
3048
  // src/admin/BuilderEditorPage.tsx
2553
- import { useEffect as useEffect4 } from "react";
3049
+ import { useEffect as useEffect5 } from "react";
2554
3050
  import {
2555
3051
  FormProvider as FormProvider3,
2556
3052
  useFieldArray,
2557
3053
  useForm as useForm4,
2558
- useWatch as useWatch2
3054
+ useWatch as useWatch5
2559
3055
  } from "react-hook-form";
2560
- import { jsx as jsx10 } from "react/jsx-runtime";
3056
+ import { jsx as jsx13 } from "react/jsx-runtime";
2561
3057
  function createBuilderFormEditorPageComponent(deps) {
2562
3058
  return function BuilderFormEditorPage({ formId }) {
2563
3059
  const Body = deps.Body;
@@ -2571,11 +3067,11 @@ function createBuilderFormEditorPageComponent(deps) {
2571
3067
  const fieldArray = useFieldArray({ control: form.control, name: "fields" });
2572
3068
  const subformArray = useFieldArray({ control: form.control, name: "subforms" });
2573
3069
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
2574
- const fields = useWatch2({ control: form.control, name: "fields" }) ?? [];
2575
- const subforms = useWatch2({ control: form.control, name: "subforms" }) ?? [];
2576
- const sourceType = useWatch2({ control: form.control, name: "sourceType" });
2577
- const sourceTable = useWatch2({ control: form.control, name: "sourceTable" });
2578
- useEffect4(() => {
3070
+ const fields = useWatch5({ control: form.control, name: "fields" }) ?? [];
3071
+ const subforms = useWatch5({ control: form.control, name: "subforms" }) ?? [];
3072
+ const sourceType = useWatch5({ control: form.control, name: "sourceType" });
3073
+ const sourceTable = useWatch5({ control: form.control, name: "sourceTable" });
3074
+ useEffect5(() => {
2579
3075
  if (formId && !entityQuery.data) return;
2580
3076
  form.reset(builderFormEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
2581
3077
  }, [entityQuery.data, form, formId]);
@@ -2598,12 +3094,12 @@ function createBuilderFormEditorPageComponent(deps) {
2598
3094
  }
2599
3095
  });
2600
3096
  if (formId && entityQuery.isPending) {
2601
- return /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
3097
+ return /* @__PURE__ */ jsx13("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
2602
3098
  }
2603
3099
  if (formId && entityQuery.isError) {
2604
- return /* @__PURE__ */ jsx10("div", { className: "text-destructive text-sm", children: deps.states.error });
3100
+ return /* @__PURE__ */ jsx13("div", { className: "text-destructive text-sm", children: deps.states.error });
2605
3101
  }
2606
- return /* @__PURE__ */ jsx10(FormProvider3, { ...form, children: /* @__PURE__ */ jsx10("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx10(
3102
+ return /* @__PURE__ */ jsx13(FormProvider3, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx13(
2607
3103
  Body,
2608
3104
  {
2609
3105
  formId,
@@ -2637,9 +3133,9 @@ function createBuilderListEditorPageComponent(deps) {
2637
3133
  const columnArray = useFieldArray({ control: form.control, name: "columns" });
2638
3134
  const orderByArray = useFieldArray({ control: form.control, name: "orderBy" });
2639
3135
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
2640
- const sourceType = useWatch2({ control: form.control, name: "sourceType" });
2641
- const sourceTable = useWatch2({ control: form.control, name: "sourceTable" });
2642
- useEffect4(() => {
3136
+ const sourceType = useWatch5({ control: form.control, name: "sourceType" });
3137
+ const sourceTable = useWatch5({ control: form.control, name: "sourceTable" });
3138
+ useEffect5(() => {
2643
3139
  if (listId && !entityQuery.data) return;
2644
3140
  form.reset(builderListEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
2645
3141
  }, [entityQuery.data, form, listId]);
@@ -2658,12 +3154,12 @@ function createBuilderListEditorPageComponent(deps) {
2658
3154
  }
2659
3155
  });
2660
3156
  if (listId && entityQuery.isPending) {
2661
- return /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
3157
+ return /* @__PURE__ */ jsx13("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
2662
3158
  }
2663
3159
  if (listId && entityQuery.isError) {
2664
- return /* @__PURE__ */ jsx10("div", { className: "text-destructive text-sm", children: deps.states.error });
3160
+ return /* @__PURE__ */ jsx13("div", { className: "text-destructive text-sm", children: deps.states.error });
2665
3161
  }
2666
- return /* @__PURE__ */ jsx10(FormProvider3, { ...form, children: /* @__PURE__ */ jsx10("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx10(
3162
+ return /* @__PURE__ */ jsx13(FormProvider3, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx13(
2667
3163
  Body,
2668
3164
  {
2669
3165
  listId,
@@ -2684,10 +3180,11 @@ function createBuilderListEditorPageComponent(deps) {
2684
3180
  }
2685
3181
 
2686
3182
  // src/admin/BuilderAdminPages.tsx
2687
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3183
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2688
3184
  var defaultFieldTypeOptions = [
2689
3185
  { value: "text", label: "Text" },
2690
3186
  { value: "textarea", label: "Textarea" },
3187
+ { value: "richtext", label: "Rich text" },
2691
3188
  { value: "number", label: "Number" },
2692
3189
  { value: "money", label: "Money" },
2693
3190
  { value: "select", label: "Select" },
@@ -2798,6 +3295,10 @@ function createBuilderAdminPages({
2798
3295
  required: true,
2799
3296
  hidden: false,
2800
3297
  disabled: false,
3298
+ storage: "s3",
3299
+ contentKind: "image",
3300
+ multiple: false,
3301
+ maxMegabytes: 10,
2801
3302
  placeholder: "",
2802
3303
  optionsText: "",
2803
3304
  optionsMode: "static",
@@ -2817,6 +3318,7 @@ function createBuilderAdminPages({
2817
3318
  sourceTable: BUILDER_EDITOR_NONE_VALUE,
2818
3319
  apiBasePath: "",
2819
3320
  fields: [emptyField],
3321
+ layoutPresentation: "stacked",
2820
3322
  layoutGroups: builderFormEditorDefaultLayoutGroups([emptyField]),
2821
3323
  subforms: [],
2822
3324
  triggers: [],
@@ -2944,14 +3446,14 @@ function createBuilderAdminPages({
2944
3446
  href: viewsPath
2945
3447
  }
2946
3448
  ];
2947
- return /* @__PURE__ */ jsxs10("section", { style: homeStyles.page, children: [
2948
- /* @__PURE__ */ jsxs10("div", { children: [
2949
- /* @__PURE__ */ jsx11("h1", { style: homeStyles.headerTitle, children: "Builder" }),
2950
- /* @__PURE__ */ jsx11("p", { style: homeStyles.description, children: "Manage dynamic forms, lists, and views." })
3449
+ return /* @__PURE__ */ jsxs12("section", { style: homeStyles.page, children: [
3450
+ /* @__PURE__ */ jsxs12("div", { children: [
3451
+ /* @__PURE__ */ jsx14("h1", { style: homeStyles.headerTitle, children: "Builder" }),
3452
+ /* @__PURE__ */ jsx14("p", { style: homeStyles.description, children: "Manage dynamic forms, lists, and views." })
2951
3453
  ] }),
2952
- /* @__PURE__ */ jsx11("div", { style: homeStyles.grid, children: items.map((item) => /* @__PURE__ */ jsxs10("a", { href: item.href, style: homeStyles.card, children: [
2953
- /* @__PURE__ */ jsx11("h2", { style: homeStyles.cardTitle, children: item.title }),
2954
- /* @__PURE__ */ jsx11("p", { style: homeStyles.description, children: item.description })
3454
+ /* @__PURE__ */ jsx14("div", { style: homeStyles.grid, children: items.map((item) => /* @__PURE__ */ jsxs12("a", { href: item.href, style: homeStyles.card, children: [
3455
+ /* @__PURE__ */ jsx14("h2", { style: homeStyles.cardTitle, children: item.title }),
3456
+ /* @__PURE__ */ jsx14("p", { style: homeStyles.description, children: item.description })
2955
3457
  ] }, item.href)) })
2956
3458
  ] });
2957
3459
  };
@@ -3040,24 +3542,24 @@ function createBuilderAdminPages({
3040
3542
  AdminHomePage,
3041
3543
  AdminFormsPage,
3042
3544
  AdminNewFormPage: function BuilderAdminNewFormPage() {
3043
- return /* @__PURE__ */ jsx11(FormEditorPage, {});
3545
+ return /* @__PURE__ */ jsx14(FormEditorPage, {});
3044
3546
  },
3045
3547
  AdminEditFormPage: function BuilderAdminEditFormPage({ formId }) {
3046
- return /* @__PURE__ */ jsx11(FormEditorPage, { formId });
3548
+ return /* @__PURE__ */ jsx14(FormEditorPage, { formId });
3047
3549
  },
3048
3550
  AdminListsPage,
3049
3551
  AdminNewListPage: function BuilderAdminNewListPage() {
3050
- return /* @__PURE__ */ jsx11(ListEditorPage, {});
3552
+ return /* @__PURE__ */ jsx14(ListEditorPage, {});
3051
3553
  },
3052
3554
  AdminEditListPage: function BuilderAdminEditListPage({ listId }) {
3053
- return /* @__PURE__ */ jsx11(ListEditorPage, { listId });
3555
+ return /* @__PURE__ */ jsx14(ListEditorPage, { listId });
3054
3556
  },
3055
3557
  AdminViewsPage,
3056
3558
  AdminNewViewPage: function BuilderAdminNewViewPage() {
3057
- return /* @__PURE__ */ jsx11(ViewEditorPage, {});
3559
+ return /* @__PURE__ */ jsx14(ViewEditorPage, {});
3058
3560
  },
3059
3561
  AdminEditViewPage: function BuilderAdminEditViewPage({ viewId }) {
3060
- return /* @__PURE__ */ jsx11(ViewEditorPage, { viewId });
3562
+ return /* @__PURE__ */ jsx14(ViewEditorPage, { viewId });
3061
3563
  },
3062
3564
  routes: {
3063
3565
  adminBasePath,
@@ -3075,11 +3577,11 @@ function createBuilderAdminPages({
3075
3577
  }
3076
3578
 
3077
3579
  // src/admin/BuilderEntityManager.tsx
3078
- import { useCallback as useCallback2, useMemo as useMemo6, useState as useState7 } from "react";
3079
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
3580
+ import { useCallback as useCallback2, useMemo as useMemo6, useState as useState9 } from "react";
3581
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3080
3582
  function createBuilderEntityManagerComponent(deps) {
3081
3583
  return function BuilderEntityManager() {
3082
- const [pendingDelete, setPendingDelete] = useState7(null);
3584
+ const [pendingDelete, setPendingDelete] = useState9(null);
3083
3585
  const state = deps.useDataTableState({ pageSize: 20 });
3084
3586
  const query = deps.hooks.useEntities(state.query);
3085
3587
  const remove = deps.hooks.useDelete();
@@ -3104,8 +3606,8 @@ function createBuilderEntityManagerComponent(deps) {
3104
3606
  state,
3105
3607
  getRowId: (row) => row.id
3106
3608
  });
3107
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3108
- /* @__PURE__ */ jsx12(
3609
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3610
+ /* @__PURE__ */ jsx15(
3109
3611
  deps.DataGrid,
3110
3612
  {
3111
3613
  title: deps.labels.title,
@@ -3116,10 +3618,10 @@ function createBuilderEntityManagerComponent(deps) {
3116
3618
  emptyTitle: deps.labels.emptyTitle,
3117
3619
  emptyDescription: deps.labels.emptyDescription,
3118
3620
  onRowClick: deps.navigateToEdit,
3119
- toolbarExtra: /* @__PURE__ */ jsx12(deps.AddButton, { href: deps.createHref, label: deps.labels.addLabel })
3621
+ toolbarExtra: /* @__PURE__ */ jsx15(deps.AddButton, { href: deps.createHref, label: deps.labels.addLabel })
3120
3622
  }
3121
3623
  ),
3122
- /* @__PURE__ */ jsx12(
3624
+ /* @__PURE__ */ jsx15(
3123
3625
  deps.DeleteDialog,
3124
3626
  {
3125
3627
  entity: pendingDelete,
@@ -3139,9 +3641,9 @@ function createBuilderEntityManagerComponent(deps) {
3139
3641
  }
3140
3642
  function createBuilderEntityDialogManagerComponent(deps) {
3141
3643
  return function BuilderEntityDialogManager() {
3142
- const [editing, setEditing] = useState7(null);
3143
- const [isEditorOpen, setEditorOpen] = useState7(false);
3144
- const [pendingDelete, setPendingDelete] = useState7(null);
3644
+ const [editing, setEditing] = useState9(null);
3645
+ const [isEditorOpen, setEditorOpen] = useState9(false);
3646
+ const [pendingDelete, setPendingDelete] = useState9(null);
3145
3647
  const state = deps.useDataTableState({ pageSize: 20 });
3146
3648
  const query = deps.hooks.useEntities(state.query);
3147
3649
  const remove = deps.hooks.useDelete();
@@ -3170,8 +3672,8 @@ function createBuilderEntityDialogManagerComponent(deps) {
3170
3672
  state,
3171
3673
  getRowId: (row) => row.id
3172
3674
  });
3173
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3174
- /* @__PURE__ */ jsx12(
3675
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3676
+ /* @__PURE__ */ jsx15(
3175
3677
  deps.DataGrid,
3176
3678
  {
3177
3679
  title: deps.labels.title,
@@ -3182,10 +3684,10 @@ function createBuilderEntityDialogManagerComponent(deps) {
3182
3684
  emptyTitle: deps.labels.emptyTitle,
3183
3685
  emptyDescription: deps.labels.emptyDescription,
3184
3686
  onRowClick: openEditor,
3185
- toolbarExtra: /* @__PURE__ */ jsx12(deps.AddButton, { label: deps.labels.addLabel, onAdd: () => openEditor(null) })
3687
+ toolbarExtra: /* @__PURE__ */ jsx15(deps.AddButton, { label: deps.labels.addLabel, onAdd: () => openEditor(null) })
3186
3688
  }
3187
3689
  ),
3188
- /* @__PURE__ */ jsx12(
3690
+ /* @__PURE__ */ jsx15(
3189
3691
  deps.EditorDialog,
3190
3692
  {
3191
3693
  open: isEditorOpen,
@@ -3193,7 +3695,7 @@ function createBuilderEntityDialogManagerComponent(deps) {
3193
3695
  onClose: () => setEditorOpen(false)
3194
3696
  }
3195
3697
  ),
3196
- /* @__PURE__ */ jsx12(
3698
+ /* @__PURE__ */ jsx15(
3197
3699
  deps.DeleteDialog,
3198
3700
  {
3199
3701
  entity: pendingDelete,
@@ -3213,9 +3715,9 @@ function createBuilderEntityDialogManagerComponent(deps) {
3213
3715
  }
3214
3716
 
3215
3717
  // src/admin/BuilderViewDialog.tsx
3216
- import { useEffect as useEffect5 } from "react";
3718
+ import { useEffect as useEffect6 } from "react";
3217
3719
  import { FormProvider as FormProvider4, useForm as useForm5 } from "react-hook-form";
3218
- import { jsx as jsx13 } from "react/jsx-runtime";
3720
+ import { jsx as jsx16 } from "react/jsx-runtime";
3219
3721
  function createBuilderViewDialogComponent(deps) {
3220
3722
  return function BuilderViewDialog({
3221
3723
  open,
@@ -3230,7 +3732,7 @@ function createBuilderViewDialogComponent(deps) {
3230
3732
  resolver: deps.resolver,
3231
3733
  defaultValues: deps.emptyValues
3232
3734
  });
3233
- useEffect5(() => {
3735
+ useEffect6(() => {
3234
3736
  if (!open) return;
3235
3737
  form.reset(
3236
3738
  builderViewEditorValuesFromEntity(editing, deps.emptyValues, deps.defaultPermission)
@@ -3245,7 +3747,7 @@ function createBuilderViewDialogComponent(deps) {
3245
3747
  deps.notifications.error(error);
3246
3748
  }
3247
3749
  });
3248
- return /* @__PURE__ */ jsx13(deps.Shell, { open, editing, onClose, children: /* @__PURE__ */ jsx13(FormProvider4, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, children: deps.Body({
3750
+ return /* @__PURE__ */ jsx16(deps.Shell, { open, editing, onClose, children: /* @__PURE__ */ jsx16(FormProvider4, { ...form, children: /* @__PURE__ */ jsx16("form", { onSubmit, noValidate: true, children: deps.Body({
3249
3751
  form,
3250
3752
  editing,
3251
3753
  forms,
@@ -3260,7 +3762,7 @@ function createBuilderViewDialogComponent(deps) {
3260
3762
 
3261
3763
  // src/admin/formLayoutEditorState.ts
3262
3764
  import { useMemo as useMemo7 } from "react";
3263
- import { useWatch as useWatch3 } from "react-hook-form";
3765
+ import { useWatch as useWatch6 } from "react-hook-form";
3264
3766
  var builderFormLayoutDragDataType = "application/x-winu-builder-layout-field";
3265
3767
  function clampBuilderFormLayoutSpan(span, columns) {
3266
3768
  return Math.max(1, Math.min(columns, span));
@@ -3307,7 +3809,7 @@ function parseBuilderFormLayoutDragPayload(raw) {
3307
3809
  }
3308
3810
  }
3309
3811
  function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
3310
- const layoutGroups = useWatch3({ control: form.control, name: "layoutGroups" }) ?? [];
3812
+ const layoutGroups = useWatch6({ control: form.control, name: "layoutGroups" }) ?? [];
3311
3813
  const layoutItems = useMemo7(
3312
3814
  () => [
3313
3815
  ...fields.map((field) => ({
@@ -3430,7 +3932,7 @@ function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
3430
3932
  // src/components/DynamicForm.tsx
3431
3933
  import { useMemo as useMemo8 } from "react";
3432
3934
  import { FormProvider as FormProvider5, useForm as useForm6 } from "react-hook-form";
3433
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3935
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
3434
3936
  function createDynamicFormComponent(deps) {
3435
3937
  return function DynamicForm({ formId }) {
3436
3938
  const query = deps.hooks.useRuntimeBuilderForm(formId);
@@ -3453,7 +3955,7 @@ function createDynamicFormComponent(deps) {
3453
3955
  }
3454
3956
  });
3455
3957
  if (query.isError) {
3456
- return /* @__PURE__ */ jsx14(
3958
+ return /* @__PURE__ */ jsx17(
3457
3959
  deps.ErrorState,
3458
3960
  {
3459
3961
  title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3462,16 +3964,16 @@ function createDynamicFormComponent(deps) {
3462
3964
  );
3463
3965
  }
3464
3966
  if (!query.data) return null;
3465
- return /* @__PURE__ */ jsx14(deps.FormShell, { title: query.data.title, children: /* @__PURE__ */ jsx14(FormProvider5, { ...form, children: /* @__PURE__ */ jsxs12("form", { onSubmit, noValidate: true, className: "space-y-6", children: [
3466
- /* @__PURE__ */ jsx14(deps.FormFields, { formId, schema: query.data.schema, namePrefix: "values" }),
3467
- /* @__PURE__ */ jsx14(deps.SubmitButton, { isSaving: save.isPending })
3967
+ return /* @__PURE__ */ jsx17(deps.FormShell, { title: query.data.title, children: /* @__PURE__ */ jsx17(FormProvider5, { ...form, children: /* @__PURE__ */ jsxs14("form", { onSubmit, noValidate: true, className: "space-y-6", children: [
3968
+ /* @__PURE__ */ jsx17(deps.FormFields, { formId, schema: query.data.schema, namePrefix: "values" }),
3969
+ /* @__PURE__ */ jsx17(deps.SubmitButton, { isSaving: save.isPending })
3468
3970
  ] }) }) });
3469
3971
  };
3470
3972
  }
3471
3973
 
3472
3974
  // src/components/DynamicList.tsx
3473
3975
  import { useMemo as useMemo9 } from "react";
3474
- import { jsx as jsx15 } from "react/jsx-runtime";
3976
+ import { jsx as jsx18 } from "react/jsx-runtime";
3475
3977
  function createDynamicListComponent(deps) {
3476
3978
  return function DynamicList({ listId }) {
3477
3979
  const query = deps.hooks.useRuntimeBuilderList(listId);
@@ -3487,7 +3989,7 @@ function createDynamicListComponent(deps) {
3487
3989
  getRowId: (row) => row.id
3488
3990
  });
3489
3991
  if (query.isError) {
3490
- return /* @__PURE__ */ jsx15(
3992
+ return /* @__PURE__ */ jsx18(
3491
3993
  deps.ErrorState,
3492
3994
  {
3493
3995
  title: "List \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3495,7 +3997,7 @@ function createDynamicListComponent(deps) {
3495
3997
  }
3496
3998
  );
3497
3999
  }
3498
- return /* @__PURE__ */ jsx15(
4000
+ return /* @__PURE__ */ jsx18(
3499
4001
  deps.DataGrid,
3500
4002
  {
3501
4003
  title: query.data?.title ?? "Dynamic List",
@@ -3511,8 +4013,8 @@ function createDynamicListComponent(deps) {
3511
4013
  }
3512
4014
 
3513
4015
  // src/components/DynamicView.tsx
3514
- import { useMemo as useMemo10, useState as useState8 } from "react";
3515
- import { jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
4016
+ import { useMemo as useMemo10, useState as useState10 } from "react";
4017
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
3516
4018
  var interactiveRowTargetSelector = "button,a,input,select,textarea,[role='button'],[role='menuitem'],[data-builder-row-action]";
3517
4019
  function hasClosest(target) {
3518
4020
  return typeof target === "object" && target !== null && "closest" in target && typeof target.closest === "function";
@@ -3524,9 +4026,9 @@ function shouldHandleDynamicViewRowClick(event) {
3524
4026
  }
3525
4027
  function createDynamicViewComponent(deps) {
3526
4028
  return function DynamicView({ viewId }) {
3527
- const [editing, setEditing] = useState8(null);
3528
- const [isDialogOpen, setDialogOpen] = useState8(false);
3529
- const [pendingDelete, setPendingDelete] = useState8(null);
4029
+ const [editing, setEditing] = useState10(null);
4030
+ const [isDialogOpen, setDialogOpen] = useState10(false);
4031
+ const [pendingDelete, setPendingDelete] = useState10(null);
3530
4032
  const viewQuery = deps.hooks.useRuntimeBuilderView(viewId);
3531
4033
  const state = deps.useDataTableState({ pageSize: 20 });
3532
4034
  const entriesQuery = deps.hooks.useBuilderViewEntries(viewId, state.query);
@@ -3555,7 +4057,7 @@ function createDynamicViewComponent(deps) {
3555
4057
  getRowId: (row) => row.id
3556
4058
  });
3557
4059
  if (viewQuery.isError) {
3558
- return /* @__PURE__ */ jsx16(
4060
+ return /* @__PURE__ */ jsx19(
3559
4061
  deps.ErrorState,
3560
4062
  {
3561
4063
  title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3563,8 +4065,8 @@ function createDynamicViewComponent(deps) {
3563
4065
  }
3564
4066
  );
3565
4067
  }
3566
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3567
- /* @__PURE__ */ jsx16(
4068
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-6", children: [
4069
+ /* @__PURE__ */ jsx19(
3568
4070
  deps.DataGrid,
3569
4071
  {
3570
4072
  title: view?.title ?? "Dynamic View",
@@ -3579,7 +4081,7 @@ function createDynamicViewComponent(deps) {
3579
4081
  setEditing(entry);
3580
4082
  setDialogOpen(true);
3581
4083
  },
3582
- toolbarExtra: /* @__PURE__ */ jsx16(
4084
+ toolbarExtra: /* @__PURE__ */ jsx19(
3583
4085
  deps.AddButton,
3584
4086
  {
3585
4087
  disabled: !view?.form,
@@ -3591,7 +4093,7 @@ function createDynamicViewComponent(deps) {
3591
4093
  )
3592
4094
  }
3593
4095
  ),
3594
- view ? /* @__PURE__ */ jsx16(
4096
+ view ? /* @__PURE__ */ jsx19(
3595
4097
  deps.EntryDialog,
3596
4098
  {
3597
4099
  open: isDialogOpen,
@@ -3602,7 +4104,7 @@ function createDynamicViewComponent(deps) {
3602
4104
  isSaving: save.isPending
3603
4105
  }
3604
4106
  ) : null,
3605
- /* @__PURE__ */ jsx16(
4107
+ /* @__PURE__ */ jsx19(
3606
4108
  deps.DeleteDialog,
3607
4109
  {
3608
4110
  entry: pendingDelete,
@@ -3620,9 +4122,9 @@ function createDynamicViewComponent(deps) {
3620
4122
  }
3621
4123
 
3622
4124
  // src/components/RuntimeEntryDialog.tsx
3623
- import { useEffect as useEffect6, useMemo as useMemo11, useState as useState9 } from "react";
4125
+ import { useEffect as useEffect7, useMemo as useMemo11, useRef as useRef8, useState as useState11 } from "react";
3624
4126
  import { FormProvider as FormProvider6, useForm as useForm7 } from "react-hook-form";
3625
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
4127
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
3626
4128
  function isDbTableSource(source) {
3627
4129
  return source?.type === "dbTable" && "tableName" in source;
3628
4130
  }
@@ -3646,6 +4148,12 @@ function childRowPayload(row, includeIdentity) {
3646
4148
  ...values
3647
4149
  };
3648
4150
  }
4151
+ function hasDraftChange(row) {
4152
+ return row.values._delete === true || row.values._draftNew === true || row.values._draftDirty === true;
4153
+ }
4154
+ function changedChildPayloads(rows, includeIdentity) {
4155
+ return rows.filter(hasDraftChange).filter((row) => includeIdentity || row.values._delete !== true).map((row) => childRowPayload(row, includeIdentity));
4156
+ }
3649
4157
  function createRuntimeEntryDialogComponent(deps) {
3650
4158
  return function RuntimeEntryDialog({
3651
4159
  open,
@@ -3655,7 +4163,8 @@ function createRuntimeEntryDialogComponent(deps) {
3655
4163
  onSave,
3656
4164
  isSaving
3657
4165
  }) {
3658
- const [draftSubforms, setDraftSubforms] = useState9({});
4166
+ const [draftSubforms, setDraftSubforms] = useState11({});
4167
+ const isSubmittingRef = useRef8(false);
3659
4168
  const compositeCreate = deps.useCreateCompositeEntry?.(view.id);
3660
4169
  const compositeUpdate = deps.useUpdateCompositeEntry?.(view.id);
3661
4170
  const form = useForm7({
@@ -3663,16 +4172,18 @@ function createRuntimeEntryDialogComponent(deps) {
3663
4172
  values: open ? createBuilderEntryDefaultValues(view, editing) : void 0
3664
4173
  });
3665
4174
  const mainTableName = runtimeViewTableName(view);
3666
- const hasDraftRows = useMemo11(
3667
- () => Object.values(draftSubforms).some((draft) => draft.rows.length > 0),
4175
+ const hasDraftChanges = useMemo11(
4176
+ () => Object.values(draftSubforms).some((draft) => draft.rows.some(hasDraftChange)),
3668
4177
  [draftSubforms]
3669
4178
  );
3670
- useEffect6(() => {
4179
+ useEffect7(() => {
3671
4180
  if (open) setDraftSubforms({});
3672
4181
  }, [open]);
3673
4182
  const onSubmit = form.handleSubmit(async (values) => {
4183
+ if (isSubmittingRef.current) return;
4184
+ isSubmittingRef.current = true;
3674
4185
  try {
3675
- if (!editing && hasDraftRows) {
4186
+ if (!editing && hasDraftChanges) {
3676
4187
  if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3677
4188
  if (!compositeCreate) throw new Error("Composite create handler \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0433\u0434\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
3678
4189
  await compositeCreate.mutateAsync({
@@ -3681,12 +4192,12 @@ function createRuntimeEntryDialogComponent(deps) {
3681
4192
  ...Object.fromEntries(
3682
4193
  Object.values(draftSubforms).map((draft) => [
3683
4194
  draft.dataKey,
3684
- draft.rows.filter((row) => row.values._delete !== true).map((row) => childRowPayload(row, false))
4195
+ changedChildPayloads(draft.rows, false)
3685
4196
  ])
3686
4197
  )
3687
4198
  }
3688
4199
  });
3689
- } else if (editing && hasDraftRows) {
4200
+ } else if (editing && hasDraftChanges) {
3690
4201
  if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3691
4202
  if (!compositeUpdate) throw new Error("Composite update handler \u0442\u043E\u0445\u0438\u0440\u0443\u0443\u043B\u0430\u0433\u0434\u0430\u0430\u0433\u04AF\u0439 \u0431\u0430\u0439\u043D\u0430");
3692
4203
  await compositeUpdate.mutateAsync({
@@ -3701,7 +4212,7 @@ function createRuntimeEntryDialogComponent(deps) {
3701
4212
  ...Object.fromEntries(
3702
4213
  Object.values(draftSubforms).map((draft) => [
3703
4214
  draft.dataKey,
3704
- draft.rows.map((row) => childRowPayload(row, true))
4215
+ changedChildPayloads(draft.rows, true)
3705
4216
  ])
3706
4217
  )
3707
4218
  }
@@ -3714,12 +4225,14 @@ function createRuntimeEntryDialogComponent(deps) {
3714
4225
  deps.notifications.success(editing ? "\u041C\u04E9\u0440 \u0445\u0430\u0434\u0433\u0430\u043B\u0430\u0433\u0434\u043B\u0430\u0430" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0433\u0434\u043B\u044D\u044D");
3715
4226
  } catch (error) {
3716
4227
  deps.notifications.error(deps.notifications.errorMessage(error, "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\u0445\u0430\u0434 \u0430\u043B\u0434\u0430\u0430 \u0433\u0430\u0440\u043B\u0430\u0430"));
4228
+ } finally {
4229
+ isSubmittingRef.current = false;
3717
4230
  }
3718
4231
  });
3719
4232
  const saving = isSaving || Boolean(compositeCreate?.isPending || compositeUpdate?.isPending);
3720
4233
  const extraItems = deps.SubformField && view.form?.schema.subforms?.length ? view.form.schema.subforms.map((subform) => ({
3721
4234
  key: subform.key,
3722
- render: () => deps.SubformField ? /* @__PURE__ */ jsx17(
4235
+ render: () => deps.SubformField ? /* @__PURE__ */ jsx20(
3723
4236
  deps.SubformField,
3724
4237
  {
3725
4238
  subform,
@@ -3734,7 +4247,7 @@ function createRuntimeEntryDialogComponent(deps) {
3734
4247
  }
3735
4248
  ) : null
3736
4249
  })) : void 0;
3737
- return /* @__PURE__ */ jsx17(
4250
+ return /* @__PURE__ */ jsx20(
3738
4251
  deps.DialogShell,
3739
4252
  {
3740
4253
  open,
@@ -3742,8 +4255,8 @@ function createRuntimeEntryDialogComponent(deps) {
3742
4255
  title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445",
3743
4256
  description: view.title,
3744
4257
  onClose,
3745
- children: /* @__PURE__ */ jsx17(FormProvider6, { ...form, children: /* @__PURE__ */ jsxs14("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
3746
- view.form ? /* @__PURE__ */ jsx17(
4258
+ children: /* @__PURE__ */ jsx20(FormProvider6, { ...form, children: /* @__PURE__ */ jsxs16("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
4259
+ view.form ? /* @__PURE__ */ jsx20(
3747
4260
  deps.FormFields,
3748
4261
  {
3749
4262
  formId: view.form.id,
@@ -3754,7 +4267,7 @@ function createRuntimeEntryDialogComponent(deps) {
3754
4267
  extraItems
3755
4268
  }
3756
4269
  ) : null,
3757
- /* @__PURE__ */ jsx17(deps.Actions, { isSaving: saving, onClose })
4270
+ /* @__PURE__ */ jsx20(deps.Actions, { isSaving: saving, onClose })
3758
4271
  ] }) })
3759
4272
  }
3760
4273
  );
@@ -3841,7 +4354,7 @@ function validateBuilderFrontendSetup(config) {
3841
4354
  // src/index.ts
3842
4355
  var builderUiPackage = {
3843
4356
  name: "@duke333/builder-ui",
3844
- version: "0.2.2"
4357
+ version: "0.2.5"
3845
4358
  };
3846
4359
  export {
3847
4360
  BUILDER_EDITOR_NONE_VALUE,
@@ -3849,6 +4362,9 @@ export {
3849
4362
  BuilderGrid,
3850
4363
  BuilderProvider,
3851
4364
  BuilderView,
4365
+ ReadyFileField,
4366
+ ReadyRichTextField,
4367
+ RichTextContent,
3852
4368
  builderEditorOptionsToText,
3853
4369
  builderEditorSearchFieldsToText,
3854
4370
  builderEditorTextToOptions,
@@ -3891,9 +4407,11 @@ export {
3891
4407
  getBuilderEditorTriggerRoute,
3892
4408
  nextBuilderFormLayoutGroupId,
3893
4409
  parseBuilderFormLayoutDragPayload,
4410
+ richTextToPlainText,
3894
4411
  serializeBuilderFormLayoutDragPayload,
3895
4412
  shouldHandleDynamicViewRowClick,
3896
4413
  swapBuilderFormLayoutItems,
4414
+ toRichTextDocument,
3897
4415
  useBuilderFormLayoutEditor,
3898
4416
  useBuilderRuntime,
3899
4417
  validateBuilderFrontendSetup