@paulpaulstudio/strapi-render 0.5.1 → 0.7.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 CHANGED
@@ -3,6 +3,11 @@
3
3
 
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var TurndownService = require('turndown');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var TurndownService__default = /*#__PURE__*/_interopDefault(TurndownService);
6
11
 
7
12
  var EDIT_SESSION_KEY = "__pp_edit_session";
8
13
  var noop = () => {
@@ -235,10 +240,24 @@ function resolveUrl(value, baseUrl) {
235
240
  return value.url;
236
241
  }
237
242
  var HOVER_OUTLINE_COLOR2 = "#FA501E";
238
- function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "lazy", fallback, allowedTypes, multiple = false, width, height, draggable }) {
243
+ function StrapiImage({
244
+ path,
245
+ value,
246
+ baseUrl,
247
+ alt,
248
+ className,
249
+ style,
250
+ loading = "lazy",
251
+ fallback,
252
+ allowedTypes,
253
+ multiple = false,
254
+ width,
255
+ height,
256
+ draggable,
257
+ priority: _ignored
258
+ }) {
239
259
  const ctx = useStrapiEditMode();
240
260
  const scope = useContentScope();
241
- const containerRef = react.useRef(null);
242
261
  const imgRef = react.useRef(null);
243
262
  const handleClick = (e) => {
244
263
  if (!ctx.enabled) return;
@@ -256,40 +275,38 @@ function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "l
256
275
  if (!value) {
257
276
  if (!ctx.enabled) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback ?? null });
258
277
  return /* @__PURE__ */ jsxRuntime.jsx(
259
- "span",
278
+ "button",
260
279
  {
261
- ref: containerRef,
262
- "data-pp-edit": path,
263
- "data-pp-type": "media",
280
+ type: "button",
264
281
  onClick: handleClick,
265
- onMouseEnter: (e) => {
266
- e.currentTarget.style.outlineColor = HOVER_OUTLINE_COLOR2;
267
- },
268
- onMouseLeave: (e) => {
269
- e.currentTarget.style.outlineColor = "transparent";
270
- },
282
+ className,
271
283
  style: {
272
284
  display: "inline-flex",
273
285
  alignItems: "center",
274
286
  justifyContent: "center",
275
287
  background: "rgba(0,0,0,0.05)",
276
288
  border: "1px dashed rgba(0,0,0,0.3)",
277
- outline: "1px dashed transparent",
278
- outlineOffset: 2,
279
- cursor: "pointer",
280
289
  padding: "20px 28px",
281
290
  fontSize: 12,
282
291
  fontWeight: 700,
283
292
  textTransform: "uppercase",
284
293
  letterSpacing: "0.15em",
285
294
  color: "#000",
286
- transition: "outline-color 0.15s ease"
295
+ cursor: "pointer",
296
+ ...style
287
297
  },
288
298
  children: "+ Bild hinzuf\xFCgen"
289
299
  }
290
300
  );
291
301
  }
292
- const imgEl = /* @__PURE__ */ jsxRuntime.jsx(
302
+ const editStyle = ctx.enabled ? {
303
+ ...style,
304
+ outline: "1px dashed transparent",
305
+ outlineOffset: 2,
306
+ cursor: "pointer",
307
+ transition: "outline-color 0.15s ease"
308
+ } : style ?? {};
309
+ return /* @__PURE__ */ jsxRuntime.jsx(
293
310
  "img",
294
311
  {
295
312
  ref: imgRef,
@@ -299,74 +316,21 @@ function StrapiImage({ path, value, baseUrl, alt, className, style, loading = "l
299
316
  height: height ?? value.height,
300
317
  loading,
301
318
  className,
302
- style,
303
- draggable
304
- }
305
- );
306
- if (!ctx.enabled) return imgEl;
307
- return /* @__PURE__ */ jsxRuntime.jsxs(
308
- "span",
309
- {
310
- ref: containerRef,
311
- "data-pp-edit": path,
312
- "data-pp-type": "media",
313
- style: {
314
- position: "relative",
315
- display: "block",
316
- // Wrapper ist block-level damit das innere img mit className w-full / h-[60vh] etc.
317
- // die korrekte Größe ausfüllt. Im Read-Mode (kein Wrapper) hatte das img direkt
318
- // diese Größe — beim Wrap mit inline-block-span schrumpfte das.
319
- outline: "1px dashed transparent",
320
- outlineOffset: 2,
321
- transition: "outline-color 0.15s ease"
322
- },
323
- onMouseEnter: (e) => {
324
- e.currentTarget.style.outlineColor = HOVER_OUTLINE_COLOR2;
325
- const btn = e.currentTarget.querySelector("[data-pp-edit-btn]");
326
- if (btn) btn.style.opacity = "1";
327
- },
328
- onMouseLeave: (e) => {
329
- e.currentTarget.style.outlineColor = "transparent";
330
- const btn = e.currentTarget.querySelector("[data-pp-edit-btn]");
331
- if (btn) btn.style.opacity = "0";
332
- },
333
- children: [
334
- imgEl,
335
- /* @__PURE__ */ jsxRuntime.jsx(
336
- "button",
337
- {
338
- type: "button",
339
- "data-pp-edit-btn": true,
340
- onClick: handleClick,
341
- style: {
342
- position: "absolute",
343
- top: 8,
344
- right: 8,
345
- background: "#000",
346
- color: "#EBC6DF",
347
- border: "2px solid #000",
348
- padding: "6px 10px",
349
- fontSize: 11,
350
- fontWeight: 700,
351
- textTransform: "uppercase",
352
- letterSpacing: "0.15em",
353
- cursor: "pointer",
354
- opacity: 0,
355
- transition: "opacity 0.15s ease, background 0.15s ease",
356
- fontFamily: "system-ui, -apple-system, sans-serif"
357
- },
358
- onMouseEnter: (e) => {
359
- e.currentTarget.style.background = "#FA501E";
360
- e.currentTarget.style.color = "#000";
361
- },
362
- onMouseLeave: (e) => {
363
- e.currentTarget.style.background = "#000";
364
- e.currentTarget.style.color = "#EBC6DF";
365
- },
366
- children: "\xC4ndern"
367
- }
368
- )
369
- ]
319
+ style: editStyle,
320
+ draggable,
321
+ "data-pp-edit": ctx.enabled ? path : void 0,
322
+ "data-pp-type": ctx.enabled ? "media" : void 0,
323
+ onClick: ctx.enabled ? handleClick : void 0,
324
+ onMouseEnter: ctx.enabled ? (e) => {
325
+ const el = e.currentTarget;
326
+ el.style.outlineColor = HOVER_OUTLINE_COLOR2;
327
+ el.style.outlineStyle = "solid";
328
+ } : void 0,
329
+ onMouseLeave: ctx.enabled ? (e) => {
330
+ const el = e.currentTarget;
331
+ el.style.outlineColor = "transparent";
332
+ el.style.outlineStyle = "dashed";
333
+ } : void 0
370
334
  }
371
335
  );
372
336
  }
@@ -594,14 +558,180 @@ function StrapiMarkdownField({ path, value, render, className, minRows = 12 }) {
594
558
  }, children: "Markdown \u2014 **fett**, *kursiv*, ## \xDCberschrift, [link](url)" })
595
559
  ] });
