@paulpaulstudio/strapi-render 0.4.0 → 0.5.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.cjs +60 -166
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -26
- package/dist/index.d.ts +48 -26
- package/dist/index.js +60 -168
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,29 +4,25 @@
|
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
|
+
var EDIT_SESSION_KEY = "__pp_edit_session";
|
|
7
8
|
var noop = () => {
|
|
8
9
|
};
|
|
9
10
|
var EditModeContext = react.createContext({
|
|
10
11
|
enabled: false,
|
|
11
12
|
token: null,
|
|
12
|
-
|
|
13
|
-
isDirty: false,
|
|
14
|
-
isCommitting: false,
|
|
15
|
-
lastCommitError: null,
|
|
16
|
-
setChange: noop,
|
|
17
|
-
clearChange: noop,
|
|
18
|
-
commit: noop,
|
|
13
|
+
publishChange: noop,
|
|
19
14
|
openMediaPicker: noop,
|
|
20
15
|
onMediaPicked: () => noop
|
|
21
16
|
});
|
|
17
|
+
var ContentScopeContext = react.createContext(null);
|
|
22
18
|
function useStrapiEditMode() {
|
|
23
19
|
return react.useContext(EditModeContext);
|
|
24
20
|
}
|
|
21
|
+
function useContentScope() {
|
|
22
|
+
return react.useContext(ContentScopeContext);
|
|
23
|
+
}
|
|
25
24
|
function StrapiEditModeProvider({ children, enabled: enabledOverride }) {
|
|
26
25
|
const [urlState, setUrlState] = react.useState({ enabled: false, token: null });
|
|
27
|
-
const [changes, setChanges] = react.useState(/* @__PURE__ */ new Map());
|
|
28
|
-
const [isCommitting, setIsCommitting] = react.useState(false);
|
|
29
|
-
const [lastCommitError, setLastCommitError] = react.useState(null);
|
|
30
26
|
const mediaPickListeners = react.useRef(/* @__PURE__ */ new Map());
|
|
31
27
|
react.useEffect(() => {
|
|
32
28
|
if (typeof window === "undefined") return;
|
|
@@ -36,9 +32,15 @@ function StrapiEditModeProvider({ children, enabled: enabledOverride }) {
|
|
|
36
32
|
}
|
|
37
33
|
try {
|
|
38
34
|
const params = new URLSearchParams(window.location.search);
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
35
|
+
const urlEdit = params.get("__pp_edit") === "1";
|
|
36
|
+
const sessionFlag = window.sessionStorage.getItem(EDIT_SESSION_KEY) === "1";
|
|
37
|
+
const enabled = urlEdit || sessionFlag;
|
|
38
|
+
if (urlEdit) {
|
|
39
|
+
window.sessionStorage.setItem(EDIT_SESSION_KEY, "1");
|
|
40
|
+
}
|
|
41
|
+
const token = params.get("__pp_token") ?? window.sessionStorage.getItem("__pp_edit_token");
|
|
42
|
+
if (token) window.sessionStorage.setItem("__pp_edit_token", token);
|
|
43
|
+
setUrlState({ enabled, token });
|
|
42
44
|
} catch {
|
|
43
45
|
}
|
|
44
46
|
}, [enabledOverride]);
|
|
@@ -65,14 +67,9 @@ function StrapiEditModeProvider({ children, enabled: enabledOverride }) {
|
|
|
65
67
|
window.location.reload();
|
|
66
68
|
return;
|
|
67
69
|
}
|
|
68
|
-
if (d.type === "pp:edit:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
setChanges(/* @__PURE__ */ new Map());
|
|
72
|
-
setLastCommitError(null);
|
|
73
|
-
} else {
|
|
74
|
-
setLastCommitError(d.error || "Speichern fehlgeschlagen");
|
|
75
|
-
}
|
|
70
|
+
if (d.type === "pp:edit:exit") {
|
|
71
|
+
window.sessionStorage.removeItem(EDIT_SESSION_KEY);
|
|
72
|
+
window.location.reload();
|
|
76
73
|
return;
|
|
77
74
|
}
|
|
78
75
|
if (d.type === "pp:edit:media-picked") {
|
|
@@ -87,58 +84,12 @@ function StrapiEditModeProvider({ children, enabled: enabledOverride }) {
|
|
|
87
84
|
window.addEventListener("message", onMsg);
|
|
88
85
|
return () => window.removeEventListener("message", onMsg);
|
|
89
86
|
}, [urlState.enabled]);
|
|
90
|
-
const
|
|
91
|
-
setChanges((prev) => {
|
|
92
|
-
const next = new Map(prev);
|
|
93
|
-
next.set(path, { path, fieldType, value: value2 });
|
|
94
|
-
return next;
|
|
95
|
-
});
|
|
96
|
-
setLastCommitError(null);
|
|
97
|
-
if (typeof window !== "undefined" && window.parent !== window) {
|
|
98
|
-
try {
|
|
99
|
-
window.parent.postMessage({ type: "pp:edit:change", path, fieldType, value: value2 }, "*");
|
|
100
|
-
} catch {
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}, []);
|
|
104
|
-
const clearChange = react.useCallback((path) => {
|
|
105
|
-
setChanges((prev) => {
|
|
106
|
-
const next = new Map(prev);
|
|
107
|
-
next.delete(path);
|
|
108
|
-
return next;
|
|
109
|
-
});
|
|
87
|
+
const publishChange = react.useCallback((_path, _fieldType, _value) => {
|
|
110
88
|
}, []);
|
|
111
|
-
const commit = react.useCallback(() => {
|
|
112
|
-
if (changes.size === 0) return;
|
|
113
|
-
if (typeof window === "undefined" || window.parent === window) return;
|
|
114
|
-
setIsCommitting(true);
|
|
115
|
-
setLastCommitError(null);
|
|
116
|
-
try {
|
|
117
|
-
window.parent.postMessage(
|
|
118
|
-
{
|
|
119
|
-
type: "pp:edit:commit-request",
|
|
120
|
-
changes: Array.from(changes.values())
|
|
121
|
-
},
|
|
122
|
-
"*"
|
|
123
|
-
);
|
|
124
|
-
} catch (err) {
|
|
125
|
-
setIsCommitting(false);
|
|
126
|
-
setLastCommitError(err instanceof Error ? err.message : String(err));
|
|
127
|
-
}
|
|
128
|
-
}, [changes]);
|
|
129
89
|
const openMediaPicker = react.useCallback((path, multiple, allowedTypes, currentValue) => {
|
|
130
90
|
if (typeof window === "undefined" || window.parent === window) return;
|
|
131
91
|
try {
|
|
132
|
-
window.parent.postMessage(
|
|
133
|
-
{
|
|
134
|
-
type: "pp:edit:open-media-picker",
|
|
135
|
-
path,
|
|
136
|
-
multiple,
|
|
137
|
-
allowedTypes,
|
|
138
|
-
currentValue
|
|
139
|
-
},
|
|
140
|
-
"*"
|
|
141
|
-
);
|
|
92
|
+
window.parent.postMessage({ type: "pp:edit:open-media-picker", path, multiple, allowedTypes, currentValue }, "*");
|
|
142
93
|
} catch {
|
|
143
94
|
}
|
|
144
95
|
}, []);
|
|
@@ -151,98 +102,34 @@ function StrapiEditModeProvider({ children, enabled: enabledOverride }) {
|
|
|
151
102
|
const value = react.useMemo(() => ({
|
|
152
103
|
enabled: urlState.enabled,
|
|
153
104
|
token: urlState.token,
|
|
154
|
-
|
|
155
|
-
isDirty: changes.size > 0,
|
|
156
|
-
isCommitting,
|
|
157
|
-
lastCommitError,
|
|
158
|
-
setChange,
|
|
159
|
-
clearChange,
|
|
160
|
-
commit,
|
|
105
|
+
publishChange,
|
|
161
106
|
openMediaPicker,
|
|
162
107
|
onMediaPicked
|
|
163
|
-
}), [urlState,
|
|
164
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
165
|
-
children,
|
|
166
|
-
urlState.enabled && /* @__PURE__ */ jsxRuntime.jsx(SaveBar, {})
|
|
167
|
-
] });
|
|
108
|
+
}), [urlState, publishChange, openMediaPicker, onMediaPicked]);
|
|
109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EditModeContext.Provider, { value, children });
|
|
168
110
|
}
|
|
169
|
-
function
|
|
170
|
-
const {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}, children: lastCommitError }),
|
|
192
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
193
|
-
"button",
|
|
194
|
-
{
|
|
195
|
-
type: "button",
|
|
196
|
-
onClick: commit,
|
|
197
|
-
disabled: isCommitting || !isDirty,
|
|
198
|
-
style: {
|
|
199
|
-
background: isCommitting ? "#666" : "#000",
|
|
200
|
-
color: "#EBC6DF",
|
|
201
|
-
border: "2px solid #000",
|
|
202
|
-
padding: "14px 22px",
|
|
203
|
-
fontSize: 13,
|
|
204
|
-
fontWeight: 700,
|
|
205
|
-
textTransform: "uppercase",
|
|
206
|
-
letterSpacing: "0.2em",
|
|
207
|
-
cursor: isCommitting ? "wait" : "pointer",
|
|
208
|
-
display: "flex",
|
|
209
|
-
alignItems: "center",
|
|
210
|
-
gap: 10,
|
|
211
|
-
boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
|
|
212
|
-
transition: "background 0.15s ease"
|
|
213
|
-
},
|
|
214
|
-
onMouseEnter: (e) => {
|
|
215
|
-
if (!isCommitting && isDirty) {
|
|
216
|
-
e.currentTarget.style.background = "#FA501E";
|
|
217
|
-
e.currentTarget.style.color = "#000";
|
|
218
|
-
}
|
|
219
|
-
},
|
|
220
|
-
onMouseLeave: (e) => {
|
|
221
|
-
if (!isCommitting && isDirty) {
|
|
222
|
-
e.currentTarget.style.background = "#000";
|
|
223
|
-
e.currentTarget.style.color = "#EBC6DF";
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
children: isCommitting ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Speichere\u2026" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
227
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: {
|
|
228
|
-
background: "#FA501E",
|
|
229
|
-
color: "#000",
|
|
230
|
-
width: 22,
|
|
231
|
-
height: 22,
|
|
232
|
-
borderRadius: "50%",
|
|
233
|
-
display: "inline-flex",
|
|
234
|
-
alignItems: "center",
|
|
235
|
-
justifyContent: "center",
|
|
236
|
-
fontSize: 11,
|
|
237
|
-
fontWeight: 700
|
|
238
|
-
}, children: changes.size }),
|
|
239
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Speichern" })
|
|
240
|
-
] })
|
|
241
|
-
}
|
|
242
|
-
)
|
|
243
|
-
]
|
|
244
|
-
}
|
|
245
|
-
);
|
|
111
|
+
function StrapiContent({ uid, kind, documentId, children }) {
|
|
112
|
+
const scope = react.useMemo(() => ({ uid, kind, documentId }), [uid, kind, documentId]);
|
|
113
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ContentScopeContext.Provider, { value: scope, children });
|
|
114
|
+
}
|
|
115
|
+
function postEditChange(scope, path, fieldType, value) {
|
|
116
|
+
if (typeof window === "undefined" || window.parent === window) return;
|
|
117
|
+
if (!scope) {
|
|
118
|
+
console.warn("[strapi-render] Feld ohne <StrapiContent>-Scope \u2014 Save wird nicht funktionieren. Wickle deine Seite mit <StrapiContent uid='...' kind='...'> ein.");
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
window.parent.postMessage({
|
|
123
|
+
type: "pp:edit:change",
|
|
124
|
+
uid: scope.uid,
|
|
125
|
+
kind: scope.kind,
|
|
126
|
+
documentId: scope.documentId,
|
|
127
|
+
path,
|
|
128
|
+
fieldType,
|
|
129
|
+
value
|
|
130
|
+
}, "*");
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
246
133
|
}
|
|
247
134
|
var EDITABLE_TYPES = /* @__PURE__ */ new Set([
|
|
248
135
|
"text",
|
|
@@ -254,6 +141,7 @@ var EDITABLE_TYPES = /* @__PURE__ */ new Set([
|
|
|
254
141
|
var HOVER_OUTLINE_COLOR = "#FA501E";
|
|
255
142
|
function StrapiField({ path, type, value, children, className }) {
|
|
256
143
|
const ctx = useStrapiEditMode();
|
|
144
|
+
const scope = useContentScope();
|
|
257
145
|
const ref = react.useRef(null);
|
|
258
146
|
const initialText = react.useRef(void 0);
|
|
259
147
|
react.useEffect(() => {
|
|
@@ -309,7 +197,7 @@ function StrapiField({ path, type, value, children, className }) {
|
|
|
309
197
|
const original = typeof value === "string" ? value : initialText.current ?? "";
|
|
310
198
|
if (newText !== original) {
|
|
311
199
|
const newValue = type === "number" ? newText === "" ? null : Number(newText) : newText;
|
|
312
|
-
|
|
200
|
+
postEditChange(scope, path, type, newValue);
|
|
313
201
|
}
|
|
314
202
|
};
|
|
315
203
|
props.onKeyDown = (e) => {
|
|
@@ -347,8 +235,9 @@ function resolveUrl(value, baseUrl) {
|
|
|
347
235
|
return value.url;
|
|
348
236
|
}
|
|
349
237
|
var HOVER_OUTLINE_COLOR2 = "#FA501E";
|
|
350
|
-
function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "lazy", fallback, allowedTypes, multiple = false }) {
|
|
238
|
+
function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "lazy", fallback, allowedTypes, multiple = false, width, height, draggable }) {
|
|
351
239
|
const ctx = useStrapiEditMode();
|
|
240
|
+
const scope = useContentScope();
|
|
352
241
|
const containerRef = react.useRef(null);
|
|
353
242
|
const imgRef = react.useRef(null);
|
|
354
243
|
const handleClick = (e) => {
|
|
@@ -356,7 +245,7 @@ function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "l
|
|
|
356
245
|
e.preventDefault();
|
|
357
246
|
e.stopPropagation();
|
|
358
247
|
const unsubscribe = ctx.onMediaPicked(path, (picked) => {
|
|
359
|
-
|
|
248
|
+
postEditChange(scope, path, "media", picked);
|
|
360
249
|
unsubscribe();
|
|
361
250
|
if (imgRef.current && picked && typeof picked === "object" && !Array.isArray(picked) && "url" in picked) {
|
|
362
251
|
imgRef.current.src = resolveUrl(picked, baseUrl);
|
|
@@ -406,11 +295,12 @@ function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "l
|
|
|
406
295
|
ref: imgRef,
|
|
407
296
|
src: resolveUrl(value, baseUrl),
|
|
408
297
|
alt: alt ?? value.alternativeText ?? value.name ?? "",
|
|
409
|
-
width: value.width,
|
|
410
|
-
height: value.height,
|
|
298
|
+
width: width ?? value.width,
|
|
299
|
+
height: height ?? value.height,
|
|
411
300
|
loading,
|
|
412
301
|
className,
|
|
413
|
-
style
|
|
302
|
+
style,
|
|
303
|
+
draggable
|
|
414
304
|
}
|
|
415
305
|
);
|
|
416
306
|
if (!ctx.enabled) return imgEl;
|
|
@@ -577,6 +467,7 @@ function parseBlocksFromDOM(root) {
|
|
|
577
467
|
}
|
|
578
468
|
function StrapiBlocks({ path, value, className }) {
|
|
579
469
|
const ctx = useStrapiEditMode();
|
|
470
|
+
const scope = useContentScope();
|
|
580
471
|
const containerRef = react.useRef(null);
|
|
581
472
|
const initialValue = react.useRef(null);
|
|
582
473
|
const blocks = Array.isArray(value) ? value : [];
|
|
@@ -617,7 +508,7 @@ function StrapiBlocks({ path, value, className }) {
|
|
|
617
508
|
const before = JSON.stringify(initialValue.current);
|
|
618
509
|
const after = JSON.stringify(parsed);
|
|
619
510
|
if (before !== after) {
|
|
620
|
-
|
|
511
|
+
postEditChange(scope, path, "blocks", parsed);
|
|
621
512
|
}
|
|
622
513
|
e.currentTarget.style.outlineColor = "transparent";
|
|
623
514
|
e.currentTarget.style.outlineStyle = "dashed";
|
|
@@ -629,6 +520,7 @@ function StrapiBlocks({ path, value, className }) {
|
|
|
629
520
|
var HOVER_OUTLINE2 = "#FA501E";
|
|
630
521
|
function StrapiMarkdownField({ path, value, render, className, minRows = 12 }) {
|
|
631
522
|
const ctx = useStrapiEditMode();
|
|
523
|
+
const scope = useContentScope();
|
|
632
524
|
const [draft, setDraft] = react.useState(value ?? "");
|
|
633
525
|
const initial = react.useRef(value ?? "");
|
|
634
526
|
react.useEffect(() => {
|
|
@@ -646,7 +538,7 @@ function StrapiMarkdownField({ path, value, render, className, minRows = 12 }) {
|
|
|
646
538
|
onChange: (e) => setDraft(e.target.value),
|
|
647
539
|
onBlur: () => {
|
|
648
540
|
if (draft !== initial.current) {
|
|
649
|
-
|
|
541
|
+
postEditChange(scope, path, "richText", draft);
|
|
650
542
|
}
|
|
651
543
|
},
|
|
652
544
|
onFocus: (e) => {
|
|
@@ -695,12 +587,14 @@ function StrapiMarkdownField({ path, value, render, className, minRows = 12 }) {
|
|
|
695
587
|
}
|
|
696
588
|
|
|
697
589
|
exports.StrapiBlocks = StrapiBlocks;
|
|
590
|
+
exports.StrapiContent = StrapiContent;
|
|
698
591
|
exports.StrapiEditModeProvider = StrapiEditModeProvider;
|
|
699
592
|
exports.StrapiField = StrapiField;
|
|
700
593
|
exports.StrapiImage = StrapiImage;
|
|
701
594
|
exports.StrapiList = StrapiList;
|
|
702
595
|
exports.StrapiMarkdownField = StrapiMarkdownField;
|
|
703
596
|
exports.StrapiText = StrapiText;
|
|
597
|
+
exports.useContentScope = useContentScope;
|
|
704
598
|
exports.useStrapiEditMode = useStrapiEditMode;
|
|
705
599
|
//# sourceMappingURL=index.cjs.map
|
|
706
600
|
//# sourceMappingURL=index.cjs.map
|