@overlap/rte 0.1.1 → 0.1.2

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
@@ -5,50 +5,78 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var React = require('react');
7
7
 
8
- const BoldIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z" }) }));
9
- const ItalicIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z" }) }));
10
- const UnderlineIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z" }) }));
11
- const UndoIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z" }) }));
12
- const RedoIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z" }) }));
13
- const ClearFormattingIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M6 5v.18L8.82 8h2.4L7.73 4.36C7.26 3.85 6.61 3.5 6 3.5c-1.11 0-2 .89-2 2 0 .61.35 1.26.86 1.73L6 5zm14.27 2.5L18.73 9H21v1h-4.27L15 8.27l1.23-1.23c.5-.5 1.15-.73 1.77-.73 1.11 0 2 .89 2 2 0 .62-.23 1.27-.73 1.77L18.27 13H21v1h-5.27l-2-2H9.73l-2 2H3v-1h4.27l2-2H7v-1h2.73l2-2H12v-1h-2.27l2-2h4.54zM5 15h14v2H5v-2z" }) }));
14
- const LinkIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" }) }));
15
- const QuoteIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z" }) }));
16
- const BulletListIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z" }) }));
17
- const NumberedListIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 11.9V11H2zm6-5v2h14V6H8zm0 14h14v-2H8v2zm0-6h14v-2H8v2z" }) }));
18
- const TextColorIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M2 20h20v4H2v-4zm3.49-3h2.42l1.27-3.58h5.64L16.09 17h2.42L13.25 3h-2.5L5.49 17zm4.22-5.61l2.03-5.79h.12l2.03 5.79H9.71z" }) }));
19
- const BackgroundColorIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z" }) }));
20
- const HeadingIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M5 4v3h5.5v12h3V7H19V4H5z" }) }));
21
- const FontSizeIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M9 4v3h5v12h3V7h5V4H9zm-6 8h3v8h3v-8h3V10H3z" }) }));
22
- const ImageIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z" }) }));
23
- const CloseIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }));
24
- const LoadingIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" }) }));
25
- const UploadIcon = ({ width = 18, height = 18, className }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z" }) }));
8
+ const BoldIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z" }) }));
9
+ const ItalicIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z" }) }));
10
+ const UnderlineIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z" }) }));
11
+ const UndoIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z" }) }));
12
+ const RedoIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z" }) }));
13
+ const ClearFormattingIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsxs("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: [jsxRuntime.jsx("path", { d: "M6 5v3h5v11h2V8h5V5H6z" }), jsxRuntime.jsx("path", { d: "M20.5 3.5L3.5 20.5l1.06 1.06L21.56 4.56z" })] }));
14
+ const LinkIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" }) }));
15
+ const QuoteIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z" }) }));
16
+ const BulletListIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z" }) }));
17
+ const NumberedListIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 11.9V11H2zm6-5v2h14V6H8zm0 14h14v-2H8v2zm0-6h14v-2H8v2z" }) }));
18
+ const TextColorIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M2 20h20v4H2v-4zm3.49-3h2.42l1.27-3.58h5.64L16.09 17h2.42L13.25 3h-2.5L5.49 17zm4.22-5.61l2.03-5.79h.12l2.03 5.79H9.71z" }) }));
19
+ const BackgroundColorIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsxs("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: [jsxRuntime.jsx("path", { d: "M17.5 4.5c-1.95 0-4.05.4-5.5 1.5-1.45-1.1-3.55-1.5-5.5-1.5-1.45 0-2.99.22-4.28.79C1.49 5.62 1 6.33 1 7.14v11.28c0 1.3 1.22 2.26 2.48 1.94.98-.25 2.02-.36 3.02-.36 1.56 0 3.22.26 4.56.92.6.3 1.28.3 1.88 0 1.34-.67 3-.92 4.56-.92 1 0 2.04.11 3.02.36C22.78 20.68 24 19.72 24 18.42V7.14c0-.81-.49-1.52-1.22-1.85-1.29-.57-2.83-.79-4.28-.79zM21 17.23c0 .63-.58 1.09-1.2.98-.75-.14-1.53-.2-2.3-.2-1.7 0-4.15.65-5.5 1.5V8c1.35-.85 3.8-1.5 5.5-1.5.77 0 1.55.06 2.3.2.62.11 1.2.58 1.2 1.18v9.35z" }), jsxRuntime.jsx("rect", { x: "4", y: "13", width: "16", height: "6", fill: "currentColor", opacity: "0.5" })] }));
20
+ const HeadingIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M5 4v3h5.5v12h3V7H19V4H5z" }) }));
21
+ const FontSizeIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M9 4v3h5v12h3V7h5V4H9zm-6 8h3v8h3v-8h3V10H3z" }) }));
22
+ const ImageIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z" }) }));
23
+ const CloseIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }));
24
+ const LoadingIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z" }) }));
25
+ const UploadIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z" }) }));
26
+ const IndentIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M3 21h18v-2H3v2zM3 8l4 4-4 4V8zm8 9h10v-2H11v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11v2z" }) }));
27
+ const OutdentIcon = ({ width = 18, height = 18, className, }) => (jsxRuntime.jsx("svg", { width: width, height: height, viewBox: "0 0 24 24", fill: "currentColor", className: className, children: jsxRuntime.jsx("path", { d: "M3 21h18v-2H3v2zM11 8l4 4-4 4V8zM3 3v2h18V3H3zm0 4h10v2H3V7zm0 4h10v2H3v-2zm0 4h18v2H3v-2z" }) }));
26
28
  const iconMap = {
27
- 'mdi:format-bold': BoldIcon,
28
- 'mdi:format-italic': ItalicIcon,
29
- 'mdi:format-underline': UnderlineIcon,
30
- 'mdi:undo': UndoIcon,
31
- 'mdi:redo': RedoIcon,
32
- 'mdi:format-clear': ClearFormattingIcon,
33
- 'mdi:link': LinkIcon,
34
- 'mdi:format-quote-close': QuoteIcon,
35
- 'mdi:format-list-bulleted': BulletListIcon,
36
- 'mdi:format-list-numbered': NumberedListIcon,
37
- 'mdi:format-color-text': TextColorIcon,
38
- 'mdi:format-color-fill': BackgroundColorIcon,
39
- 'mdi:format-header-1': HeadingIcon,
40
- 'mdi:format-size': FontSizeIcon,
41
- 'mdi:image': ImageIcon,
42
- 'mdi:close': CloseIcon,
43
- 'mdi:loading': LoadingIcon,
44
- 'mdi:upload': UploadIcon,
29
+ "mdi:format-bold": BoldIcon,
30
+ "mdi:format-italic": ItalicIcon,
31
+ "mdi:format-underline": UnderlineIcon,
32
+ "mdi:undo": UndoIcon,
33
+ "mdi:redo": RedoIcon,
34
+ "mdi:format-clear": ClearFormattingIcon,
35
+ "mdi:link": LinkIcon,
36
+ "mdi:format-quote-close": QuoteIcon,
37
+ "mdi:format-list-bulleted": BulletListIcon,
38
+ "mdi:format-list-numbered": NumberedListIcon,
39
+ "mdi:format-color-text": TextColorIcon,
40
+ "mdi:format-color-fill": BackgroundColorIcon,
41
+ "mdi:format-header-1": HeadingIcon,
42
+ "mdi:format-size": FontSizeIcon,
43
+ "mdi:image": ImageIcon,
44
+ "mdi:close": CloseIcon,
45
+ "mdi:loading": LoadingIcon,
46
+ "mdi:upload": UploadIcon,
47
+ "mdi:format-indent-increase": IndentIcon,
48
+ "mdi:format-indent-decrease": OutdentIcon,
45
49
  };
