@duke333/builder-ui 0.2.3 → 0.2.4

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 useState6 } 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 { useRef as useRef4 } 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,47 @@ 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) => {
934
+ return /* @__PURE__ */ jsxs4("div", { className: "builder-form-fields", children: [
935
+ schema.layout?.groups.map((group) => /* @__PURE__ */ jsxs4("fieldset", { className: "builder-fieldset", children: [
936
+ group.title ? /* @__PURE__ */ jsx4("legend", { children: group.title }) : null,
937
+ /* @__PURE__ */ jsx4("div", { className: "builder-form-grid", children: group.fields.map((item) => {
586
938
  const field = fields.get(item.key);
587
939
  if (!field) return null;
588
940
  rendered.add(field.key);
589
- return /* @__PURE__ */ jsx2("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx2(ReadyField, { field, formId, viewId }) }, field.key);
941
+ return /* @__PURE__ */ jsx4("div", { style: { gridColumn: `span ${item.span}` }, children: /* @__PURE__ */ jsx4(ReadyField, { field, formId, viewId, parentValues }) }, field.key);
590
942
  }) })
591
943
  ] }, 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))
944
+ /* @__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)) }),
945
+ extraItems.map((item) => /* @__PURE__ */ jsx4("div", { children: item.render() }, item.key))
594
946
  ] });
595
947
  }
596
948
 
597
949
  // src/ready/ReadyOverlay.tsx
598
- import { useEffect, useId, useRef as useRef3, useState as useState2 } from "react";
950
+ import { useEffect as useEffect2, useId as useId2, useRef as useRef5, useState as useState3 } from "react";
599
951
  import { createPortal } from "react-dom";
