@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.
- package/dist/index/index.d.ts +17 -0
- package/dist/index/index.js +20 -1
- package/dist/index/index.js.map +1 -1
- package/dist/index/server.js +5 -0
- package/dist/index/server.js.map +1 -1
- package/dist/tanstack-start/index.d.ts +22 -0
- package/dist/tanstack-start/index.js +113 -13
- package/dist/tanstack-start/index.js.map +1 -1
- package/dist/tanstack-start/server.js +82 -13
- package/dist/tanstack-start/server.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { className, createComponent, delegateEvents, effect, insert, memo, setAttribute, template } from "solid-js/web";
|
|
1
|
+
import { className, createComponent, delegateEvents, effect, insert, memo, setAttribute, template, use } 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 { PREVIEW_VALUES_MESSAGE, 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$$
|
|
9
|
+
var _tmpl$$5 = /*#__PURE__*/ template(`<p class="text-sm text-error"role=alert>`), _tmpl$2$3 = /*#__PURE__*/ template(`<span class="loading loading-spinner loading-sm">`), _tmpl$3$2 = /*#__PURE__*/ template(`<button type=button class="btn flex-1">`), _tmpl$4$2 = /*#__PURE__*/ template(`<button type=button class="btn btn-primary flex-1">`), _tmpl$5$1 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline flex-1">`), _tmpl$6$1 = /*#__PURE__*/ template(`<span class="text-base-content/60 self-center px-1 text-xs"aria-live=polite>`), _tmpl$7$1 = /*#__PURE__*/ template(`<form class="flex flex-col gap-4"><div class="bg-base-100 sticky bottom-0 flex gap-2 border-t py-3">`), _tmpl$8$1 = /*#__PURE__*/ template(`<fieldset class="border-base-300 rounded-box border p-4"><legend class="px-2 text-sm font-semibold">`), _tmpl$9$1 = /*#__PURE__*/ template(`<div class="grid grid-cols-1 gap-4 md:grid-cols-2">`), _tmpl$0$1 = /*#__PURE__*/ template(`<span class=text-error> *`), _tmpl$1$1 = /*#__PURE__*/ template(`<p class="text-base-content/60 mb-1 text-xs">`), _tmpl$10$1 = /*#__PURE__*/ template(`<p class="text-error mt-1 text-sm"role=alert>`), _tmpl$11$1 = /*#__PURE__*/ template(`<div><label class=label>`), _tmpl$12$1 = /*#__PURE__*/ template(`<input class=input type=text>`), _tmpl$13$1 = /*#__PURE__*/ template(`<select class=select>`), _tmpl$14 = /*#__PURE__*/ template(`<option>`), _tmpl$15 = /*#__PURE__*/ template(`<input class=input type=number>`), _tmpl$16 = /*#__PURE__*/ template(`<input class=input type=text readonly>`), _tmpl$17 = /*#__PURE__*/ template(`<input class=checkbox type=checkbox>`), _tmpl$18 = /*#__PURE__*/ template(`<p class="text-sm opacity-70 break-all">`), _tmpl$19 = /*#__PURE__*/ template(`<p class="text-sm text-error">`), _tmpl$20 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2"><input class=file-input type=file>`), _tmpl$21 = /*#__PURE__*/ template(`<div class="mb-1 flex flex-wrap gap-1">`), _tmpl$22 = /*#__PURE__*/ template(`<button type=button aria-label=Clear class="absolute top-2 right-2 cursor-pointer opacity-60">×`), _tmpl$23 = /*#__PURE__*/ template(`<div role=listbox class="bg-base-100 border-base-300 rounded-box absolute z-10 mt-1 flex max-h-56 w-full flex-col overflow-auto border p-1 shadow">`), _tmpl$24 = /*#__PURE__*/ template(`<div class=relative><input type=text role=combobox autocomplete=off class=input>`), _tmpl$25 = /*#__PURE__*/ template(`<span class="badge badge-primary gap-1"><button type=button class=cursor-pointer>×`), _tmpl$26 = /*#__PURE__*/ template(`<button type=button role=option class="rounded px-3 py-2 text-left">`), _tmpl$27 = /*#__PURE__*/ template(`<div role=menu class="bg-base-100 border-base-300 rounded-box absolute z-10 mt-1 flex flex-col border p-1 shadow">`), _tmpl$28 = /*#__PURE__*/ template(`<div class="relative self-start"><button type=button class="btn btn-outline btn-sm"aria-haspopup=menu>Add block`), _tmpl$29 = /*#__PURE__*/ template(`<div class="form-control md:col-span-2"><div class="label font-medium"></div><div class="flex flex-col gap-3">`), _tmpl$30 = /*#__PURE__*/ template(`<span class="text-base-content/60 truncate text-sm">`), _tmpl$31 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2">`), _tmpl$32 = /*#__PURE__*/ template(`<div class="card bg-base-200 flex flex-col gap-2 p-3"><div class="flex items-center gap-2"><button type=button class="btn btn-ghost btn-sm gap-2"><span aria-hidden=true></span><span class=font-semibold></span></button><div class="ml-auto flex gap-1"><button type=button class="btn btn-ghost btn-xs"aria-label="Move up">↑</button><button type=button class="btn btn-ghost btn-xs"aria-label="Move down">↓</button><button type=button class="btn btn-ghost btn-xs"aria-label=Duplicate>⧉</button><button type=button class="btn btn-ghost btn-xs text-error"aria-label=Remove>Remove`), _tmpl$33 = /*#__PURE__*/ template(`<button type=button class="btn btn-outline btn-sm self-start">Add `), _tmpl$34 = /*#__PURE__*/ template(`<i aria-hidden=true>`), _tmpl$35 = /*#__PURE__*/ template(`<button type=button role=menuitem class="flex items-center gap-2 rounded px-3 py-2 text-left">`);
|
|
10
10
|
const RichTextEditor = lazy(() => import("../RichTextEditor-ComcBFfl.js").then((mod) => ({ default: mod.RichTextEditor })));
|
|
11
11
|
function editableFields(config) {
|
|
12
12
|
return Object.entries(config.fields).filter(([key]) => key !== "id");
|
|
@@ -54,6 +54,7 @@ function CollectionEdit(props) {
|
|
|
54
54
|
const isDefaultValue = form.useStore((s) => s.isDefaultValue);
|
|
55
55
|
createEffect(() => props.onDirtyChange?.(!isDefaultValue()));
|
|
56
56
|
const formValues = form.useStore((s) => s.values);
|
|
57
|
+
createEffect(() => props.onValuesChange?.(editablePayload(formValues())));
|
|
57
58
|
function editablePayload(value) {
|
|
58
59
|
return Object.fromEntries(Object.entries(value).filter(([key]) => props.config.fields[key]?.type !== "date"));
|
|
59
60
|
}
|
|
@@ -103,7 +104,7 @@ function CollectionEdit(props) {
|
|
|
103
104
|
return props.error;
|
|
104
105
|
},
|
|
105
106
|
get children() {
|
|
106
|
-
var _el$2 = _tmpl$$
|
|
107
|
+
var _el$2 = _tmpl$$5();
|
|
107
108
|
insert(_el$2, () => props.error);
|
|
108
109
|
return _el$2;
|
|
109
110
|
}
|
|
@@ -149,7 +150,7 @@ function CollectionEdit(props) {
|
|
|
149
150
|
return props.capabilities?.canUpdate !== false;
|
|
150
151
|
},
|
|
151
152
|
get children() {
|
|
152
|
-
var _el$11 = _tmpl$4$
|
|
153
|
+
var _el$11 = _tmpl$4$2();
|
|
153
154
|
_el$11.$$click = () => void form.handleSubmit();
|
|
154
155
|
insert(_el$11, createComponent(Show, {
|
|
155
156
|
get when() {
|
|
@@ -170,7 +171,7 @@ function CollectionEdit(props) {
|
|
|
170
171
|
get children() {
|
|
171
172
|
return [
|
|
172
173
|
(() => {
|
|
173
|
-
var _el$4 = _tmpl$3$
|
|
174
|
+
var _el$4 = _tmpl$3$2();
|
|
174
175
|
_el$4.$$click = () => void props.draftActions?.onSaveDraft(editablePayload(formValues()));
|
|
175
176
|
insert(_el$4, createComponent(Show, {
|
|
176
177
|
get when() {
|
|
@@ -187,7 +188,7 @@ function CollectionEdit(props) {
|
|
|
187
188
|
return _el$4;
|
|
188
189
|
})(),
|
|
189
190
|
(() => {
|
|
190
|
-
var _el$6 = _tmpl$4$
|
|
191
|
+
var _el$6 = _tmpl$4$2();
|
|
191
192
|
_el$6.$$click = () => void props.draftActions?.onPublish?.();
|
|
192
193
|
insert(_el$6, createComponent(Show, {
|
|
193
194
|
get when() {
|
|
@@ -849,7 +850,7 @@ delegateEvents([
|
|
|
849
850
|
]);
|
|
850
851
|
//#endregion
|
|
851
852
|
//#region src/tanstack-start/create.tsx
|
|
852
|
-
var _tmpl$$
|
|
853
|
+
var _tmpl$$4 = /*#__PURE__*/ template(`<div class="flex flex-col gap-4"><h1 class="text-xl font-semibold">`);
|
|
853
854
|
/**
|
|
854
855
|
* Builds a create-page component for a collection. See
|
|
855
856
|
* `createCollectionListPage`'s doc comment for the same rationale on
|
|
@@ -868,7 +869,7 @@ function createCollectionCreatePage(options) {
|
|
|
868
869
|
onError: (e) => setError(e.message)
|
|
869
870
|
}));
|
|
870
871
|
return (() => {
|
|
871
|
-
var _el$ = _tmpl$$
|
|
872
|
+
var _el$ = _tmpl$$4(), _el$2 = _el$.firstChild;
|
|
872
873
|
insert(_el$2, () => options.label ?? `New ${options.collection.slug}`);
|
|
873
874
|
insert(_el$, createComponent(CollectionEdit, {
|
|
874
875
|
get config() {
|
|
@@ -893,8 +894,63 @@ function createCollectionCreatePage(options) {
|
|
|
893
894
|
};
|
|
894
895
|
}
|
|
895
896
|
//#endregion
|
|
897
|
+
//#region src/VisualEditingPane.tsx
|
|
898
|
+
var _tmpl$$3 = /*#__PURE__*/ template(`<iframe>`);
|
|
899
|
+
function originOf(url) {
|
|
900
|
+
try {
|
|
901
|
+
return new URL(url).origin;
|
|
902
|
+
} catch {
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
function VisualEditingPane(props) {
|
|
907
|
+
let iframe;
|
|
908
|
+
const targetOrigin = () => props.allowedOrigin ?? originOf(props.src) ?? "*";
|
|
909
|
+
onMount(() => {
|
|
910
|
+
const expected = props.allowedOrigin ?? originOf(props.src);
|
|
911
|
+
const handler = (event) => {
|
|
912
|
+
if (expected && event.origin !== expected) return;
|
|
913
|
+
const data = event.data;
|
|
914
|
+
if (data?.type === VISUAL_EDIT_MESSAGE && data.ref) props.onEdit?.(data.ref);
|
|
915
|
+
};
|
|
916
|
+
window.addEventListener("message", handler);
|
|
917
|
+
onCleanup(() => window.removeEventListener("message", handler));
|
|
918
|
+
});
|
|
919
|
+
createEffect(() => {
|
|
920
|
+
const values = props.previewValues;
|
|
921
|
+
const target = props.previewTarget;
|
|
922
|
+
const win = iframe?.contentWindow;
|
|
923
|
+
if (!values || !target || !win) return;
|
|
924
|
+
const message = {
|
|
925
|
+
type: PREVIEW_VALUES_MESSAGE,
|
|
926
|
+
collection: target.collection,
|
|
927
|
+
id: target.id,
|
|
928
|
+
values
|
|
929
|
+
};
|
|
930
|
+
win.postMessage(message, targetOrigin());
|
|
931
|
+
});
|
|
932
|
+
return (() => {
|
|
933
|
+
var _el$ = _tmpl$$3();
|
|
934
|
+
use((el) => {
|
|
935
|
+
iframe = el;
|
|
936
|
+
}, _el$);
|
|
937
|
+
effect((_p$) => {
|
|
938
|
+
var _v$ = props.src, _v$2 = props.title ?? "Preview", _v$3 = props.class ?? "h-full w-full border-0";
|
|
939
|
+
_v$ !== _p$.e && setAttribute(_el$, "src", _p$.e = _v$);
|
|
940
|
+
_v$2 !== _p$.t && setAttribute(_el$, "title", _p$.t = _v$2);
|
|
941
|
+
_v$3 !== _p$.a && className(_el$, _p$.a = _v$3);
|
|
942
|
+
return _p$;
|
|
943
|
+
}, {
|
|
944
|
+
e: void 0,
|
|
945
|
+
t: void 0,
|
|
946
|
+
a: void 0
|
|
947
|
+
});
|
|
948
|
+
return _el$;
|
|
949
|
+
})();
|
|
950
|
+
}
|
|
951
|
+
//#endregion
|
|
896
952
|
//#region src/tanstack-start/edit.tsx
|
|
897
|
-
var _tmpl$$2 = /*#__PURE__*/ template(`<button type=button class="btn btn-error btn-outline btn-sm self-start">`), _tmpl$2$2 = /*#__PURE__*/ template(`<div class="flex flex-col gap-4"><h1 class="text-xl font-semibold">`);
|
|
953
|
+
var _tmpl$$2 = /*#__PURE__*/ template(`<button type=button class="btn btn-error btn-outline btn-sm self-start">`), _tmpl$2$2 = /*#__PURE__*/ template(`<div class="flex flex-col gap-4"><h1 class="text-xl font-semibold">`), _tmpl$3$1 = /*#__PURE__*/ template(`<div class="grid grid-cols-1 gap-4 lg:grid-cols-2">`), _tmpl$4$1 = /*#__PURE__*/ template(`<div class="lg:sticky lg:top-4 lg:h-[calc(100vh-2rem)]">`);
|
|
898
954
|
/**
|
|
899
955
|
* Builds an edit-page component for a collection — fetch, update, and
|
|
900
956
|
* delete, all wired together, plus a router-level unsaved-changes guard
|
|
@@ -908,6 +964,7 @@ function createCollectionEditPage(options) {
|
|
|
908
964
|
const [error, setError] = createSignal();
|
|
909
965
|
const [dirty, setDirty] = createSignal(false);
|
|
910
966
|
const [latestDraftId, setLatestDraftId] = createSignal();
|
|
967
|
+
const [previewValues, setPreviewValues] = createSignal({});
|
|
911
968
|
useBlocker({
|
|
912
969
|
shouldBlockFn: () => dirty(),
|
|
913
970
|
enableBeforeUnload: () => dirty()
|
|
@@ -964,7 +1021,7 @@ function createCollectionEditPage(options) {
|
|
|
964
1021
|
},
|
|
965
1022
|
onError: (e) => setError(e.message)
|
|
966
1023
|
}));
|
|
967
|
-
|
|
1024
|
+
const EditorPane = () => (() => {
|
|
968
1025
|
var _el$ = _tmpl$2$2(), _el$2 = _el$.firstChild;
|
|
969
1026
|
insert(_el$2, () => options.label ?? `Edit ${options.collection.slug}`);
|
|
970
1027
|
insert(_el$, createComponent(Show, {
|
|
@@ -996,6 +1053,7 @@ function createCollectionEditPage(options) {
|
|
|
996
1053
|
return options.fieldWidgets;
|
|
997
1054
|
},
|
|
998
1055
|
onDirtyChange: setDirty,
|
|
1056
|
+
onValuesChange: setPreviewValues,
|
|
999
1057
|
get capabilities() {
|
|
1000
1058
|
return options.capabilities?.();
|
|
1001
1059
|
},
|
|
@@ -1011,7 +1069,8 @@ function createCollectionEditPage(options) {
|
|
|
1011
1069
|
canPreview: latestDraftId() !== void 0,
|
|
1012
1070
|
saveDraftLabel: options.draftActions.saveDraftLabel,
|
|
1013
1071
|
publishLabel: options.draftActions.publishLabel,
|
|
1014
|
-
previewLabel: options.draftActions.previewLabel
|
|
1072
|
+
previewLabel: options.draftActions.previewLabel,
|
|
1073
|
+
autosave: options.draftActions.autosave
|
|
1015
1074
|
};
|
|
1016
1075
|
}
|
|
1017
1076
|
});
|
|
@@ -1030,6 +1089,47 @@ function createCollectionEditPage(options) {
|
|
|
1030
1089
|
}), null);
|
|
1031
1090
|
return _el$;
|
|
1032
1091
|
})();
|
|
1092
|
+
return createComponent(Show, {
|
|
1093
|
+
get when() {
|
|
1094
|
+
return options.preview;
|
|
1095
|
+
},
|
|
1096
|
+
get fallback() {
|
|
1097
|
+
return createComponent(EditorPane, {});
|
|
1098
|
+
},
|
|
1099
|
+
get children() {
|
|
1100
|
+
var _el$4 = _tmpl$3$1();
|
|
1101
|
+
insert(_el$4, createComponent(EditorPane, {}), null);
|
|
1102
|
+
insert(_el$4, createComponent(Show, {
|
|
1103
|
+
get when() {
|
|
1104
|
+
return options.preview?.url();
|
|
1105
|
+
},
|
|
1106
|
+
children: (url) => (() => {
|
|
1107
|
+
var _el$5 = _tmpl$4$1();
|
|
1108
|
+
insert(_el$5, createComponent(VisualEditingPane, {
|
|
1109
|
+
get src() {
|
|
1110
|
+
return url();
|
|
1111
|
+
},
|
|
1112
|
+
get allowedOrigin() {
|
|
1113
|
+
return options.preview?.allowedOrigin?.();
|
|
1114
|
+
},
|
|
1115
|
+
get previewValues() {
|
|
1116
|
+
return previewValues();
|
|
1117
|
+
},
|
|
1118
|
+
get previewTarget() {
|
|
1119
|
+
return {
|
|
1120
|
+
collection: options.collection.slug,
|
|
1121
|
+
id: Number(row.data?.id)
|
|
1122
|
+
};
|
|
1123
|
+
},
|
|
1124
|
+
"class": "border-base-300 rounded-box h-full w-full border",
|
|
1125
|
+
title: "Live preview"
|
|
1126
|
+
}));
|
|
1127
|
+
return _el$5;
|
|
1128
|
+
})()
|
|
1129
|
+
}), null);
|
|
1130
|
+
return _el$4;
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1033
1133
|
};
|
|
1034
1134
|
}
|
|
1035
1135
|
delegateEvents(["click"]);
|