46
50
  const Icon = ({ icon, width = 18, height = 18, className }) => {
47
51
  const IconComponent = iconMap[icon];
48
52
  if (!IconComponent) {
49
- return jsxRuntime.jsx("span", { style: { width, height, display: 'inline-block' } });
53
+ return jsxRuntime.jsx("span", { style: { width, height, display: "inline-block" } });
50
54
  }
51
- return jsxRuntime.jsx(IconComponent, { width: width, height: height, className: className });
55
+ return (jsxRuntime.jsx(IconComponent, { width: width, height: height, className: className }));
56
+ };
57
+
58
+ const Dropdown = ({ icon, label, options, onSelect, currentValue, disabled, }) => {
59
+ const [isOpen, setIsOpen] = React.useState(false);
60
+ const dropdownRef = React.useRef(null);
61
+ React.useEffect(() => {
62
+ const handleClickOutside = (event) => {
63
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
64
+ setIsOpen(false);
65
+ }
66
+ };
67
+ if (isOpen) {
68
+ document.addEventListener('mousedown', handleClickOutside);
69
+ }
70
+ return () => {
71
+ document.removeEventListener('mousedown', handleClickOutside);
72
+ };
73
+ }, [isOpen]);
74
+ const handleSelect = (value) => {
75
+ onSelect(value);
76
+ setIsOpen(false);
77
+ };
78
+ const currentOption = options.find(opt => opt.value === currentValue);
79
+ return (jsxRuntime.jsxs("div", { className: "rte-dropdown", ref: dropdownRef, children: [jsxRuntime.jsxs("button", { type: "button", onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, className: `rte-toolbar-button rte-dropdown-button ${currentOption ? 'rte-dropdown-button-has-value' : ''}`, title: label, "aria-label": label, children: [jsxRuntime.jsx(Icon, { icon: icon, width: 18, height: 18 }), currentOption && (jsxRuntime.jsx("span", { className: "rte-dropdown-value", children: currentOption.label }))] }), isOpen && (jsxRuntime.jsx("div", { className: "rte-dropdown-menu", children: options.map((option) => (jsxRuntime.jsxs("button", { type: "button", className: `rte-dropdown-item ${currentValue === option.value ? 'rte-dropdown-item-active' : ''}`, onClick: () => handleSelect(option.value), children: [option.color && (jsxRuntime.jsx("span", { className: `rte-dropdown-color-preview ${currentValue === option.value ? 'active' : ''}`, style: { backgroundColor: option.color } })), option.preview && !option.headingPreview && (jsxRuntime.jsx("span", { className: "rte-dropdown-fontsize-preview", style: { fontSize: `${option.preview}px` }, children: "Aa" })), option.headingPreview && (jsxRuntime.jsx("span", { className: `rte-dropdown-heading-preview ${option.headingPreview}`, children: option.headingPreview === 'p' ? 'Normal' : option.headingPreview.toUpperCase() })), option.icon && jsxRuntime.jsx(Icon, { icon: option.icon, width: 16, height: 16 }), jsxRuntime.jsx("span", { style: { flex: 1, fontWeight: currentValue === option.value ? 600 : 400 }, children: option.label })] }, option.value))) }))] }));
52
80
  };
53
81
 
54
82
  const IconWrapper = ({ icon, width = 18, height = 18, className }) => {
@@ -111,6 +139,168 @@ function createCommandPlugin(name, command, icon, label) {
111
139
  };
112
140
  }
113
141
 