600
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
952
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
601
953
  function ReadyOverlay({
602
954
  open,
603
955
  presentation = "dialog",
@@ -606,15 +958,15 @@ function ReadyOverlay({
606
958
  onClose,
607
959
  children
608
960
  }) {
609
- const panelRef = useRef3(null);
610
- const onCloseRef = useRef3(onClose);
611
- const [portalRoot, setPortalRoot] = useState2(null);
961
+ const panelRef = useRef5(null);
962
+ const onCloseRef = useRef5(onClose);
963
+ const [portalRoot, setPortalRoot] = useState3(null);
612
964
  onCloseRef.current = onClose;
613
- const titleId = useId();
614
- useEffect(() => {
965
+ const titleId = useId2();
966
+ useEffect2(() => {
615
967
  setPortalRoot(document.body);
616
968
  }, []);
617
- useEffect(() => {
969
+ useEffect2(() => {
618
970
  if (!open || !portalRoot) return;
619
971
  const previous = document.activeElement;
620
972
  panelRef.current?.focus();
@@ -648,7 +1000,7 @@ function ReadyOverlay({
648
1000
  }, [open, portalRoot]);
649
1001
  if (!open || !portalRoot) return null;
650
1002
  return createPortal(
651
- /* @__PURE__ */ jsx3("div", { className: "builder-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs3(
1003
+ /* @__PURE__ */ jsx5("div", { className: "builder-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && onClose(), children: /* @__PURE__ */ jsxs5(
652
1004
  "div",
653
1005
  {
654
1006
  ref: panelRef,
@@ -658,14 +1010,14 @@ function ReadyOverlay({
658
1010
  "aria-labelledby": titleId,
659
1011
  tabIndex: -1,
660
1012
  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
1013
+ /* @__PURE__ */ jsxs5("header", { className: "builder-overlay__header", children: [
1014
+ /* @__PURE__ */ jsxs5("div", { children: [
1015
+ /* @__PURE__ */ jsx5("h2", { id: titleId, className: "builder-title", children: title }),
1016
+ description ? /* @__PURE__ */ jsx5("p", { className: "builder-description", children: description }) : null
665
1017
  ] }),
666
- /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-icon-button", "aria-label": "\u0425\u0430\u0430\u0445", onClick: onClose, children: "\xD7" })
1018
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-icon-button", "aria-label": "\u0425\u0430\u0430\u0445", onClick: onClose, children: "\xD7" })
667
1019
  ] }),
668
- /* @__PURE__ */ jsx3("div", { className: "builder-overlay__body", children })
1020
+ /* @__PURE__ */ jsx5("div", { className: "builder-overlay__body", children })
669
1021
  ]
670
1022
  }
671
1023
  ) }),
@@ -681,29 +1033,29 @@ function ReadyConfirmDialog({
681
1033
  onClose,
682
1034
  onConfirm
683
1035
  }) {
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 })
1036
+ return /* @__PURE__ */ jsx5(ReadyOverlay, { open, title, description, onClose, children: /* @__PURE__ */ jsxs5("div", { className: "builder-actions", children: [
1037
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-button builder-button--ghost", onClick: onClose, children: "\u0411\u043E\u043B\u0438\u0445" }),
1038
+ /* @__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
1039
  ] }) });
688
1040
  }
689
1041
  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 })
1042
+ return /* @__PURE__ */ jsxs5("div", { className: "builder-state builder-state--error", role: "alert", children: [
1043
+ /* @__PURE__ */ jsx5("strong", { children: title }),
1044
+ /* @__PURE__ */ jsx5("span", { children: description })
693
1045
  ] });
694
1046
  }
695
1047
 
696
1048
  // 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";
1049
+ import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef6, useState as useState5 } from "react";
1050
+ import { FormProvider, useForm, useFormContext as useFormContext4, useWatch as useWatch4 } from "react-hook-form";
699
1051
 
700
1052
  // 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";
1053
+ import { useMemo as useMemo2, useState as useState4 } from "react";
1054
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
703
1055
  function useReadyTableState({ pageSize = 20 } = {}) {
704
- const [page, setPage] = useState3(1);
705
- const [search, setSearchValue] = useState3("");
706
- const [sort, setSort] = useState3();
1056
+ const [page, setPage] = useState4(1);
1057
+ const [search, setSearchValue] = useState4("");
1058
+ const [sort, setSort] = useState4();
707
1059
  return {
708
1060
  query: { page, pageSize, search: search || void 0, sort },
709
1061
  page,
@@ -722,7 +1074,7 @@ function useReadyTableState({ pageSize = 20 } = {}) {
722
1074
  };
723
1075
  }
724
1076
  function useReadyTable(args) {
725
- const [selectedIds, setSelectedIds] = useState3([]);
1077
+ const [selectedIds, setSelectedIds] = useState4([]);
726
1078
  return useMemo2(
727
1079
  () => ({
728
1080
  ...args,
@@ -756,14 +1108,14 @@ function ReadyDataGrid({
756
1108
  selectable = false
757
1109
  }) {
758
1110
  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
1111
+ return /* @__PURE__ */ jsxs6("section", { className: "builder-card builder-grid", "aria-busy": isLoading || void 0, children: [
1112
+ /* @__PURE__ */ jsxs6("header", { className: "builder-grid__header", children: [
1113
+ /* @__PURE__ */ jsxs6("div", { children: [
1114
+ title ? /* @__PURE__ */ jsx6("h2", { className: "builder-title", children: title }) : null,
1115
+ description ? /* @__PURE__ */ jsx6("p", { className: "builder-description", children: description }) : null
764
1116
  ] }),
765
- /* @__PURE__ */ jsxs4("div", { className: "builder-grid__toolbar", children: [
766
- /* @__PURE__ */ jsx4(
1117
+ /* @__PURE__ */ jsxs6("div", { className: "builder-grid__toolbar", children: [
1118
+ /* @__PURE__ */ jsx6(
767
1119
  "input",
768
1120
  {
769
1121
  className: "builder-input builder-grid__search",
@@ -777,19 +1129,19 @@ function ReadyDataGrid({
777
1129
  toolbarExtra
778
1130
  ] })
779
1131
  ] }),
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))
1132
+ /* @__PURE__ */ jsxs6("div", { className: "builder-table-wrap", children: [
1133
+ /* @__PURE__ */ jsxs6("table", { className: "builder-table", children: [
1134
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs6("tr", { children: [
1135
+ selectable ? /* @__PURE__ */ jsx6("th", { "aria-label": "\u0421\u043E\u043D\u0433\u043E\u043B\u0442" }) : null,
1136
+ 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
1137
  ] }) }),
786
- /* @__PURE__ */ jsx4("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs4(
1138
+ /* @__PURE__ */ jsx6("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs6(
787
1139
  "tr",
788
1140
  {
789
1141
  className: onRowClick ? "builder-row-clickable" : void 0,
790
1142
  onClick: (event) => onRowClick?.(entry, event),
791
1143
  children: [
792
- selectable ? /* @__PURE__ */ jsx4("td", { children: /* @__PURE__ */ jsx4(
1144
+ selectable ? /* @__PURE__ */ jsx6("td", { children: /* @__PURE__ */ jsx6(
793
1145
  "input",
794
1146
  {
795
1147
  type: "checkbox",
@@ -799,31 +1151,31 @@ function ReadyDataGrid({
799
1151
  onChange: () => controller.toggleSelected(entry.id)
800
1152
  }
801
1153
  ) }) : null,
802
- controller.columns.map((column) => /* @__PURE__ */ jsx4("td", { className: `builder-align-${column.align}`, children: cellValue(entry, column) }, column.key))
1154
+ controller.columns.map((column) => /* @__PURE__ */ jsx6("td", { className: `builder-align-${column.align}`, children: cellValue(entry, column) }, column.key))
803
1155
  ]
804
1156
  },
805
1157
  entry.id
806
1158
  )) })
807
1159
  ] }),
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
1160
+ isLoading ? /* @__PURE__ */ jsx6("div", { className: "builder-state", children: "\u0423\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" }) : null,
1161
+ !isLoading && controller.data.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "builder-state", children: [
1162
+ /* @__PURE__ */ jsx6("strong", { children: emptyTitle }),
1163
+ emptyDescription ? /* @__PURE__ */ jsx6("span", { children: emptyDescription }) : null
812
1164
  ] }) : null
813
1165
  ] }),
814
- /* @__PURE__ */ jsxs4("footer", { className: "builder-pagination", children: [
815
- /* @__PURE__ */ jsxs4("span", { children: [
1166
+ /* @__PURE__ */ jsxs6("footer", { className: "builder-pagination", children: [
1167
+ /* @__PURE__ */ jsxs6("span", { children: [
816
1168
  controller.rowCount,
817
1169
  " \u043C\u04E9\u0440"
818
1170
  ] }),
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: [
1171
+ /* @__PURE__ */ jsxs6("div", { children: [
1172
+ /* @__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" }),
1173
+ /* @__PURE__ */ jsxs6("span", { children: [
822
1174
  controller.state.page,
823
1175
  " / ",
824
1176
  totalPages
825
1177
  ] }),
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" })
1178
+ /* @__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
1179
  ] })
828
1180
  ] })
829
1181
  ] });
@@ -833,7 +1185,7 @@ function readyColumns(columns) {
833
1185
  }
834
1186
 
835
1187
  // src/ready/ReadySubform.tsx
836
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1188
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
837
1189
  function linkedValue(entry, field) {
838
1190
  if (!entry) return void 0;
839
1191
  const value = field === "id" ? entry.id : entry.values[field];
@@ -847,7 +1199,7 @@ function makeDraftEntry(viewId, values, editing) {
847
1199
  return {
848
1200
  id: editing?.id ?? (globalThis.crypto?.randomUUID?.() ?? `draft-${Date.now()}`),
849
1201
  viewId,
850
- values: editing ? values.values : { ...values.values, _draftNew: true },
1202
+ values: editing ? { ...values.values, _draftDirty: true } : { ...values.values, _draftNew: true },
851
1203
  version: editing?.version ?? 0,
852
1204
  createdAt: editing?.createdAt ?? now,
853
1205
  updatedAt: now
@@ -855,9 +1207,12 @@ function makeDraftEntry(viewId, values, editing) {
855
1207
  }
856
1208
  function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
857
1209
  const { hooks, notify } = useBuilderRuntime();
858
- const [open, setOpen] = useState4(false);
859
- const [editing, setEditing] = useState4(null);
860
- const initialized = useRef4(false);
1210
+ const parentForm = useFormContext4();
1211
+ const watchedParentValues = useWatch4({ control: parentForm.control, name: "values" });
1212
+ const parentValues = watchedParentValues && typeof watchedParentValues === "object" && !Array.isArray(watchedParentValues) ? watchedParentValues : void 0;
1213
+ const [open, setOpen] = useState5(false);
1214
+ const [editing, setEditing] = useState5(null);
1215
+ const initialized = useRef6(false);
861
1216
  const parentValue = linkedValue(parentEntry, subform.parentField);
862
1217
  const viewQuery = hooks.useRuntimeBuilderView(subform.viewId, Boolean(subform.viewId));
863
1218
  const tableState = useReadyTableState({ pageSize: 100 });
@@ -868,7 +1223,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
868
1223
  const entriesQuery = hooks.useBuilderViewEntries(subform.viewId, filterQuery, Boolean(parentValue));
869
1224
  const view = viewQuery.data;
870
1225
  const source = view?.list?.source?.type === "dbTable" ? view.list.source.tableName : void 0;
871
- useEffect2(() => {
1226
+ useEffect3(() => {
872
1227
  if (initialized.current || !view || !entriesQuery.data || !parentValue) return;
873
1228
  initialized.current = true;
874
1229
  onRowsChange({ key: subform.key, dataKey: dataKey(view.id, source), rows: entriesQuery.data.items });
@@ -888,7 +1243,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
888
1243
  sortable: false,
889
1244
  hidden: false,
890
1245
  align: "right",
891
- render: (row) => /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-link builder-link--danger", onClick: (event) => {
1246
+ render: (row) => /* @__PURE__ */ jsx7("button", { type: "button", className: "builder-link builder-link--danger", onClick: (event) => {
892
1247
  event.stopPropagation();
893
1248
  removeRow(row);
894
1249
  }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
@@ -922,12 +1277,12 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
922
1277
  close();
923
1278
  });
924
1279
  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`) });
1280
+ 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
1281
  }
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: () => {
1282
+ return /* @__PURE__ */ jsxs7("section", { className: "builder-subform", children: [
1283
+ /* @__PURE__ */ jsxs7("div", { className: "builder-subform__header", children: [
1284
+ /* @__PURE__ */ jsx7("strong", { children: subform.label }),
1285
+ /* @__PURE__ */ jsxs7("button", { type: "button", className: "builder-button builder-button--secondary", disabled: !view?.form, onClick: () => {
931
1286
  setEditing(null);
932
1287
  setOpen(true);
933
1288
  }, children: [
@@ -935,7 +1290,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
935
1290
  subform.buttonLabel ?? "\u041D\u044D\u043C\u044D\u0445"
936
1291
  ] })
937
1292
  ] }),
938
- visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx5(
1293
+ visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx7(
939
1294
  ReadyDataGrid,
940
1295
  {
941
1296
  controller: table,
@@ -947,26 +1302,34 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
947
1302
  emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430"
948
1303
  }
949
1304
  ) : 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" })
1305
+ 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: [
1306
+ /* @__PURE__ */ jsx7(
1307
+ ReadyFields,
1308
+ {
1309
+ formId: view.form.id,
1310
+ viewId: view.id,
1311
+ schema: view.form.schema,
1312
+ parentValues
1313
+ }
1314
+ ),
1315
+ /* @__PURE__ */ jsxs7("div", { className: "builder-actions", children: [
1316
+ /* @__PURE__ */ jsx7("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1317
+ /* @__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
1318
  ] })
956
1319
  ] }) }) }) : null
957
1320
  ] });
958
1321
  }
959
1322
 
960
1323
  // src/ready/BuilderRuntimeComponents.tsx
961
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1324
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
962
1325
  function DefaultBuilderForm({ formId }) {
963
1326
  const { hooks, notify } = useBuilderRuntime();
964
1327
  const query = hooks.useRuntimeBuilderForm(formId);
965
1328
  const save = hooks.useSaveRuntimeBuilderFormEntry(formId);
966
1329
  const defaults = useMemo4(() => createBuilderFormDefaultValues(query.data?.schema), [query.data]);
967
1330
  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" });
1331
+ 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`) });
1332
+ if (!query.data) return /* @__PURE__ */ jsx8("div", { className: "builder-state", children: "Form \u0443\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" });
970
1333
  const submit = form.handleSubmit(async (input) => {
971
1334
  try {
972
1335
  await save.mutateAsync(input);
@@ -976,12 +1339,12 @@ function DefaultBuilderForm({ formId }) {
976
1339
  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
1340
  }
978
1341
  });
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" }) })
1342
+ return /* @__PURE__ */ jsxs8("section", { className: "builder-card", children: [
1343
+ /* @__PURE__ */ jsx8("h2", { className: "builder-title", children: query.data.title }),
1344
+ query.data.description ? /* @__PURE__ */ jsx8("p", { className: "builder-description", children: query.data.description }) : null,
1345
+ /* @__PURE__ */ jsx8(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs8("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
1346
+ /* @__PURE__ */ jsx8(ReadyFields, { formId, schema: query.data.schema }),
1347
+ /* @__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
1348
  ] }) })
986
1349
  ] });
987
1350
  }
@@ -997,8 +1360,8 @@ function DefaultBuilderGrid({ listId }) {
997
1360
  state,
998
1361
  getRowId: (row) => row.id
999
1362
  });
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 });
1363
+ 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`) });
1364
+ return /* @__PURE__ */ jsx8(ReadyDataGrid, { title: listQuery.data?.title ?? "Grid", description: listQuery.data?.description, controller: table, isLoading: listQuery.isPending || entriesQuery.isPending });
1002
1365
  }
1003
1366
  function dbTableName(view) {
1004
1367
  if (view.list?.source?.type === "dbTable") return view.list.source.tableName;
@@ -1009,9 +1372,16 @@ function childPayload(row, includeIdentity) {
1009
1372
  const values = Object.fromEntries(Object.entries(row.values).filter(([key]) => key === "_delete" || !key.startsWith("_")));
1010
1373
  return includeIdentity && row.values._draftNew !== true ? { id: row.id, version: row.version, ...values } : values;
1011
1374
  }
1375
+ function hasSubformChange(row) {
1376
+ return row.values._delete === true || row.values._draftNew === true || row.values._draftDirty === true;
1377
+ }
1378
+ function changedSubformPayloads(rows, includeIdentity) {
1379
+ return rows.filter(hasSubformChange).filter((row) => includeIdentity || row.values._delete !== true).map((row) => childPayload(row, includeIdentity));
1380
+ }
1012
1381
  function BuilderEntryEditor({ view, editing, open, onClose }) {
1013
1382
  const { hooks, notify } = useBuilderRuntime();
1014
- const [subforms, setSubforms] = useState5({});
1383
+ const [subforms, setSubforms] = useState6({});
1384
+ const isSubmittingRef = useRef7(false);
1015
1385
  const save = hooks.useSaveBuilderViewEntry(view.id);
1016
1386
  const createComposite = hooks.useCreateCompositeBuilderViewEntry(view.id);
1017
1387
  const updateComposite = hooks.useUpdateCompositeBuilderViewEntry(view.id);
@@ -1022,11 +1392,13 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1022
1392
  onClose();
1023
1393
  };
1024
1394
  const submit = form.handleSubmit(async (input) => {
1395
+ if (isSubmittingRef.current) return;
1396
+ isSubmittingRef.current = true;
1025
1397
  try {
1026
1398
  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)))]));
1399
+ const hasSubformChanges = Object.values(subforms).some((item) => item.rows.some(hasSubformChange));
1400
+ if (hasSubformChanges && mainKey) {
1401
+ const children = Object.fromEntries(Object.values(subforms).map((item) => [item.dataKey, changedSubformPayloads(item.rows, Boolean(editing))]));
1030
1402
  if (editing) {
1031
1403
  await updateComposite.mutateAsync({ id: editing.id, input: { data: { [mainKey]: { id: editing.id, version: input.version, ...input.values }, ...children } } });
1032
1404
  } else {
@@ -1039,24 +1411,26 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1039
1411
  close();
1040
1412
  } catch (error) {
1041
1413
  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") });
1414
+ } finally {
1415
+ isSubmittingRef.current = false;
1042
1416
  }
1043
1417
  });
1044
1418
  const saving = save.isPending || createComposite.isPending || updateComposite.isPending;
1045
1419
  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" })
1420
+ 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: [
1421
+ /* @__PURE__ */ jsx8(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
1422
+ view.form.schema.subforms.map((subform) => /* @__PURE__ */ jsx8(ReadySubform, { subform, parentEntry: editing, rows: subforms[subform.key]?.rows ?? [], onRowsChange: updateRows }, subform.key)),
1423
+ /* @__PURE__ */ jsxs8("div", { className: "builder-actions builder-actions--sticky", children: [
1424
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1425
+ /* @__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
1426
  ] })
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." }) });
1427
+ ] }) }) : /* @__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
1428
  }
1055
1429
  function DefaultBuilderView({ viewId }) {
1056
1430
  const { hooks, notify } = useBuilderRuntime();
1057
- const [editing, setEditing] = useState5(null);
1058
- const [editorOpen, setEditorOpen] = useState5(false);
1059
- const [pendingDelete, setPendingDelete] = useState5(null);
1431
+ const [editing, setEditing] = useState6(null);
1432
+ const [editorOpen, setEditorOpen] = useState6(false);
1433
+ const [pendingDelete, setPendingDelete] = useState6(null);
1060
1434
  const viewQuery = hooks.useRuntimeBuilderView(viewId);
1061
1435
  const state = useReadyTableState();
1062
1436
  const entriesQuery = hooks.useBuilderViewEntries(viewId, state.query);
@@ -1071,13 +1445,13 @@ function DefaultBuilderView({ viewId }) {
1071
1445
  sortable: false,
1072
1446
  hidden: false,
1073
1447
  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) => {
1448
+ render: (entry) => /* @__PURE__ */ jsxs8("div", { className: "builder-row-actions", "data-builder-row-action": true, children: [
1449
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--ghost", onClick: (event) => {
1076
1450
  event.stopPropagation();
1077
1451
  setEditing(entry);
1078
1452
  setEditorOpen(true);
1079
1453
  }, children: "\u0417\u0430\u0441\u0430\u0445" }),
1080
- /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--danger", onClick: (event) => {
1454
+ /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--danger", onClick: (event) => {
1081
1455
  event.stopPropagation();
1082
1456
  setPendingDelete(entry);
1083
1457
  }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
@@ -1086,9 +1460,9 @@ function DefaultBuilderView({ viewId }) {
1086
1460
  return result;
1087
1461
  }, [view]);
1088
1462
  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(
1463
+ 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`) });
1464
+ return /* @__PURE__ */ jsxs8("div", { className: "builder-runtime", children: [
1465
+ /* @__PURE__ */ jsx8(
1092
1466
  ReadyDataGrid,
1093
1467
  {
1094
1468
  title: view?.title ?? "View",
@@ -1099,14 +1473,14 @@ function DefaultBuilderView({ viewId }) {
1099
1473
  setEditing(entry);
1100
1474
  setEditorOpen(true);
1101
1475
  },
1102
- toolbarExtra: /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--primary", disabled: !view?.form, onClick: () => {
1476
+ toolbarExtra: /* @__PURE__ */ jsx8("button", { type: "button", className: "builder-button builder-button--primary", disabled: !view?.form, onClick: () => {
1103
1477
  setEditing(null);
1104
1478
  setEditorOpen(true);
1105
1479
  }, children: "+ \u041D\u044D\u043C\u044D\u0445" })
1106
1480
  }
1107
1481
  ),
1108
- view ? /* @__PURE__ */ jsx6(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1109
- /* @__PURE__ */ jsx6(
1482
+ view ? /* @__PURE__ */ jsx8(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1483
+ /* @__PURE__ */ jsx8(
1110
1484
  ReadyConfirmDialog,
1111
1485
  {
1112
1486
  open: Boolean(pendingDelete),
@@ -1131,17 +1505,52 @@ function DefaultBuilderView({ viewId }) {
1131
1505
  function BuilderForm(props) {
1132
1506
  const { components } = useBuilderRuntime();
1133
1507
  const Component = components.Form;
1134
- return Component ? /* @__PURE__ */ jsx6(Component, { ...props }) : /* @__PURE__ */ jsx6(DefaultBuilderForm, { ...props });
1508
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderForm, { ...props });
1135
1509
  }
1136
1510
  function BuilderGrid(props) {
1137
1511
  const { components } = useBuilderRuntime();
1138
1512
  const Component = components.Grid;
1139
- return Component ? /* @__PURE__ */ jsx6(Component, { ...props }) : /* @__PURE__ */ jsx6(DefaultBuilderGrid, { ...props });
1513
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderGrid, { ...props });
1140
1514
  }
1141
1515
  function BuilderView(props) {
1142
1516
  const { components } = useBuilderRuntime();
1143
1517
  const Component = components.View;
1144
- return Component ? /* @__PURE__ */ jsx6(Component, { ...props }) : /* @__PURE__ */ jsx6(DefaultBuilderView, { ...props });
1518
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderView, { ...props });
1519
+ }
1520
+
1521
+ // src/RichTextContent.tsx
1522
+ import { Fragment } from "react";
1523
+ import { jsx as jsx9 } from "react/jsx-runtime";
1524
+ function renderChildren(node) {
1525
+ return (node.content ?? []).map((child, index) => renderNode(child, index));
1526
+ }
1527
+ function renderText(node, key) {
1528
+ let value = node.text ?? "";
1529
+ for (const mark of node.marks ?? []) {
1530
+ if (mark.type === "bold") value = /* @__PURE__ */ jsx9("strong", { children: value });
1531
+ if (mark.type === "italic") value = /* @__PURE__ */ jsx9("em", { children: value });
1532
+ if (mark.type === "strike") value = /* @__PURE__ */ jsx9("s", { children: value });
1533
+ }
1534
+ return /* @__PURE__ */ jsx9(Fragment, { children: value }, key);
1535
+ }
1536
+ function renderNode(node, key) {
1537
+ if (node.type === "text") return renderText(node, key);
1538
+ if (node.type === "hardBreak") return /* @__PURE__ */ jsx9("br", {}, key);
1539
+ if (node.type === "paragraph") return /* @__PURE__ */ jsx9("p", { children: renderChildren(node) }, key);
1540
+ if (node.type === "heading") {
1541
+ const level = node.attrs?.level;
1542
+ if (level === 3) return /* @__PURE__ */ jsx9("h3", { children: renderChildren(node) }, key);
1543
+ return /* @__PURE__ */ jsx9("h2", { children: renderChildren(node) }, key);
1544
+ }
1545
+ if (node.type === "bulletList") return /* @__PURE__ */ jsx9("ul", { children: renderChildren(node) }, key);
1546
+ if (node.type === "orderedList") return /* @__PURE__ */ jsx9("ol", { children: renderChildren(node) }, key);
1547
+ if (node.type === "listItem") return /* @__PURE__ */ jsx9("li", { children: renderChildren(node) }, key);
1548
+ if (node.type === "blockquote") return /* @__PURE__ */ jsx9("blockquote", { children: renderChildren(node) }, key);
1549
+ return /* @__PURE__ */ jsx9(Fragment, { children: renderChildren(node) }, key);
1550
+ }
1551
+ function RichTextContent({ className, value }) {
1552
+ const document2 = toRichTextDocument(value);
1553
+ return /* @__PURE__ */ jsx9("div", { className, children: (document2.content ?? []).map((node, index) => renderNode(node, index)) });
1145
1554
  }
1146
1555
 
1147
1556
  // src/admin/editorState.ts
@@ -1189,7 +1598,7 @@ function clampLayoutSpan(span, columns) {
1189
1598
  return Math.max(1, Math.min(columns, Math.trunc(span)));
1190
1599
  }
1191
1600
  function builderFormEditorDefaultSpan(field) {
1192
- if (field.type === "textarea" || field.type === "checkbox") return 12;
1601
+ if (field.type === "textarea" || field.type === "richtext" || field.type === "checkbox") return 12;
1193
1602
  return 6;
1194
1603
  }
1195
1604
  function builderFormEditorDefaultLayoutGroups(fields, subforms = []) {
@@ -1256,6 +1665,10 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
1256
1665
  required: field.required,
1257
1666
  hidden: field.hidden ?? false,
1258
1667
  disabled: field.disabled ?? false,
1668
+ storage: field.storage ?? "s3",
1669
+ contentKind: field.contentKind ?? "image",
1670
+ multiple: field.multiple ?? false,
1671
+ maxMegabytes: field.maxBytes ? field.maxBytes / (1024 * 1024) : 10,
1259
1672
  placeholder: field.placeholder ?? "",
1260
1673
  optionsText: builderEditorOptionsToText(field.options),
1261
1674
  optionsMode: field.optionsSource?.type === "dbTable" ? "table" : "static",
@@ -1338,6 +1751,10 @@ function builderFormEditorFieldsFromTable(table) {
1338
1751
  required: !column.nullable,
1339
1752
  hidden: false,
1340
1753
  disabled: false,
1754
+ storage: "s3",
1755
+ contentKind: "image",
1756
+ multiple: false,
1757
+ maxMegabytes: 10,
1341
1758
  placeholder: column.label,
1342
1759
  optionsText: "",
1343
1760
  optionsMode: "static",
@@ -1374,6 +1791,10 @@ function builderFormEditorInputFromValues(values) {
1374
1791
  required: field.required,
1375
1792
  hidden: field.hidden,
1376
1793
  disabled: field.disabled,
1794
+ storage: field.type === "file" ? field.storage : void 0,
1795
+ contentKind: field.type === "file" ? field.contentKind : void 0,
1796
+ multiple: field.type === "file" ? field.multiple : void 0,
1797
+ maxBytes: field.type === "file" && typeof field.maxMegabytes === "number" && field.maxMegabytes > 0 ? Math.round(field.maxMegabytes * 1024 * 1024) : void 0,
1377
1798
  placeholder: field.placeholder?.trim() || field.label,
1378
1799
  options: field.type === "select" && field.optionsMode === "static" ? builderEditorTextToOptions(field.optionsText) : void 0,
1379
1800
  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 ? {
@@ -1464,7 +1885,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
1464
1885
  }
1465
1886
 
1466
1887
  // src/admin/BuilderDefaultEditorBodies.tsx
1467
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1888
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1468
1889
  var styles = {
1469
1890
  page: {
1470
1891
  display: "grid",
@@ -1585,7 +2006,7 @@ var styles = {
1585
2006
  }
1586
2007
  };
1587
2008
  function optionItems(options) {
1588
- return options.map((option) => /* @__PURE__ */ jsx7("option", { value: option.value, children: option.label }, option.value));
2009
+ return options.map((option) => /* @__PURE__ */ jsx10("option", { value: option.value, children: option.label }, option.value));
1589
2010
  }
1590
2011
  function createBuilderDefaultFormEditorBody(options) {
1591
2012
  return function BuilderDefaultFormEditorBody({
@@ -1603,63 +2024,63 @@ function createBuilderDefaultFormEditorBody(options) {
1603
2024
  isSaving,
1604
2025
  importFieldsFromTable
1605
2026
  }) {
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." })
2027
+ return /* @__PURE__ */ jsxs9("div", { style: styles.page, children: [
2028
+ /* @__PURE__ */ jsxs9("div", { style: styles.header, children: [
2029
+ /* @__PURE__ */ jsxs9("div", { children: [
2030
+ /* @__PURE__ */ jsx10("h1", { style: styles.title, children: formId ? "Edit Dynamic Form" : "New Dynamic Form" }),
2031
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Configure fields, source mapping, layout, and triggers." })
1611
2032
  ] }),
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" })
2033
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2034
+ /* @__PURE__ */ jsx10("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
2035
+ /* @__PURE__ */ jsx10("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
1615
2036
  ] })
1616
2037
  ] }),
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 }) })
2038
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2039
+ /* @__PURE__ */ jsx10("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Details" }) }),
2040
+ /* @__PURE__ */ jsxs9("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
2041
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2042
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Title" }),
2043
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("title", { required: true }) })
1623
2044
  ] }),
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") })
2045
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2046
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Description" }),
2047
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("description") })
1627
2048
  ] }),
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" })
2049
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2050
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Presentation" }),
2051
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("presentation"), children: [
2052
+ /* @__PURE__ */ jsx10("option", { value: "dialog", children: "Dialog" }),
2053
+ /* @__PURE__ */ jsx10("option", { value: "drawer", children: "Drawer" })
1633
2054
  ] })
1634
2055
  ] }),
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" })
2056
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2057
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Datasource" }),
2058
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("sourceType"), children: [
2059
+ /* @__PURE__ */ jsx10("option", { value: "none", children: "None" }),
2060
+ /* @__PURE__ */ jsx10("option", { value: "dbTable", children: "DB table" }),
2061
+ /* @__PURE__ */ jsx10("option", { value: "apiEndpoint", children: "API endpoint" })
1641
2062
  ] })
1642
2063
  ] }),
1643
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1644
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1645
- /* @__PURE__ */ jsxs7(
2064
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2065
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Table" }),
2066
+ /* @__PURE__ */ jsxs9(
1646
2067
  "select",
1647
2068
  {
1648
2069
  style: styles.input,
1649
2070
  value: sourceTable,
1650
2071
  ...form.register("sourceTable"),
1651
2072
  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))
2073
+ /* @__PURE__ */ jsx10("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
2074
+ tables.map((table) => /* @__PURE__ */ jsx10("option", { value: table.name, children: table.label ?? table.name }, table.name))
1654
2075
  ]
1655
2076
  }
1656
2077
  )
1657
2078
  ] }) : 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") })
2079
+ sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2080
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "API base path" }),
2081
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("apiBasePath") })
1661
2082
  ] }) : null,
1662
- sourceType === "dbTable" ? /* @__PURE__ */ jsx7("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx7(
2083
+ sourceType === "dbTable" ? /* @__PURE__ */ jsx10("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx10(
1663
2084
  "button",
1664
2085
  {
1665
2086
  type: "button",
@@ -1671,13 +2092,13 @@ function createBuilderDefaultFormEditorBody(options) {
1671
2092
  ) }) : null
1672
2093
  ] })
1673
2094
  ] }),
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." })
2095
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2096
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2097
+ /* @__PURE__ */ jsxs9("div", { children: [
2098
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Fields" }),
2099
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Runtime form inputs." })
1679
2100
  ] }),
1680
- /* @__PURE__ */ jsx7(
2101
+ /* @__PURE__ */ jsx10(
1681
2102
  "button",
1682
2103
  {
1683
2104
  type: "button",
@@ -1695,18 +2116,18 @@ function createBuilderDefaultFormEditorBody(options) {
1695
2116
  }
1696
2117
  )
1697
2118
  ] }),
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`) })
2119
+ fieldArray.fields.map((field, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2120
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2121
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Key" }),
2122
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`fields.${index}.key`) })
1702
2123
  ] }),
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`) })
2124
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2125
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Label" }),
2126
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`fields.${index}.label`) })
1706
2127
  ] }),
1707
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1708
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Type" }),
1709
- /* @__PURE__ */ jsx7(
2128
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2129
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Type" }),
2130
+ /* @__PURE__ */ jsx10(
1710
2131
  "select",
1711
2132
  {
1712
2133
  style: styles.input,
@@ -1715,27 +2136,51 @@ function createBuilderDefaultFormEditorBody(options) {
1715
2136
  }
1716
2137
  )
1717
2138
  ] }),
1718
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1719
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.required`) }),
2139
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2140
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.required`) }),
1720
2141
  "Required"
1721
2142
  ] }),
1722
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1723
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.hidden`) }),
2143
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2144
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.hidden`) }),
1724
2145
  "Hidden"
1725
2146
  ] }),
1726
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1727
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
2147
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2148
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.disabled`) }),
1728
2149
  "Disabled"
1729
2150
  ] }),
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`) })
2151
+ fields[index]?.type === "file" ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
2152
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2153
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Storage" }),
2154
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`fields.${index}.storage`), children: [
2155
+ /* @__PURE__ */ jsx10("option", { value: "s3", children: "S3" }),
2156
+ /* @__PURE__ */ jsx10("option", { value: "server", children: "Server" })
2157
+ ] })
2158
+ ] }),
2159
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2160
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Content type" }),
2161
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`fields.${index}.contentKind`), children: [
2162
+ /* @__PURE__ */ jsx10("option", { value: "image", children: "Image" }),
2163
+ /* @__PURE__ */ jsx10("option", { value: "file", children: "File" })
2164
+ ] })
2165
+ ] }),
2166
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2167
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`fields.${index}.multiple`) }),
2168
+ "Multiple"
2169
+ ] }),
2170
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2171
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Max size (MB)" }),
2172
+ /* @__PURE__ */ jsx10("input", { type: "number", min: "1", max: "100", style: styles.input, ...form.register(`fields.${index}.maxMegabytes`, { valueAsNumber: true }) })
2173
+ ] })
2174
+ ] }) : null,
2175
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2176
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Placeholder" }),
2177
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`fields.${index}.placeholder`) })
1733
2178
  ] }),
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`) })
2179
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2180
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Static options" }),
2181
+ /* @__PURE__ */ jsx10("textarea", { style: styles.textarea, ...form.register(`fields.${index}.optionsText`) })
1737
2182
  ] }),
1738
- /* @__PURE__ */ jsx7("div", { style: styles.actions, children: /* @__PURE__ */ jsx7(
2183
+ /* @__PURE__ */ jsx10("div", { style: styles.actions, children: /* @__PURE__ */ jsx10(
1739
2184
  "button",
1740
2185
  {
1741
2186
  type: "button",
@@ -1747,13 +2192,13 @@ function createBuilderDefaultFormEditorBody(options) {
1747
2192
  ) })
1748
2193
  ] }, field.id))
1749
2194
  ] }),
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." })
2195
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2196
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2197
+ /* @__PURE__ */ jsxs9("div", { children: [
2198
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Layout" }),
2199
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Default layout can be regenerated from current fields." })
1755
2200
  ] }),
1756
- /* @__PURE__ */ jsx7(
2201
+ /* @__PURE__ */ jsx10(
1757
2202
  "button",
1758
2203
  {
1759
2204
  type: "button",
@@ -1765,14 +2210,14 @@ function createBuilderDefaultFormEditorBody(options) {
1765
2210
  }
1766
2211
  )
1767
2212
  ] }),
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`) })
2213
+ form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2214
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2215
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Group title" }),
2216
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`layoutGroups.${groupIndex}.title`) })
1772
2217
  ] }),
1773
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1774
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Columns" }),
1775
- /* @__PURE__ */ jsxs7(
2218
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2219
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Columns" }),
2220
+ /* @__PURE__ */ jsxs9(
1776
2221
  "select",
1777
2222
  {
1778
2223
  style: styles.input,
@@ -1783,16 +2228,16 @@ function createBuilderDefaultFormEditorBody(options) {
1783
2228
  { shouldDirty: true }
1784
2229
  ),
1785
2230
  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" })
2231
+ /* @__PURE__ */ jsx10("option", { value: 6, children: "6" }),
2232
+ /* @__PURE__ */ jsx10("option", { value: 8, children: "8" }),
2233
+ /* @__PURE__ */ jsx10("option", { value: 12, children: "12" })
1789
2234
  ]
1790
2235
  }
1791
2236
  )
1792
2237
  ] }),
1793
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1794
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Fields" }),
1795
- /* @__PURE__ */ jsx7(
2238
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2239
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Fields" }),
2240
+ /* @__PURE__ */ jsx10(
1796
2241
  "input",
1797
2242
  {
1798
2243
  style: styles.input,
@@ -1803,13 +2248,13 @@ function createBuilderDefaultFormEditorBody(options) {
1803
2248
  ] })
1804
2249
  ] }, group.id))
1805
2250
  ] }),
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." })
2251
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2252
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2253
+ /* @__PURE__ */ jsxs9("div", { children: [
2254
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Subforms" }),
2255
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Optional nested runtime view bindings." })
1811
2256
  ] }),
1812
- /* @__PURE__ */ jsx7(
2257
+ /* @__PURE__ */ jsx10(
1813
2258
  "button",
1814
2259
  {
1815
2260
  type: "button",
@@ -1828,56 +2273,56 @@ function createBuilderDefaultFormEditorBody(options) {
1828
2273
  }
1829
2274
  )
1830
2275
  ] }),
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`) })
2276
+ subformArray.fields.map((subform, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2277
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2278
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Key" }),
2279
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.key`) })
1835
2280
  ] }),
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`) })
2281
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2282
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Label" }),
2283
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.label`) })
1839
2284
  ] }),
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`) })
2285
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2286
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "View ID" }),
2287
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.viewId`) })
1843
2288
  ] }),
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`) })
2289
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2290
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Parent field" }),
2291
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.parentField`) })
1847
2292
  ] }),
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`) })
2293
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2294
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Child field" }),
2295
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`subforms.${index}.childField`) })
1851
2296
  ] }),