596
560
  }
561
+ var HOVER_OUTLINE3 = "#FA501E";
562
+ function StrapiRichTextField({ path, value, render, className }) {
563
+ const ctx = useStrapiEditMode();
564
+ const scope = useContentScope();
565
+ const containerRef = react.useRef(null);
566
+ const turndownRef = react.useRef(null);
567
+ const initial = react.useRef(value ?? "");
568
+ const [, force] = react.useState({});
569
+ if (typeof window !== "undefined" && !turndownRef.current) {
570
+ const td = new TurndownService__default.default({
571
+ headingStyle: "atx",
572
+ hr: "---",
573
+ bulletListMarker: "-",
574
+ codeBlockStyle: "fenced",
575
+ emDelimiter: "*"
576
+ });
577
+ td.addRule("br", {
578
+ filter: "br",
579
+ replacement: () => "\n"
580
+ });
581
+ turndownRef.current = td;
582
+ }
583
+ react.useEffect(() => {
584
+ initial.current = value ?? "";
585
+ force({});
586
+ }, [value]);
587
+ if (!ctx.enabled) {
588
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: render(value ?? "") });
589
+ }
590
+ return /* @__PURE__ */ jsxRuntime.jsx(
591
+ "div",
592
+ {
593
+ ref: containerRef,
594
+ className,
595
+ contentEditable: true,
596
+ suppressContentEditableWarning: true,
597
+ "data-pp-edit": path,
598
+ "data-pp-type": "richText",
599
+ style: {
600
+ outline: "1px dashed transparent",
601
+ outlineOffset: 4,
602
+ transition: "outline-color 0.15s ease",
603
+ cursor: "text"
604
+ },
605
+ onMouseEnter: (e) => {
606
+ e.currentTarget.style.outlineColor = HOVER_OUTLINE3;
607
+ },
608
+ onMouseLeave: (e) => {
609
+ if (document.activeElement !== e.currentTarget) {
610
+ e.currentTarget.style.outlineColor = "transparent";
611
+ }
612
+ },
613
+ onFocus: (e) => {
614
+ e.currentTarget.style.outlineColor = HOVER_OUTLINE3;
615
+ e.currentTarget.style.outlineStyle = "solid";
616
+ },
617
+ onBlur: (e) => {
618
+ const el = e.currentTarget;
619
+ el.style.outlineColor = "transparent";
620
+ el.style.outlineStyle = "dashed";
621
+ if (!turndownRef.current) return;
622
+ const html = el.innerHTML;
623
+ const md = turndownRef.current.turndown(html).trim();
624
+ if (md !== initial.current.trim()) {
625
+ postEditChange(scope, path, "richText", md);
626
+ }
627
+ },
628
+ onKeyDown: (e) => {
629
+ if (e.metaKey || e.ctrlKey) {
630
+ if (e.key === "b") {
631
+ e.preventDefault();
632
+ document.execCommand("bold");
633
+ } else if (e.key === "i") {
634
+ e.preventDefault();
635
+ document.execCommand("italic");
636
+ } else if (e.key === "u") {
637
+ e.preventDefault();
638
+ document.execCommand("underline");
639
+ } else if (e.key === "k") {
640
+ e.preventDefault();
641
+ const url = window.prompt("Link-URL:");
642
+ if (url) document.execCommand("createLink", false, url);
643
+ }
644
+ }
645
+ },
646
+ children: render(value ?? "")
647
+ }
648
+ );
649
+ }
650
+ function StrapiLink({ path, value, target, rel, className, children }) {
651
+ const ctx = useStrapiEditMode();
652
+ const scope = useContentScope();
653
+ const [hover, setHover] = react.useState(false);
654
+ if (!ctx.enabled) {
655
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href: value ?? "#", target, rel, className, children });
656
+ }
657
+ const handleEdit = (e) => {
658
+ e.preventDefault();
659
+ e.stopPropagation();
660
+ const next = window.prompt("Link-URL bearbeiten:", value ?? "");
661
+ if (next !== null && next !== value) {
662
+ postEditChange(scope, path, "text", next);
663
+ }
664
+ };
665
+ return /* @__PURE__ */ jsxRuntime.jsxs(
666
+ "span",
667
+ {
668
+ style: { position: "relative", display: "inline-block" },
669
+ onMouseEnter: () => setHover(true),
670
+ onMouseLeave: () => setHover(false),
671
+ children: [
672
+ /* @__PURE__ */ jsxRuntime.jsx(
673
+ "a",
674
+ {
675
+ href: value ?? "#",
676
+ target,
677
+ rel,
678
+ className,
679
+ onClick: (e) => {
680
+ e.preventDefault();
681
+ },
682
+ "data-pp-edit": path,
683
+ "data-pp-type": "text",
684
+ children
685
+ }
686
+ ),
687
+ /* @__PURE__ */ jsxRuntime.jsx(
688
+ "button",
689
+ {
690
+ type: "button",
691
+ onClick: handleEdit,
692
+ style: {
693
+ position: "absolute",
694
+ top: 8,
695
+ right: 8,
696
+ background: "#000",
697
+ color: "#EBC6DF",
698
+ border: "2px solid #000",
699
+ padding: "4px 8px",
700
+ fontSize: 10,
701
+ fontWeight: 700,
702
+ textTransform: "uppercase",
703
+ letterSpacing: "0.15em",
704
+ cursor: "pointer",
705
+ opacity: hover ? 1 : 0,
706
+ transition: "opacity 0.15s ease, background 0.15s ease",
707
+ fontFamily: "system-ui, sans-serif",
708
+ zIndex: 10
709
+ },
710
+ onMouseEnter: (e) => {
711
+ e.currentTarget.style.background = "#FA501E";
712
+ e.currentTarget.style.color = "#000";
713
+ },
714
+ onMouseLeave: (e) => {
715
+ e.currentTarget.style.background = "#000";
716
+ e.currentTarget.style.color = "#EBC6DF";
717
+ },
718
+ children: "\u{1F517} Link"
719
+ }
720
+ )
721
+ ]
722
+ }
723
+ );
724
+ }
597
725
 
598
726
  exports.StrapiBlocks = StrapiBlocks;
599
727
  exports.StrapiContent = StrapiContent;
600
728
  exports.StrapiEditModeProvider = StrapiEditModeProvider;
601
729
  exports.StrapiField = StrapiField;
602
730
  exports.StrapiImage = StrapiImage;
731
+ exports.StrapiLink = StrapiLink;
603
732
  exports.StrapiList = StrapiList;
604
733
  exports.StrapiMarkdownField = StrapiMarkdownField;
734
+ exports.StrapiRichTextField = StrapiRichTextField;
605
735
  exports.StrapiText = StrapiText;
606
736
  exports.useContentScope = useContentScope;
607
737
  exports.useStrapiEditMode = useStrapiEditMode;