142
+ const defaultHeadings$2 = ["h1", "h2", "h3"];
143
+ const headingLabels$1 = {
144
+ h1: "Überschrift 1",
145
+ h2: "Überschrift 2",
146
+ h3: "Überschrift 3",
147
+ h4: "Überschrift 4",
148
+ h5: "Überschrift 5",
149
+ h6: "Überschrift 6",
150
+ };
151
+ /**
152
+ * Erstellt ein Block-Format-Plugin, das Headlines, Listen und Quote in einem Dropdown kombiniert
153
+ * @param headings - Array von Heading-Levels (z.B. ["h1", "h2", "h3"])
154
+ */
155
+ function createBlockFormatPlugin(headings = defaultHeadings$2) {
156
+ const options = [
157
+ { value: "p", label: "Normal", headingPreview: "p" },
158
+ ...headings.map((h) => ({
159
+ value: h,
160
+ label: headingLabels$1[h] || h.toUpperCase(),
161
+ headingPreview: h,
162
+ })),
163
+ {
164
+ value: "ul",
165
+ label: "Aufzählungsliste",
166
+ icon: "mdi:format-list-bulleted",
167
+ },
168
+ {
169
+ value: "ol",
170
+ label: "Nummerierte Liste",
171
+ icon: "mdi:format-list-numbered",
172
+ },
173
+ { value: "blockquote", label: "Zitat", icon: "mdi:format-quote-close" },
174
+ ];
175
+ return {
176
+ name: "blockFormat",
177
+ type: "block",
178
+ renderButton: (props) => {
179
+ // Aktuelles Format bestimmen
180
+ const editor = props.editorAPI;
181
+ let currentValue = props.currentValue;
182
+ if (!currentValue && editor) {
183
+ const selection = editor.getSelection();
184
+ if (selection && selection.rangeCount > 0) {
185
+ const range = selection.getRangeAt(0);
186
+ const container = range.commonAncestorContainer;
187
+ const element = container.nodeType === Node.TEXT_NODE
188
+ ? container.parentElement
189
+ : container;
190
+ if (element) {
191
+ const tagName = element.tagName.toLowerCase();
192
+ // Prüfe auf Heading
193
+ if (headings.includes(tagName)) {
194
+ currentValue = tagName;
195
+ }
196
+ // Prüfe auf Blockquote
197
+ else if (element.closest("blockquote")) {
198
+ currentValue = "blockquote";
199
+ }
200
+ // Prüfe auf Liste
201
+ else if (element.closest("ul")) {
202
+ currentValue = "ul";
203
+ }
204
+ else if (element.closest("ol")) {
205
+ currentValue = "ol";
206
+ }
207
+ // Prüfe auf Paragraph
208
+ else if (tagName === "p") {
209
+ currentValue = "p";
210
+ }
211
+ }
212
+ }
213
+ }
214
+ return (jsxRuntime.jsx(Dropdown, { icon: "mdi:format-header-1", label: "Format", options: options, onSelect: (value) => {
215
+ // onSelect wird von der Toolbar übergeben und ruft handlePluginClick auf
216
+ if (props.onSelect) {
217
+ props.onSelect(value);
218
+ }
219
+ }, currentValue: currentValue, disabled: props.disabled }));
220
+ },
221
+ getCurrentValue: (editor) => {
222
+ const selection = editor.getSelection();
223
+ if (!selection || selection.rangeCount === 0)
224
+ return undefined;
225
+ const range = selection.getRangeAt(0);
226
+ const container = range.commonAncestorContainer;
227
+ const element = container.nodeType === Node.TEXT_NODE
228
+ ? container.parentElement
229
+ : container;
230
+ if (!element)
231
+ return undefined;
232
+ const tagName = element.tagName.toLowerCase();
233
+ // Prüfe auf Heading
234
+ if (headings.includes(tagName)) {
235
+ return tagName;
236
+ }
237
+ // Prüfe auf Blockquote
238
+ if (element.closest("blockquote")) {
239
+ return "blockquote";
240
+ }
241
+ // Prüfe auf Liste
242
+ if (element.closest("ul")) {
243
+ return "ul";
244
+ }
245
+ if (element.closest("ol")) {
246
+ return "ol";
247
+ }
248
+ // Prüfe auf Paragraph
249
+ if (tagName === "p") {
250
+ return "p";
251
+ }
252
+ return undefined;
253
+ },
254
+ execute: (editor, value) => {
255
+ if (!value)
256
+ return;
257
+ if (value === "ul") {
258
+ editor.executeCommand("insertUnorderedList");
259
+ }
260
+ else if (value === "ol") {
261
+ editor.executeCommand("insertOrderedList");
262
+ }
263
+ else if (value === "blockquote") {
264
+ const selection = editor.getSelection();
265
+ if (selection && selection.rangeCount > 0) {
266
+ const range = selection.getRangeAt(0);
267
+ const container = range.commonAncestorContainer;
268
+ const element = container.nodeType === Node.TEXT_NODE
269
+ ? container.parentElement
270
+ : container;
271
+ if (element?.closest("blockquote")) {
272
+ editor.executeCommand("formatBlock", "<p>");
273
+ }
274
+ else {
275
+ editor.executeCommand("formatBlock", "<blockquote>");
276
+ }
277
+ }
278
+ }
279
+ else {
280
+ editor.executeCommand("formatBlock", `<${value}>`);
281
+ }
282
+ },
283
+ isActive: (editor) => {
284
+ const selection = editor.getSelection();
285
+ if (!selection || selection.rangeCount === 0)
286
+ return false;
287
+ const range = selection.getRangeAt(0);
288
+ const container = range.commonAncestorContainer;
289
+ const element = container.nodeType === Node.TEXT_NODE
290
+ ? container.parentElement
291
+ : container;
292
+ if (!element)
293
+ return false;
294
+ const tagName = element.tagName.toLowerCase();
295
+ return (headings.includes(tagName) ||
296
+ element.closest("blockquote") !== null ||
297
+ element.closest("ul") !== null ||
298
+ element.closest("ol") !== null);
299
+ },
300
+ canExecute: () => true,
301
+ };
302
+ }
303
+
114
304
  /**
115
305
  * Clear Formatting Plugin - Entfernt alle Formatierungen
116
306
  */
@@ -127,50 +317,89 @@ const clearFormattingPlugin = {
127
317
  },
128
318
  };
129
319
 
320
+ const defaultHeadings$1 = ["h1", "h2", "h3"];
130
321
  /**
131
322
  * Standard-Plugins
132
323
  */