1852
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1853
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1854
- /* @__PURE__ */ jsxs7(
2297
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2298
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Presentation" }),
2299
+ /* @__PURE__ */ jsxs9(
1855
2300
  "select",
1856
2301
  {
1857
2302
  style: styles.input,
1858
2303
  ...form.register(`subforms.${index}.presentation`),
1859
2304
  children: [
1860
- /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1861
- /* @__PURE__ */ jsx7("option", { value: "drawer", children: "Drawer" })
2305
+ /* @__PURE__ */ jsx10("option", { value: "dialog", children: "Dialog" }),
2306
+ /* @__PURE__ */ jsx10("option", { value: "drawer", children: "Drawer" })
1862
2307
  ]
1863
2308
  }
1864
2309
  )
1865
2310
  ] }),
1866
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => subformArray.remove(index), children: "Remove" })
2311
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => subformArray.remove(index), children: "Remove" })
1867
2312
  ] }, subform.id))
1868
2313
  ] }),
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." })
2314
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2315
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2316
+ /* @__PURE__ */ jsxs9("div", { children: [
2317
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Form Triggers" }),
2318
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Optional API callbacks for lifecycle events." })
1874
2319
  ] }),
1875
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
2320
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
1876
2321
  ] }),
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(
2322
+ triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2323
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2324
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Event" }),
2325
+ /* @__PURE__ */ jsx10(
1881
2326
  "select",
1882
2327
  {
1883
2328
  style: styles.input,
@@ -1888,19 +2333,19 @@ function createBuilderDefaultFormEditorBody(options) {
1888
2333
  }
1889
2334
  )
1890
2335
  ] }),
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`) })
2336
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2337
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Route" }),
2338
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
1894
2339
  ] }),
1895
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1896
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2340
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2341
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
1897
2342
  "Enabled"
1898
2343
  ] }),
1899
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1900
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2344
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2345
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
1901
2346
  "Blocking"
1902
2347
  ] }),
1903
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2348
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
1904
2349
  ] }, trigger.id))
1905
2350
  ] })
1906
2351
  ] });
@@ -1923,56 +2368,56 @@ function createBuilderDefaultListEditorBody(options) {
1923
2368
  }) {
1924
2369
  const selectedTable = tables.find((table) => table.name === sourceTable);
1925
2370
  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." })
2371
+ return /* @__PURE__ */ jsxs9("div", { style: styles.page, children: [
2372
+ /* @__PURE__ */ jsxs9("div", { style: styles.header, children: [
2373
+ /* @__PURE__ */ jsxs9("div", { children: [
2374
+ /* @__PURE__ */ jsx10("h1", { style: styles.title, children: listId ? "Edit Dynamic List" : "New Dynamic List" }),
2375
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Configure list columns, source mapping, and triggers." })
1931
2376
  ] }),
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" })
2377
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2378
+ /* @__PURE__ */ jsx10("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
2379
+ /* @__PURE__ */ jsx10("button", { type: "submit", disabled: isSaving, style: styles.primaryButton, children: isSaving ? "Saving..." : "Save" })
1935
2380
  ] })
1936
2381
  ] }),
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 }) })
2382
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2383
+ /* @__PURE__ */ jsx10("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Details" }) }),
2384
+ /* @__PURE__ */ jsxs9("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
2385
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2386
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Title" }),
2387
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("title", { required: true }) })
1943
2388
  ] }),
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") })
2389
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2390
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Description" }),
2391
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("description") })
1947
2392
  ] }),
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" })
2393
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2394
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Datasource" }),
2395
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register("sourceType"), children: [
2396
+ /* @__PURE__ */ jsx10("option", { value: "none", children: "None" }),
2397
+ /* @__PURE__ */ jsx10("option", { value: "dbTable", children: "DB table" }),
2398
+ /* @__PURE__ */ jsx10("option", { value: "apiEndpoint", children: "API endpoint" })
1954
2399
  ] })
1955
2400
  ] }),
1956
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1957
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1958
- /* @__PURE__ */ jsxs7(
2401
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2402
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Table" }),
2403
+ /* @__PURE__ */ jsxs9(
1959
2404
  "select",
1960
2405
  {
1961
2406
  style: styles.input,
1962
2407
  value: sourceTable,
1963
2408
  ...form.register("sourceTable"),
1964
2409
  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))
2410
+ /* @__PURE__ */ jsx10("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
2411
+ tables.map((table) => /* @__PURE__ */ jsx10("option", { value: table.name, children: table.label ?? table.name }, table.name))
1967
2412
  ]
1968
2413
  }
1969
2414
  )
1970
2415
  ] }) : 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") })
2416
+ sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2417
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "API base path" }),
2418
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register("apiBasePath") })
1974
2419
  ] }) : null,
1975
- sourceType === "dbTable" ? /* @__PURE__ */ jsx7("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx7(
2420
+ sourceType === "dbTable" ? /* @__PURE__ */ jsx10("div", { style: { ...styles.field, justifyContent: "end" }, children: /* @__PURE__ */ jsx10(
1976
2421
  "button",
1977
2422
  {
1978
2423
  type: "button",
@@ -1984,13 +2429,13 @@ function createBuilderDefaultListEditorBody(options) {
1984
2429
  ) }) : null
1985
2430
  ] })
1986
2431
  ] }),
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." })
2432
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2433
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2434
+ /* @__PURE__ */ jsxs9("div", { children: [
2435
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Default ordering" }),
2436
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Rules are applied from top to bottom." })
1992
2437
  ] }),
1993
- /* @__PURE__ */ jsx7(
2438
+ /* @__PURE__ */ jsx10(
1994
2439
  "button",
1995
2440
  {
1996
2441
  type: "button",
@@ -2004,17 +2449,17 @@ function createBuilderDefaultListEditorBody(options) {
2004
2449
  }
2005
2450
  )
2006
2451
  ] }),
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))
2452
+ orderByArray.fields.length === 0 ? /* @__PURE__ */ jsx10("div", { style: styles.grid, children: /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Automatic ordering is used." }) }) : null,
2453
+ orderByArray.fields.map((rule, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2454
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2455
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Order by field" }),
2456
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`orderBy.${index}.field`), children: [
2457
+ /* @__PURE__ */ jsx10("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select field" }),
2458
+ orderByColumns.map((column) => /* @__PURE__ */ jsx10("option", { value: column.name, children: column.label }, column.name))
2014
2459
  ] })
2015
- ] }) : /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2016
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Order by field" }),
2017
- /* @__PURE__ */ jsx7(
2460
+ ] }) : /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2461
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Order by field" }),
2462
+ /* @__PURE__ */ jsx10(
2018
2463
  "input",
2019
2464
  {
2020
2465
  style: styles.input,
@@ -2023,15 +2468,15 @@ function createBuilderDefaultListEditorBody(options) {
2023
2468
  }
2024
2469
  )
2025
2470
  ] }),
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" })
2471
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2472
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Direction" }),
2473
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`orderBy.${index}.direction`), children: [
2474
+ /* @__PURE__ */ jsx10("option", { value: "asc", children: "Ascending" }),
2475
+ /* @__PURE__ */ jsx10("option", { value: "desc", children: "Descending" })
2031
2476
  ] })
2032
2477
  ] }),
2033
- /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
2034
- /* @__PURE__ */ jsx7(
2478
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2479
+ /* @__PURE__ */ jsx10(
2035
2480
  "button",
2036
2481
  {
2037
2482
  type: "button",
@@ -2041,7 +2486,7 @@ function createBuilderDefaultListEditorBody(options) {
2041
2486
  children: "Move up"
2042
2487
  }
2043
2488
  ),
2044
- /* @__PURE__ */ jsx7(
2489
+ /* @__PURE__ */ jsx10(
2045
2490
  "button",
2046
2491
  {
2047
2492
  type: "button",
@@ -2051,7 +2496,7 @@ function createBuilderDefaultListEditorBody(options) {
2051
2496
  children: "Move down"
2052
2497
  }
2053
2498
  ),
2054
- /* @__PURE__ */ jsx7(
2499
+ /* @__PURE__ */ jsx10(
2055
2500
  "button",
2056
2501
  {
2057
2502
  type: "button",
@@ -2063,13 +2508,13 @@ function createBuilderDefaultListEditorBody(options) {
2063
2508
  ] })
2064
2509
  ] }, rule.id))
2065
2510
  ] }),
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." })
2511
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2512
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2513
+ /* @__PURE__ */ jsxs9("div", { children: [
2514
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "Columns" }),
2515
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Runtime list columns." })
2071
2516
  ] }),
2072
- /* @__PURE__ */ jsx7(
2517
+ /* @__PURE__ */ jsx10(
2073
2518
  "button",
2074
2519
  {
2075
2520
  type: "button",
@@ -2083,44 +2528,44 @@ function createBuilderDefaultListEditorBody(options) {
2083
2528
  }
2084
2529
  )
2085
2530
  ] }),
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`) })
2531
+ columnArray.fields.map((column, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2532
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2533
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Key" }),
2534
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`columns.${index}.key`) })
2090
2535
  ] }),
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`) })
2536
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2537
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Label" }),
2538
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`columns.${index}.label`) })
2094
2539
  ] }),
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" })
2540
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2541
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Align" }),
2542
+ /* @__PURE__ */ jsxs9("select", { style: styles.input, ...form.register(`columns.${index}.align`), children: [
2543
+ /* @__PURE__ */ jsx10("option", { value: "left", children: "Left" }),
2544
+ /* @__PURE__ */ jsx10("option", { value: "right", children: "Right" })
2100
2545
  ] })
2101
2546
  ] }),
2102
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2103
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
2547
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2548
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`columns.${index}.sortable`) }),
2104
2549
  "Sortable"
2105
2550
  ] }),
2106
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2107
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`columns.${index}.hidden`) }),
2551
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2552
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`columns.${index}.hidden`) }),
2108
2553
  "Hidden"
2109
2554
  ] })
2110
2555
  ] }, column.id))
2111
2556
  ] }),
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." })
2557
+ /* @__PURE__ */ jsxs9("section", { style: styles.section, children: [
2558
+ /* @__PURE__ */ jsxs9("div", { style: styles.sectionHeader, children: [
2559
+ /* @__PURE__ */ jsxs9("div", { children: [
2560
+ /* @__PURE__ */ jsx10("h2", { style: styles.sectionTitle, children: "List Triggers" }),
2561
+ /* @__PURE__ */ jsx10("p", { style: styles.description, children: "Optional API callbacks for list lifecycle events." })
2117
2562
  ] }),
2118
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
2563
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.append(emptyTrigger), children: "Add trigger" })
2119
2564
  ] }),
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(
2565
+ triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs9("div", { style: styles.row, children: [
2566
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2567
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Event" }),
2568
+ /* @__PURE__ */ jsx10(
2124
2569
  "select",
2125
2570
  {
2126
2571
  style: styles.input,
@@ -2131,19 +2576,19 @@ function createBuilderDefaultListEditorBody(options) {
2131
2576
  }
2132
2577
  )
2133
2578
  ] }),
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`) })
2579
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2580
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Route" }),
2581
+ /* @__PURE__ */ jsx10("input", { style: styles.input, ...form.register(`triggers.${index}.route`) })
2137
2582
  ] }),
