@thebes/cadmea 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,16 @@
1
1
  import { createComponent, escape, ssr, ssrAttribute } from "solid-js/web";
2
2
  import { createMutation, createQuery, useQueryClient } from "@tanstack/solid-query";
3
- import { For, Index, Show, Suspense, createEffect, createSignal, lazy, onCleanup } from "solid-js";
3
+ import { For, Index, Show, Suspense, createEffect, createSignal, lazy, onCleanup, onMount } from "solid-js";
4
4
  import { createForm } from "@tanstack/solid-form";
5
- import { validateDocument } from "@thebes/cadmus/cms";
5
+ import { VISUAL_EDIT_MESSAGE, validateDocument } from "@thebes/cadmus/cms";
6
6
  import { Link, useBlocker } from "@tanstack/solid-router";
7
7
  import { createSolidTable, flexRender, getCoreRowModel } from "@tanstack/solid-table";
8
8
  //#region src/CollectionEdit.tsx
9
- var _tmpl$$4 = ["<p class=\"text-sm text-error\" role=\"alert\">", "</p>"], _tmpl$2$3 = "<span class=\"loading loading-spinner loading-sm\"></span>", _tmpl$3$1 = [
9
+ var _tmpl$$5 = ["<p class=\"text-sm text-error\" role=\"alert\">", "</p>"], _tmpl$2$3 = "<span class=\"loading loading-spinner loading-sm\"></span>", _tmpl$3$2 = [
10
10
  "<button type=\"button\" class=\"btn flex-1\"",
11
11
  ">",
12
12
  "</button>"
13
- ], _tmpl$4$1 = [
13
+ ], _tmpl$4$2 = [
14
14
  "<button type=\"button\" class=\"btn btn-primary flex-1\"",
15
15
  ">",
16
16
  "</button>"
@@ -172,6 +172,7 @@ function CollectionEdit(props) {
172
172
  const isDefaultValue = form.useStore((s) => s.isDefaultValue);
173
173
  createEffect(() => props.onDirtyChange?.(!isDefaultValue()));
174
174
  const formValues = form.useStore((s) => s.values);
175
+ createEffect(() => props.onValuesChange?.(editablePayload(formValues())));
175
176
  function editablePayload(value) {
176
177
  return Object.fromEntries(Object.entries(value).filter(([key]) => props.config.fields[key]?.type !== "date"));
177
178
  }
@@ -215,7 +216,7 @@ function CollectionEdit(props) {
215
216
  return props.error;
216
217
  },
217
218
  get children() {
218
- return ssr(_tmpl$$4, escape(props.error));
219
+ return ssr(_tmpl$$5, escape(props.error));
219
220
  }
220
221
  })), escape(createComponent(For, {
221
222
  each: fieldGroups,
@@ -254,7 +255,7 @@ function CollectionEdit(props) {
254
255
  return props.capabilities?.canUpdate !== false;
255
256
  },
256
257
  get children() {
257
- return ssr(_tmpl$4$1, ssrAttribute("disabled", props.saving, true), escape(createComponent(Show, {
258
+ return ssr(_tmpl$4$2, ssrAttribute("disabled", props.saving, true), escape(createComponent(Show, {
258
259
  get when() {
259
260
  return props.saving;
260
261
  },
@@ -270,7 +271,7 @@ function CollectionEdit(props) {
270
271
  },
271
272
  get children() {
272
273
  return [
273
- ssr(_tmpl$3$1, ssrAttribute("disabled", props.draftActions?.saving, true), escape(createComponent(Show, {
274
+ ssr(_tmpl$3$2, ssrAttribute("disabled", props.draftActions?.saving, true), escape(createComponent(Show, {
274
275
  get when() {
275
276
  return props.draftActions?.saving;
276
277
  },
@@ -281,7 +282,7 @@ function CollectionEdit(props) {
281
282
  return ssr(_tmpl$2$3);
282
283
  }
283
284
  }))),
284
- ssr(_tmpl$4$1, ssrAttribute("disabled", !props.draftActions?.canPublish || props.draftActions?.publishing, true), escape(createComponent(Show, {
285
+ ssr(_tmpl$4$2, ssrAttribute("disabled", !props.draftActions?.canPublish || props.draftActions?.publishing, true), escape(createComponent(Show, {
285
286
  get when() {
286
287
  return props.draftActions?.publishing;
287
288
  },
@@ -635,7 +636,7 @@ function formatDateValue(value) {
635
636
  }
636
637
  //#endregion
637
638
  //#region src/tanstack-start/create.tsx
638
- var _tmpl$$3 = [
639
+ var _tmpl$$4 = [
639
640
  "<div class=\"flex flex-col gap-4\"><h1 class=\"text-xl font-semibold\">",
640
641
  "</h1>",
641
642
  "</div>"
@@ -657,7 +658,7 @@ function createCollectionCreatePage(options) {
657
658
  },
658
659
  onError: (e) => setError(e.message)
659
660
  }));
660
- return ssr(_tmpl$$3, escape(options.label ?? `New ${options.collection.slug}`), escape(createComponent(CollectionEdit, {
661
+ return ssr(_tmpl$$4, escape(options.label ?? `New ${options.collection.slug}`), escape(createComponent(CollectionEdit, {
661
662
  get config() {
662
663
  return options.collection;
663
664
  },
@@ -678,13 +679,44 @@ function createCollectionCreatePage(options) {
678
679
  };
679
680
  }
680
681
  //#endregion
682
+ //#region src/VisualEditingPane.tsx
683
+ var _tmpl$$3 = ["<iframe", "></iframe>"];
684
+ function originOf(url) {
685
+ try {
686
+ return new URL(url).origin;
687
+ } catch {
688
+ return;
689
+ }
690
+ }
691
+ function VisualEditingPane(props) {
692
+ onMount(() => {
693
+ const expected = props.allowedOrigin ?? originOf(props.src);
694
+ const handler = (event) => {
695
+ if (expected && event.origin !== expected) return;
696
+ const data = event.data;
697
+ if (data?.type === VISUAL_EDIT_MESSAGE && data.ref) props.onEdit?.(data.ref);
698
+ };
699
+ window.addEventListener("message", handler);
700
+ onCleanup(() => window.removeEventListener("message", handler));
701
+ });
702
+ createEffect(() => {
703
+ props.previewValues;
704
+ props.previewTarget;
705
+ });
706
+ return ssr(_tmpl$$3, ssrAttribute("src", escape(props.src, true), false) + ssrAttribute("title", escape(props.title ?? "Preview", true), false) + ssrAttribute("class", escape(props.class ?? "h-full w-full border-0", true), false));
707
+ }
708
+ //#endregion
681
709
  //#region src/tanstack-start/edit.tsx
682
710
  var _tmpl$$2 = ["<button type=\"button\" class=\"btn btn-error btn-outline btn-sm self-start\">", "</button>"], _tmpl$2$2 = [
683
711
  "<div class=\"flex flex-col gap-4\"><h1 class=\"text-xl font-semibold\">",
684
712
  "</h1>",
685
713
  "",
686
714
  "</div>"
687
- ];
715
+ ], _tmpl$3$1 = [
716
+ "<div class=\"grid grid-cols-1 gap-4 lg:grid-cols-2\">",
717
+ "",
718
+ "</div>"
719
+ ], _tmpl$4$1 = ["<div class=\"lg:sticky lg:top-4 lg:h-[calc(100vh-2rem)]\">", "</div>"];
688
720
  /**
689
721
  * Builds an edit-page component for a collection — fetch, update, and
690
722
  * delete, all wired together, plus a router-level unsaved-changes guard
@@ -698,6 +730,7 @@ function createCollectionEditPage(options) {
698
730
  const [error, setError] = createSignal();
699
731
  const [dirty, setDirty] = createSignal(false);
700
732
  const [latestDraftId, setLatestDraftId] = createSignal();
733
+ const [previewValues, setPreviewValues] = createSignal({});
701
734
  useBlocker({
702
735
  shouldBlockFn: () => dirty(),
703
736
  enableBeforeUnload: () => dirty()
@@ -754,7 +787,7 @@ function createCollectionEditPage(options) {
754
787
  },
755
788
  onError: (e) => setError(e.message)
756
789
  }));
757
- return ssr(_tmpl$2$2, escape(options.label ?? `Edit ${options.collection.slug}`), escape(createComponent(Show, {
790
+ const EditorPane = () => ssr(_tmpl$2$2, escape(options.label ?? `Edit ${options.collection.slug}`), escape(createComponent(Show, {
758
791
  get when() {
759
792
  return row.data;
760
793
  },
@@ -783,6 +816,7 @@ function createCollectionEditPage(options) {
783
816
  return options.fieldWidgets;
784
817
  },
785
818
  onDirtyChange: setDirty,
819
+ onValuesChange: setPreviewValues,
786
820
  get capabilities() {
787
821
  return options.capabilities?.();
788
822
  },
@@ -798,7 +832,8 @@ function createCollectionEditPage(options) {
798
832
  canPreview: latestDraftId() !== void 0,
799
833
  saveDraftLabel: options.draftActions.saveDraftLabel,
800
834
  publishLabel: options.draftActions.publishLabel,
801
- previewLabel: options.draftActions.previewLabel
835
+ previewLabel: options.draftActions.previewLabel,
836
+ autosave: options.draftActions.autosave
802
837
  };
803
838
  }
804
839
  });
@@ -811,6 +846,40 @@ function createCollectionEditPage(options) {
811
846
  return ssr(_tmpl$$2, escape(options.deleteLabel ?? `Delete ${options.collection.slug}`));
812
847
  }
813
848
  })));
849
+ return createComponent(Show, {
850
+ get when() {
851
+ return options.preview;
852
+ },
853
+ get fallback() {
854
+ return createComponent(EditorPane, {});
855
+ },
856
+ get children() {
857
+ return ssr(_tmpl$3$1, escape(createComponent(EditorPane, {})), escape(createComponent(Show, {
858
+ get when() {
859
+ return options.preview?.url();
860
+ },
861
+ children: (url) => ssr(_tmpl$4$1, escape(createComponent(VisualEditingPane, {
862
+ get src() {
863
+ return url();
864
+ },
865
+ get allowedOrigin() {
866
+ return options.preview?.allowedOrigin?.();
867
+ },
868
+ get previewValues() {
869
+ return previewValues();
870
+ },
871
+ get previewTarget() {
872
+ return {
873
+ collection: options.collection.slug,
874
+ id: Number(row.data?.id)
875
+ };
876
+ },
877
+ "class": "border-base-300 rounded-box h-full w-full border",
878
+ title: "Live preview"
879
+ })))
880
+ })));
881
+ }
882
+ });
814
883
  };
815
884
  }
816
885
  //#endregion