133
- const boldPlugin = createInlinePlugin('bold', 'bold', 'mdi:format-bold', 'Fett');
134
- const italicPlugin = createInlinePlugin('italic', 'italic', 'mdi:format-italic', 'Kursiv');
135
- const underlinePlugin = createInlinePlugin('underline', 'underline', 'mdi:format-underline', 'Unterstrichen');
136
- const undoPlugin = createCommandPlugin('undo', 'undo', 'mdi:undo', 'Rückgängig');
137
- const redoPlugin = createCommandPlugin('redo', 'redo', 'mdi:redo', 'Wiederholen');
324
+ const boldPlugin = createInlinePlugin("bold", "bold", "mdi:format-bold", "Fett");
325
+ const italicPlugin = createInlinePlugin("italic", "italic", "mdi:format-italic", "Kursiv");
326
+ const underlinePlugin = createInlinePlugin("underline", "underline", "mdi:format-underline", "Unterstrichen");
327
+ const undoPlugin = createCommandPlugin("undo", "undo", "mdi:undo", "Rückgängig");
328
+ const redoPlugin = createCommandPlugin("redo", "redo", "mdi:redo", "Wiederholen");
329
+ /**
330
+ * Indent List Item Plugin (Tab für Unterliste)
331
+ */
332
+ const indentListItemPlugin = {
333
+ name: "indentListItem",
334
+ type: "command",
335
+ renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: "rte-toolbar-button", title: "Einr\u00FCcken (Unterliste)", "aria-label": "Einr\u00FCcken (Unterliste)", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-indent-increase", width: 18, height: 18 }) })),
336
+ execute: (editor) => {
337
+ editor.indentListItem();
338
+ },
339
+ canExecute: (editor) => {
340
+ const selection = editor.getSelection();
341
+ if (!selection || selection.rangeCount === 0)
342
+ return false;
343
+ const range = selection.getRangeAt(0);
344
+ const container = range.commonAncestorContainer;
345
+ const listItem = container.nodeType === Node.TEXT_NODE
346
+ ? container.parentElement?.closest("li")
347
+ : container.closest("li");
348
+ return listItem !== null;
349
+ },
350
+ };
351
+ /**
352
+ * Outdent List Item Plugin (Shift+Tab)
353
+ */
354
+ const outdentListItemPlugin = {
355
+ name: "outdentListItem",
356
+ type: "command",
357
+ renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: "rte-toolbar-button", title: "Ausr\u00FCcken", "aria-label": "Ausr\u00FCcken", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-indent-decrease", width: 18, height: 18 }) })),
358
+ execute: (editor) => {
359
+ editor.outdentListItem();
360
+ },
361
+ canExecute: (editor) => {
362
+ const selection = editor.getSelection();
363
+ if (!selection || selection.rangeCount === 0)
364
+ return false;
365
+ const range = selection.getRangeAt(0);
366
+ const container = range.commonAncestorContainer;
367
+ const listItem = container.nodeType === Node.TEXT_NODE
368
+ ? container.parentElement?.closest("li")
369
+ : container.closest("li");
370
+ if (!listItem)
371
+ return false;
372
+ // Prüfe ob in verschachtelter Liste
373
+ const list = listItem.parentElement;
374
+ if (!list || (list.tagName !== "UL" && list.tagName !== "OL"))
375
+ return false;
376
+ const parentListItem = list.parentElement;
377
+ return parentListItem !== null && parentListItem.tagName === "LI";
378
+ },
379
+ };
138
380
  /**
139
381
  * Standard-Plugin-Liste
382
+ * Die Plugins werden hier direkt referenziert, um sicherzustellen, dass sie in defaultPlugins enthalten sind
140
383
  */
384
+ const _indentPlugin = indentListItemPlugin;
385
+ const _outdentPlugin = outdentListItemPlugin;
386
+ /**
387
+ * Standard Block-Format Plugin (Headlines, Listen, Quote in einem Dropdown)
388
+ * Verwendet standardmäßig h1, h2, h3, kann aber über Editor-Props angepasst werden
389
+ */
390
+ const defaultBlockFormatPlugin = createBlockFormatPlugin(defaultHeadings$1);
141
391
  const defaultPlugins = [
142
392
  undoPlugin,
143
393
  redoPlugin,
144
394
  boldPlugin,
145
395
  italicPlugin,
146
396
  underlinePlugin,
397
+ defaultBlockFormatPlugin,
147
398
  clearFormattingPlugin,
399
+ _indentPlugin,
400
+ _outdentPlugin,
148
401
  ];
149
402
 
150
- const Dropdown = ({ icon, label, options, onSelect, currentValue, disabled, }) => {
151
- const [isOpen, setIsOpen] = React.useState(false);
152
- const dropdownRef = React.useRef(null);
153
- React.useEffect(() => {
154
- const handleClickOutside = (event) => {
155
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
156
- setIsOpen(false);
157
- }
158
- };
159
- if (isOpen) {
160
- document.addEventListener('mousedown', handleClickOutside);
161
- }
162
- return () => {
163
- document.removeEventListener('mousedown', handleClickOutside);
164
- };
165
- }, [isOpen]);
166
- const handleSelect = (value) => {
167
- onSelect(value);
168
- setIsOpen(false);
169
- };
170
- const currentOption = options.find(opt => opt.value === currentValue);
171
- return (jsxRuntime.jsxs("div", { className: "rte-dropdown", ref: dropdownRef, children: [jsxRuntime.jsxs("button", { type: "button", onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, className: `rte-toolbar-button rte-dropdown-button ${currentOption ? 'rte-dropdown-button-has-value' : ''}`, title: label, "aria-label": label, children: [jsxRuntime.jsx(Icon, { icon: icon, width: 18, height: 18 }), currentOption && (jsxRuntime.jsx("span", { className: "rte-dropdown-value", children: currentOption.label }))] }), isOpen && (jsxRuntime.jsx("div", { className: "rte-dropdown-menu", children: options.map((option) => (jsxRuntime.jsxs("button", { type: "button", className: `rte-dropdown-item ${currentValue === option.value ? 'rte-dropdown-item-active' : ''}`, onClick: () => handleSelect(option.value), children: [option.color && (jsxRuntime.jsx("span", { className: `rte-dropdown-color-preview ${currentValue === option.value ? 'active' : ''}`, style: { backgroundColor: option.color } })), option.preview && !option.headingPreview && (jsxRuntime.jsx("span", { className: "rte-dropdown-fontsize-preview", style: { fontSize: `${option.preview}px` }, children: "Aa" })), option.headingPreview && (jsxRuntime.jsx("span", { className: `rte-dropdown-heading-preview ${option.headingPreview}`, children: option.headingPreview === 'p' ? 'Normal' : option.headingPreview.toUpperCase() })), option.icon && jsxRuntime.jsx(Icon, { icon: option.icon, width: 16, height: 16 }), jsxRuntime.jsx("span", { style: { flex: 1, fontWeight: currentValue === option.value ? 600 : 400 }, children: option.label })] }, option.value))) }))] }));
172
- };
173
-
174
403
  /**
175
404
  * Liest die aktuelle Font-Size aus dem DOM an der Cursor-Position
176
405
  */