2138
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2139
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2583
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2584
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.enabled`) }),
2140
2585
  "Enabled"
2141
2586
  ] }),
2142
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2143
- /* @__PURE__ */ jsx7("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2587
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2588
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`triggers.${index}.blocking`) }),
2144
2589
  "Blocking"
2145
2590
  ] }),
2146
- /* @__PURE__ */ jsx7("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2591
+ /* @__PURE__ */ jsx10("button", { type: "button", style: styles.button, onClick: () => triggerArray.remove(index), children: "Remove" })
2147
2592
  ] }, trigger.id))
2148
2593
  ] })
2149
2594
  ] });
@@ -2151,8 +2596,8 @@ function createBuilderDefaultListEditorBody(options) {
2151
2596
  }
2152
2597
 
2153
2598
  // 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";
2599
+ import { useMemo as useMemo5, useState as useState7 } from "react";
2600
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
2156
2601
  var styles2 = {
2157
2602
  page: {
2158
2603
  display: "grid",
@@ -2248,7 +2693,7 @@ var styles2 = {
2248
2693
  };
2249
2694
  function createBuilderDefaultEntityManagerComponent(deps) {
2250
2695
  return function BuilderDefaultEntityManager() {
2251
- const [state, setState] = useState6({
2696
+ const [state, setState] = useState7({
2252
2697
  page: 1,
2253
2698
  pageSize: 20,
2254
2699
  search: ""
@@ -2269,16 +2714,16 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2269
2714
  if (!window.confirm(deps.labels.deleteConfirm(entity))) return;
2270
2715
  await remove.mutateAsync(entity.id);
2271
2716
  };
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 })
2717
+ return /* @__PURE__ */ jsxs10("section", { style: styles2.page, children: [
2718
+ /* @__PURE__ */ jsxs10("div", { style: styles2.header, children: [
2719
+ /* @__PURE__ */ jsxs10("div", { children: [
2720
+ /* @__PURE__ */ jsx11("h1", { style: styles2.title, children: deps.labels.title }),
2721
+ /* @__PURE__ */ jsx11("p", { style: styles2.description, children: deps.labels.description })
2277
2722
  ] }),
2278
- deps.createHref ? /* @__PURE__ */ jsx8("a", { href: deps.createHref, style: styles2.primaryButton, children: deps.labels.addLabel }) : null
2723
+ deps.createHref ? /* @__PURE__ */ jsx11("a", { href: deps.createHref, style: styles2.primaryButton, children: deps.labels.addLabel }) : null
2279
2724
  ] }),
2280
- /* @__PURE__ */ jsxs8("div", { style: styles2.card, children: [
2281
- /* @__PURE__ */ jsx8("div", { style: styles2.toolbar, children: /* @__PURE__ */ jsx8(
2725
+ /* @__PURE__ */ jsxs10("div", { style: styles2.card, children: [
2726
+ /* @__PURE__ */ jsx11("div", { style: styles2.toolbar, children: /* @__PURE__ */ jsx11(
2282
2727
  "input",
2283
2728
  {
2284
2729
  style: styles2.input,
@@ -2287,21 +2732,21 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2287
2732
  onChange: (event) => setState((current) => ({ ...current, page: 1, search: event.target.value }))
2288
2733
  }
2289
2734
  ) }),
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" })
2735
+ /* @__PURE__ */ jsx11("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs10("table", { style: styles2.table, children: [
2736
+ /* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
2737
+ /* @__PURE__ */ jsx11("th", { style: styles2.th, children: deps.labels.title }),
2738
+ /* @__PURE__ */ jsx11("th", { style: styles2.th, children: "Detail" }),
2739
+ /* @__PURE__ */ jsx11("th", { style: styles2.th, children: "Description" }),
2740
+ /* @__PURE__ */ jsx11("th", { style: { ...styles2.th, textAlign: "right" }, children: "Actions" })
2296
2741
  ] }) }),
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(
2742
+ /* @__PURE__ */ jsx11("tbody", { children: items.map((entity) => /* @__PURE__ */ jsxs10("tr", { children: [
2743
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: /* @__PURE__ */ jsx11("a", { href: deps.editHref(entity), children: entity.title }) }),
2744
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: deps.getDetail?.(entity) ?? "-" }),
2745
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: entity.description || "-" }),
2746
+ /* @__PURE__ */ jsx11("td", { style: styles2.td, children: /* @__PURE__ */ jsxs10("div", { style: styles2.actions, children: [
2747
+ deps.runtimeHref ? /* @__PURE__ */ jsx11("a", { href: deps.runtimeHref(entity), style: styles2.button, children: deps.labels.runtimeLabel }) : null,
2748
+ /* @__PURE__ */ jsx11("a", { href: deps.editHref(entity), style: styles2.button, children: deps.labels.editLabel }),
2749
+ /* @__PURE__ */ jsx11(
2305
2750
  "button",
2306
2751
  {
2307
2752
  type: "button",
@@ -2310,7 +2755,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2310
2755
  children: deps.labels.replicateLabel
2311
2756
  }
2312
2757
  ),
2313
- /* @__PURE__ */ jsx8(
2758
+ /* @__PURE__ */ jsx11(
2314
2759
  "button",
2315
2760
  {
2316
2761
  type: "button",
@@ -2323,11 +2768,11 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2323
2768
  ] }) })
2324
2769
  ] }, entity.id)) })
2325
2770
  ] }) }),
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 })
2771
+ query.isPending ? /* @__PURE__ */ jsx11("div", { style: styles2.empty, children: "Loading..." }) : null,
2772
+ query.isError ? /* @__PURE__ */ jsx11("div", { style: styles2.empty, children: "Failed to load." }) : null,
2773
+ !query.isPending && !query.isError && items.length === 0 ? /* @__PURE__ */ jsxs10("div", { style: styles2.empty, children: [
2774
+ /* @__PURE__ */ jsx11("strong", { children: deps.labels.emptyTitle }),
2775
+ /* @__PURE__ */ jsx11("div", { children: deps.labels.emptyDescription })
2331
2776
  ] }) : null
2332
2777
  ] })
2333
2778
  ] });
@@ -2335,9 +2780,9 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2335
2780
  }
2336
2781
 
2337
2782
  // src/admin/BuilderDefaultViewEditorPage.tsx
2338
- import { useEffect as useEffect3 } from "react";
2783
+ import { useEffect as useEffect4 } from "react";
2339
2784
  import { useForm as useForm3 } from "react-hook-form";
2340
- import { Fragment, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2785
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2341
2786
  var styles3 = {
2342
2787
  page: {
2343
2788
  display: "grid",
@@ -2454,7 +2899,7 @@ function createBuilderDefaultViewEditorPage(options) {
2454
2899
  permissionWrite: defaultPermission
2455
2900
  }
2456
2901
  });
2457
- useEffect3(() => {
2902
+ useEffect4(() => {
2458
2903
  if (viewId && !view.data) return;
2459
2904
  form.reset(
2460
2905
  builderViewEditorValuesFromEntity(
@@ -2485,64 +2930,64 @@ function createBuilderDefaultViewEditorPage(options) {
2485
2930
  }
2486
2931
  });
2487
2932
  if (viewId && view.isPending) {
2488
- return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Loading..." });
2933
+ return /* @__PURE__ */ jsx12("div", { style: styles3.state, children: "Loading..." });
2489
2934
  }
2490
2935
  if (viewId && view.isError) {
2491
- return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Failed to load view." });
2936
+ return /* @__PURE__ */ jsx12("div", { style: styles3.state, children: "Failed to load view." });
2492
2937
  }
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." })
2938
+ return /* @__PURE__ */ jsxs11("form", { onSubmit, noValidate: true, style: styles3.page, children: [
2939
+ /* @__PURE__ */ jsxs11("div", { style: styles3.header, children: [
2940
+ /* @__PURE__ */ jsxs11("div", { children: [
2941
+ /* @__PURE__ */ jsx12("h1", { style: styles3.title, children: viewId ? "Edit Dynamic View" : "New Dynamic View" }),
2942
+ /* @__PURE__ */ jsx12("p", { style: styles3.description, children: "Connect a form and list into a runtime screen." })
2498
2943
  ] }),
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" })
2944
+ /* @__PURE__ */ jsxs11("div", { style: styles3.actions, children: [
2945
+ /* @__PURE__ */ jsx12("a", { href: options.backHref, style: styles3.button, children: "Cancel" }),
2946
+ /* @__PURE__ */ jsx12("button", { type: "submit", disabled: save.isPending, style: styles3.primaryButton, children: save.isPending ? "Saving..." : "Save" })
2502
2947
  ] })
2503
2948
  ] }),
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 }) })
2949
+ /* @__PURE__ */ jsx12("section", { style: styles3.section, children: /* @__PURE__ */ jsxs11("div", { style: styles3.grid, children: [
2950
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
2951
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Title" }),
2952
+ /* @__PURE__ */ jsx12("input", { style: styles3.input, ...form.register("title", { required: true }) })
2508
2953
  ] }),
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") })
2954
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
2955
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Description" }),
2956
+ /* @__PURE__ */ jsx12("input", { style: styles3.input, ...form.register("description") })
2512
2957
  ] }),
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))
2958
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
2959
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Form" }),
2960
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("formId"), children: [
2961
+ /* @__PURE__ */ jsx12("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No form" }),
2962
+ (forms.data ?? []).map((item) => /* @__PURE__ */ jsx12("option", { value: item.id, children: item.title }, item.id))
2518
2963
  ] })
2519
2964
  ] }),
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))
2965
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
2966
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "List" }),
2967
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("listId"), children: [
2968
+ /* @__PURE__ */ jsx12("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No list" }),
2969
+ (lists.data ?? []).map((item) => /* @__PURE__ */ jsx12("option", { value: item.id, children: item.title }, item.id))
2525
2970
  ] })
2526
2971
  ] }),
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))
2972
+ showPermissions ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
2973
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
2974
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Read permission" }),
2975
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("permissionRead"), children: [
2976
+ /* @__PURE__ */ jsx12("option", { value: "", children: "Authenticated users" }),
2977
+ options.permissionOptions.map((permission) => /* @__PURE__ */ jsx12("option", { value: permission.value, children: permission.label }, permission.value))
2533
2978
  ] })
2534
2979
  ] }),
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))
2980
+ /* @__PURE__ */ jsxs11("label", { style: styles3.field, children: [
2981
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Write permission" }),
2982
+ /* @__PURE__ */ jsxs11("select", { style: styles3.input, ...form.register("permissionWrite"), children: [
2983
+ /* @__PURE__ */ jsx12("option", { value: "", children: "Authenticated users" }),
2984
+ options.permissionOptions.map((permission) => /* @__PURE__ */ jsx12("option", { value: permission.value, children: permission.label }, permission.value))
2540
2985
  ] })
2541
2986
  ] })
2542
2987
  ] }) : 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") })
2988
+ /* @__PURE__ */ jsxs11("label", { style: { ...styles3.field, gridColumn: "1 / -1" }, children: [
2989
+ /* @__PURE__ */ jsx12("span", { style: styles3.label, children: "Triggers JSON" }),
2990
+ /* @__PURE__ */ jsx12("textarea", { style: styles3.textarea, ...form.register("triggersText") })
2546
2991
  ] })
2547
2992
  ] }) })
2548
2993
  ] });
@@ -2550,14 +2995,14 @@ function createBuilderDefaultViewEditorPage(options) {
2550
2995
  }
2551
2996
 
2552
2997
  // src/admin/BuilderEditorPage.tsx
2553
- import { useEffect as useEffect4 } from "react";
2998
+ import { useEffect as useEffect5 } from "react";
2554
2999
  import {
2555
3000
  FormProvider as FormProvider3,
2556
3001
  useFieldArray,
2557
3002
  useForm as useForm4,
2558
- useWatch as useWatch2
3003
+ useWatch as useWatch5
2559
3004
  } from "react-hook-form";
2560
- import { jsx as jsx10 } from "react/jsx-runtime";
3005
+ import { jsx as jsx13 } from "react/jsx-runtime";
2561
3006
  function createBuilderFormEditorPageComponent(deps) {
2562
3007
  return function BuilderFormEditorPage({ formId }) {
2563
3008
  const Body = deps.Body;
@@ -2571,11 +3016,11 @@ function createBuilderFormEditorPageComponent(deps) {
2571
3016
  const fieldArray = useFieldArray({ control: form.control, name: "fields" });
2572
3017
  const subformArray = useFieldArray({ control: form.control, name: "subforms" });
2573
3018
  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(() => {
3019
+ const fields = useWatch5({ control: form.control, name: "fields" }) ?? [];
3020
+ const subforms = useWatch5({ control: form.control, name: "subforms" }) ?? [];
3021
+ const sourceType = useWatch5({ control: form.control, name: "sourceType" });
3022
+ const sourceTable = useWatch5({ control: form.control, name: "sourceTable" });
3023
+ useEffect5(() => {
2579
3024
  if (formId && !entityQuery.data) return;
2580
3025
  form.reset(builderFormEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
2581
3026
  }, [entityQuery.data, form, formId]);
@@ -2598,12 +3043,12 @@ function createBuilderFormEditorPageComponent(deps) {
2598
3043
  }
2599
3044
  });
2600
3045
  if (formId && entityQuery.isPending) {
2601
- return /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
3046
+ return /* @__PURE__ */ jsx13("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
2602
3047
  }
2603
3048
  if (formId && entityQuery.isError) {
2604
- return /* @__PURE__ */ jsx10("div", { className: "text-destructive text-sm", children: deps.states.error });
3049
+ return /* @__PURE__ */ jsx13("div", { className: "text-destructive text-sm", children: deps.states.error });
2605
3050
  }
2606
- return /* @__PURE__ */ jsx10(FormProvider3, { ...form, children: /* @__PURE__ */ jsx10("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx10(
3051
+ return /* @__PURE__ */ jsx13(FormProvider3, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx13(
2607
3052
  Body,
2608
3053
  {
2609
3054
  formId,
@@ -2637,9 +3082,9 @@ function createBuilderListEditorPageComponent(deps) {
2637
3082
  const columnArray = useFieldArray({ control: form.control, name: "columns" });
2638
3083
  const orderByArray = useFieldArray({ control: form.control, name: "orderBy" });
2639
3084
  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(() => {
3085
+ const sourceType = useWatch5({ control: form.control, name: "sourceType" });
3086
+ const sourceTable = useWatch5({ control: form.control, name: "sourceTable" });
3087
+ useEffect5(() => {
2643
3088
  if (listId && !entityQuery.data) return;
2644
3089
  form.reset(builderListEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
2645
3090
  }, [entityQuery.data, form, listId]);
@@ -2658,12 +3103,12 @@ function createBuilderListEditorPageComponent(deps) {
2658
3103
  }
2659
3104
  });
2660
3105
  if (listId && entityQuery.isPending) {
2661
- return /* @__PURE__ */ jsx10("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
3106
+ return /* @__PURE__ */ jsx13("div", { className: "text-muted-foreground text-sm", children: deps.states.loading });
2662
3107
  }
2663
3108
  if (listId && entityQuery.isError) {
2664
- return /* @__PURE__ */ jsx10("div", { className: "text-destructive text-sm", children: deps.states.error });
3109
+ return /* @__PURE__ */ jsx13("div", { className: "text-destructive text-sm", children: deps.states.error });
2665
3110
  }
2666
- return /* @__PURE__ */ jsx10(FormProvider3, { ...form, children: /* @__PURE__ */ jsx10("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx10(
3111
+ return /* @__PURE__ */ jsx13(FormProvider3, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, className: "space-y-6", children: /* @__PURE__ */ jsx13(
2667
3112
  Body,
2668
3113
  {
2669
3114
  listId,
@@ -2684,10 +3129,11 @@ function createBuilderListEditorPageComponent(deps) {
2684
3129
  }
2685
3130
 
2686
3131
  // src/admin/BuilderAdminPages.tsx
2687
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3132
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2688
3133
  var defaultFieldTypeOptions = [
2689
3134
  { value: "text", label: "Text" },
2690
3135
  { value: "textarea", label: "Textarea" },
3136
+ { value: "richtext", label: "Rich text" },
2691
3137
  { value: "number", label: "Number" },
2692
3138
  { value: "money", label: "Money" },
2693
3139
  { value: "select", label: "Select" },
@@ -2798,6 +3244,10 @@ function createBuilderAdminPages({
2798
3244
  required: true,
2799
3245
  hidden: false,
2800
3246
  disabled: false,
3247
+ storage: "s3",
3248
+ contentKind: "image",
3249
+ multiple: false,
3250
+ maxMegabytes: 10,
2801
3251
  placeholder: "",
2802
3252
  optionsText: "",
2803
3253
  optionsMode: "static",
@@ -2944,14 +3394,14 @@ function createBuilderAdminPages({
2944
3394
  href: viewsPath
2945
3395
  }
2946
3396
  ];
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." })
3397
+ return /* @__PURE__ */ jsxs12("section", { style: homeStyles.page, children: [
3398
+ /* @__PURE__ */ jsxs12("div", { children: [
3399
+ /* @__PURE__ */ jsx14("h1", { style: homeStyles.headerTitle, children: "Builder" }),
3400
+ /* @__PURE__ */ jsx14("p", { style: homeStyles.description, children: "Manage dynamic forms, lists, and views." })
2951
3401
  ] }),
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 })
3402
+ /* @__PURE__ */ jsx14("div", { style: homeStyles.grid, children: items.map((item) => /* @__PURE__ */ jsxs12("a", { href: item.href, style: homeStyles.card, children: [
3403
+ /* @__PURE__ */ jsx14("h2", { style: homeStyles.cardTitle, children: item.title }),
3404
+ /* @__PURE__ */ jsx14("p", { style: homeStyles.description, children: item.description })
2955
3405
  ] }, item.href)) })
2956
3406
  ] });
2957
3407
  };
@@ -3040,24 +3490,24 @@ function createBuilderAdminPages({
3040
3490
  AdminHomePage,
3041
3491
  AdminFormsPage,
3042
3492
  AdminNewFormPage: function BuilderAdminNewFormPage() {
3043
- return /* @__PURE__ */ jsx11(FormEditorPage, {});
3493
+ return /* @__PURE__ */ jsx14(FormEditorPage, {});
3044
3494
  },
3045
3495
  AdminEditFormPage: function BuilderAdminEditFormPage({ formId }) {
3046
- return /* @__PURE__ */ jsx11(FormEditorPage, { formId });
3496
+ return /* @__PURE__ */ jsx14(FormEditorPage, { formId });
3047
3497
  },
3048
3498
  AdminListsPage,
3049
3499
  AdminNewListPage: function BuilderAdminNewListPage() {
3050
- return /* @__PURE__ */ jsx11(ListEditorPage, {});
3500
+ return /* @__PURE__ */ jsx14(ListEditorPage, {});
3051
3501
  },
3052
3502
  AdminEditListPage: function BuilderAdminEditListPage({ listId }) {
3053
- return /* @__PURE__ */ jsx11(ListEditorPage, { listId });
3503
+ return /* @__PURE__ */ jsx14(ListEditorPage, { listId });
3054
3504
  },
3055
3505
  AdminViewsPage,
3056
3506
  AdminNewViewPage: function BuilderAdminNewViewPage() {
3057
- return /* @__PURE__ */ jsx11(ViewEditorPage, {});
3507
+ return /* @__PURE__ */ jsx14(ViewEditorPage, {});
3058
3508
  },
3059
3509
  AdminEditViewPage: function BuilderAdminEditViewPage({ viewId }) {
3060
- return /* @__PURE__ */ jsx11(ViewEditorPage, { viewId });
3510
+ return /* @__PURE__ */ jsx14(ViewEditorPage, { viewId });
3061
3511
  },
3062
3512
  routes: {
3063
3513
  adminBasePath,
@@ -3075,11 +3525,11 @@ function createBuilderAdminPages({
3075
3525
  }
3076
3526
 
3077
3527
  // 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";
3528
+ import { useCallback as useCallback2, useMemo as useMemo6, useState as useState8 } from "react";
3529
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3080
3530
  function createBuilderEntityManagerComponent(deps) {
3081
3531
  return function BuilderEntityManager() {
3082
- const [pendingDelete, setPendingDelete] = useState7(null);
3532
+ const [pendingDelete, setPendingDelete] = useState8(null);
3083
3533
  const state = deps.useDataTableState({ pageSize: 20 });
3084
3534
  const query = deps.hooks.useEntities(state.query);
3085
3535
  const remove = deps.hooks.useDelete();
@@ -3104,8 +3554,8 @@ function createBuilderEntityManagerComponent(deps) {
3104
3554
  state,
3105
3555
  getRowId: (row) => row.id
3106
3556
  });
3107
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3108
- /* @__PURE__ */ jsx12(
3557
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3558
+ /* @__PURE__ */ jsx15(
3109
3559
  deps.DataGrid,
3110
3560
  {
3111
3561
  title: deps.labels.title,
@@ -3116,10 +3566,10 @@ function createBuilderEntityManagerComponent(deps) {
3116
3566
  emptyTitle: deps.labels.emptyTitle,
3117
3567
  emptyDescription: deps.labels.emptyDescription,
3118
3568
  onRowClick: deps.navigateToEdit,
3119
- toolbarExtra: /* @__PURE__ */ jsx12(deps.AddButton, { href: deps.createHref, label: deps.labels.addLabel })
3569
+ toolbarExtra: /* @__PURE__ */ jsx15(deps.AddButton, { href: deps.createHref, label: deps.labels.addLabel })
3120
3570
  }
3121
3571
  ),
3122
- /* @__PURE__ */ jsx12(
3572
+ /* @__PURE__ */ jsx15(
3123
3573
  deps.DeleteDialog,
3124
3574
  {
3125
3575
  entity: pendingDelete,
@@ -3139,9 +3589,9 @@ function createBuilderEntityManagerComponent(deps) {
3139
3589
  }
3140
3590
  function createBuilderEntityDialogManagerComponent(deps) {
3141
3591
  return function BuilderEntityDialogManager() {
3142
- const [editing, setEditing] = useState7(null);
3143
- const [isEditorOpen, setEditorOpen] = useState7(false);
3144
- const [pendingDelete, setPendingDelete] = useState7(null);
3592
+ const [editing, setEditing] = useState8(null);
3593
+ const [isEditorOpen, setEditorOpen] = useState8(false);
3594
+ const [pendingDelete, setPendingDelete] = useState8(null);
3145
3595
  const state = deps.useDataTableState({ pageSize: 20 });
3146
3596
  const query = deps.hooks.useEntities(state.query);
3147
3597
  const remove = deps.hooks.useDelete();
@@ -3170,8 +3620,8 @@ function createBuilderEntityDialogManagerComponent(deps) {
3170
3620
  state,
3171
3621
  getRowId: (row) => row.id
3172
3622
  });
3173
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3174
- /* @__PURE__ */ jsx12(
3623
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3624
+ /* @__PURE__ */ jsx15(
3175
3625
  deps.DataGrid,
3176
3626
  {
3177
3627
  title: deps.labels.title,
@@ -3182,10 +3632,10 @@ function createBuilderEntityDialogManagerComponent(deps) {
3182
3632
  emptyTitle: deps.labels.emptyTitle,
3183
3633
  emptyDescription: deps.labels.emptyDescription,
3184
3634
  onRowClick: openEditor,
3185
- toolbarExtra: /* @__PURE__ */ jsx12(deps.AddButton, { label: deps.labels.addLabel, onAdd: () => openEditor(null) })
3635
+ toolbarExtra: /* @__PURE__ */ jsx15(deps.AddButton, { label: deps.labels.addLabel, onAdd: () => openEditor(null) })
3186
3636
  }
3187
3637
  ),
3188
- /* @__PURE__ */ jsx12(
3638
+ /* @__PURE__ */ jsx15(
3189
3639
  deps.EditorDialog,
3190
3640
  {
3191
3641
  open: isEditorOpen,
@@ -3193,7 +3643,7 @@ function createBuilderEntityDialogManagerComponent(deps) {
3193
3643
  onClose: () => setEditorOpen(false)
3194
3644
  }
3195
3645
  ),
3196
- /* @__PURE__ */ jsx12(
3646
+ /* @__PURE__ */ jsx15(
3197
3647
  deps.DeleteDialog,
3198
3648
  {
3199
3649
  entity: pendingDelete,
@@ -3213,9 +3663,9 @@ function createBuilderEntityDialogManagerComponent(deps) {
3213
3663
  }
3214
3664
 
3215
3665
  // src/admin/BuilderViewDialog.tsx
3216
- import { useEffect as useEffect5 } from "react";
3666
+ import { useEffect as useEffect6 } from "react";
3217
3667
  import { FormProvider as FormProvider4, useForm as useForm5 } from "react-hook-form";
3218
- import { jsx as jsx13 } from "react/jsx-runtime";
3668
+ import { jsx as jsx16 } from "react/jsx-runtime";
3219
3669
  function createBuilderViewDialogComponent(deps) {
3220
3670
  return function BuilderViewDialog({
3221
3671
  open,
@@ -3230,7 +3680,7 @@ function createBuilderViewDialogComponent(deps) {
3230
3680
  resolver: deps.resolver,
3231
3681
  defaultValues: deps.emptyValues
3232
3682
  });
3233
- useEffect5(() => {
3683
+ useEffect6(() => {
3234
3684
  if (!open) return;
3235
3685
  form.reset(
3236
3686
  builderViewEditorValuesFromEntity(editing, deps.emptyValues, deps.defaultPermission)
@@ -3245,7 +3695,7 @@ function createBuilderViewDialogComponent(deps) {
3245
3695
  deps.notifications.error(error);
3246
3696
  }
3247
3697
  });
3248
- return /* @__PURE__ */ jsx13(deps.Shell, { open, editing, onClose, children: /* @__PURE__ */ jsx13(FormProvider4, { ...form, children: /* @__PURE__ */ jsx13("form", { onSubmit, noValidate: true, children: deps.Body({
3698
+ return /* @__PURE__ */ jsx16(deps.Shell, { open, editing, onClose, children: /* @__PURE__ */ jsx16(FormProvider4, { ...form, children: /* @__PURE__ */ jsx16("form", { onSubmit, noValidate: true, children: deps.Body({
3249
3699
  form,
3250
3700
  editing,
3251
3701
  forms,
@@ -3260,7 +3710,7 @@ function createBuilderViewDialogComponent(deps) {
3260
3710
 
3261
3711
  // src/admin/formLayoutEditorState.ts
3262
3712
  import { useMemo as useMemo7 } from "react";
3263
- import { useWatch as useWatch3 } from "react-hook-form";
3713
+ import { useWatch as useWatch6 } from "react-hook-form";
3264
3714
  var builderFormLayoutDragDataType = "application/x-winu-builder-layout-field";
3265
3715
  function clampBuilderFormLayoutSpan(span, columns) {
3266
3716
  return Math.max(1, Math.min(columns, span));
@@ -3307,7 +3757,7 @@ function parseBuilderFormLayoutDragPayload(raw) {
3307
3757
  }
3308
3758
  }
3309
3759
  function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
3310
- const layoutGroups = useWatch3({ control: form.control, name: "layoutGroups" }) ?? [];
3760
+ const layoutGroups = useWatch6({ control: form.control, name: "layoutGroups" }) ?? [];
3311
3761
  const layoutItems = useMemo7(
3312
3762
  () => [
3313
3763
  ...fields.map((field) => ({
@@ -3430,7 +3880,7 @@ function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
3430
3880
  // src/components/DynamicForm.tsx
3431
3881
  import { useMemo as useMemo8 } from "react";
3432
3882
  import { FormProvider as FormProvider5, useForm as useForm6 } from "react-hook-form";
3433
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3883
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
3434
3884
  function createDynamicFormComponent(deps) {
3435
3885
  return function DynamicForm({ formId }) {
3436
3886
  const query = deps.hooks.useRuntimeBuilderForm(formId);
@@ -3453,7 +3903,7 @@ function createDynamicFormComponent(deps) {
3453
3903
  }
3454
3904
  });
3455
3905
  if (query.isError) {
3456
- return /* @__PURE__ */ jsx14(
3906
+ return /* @__PURE__ */ jsx17(
3457
3907
  deps.ErrorState,
3458
3908
  {
3459
3909
  title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3462,16 +3912,16 @@ function createDynamicFormComponent(deps) {
3462
3912
  );
3463
3913
  }
3464
3914
  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 })
3915
+ 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: [
3916
+ /* @__PURE__ */ jsx17(deps.FormFields, { formId, schema: query.data.schema, namePrefix: "values" }),
3917
+ /* @__PURE__ */ jsx17(deps.SubmitButton, { isSaving: save.isPending })
3468
3918
  ] }) }) });
3469
3919
  };
3470
3920
  }
3471
3921
 
3472
3922
  // src/components/DynamicList.tsx
3473
3923
  import { useMemo as useMemo9 } from "react";
3474
- import { jsx as jsx15 } from "react/jsx-runtime";
3924
+ import { jsx as jsx18 } from "react/jsx-runtime";
3475
3925
  function createDynamicListComponent(deps) {
3476
3926
  return function DynamicList({ listId }) {
3477
3927
  const query = deps.hooks.useRuntimeBuilderList(listId);
@@ -3487,7 +3937,7 @@ function createDynamicListComponent(deps) {
3487
3937
  getRowId: (row) => row.id
3488
3938
  });
3489
3939
  if (query.isError) {
3490
- return /* @__PURE__ */ jsx15(
3940
+ return /* @__PURE__ */ jsx18(
3491
3941
  deps.ErrorState,
3492
3942
  {
3493
3943
  title: "List \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3495,7 +3945,7 @@ function createDynamicListComponent(deps) {
3495
3945
  }
3496
3946
  );
3497
3947
  }
3498
- return /* @__PURE__ */ jsx15(
3948
+ return /* @__PURE__ */ jsx18(
3499
3949
  deps.DataGrid,
3500
3950
  {
3501
3951
  title: query.data?.title ?? "Dynamic List",
@@ -3511,8 +3961,8 @@ function createDynamicListComponent(deps) {
3511
3961
  }
3512
3962
 
3513
3963
  // 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";
3964
+ import { useMemo as useMemo10, useState as useState9 } from "react";
3965
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
3516
3966
  var interactiveRowTargetSelector = "button,a,input,select,textarea,[role='button'],[role='menuitem'],[data-builder-row-action]";
3517
3967
  function hasClosest(target) {
3518
3968
  return typeof target === "object" && target !== null && "closest" in target && typeof target.closest === "function";
@@ -3524,9 +3974,9 @@ function shouldHandleDynamicViewRowClick(event) {
3524
3974
  }
3525
3975
  function createDynamicViewComponent(deps) {
3526
3976
  return function DynamicView({ viewId }) {
3527
- const [editing, setEditing] = useState8(null);
3528
- const [isDialogOpen, setDialogOpen] = useState8(false);
3529
- const [pendingDelete, setPendingDelete] = useState8(null);
3977
+ const [editing, setEditing] = useState9(null);
3978
+ const [isDialogOpen, setDialogOpen] = useState9(false);
3979
+ const [pendingDelete, setPendingDelete] = useState9(null);
3530
3980
  const viewQuery = deps.hooks.useRuntimeBuilderView(viewId);
3531
3981
  const state = deps.useDataTableState({ pageSize: 20 });
3532
3982
  const entriesQuery = deps.hooks.useBuilderViewEntries(viewId, state.query);
@@ -3555,7 +4005,7 @@ function createDynamicViewComponent(deps) {
3555
4005
  getRowId: (row) => row.id
3556
4006
  });
3557
4007
  if (viewQuery.isError) {
3558
- return /* @__PURE__ */ jsx16(
4008
+ return /* @__PURE__ */ jsx19(
3559
4009
  deps.ErrorState,
3560
4010
  {
3561
4011
  title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3563,8 +4013,8 @@ function createDynamicViewComponent(deps) {
3563
4013
  }
3564
4014
  );
3565
4015
  }
3566
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3567
- /* @__PURE__ */ jsx16(
4016
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-6", children: [
4017
+ /* @__PURE__ */ jsx19(
3568
4018
  deps.DataGrid,
3569
4019
  {
3570
4020
  title: view?.title ?? "Dynamic View",
@@ -3579,7 +4029,7 @@ function createDynamicViewComponent(deps) {
3579
4029
  setEditing(entry);
3580
4030
  setDialogOpen(true);
3581
4031
  },
3582
- toolbarExtra: /* @__PURE__ */ jsx16(
4032
+ toolbarExtra: /* @__PURE__ */ jsx19(
3583
4033
  deps.AddButton,
3584
4034
  {
3585
4035
  disabled: !view?.form,
@@ -3591,7 +4041,7 @@ function createDynamicViewComponent(deps) {
3591
4041
  )
3592
4042
  }
3593
4043
  ),
3594
- view ? /* @__PURE__ */ jsx16(
4044
+ view ? /* @__PURE__ */ jsx19(
3595
4045
  deps.EntryDialog,
3596
4046
  {
3597
4047
  open: isDialogOpen,
@@ -3602,7 +4052,7 @@ function createDynamicViewComponent(deps) {
3602
4052
  isSaving: save.isPending
3603
4053
  }
3604
4054
  ) : null,
3605
- /* @__PURE__ */ jsx16(
4055
+ /* @__PURE__ */ jsx19(
3606
4056
  deps.DeleteDialog,
3607
4057
  {
3608
4058
  entry: pendingDelete,
@@ -3620,9 +4070,9 @@ function createDynamicViewComponent(deps) {
3620
4070
  }
3621
4071
 
3622
4072
  // src/components/RuntimeEntryDialog.tsx
3623
- import { useEffect as useEffect6, useMemo as useMemo11, useState as useState9 } from "react";
4073
+ import { useEffect as useEffect7, useMemo as useMemo11, useRef as useRef8, useState as useState10 } from "react";
3624
4074
  import { FormProvider as FormProvider6, useForm as useForm7 } from "react-hook-form";
3625
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
4075
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
3626
4076
  function isDbTableSource(source) {
3627
4077
  return source?.type === "dbTable" && "tableName" in source;
3628
4078
  }
@@ -3646,6 +4096,12 @@ function childRowPayload(row, includeIdentity) {
3646
4096
  ...values
3647
4097
  };
3648
4098
  }
4099
+ function hasDraftChange(row) {
4100
+ return row.values._delete === true || row.values._draftNew === true || row.values._draftDirty === true;
4101
+ }
4102
+ function changedChildPayloads(rows, includeIdentity) {
4103
+ return rows.filter(hasDraftChange).filter((row) => includeIdentity || row.values._delete !== true).map((row) => childRowPayload(row, includeIdentity));
4104
+ }
3649
4105
  function createRuntimeEntryDialogComponent(deps) {
3650
4106
  return function RuntimeEntryDialog({
3651
4107
  open,
@@ -3655,7 +4111,8 @@ function createRuntimeEntryDialogComponent(deps) {
3655
4111
  onSave,
3656
4112
  isSaving
3657
4113
  }) {
3658
- const [draftSubforms, setDraftSubforms] = useState9({});
4114
+ const [draftSubforms, setDraftSubforms] = useState10({});
4115
+ const isSubmittingRef = useRef8(false);
3659
4116
  const compositeCreate = deps.useCreateCompositeEntry?.(view.id);
3660
4117
  const compositeUpdate = deps.useUpdateCompositeEntry?.(view.id);
3661
4118
  const form = useForm7({
@@ -3663,16 +4120,18 @@ function createRuntimeEntryDialogComponent(deps) {
3663
4120
  values: open ? createBuilderEntryDefaultValues(view, editing) : void 0
3664
4121
  });
3665
4122
  const mainTableName = runtimeViewTableName(view);
3666
- const hasDraftRows = useMemo11(
3667
- () => Object.values(draftSubforms).some((draft) => draft.rows.length > 0),
4123
+ const hasDraftChanges = useMemo11(
4124
+ () => Object.values(draftSubforms).some((draft) => draft.rows.some(hasDraftChange)),
3668
4125
  [draftSubforms]
3669
4126
  );
3670
- useEffect6(() => {
4127
+ useEffect7(() => {
3671
4128
  if (open) setDraftSubforms({});
3672
4129
  }, [open]);
3673
4130
  const onSubmit = form.handleSubmit(async (values) => {
4131
+ if (isSubmittingRef.current) return;
4132
+ isSubmittingRef.current = true;
3674
4133
  try {
3675
- if (!editing && hasDraftRows) {
4134
+ if (!editing && hasDraftChanges) {
3676
4135
  if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3677
4136
  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
4137
  await compositeCreate.mutateAsync({
@@ -3681,12 +4140,12 @@ function createRuntimeEntryDialogComponent(deps) {
3681
4140
  ...Object.fromEntries(
3682
4141
  Object.values(draftSubforms).map((draft) => [
3683
4142
  draft.dataKey,
3684
- draft.rows.filter((row) => row.values._delete !== true).map((row) => childRowPayload(row, false))
4143
+ changedChildPayloads(draft.rows, false)
3685
4144
  ])
3686
4145
  )
3687
4146
  }
3688
4147
  });
3689
- } else if (editing && hasDraftRows) {
4148
+ } else if (editing && hasDraftChanges) {
3690
4149
  if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3691
4150
  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
4151
  await compositeUpdate.mutateAsync({
@@ -3701,7 +4160,7 @@ function createRuntimeEntryDialogComponent(deps) {
3701
4160
  ...Object.fromEntries(
3702
4161
  Object.values(draftSubforms).map((draft) => [
3703
4162
  draft.dataKey,
3704
- draft.rows.map((row) => childRowPayload(row, true))
4163
+ changedChildPayloads(draft.rows, true)
3705
4164
  ])
3706
4165
  )
3707
4166
  }
@@ -3714,12 +4173,14 @@ function createRuntimeEntryDialogComponent(deps) {
3714
4173
  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
4174
  } catch (error) {
3716
4175
  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"));
4176
+ } finally {
4177
+ isSubmittingRef.current = false;
3717
4178
  }
3718
4179
  });
3719
4180
  const saving = isSaving || Boolean(compositeCreate?.isPending || compositeUpdate?.isPending);
3720
4181
  const extraItems = deps.SubformField && view.form?.schema.subforms?.length ? view.form.schema.subforms.map((subform) => ({
3721
4182
  key: subform.key,
3722
- render: () => deps.SubformField ? /* @__PURE__ */ jsx17(
4183
+ render: () => deps.SubformField ? /* @__PURE__ */ jsx20(
3723
4184
  deps.SubformField,
3724
4185
  {
3725
4186
  subform,
@@ -3734,7 +4195,7 @@ function createRuntimeEntryDialogComponent(deps) {
3734
4195
  }
3735
4196
  ) : null
3736
4197
  })) : void 0;
3737
- return /* @__PURE__ */ jsx17(
4198
+ return /* @__PURE__ */ jsx20(
3738
4199
  deps.DialogShell,
3739
4200
  {
3740
4201
  open,
@@ -3742,8 +4203,8 @@ function createRuntimeEntryDialogComponent(deps) {
3742
4203
  title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445",
3743
4204
  description: view.title,
3744
4205
  onClose,
3745
- children: /* @__PURE__ */ jsx17(FormProvider6, { ...form, children: /* @__PURE__ */ jsxs14("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
3746
- view.form ? /* @__PURE__ */ jsx17(
4206
+ children: /* @__PURE__ */ jsx20(FormProvider6, { ...form, children: /* @__PURE__ */ jsxs16("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
4207
+ view.form ? /* @__PURE__ */ jsx20(
3747
4208
  deps.FormFields,
3748
4209
  {
3749
4210
  formId: view.form.id,
@@ -3754,7 +4215,7 @@ function createRuntimeEntryDialogComponent(deps) {
3754
4215
  extraItems
3755
4216
  }
3756
4217
  ) : null,
3757
- /* @__PURE__ */ jsx17(deps.Actions, { isSaving: saving, onClose })
4218
+ /* @__PURE__ */ jsx20(deps.Actions, { isSaving: saving, onClose })
3758
4219
  ] }) })
3759
4220
  }
3760
4221
  );
@@ -3841,7 +4302,7 @@ function validateBuilderFrontendSetup(config) {
3841
4302
  // src/index.ts
3842
4303
  var builderUiPackage = {
3843
4304
  name: "@duke333/builder-ui",
3844
- version: "0.2.2"
4305
+ version: "0.2.4"
3845
4306
  };
3846
4307
  export {
3847
4308
  BUILDER_EDITOR_NONE_VALUE,
@@ -3849,6 +4310,9 @@ export {
3849
4310
  BuilderGrid,
3850
4311
  BuilderProvider,
3851
4312
  BuilderView,
4313
+ ReadyFileField,
4314
+ ReadyRichTextField,
4315
+ RichTextContent,
3852
4316
  builderEditorOptionsToText,
3853
4317
  builderEditorSearchFieldsToText,
3854
4318
  builderEditorTextToOptions,
@@ -3891,9 +4355,11 @@ export {
3891
4355
  getBuilderEditorTriggerRoute,
3892
4356
  nextBuilderFormLayoutGroupId,
3893
4357
  parseBuilderFormLayoutDragPayload,
4358
+ richTextToPlainText,
3894
4359
  serializeBuilderFormLayoutDragPayload,
3895
4360
  shouldHandleDynamicViewRowClick,
3896
4361
  swapBuilderFormLayoutItems,
4362
+ toRichTextDocument,
3897
4363
  useBuilderFormLayoutEditor,
3898
4364
  useBuilderRuntime,
3899
4365
  validateBuilderFrontendSetup