@duke333/builder-ui 0.2.2 → 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) {
@@ -420,11 +464,13 @@ function createBuilderClient({ transport, apiBasePath }) {
420
464
  return createBuilderApiClient(transport, { apiBasePath });
421
465
  }
422
466
  var BuilderContext = createContext(null);
467
+ var defaultComponents = {};
423
468
  function BuilderProvider({
424
469
  children,
425
470
  client: configuredClient,
426
471
  transport,
427
472
  apiBasePath,
473
+ components = defaultComponents,
428
474
  queryClient,
429
475
  onNotify
430
476
  }) {
@@ -446,8 +492,8 @@ function BuilderProvider({
446
492
  const internalQueryClient = useRef(null);
447
493
  if (!internalQueryClient.current) internalQueryClient.current = queryClient ?? new QueryClient();
448
494
  const value = useMemo(
449
- () => ({ client: internalClient, hooks, notify }),
450
- [hooks, internalClient, notify]
495
+ () => ({ client: internalClient, components, hooks, notify }),
496
+ [components, hooks, internalClient, notify]
451
497
  );
452
498
  return /* @__PURE__ */ jsx(QueryClientProvider, { client: internalQueryClient.current, children: /* @__PURE__ */ jsxs(BuilderContext.Provider, { value, children: [
453
499
  children,
@@ -468,11 +514,49 @@ function builderErrorMessage(error, fallback) {
468
514
  }
469
515
 
470
516
  // src/ready/BuilderRuntimeComponents.tsx
471
- import { useMemo as useMemo4, useState as useState5 } from "react";
517
+ import { useMemo as useMemo4, useRef as useRef7, useState as useState6 } from "react";
472
518
  import { FormProvider as FormProvider2, useForm as useForm2 } from "react-hook-form";
473
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
+
474
556
  // src/runtime/runtimeUtils.ts
475
557
  function emptyFieldValue(field) {
558
+ if (field.defaultValue !== void 0) return field.defaultValue;
559
+ if (field.type === "file" && field.multiple) return [];
476
560
  return field.type === "checkbox" ? false : "";
477
561
  }
478
562
  function createBuilderFormDefaultValues(schema) {
@@ -498,19 +582,277 @@ function formatBuilderRuntimeValue(value, locale = "mn-MN") {
498
582
  }
499
583
 
500
584
  // src/ready/ReadyFields.tsx
501
- import { useRef as useRef2 } from "react";
502
- 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";
503
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";
504
841
  function inputType(field) {
505
842
  if (field.type === "date") return "date";
506
843
  if (field.type === "number" || field.type === "money") return "number";
507
844
  return "text";
508
845
  }
509
- function ReadyField({ field, formId, viewId }) {
846
+ function ReadyField({
847
+ field,
848
+ formId,
849
+ viewId,
850
+ parentValues
851
+ }) {
510
852
  const { hooks, notify } = useBuilderRuntime();
511
- const form = useFormContext();
512
- const values = useWatch({ control: form.control, name: "values" }) ?? {};
513
- const timer = useRef2(null);
853
+ const form = useFormContext3();
854
+ const values = useWatch3({ control: form.control, name: "values" }) ?? {};
855
+ const timer = useRef4(null);
514
856
  const source = field.optionsSource;
515
857
  const dependencyValue = source?.filterBy ? values[source.filterBy.valueFromField] : void 0;
516
858
  const depends = source?.filterBy && dependencyValue != null ? { [source.filterBy.valueFromField]: String(dependencyValue) } : void 0;
@@ -523,6 +865,12 @@ function ReadyField({ field, formId, viewId }) {
523
865
  const trigger = hooks.useRunRuntimeBuilderFieldTrigger();
524
866
  const name = `values.${field.key}`;
525
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
+ }
526
874
  const runTrigger = (event, value) => {
527
875
  const definition = field.triggers.find((item) => item.enabled && item.event === event);
528
876
  if (!definition) return;
@@ -533,7 +881,7 @@ function ReadyField({ field, formId, viewId }) {
533
881
  viewId,
534
882
  fieldKey: field.key,
535
883
  event,
536
- input: { value, values: form.getValues("values") }
884
+ input: { value, values: form.getValues("values"), parentValues }
537
885
  });
538
886
  for (const [key, patchedValue] of Object.entries(response.valuesPatch)) {
539
887
  form.setValue(`values.${key}`, patchedValue, { shouldDirty: true, shouldValidate: true });
@@ -561,41 +909,47 @@ function ReadyField({ field, formId, viewId }) {
561
909
  });
562
910
  const error = form.formState.errors.values?.[field.key];
563
911
  const options = source ? optionsQuery.data ?? [] : field.options ?? [];
564
- return /* @__PURE__ */ jsxs2("label", { className: "builder-field", children: [
565
- /* @__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: [
566
914
  field.label,
567
- field.required ? /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", children: " *" }) : null
915
+ field.required ? /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", children: " *" }) : null
568
916
  ] }),
569
- 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: [
570
- /* @__PURE__ */ jsx2("option", { value: "", children: field.placeholder ?? "\u0421\u043E\u043D\u0433\u043E\u0445" }),
571
- options.map((option) => /* @__PURE__ */ jsx2("option", { value: option.value, children: option.label }, option.value))
572
- ] }) : 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 }),
573
- field.description ? /* @__PURE__ */ jsx2("small", { className: "builder-field__description", children: field.description }) : null,
574
- 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
575
923
  ] });
576
924
  }
577
- function ReadyFields({ formId, viewId, schema, extraItems = [] }) {
925
+ function ReadyFields({
926
+ formId,
927
+ viewId,
928
+ schema,
929
+ parentValues,
930
+ extraItems = []
931
+ }) {
578
932
  const fields = new Map(schema.fields.map((field) => [field.key, field]));
579
933
  const rendered = /* @__PURE__ */ new Set();
580
- return /* @__PURE__ */ jsxs2("div", { className: "builder-form-fields", children: [
581
- schema.layout?.groups.map((group) => /* @__PURE__ */ jsxs2("fieldset", { className: "builder-fieldset", children: [
582
- group.title ? /* @__PURE__ */ jsx2("legend", { children: group.title }) : null,
583
- /* @__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) => {
584
938
  const field = fields.get(item.key);
585
939
  if (!field) return null;
586
940
  rendered.add(field.key);
587
- 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);
588
942
  }) })
589
943
  ] }, group.id)),
590
- /* @__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)) }),
591
- 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))
592
946
  ] });
593
947
  }
594
948
 
595
949
  // src/ready/ReadyOverlay.tsx
596
- 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";
597
951
  import { createPortal } from "react-dom";
598
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
952
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
599
953
  function ReadyOverlay({
600
954
  open,
601
955
  presentation = "dialog",
@@ -604,15 +958,15 @@ function ReadyOverlay({
604
958
  onClose,
605
959
  children
606
960
  }) {
607
- const panelRef = useRef3(null);
608
- const onCloseRef = useRef3(onClose);
609
- const [portalRoot, setPortalRoot] = useState2(null);
961
+ const panelRef = useRef5(null);
962
+ const onCloseRef = useRef5(onClose);
963
+ const [portalRoot, setPortalRoot] = useState3(null);
610
964
  onCloseRef.current = onClose;
611
- const titleId = useId();
612
- useEffect(() => {
965
+ const titleId = useId2();
966
+ useEffect2(() => {
613
967
  setPortalRoot(document.body);
614
968
  }, []);
615
- useEffect(() => {
969
+ useEffect2(() => {
616
970
  if (!open || !portalRoot) return;
617
971
  const previous = document.activeElement;
618
972
  panelRef.current?.focus();
@@ -646,7 +1000,7 @@ function ReadyOverlay({
646
1000
  }, [open, portalRoot]);
647
1001
  if (!open || !portalRoot) return null;
648
1002
  return createPortal(
649
- /* @__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(
650
1004
  "div",
651
1005
  {
652
1006
  ref: panelRef,
@@ -656,14 +1010,14 @@ function ReadyOverlay({
656
1010
  "aria-labelledby": titleId,
657
1011
  tabIndex: -1,
658
1012
  children: [
659
- /* @__PURE__ */ jsxs3("header", { className: "builder-overlay__header", children: [
660
- /* @__PURE__ */ jsxs3("div", { children: [
661
- /* @__PURE__ */ jsx3("h2", { id: titleId, className: "builder-title", children: title }),
662
- 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
663
1017
  ] }),
664
- /* @__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" })
665
1019
  ] }),
666
- /* @__PURE__ */ jsx3("div", { className: "builder-overlay__body", children })
1020
+ /* @__PURE__ */ jsx5("div", { className: "builder-overlay__body", children })
667
1021
  ]
668
1022
  }
669
1023
  ) }),
@@ -679,29 +1033,29 @@ function ReadyConfirmDialog({
679
1033
  onClose,
680
1034
  onConfirm
681
1035
  }) {
682
- return /* @__PURE__ */ jsx3(ReadyOverlay, { open, title, description, onClose, children: /* @__PURE__ */ jsxs3("div", { className: "builder-actions", children: [
683
- /* @__PURE__ */ jsx3("button", { type: "button", className: "builder-button builder-button--ghost", onClick: onClose, children: "\u0411\u043E\u043B\u0438\u0445" }),
684
- /* @__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 })
685
1039
  ] }) });
686
1040
  }
687
1041
  function ReadyErrorState({ title, description }) {
688
- return /* @__PURE__ */ jsxs3("div", { className: "builder-state builder-state--error", role: "alert", children: [
689
- /* @__PURE__ */ jsx3("strong", { children: title }),
690
- /* @__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 })
691
1045
  ] });
692
1046
  }
693
1047
 
694
1048
  // src/ready/ReadySubform.tsx
695
- import { useEffect as useEffect2, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
696
- 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";
697
1051
 
698
1052
  // src/ready/ReadyTable.tsx
699
- import { useMemo as useMemo2, useState as useState3 } from "react";
700
- 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";
701
1055
  function useReadyTableState({ pageSize = 20 } = {}) {
702
- const [page, setPage] = useState3(1);
703
- const [search, setSearchValue] = useState3("");
704
- const [sort, setSort] = useState3();
1056
+ const [page, setPage] = useState4(1);
1057
+ const [search, setSearchValue] = useState4("");
1058
+ const [sort, setSort] = useState4();
705
1059
  return {
706
1060
  query: { page, pageSize, search: search || void 0, sort },
707
1061
  page,
@@ -720,7 +1074,7 @@ function useReadyTableState({ pageSize = 20 } = {}) {
720
1074
  };
721
1075
  }
722
1076
  function useReadyTable(args) {
723
- const [selectedIds, setSelectedIds] = useState3([]);
1077
+ const [selectedIds, setSelectedIds] = useState4([]);
724
1078
  return useMemo2(
725
1079
  () => ({
726
1080
  ...args,
@@ -754,14 +1108,14 @@ function ReadyDataGrid({
754
1108
  selectable = false
755
1109
  }) {
756
1110
  const totalPages = Math.max(1, Math.ceil(controller.rowCount / controller.state.pageSize));
757
- return /* @__PURE__ */ jsxs4("section", { className: "builder-card builder-grid", "aria-busy": isLoading || void 0, children: [
758
- /* @__PURE__ */ jsxs4("header", { className: "builder-grid__header", children: [
759
- /* @__PURE__ */ jsxs4("div", { children: [
760
- title ? /* @__PURE__ */ jsx4("h2", { className: "builder-title", children: title }) : null,
761
- 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
762
1116
  ] }),
763
- /* @__PURE__ */ jsxs4("div", { className: "builder-grid__toolbar", children: [
764
- /* @__PURE__ */ jsx4(
1117
+ /* @__PURE__ */ jsxs6("div", { className: "builder-grid__toolbar", children: [
1118
+ /* @__PURE__ */ jsx6(
765
1119
  "input",
766
1120
  {
767
1121
  className: "builder-input builder-grid__search",
@@ -775,19 +1129,19 @@ function ReadyDataGrid({
775
1129
  toolbarExtra
776
1130
  ] })
777
1131
  ] }),
778
- /* @__PURE__ */ jsxs4("div", { className: "builder-table-wrap", children: [
779
- /* @__PURE__ */ jsxs4("table", { className: "builder-table", children: [
780
- /* @__PURE__ */ jsx4("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
781
- selectable ? /* @__PURE__ */ jsx4("th", { "aria-label": "\u0421\u043E\u043D\u0433\u043E\u043B\u0442" }) : null,
782
- 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))
783
1137
  ] }) }),
784
- /* @__PURE__ */ jsx4("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs4(
1138
+ /* @__PURE__ */ jsx6("tbody", { children: controller.data.map((entry) => /* @__PURE__ */ jsxs6(
785
1139
  "tr",
786
1140
  {
787
1141
  className: onRowClick ? "builder-row-clickable" : void 0,
788
1142
  onClick: (event) => onRowClick?.(entry, event),
789
1143
  children: [
790
- selectable ? /* @__PURE__ */ jsx4("td", { children: /* @__PURE__ */ jsx4(
1144
+ selectable ? /* @__PURE__ */ jsx6("td", { children: /* @__PURE__ */ jsx6(
791
1145
  "input",
792
1146
  {
793
1147
  type: "checkbox",
@@ -797,41 +1151,41 @@ function ReadyDataGrid({
797
1151
  onChange: () => controller.toggleSelected(entry.id)
798
1152
  }
799
1153
  ) }) : null,
800
- 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))
801
1155
  ]
802
1156
  },
803
1157
  entry.id
804
1158
  )) })
805
1159
  ] }),
806
- isLoading ? /* @__PURE__ */ jsx4("div", { className: "builder-state", children: "\u0423\u043D\u0448\u0438\u0436 \u0431\u0430\u0439\u043D\u0430\u2026" }) : null,
807
- !isLoading && controller.data.length === 0 ? /* @__PURE__ */ jsxs4("div", { className: "builder-state", children: [
808
- /* @__PURE__ */ jsx4("strong", { children: emptyTitle }),
809
- 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
810
1164
  ] }) : null
811
1165
  ] }),
812
- /* @__PURE__ */ jsxs4("footer", { className: "builder-pagination", children: [
813
- /* @__PURE__ */ jsxs4("span", { children: [
1166
+ /* @__PURE__ */ jsxs6("footer", { className: "builder-pagination", children: [
1167
+ /* @__PURE__ */ jsxs6("span", { children: [
814
1168
  controller.rowCount,
815
1169
  " \u043C\u04E9\u0440"
816
1170
  ] }),
817
- /* @__PURE__ */ jsxs4("div", { children: [
818
- /* @__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" }),
819
- /* @__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: [
820
1174
  controller.state.page,
821
1175
  " / ",
822
1176
  totalPages
823
1177
  ] }),
824
- /* @__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" })
825
1179
  ] })
826
1180
  ] })
827
1181
  ] });
828
1182
  }
829
1183
  function readyColumns(columns) {
830
- return columns.map((column) => ({ ...column }));
1184
+ return columns.filter((column) => !column.hidden).map((column) => ({ ...column }));
831
1185
  }
832
1186
 
833
1187
  // src/ready/ReadySubform.tsx
834
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1188
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
835
1189
  function linkedValue(entry, field) {
836
1190
  if (!entry) return void 0;
837
1191
  const value = field === "id" ? entry.id : entry.values[field];
@@ -845,7 +1199,7 @@ function makeDraftEntry(viewId, values, editing) {
845
1199
  return {
846
1200
  id: editing?.id ?? (globalThis.crypto?.randomUUID?.() ?? `draft-${Date.now()}`),
847
1201
  viewId,
848
- values: editing ? values.values : { ...values.values, _draftNew: true },
1202
+ values: editing ? { ...values.values, _draftDirty: true } : { ...values.values, _draftNew: true },
849
1203
  version: editing?.version ?? 0,
850
1204
  createdAt: editing?.createdAt ?? now,
851
1205
  updatedAt: now
@@ -853,9 +1207,12 @@ function makeDraftEntry(viewId, values, editing) {
853
1207
  }
854
1208
  function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
855
1209
  const { hooks, notify } = useBuilderRuntime();
856
- const [open, setOpen] = useState4(false);
857
- const [editing, setEditing] = useState4(null);
858
- 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);
859
1216
  const parentValue = linkedValue(parentEntry, subform.parentField);
860
1217
  const viewQuery = hooks.useRuntimeBuilderView(subform.viewId, Boolean(subform.viewId));
861
1218
  const tableState = useReadyTableState({ pageSize: 100 });
@@ -866,7 +1223,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
866
1223
  const entriesQuery = hooks.useBuilderViewEntries(subform.viewId, filterQuery, Boolean(parentValue));
867
1224
  const view = viewQuery.data;
868
1225
  const source = view?.list?.source?.type === "dbTable" ? view.list.source.tableName : void 0;
869
- useEffect2(() => {
1226
+ useEffect3(() => {
870
1227
  if (initialized.current || !view || !entriesQuery.data || !parentValue) return;
871
1228
  initialized.current = true;
872
1229
  onRowsChange({ key: subform.key, dataKey: dataKey(view.id, source), rows: entriesQuery.data.items });
@@ -884,8 +1241,9 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
884
1241
  key: "_actions",
885
1242
  label: "\u04AE\u0439\u043B\u0434\u044D\u043B",
886
1243
  sortable: false,
1244
+ hidden: false,
887
1245
  align: "right",
888
- 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) => {
889
1247
  event.stopPropagation();
890
1248
  removeRow(row);
891
1249
  }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
@@ -919,12 +1277,12 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
919
1277
  close();
920
1278
  });
921
1279
  if (viewQuery.isError) {
922
- 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`) });
923
1281
  }
924
- return /* @__PURE__ */ jsxs5("section", { className: "builder-subform", children: [
925
- /* @__PURE__ */ jsxs5("div", { className: "builder-subform__header", children: [
926
- /* @__PURE__ */ jsx5("strong", { children: subform.label }),
927
- /* @__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: () => {
928
1286
  setEditing(null);
929
1287
  setOpen(true);
930
1288
  }, children: [
@@ -932,7 +1290,7 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
932
1290
  subform.buttonLabel ?? "\u041D\u044D\u043C\u044D\u0445"
933
1291
  ] })
934
1292
  ] }),
935
- visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx5(
1293
+ visibleRows.length > 0 || Boolean(parentValue) && entriesQuery.isPending ? /* @__PURE__ */ jsx7(
936
1294
  ReadyDataGrid,
937
1295
  {
938
1296
  controller: table,
@@ -944,26 +1302,34 @@ function ReadySubform({ subform, parentEntry, rows, onRowsChange }) {
944
1302
  emptyTitle: "\u041C\u04E9\u0440 \u0430\u043B\u0433\u0430"
945
1303
  }
946
1304
  ) : null,
947
- 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: [
948
- /* @__PURE__ */ jsx5(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
949
- /* @__PURE__ */ jsxs5("div", { className: "builder-actions", children: [
950
- /* @__PURE__ */ jsx5("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
951
- /* @__PURE__ */ jsx5("button", { type: "submit", className: "builder-button builder-button--primary", children: "\u0425\u0430\u0434\u0433\u0430\u043B\u0430\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" })
952
1318
  ] })
953
1319
  ] }) }) }) : null
954
1320
  ] });
955
1321
  }
956
1322
 
957
1323
  // src/ready/BuilderRuntimeComponents.tsx
958
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
959
- function BuilderForm({ formId }) {
1324
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1325
+ function DefaultBuilderForm({ formId }) {
960
1326
  const { hooks, notify } = useBuilderRuntime();
961
1327
  const query = hooks.useRuntimeBuilderForm(formId);
962
1328
  const save = hooks.useSaveRuntimeBuilderFormEntry(formId);
963
1329
  const defaults = useMemo4(() => createBuilderFormDefaultValues(query.data?.schema), [query.data]);
964
1330
  const form = useForm2({ defaultValues: defaults, values: query.data ? defaults : void 0 });
965
- 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`) });
966
- 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" });
967
1333
  const submit = form.handleSubmit(async (input) => {
968
1334
  try {
969
1335
  await save.mutateAsync(input);
@@ -973,16 +1339,16 @@ function BuilderForm({ formId }) {
973
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") });
974
1340
  }
975
1341
  });
976
- return /* @__PURE__ */ jsxs6("section", { className: "builder-card", children: [
977
- /* @__PURE__ */ jsx6("h2", { className: "builder-title", children: query.data.title }),
978
- query.data.description ? /* @__PURE__ */ jsx6("p", { className: "builder-description", children: query.data.description }) : null,
979
- /* @__PURE__ */ jsx6(FormProvider2, { ...form, children: /* @__PURE__ */ jsxs6("form", { className: "builder-form", onSubmit: submit, noValidate: true, children: [
980
- /* @__PURE__ */ jsx6(ReadyFields, { formId, schema: query.data.schema }),
981
- /* @__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" }) })
982
1348
  ] }) })
983
1349
  ] });
984
1350
  }
985
- function BuilderGrid({ listId }) {
1351
+ function DefaultBuilderGrid({ listId }) {
986
1352
  const { hooks } = useBuilderRuntime();
987
1353
  const listQuery = hooks.useRuntimeBuilderList(listId);
988
1354
  const state = useReadyTableState();
@@ -994,8 +1360,8 @@ function BuilderGrid({ listId }) {
994
1360
  state,
995
1361
  getRowId: (row) => row.id
996
1362
  });
997
- 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`) });
998
- 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 });
999
1365
  }
1000
1366
  function dbTableName(view) {
1001
1367
  if (view.list?.source?.type === "dbTable") return view.list.source.tableName;
@@ -1006,9 +1372,16 @@ function childPayload(row, includeIdentity) {
1006
1372
  const values = Object.fromEntries(Object.entries(row.values).filter(([key]) => key === "_delete" || !key.startsWith("_")));
1007
1373
  return includeIdentity && row.values._draftNew !== true ? { id: row.id, version: row.version, ...values } : values;
1008
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
+ }
1009
1381
  function BuilderEntryEditor({ view, editing, open, onClose }) {
1010
1382
  const { hooks, notify } = useBuilderRuntime();
1011
- const [subforms, setSubforms] = useState5({});
1383
+ const [subforms, setSubforms] = useState6({});
1384
+ const isSubmittingRef = useRef7(false);
1012
1385
  const save = hooks.useSaveBuilderViewEntry(view.id);
1013
1386
  const createComposite = hooks.useCreateCompositeBuilderViewEntry(view.id);
1014
1387
  const updateComposite = hooks.useUpdateCompositeBuilderViewEntry(view.id);
@@ -1019,11 +1392,13 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1019
1392
  onClose();
1020
1393
  };
1021
1394
  const submit = form.handleSubmit(async (input) => {
1395
+ if (isSubmittingRef.current) return;
1396
+ isSubmittingRef.current = true;
1022
1397
  try {
1023
1398
  const mainKey = dbTableName(view);
1024
- const hasSubformRows = Object.values(subforms).some((item) => item.rows.length > 0);
1025
- if (hasSubformRows && mainKey) {
1026
- 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))]));
1027
1402
  if (editing) {
1028
1403
  await updateComposite.mutateAsync({ id: editing.id, input: { data: { [mainKey]: { id: editing.id, version: input.version, ...input.values }, ...children } } });
1029
1404
  } else {
@@ -1036,24 +1411,26 @@ function BuilderEntryEditor({ view, editing, open, onClose }) {
1036
1411
  close();
1037
1412
  } catch (error) {
1038
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;
1039
1416
  }
1040
1417
  });
1041
1418
  const saving = save.isPending || createComposite.isPending || updateComposite.isPending;
1042
1419
  const updateRows = ({ key, dataKey: dataKey2, rows }) => setSubforms((current) => ({ ...current, [key]: { dataKey: dataKey2, rows } }));
1043
- 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: [
1044
- /* @__PURE__ */ jsx6(ReadyFields, { formId: view.form.id, viewId: view.id, schema: view.form.schema }),
1045
- view.form.schema.subforms.map((subform) => /* @__PURE__ */ jsx6(ReadySubform, { subform, parentEntry: editing, rows: subforms[subform.key]?.rows ?? [], onRowsChange: updateRows }, subform.key)),
1046
- /* @__PURE__ */ jsxs6("div", { className: "builder-actions builder-actions--sticky", children: [
1047
- /* @__PURE__ */ jsx6("button", { type: "button", className: "builder-button builder-button--ghost", onClick: close, children: "\u0411\u043E\u043B\u0438\u0445" }),
1048
- /* @__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" })
1049
1426
  ] })
1050
- ] }) }) : /* @__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." }) });
1051
1428
  }
1052
- function BuilderView({ viewId }) {
1429
+ function DefaultBuilderView({ viewId }) {
1053
1430
  const { hooks, notify } = useBuilderRuntime();
1054
- const [editing, setEditing] = useState5(null);
1055
- const [editorOpen, setEditorOpen] = useState5(false);
1056
- const [pendingDelete, setPendingDelete] = useState5(null);
1431
+ const [editing, setEditing] = useState6(null);
1432
+ const [editorOpen, setEditorOpen] = useState6(false);
1433
+ const [pendingDelete, setPendingDelete] = useState6(null);
1057
1434
  const viewQuery = hooks.useRuntimeBuilderView(viewId);
1058
1435
  const state = useReadyTableState();
1059
1436
  const entriesQuery = hooks.useBuilderViewEntries(viewId, state.query);
@@ -1066,14 +1443,15 @@ function BuilderView({ viewId }) {
1066
1443
  key: "_actions",
1067
1444
  label: "\u04AE\u0439\u043B\u0434\u044D\u043B",
1068
1445
  sortable: false,
1446
+ hidden: false,
1069
1447
  align: "right",
1070
- render: (entry) => /* @__PURE__ */ jsxs6("div", { className: "builder-row-actions", "data-builder-row-action": true, children: [
1071
- /* @__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) => {
1072
1450
  event.stopPropagation();
1073
1451
  setEditing(entry);
1074
1452
  setEditorOpen(true);
1075
1453
  }, children: "\u0417\u0430\u0441\u0430\u0445" }),
1076
- /* @__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) => {
1077
1455
  event.stopPropagation();
1078
1456
  setPendingDelete(entry);
1079
1457
  }, children: "\u0423\u0441\u0442\u0433\u0430\u0445" })
@@ -1082,9 +1460,9 @@ function BuilderView({ viewId }) {
1082
1460
  return result;
1083
1461
  }, [view]);
1084
1462
  const table = useReadyTable({ columns, data: entriesQuery.data?.items ?? [], rowCount: entriesQuery.data?.total ?? 0, state, getRowId: (row) => row.id });
1085
- 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`) });
1086
- return /* @__PURE__ */ jsxs6("div", { className: "builder-runtime", children: [
1087
- /* @__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(
1088
1466
  ReadyDataGrid,
1089
1467
  {
1090
1468
  title: view?.title ?? "View",
@@ -1095,14 +1473,14 @@ function BuilderView({ viewId }) {
1095
1473
  setEditing(entry);
1096
1474
  setEditorOpen(true);
1097
1475
  },
1098
- 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: () => {
1099
1477
  setEditing(null);
1100
1478
  setEditorOpen(true);
1101
1479
  }, children: "+ \u041D\u044D\u043C\u044D\u0445" })
1102
1480
  }
1103
1481
  ),
1104
- view ? /* @__PURE__ */ jsx6(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1105
- /* @__PURE__ */ jsx6(
1482
+ view ? /* @__PURE__ */ jsx8(BuilderEntryEditor, { view, editing, open: editorOpen, onClose: () => setEditorOpen(false) }) : null,
1483
+ /* @__PURE__ */ jsx8(
1106
1484
  ReadyConfirmDialog,
1107
1485
  {
1108
1486
  open: Boolean(pendingDelete),
@@ -1124,6 +1502,56 @@ function BuilderView({ viewId }) {
1124
1502
  )
1125
1503
  ] });
1126
1504
  }
1505
+ function BuilderForm(props) {
1506
+ const { components } = useBuilderRuntime();
1507
+ const Component = components.Form;
1508
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderForm, { ...props });
1509
+ }
1510
+ function BuilderGrid(props) {
1511
+ const { components } = useBuilderRuntime();
1512
+ const Component = components.Grid;
1513
+ return Component ? /* @__PURE__ */ jsx8(Component, { ...props }) : /* @__PURE__ */ jsx8(DefaultBuilderGrid, { ...props });
1514
+ }
1515
+ function BuilderView(props) {
1516
+ const { components } = useBuilderRuntime();
1517
+ const Component = components.View;
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)) });
1554
+ }
1127
1555
 
1128
1556
  // src/admin/editorState.ts
1129
1557
  var BUILDER_EDITOR_NONE_VALUE = "__none";
@@ -1170,7 +1598,7 @@ function clampLayoutSpan(span, columns) {
1170
1598
  return Math.max(1, Math.min(columns, Math.trunc(span)));
1171
1599
  }
1172
1600
  function builderFormEditorDefaultSpan(field) {
1173
- if (field.type === "textarea" || field.type === "checkbox") return 12;
1601
+ if (field.type === "textarea" || field.type === "richtext" || field.type === "checkbox") return 12;
1174
1602
  return 6;
1175
1603
  }
1176
1604
  function builderFormEditorDefaultLayoutGroups(fields, subforms = []) {
@@ -1237,6 +1665,10 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
1237
1665
  required: field.required,
1238
1666
  hidden: field.hidden ?? false,
1239
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,
1240
1672
  placeholder: field.placeholder ?? "",
1241
1673
  optionsText: builderEditorOptionsToText(field.options),
1242
1674
  optionsMode: field.optionsSource?.type === "dbTable" ? "table" : "static",
@@ -1279,16 +1711,19 @@ function builderFormEditorValuesFromEntity(form, emptyValues) {
1279
1711
  function builderListEditorValuesFromEntity(list, emptyValues) {
1280
1712
  if (!list) return emptyValues;
1281
1713
  const source = list.source;
1714
+ const orderBy = list.schema.orderBy ? Array.isArray(list.schema.orderBy) ? list.schema.orderBy : [list.schema.orderBy] : [];
1282
1715
  return {
1283
1716
  title: list.title,
1284
1717
  description: list.description ?? "",
1285
1718
  sourceType: source?.type ?? "none",
1286
1719
  sourceTable: source?.type === "dbTable" ? source.tableName : BUILDER_EDITOR_NONE_VALUE,
1287
1720
  apiBasePath: source?.type === "apiEndpoint" ? source.basePath : "",
1721
+ orderBy,
1288
1722
  columns: list.schema.columns.map((column) => ({
1289
1723
  key: column.key,
1290
1724
  label: column.label,
1291
1725
  sortable: column.sortable,
1726
+ hidden: column.hidden ?? false,
1292
1727
  align: column.align
1293
1728
  })),
1294
1729
  triggers: valuesFromTriggers(list.triggers),
@@ -1316,6 +1751,10 @@ function builderFormEditorFieldsFromTable(table) {
1316
1751
  required: !column.nullable,
1317
1752
  hidden: false,
1318
1753
  disabled: false,
1754
+ storage: "s3",
1755
+ contentKind: "image",
1756
+ multiple: false,
1757
+ maxMegabytes: 10,
1319
1758
  placeholder: column.label,
1320
1759
  optionsText: "",
1321
1760
  optionsMode: "static",
@@ -1333,6 +1772,7 @@ function builderListEditorColumnsFromTable(table) {
1333
1772
  key: column.name,
1334
1773
  label: column.label,
1335
1774
  sortable: column.sortable,
1775
+ hidden: false,
1336
1776
  align: column.fieldType === "number" || column.fieldType === "money" ? "right" : "left"
1337
1777
  }));
1338
1778
  }
@@ -1351,6 +1791,10 @@ function builderFormEditorInputFromValues(values) {
1351
1791
  required: field.required,
1352
1792
  hidden: field.hidden,
1353
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,
1354
1798
  placeholder: field.placeholder?.trim() || field.label,
1355
1799
  options: field.type === "select" && field.optionsMode === "static" ? builderEditorTextToOptions(field.optionsText) : void 0,
1356
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 ? {
@@ -1404,11 +1848,19 @@ function builderFormEditorInputFromValues(values) {
1404
1848
  }
1405
1849
  function builderListEditorInputFromValues(values) {
1406
1850
  const source = values.sourceType === "dbTable" && values.sourceTable !== BUILDER_EDITOR_NONE_VALUE ? { type: "dbTable", tableName: values.sourceTable } : values.sourceType === "apiEndpoint" && values.apiBasePath ? { type: "apiEndpoint", basePath: values.apiBasePath } : null;
1851
+ const orderBy = Array.from(
1852
+ new Map(
1853
+ values.orderBy.filter((rule) => rule.field && rule.field !== BUILDER_EDITOR_NONE_VALUE).map((rule) => [rule.field, rule])
1854
+ ).values()
1855
+ );
1407
1856
  return {
1408
1857
  title: values.title,
1409
1858
  description: values.description || null,
1410
1859
  source,
1411
- schema: { columns: values.columns },
1860
+ schema: {
1861
+ columns: values.columns,
1862
+ ...source && orderBy.length > 0 ? { orderBy } : {}
1863
+ },
1412
1864
  triggers: values.triggers.map((trigger) => ({
1413
1865
  event: trigger.event,
1414
1866
  action: "callApi",
@@ -1433,7 +1885,7 @@ function builderViewEditorInputFromValues(values, parseTriggers) {
1433
1885
  }
1434
1886
 
1435
1887
  // src/admin/BuilderDefaultEditorBodies.tsx
1436
- 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";
1437
1889
  var styles = {
1438
1890
  page: {
1439
1891
  display: "grid",
@@ -1554,7 +2006,7 @@ var styles = {
1554
2006
  }
1555
2007
  };
1556
2008
  function optionItems(options) {
1557
- 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));
1558
2010
  }
1559
2011
  function createBuilderDefaultFormEditorBody(options) {
1560
2012
  return function BuilderDefaultFormEditorBody({
@@ -1572,55 +2024,63 @@ function createBuilderDefaultFormEditorBody(options) {
1572
2024
  isSaving,
1573
2025
  importFieldsFromTable
1574
2026
  }) {
1575
- return /* @__PURE__ */ jsxs7("div", { style: styles.page, children: [
1576
- /* @__PURE__ */ jsxs7("div", { style: styles.header, children: [
1577
- /* @__PURE__ */ jsxs7("div", { children: [
1578
- /* @__PURE__ */ jsx7("h1", { style: styles.title, children: formId ? "Edit Dynamic Form" : "New Dynamic Form" }),
1579
- /* @__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." })
1580
2032
  ] }),
1581
- /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
1582
- /* @__PURE__ */ jsx7("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
1583
- /* @__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" })
1584
2036
  ] })
1585
2037
  ] }),
1586
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1587
- /* @__PURE__ */ jsx7("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Details" }) }),
1588
- /* @__PURE__ */ jsxs7("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
1589
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1590
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Title" }),
1591
- /* @__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 }) })
1592
2044
  ] }),
1593
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1594
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Description" }),
1595
- /* @__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") })
1596
2048
  ] }),
1597
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1598
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1599
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("presentation"), children: [
1600
- /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1601
- /* @__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" })
1602
2054
  ] })
1603
2055
  ] }),
1604
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1605
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Datasource" }),
1606
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceType"), children: [
1607
- /* @__PURE__ */ jsx7("option", { value: "none", children: "None" }),
1608
- /* @__PURE__ */ jsx7("option", { value: "dbTable", children: "DB table" }),
1609
- /* @__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" })
1610
2062
  ] })
1611
2063
  ] }),
1612
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1613
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1614
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceTable"), children: [
1615
- /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
1616
- tables.map((table) => /* @__PURE__ */ jsx7("option", { value: table.name, children: table.label ?? table.name }, table.name))
1617
- ] })
2064
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2065
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Table" }),
2066
+ /* @__PURE__ */ jsxs9(
2067
+ "select",
2068
+ {
2069
+ style: styles.input,
2070
+ value: sourceTable,
2071
+ ...form.register("sourceTable"),
2072
+ children: [
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))
2075
+ ]
2076
+ }
2077
+ )
1618
2078
  ] }) : null,
1619
- sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1620
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "API base path" }),
1621
- /* @__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") })
1622
2082
  ] }) : null,
1623
- 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(
1624
2084
  "button",
1625
2085
  {
1626
2086
  type: "button",
@@ -1632,13 +2092,13 @@ function createBuilderDefaultFormEditorBody(options) {
1632
2092
  ) }) : null
1633
2093
  ] })
1634
2094
  ] }),
1635
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1636
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1637
- /* @__PURE__ */ jsxs7("div", { children: [
1638
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Fields" }),
1639
- /* @__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." })
1640
2100
  ] }),
1641
- /* @__PURE__ */ jsx7(
2101
+ /* @__PURE__ */ jsx10(
1642
2102
  "button",
1643
2103
  {
1644
2104
  type: "button",
@@ -1656,18 +2116,18 @@ function createBuilderDefaultFormEditorBody(options) {
1656
2116
  }
1657
2117
  )
1658
2118
  ] }),
1659
- fieldArray.fields.map((field, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1660
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1661
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1662
- /* @__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`) })
1663
2123
  ] }),
1664
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1665
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1666
- /* @__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`) })
1667
2127
  ] }),
1668
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1669
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Type" }),
1670
- /* @__PURE__ */ jsx7(
2128
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2129
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Type" }),
2130
+ /* @__PURE__ */ jsx10(
1671
2131
  "select",
1672
2132
  {
1673
2133
  style: styles.input,
@@ -1676,27 +2136,51 @@ function createBuilderDefaultFormEditorBody(options) {
1676
2136
  }
1677
2137
  )
1678
2138
  ] }),
1679
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1680
- /* @__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`) }),
1681
2141
  "Required"
1682
2142
  ] }),
1683
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1684
- /* @__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`) }),
1685
2145
  "Hidden"
1686
2146
  ] }),
1687
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1688
- /* @__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`) }),
1689
2149
  "Disabled"
1690
2150
  ] }),
1691
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1692
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Placeholder" }),
1693
- /* @__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`) })
1694
2178
  ] }),
1695
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1696
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Static options" }),
1697
- /* @__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`) })
1698
2182
  ] }),
1699
- /* @__PURE__ */ jsx7("div", { style: styles.actions, children: /* @__PURE__ */ jsx7(
2183
+ /* @__PURE__ */ jsx10("div", { style: styles.actions, children: /* @__PURE__ */ jsx10(
1700
2184
  "button",
1701
2185
  {
1702
2186
  type: "button",
@@ -1708,13 +2192,13 @@ function createBuilderDefaultFormEditorBody(options) {
1708
2192
  ) })
1709
2193
  ] }, field.id))
1710
2194
  ] }),
1711
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1712
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1713
- /* @__PURE__ */ jsxs7("div", { children: [
1714
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Layout" }),
1715
- /* @__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." })
1716
2200
  ] }),
1717
- /* @__PURE__ */ jsx7(
2201
+ /* @__PURE__ */ jsx10(
1718
2202
  "button",
1719
2203
  {
1720
2204
  type: "button",
@@ -1726,14 +2210,14 @@ function createBuilderDefaultFormEditorBody(options) {
1726
2210
  }
1727
2211
  )
1728
2212
  ] }),
1729
- form.watch("layoutGroups").map((group, groupIndex) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1730
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1731
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Group title" }),
1732
- /* @__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`) })
1733
2217
  ] }),
1734
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1735
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Columns" }),
1736
- /* @__PURE__ */ jsxs7(
2218
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2219
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Columns" }),
2220
+ /* @__PURE__ */ jsxs9(
1737
2221
  "select",
1738
2222
  {
1739
2223
  style: styles.input,
@@ -1744,16 +2228,16 @@ function createBuilderDefaultFormEditorBody(options) {
1744
2228
  { shouldDirty: true }
1745
2229
  ),
1746
2230
  children: [
1747
- /* @__PURE__ */ jsx7("option", { value: 6, children: "6" }),
1748
- /* @__PURE__ */ jsx7("option", { value: 8, children: "8" }),
1749
- /* @__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" })
1750
2234
  ]
1751
2235
  }
1752
2236
  )
1753
2237
  ] }),
1754
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1755
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Fields" }),
1756
- /* @__PURE__ */ jsx7(
2238
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2239
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Fields" }),
2240
+ /* @__PURE__ */ jsx10(
1757
2241
  "input",
1758
2242
  {
1759
2243
  style: styles.input,
@@ -1764,13 +2248,13 @@ function createBuilderDefaultFormEditorBody(options) {
1764
2248
  ] })
1765
2249
  ] }, group.id))
1766
2250
  ] }),
1767
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1768
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1769
- /* @__PURE__ */ jsxs7("div", { children: [
1770
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Subforms" }),
1771
- /* @__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." })
1772
2256
  ] }),
1773
- /* @__PURE__ */ jsx7(
2257
+ /* @__PURE__ */ jsx10(
1774
2258
  "button",
1775
2259
  {
1776
2260
  type: "button",
@@ -1789,56 +2273,56 @@ function createBuilderDefaultFormEditorBody(options) {
1789
2273
  }
1790
2274
  )
1791
2275
  ] }),
1792
- subformArray.fields.map((subform, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1793
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1794
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1795
- /* @__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`) })
1796
2280
  ] }),
1797
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1798
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1799
- /* @__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`) })
1800
2284
  ] }),
1801
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1802
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "View ID" }),
1803
- /* @__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`) })
1804
2288
  ] }),
1805
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1806
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Parent field" }),
1807
- /* @__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`) })
1808
2292
  ] }),
1809
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1810
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Child field" }),
1811
- /* @__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`) })
1812
2296
  ] }),
1813
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1814
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Presentation" }),
1815
- /* @__PURE__ */ jsxs7(
2297
+ /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2298
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Presentation" }),
2299
+ /* @__PURE__ */ jsxs9(
1816
2300
  "select",
1817
2301
  {
1818
2302
  style: styles.input,
1819
2303
  ...form.register(`subforms.${index}.presentation`),
1820
2304
  children: [
1821
- /* @__PURE__ */ jsx7("option", { value: "dialog", children: "Dialog" }),
1822
- /* @__PURE__ */ jsx7("option", { value: "drawer", children: "Drawer" })
2305
+ /* @__PURE__ */ jsx10("option", { value: "dialog", children: "Dialog" }),
2306
+ /* @__PURE__ */ jsx10("option", { value: "drawer", children: "Drawer" })
1823
2307
  ]
1824
2308
  }
1825
2309
  )
1826
2310
  ] }),
1827
- /* @__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" })
1828
2312
  ] }, subform.id))
1829
2313
  ] }),
1830
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1831
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1832
- /* @__PURE__ */ jsxs7("div", { children: [
1833
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Form Triggers" }),
1834
- /* @__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." })
1835
2319
  ] }),
1836
- /* @__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" })
1837
2321
  ] }),
1838
- triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1839
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1840
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Event" }),
1841
- /* @__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(
1842
2326
  "select",
1843
2327
  {
1844
2328
  style: styles.input,
@@ -1849,19 +2333,19 @@ function createBuilderDefaultFormEditorBody(options) {
1849
2333
  }
1850
2334
  )
1851
2335
  ] }),
1852
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1853
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Route" }),
1854
- /* @__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`) })
1855
2339
  ] }),
1856
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1857
- /* @__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`) }),
1858
2342
  "Enabled"
1859
2343
  ] }),
1860
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1861
- /* @__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`) }),
1862
2346
  "Blocking"
1863
2347
  ] }),
1864
- /* @__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" })
1865
2349
  ] }, trigger.id))
1866
2350
  ] })
1867
2351
  ] });
@@ -1872,6 +2356,7 @@ function createBuilderDefaultListEditorBody(options) {
1872
2356
  listId,
1873
2357
  form,
1874
2358
  columnArray,
2359
+ orderByArray,
1875
2360
  triggerArray,
1876
2361
  sourceType,
1877
2362
  sourceTable,
@@ -1881,48 +2366,58 @@ function createBuilderDefaultListEditorBody(options) {
1881
2366
  isSaving,
1882
2367
  importColumnsFromTable
1883
2368
  }) {
1884
- return /* @__PURE__ */ jsxs7("div", { style: styles.page, children: [
1885
- /* @__PURE__ */ jsxs7("div", { style: styles.header, children: [
1886
- /* @__PURE__ */ jsxs7("div", { children: [
1887
- /* @__PURE__ */ jsx7("h1", { style: styles.title, children: listId ? "Edit Dynamic List" : "New Dynamic List" }),
1888
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Configure list columns, source mapping, and triggers." })
2369
+ const selectedTable = tables.find((table) => table.name === sourceTable);
2370
+ const orderByColumns = selectedTable?.columns.filter((column) => column.sortable) ?? [];
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." })
1889
2376
  ] }),
1890
- /* @__PURE__ */ jsxs7("div", { style: styles.actions, children: [
1891
- /* @__PURE__ */ jsx7("a", { href: options.backHref, style: styles.button, children: "Cancel" }),
1892
- /* @__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" })
1893
2380
  ] })
1894
2381
  ] }),
1895
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1896
- /* @__PURE__ */ jsx7("div", { style: styles.sectionHeader, children: /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Details" }) }),
1897
- /* @__PURE__ */ jsxs7("div", { style: { ...styles.grid, ...styles.twoColumn }, children: [
1898
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1899
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Title" }),
1900
- /* @__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 }) })
1901
2388
  ] }),
1902
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1903
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Description" }),
1904
- /* @__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") })
1905
2392
  ] }),
1906
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1907
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Datasource" }),
1908
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceType"), children: [
1909
- /* @__PURE__ */ jsx7("option", { value: "none", children: "None" }),
1910
- /* @__PURE__ */ jsx7("option", { value: "dbTable", children: "DB table" }),
1911
- /* @__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" })
1912
2399
  ] })
1913
2400
  ] }),
1914
- sourceType === "dbTable" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1915
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Table" }),
1916
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register("sourceTable"), children: [
1917
- /* @__PURE__ */ jsx7("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "Select table" }),
1918
- tables.map((table) => /* @__PURE__ */ jsx7("option", { value: table.name, children: table.label ?? table.name }, table.name))
1919
- ] })
2401
+ sourceType === "dbTable" ? /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2402
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Table" }),
2403
+ /* @__PURE__ */ jsxs9(
2404
+ "select",
2405
+ {
2406
+ style: styles.input,
2407
+ value: sourceTable,
2408
+ ...form.register("sourceTable"),
2409
+ children: [
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))
2412
+ ]
2413
+ }
2414
+ )
1920
2415
  ] }) : null,
1921
- sourceType === "apiEndpoint" ? /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1922
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "API base path" }),
1923
- /* @__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") })
1924
2419
  ] }) : null,
1925
- 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(
1926
2421
  "button",
1927
2422
  {
1928
2423
  type: "button",
@@ -1934,13 +2429,92 @@ function createBuilderDefaultListEditorBody(options) {
1934
2429
  ) }) : null
1935
2430
  ] })
1936
2431
  ] }),
1937
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1938
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1939
- /* @__PURE__ */ jsxs7("div", { children: [
1940
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "Columns" }),
1941
- /* @__PURE__ */ jsx7("p", { style: styles.description, children: "Runtime list columns." })
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." })
1942
2437
  ] }),
1943
- /* @__PURE__ */ jsx7(
2438
+ /* @__PURE__ */ jsx10(
2439
+ "button",
2440
+ {
2441
+ type: "button",
2442
+ style: styles.button,
2443
+ disabled: sourceType === "none" || orderByArray.fields.length >= 8,
2444
+ onClick: () => orderByArray.append({
2445
+ field: sourceType === "dbTable" ? orderByColumns[0]?.name ?? BUILDER_EDITOR_NONE_VALUE : "",
2446
+ direction: "desc"
2447
+ }),
2448
+ children: "Add ordering"
2449
+ }
2450
+ )
2451
+ ] }),
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))
2459
+ ] })
2460
+ ] }) : /* @__PURE__ */ jsxs9("label", { style: styles.field, children: [
2461
+ /* @__PURE__ */ jsx10("span", { style: styles.label, children: "Order by field" }),
2462
+ /* @__PURE__ */ jsx10(
2463
+ "input",
2464
+ {
2465
+ style: styles.input,
2466
+ placeholder: "createdAt",
2467
+ ...form.register(`orderBy.${index}.field`)
2468
+ }
2469
+ )
2470
+ ] }),
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" })
2476
+ ] })
2477
+ ] }),
2478
+ /* @__PURE__ */ jsxs9("div", { style: styles.actions, children: [
2479
+ /* @__PURE__ */ jsx10(
2480
+ "button",
2481
+ {
2482
+ type: "button",
2483
+ style: styles.button,
2484
+ disabled: index === 0,
2485
+ onClick: () => orderByArray.move(index, index - 1),
2486
+ children: "Move up"
2487
+ }
2488
+ ),
2489
+ /* @__PURE__ */ jsx10(
2490
+ "button",
2491
+ {
2492
+ type: "button",
2493
+ style: styles.button,
2494
+ disabled: index === orderByArray.fields.length - 1,
2495
+ onClick: () => orderByArray.move(index, index + 1),
2496
+ children: "Move down"
2497
+ }
2498
+ ),
2499
+ /* @__PURE__ */ jsx10(
2500
+ "button",
2501
+ {
2502
+ type: "button",
2503
+ style: styles.button,
2504
+ onClick: () => orderByArray.remove(index),
2505
+ children: "Remove"
2506
+ }
2507
+ )
2508
+ ] })
2509
+ ] }, rule.id))
2510
+ ] }),
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." })
2516
+ ] }),
2517
+ /* @__PURE__ */ jsx10(
1944
2518
  "button",
1945
2519
  {
1946
2520
  type: "button",
@@ -1954,50 +2528,44 @@ function createBuilderDefaultListEditorBody(options) {
1954
2528
  }
1955
2529
  )
1956
2530
  ] }),
1957
- columnArray.fields.map((column, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1958
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1959
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Key" }),
1960
- /* @__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`) })
1961
2535
  ] }),
1962
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1963
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Label" }),
1964
- /* @__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`) })
1965
2539
  ] }),
1966
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1967
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Align" }),
1968
- /* @__PURE__ */ jsxs7("select", { style: styles.input, ...form.register(`columns.${index}.align`), children: [
1969
- /* @__PURE__ */ jsx7("option", { value: "left", children: "Left" }),
1970
- /* @__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" })
1971
2545
  ] })
1972
2546
  ] }),
1973
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
1974
- /* @__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`) }),
1975
2549
  "Sortable"
1976
2550
  ] }),
1977
- /* @__PURE__ */ jsx7(
1978
- "button",
1979
- {
1980
- type: "button",
1981
- style: styles.button,
1982
- onClick: () => columnArray.remove(index),
1983
- disabled: columnArray.fields.length <= 1,
1984
- children: "Remove"
1985
- }
1986
- )
2551
+ /* @__PURE__ */ jsxs9("label", { style: styles.checkboxField, children: [
2552
+ /* @__PURE__ */ jsx10("input", { type: "checkbox", ...form.register(`columns.${index}.hidden`) }),
2553
+ "Hidden"
2554
+ ] })
1987
2555
  ] }, column.id))
1988
2556
  ] }),
1989
- /* @__PURE__ */ jsxs7("section", { style: styles.section, children: [
1990
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1991
- /* @__PURE__ */ jsxs7("div", { children: [
1992
- /* @__PURE__ */ jsx7("h2", { style: styles.sectionTitle, children: "List Triggers" }),
1993
- /* @__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." })
1994
2562
  ] }),
1995
- /* @__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" })
1996
2564
  ] }),
1997
- triggerArray.fields.map((trigger, index) => /* @__PURE__ */ jsxs7("div", { style: styles.row, children: [
1998
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
1999
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Event" }),
2000
- /* @__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(
2001
2569
  "select",
2002
2570
  {
2003
2571
  style: styles.input,
@@ -2008,19 +2576,19 @@ function createBuilderDefaultListEditorBody(options) {
2008
2576
  }
2009
2577
  )
2010
2578
  ] }),
2011
- /* @__PURE__ */ jsxs7("label", { style: styles.field, children: [
2012
- /* @__PURE__ */ jsx7("span", { style: styles.label, children: "Route" }),
2013
- /* @__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`) })
2014
2582
  ] }),
2015
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2016
- /* @__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`) }),
2017
2585
  "Enabled"
2018
2586
  ] }),
2019
- /* @__PURE__ */ jsxs7("label", { style: styles.checkboxField, children: [
2020
- /* @__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`) }),
2021
2589
  "Blocking"
2022
2590
  ] }),
2023
- /* @__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" })
2024
2592
  ] }, trigger.id))
2025
2593
  ] })
2026
2594
  ] });
@@ -2028,8 +2596,8 @@ function createBuilderDefaultListEditorBody(options) {
2028
2596
  }
2029
2597
 
2030
2598
  // src/admin/BuilderDefaultEntityManager.tsx
2031
- import { useMemo as useMemo5, useState as useState6 } from "react";
2032
- 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";
2033
2601
  var styles2 = {
2034
2602
  page: {
2035
2603
  display: "grid",
@@ -2125,7 +2693,7 @@ var styles2 = {
2125
2693
  };
2126
2694
  function createBuilderDefaultEntityManagerComponent(deps) {
2127
2695
  return function BuilderDefaultEntityManager() {
2128
- const [state, setState] = useState6({
2696
+ const [state, setState] = useState7({
2129
2697
  page: 1,
2130
2698
  pageSize: 20,
2131
2699
  search: ""
@@ -2146,16 +2714,16 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2146
2714
  if (!window.confirm(deps.labels.deleteConfirm(entity))) return;
2147
2715
  await remove.mutateAsync(entity.id);
2148
2716
  };
2149
- return /* @__PURE__ */ jsxs8("section", { style: styles2.page, children: [
2150
- /* @__PURE__ */ jsxs8("div", { style: styles2.header, children: [
2151
- /* @__PURE__ */ jsxs8("div", { children: [
2152
- /* @__PURE__ */ jsx8("h1", { style: styles2.title, children: deps.labels.title }),
2153
- /* @__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 })
2154
2722
  ] }),
2155
- 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
2156
2724
  ] }),
2157
- /* @__PURE__ */ jsxs8("div", { style: styles2.card, children: [
2158
- /* @__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(
2159
2727
  "input",
2160
2728
  {
2161
2729
  style: styles2.input,
@@ -2164,21 +2732,21 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2164
2732
  onChange: (event) => setState((current) => ({ ...current, page: 1, search: event.target.value }))
2165
2733
  }
2166
2734
  ) }),
2167
- /* @__PURE__ */ jsx8("div", { style: styles2.tableWrap, children: /* @__PURE__ */ jsxs8("table", { style: styles2.table, children: [
2168
- /* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
2169
- /* @__PURE__ */ jsx8("th", { style: styles2.th, children: deps.labels.title }),
2170
- /* @__PURE__ */ jsx8("th", { style: styles2.th, children: "Detail" }),
2171
- /* @__PURE__ */ jsx8("th", { style: styles2.th, children: "Description" }),
2172
- /* @__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" })
2173
2741
  ] }) }),
2174
- /* @__PURE__ */ jsx8("tbody", { children: items.map((entity) => /* @__PURE__ */ jsxs8("tr", { children: [
2175
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: /* @__PURE__ */ jsx8("a", { href: deps.editHref(entity), children: entity.title }) }),
2176
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: deps.getDetail?.(entity) ?? "-" }),
2177
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: entity.description || "-" }),
2178
- /* @__PURE__ */ jsx8("td", { style: styles2.td, children: /* @__PURE__ */ jsxs8("div", { style: styles2.actions, children: [
2179
- deps.runtimeHref ? /* @__PURE__ */ jsx8("a", { href: deps.runtimeHref(entity), style: styles2.button, children: deps.labels.runtimeLabel }) : null,
2180
- /* @__PURE__ */ jsx8("a", { href: deps.editHref(entity), style: styles2.button, children: deps.labels.editLabel }),
2181
- /* @__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(
2182
2750
  "button",
2183
2751
  {
2184
2752
  type: "button",
@@ -2187,7 +2755,7 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2187
2755
  children: deps.labels.replicateLabel
2188
2756
  }
2189
2757
  ),
2190
- /* @__PURE__ */ jsx8(
2758
+ /* @__PURE__ */ jsx11(
2191
2759
  "button",
2192
2760
  {
2193
2761
  type: "button",
@@ -2200,11 +2768,11 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2200
2768
  ] }) })
2201
2769
  ] }, entity.id)) })
2202
2770
  ] }) }),
2203
- query.isPending ? /* @__PURE__ */ jsx8("div", { style: styles2.empty, children: "Loading..." }) : null,
2204
- query.isError ? /* @__PURE__ */ jsx8("div", { style: styles2.empty, children: "Failed to load." }) : null,
2205
- !query.isPending && !query.isError && items.length === 0 ? /* @__PURE__ */ jsxs8("div", { style: styles2.empty, children: [
2206
- /* @__PURE__ */ jsx8("strong", { children: deps.labels.emptyTitle }),
2207
- /* @__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 })
2208
2776
  ] }) : null
2209
2777
  ] })
2210
2778
  ] });
@@ -2212,9 +2780,9 @@ function createBuilderDefaultEntityManagerComponent(deps) {
2212
2780
  }
2213
2781
 
2214
2782
  // src/admin/BuilderDefaultViewEditorPage.tsx
2215
- import { useEffect as useEffect3 } from "react";
2783
+ import { useEffect as useEffect4 } from "react";
2216
2784
  import { useForm as useForm3 } from "react-hook-form";
2217
- 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";
2218
2786
  var styles3 = {
2219
2787
  page: {
2220
2788
  display: "grid",
@@ -2331,7 +2899,7 @@ function createBuilderDefaultViewEditorPage(options) {
2331
2899
  permissionWrite: defaultPermission
2332
2900
  }
2333
2901
  });
2334
- useEffect3(() => {
2902
+ useEffect4(() => {
2335
2903
  if (viewId && !view.data) return;
2336
2904
  form.reset(
2337
2905
  builderViewEditorValuesFromEntity(
@@ -2362,64 +2930,64 @@ function createBuilderDefaultViewEditorPage(options) {
2362
2930
  }
2363
2931
  });
2364
2932
  if (viewId && view.isPending) {
2365
- return /* @__PURE__ */ jsx9("div", { style: styles3.state, children: "Loading..." });
2933
+ return /* @__PURE__ */ jsx12("div", { style: styles3.state, children: "Loading..." });
2366
2934
  }
2367
2935
  if (viewId && view.isError) {
2368
- 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." });
2369
2937
  }
2370
- return /* @__PURE__ */ jsxs9("form", { onSubmit, noValidate: true, style: styles3.page, children: [
2371
- /* @__PURE__ */ jsxs9("div", { style: styles3.header, children: [
2372
- /* @__PURE__ */ jsxs9("div", { children: [
2373
- /* @__PURE__ */ jsx9("h1", { style: styles3.title, children: viewId ? "Edit Dynamic View" : "New Dynamic View" }),
2374
- /* @__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." })
2375
2943
  ] }),
2376
- /* @__PURE__ */ jsxs9("div", { style: styles3.actions, children: [
2377
- /* @__PURE__ */ jsx9("a", { href: options.backHref, style: styles3.button, children: "Cancel" }),
2378
- /* @__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" })
2379
2947
  ] })
2380
2948
  ] }),
2381
- /* @__PURE__ */ jsx9("section", { style: styles3.section, children: /* @__PURE__ */ jsxs9("div", { style: styles3.grid, children: [
2382
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2383
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Title" }),
2384
- /* @__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 }) })
2385
2953
  ] }),
2386
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2387
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Description" }),
2388
- /* @__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") })
2389
2957
  ] }),
2390
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2391
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Form" }),
2392
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("formId"), children: [
2393
- /* @__PURE__ */ jsx9("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No form" }),
2394
- (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))
2395
2963
  ] })
2396
2964
  ] }),
2397
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2398
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "List" }),
2399
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("listId"), children: [
2400
- /* @__PURE__ */ jsx9("option", { value: BUILDER_EDITOR_NONE_VALUE, children: "No list" }),
2401
- (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))
2402
2970
  ] })
2403
2971
  ] }),
2404
- showPermissions ? /* @__PURE__ */ jsxs9(Fragment, { children: [
2405
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2406
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Read permission" }),
2407
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("permissionRead"), children: [
2408
- /* @__PURE__ */ jsx9("option", { value: "", children: "Authenticated users" }),
2409
- 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))
2410
2978
  ] })
2411
2979
  ] }),
2412
- /* @__PURE__ */ jsxs9("label", { style: styles3.field, children: [
2413
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Write permission" }),
2414
- /* @__PURE__ */ jsxs9("select", { style: styles3.input, ...form.register("permissionWrite"), children: [
2415
- /* @__PURE__ */ jsx9("option", { value: "", children: "Authenticated users" }),
2416
- 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))
2417
2985
  ] })
2418
2986
  ] })
2419
2987
  ] }) : null,
2420
- /* @__PURE__ */ jsxs9("label", { style: { ...styles3.field, gridColumn: "1 / -1" }, children: [
2421
- /* @__PURE__ */ jsx9("span", { style: styles3.label, children: "Triggers JSON" }),
2422
- /* @__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") })
2423
2991
  ] })
2424
2992
  ] }) })
2425
2993
  ] });
@@ -2427,14 +2995,14 @@ function createBuilderDefaultViewEditorPage(options) {
2427
2995
  }
2428
2996
 
2429
2997
  // src/admin/BuilderEditorPage.tsx
2430
- import { useEffect as useEffect4 } from "react";
2998
+ import { useEffect as useEffect5 } from "react";
2431
2999
  import {
2432
3000
  FormProvider as FormProvider3,
2433
3001
  useFieldArray,
2434
3002
  useForm as useForm4,
2435
- useWatch as useWatch2
3003
+ useWatch as useWatch5
2436
3004
  } from "react-hook-form";
2437
- import { jsx as jsx10 } from "react/jsx-runtime";
3005
+ import { jsx as jsx13 } from "react/jsx-runtime";
2438
3006
  function createBuilderFormEditorPageComponent(deps) {
2439
3007
  return function BuilderFormEditorPage({ formId }) {
2440
3008
  const Body = deps.Body;
@@ -2448,11 +3016,11 @@ function createBuilderFormEditorPageComponent(deps) {
2448
3016
  const fieldArray = useFieldArray({ control: form.control, name: "fields" });
2449
3017
  const subformArray = useFieldArray({ control: form.control, name: "subforms" });
2450
3018
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
2451
- const fields = useWatch2({ control: form.control, name: "fields" }) ?? [];
2452
- const subforms = useWatch2({ control: form.control, name: "subforms" }) ?? [];
2453
- const sourceType = useWatch2({ control: form.control, name: "sourceType" });
2454
- const sourceTable = useWatch2({ control: form.control, name: "sourceTable" });
2455
- 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(() => {
2456
3024
  if (formId && !entityQuery.data) return;
2457
3025
  form.reset(builderFormEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
2458
3026
  }, [entityQuery.data, form, formId]);
@@ -2475,12 +3043,12 @@ function createBuilderFormEditorPageComponent(deps) {
2475
3043
  }
2476
3044
  });
2477
3045
  if (formId && entityQuery.isPending) {
2478
- 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 });
2479
3047
  }
2480
3048
  if (formId && entityQuery.isError) {
2481
- 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 });
2482
3050
  }
2483
- 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(
2484
3052
  Body,
2485
3053
  {
2486
3054
  formId,
@@ -2512,10 +3080,11 @@ function createBuilderListEditorPageComponent(deps) {
2512
3080
  defaultValues: deps.emptyValues
2513
3081
  });
2514
3082
  const columnArray = useFieldArray({ control: form.control, name: "columns" });
3083
+ const orderByArray = useFieldArray({ control: form.control, name: "orderBy" });
2515
3084
  const triggerArray = useFieldArray({ control: form.control, name: "triggers" });
2516
- const sourceType = useWatch2({ control: form.control, name: "sourceType" });
2517
- const sourceTable = useWatch2({ control: form.control, name: "sourceTable" });
2518
- useEffect4(() => {
3085
+ const sourceType = useWatch5({ control: form.control, name: "sourceType" });
3086
+ const sourceTable = useWatch5({ control: form.control, name: "sourceTable" });
3087
+ useEffect5(() => {
2519
3088
  if (listId && !entityQuery.data) return;
2520
3089
  form.reset(builderListEditorValuesFromEntity(entityQuery.data ?? null, deps.emptyValues));
2521
3090
  }, [entityQuery.data, form, listId]);
@@ -2534,17 +3103,18 @@ function createBuilderListEditorPageComponent(deps) {
2534
3103
  }
2535
3104
  });
2536
3105
  if (listId && entityQuery.isPending) {
2537
- 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 });
2538
3107
  }
2539
3108
  if (listId && entityQuery.isError) {
2540
- 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 });
2541
3110
  }
2542
- 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(
2543
3112
  Body,
2544
3113
  {
2545
3114
  listId,
2546
3115
  form,
2547
3116
  columnArray,
3117
+ orderByArray,
2548
3118
  triggerArray,
2549
3119
  sourceType,
2550
3120
  sourceTable,
@@ -2559,10 +3129,11 @@ function createBuilderListEditorPageComponent(deps) {
2559
3129
  }
2560
3130
 
2561
3131
  // src/admin/BuilderAdminPages.tsx
2562
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3132
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2563
3133
  var defaultFieldTypeOptions = [
2564
3134
  { value: "text", label: "Text" },
2565
3135
  { value: "textarea", label: "Textarea" },
3136
+ { value: "richtext", label: "Rich text" },
2566
3137
  { value: "number", label: "Number" },
2567
3138
  { value: "money", label: "Money" },
2568
3139
  { value: "select", label: "Select" },
@@ -2673,6 +3244,10 @@ function createBuilderAdminPages({
2673
3244
  required: true,
2674
3245
  hidden: false,
2675
3246
  disabled: false,
3247
+ storage: "s3",
3248
+ contentKind: "image",
3249
+ multiple: false,
3250
+ maxMegabytes: 10,
2676
3251
  placeholder: "",
2677
3252
  optionsText: "",
2678
3253
  optionsMode: "static",
@@ -2707,6 +3282,7 @@ function createBuilderAdminPages({
2707
3282
  key: "name",
2708
3283
  label: "Name",
2709
3284
  sortable: true,
3285
+ hidden: false,
2710
3286
  align: "left"
2711
3287
  };
2712
3288
  const emptyListValues = {
@@ -2715,6 +3291,7 @@ function createBuilderAdminPages({
2715
3291
  sourceType: "none",
2716
3292
  sourceTable: BUILDER_EDITOR_NONE_VALUE,
2717
3293
  apiBasePath: "",
3294
+ orderBy: [],
2718
3295
  columns: [emptyColumn],
2719
3296
  triggers: [],
2720
3297
  version: 0
@@ -2817,14 +3394,14 @@ function createBuilderAdminPages({
2817
3394
  href: viewsPath
2818
3395
  }
2819
3396
  ];
2820
- return /* @__PURE__ */ jsxs10("section", { style: homeStyles.page, children: [
2821
- /* @__PURE__ */ jsxs10("div", { children: [
2822
- /* @__PURE__ */ jsx11("h1", { style: homeStyles.headerTitle, children: "Builder" }),
2823
- /* @__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." })
2824
3401
  ] }),
2825
- /* @__PURE__ */ jsx11("div", { style: homeStyles.grid, children: items.map((item) => /* @__PURE__ */ jsxs10("a", { href: item.href, style: homeStyles.card, children: [
2826
- /* @__PURE__ */ jsx11("h2", { style: homeStyles.cardTitle, children: item.title }),
2827
- /* @__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 })
2828
3405
  ] }, item.href)) })
2829
3406
  ] });
2830
3407
  };
@@ -2913,24 +3490,24 @@ function createBuilderAdminPages({
2913
3490
  AdminHomePage,
2914
3491
  AdminFormsPage,
2915
3492
  AdminNewFormPage: function BuilderAdminNewFormPage() {
2916
- return /* @__PURE__ */ jsx11(FormEditorPage, {});
3493
+ return /* @__PURE__ */ jsx14(FormEditorPage, {});
2917
3494
  },
2918
3495
  AdminEditFormPage: function BuilderAdminEditFormPage({ formId }) {
2919
- return /* @__PURE__ */ jsx11(FormEditorPage, { formId });
3496
+ return /* @__PURE__ */ jsx14(FormEditorPage, { formId });
2920
3497
  },
2921
3498
  AdminListsPage,
2922
3499
  AdminNewListPage: function BuilderAdminNewListPage() {
2923
- return /* @__PURE__ */ jsx11(ListEditorPage, {});
3500
+ return /* @__PURE__ */ jsx14(ListEditorPage, {});
2924
3501
  },
2925
3502
  AdminEditListPage: function BuilderAdminEditListPage({ listId }) {
2926
- return /* @__PURE__ */ jsx11(ListEditorPage, { listId });
3503
+ return /* @__PURE__ */ jsx14(ListEditorPage, { listId });
2927
3504
  },
2928
3505
  AdminViewsPage,
2929
3506
  AdminNewViewPage: function BuilderAdminNewViewPage() {
2930
- return /* @__PURE__ */ jsx11(ViewEditorPage, {});
3507
+ return /* @__PURE__ */ jsx14(ViewEditorPage, {});
2931
3508
  },
2932
3509
  AdminEditViewPage: function BuilderAdminEditViewPage({ viewId }) {
2933
- return /* @__PURE__ */ jsx11(ViewEditorPage, { viewId });
3510
+ return /* @__PURE__ */ jsx14(ViewEditorPage, { viewId });
2934
3511
  },
2935
3512
  routes: {
2936
3513
  adminBasePath,
@@ -2948,11 +3525,11 @@ function createBuilderAdminPages({
2948
3525
  }
2949
3526
 
2950
3527
  // src/admin/BuilderEntityManager.tsx
2951
- import { useCallback as useCallback2, useMemo as useMemo6, useState as useState7 } from "react";
2952
- 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";
2953
3530
  function createBuilderEntityManagerComponent(deps) {
2954
3531
  return function BuilderEntityManager() {
2955
- const [pendingDelete, setPendingDelete] = useState7(null);
3532
+ const [pendingDelete, setPendingDelete] = useState8(null);
2956
3533
  const state = deps.useDataTableState({ pageSize: 20 });
2957
3534
  const query = deps.hooks.useEntities(state.query);
2958
3535
  const remove = deps.hooks.useDelete();
@@ -2977,8 +3554,8 @@ function createBuilderEntityManagerComponent(deps) {
2977
3554
  state,
2978
3555
  getRowId: (row) => row.id
2979
3556
  });
2980
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
2981
- /* @__PURE__ */ jsx12(
3557
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3558
+ /* @__PURE__ */ jsx15(
2982
3559
  deps.DataGrid,
2983
3560
  {
2984
3561
  title: deps.labels.title,
@@ -2989,10 +3566,10 @@ function createBuilderEntityManagerComponent(deps) {
2989
3566
  emptyTitle: deps.labels.emptyTitle,
2990
3567
  emptyDescription: deps.labels.emptyDescription,
2991
3568
  onRowClick: deps.navigateToEdit,
2992
- 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 })
2993
3570
  }
2994
3571
  ),
2995
- /* @__PURE__ */ jsx12(
3572
+ /* @__PURE__ */ jsx15(
2996
3573
  deps.DeleteDialog,
2997
3574
  {
2998
3575
  entity: pendingDelete,
@@ -3012,9 +3589,9 @@ function createBuilderEntityManagerComponent(deps) {
3012
3589
  }
3013
3590
  function createBuilderEntityDialogManagerComponent(deps) {
3014
3591
  return function BuilderEntityDialogManager() {
3015
- const [editing, setEditing] = useState7(null);
3016
- const [isEditorOpen, setEditorOpen] = useState7(false);
3017
- const [pendingDelete, setPendingDelete] = useState7(null);
3592
+ const [editing, setEditing] = useState8(null);
3593
+ const [isEditorOpen, setEditorOpen] = useState8(false);
3594
+ const [pendingDelete, setPendingDelete] = useState8(null);
3018
3595
  const state = deps.useDataTableState({ pageSize: 20 });
3019
3596
  const query = deps.hooks.useEntities(state.query);
3020
3597
  const remove = deps.hooks.useDelete();
@@ -3043,8 +3620,8 @@ function createBuilderEntityDialogManagerComponent(deps) {
3043
3620
  state,
3044
3621
  getRowId: (row) => row.id
3045
3622
  });
3046
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
3047
- /* @__PURE__ */ jsx12(
3623
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3624
+ /* @__PURE__ */ jsx15(
3048
3625
  deps.DataGrid,
3049
3626
  {
3050
3627
  title: deps.labels.title,
@@ -3055,10 +3632,10 @@ function createBuilderEntityDialogManagerComponent(deps) {
3055
3632
  emptyTitle: deps.labels.emptyTitle,
3056
3633
  emptyDescription: deps.labels.emptyDescription,
3057
3634
  onRowClick: openEditor,
3058
- 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) })
3059
3636
  }
3060
3637
  ),
3061
- /* @__PURE__ */ jsx12(
3638
+ /* @__PURE__ */ jsx15(
3062
3639
  deps.EditorDialog,
3063
3640
  {
3064
3641
  open: isEditorOpen,
@@ -3066,7 +3643,7 @@ function createBuilderEntityDialogManagerComponent(deps) {
3066
3643
  onClose: () => setEditorOpen(false)
3067
3644
  }
3068
3645
  ),
3069
- /* @__PURE__ */ jsx12(
3646
+ /* @__PURE__ */ jsx15(
3070
3647
  deps.DeleteDialog,
3071
3648
  {
3072
3649
  entity: pendingDelete,
@@ -3086,9 +3663,9 @@ function createBuilderEntityDialogManagerComponent(deps) {
3086
3663
  }
3087
3664
 
3088
3665
  // src/admin/BuilderViewDialog.tsx
3089
- import { useEffect as useEffect5 } from "react";
3666
+ import { useEffect as useEffect6 } from "react";
3090
3667
  import { FormProvider as FormProvider4, useForm as useForm5 } from "react-hook-form";
3091
- import { jsx as jsx13 } from "react/jsx-runtime";
3668
+ import { jsx as jsx16 } from "react/jsx-runtime";
3092
3669
  function createBuilderViewDialogComponent(deps) {
3093
3670
  return function BuilderViewDialog({
3094
3671
  open,
@@ -3103,7 +3680,7 @@ function createBuilderViewDialogComponent(deps) {
3103
3680
  resolver: deps.resolver,
3104
3681
  defaultValues: deps.emptyValues
3105
3682
  });
3106
- useEffect5(() => {
3683
+ useEffect6(() => {
3107
3684
  if (!open) return;
3108
3685
  form.reset(
3109
3686
  builderViewEditorValuesFromEntity(editing, deps.emptyValues, deps.defaultPermission)
@@ -3118,7 +3695,7 @@ function createBuilderViewDialogComponent(deps) {
3118
3695
  deps.notifications.error(error);
3119
3696
  }
3120
3697
  });
3121
- 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({
3122
3699
  form,
3123
3700
  editing,
3124
3701
  forms,
@@ -3133,7 +3710,7 @@ function createBuilderViewDialogComponent(deps) {
3133
3710
 
3134
3711
  // src/admin/formLayoutEditorState.ts
3135
3712
  import { useMemo as useMemo7 } from "react";
3136
- import { useWatch as useWatch3 } from "react-hook-form";
3713
+ import { useWatch as useWatch6 } from "react-hook-form";
3137
3714
  var builderFormLayoutDragDataType = "application/x-winu-builder-layout-field";
3138
3715
  function clampBuilderFormLayoutSpan(span, columns) {
3139
3716
  return Math.max(1, Math.min(columns, span));
@@ -3180,7 +3757,7 @@ function parseBuilderFormLayoutDragPayload(raw) {
3180
3757
  }
3181
3758
  }
3182
3759
  function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
3183
- const layoutGroups = useWatch3({ control: form.control, name: "layoutGroups" }) ?? [];
3760
+ const layoutGroups = useWatch6({ control: form.control, name: "layoutGroups" }) ?? [];
3184
3761
  const layoutItems = useMemo7(
3185
3762
  () => [
3186
3763
  ...fields.map((field) => ({
@@ -3303,7 +3880,7 @@ function useBuilderFormLayoutEditor({ form, fields, subforms = [] }) {
3303
3880
  // src/components/DynamicForm.tsx
3304
3881
  import { useMemo as useMemo8 } from "react";
3305
3882
  import { FormProvider as FormProvider5, useForm as useForm6 } from "react-hook-form";
3306
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
3883
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
3307
3884
  function createDynamicFormComponent(deps) {
3308
3885
  return function DynamicForm({ formId }) {
3309
3886
  const query = deps.hooks.useRuntimeBuilderForm(formId);
@@ -3326,7 +3903,7 @@ function createDynamicFormComponent(deps) {
3326
3903
  }
3327
3904
  });
3328
3905
  if (query.isError) {
3329
- return /* @__PURE__ */ jsx14(
3906
+ return /* @__PURE__ */ jsx17(
3330
3907
  deps.ErrorState,
3331
3908
  {
3332
3909
  title: "Form \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3335,16 +3912,16 @@ function createDynamicFormComponent(deps) {
3335
3912
  );
3336
3913
  }
3337
3914
  if (!query.data) return null;
3338
- 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: [
3339
- /* @__PURE__ */ jsx14(deps.FormFields, { formId, schema: query.data.schema, namePrefix: "values" }),
3340
- /* @__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 })
3341
3918
  ] }) }) });
3342
3919
  };
3343
3920
  }
3344
3921
 
3345
3922
  // src/components/DynamicList.tsx
3346
3923
  import { useMemo as useMemo9 } from "react";
3347
- import { jsx as jsx15 } from "react/jsx-runtime";
3924
+ import { jsx as jsx18 } from "react/jsx-runtime";
3348
3925
  function createDynamicListComponent(deps) {
3349
3926
  return function DynamicList({ listId }) {
3350
3927
  const query = deps.hooks.useRuntimeBuilderList(listId);
@@ -3360,7 +3937,7 @@ function createDynamicListComponent(deps) {
3360
3937
  getRowId: (row) => row.id
3361
3938
  });
3362
3939
  if (query.isError) {
3363
- return /* @__PURE__ */ jsx15(
3940
+ return /* @__PURE__ */ jsx18(
3364
3941
  deps.ErrorState,
3365
3942
  {
3366
3943
  title: "List \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3368,7 +3945,7 @@ function createDynamicListComponent(deps) {
3368
3945
  }
3369
3946
  );
3370
3947
  }
3371
- return /* @__PURE__ */ jsx15(
3948
+ return /* @__PURE__ */ jsx18(
3372
3949
  deps.DataGrid,
3373
3950
  {
3374
3951
  title: query.data?.title ?? "Dynamic List",
@@ -3384,8 +3961,8 @@ function createDynamicListComponent(deps) {
3384
3961
  }
3385
3962
 
3386
3963
  // src/components/DynamicView.tsx
3387
- import { useMemo as useMemo10, useState as useState8 } from "react";
3388
- 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";
3389
3966
  var interactiveRowTargetSelector = "button,a,input,select,textarea,[role='button'],[role='menuitem'],[data-builder-row-action]";
3390
3967
  function hasClosest(target) {
3391
3968
  return typeof target === "object" && target !== null && "closest" in target && typeof target.closest === "function";
@@ -3397,9 +3974,9 @@ function shouldHandleDynamicViewRowClick(event) {
3397
3974
  }
3398
3975
  function createDynamicViewComponent(deps) {
3399
3976
  return function DynamicView({ viewId }) {
3400
- const [editing, setEditing] = useState8(null);
3401
- const [isDialogOpen, setDialogOpen] = useState8(false);
3402
- const [pendingDelete, setPendingDelete] = useState8(null);
3977
+ const [editing, setEditing] = useState9(null);
3978
+ const [isDialogOpen, setDialogOpen] = useState9(false);
3979
+ const [pendingDelete, setPendingDelete] = useState9(null);
3403
3980
  const viewQuery = deps.hooks.useRuntimeBuilderView(viewId);
3404
3981
  const state = deps.useDataTableState({ pageSize: 20 });
3405
3982
  const entriesQuery = deps.hooks.useBuilderViewEntries(viewId, state.query);
@@ -3428,7 +4005,7 @@ function createDynamicViewComponent(deps) {
3428
4005
  getRowId: (row) => row.id
3429
4006
  });
3430
4007
  if (viewQuery.isError) {
3431
- return /* @__PURE__ */ jsx16(
4008
+ return /* @__PURE__ */ jsx19(
3432
4009
  deps.ErrorState,
3433
4010
  {
3434
4011
  title: "View \u043D\u044D\u044D\u0433\u0434\u0441\u044D\u043D\u0433\u04AF\u0439",
@@ -3436,8 +4013,8 @@ function createDynamicViewComponent(deps) {
3436
4013
  }
3437
4014
  );
3438
4015
  }
3439
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3440
- /* @__PURE__ */ jsx16(
4016
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-6", children: [
4017
+ /* @__PURE__ */ jsx19(
3441
4018
  deps.DataGrid,
3442
4019
  {
3443
4020
  title: view?.title ?? "Dynamic View",
@@ -3452,7 +4029,7 @@ function createDynamicViewComponent(deps) {
3452
4029
  setEditing(entry);
3453
4030
  setDialogOpen(true);
3454
4031
  },
3455
- toolbarExtra: /* @__PURE__ */ jsx16(
4032
+ toolbarExtra: /* @__PURE__ */ jsx19(
3456
4033
  deps.AddButton,
3457
4034
  {
3458
4035
  disabled: !view?.form,
@@ -3464,7 +4041,7 @@ function createDynamicViewComponent(deps) {
3464
4041
  )
3465
4042
  }
3466
4043
  ),
3467
- view ? /* @__PURE__ */ jsx16(
4044
+ view ? /* @__PURE__ */ jsx19(
3468
4045
  deps.EntryDialog,
3469
4046
  {
3470
4047
  open: isDialogOpen,
@@ -3475,7 +4052,7 @@ function createDynamicViewComponent(deps) {
3475
4052
  isSaving: save.isPending
3476
4053
  }
3477
4054
  ) : null,
3478
- /* @__PURE__ */ jsx16(
4055
+ /* @__PURE__ */ jsx19(
3479
4056
  deps.DeleteDialog,
3480
4057
  {
3481
4058
  entry: pendingDelete,
@@ -3493,9 +4070,9 @@ function createDynamicViewComponent(deps) {
3493
4070
  }
3494
4071
 
3495
4072
  // src/components/RuntimeEntryDialog.tsx
3496
- 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";
3497
4074
  import { FormProvider as FormProvider6, useForm as useForm7 } from "react-hook-form";
3498
- import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
4075
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
3499
4076
  function isDbTableSource(source) {
3500
4077
  return source?.type === "dbTable" && "tableName" in source;
3501
4078
  }
@@ -3519,6 +4096,12 @@ function childRowPayload(row, includeIdentity) {
3519
4096
  ...values
3520
4097
  };
3521
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
+ }
3522
4105
  function createRuntimeEntryDialogComponent(deps) {
3523
4106
  return function RuntimeEntryDialog({
3524
4107
  open,
@@ -3528,7 +4111,8 @@ function createRuntimeEntryDialogComponent(deps) {
3528
4111
  onSave,
3529
4112
  isSaving
3530
4113
  }) {
3531
- const [draftSubforms, setDraftSubforms] = useState9({});
4114
+ const [draftSubforms, setDraftSubforms] = useState10({});
4115
+ const isSubmittingRef = useRef8(false);
3532
4116
  const compositeCreate = deps.useCreateCompositeEntry?.(view.id);
3533
4117
  const compositeUpdate = deps.useUpdateCompositeEntry?.(view.id);
3534
4118
  const form = useForm7({
@@ -3536,16 +4120,18 @@ function createRuntimeEntryDialogComponent(deps) {
3536
4120
  values: open ? createBuilderEntryDefaultValues(view, editing) : void 0
3537
4121
  });
3538
4122
  const mainTableName = runtimeViewTableName(view);
3539
- const hasDraftRows = useMemo11(
3540
- () => Object.values(draftSubforms).some((draft) => draft.rows.length > 0),
4123
+ const hasDraftChanges = useMemo11(
4124
+ () => Object.values(draftSubforms).some((draft) => draft.rows.some(hasDraftChange)),
3541
4125
  [draftSubforms]
3542
4126
  );
3543
- useEffect6(() => {
4127
+ useEffect7(() => {
3544
4128
  if (open) setDraftSubforms({});
3545
4129
  }, [open]);
3546
4130
  const onSubmit = form.handleSubmit(async (values) => {
4131
+ if (isSubmittingRef.current) return;
4132
+ isSubmittingRef.current = true;
3547
4133
  try {
3548
- if (!editing && hasDraftRows) {
4134
+ if (!editing && hasDraftChanges) {
3549
4135
  if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3550
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");
3551
4137
  await compositeCreate.mutateAsync({
@@ -3554,12 +4140,12 @@ function createRuntimeEntryDialogComponent(deps) {
3554
4140
  ...Object.fromEntries(
3555
4141
  Object.values(draftSubforms).map((draft) => [
3556
4142
  draft.dataKey,
3557
- draft.rows.filter((row) => row.values._delete !== true).map((row) => childRowPayload(row, false))
4143
+ changedChildPayloads(draft.rows, false)
3558
4144
  ])
3559
4145
  )
3560
4146
  }
3561
4147
  });
3562
- } else if (editing && hasDraftRows) {
4148
+ } else if (editing && hasDraftChanges) {
3563
4149
  if (!mainTableName) throw new Error("Main form datasource table \u043E\u043B\u0434\u0441\u043E\u043D\u0433\u04AF\u0439");
3564
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");
3565
4151
  await compositeUpdate.mutateAsync({
@@ -3574,7 +4160,7 @@ function createRuntimeEntryDialogComponent(deps) {
3574
4160
  ...Object.fromEntries(
3575
4161
  Object.values(draftSubforms).map((draft) => [
3576
4162
  draft.dataKey,
3577
- draft.rows.map((row) => childRowPayload(row, true))
4163
+ changedChildPayloads(draft.rows, true)
3578
4164
  ])
3579
4165
  )
3580
4166
  }
@@ -3587,12 +4173,14 @@ function createRuntimeEntryDialogComponent(deps) {
3587
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");
3588
4174
  } catch (error) {
3589
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;
3590
4178
  }
3591
4179
  });
3592
4180
  const saving = isSaving || Boolean(compositeCreate?.isPending || compositeUpdate?.isPending);
3593
4181
  const extraItems = deps.SubformField && view.form?.schema.subforms?.length ? view.form.schema.subforms.map((subform) => ({
3594
4182
  key: subform.key,
3595
- render: () => deps.SubformField ? /* @__PURE__ */ jsx17(
4183
+ render: () => deps.SubformField ? /* @__PURE__ */ jsx20(
3596
4184
  deps.SubformField,
3597
4185
  {
3598
4186
  subform,
@@ -3607,7 +4195,7 @@ function createRuntimeEntryDialogComponent(deps) {
3607
4195
  }
3608
4196
  ) : null
3609
4197
  })) : void 0;
3610
- return /* @__PURE__ */ jsx17(
4198
+ return /* @__PURE__ */ jsx20(
3611
4199
  deps.DialogShell,
3612
4200
  {
3613
4201
  open,
@@ -3615,8 +4203,8 @@ function createRuntimeEntryDialogComponent(deps) {
3615
4203
  title: editing ? "\u041C\u04E9\u0440 \u0437\u0430\u0441\u0430\u0445" : "\u041C\u04E9\u0440 \u043D\u044D\u043C\u044D\u0445",
3616
4204
  description: view.title,
3617
4205
  onClose,
3618
- children: /* @__PURE__ */ jsx17(FormProvider6, { ...form, children: /* @__PURE__ */ jsxs14("form", { onSubmit, noValidate: true, className: deps.formClassName, children: [
3619
- 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(
3620
4208
  deps.FormFields,
3621
4209
  {
3622
4210
  formId: view.form.id,
@@ -3627,7 +4215,7 @@ function createRuntimeEntryDialogComponent(deps) {
3627
4215
  extraItems
3628
4216
  }
3629
4217
  ) : null,
3630
- /* @__PURE__ */ jsx17(deps.Actions, { isSaving: saving, onClose })
4218
+ /* @__PURE__ */ jsx20(deps.Actions, { isSaving: saving, onClose })
3631
4219
  ] }) })
3632
4220
  }
3633
4221
  );
@@ -3714,7 +4302,7 @@ function validateBuilderFrontendSetup(config) {
3714
4302
  // src/index.ts
3715
4303
  var builderUiPackage = {
3716
4304
  name: "@duke333/builder-ui",
3717
- version: "0.2.2"
4305
+ version: "0.2.4"
3718
4306
  };
3719
4307
  export {
3720
4308
  BUILDER_EDITOR_NONE_VALUE,
@@ -3722,6 +4310,9 @@ export {
3722
4310
  BuilderGrid,
3723
4311
  BuilderProvider,
3724
4312
  BuilderView,
4313
+ ReadyFileField,
4314
+ ReadyRichTextField,
4315
+ RichTextContent,
3725
4316
  builderEditorOptionsToText,
3726
4317
  builderEditorSearchFieldsToText,
3727
4318
  builderEditorTextToOptions,
@@ -3764,9 +4355,11 @@ export {
3764
4355
  getBuilderEditorTriggerRoute,
3765
4356
  nextBuilderFormLayoutGroupId,
3766
4357
  parseBuilderFormLayoutDragPayload,
4358
+ richTextToPlainText,
3767
4359
  serializeBuilderFormLayoutDragPayload,
3768
4360
  shouldHandleDynamicViewRowClick,
3769
4361
  swapBuilderFormLayoutItems,
4362
+ toRichTextDocument,
3770
4363
  useBuilderFormLayoutEditor,
3771
4364
  useBuilderRuntime,
3772
4365
  validateBuilderFrontendSetup