@@ -488,64 +717,6 @@ function createFontSizePlugin(fontSizes = [12, 14, 16, 18, 20, 24]) {
488
717
  };
489
718
  }
490
719
 
491
- const defaultHeadings = ['h1', 'h2', 'h3'];
492
- const headingLabels = {
493
- h1: 'Überschrift 1',
494
- h2: 'Überschrift 2',
495
- h3: 'Überschrift 3',
496
- h4: 'Überschrift 4',
497
- h5: 'Überschrift 5',
498
- h6: 'Überschrift 6',
499
- };
500
- function createHeadingsPlugin(headings = defaultHeadings) {
501
- const options = [
502
- { value: 'p', label: 'Normal', headingPreview: 'p' },
503
- ...headings.map(h => ({
504
- value: h,
505
- label: headingLabels[h] || h.toUpperCase(),
506
- headingPreview: h,
507
- })),
508
- ];
509
- return {
510
- name: 'headings',
511
- type: 'block',
512
- renderButton: (props) => {
513
- // Aktuelles Heading aus State Reflection
514
- const currentValue = props.currentValue || (props.editorAPI ? getCurrentHeading(props.editorAPI, headings) : undefined);
515
- return (jsxRuntime.jsx(Dropdown, { icon: "mdi:format-header-1", label: "\u00DCberschrift", options: options, onSelect: (value) => {
516
- if (props.onSelect) {
517
- props.onSelect(value);
518
- }
519
- else {
520
- props.onClick();
521
- }
522
- }, currentValue: currentValue, disabled: props.disabled }));
523
- },
524
- getCurrentValue: (editor) => {
525
- return getCurrentHeading(editor, headings);
526
- },
527
- execute: (editor, value) => {
528
- const tag = value || 'p';
529
- editor.executeCommand('formatBlock', `<${tag}>`);
530
- },
531
- isActive: (editor) => {
532
- const selection = editor.getSelection();
533
- if (!selection || selection.rangeCount === 0)
534
- return false;
535
- const range = selection.getRangeAt(0);
536
- const container = range.commonAncestorContainer;
537
- const element = container.nodeType === Node.TEXT_NODE
538
- ? container.parentElement
539
- : container;
540
- if (!element)
541
- return false;
542
- const tagName = element.tagName.toLowerCase();
543
- return headings.includes(tagName);
544
- },
545
- canExecute: () => true,
546
- };
547
- }
548
-
549
720
  /**
550
721
  * Image-Plugin mit URL-Eingabe und File-Upload
551
722
  */
@@ -1341,8 +1512,16 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1341
1512
  allPlugins.push(createTextColorPlugin(colors));
1342
1513
  allPlugins.push(createBackgroundColorPlugin(colors));
1343
1514
  }
1515
+ // BlockFormat Plugin ist bereits in defaultPlugins enthalten
1516
+ // Wenn custom headings angegeben sind, ersetze das Standard-Plugin
1344
1517
  if (headings && headings.length > 0) {
1345
- allPlugins.push(createHeadingsPlugin(headings));
1518
+ // Entferne das Standard-BlockFormat-Plugin
1519
+ const blockFormatIndex = allPlugins.findIndex((p) => p.name === "blockFormat");
1520
+ if (blockFormatIndex !== -1) {
1521
+ allPlugins.splice(blockFormatIndex, 1);
1522
+ }
1523
+ // Füge das Plugin mit custom Headlines hinzu
1524
+ allPlugins.push(createBlockFormatPlugin(headings));
1346
1525
  }
1347
1526
  allPlugins.push(createImagePlugin(onImageUpload));
1348
1527
  return allPlugins;
@@ -1356,7 +1535,7 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1356
1535
  }
1357
1536
  }, [onChange]);
1358
1537
  const restoreSelection = React.useCallback((editor) => {
1359
- if (typeof window === 'undefined' || typeof document === 'undefined')
1538
+ if (typeof window === "undefined" || typeof document === "undefined")
1360
1539
  return;
1361
1540
  const range = document.createRange();
1362
1541
  const selection = window.getSelection();
@@ -1549,7 +1728,7 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1549
1728
  return {
1550
1729
  executeCommand,
1551
1730
  getSelection: () => {
1552
- if (typeof window === 'undefined')
1731
+ if (typeof window === "undefined")
1553
1732
  return null;
1554
1733
  return window.getSelection();
1555
1734
  },
@@ -1741,6 +1920,40 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1741
1920
  }, 0);
1742
1921
  }
1743
1922
  },
1923
+ indentListItem: () => {
1924
+ const editor = editorRef.current;
1925
+ if (!editor)
1926
+ return;
1927
+ const selection = window.getSelection();
1928
+ if (selection && selection.rangeCount > 0) {
1929
+ const currentContent = domToContent(editor);
1930
+ historyRef.current.push(currentContent);
1931
+ indentListItem(selection);
1932
+ setTimeout(() => {
1933
+ if (editor) {
1934
+ const content = domToContent(editor);
1935
+ notifyChange(content);
1936
+ }
1937
+ }, 0);
1938
+ }
1939
+ },
1940
+ outdentListItem: () => {
1941
+ const editor = editorRef.current;
1942
+ if (!editor)
1943
+ return;
1944
+ const selection = window.getSelection();
1945
+ if (selection && selection.rangeCount > 0) {
1946
+ const currentContent = domToContent(editor);
1947
+ historyRef.current.push(currentContent);
1948
+ outdentListItem(selection);
1949
+ setTimeout(() => {
1950
+ if (editor) {
1951
+ const content = domToContent(editor);
1952
+ notifyChange(content);
1953
+ }
1954
+ }, 0);
1955
+ }
1956
+ },
1744
1957
  };
1745
1958
  }, [
1746
1959
  notifyChange,
@@ -1781,46 +1994,45 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1781
1994
  const handleKeyDown = (e) => {
1782
1995
  const isModifierPressed = e.metaKey || e.ctrlKey;
1783
1996
  if (e.key === "Tab" && !isModifierPressed && !e.altKey) {
1997
+ // Immer preventDefault aufrufen (wie Lexical), damit Tab den Fokus nicht aus dem Editor entfernt
1998
+ e.preventDefault();
1999
+ e.stopPropagation();
2000
+ e.stopImmediatePropagation();
1784
2001
  const selection = window.getSelection();
1785
- const isSelectionInEditor = selection &&
1786
- selection.rangeCount > 0 &&
1787
- editor.contains(selection.getRangeAt(0).commonAncestorContainer);
1788
- const isEditorFocused = document.activeElement === editor ||
1789
- editor.contains(document.activeElement) ||
1790
- isSelectionInEditor;
1791
- if (!isEditorFocused) {
2002
+ if (!selection || selection.rangeCount === 0) {
2003
+ // Keine Selection: Tab verhindern, Fokus bleibt im Editor
1792
2004
  return;
1793
2005
  }
1794
- e.preventDefault();
1795
- e.stopPropagation();
1796
- if (isSelectionInEditor &&
1797
- selection &&
1798
- selection.rangeCount > 0) {
1799
- const range = selection.getRangeAt(0);
1800
- const container = range.commonAncestorContainer;
1801
- const listItem = container.nodeType === Node.TEXT_NODE
1802
- ? container.parentElement?.closest("li")
1803
- : container.closest("li");
1804
- if (listItem && editor.contains(listItem)) {
1805
- e.stopImmediatePropagation();
1806
- const currentContent = domToContent(editor);
1807
- historyRef.current.push(currentContent);
1808
- if (e.shiftKey) {
1809
- outdentListItem(selection);
1810
- }
1811
- else {
1812
- indentListItem(selection);
1813
- }
1814
- setTimeout(() => {
1815
- if (editor) {
1816
- const content = domToContent(editor);
1817
- notifyChange(content);
1818
- }
1819
- }, 0);
1820
- return;
2006
+ const range = selection.getRangeAt(0);
2007
+ const container = range.commonAncestorContainer;
2008
+ if (!editor.contains(container)) {
2009
+ // Container nicht im Editor: Tab verhindern
2010
+ return;
2011
+ }
2012
+ // Prüfe ob wir in einer Liste sind
2013
+ const listItem = container.nodeType === Node.TEXT_NODE
2014
+ ? container.parentElement?.closest("li")
2015
+ : container.closest("li");
2016
+ if (listItem && editor.contains(listItem)) {
2017
+ // In Liste: Indent/Outdent durchführen
2018
+ const currentContent = domToContent(editor);
2019
+ historyRef.current.push(currentContent);
2020
+ if (e.shiftKey) {
2021
+ outdentListItem(selection);
2022
+ }
2023
+ else {
2024
+ indentListItem(selection);
1821
2025
  }
2026
+ setTimeout(() => {
2027
+ if (editor) {
2028
+ const content = domToContent(editor);
2029
+ notifyChange(content);
2030
+ }
2031
+ }, 0);
2032
+ return;
1822
2033
  }
1823
- document.execCommand("insertText", false, "\t");
2034
+ // Nicht in Liste: Tab verhindern, aber kein Tab-Zeichen einfügen
2035
+ // Der Fokus bleibt im Editor (durch preventDefault)
1824
2036
  }
1825
2037
  if (isModifierPressed && e.key === "z" && !e.shiftKey) {
1826
2038
  e.preventDefault();
@@ -1835,10 +2047,10 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1835
2047
  }
1836
2048
  };
1837
2049
  editor.addEventListener("input", handleInput);
1838
- editor.addEventListener("keydown", handleKeyDown);
2050
+ editor.addEventListener("keydown", handleKeyDown, true);
1839
2051
  return () => {
1840
2052
  editor.removeEventListener("input", handleInput);
1841
- editor.removeEventListener("keydown", handleKeyDown);
2053
+ editor.removeEventListener("keydown", handleKeyDown, true);
1842
2054
  if (inputTimeout) {
1843
2055
  clearTimeout(inputTimeout);
1844
2056
  }
@@ -1914,15 +2126,76 @@ const Editor = ({ initialContent, onChange, plugins: providedPlugins, placeholde
1914
2126
  return (jsxRuntime.jsxs("div", { className: `rte-container ${className || ""}`, style: containerStyle, children: [jsxRuntime.jsx(Toolbar, { plugins: plugins, editorAPI: editorAPI, className: toolbarClassName }), jsxRuntime.jsx("div", { ref: editorRef, contentEditable: true, className: `rte-editor ${editorClassName || ""}`, "data-placeholder": placeholder, onPaste: handlePaste, suppressContentEditableWarning: true })] }));
1915
2127
  };
1916
2128
 
2129
+ const defaultHeadings = ["h1", "h2", "h3"];
2130
+ const headingLabels = {
2131
+ h1: "Überschrift 1",
2132
+ h2: "Überschrift 2",
2133
+ h3: "Überschrift 3",
2134
+ h4: "Überschrift 4",
2135
+ h5: "Überschrift 5",
2136
+ h6: "Überschrift 6",
2137
+ };
2138
+ function createHeadingsPlugin(headings = defaultHeadings) {
2139
+ const options = [
2140
+ { value: "p", label: "Normal", headingPreview: "p" },
2141
+ ...headings.map((h) => ({
2142
+ value: h,
2143
+ label: headingLabels[h] || h.toUpperCase(),
2144
+ headingPreview: h,
2145
+ })),
2146
+ ];
2147
+ return {
2148
+ name: "headings",
2149
+ type: "block",
2150
+ renderButton: (props) => {
2151
+ // Aktuelles Heading aus State Reflection
2152
+ const currentValue = props.currentValue ||
2153
+ (props.editorAPI
2154
+ ? getCurrentHeading(props.editorAPI, headings)
2155
+ : undefined);
2156
+ return (jsxRuntime.jsx(Dropdown, { icon: "mdi:format-header-1", label: "\u00DCberschrift", options: options, onSelect: (value) => {
2157
+ if (props.onSelect) {
2158
+ props.onSelect(value);
2159
+ }
2160
+ else {
2161
+ props.onClick();
2162
+ }
2163
+ }, currentValue: currentValue, disabled: props.disabled }));
2164
+ },
2165
+ getCurrentValue: (editor) => {
2166
+ return getCurrentHeading(editor, headings);
2167
+ },
2168
+ execute: (editor, value) => {
2169
+ const tag = value || "p";
2170
+ editor.executeCommand("formatBlock", `<${tag}>`);
2171
+ },
2172
+ isActive: (editor) => {
2173
+ const selection = editor.getSelection();
2174
+ if (!selection || selection.rangeCount === 0)
2175
+ return false;
2176
+ const range = selection.getRangeAt(0);
2177
+ const container = range.commonAncestorContainer;
2178
+ const element = container.nodeType === Node.TEXT_NODE
2179
+ ? container.parentElement
2180
+ : container;
2181
+ if (!element)
2182
+ return false;
2183
+ const tagName = element.tagName.toLowerCase();
2184
+ return headings.includes(tagName);
2185
+ },
2186
+ canExecute: () => true,
2187
+ };
2188
+ }
2189
+
1917
2190
  /**
1918
2191
  * Link-Plugin mit verbesserter Funktionalität
1919
2192
  */
1920
2193
  function createLinkPlugin() {
1921
2194
  return {
1922
- name: 'link',
1923
- type: 'inline',
1924
- command: 'createLink',
1925
- renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? 'rte-toolbar-button-active' : ''}`, title: "Link einf\u00FCgen", "aria-label": "Link einf\u00FCgen", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:link", width: 18, height: 18 }) })),
2195
+ name: "link",
2196
+ type: "inline",
2197
+ command: "createLink",
2198
+ renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? "rte-toolbar-button-active" : ""}`, title: "Link einf\u00FCgen", "aria-label": "Link einf\u00FCgen", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:link", width: 18, height: 18 }) })),
1926
2199
  execute: (editor) => {
1927
2200
  const selection = editor.getSelection();
1928
2201
  if (!selection || selection.rangeCount === 0)
@@ -1933,7 +2206,7 @@ function createLinkPlugin() {
1933
2206
  ? container.parentElement
1934
2207
  : container;
1935
2208
  // Prüfe ob bereits ein Link vorhanden ist
1936
- const existingLink = element?.closest('a');
2209
+ const existingLink = element?.closest("a");
1937
2210
  if (existingLink) {
1938
2211
  // Link entfernen
1939
2212
  const parent = existingLink.parentNode;
@@ -1952,9 +2225,9 @@ function createLinkPlugin() {
1952
2225
  }
1953
2226
  else {
1954
2227
  // Neuen Link einfügen
1955
- const url = prompt('URL eingeben:');
2228
+ const url = prompt("URL eingeben:");
1956
2229
  if (url) {
1957
- editor.executeCommand('createLink', url);
2230
+ editor.executeCommand("createLink", url);
1958
2231
  }
1959
2232
  }
1960
2233
  },
@@ -1969,7 +2242,7 @@ function createLinkPlugin() {
1969
2242
  : container;
1970
2243
  if (!element)
1971
2244
  return false;
1972
- return element.closest('a') !== null;
2245
+ return element.closest("a") !== null;
1973
2246
  },
1974
2247
  getCurrentValue: (editor) => {
1975
2248
  const selection = editor.getSelection();
@@ -1982,7 +2255,7 @@ function createLinkPlugin() {
1982
2255
  : container;
1983
2256
  if (!element)
1984
2257
  return undefined;
1985
- const link = element.closest('a');
2258
+ const link = element.closest("a");
1986
2259
  return link ? link.href : undefined;
1987
2260
  },
1988
2261
  canExecute: (editor) => {
@@ -1996,10 +2269,10 @@ const linkPlugin = createLinkPlugin();
1996
2269
  * Blockquote-Plugin
1997
2270
  */
1998
2271
  const blockquotePlugin = {
1999
- name: 'blockquote',
2000
- type: 'block',
2001
- command: 'formatBlock',
2002
- renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? 'rte-toolbar-button-active' : ''}`, title: "Zitat", "aria-label": "Zitat", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-quote-close", width: 18, height: 18 }) })),
2272
+ name: "blockquote",
2273
+ type: "block",
2274
+ command: "formatBlock",
2275
+ renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? "rte-toolbar-button-active" : ""}`, title: "Zitat", "aria-label": "Zitat", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-quote-close", width: 18, height: 18 }) })),
2003
2276
  execute: (editor) => {
2004
2277
  const selection = editor.getSelection();
2005
2278
  if (!selection || selection.rangeCount === 0)
@@ -2011,12 +2284,12 @@ const blockquotePlugin = {
2011
2284
  : container;
2012
2285
  if (!element)
2013
2286
  return;
2014
- const isBlockquote = element.closest('blockquote') !== null;
2287
+ const isBlockquote = element.closest("blockquote") !== null;
2015
2288
  if (isBlockquote) {
2016
- editor.executeCommand('formatBlock', '<p>');
2289
+ editor.executeCommand("formatBlock", "<p>");
2017
2290
  }
2018
2291
  else {
2019
- editor.executeCommand('formatBlock', '<blockquote>');
2292
+ editor.executeCommand("formatBlock", "<blockquote>");
2020
2293
  }
2021
2294
  },
2022
2295
  isActive: (editor) => {
@@ -2030,7 +2303,7 @@ const blockquotePlugin = {
2030
2303
  : container;
2031
2304
  if (!element)
2032
2305
  return false;
2033
- return element.closest('blockquote') !== null;
2306
+ return element.closest("blockquote") !== null;
2034
2307
  },
2035
2308
  canExecute: (editor) => {
2036
2309
  const selection = editor.getSelection();
@@ -2041,17 +2314,17 @@ const blockquotePlugin = {
2041
2314
  * Unordered List Plugin
2042
2315
  */
2043
2316
  const unorderedListPlugin = {
2044
- name: 'unorderedList',
2045
- type: 'block',
2046
- command: 'insertUnorderedList',
2047
- renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? 'rte-toolbar-button-active' : ''}`, title: "Aufz\u00E4hlungsliste", "aria-label": "Aufz\u00E4hlungsliste", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-list-bulleted", width: 18, height: 18 }) })),
2317
+ name: "unorderedList",
2318
+ type: "block",
2319
+ command: "insertUnorderedList",
2320
+ renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? "rte-toolbar-button-active" : ""}`, title: "Aufz\u00E4hlungsliste", "aria-label": "Aufz\u00E4hlungsliste", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-list-bulleted", width: 18, height: 18 }) })),
2048
2321
  execute: (editor) => {
2049
- editor.executeCommand('insertUnorderedList');
2322
+ editor.executeCommand("insertUnorderedList");
2050
2323
  },
2051
2324
  isActive: (editor) => {
2052
- if (typeof document === 'undefined')
2325
+ if (typeof document === "undefined")
2053
2326
  return false;
2054
- return document.queryCommandState('insertUnorderedList');
2327
+ return document.queryCommandState("insertUnorderedList");
2055
2328
  },
2056
2329
  canExecute: (editor) => {
2057
2330
  const selection = editor.getSelection();
@@ -2062,17 +2335,17 @@ const unorderedListPlugin = {
2062
2335
  * Ordered List Plugin
2063
2336
  */
2064
2337
  const orderedListPlugin = {
2065
- name: 'orderedList',
2066
- type: 'block',
2067
- command: 'insertOrderedList',
2068
- renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? 'rte-toolbar-button-active' : ''}`, title: "Nummerierte Liste", "aria-label": "Nummerierte Liste", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-list-numbered", width: 18, height: 18 }) })),
2338
+ name: "orderedList",
2339
+ type: "block",
2340
+ command: "insertOrderedList",
2341
+ renderButton: (props) => (jsxRuntime.jsx("button", { type: "button", onClick: props.onClick, disabled: props.disabled, className: `rte-toolbar-button ${props.isActive ? "rte-toolbar-button-active" : ""}`, title: "Nummerierte Liste", "aria-label": "Nummerierte Liste", children: jsxRuntime.jsx(IconWrapper, { icon: "mdi:format-list-numbered", width: 18, height: 18 }) })),
2069
2342
  execute: (editor) => {
2070
- editor.executeCommand('insertOrderedList');
2343
+ editor.executeCommand("insertOrderedList");
2071
2344
  },
2072
2345
  isActive: (editor) => {
2073
- if (typeof document === 'undefined')
2346
+ if (typeof document === "undefined")
2074
2347
  return false;
2075
- return document.queryCommandState('insertOrderedList');
2348
+ return document.queryCommandState("insertOrderedList");
2076
2349
  },
2077
2350
  canExecute: (editor) => {
2078
2351
  const selection = editor.getSelection();
@@ -2090,6 +2363,7 @@ exports.clearFormattingPlugin = clearFormattingPlugin;
2090
2363
  exports.contentToDOM = contentToDOM;
2091
2364
  exports.contentToHTML = contentToHTML;
2092
2365
  exports.createBackgroundColorPlugin = createBackgroundColorPlugin;
2366
+ exports.createBlockFormatPlugin = createBlockFormatPlugin;
2093
2367
  exports.createEmptyContent = createEmptyContent;
2094
2368
  exports.createFontSizePlugin = createFontSizePlugin;
2095
2369
  exports.createHeadingsPlugin = createHeadingsPlugin;
@@ -2105,10 +2379,12 @@ exports.getCurrentHeading = getCurrentHeading;
2105
2379
  exports.getCurrentTextColor = getCurrentTextColor;
2106
2380
  exports.htmlToContent = htmlToContent;
2107
2381
  exports.indentListItem = indentListItem;
2382
+ exports.indentListItemPlugin = indentListItemPlugin;
2108
2383
  exports.italicPlugin = italicPlugin;
2109
2384
  exports.linkPlugin = linkPlugin;
2110
2385
  exports.orderedListPlugin = orderedListPlugin;
2111
2386
  exports.outdentListItem = outdentListItem;
2387
+ exports.outdentListItemPlugin = outdentListItemPlugin;
2112
2388
  exports.redoPlugin = redoPlugin;
2113
2389
  exports.underlinePlugin = underlinePlugin;
2114
2390
  exports.undoPlugin = undoPlugin;