dishui 0.0.73 → 0.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,57 +1,68 @@
1
- import { useEffect as e, useRef as t, useState as n } from "react";
2
- import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
3
- import { useEditorState as o } from "@tiptap/react";
4
- import { TextSelection as s } from "@tiptap/pm/state";
1
+ import { ColorPicker as e } from "./Toolbar/ColorPicker.js";
2
+ import { FONT_FAMILIES as t, FONT_SIZES as n } from "./Toolbar/SelectDropdown.js";
3
+ import { useEffect as r, useLayoutEffect as i, useRef as a, useState as o } from "react";
4
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
5
+ import { useEditorState as u } from "@tiptap/react";
6
+ import { TextSelection as d } from "@tiptap/pm/state";
5
7
  //#region src/components/pro/RichTextEditor/BubbleToolbar.tsx
6
- var c = ({ editor: c, onAddComment: l }) => {
7
- o({
8
- editor: c,
8
+ var f = ({ editor: f, onAddComment: p }) => {
9
+ u({
10
+ editor: f,
9
11
  selector: ({ transactionNumber: e }) => e
10
12
  });
11
- let [u, d] = n(!1), [f, p] = n({
13
+ let [m, h] = o(!1), [g, _] = o({
12
14
  x: 0,
13
15
  y: 0
14
- }), m = t(null);
15
- if (e(() => {
16
- if (c.isDestroyed) return;
17
- let e = c.view.dom.ownerDocument, t = e.defaultView;
16
+ }), v = a(null);
17
+ if (r(() => {
18
+ if (f.isDestroyed) return;
19
+ let e = f.view.dom.ownerDocument, t = e.defaultView;
18
20
  if (!t) return;
19
21
  let n = null, r = () => {
20
- n !== null && t.cancelAnimationFrame(n), n = null, d(!1);
22
+ n !== null && t.cancelAnimationFrame(n), n = null, h(!1);
21
23
  }, i = () => {
22
- if (n = null, c.isDestroyed) {
24
+ if (n = null, f.isDestroyed) {
23
25
  r();
24
26
  return;
25
27
  }
26
- let { from: t, to: i } = c.state.selection;
27
- if (!c.isEditable || !(c.state.selection instanceof s) || t === i || !c.isFocused && !m.current?.contains(e.activeElement)) {
28
- d(!1);
28
+ let { from: t, to: i } = f.state.selection;
29
+ if (!f.isEditable || !(f.state.selection instanceof d) || t === i || !f.isFocused && !v.current?.contains(e.activeElement)) {
30
+ h(!1);
29
31
  return;
30
32
  }
31
- let a = c.view.coordsAtPos(t), o = c.view.coordsAtPos(i), l = c.view.dom.closest(".rte-editor-wrapper");
32
- if (!l) {
33
+ let a = f.view.coordsAtPos(t), o = f.view.coordsAtPos(i), s = f.view.dom.closest(".rte-editor-wrapper");
34
+ if (!s) {
33
35
  r();
34
36
  return;
35
37
  }
36
- let u = l.getBoundingClientRect(), f = (a.left + o.left) / 2 - u.left - l.clientLeft + l.scrollLeft, h = Math.min(a.top, o.top) - u.top - l.clientTop + l.scrollTop - 44;
37
- p({
38
- x: f,
39
- y: h
40
- }), d(!0);
38
+ let c = s.getBoundingClientRect(), l = (a.left + o.left) / 2 - c.left - s.clientLeft + s.scrollLeft, u = Math.min(a.top, o.top) - c.top - s.clientTop + s.scrollTop - 44;
39
+ _({
40
+ x: l,
41
+ y: u
42
+ }), h(!0);
41
43
  }, a = () => {
42
44
  n !== null && t.cancelAnimationFrame(n), n = t.requestAnimationFrame(i);
43
45
  }, o = ({ event: e }) => {
44
- e.relatedTarget instanceof Node && m.current?.contains(e.relatedTarget) || r();
46
+ e.relatedTarget instanceof Node && v.current?.contains(e.relatedTarget) || r();
45
47
  };
46
- return c.on("transaction", a), c.on("selectionUpdate", a), c.on("focus", a), c.on("blur", o), c.on("destroy", r), e.addEventListener("scroll", a, !0), t.addEventListener("resize", a), i(), () => {
47
- n !== null && t.cancelAnimationFrame(n), c.off("transaction", a), c.off("selectionUpdate", a), c.off("focus", a), c.off("blur", o), c.off("destroy", r), e.removeEventListener("scroll", a, !0), t.removeEventListener("resize", a);
48
+ return f.on("transaction", a), f.on("selectionUpdate", a), f.on("focus", a), f.on("blur", o), f.on("destroy", r), e.addEventListener("scroll", a, !0), t.addEventListener("resize", a), i(), () => {
49
+ n !== null && t.cancelAnimationFrame(n), f.off("transaction", a), f.off("selectionUpdate", a), f.off("focus", a), f.off("blur", o), f.off("destroy", r), e.removeEventListener("scroll", a, !0), t.removeEventListener("resize", a);
48
50
  };
49
- }, [c]), !u || c.isDestroyed || !c.isEditable) return null;
50
- let h = (e, t, n, r) => /* @__PURE__ */ i("button", {
51
+ }, [f]), i(() => {
52
+ if (!m || !v.current) return;
53
+ let e = v.current, t = e.parentElement;
54
+ if (!t) return;
55
+ let n = t.clientWidth, r = e.offsetWidth / 2, i = Math.min(r + 4, n / 2), a = Math.max(n - r - 4, n / 2), o = Math.min(Math.max(g.x, i), a);
56
+ o !== g.x && _((e) => ({
57
+ ...e,
58
+ x: o
59
+ }));
60
+ }, [m, g.x]), !m || f.isDestroyed || !f.isEditable) return null;
61
+ let y = (e, t, n, r) => /* @__PURE__ */ c("button", {
51
62
  type: "button",
52
63
  className: `rte-bubble__btn ${n ? "rte-bubble__btn--active" : ""}`,
53
64
  onClick: () => {
54
- !c.isDestroyed && c.isEditable && e();
65
+ !f.isDestroyed && f.isEditable && e();
55
66
  },
56
67
  title: t,
57
68
  "aria-label": t,
@@ -59,78 +70,148 @@ var c = ({ editor: c, onAddComment: l }) => {
59
70
  onMouseDown: (e) => e.preventDefault(),
60
71
  children: r
61
72
  });
62
- return /* @__PURE__ */ a("div", {
63
- ref: m,
73
+ return /* @__PURE__ */ l("div", {
74
+ ref: v,
64
75
  className: "rte-bubble",
65
76
  role: "group",
66
77
  "aria-label": "Selection formatting",
67
78
  onBlur: (e) => {
68
- !e.currentTarget.contains(e.relatedTarget) && !c.isFocused && d(!1);
79
+ !e.currentTarget.contains(e.relatedTarget) && !f.isFocused && h(!1);
69
80
  },
70
81
  onKeyDown: (e) => {
71
- e.key === "Escape" && (e.preventDefault(), c.commands.focus(), d(!1));
82
+ e.key === "Escape" && (e.preventDefault(), f.commands.focus(), h(!1));
72
83
  },
73
84
  style: {
74
- left: f.x,
75
- top: f.y
85
+ left: g.x,
86
+ top: g.y
76
87
  },
77
88
  children: [
78
- h(() => c.chain().focus().toggleBold().run(), "Bold", c.isActive("bold"), /* @__PURE__ */ i("strong", {
89
+ y(() => f.chain().focus().toggleBold().run(), "Bold", f.isActive("bold"), /* @__PURE__ */ c("strong", {
79
90
  style: { fontSize: 13 },
80
91
  children: "B"
81
92
  })),
82
- h(() => c.chain().focus().toggleItalic().run(), "Italic", c.isActive("italic"), /* @__PURE__ */ i("em", {
93
+ y(() => f.chain().focus().toggleItalic().run(), "Italic", f.isActive("italic"), /* @__PURE__ */ c("em", {
83
94
  style: { fontSize: 13 },
84
95
  children: "I"
85
96
  })),
86
- h(() => c.chain().focus().toggleUnderline().run(), "Underline", c.isActive("underline"), /* @__PURE__ */ i("span", {
97
+ y(() => f.chain().focus().toggleUnderline().run(), "Underline", f.isActive("underline"), /* @__PURE__ */ c("span", {
87
98
  style: {
88
99
  fontSize: 13,
89
100
  textDecoration: "underline"
90
101
  },
91
102
  children: "U"
92
103
  })),
93
- h(() => c.chain().focus().toggleStrike().run(), "Strike", c.isActive("strike"), /* @__PURE__ */ i("span", {
104
+ y(() => f.chain().focus().toggleStrike().run(), "Strike", f.isActive("strike"), /* @__PURE__ */ c("span", {
94
105
  style: {
95
106
  fontSize: 13,
96
107
  textDecoration: "line-through"
97
108
  },
98
109
  children: "S"
99
110
  })),
100
- h(() => c.chain().focus().toggleCode().run(), "Code", c.isActive("code"), /* @__PURE__ */ i("span", {
111
+ y(() => f.chain().focus().toggleCode().run(), "Code", f.isActive("code"), /* @__PURE__ */ c("span", {
101
112
  style: {
102
113
  fontSize: 11,
103
114
  fontFamily: "monospace"
104
115
  },
105
116
  children: "</>"
106
117
  })),
107
- h(() => {
108
- let e = window.prompt("URL:", c.getAttributes("link").href || "");
109
- if (e === null || c.isDestroyed || !c.isEditable) return;
110
- let t = c.chain().focus().extendMarkRange("link");
118
+ y(() => {
119
+ let e = window.prompt("URL:", f.getAttributes("link").href || "");
120
+ if (e === null || f.isDestroyed || !f.isEditable) return;
121
+ let t = f.chain().focus().extendMarkRange("link");
111
122
  e.trim() === "" ? t.unsetLink().run() : t.setLink({ href: e.trim() }).run();
112
- }, "Link", c.isActive("link"), /* @__PURE__ */ a("svg", {
123
+ }, "Link", f.isActive("link"), /* @__PURE__ */ l("svg", {
113
124
  width: "14",
114
125
  height: "14",
115
126
  viewBox: "0 0 24 24",
116
127
  fill: "none",
117
128
  stroke: "currentColor",
118
129
  strokeWidth: "2",
119
- children: [/* @__PURE__ */ i("path", { d: "M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" }), /* @__PURE__ */ i("path", { d: "M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" })]
130
+ children: [/* @__PURE__ */ c("path", { d: "M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" }), /* @__PURE__ */ c("path", { d: "M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" })]
120
131
  })),
121
- l && /* @__PURE__ */ a(r, { children: [/* @__PURE__ */ i("div", { className: "rte-bubble__divider" }), h(l, "Comment", void 0, /* @__PURE__ */ i("svg", {
132
+ /* @__PURE__ */ c("div", { className: "rte-bubble__divider" }),
133
+ /* @__PURE__ */ c(e, {
134
+ value: f.getAttributes("textStyle").color || "",
135
+ onChange: (e) => {
136
+ !f.isDestroyed && f.isEditable && (e ? f.chain().focus().setColor(e).run() : f.chain().focus().unsetColor().run());
137
+ },
138
+ title: "Text color",
139
+ buttonClassName: "rte-bubble__btn",
140
+ icon: /* @__PURE__ */ l("svg", {
141
+ width: "14",
142
+ height: "14",
143
+ viewBox: "0 0 24 24",
144
+ fill: "none",
145
+ stroke: "currentColor",
146
+ strokeWidth: "2",
147
+ strokeLinecap: "round",
148
+ strokeLinejoin: "round",
149
+ children: [
150
+ /* @__PURE__ */ c("path", { d: "M4 20h16" }),
151
+ /* @__PURE__ */ c("path", { d: "M6 16l4.5-12h1L16 16" }),
152
+ /* @__PURE__ */ c("path", { d: "M7.8 12h6.4" })
153
+ ]
154
+ })
155
+ }),
156
+ /* @__PURE__ */ c(e, {
157
+ value: f.getAttributes("highlight").color || "",
158
+ onChange: (e) => {
159
+ !f.isDestroyed && f.isEditable && (e ? f.chain().focus().toggleHighlight({ color: e }).run() : f.chain().focus().unsetHighlight().run());
160
+ },
161
+ title: "Highlight color",
162
+ buttonClassName: "rte-bubble__btn",
163
+ icon: /* @__PURE__ */ l("svg", {
164
+ width: "14",
165
+ height: "14",
166
+ viewBox: "0 0 24 24",
167
+ fill: "none",
168
+ stroke: "currentColor",
169
+ strokeWidth: "2",
170
+ strokeLinecap: "round",
171
+ strokeLinejoin: "round",
172
+ children: [/* @__PURE__ */ c("path", { d: "M12 20h9" }), /* @__PURE__ */ c("path", { d: "M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z" })]
173
+ })
174
+ }),
175
+ /* @__PURE__ */ c("div", { className: "rte-bubble__divider" }),
176
+ /* @__PURE__ */ c("select", {
177
+ className: "rte-bubble__select",
178
+ value: f.getAttributes("textStyle").fontFamily || "",
179
+ onChange: (e) => {
180
+ !f.isDestroyed && f.isEditable && (e.target.value ? f.chain().focus().setFontFamily(e.target.value).run() : f.chain().focus().unsetFontFamily().run());
181
+ },
182
+ title: "Font family",
183
+ "aria-label": "Font family",
184
+ children: t.map((e) => /* @__PURE__ */ c("option", {
185
+ value: e.value,
186
+ children: e.label
187
+ }, e.value))
188
+ }),
189
+ /* @__PURE__ */ c("select", {
190
+ className: "rte-bubble__select rte-bubble__select--size",
191
+ value: f.getAttributes("textStyle").fontSize || "",
192
+ onChange: (e) => {
193
+ !f.isDestroyed && f.isEditable && (e.target.value ? f.chain().focus().setFontSize(e.target.value).run() : f.chain().focus().unsetFontSize().run());
194
+ },
195
+ title: "Font size",
196
+ "aria-label": "Font size",
197
+ children: n.map((e) => /* @__PURE__ */ c("option", {
198
+ value: e.value,
199
+ children: e.label
200
+ }, e.value))
201
+ }),
202
+ p && /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c("div", { className: "rte-bubble__divider" }), y(p, "Comment", void 0, /* @__PURE__ */ c("svg", {
122
203
  width: "14",
123
204
  height: "14",
124
205
  viewBox: "0 0 24 24",
125
206
  fill: "none",
126
207
  stroke: "currentColor",
127
208
  strokeWidth: "2",
128
- children: /* @__PURE__ */ i("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" })
209
+ children: /* @__PURE__ */ c("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" })
129
210
  }))] })
130
211
  ]
131
212
  });
132
213
  };
133
214
  //#endregion
134
- export { c as default };
215
+ export { f as default };
135
216
 
136
217
  //# sourceMappingURL=BubbleToolbar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BubbleToolbar.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/BubbleToolbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport { TextSelection } from '@tiptap/pm/state';\n\ninterface BubbleToolbarProps {\n editor: Editor;\n onAddComment?: () => void;\n}\n\nconst BubbleToolbar: React.FC<BubbleToolbarProps> = ({ editor, onAddComment }) => {\n useEditorState({ editor, selector: ({ transactionNumber }) => transactionNumber });\n const [visible, setVisible] = useState(false);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (editor.isDestroyed) return;\n const doc = editor.view.dom.ownerDocument;\n const win = doc.defaultView;\n if (!win) return;\n let frame: number | null = null;\n const hide = () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n frame = null;\n setVisible(false);\n };\n const update = () => {\n frame = null;\n if (editor.isDestroyed) { hide(); return; }\n const { from, to } = editor.state.selection;\n if (!editor.isEditable || !(editor.state.selection instanceof TextSelection) || from === to || (!editor.isFocused && !ref.current?.contains(doc.activeElement))) {\n setVisible(false);\n return;\n }\n const coords = editor.view.coordsAtPos(from);\n const endCoords = editor.view.coordsAtPos(to);\n const wrapperEl = editor.view.dom.closest<HTMLElement>('.rte-editor-wrapper');\n if (!wrapperEl) { hide(); return; }\n const rect = wrapperEl.getBoundingClientRect();\n\n const centerX = (coords.left + endCoords.left) / 2 - rect.left - wrapperEl.clientLeft + wrapperEl.scrollLeft;\n const topY = Math.min(coords.top, endCoords.top) - rect.top - wrapperEl.clientTop + wrapperEl.scrollTop - 44;\n\n setPos({ x: centerX, y: topY });\n setVisible(true);\n };\n\n const scheduleUpdate = () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n frame = win.requestAnimationFrame(update);\n };\n const onBlur = ({ event }: { event: FocusEvent }) => {\n if (event.relatedTarget instanceof Node && ref.current?.contains(event.relatedTarget)) return;\n hide();\n };\n editor.on('transaction', scheduleUpdate);\n editor.on('selectionUpdate', scheduleUpdate);\n editor.on('focus', scheduleUpdate);\n editor.on('blur', onBlur);\n editor.on('destroy', hide);\n doc.addEventListener('scroll', scheduleUpdate, true);\n win.addEventListener('resize', scheduleUpdate);\n update();\n return () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n editor.off('transaction', scheduleUpdate);\n editor.off('selectionUpdate', scheduleUpdate);\n editor.off('focus', scheduleUpdate);\n editor.off('blur', onBlur);\n editor.off('destroy', hide);\n doc.removeEventListener('scroll', scheduleUpdate, true);\n win.removeEventListener('resize', scheduleUpdate);\n };\n }, [editor]);\n\n if (!visible || editor.isDestroyed || !editor.isEditable) return null;\n\n const btn = (onClick: () => void, title: string, isActive: boolean | undefined, children: React.ReactNode) => (\n <button\n type=\"button\"\n className={`rte-bubble__btn ${isActive ? 'rte-bubble__btn--active' : ''}`}\n onClick={() => { if (!editor.isDestroyed && editor.isEditable) onClick(); }}\n title={title}\n aria-label={title}\n aria-pressed={isActive}\n onMouseDown={(e) => e.preventDefault()}\n >\n {children}\n </button>\n );\n\n return (\n <div ref={ref} className=\"rte-bubble\" role=\"group\" aria-label=\"Selection formatting\"\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !editor.isFocused) setVisible(false);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n editor.commands.focus();\n setVisible(false);\n }\n }}\n style={{ left: pos.x, top: pos.y }}>\n {btn(() => editor.chain().focus().toggleBold().run(), 'Bold', editor.isActive('bold'),\n <strong style={{ fontSize: 13 }}>B</strong>)}\n {btn(() => editor.chain().focus().toggleItalic().run(), 'Italic', editor.isActive('italic'),\n <em style={{ fontSize: 13 }}>I</em>)}\n {btn(() => editor.chain().focus().toggleUnderline().run(), 'Underline', editor.isActive('underline'),\n <span style={{ fontSize: 13, textDecoration: 'underline' }}>U</span>)}\n {btn(() => editor.chain().focus().toggleStrike().run(), 'Strike', editor.isActive('strike'),\n <span style={{ fontSize: 13, textDecoration: 'line-through' }}>S</span>)}\n {btn(() => editor.chain().focus().toggleCode().run(), 'Code', editor.isActive('code'),\n <span style={{ fontSize: 11, fontFamily: 'monospace' }}>&lt;/&gt;</span>)}\n {btn(() => {\n const url = window.prompt('URL:', editor.getAttributes('link').href || '');\n if (url === null || editor.isDestroyed || !editor.isEditable) return;\n const chain = editor.chain().focus().extendMarkRange('link');\n if (url.trim() === '') chain.unsetLink().run();\n else chain.setLink({ href: url.trim() }).run();\n }, 'Link', editor.isActive('link'),\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\" /></svg>)}\n {onAddComment && (\n <>\n <div className=\"rte-bubble__divider\" />\n {btn(onAddComment, 'Comment', undefined,\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" /></svg>)}\n </>\n )}\n </div>\n );\n};\n\nexport default BubbleToolbar;\n"],"mappings":";;;;;AASA,IAAM,KAA+C,EAAE,WAAQ,sBAAmB;CAChF,EAAe;EAAE;EAAQ,WAAW,EAAE,2BAAwB;CAAkB,CAAC;CACjF,IAAM,CAAC,GAAS,KAAc,EAAS,EAAK,GACtC,CAAC,GAAK,KAAU,EAAS;EAAE,GAAG;EAAG,GAAG;CAAE,CAAC,GACvC,IAAM,EAAuB,IAAI;CA8DvC,IA5DA,QAAgB;EACd,IAAI,EAAO,aAAa;EACxB,IAAM,IAAM,EAAO,KAAK,IAAI,eACtB,IAAM,EAAI;EAChB,IAAI,CAAC,GAAK;EACV,IAAI,IAAuB,MACrB,UAAa;GAGjB,AAFI,MAAU,QAAM,EAAI,qBAAqB,CAAK,GAClD,IAAQ,MACR,EAAW,EAAK;EAClB,GACM,UAAe;GAEnB,IADA,IAAQ,MACJ,EAAO,aAAa;IAAE,EAAK;IAAG;GAAQ;GAC1C,IAAM,EAAE,SAAM,UAAO,EAAO,MAAM;GAClC,IAAI,CAAC,EAAO,cAAc,EAAE,EAAO,MAAM,qBAAqB,MAAkB,MAAS,KAAO,CAAC,EAAO,aAAa,CAAC,EAAI,SAAS,SAAS,EAAI,aAAa,GAAI;IAC/J,EAAW,EAAK;IAChB;GACF;GACA,IAAM,IAAS,EAAO,KAAK,YAAY,CAAI,GACrC,IAAY,EAAO,KAAK,YAAY,CAAE,GACtC,IAAY,EAAO,KAAK,IAAI,QAAqB,qBAAqB;GAC5E,IAAI,CAAC,GAAW;IAAE,EAAK;IAAG;GAAQ;GAClC,IAAM,IAAO,EAAU,sBAAsB,GAEvC,KAAW,EAAO,OAAO,EAAU,QAAQ,IAAI,EAAK,OAAO,EAAU,aAAa,EAAU,YAC5F,IAAO,KAAK,IAAI,EAAO,KAAK,EAAU,GAAG,IAAI,EAAK,MAAM,EAAU,YAAY,EAAU,YAAY;GAG1G,AADA,EAAO;IAAE,GAAG;IAAS,GAAG;GAAK,CAAC,GAC9B,EAAW,EAAI;EACjB,GAEM,UAAuB;GAE3B,AADI,MAAU,QAAM,EAAI,qBAAqB,CAAK,GAClD,IAAQ,EAAI,sBAAsB,CAAM;EAC1C,GACM,KAAU,EAAE,eAAmC;GAC/C,EAAM,yBAAyB,QAAQ,EAAI,SAAS,SAAS,EAAM,aAAa,KACpF,EAAK;EACP;EASA,OARA,EAAO,GAAG,eAAe,CAAc,GACvC,EAAO,GAAG,mBAAmB,CAAc,GAC3C,EAAO,GAAG,SAAS,CAAc,GACjC,EAAO,GAAG,QAAQ,CAAM,GACxB,EAAO,GAAG,WAAW,CAAI,GACzB,EAAI,iBAAiB,UAAU,GAAgB,EAAI,GACnD,EAAI,iBAAiB,UAAU,CAAc,GAC7C,EAAO,SACM;GAQX,AAPI,MAAU,QAAM,EAAI,qBAAqB,CAAK,GAClD,EAAO,IAAI,eAAe,CAAc,GACxC,EAAO,IAAI,mBAAmB,CAAc,GAC5C,EAAO,IAAI,SAAS,CAAc,GAClC,EAAO,IAAI,QAAQ,CAAM,GACzB,EAAO,IAAI,WAAW,CAAI,GAC1B,EAAI,oBAAoB,UAAU,GAAgB,EAAI,GACtD,EAAI,oBAAoB,UAAU,CAAc;EAClD;CACF,GAAG,CAAC,CAAM,CAAC,GAEP,CAAC,KAAW,EAAO,eAAe,CAAC,EAAO,YAAY,OAAO;CAEjE,IAAM,KAAO,GAAqB,GAAe,GAA+B,MAC9E,kBAAC,UAAD;EACE,MAAK;EACL,WAAW,mBAAmB,IAAW,4BAA4B;EACrE,eAAe;GAAE,AAAI,CAAC,EAAO,eAAe,EAAO,cAAY,EAAQ;EAAG;EACnE;EACP,cAAY;EACZ,gBAAc;EACd,cAAc,MAAM,EAAE,eAAe;EAEpC;CACK,CAAA;CAGV,OACE,kBAAC,OAAD;EAAU;EAAK,WAAU;EAAa,MAAK;EAAQ,cAAW;EAC5D,SAAS,MAAU;GACjB,AAAI,CAAC,EAAM,cAAc,SAAS,EAAM,aAAa,KAAK,CAAC,EAAO,aAAW,EAAW,EAAK;EAC/F;EACA,YAAY,MAAU;GACpB,AAAI,EAAM,QAAQ,aAChB,EAAM,eAAe,GACrB,EAAO,SAAS,MAAM,GACtB,EAAW,EAAK;EAEpB;EACA,OAAO;GAAE,MAAM,EAAI;GAAG,KAAK,EAAI;EAAE;EAXnC,UAAA;GAYG,QAAU,EAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,GAAG,QAAQ,EAAO,SAAS,MAAM,GAClF,kBAAC,UAAD;IAAQ,OAAO,EAAE,UAAU,GAAG;IAAG,UAAA;GAAS,CAAA,CAAC;GAC5C,QAAU,EAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,GAAG,UAAU,EAAO,SAAS,QAAQ,GACxF,kBAAC,MAAD;IAAI,OAAO,EAAE,UAAU,GAAG;IAAG,UAAA;GAAK,CAAA,CAAC;GACpC,QAAU,EAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,gBAAgB,CAAC,CAAC,IAAI,GAAG,aAAa,EAAO,SAAS,WAAW,GACjG,kBAAC,QAAD;IAAM,OAAO;KAAE,UAAU;KAAI,gBAAgB;IAAY;IAAG,UAAA;GAAO,CAAA,CAAC;GACrE,QAAU,EAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,GAAG,UAAU,EAAO,SAAS,QAAQ,GACxF,kBAAC,QAAD;IAAM,OAAO;KAAE,UAAU;KAAI,gBAAgB;IAAe;IAAG,UAAA;GAAO,CAAA,CAAC;GACxE,QAAU,EAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,GAAG,QAAQ,EAAO,SAAS,MAAM,GAClF,kBAAC,QAAD;IAAM,OAAO;KAAE,UAAU;KAAI,YAAY;IAAY;IAAG,UAAA;GAAe,CAAA,CAAC;GACzE,QAAU;IACT,IAAM,IAAM,OAAO,OAAO,QAAQ,EAAO,cAAc,MAAM,CAAC,CAAC,QAAQ,EAAE;IACzE,IAAI,MAAQ,QAAQ,EAAO,eAAe,CAAC,EAAO,YAAY;IAC9D,IAAM,IAAQ,EAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,gBAAgB,MAAM;IAC3D,AAAI,EAAI,KAAK,MAAM,KAAI,EAAM,UAAU,CAAC,CAAC,IAAI,IACxC,EAAM,QAAQ,EAAE,MAAM,EAAI,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI;GAC/C,GAAG,QAAQ,EAAO,SAAS,MAAM,GAC/B,kBAAC,OAAD;IAAK,OAAM;IAAK,QAAO;IAAK,SAAQ;IAAY,MAAK;IAAO,QAAO;IAAe,aAAY;IAA9F,UAAA,CAAkG,kBAAC,QAAD,EAAM,GAAE,2DAA4D,CAAA,GAAC,kBAAC,QAAD,EAAM,GAAE,4DAA6D,CAAA,CAAM;GAAC,CAAA,CAAA;GACpP,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,OAAD,EAAK,WAAU,sBAAuB,CAAA,GACrC,EAAI,GAAc,WAAW,KAAA,GAC5B,kBAAC,OAAD;IAAK,OAAM;IAAK,QAAO;IAAK,SAAQ;IAAY,MAAK;IAAO,QAAO;IAAe,aAAY;IAAI,UAAA,kBAAC,QAAD,EAAM,GAAE,2DAA4D,CAAA;GAAM,CAAA,CAAC,CAC/K,EAAA,CAAA;EAED;;AAET"}
1
+ {"version":3,"file":"BubbleToolbar.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/BubbleToolbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef } from 'react';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport { TextSelection } from '@tiptap/pm/state';\nimport { ColorPicker } from './Toolbar/ColorPicker';\nimport { FONT_FAMILIES, FONT_SIZES } from './Toolbar/SelectDropdown';\n\ninterface BubbleToolbarProps {\n editor: Editor;\n onAddComment?: () => void;\n}\n\nconst BubbleToolbar: React.FC<BubbleToolbarProps> = ({ editor, onAddComment }) => {\n useEditorState({ editor, selector: ({ transactionNumber }) => transactionNumber });\n const [visible, setVisible] = useState(false);\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (editor.isDestroyed) return;\n const doc = editor.view.dom.ownerDocument;\n const win = doc.defaultView;\n if (!win) return;\n let frame: number | null = null;\n const hide = () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n frame = null;\n setVisible(false);\n };\n const update = () => {\n frame = null;\n if (editor.isDestroyed) { hide(); return; }\n const { from, to } = editor.state.selection;\n if (!editor.isEditable || !(editor.state.selection instanceof TextSelection) || from === to || (!editor.isFocused && !ref.current?.contains(doc.activeElement))) {\n setVisible(false);\n return;\n }\n const coords = editor.view.coordsAtPos(from);\n const endCoords = editor.view.coordsAtPos(to);\n const wrapperEl = editor.view.dom.closest<HTMLElement>('.rte-editor-wrapper');\n if (!wrapperEl) { hide(); return; }\n const rect = wrapperEl.getBoundingClientRect();\n\n const centerX = (coords.left + endCoords.left) / 2 - rect.left - wrapperEl.clientLeft + wrapperEl.scrollLeft;\n const topY = Math.min(coords.top, endCoords.top) - rect.top - wrapperEl.clientTop + wrapperEl.scrollTop - 44;\n\n setPos({ x: centerX, y: topY });\n setVisible(true);\n };\n\n const scheduleUpdate = () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n frame = win.requestAnimationFrame(update);\n };\n const onBlur = ({ event }: { event: FocusEvent }) => {\n if (event.relatedTarget instanceof Node && ref.current?.contains(event.relatedTarget)) return;\n hide();\n };\n editor.on('transaction', scheduleUpdate);\n editor.on('selectionUpdate', scheduleUpdate);\n editor.on('focus', scheduleUpdate);\n editor.on('blur', onBlur);\n editor.on('destroy', hide);\n doc.addEventListener('scroll', scheduleUpdate, true);\n win.addEventListener('resize', scheduleUpdate);\n update();\n return () => {\n if (frame !== null) win.cancelAnimationFrame(frame);\n editor.off('transaction', scheduleUpdate);\n editor.off('selectionUpdate', scheduleUpdate);\n editor.off('focus', scheduleUpdate);\n editor.off('blur', onBlur);\n editor.off('destroy', hide);\n doc.removeEventListener('scroll', scheduleUpdate, true);\n win.removeEventListener('resize', scheduleUpdate);\n };\n }, [editor]);\n\n // Keep the bubble inside the wrapper horizontally: with the extra color /\n // font controls it can be wider than a phone-size editor, and transform:\n // translateX(-50%) would otherwise clip it at either edge.\n useLayoutEffect(() => {\n if (!visible || !ref.current) return;\n const el = ref.current;\n const wrapper = el.parentElement;\n if (!wrapper) return;\n const w = wrapper.clientWidth;\n const half = el.offsetWidth / 2;\n const min = Math.min(half + 4, w / 2);\n const max = Math.max(w - half - 4, w / 2);\n const clamped = Math.min(Math.max(pos.x, min), max);\n if (clamped !== pos.x) setPos((p) => ({ ...p, x: clamped }));\n }, [visible, pos.x]);\n\n if (!visible || editor.isDestroyed || !editor.isEditable) return null;\n\n const btn = (onClick: () => void, title: string, isActive: boolean | undefined, children: React.ReactNode) => (\n <button\n type=\"button\"\n className={`rte-bubble__btn ${isActive ? 'rte-bubble__btn--active' : ''}`}\n onClick={() => { if (!editor.isDestroyed && editor.isEditable) onClick(); }}\n title={title}\n aria-label={title}\n aria-pressed={isActive}\n onMouseDown={(e) => e.preventDefault()}\n >\n {children}\n </button>\n );\n\n return (\n <div ref={ref} className=\"rte-bubble\" role=\"group\" aria-label=\"Selection formatting\"\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !editor.isFocused) setVisible(false);\n }}\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n editor.commands.focus();\n setVisible(false);\n }\n }}\n style={{ left: pos.x, top: pos.y }}>\n {btn(() => editor.chain().focus().toggleBold().run(), 'Bold', editor.isActive('bold'),\n <strong style={{ fontSize: 13 }}>B</strong>)}\n {btn(() => editor.chain().focus().toggleItalic().run(), 'Italic', editor.isActive('italic'),\n <em style={{ fontSize: 13 }}>I</em>)}\n {btn(() => editor.chain().focus().toggleUnderline().run(), 'Underline', editor.isActive('underline'),\n <span style={{ fontSize: 13, textDecoration: 'underline' }}>U</span>)}\n {btn(() => editor.chain().focus().toggleStrike().run(), 'Strike', editor.isActive('strike'),\n <span style={{ fontSize: 13, textDecoration: 'line-through' }}>S</span>)}\n {btn(() => editor.chain().focus().toggleCode().run(), 'Code', editor.isActive('code'),\n <span style={{ fontSize: 11, fontFamily: 'monospace' }}>&lt;/&gt;</span>)}\n {btn(() => {\n const url = window.prompt('URL:', editor.getAttributes('link').href || '');\n if (url === null || editor.isDestroyed || !editor.isEditable) return;\n const chain = editor.chain().focus().extendMarkRange('link');\n if (url.trim() === '') chain.unsetLink().run();\n else chain.setLink({ href: url.trim() }).run();\n }, 'Link', editor.isActive('link'),\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71\" /><path d=\"M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71\" /></svg>)}\n <div className=\"rte-bubble__divider\" />\n <ColorPicker\n value={editor.getAttributes('textStyle').color || ''}\n onChange={(color) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (color) editor.chain().focus().setColor(color).run();\n else editor.chain().focus().unsetColor().run();\n }}\n title=\"Text color\"\n buttonClassName=\"rte-bubble__btn\"\n icon={\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M4 20h16\" /><path d=\"M6 16l4.5-12h1L16 16\" /><path d=\"M7.8 12h6.4\" />\n </svg>\n }\n />\n <ColorPicker\n value={editor.getAttributes('highlight').color || ''}\n onChange={(color) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (color) editor.chain().focus().toggleHighlight({ color }).run();\n else editor.chain().focus().unsetHighlight().run();\n }}\n title=\"Highlight color\"\n buttonClassName=\"rte-bubble__btn\"\n icon={\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M12 20h9\" /><path d=\"M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z\" />\n </svg>\n }\n />\n <div className=\"rte-bubble__divider\" />\n <select\n className=\"rte-bubble__select\"\n value={editor.getAttributes('textStyle').fontFamily || ''}\n onChange={(e) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (e.target.value) editor.chain().focus().setFontFamily(e.target.value).run();\n else editor.chain().focus().unsetFontFamily().run();\n }}\n title=\"Font family\"\n aria-label=\"Font family\"\n >\n {FONT_FAMILIES.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n <select\n className=\"rte-bubble__select rte-bubble__select--size\"\n value={editor.getAttributes('textStyle').fontSize || ''}\n onChange={(e) => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (e.target.value) (editor.chain().focus() as any).setFontSize(e.target.value).run();\n else (editor.chain().focus() as any).unsetFontSize().run();\n }}\n title=\"Font size\"\n aria-label=\"Font size\"\n >\n {FONT_SIZES.map((opt) => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n {onAddComment && (\n <>\n <div className=\"rte-bubble__divider\" />\n {btn(onAddComment, 'Comment', undefined,\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\"><path d=\"M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z\" /></svg>)}\n </>\n )}\n </div>\n );\n};\n\nexport default BubbleToolbar;\n"],"mappings":"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"}
@@ -190,18 +190,14 @@ var c = [
190
190
  w();
191
191
  return;
192
192
  }
193
- let r = l.view.coordsAtPos(n.to), i = e.getBoundingClientRect(), a = Math.max(8, i.left + e.clientLeft), o = Math.min(window.innerWidth - 8, i.right), s = Math.max(8, i.top + e.clientTop), c = Math.min(window.innerHeight - 8, i.bottom);
194
- if (r.bottom < s || r.top > c) {
195
- w();
196
- return;
197
- }
198
- t.style.minWidth = "0", t.style.width = `${Math.max(0, Math.min(280, o - a))}px`;
199
- let u = c - r.bottom - 4, d = r.top - s - 4, f = u < Math.min(300, t.scrollHeight) && d > u;
200
- t.style.maxHeight = `${Math.max(0, Math.min(300, f ? d : u))}px`;
201
- let p = Math.max(a, Math.min(r.left, o - t.offsetWidth)), m = f ? r.top - t.offsetHeight - 4 : r.bottom + 4;
193
+ let r = l.view.coordsAtPos(n.to), i = e.getBoundingClientRect(), a = Math.max(8, i.left + e.clientLeft), o = Math.min(window.innerWidth - 8, i.right), s = Math.max(8, i.top + e.clientTop), c = Math.min(window.innerHeight - 8, i.bottom), u = Math.min(Math.max(r.top, s), c), d = Math.min(Math.max(r.bottom, s), c);
194
+ t.style.minWidth = "0", t.style.width = `${Math.min(280, Math.max(120, o - a))}px`;
195
+ let f = c - d - 4, p = u - s - 4, m = f < Math.min(300, t.scrollHeight) && p > f;
196
+ t.style.maxHeight = `${Math.max(120, Math.min(300, m ? p : f))}px`;
197
+ let g = Math.max(a, Math.min(r.left, o - t.offsetWidth)), _ = m ? u - t.offsetHeight - 4 : d + 4;
202
198
  h({
203
- x: p - i.left - e.clientLeft + e.scrollLeft,
204
- y: m - i.top - e.clientTop + e.scrollTop
199
+ x: g - i.left - e.clientLeft + e.scrollLeft,
200
+ y: _ - i.top - e.clientTop + e.scrollTop
205
201
  });
206
202
  };
207
203
  return n(), window.addEventListener("scroll", n, !0), window.addEventListener("resize", n), l.on("transaction", n), () => {
@@ -1 +1 @@
1
- {"version":3,"file":"SlashMenu.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/SlashMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { ChainedCommands } from '@tiptap/core';\nimport { TextSelection } from '@tiptap/pm/state';\n\ninterface SlashMenuItem {\n label: string;\n icon: string;\n description: string;\n action: (chain: ChainedCommands) => ChainedCommands;\n keywords?: string[];\n}\n\nconst SLASH_ITEMS: SlashMenuItem[] = [\n { label: 'Text', icon: 'Aa', description: 'Plain text', keywords: ['paragraph', 'text', 'plain'],\n action: (e) => e.setParagraph() },\n { label: 'Heading 1', icon: 'H1', description: 'Large heading', keywords: ['h1', 'title'],\n action: (e) => e.setHeading({ level: 1 }) },\n { label: 'Heading 2', icon: 'H2', description: 'Medium heading', keywords: ['h2', 'subtitle'],\n action: (e) => e.setHeading({ level: 2 }) },\n { label: 'Heading 3', icon: 'H3', description: 'Small heading', keywords: ['h3'],\n action: (e) => e.setHeading({ level: 3 }) },\n { label: 'Bullet List', icon: '•', description: 'Unordered list', keywords: ['ul', 'bullet', 'unordered'],\n action: (e) => e.toggleBulletList() },\n { label: 'Numbered List', icon: '1.', description: 'Ordered list', keywords: ['ol', 'ordered', 'number'],\n action: (e) => e.toggleOrderedList() },\n { label: 'Task List', icon: '☑', description: 'To-do list', keywords: ['todo', 'checkbox', 'task'],\n action: (e) => e.toggleTaskList() },\n { label: 'Blockquote', icon: '\"', description: 'Quote block', keywords: ['quote', 'blockquote'],\n action: (e) => e.toggleBlockquote() },\n { label: 'Code Block', icon: '</>', description: 'Code snippet', keywords: ['code', 'pre', 'snippet'],\n action: (e) => e.setNode('codeBlock') },\n { label: 'Divider', icon: '—', description: 'Horizontal rule', keywords: ['hr', 'divider', 'separator', 'line'],\n action: (e) => e.setHorizontalRule() },\n { label: 'Table', icon: '⊞', description: 'Insert 3×3 table', keywords: ['table', 'grid'],\n action: (e) => e.insertTable({ rows: 3, cols: 3, withHeaderRow: true }) },\n { label: 'Image', icon: '🖼', description: 'Insert image by URL', keywords: ['image', 'picture', 'photo'],\n action: (e) => e},\n];\n\ninterface SlashMenuProps {\n editor: Editor;\n}\n\nconst SlashMenu: React.FC<SlashMenuProps> = ({ editor }) => {\n const [visible, setVisible] = useState(false);\n const [query, setQuery] = useState('');\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [selected, setSelected] = useState(0);\n const menuRef = useRef<HTMLDivElement>(null);\n const activeRange = useRef<{ from: number; to: number; query: string } | null>(null);\n const dismissed = useRef<string | null>(null);\n const composing = useRef(false);\n\n const getRange = useCallback(() => {\n if (editor.isDestroyed || !editor.isEditable || editor.view.composing || composing.current) return null;\n const selection = editor.state.selection;\n if (!(selection instanceof TextSelection) || !selection.empty || selection.$from.parent.type.spec.code || selection.$from.marks().some((mark) => mark.type.spec.code)) return null;\n const { $from } = selection;\n // textContent drops inline atoms and hard breaks, so its offsets are not document offsets.\n const text = $from.parent.textBetween(0, $from.parentOffset, '\\n', (node) => node.type.name === 'hardBreak' ? '\\n' : '\\ufffc');\n const match = /(?:^|\\s)\\/([^\\s/]*)$/.exec(text);\n if (!match) return null;\n return { from: $from.pos - match[1].length - 1, to: $from.pos, query: match[1] };\n }, [editor]);\n\n const filtered = query\n ? SLASH_ITEMS.filter((item) => {\n const q = query.toLowerCase();\n return item.label.toLowerCase().includes(q)\n || item.description.toLowerCase().includes(q)\n || item.keywords?.some((k) => k.includes(q));\n })\n : SLASH_ITEMS;\n\n const close = useCallback(() => {\n setVisible(false);\n setQuery('');\n const range = activeRange.current;\n if (range) dismissed.current = `${range.from}:${range.to}:${range.query}`;\n activeRange.current = null;\n setSelected(0);\n }, []);\n\n const executeItem = useCallback((item: SlashMenuItem) => {\n const range = getRange();\n const active = activeRange.current;\n if (!range || !active || range.from !== active.from || range.to !== active.to || range.query !== active.query) {\n close();\n return;\n }\n const url = item.label === 'Image' ? window.prompt('Image URL:')?.trim() : undefined;\n if (item.label === 'Image' && !url) { close(); return; }\n close();\n // Delete the trigger and insert/convert in one transaction (one undo step).\n const chain = editor.chain().focus().deleteRange(range);\n (url ? chain.setImage({ src: url }) : item.action(chain)).run();\n }, [editor, getRange, close]);\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const handleUpdate = () => {\n const range = editor.isFocused ? getRange() : null;\n if (!range) {\n activeRange.current = null;\n dismissed.current = null;\n setVisible(false);\n return;\n }\n if (dismissed.current === `${range.from}:${range.to}:${range.query}`) return;\n if (activeRange.current?.query !== range.query || activeRange.current?.from !== range.from) setSelected(0);\n activeRange.current = range;\n setQuery(range.query);\n setVisible(true);\n };\n const start = () => { composing.current = true; close(); };\n const end = () => {\n composing.current = false;\n dismissed.current = null;\n timer = setTimeout(handleUpdate, 0);\n };\n const dom = editor.view.dom;\n editor.on('transaction', handleUpdate);\n editor.on('blur', close);\n dom.addEventListener('compositionstart', start);\n dom.addEventListener('compositionend', end);\n return () => {\n clearTimeout(timer);\n editor.off('transaction', handleUpdate);\n editor.off('blur', close);\n dom.removeEventListener('compositionstart', start);\n dom.removeEventListener('compositionend', end);\n };\n }, [editor, getRange, close]);\n\n useLayoutEffect(() => {\n if (!visible || !filtered.length) return;\n const wrapper = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n const menu = menuRef.current;\n if (!wrapper || !menu) return;\n const place = () => {\n const range = getRange();\n if (!range) { close(); return; }\n const coords = editor.view.coordsAtPos(range.to);\n const rect = wrapper.getBoundingClientRect();\n const left = Math.max(8, rect.left + wrapper.clientLeft);\n const right = Math.min(window.innerWidth - 8, rect.right);\n const top = Math.max(8, rect.top + wrapper.clientTop);\n const bottom = Math.min(window.innerHeight - 8, rect.bottom);\n if (coords.bottom < top || coords.top > bottom) { close(); return; }\n menu.style.minWidth = '0';\n menu.style.width = `${Math.max(0, Math.min(280, right - left))}px`;\n const below = bottom - coords.bottom - 4;\n const above = coords.top - top - 4;\n const flip = below < Math.min(300, menu.scrollHeight) && above > below;\n menu.style.maxHeight = `${Math.max(0, Math.min(300, flip ? above : below))}px`;\n const x = Math.max(left, Math.min(coords.left, right - menu.offsetWidth));\n const y = flip ? coords.top - menu.offsetHeight - 4 : coords.bottom + 4;\n setPos({ x: x - rect.left - wrapper.clientLeft + wrapper.scrollLeft,\n y: y - rect.top - wrapper.clientTop + wrapper.scrollTop });\n };\n place();\n window.addEventListener('scroll', place, true);\n window.addEventListener('resize', place);\n editor.on('transaction', place);\n return () => {\n window.removeEventListener('scroll', place, true);\n window.removeEventListener('resize', place);\n editor.off('transaction', place);\n };\n }, [editor, visible, filtered.length, getRange, close]);\n\n useEffect(() => {\n if (!visible) return;\n const menu = menuRef.current;\n const item = menu?.children[selected] as HTMLElement | undefined;\n if (!menu || !item) return;\n if (item.offsetTop < menu.scrollTop) menu.scrollTop = item.offsetTop;\n else if (item.offsetTop + item.offsetHeight > menu.scrollTop + menu.clientHeight) {\n menu.scrollTop = item.offsetTop + item.offsetHeight - menu.clientHeight;\n }\n }, [selected, visible]);\n\n useEffect(() => {\n if (!visible) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (!editor.view.dom.contains(e.target as Node) || !editor.isFocused || e.isComposing || e.keyCode === 229 || editor.view.composing || composing.current || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return;\n if (!filtered.length && e.key !== 'Escape') return;\n if (['ArrowDown', 'ArrowUp', 'Enter', 'Escape'].includes(e.key)) e.stopImmediatePropagation();\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelected((s) => (s + 1) % filtered.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelected((s) => (s - 1 + filtered.length) % filtered.length);\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (filtered[selected]) executeItem(filtered[selected]);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n close();\n }\n };\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [editor, visible, filtered, selected, executeItem, close]);\n\n useEffect(() => {\n if (!visible) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) close();\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [visible, close]);\n\n if (!visible || filtered.length === 0) return null;\n\n return (\n <div ref={menuRef} className=\"rte-slash-menu\" role=\"menu\" aria-label=\"Insert block\" style={{ left: pos.x, top: pos.y }} onMouseDown={(e) => e.preventDefault()}>\n {filtered.map((item, i) => (\n <button\n key={item.label}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className={`rte-slash-menu__item ${i === selected ? 'rte-slash-menu__item--active' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setSelected(i)}\n >\n <span className=\"rte-slash-menu__icon\">{item.icon}</span>\n <div className=\"rte-slash-menu__text\">\n <span className=\"rte-slash-menu__label\">{item.label}</span>\n <span className=\"rte-slash-menu__desc\">{item.description}</span>\n </div>\n </button>\n ))}\n </div>\n );\n};\n\nexport default SlashMenu;\n"],"mappings":"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"}
1
+ {"version":3,"file":"SlashMenu.js","names":[],"sources":["../../../../src/components/pro/RichTextEditor/SlashMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef, useCallback } from 'react';\nimport type { Editor } from '@tiptap/react';\nimport type { ChainedCommands } from '@tiptap/core';\nimport { TextSelection } from '@tiptap/pm/state';\n\ninterface SlashMenuItem {\n label: string;\n icon: string;\n description: string;\n action: (chain: ChainedCommands) => ChainedCommands;\n keywords?: string[];\n}\n\nconst SLASH_ITEMS: SlashMenuItem[] = [\n { label: 'Text', icon: 'Aa', description: 'Plain text', keywords: ['paragraph', 'text', 'plain'],\n action: (e) => e.setParagraph() },\n { label: 'Heading 1', icon: 'H1', description: 'Large heading', keywords: ['h1', 'title'],\n action: (e) => e.setHeading({ level: 1 }) },\n { label: 'Heading 2', icon: 'H2', description: 'Medium heading', keywords: ['h2', 'subtitle'],\n action: (e) => e.setHeading({ level: 2 }) },\n { label: 'Heading 3', icon: 'H3', description: 'Small heading', keywords: ['h3'],\n action: (e) => e.setHeading({ level: 3 }) },\n { label: 'Bullet List', icon: '•', description: 'Unordered list', keywords: ['ul', 'bullet', 'unordered'],\n action: (e) => e.toggleBulletList() },\n { label: 'Numbered List', icon: '1.', description: 'Ordered list', keywords: ['ol', 'ordered', 'number'],\n action: (e) => e.toggleOrderedList() },\n { label: 'Task List', icon: '☑', description: 'To-do list', keywords: ['todo', 'checkbox', 'task'],\n action: (e) => e.toggleTaskList() },\n { label: 'Blockquote', icon: '\"', description: 'Quote block', keywords: ['quote', 'blockquote'],\n action: (e) => e.toggleBlockquote() },\n { label: 'Code Block', icon: '</>', description: 'Code snippet', keywords: ['code', 'pre', 'snippet'],\n action: (e) => e.setNode('codeBlock') },\n { label: 'Divider', icon: '—', description: 'Horizontal rule', keywords: ['hr', 'divider', 'separator', 'line'],\n action: (e) => e.setHorizontalRule() },\n { label: 'Table', icon: '⊞', description: 'Insert 3×3 table', keywords: ['table', 'grid'],\n action: (e) => e.insertTable({ rows: 3, cols: 3, withHeaderRow: true }) },\n { label: 'Image', icon: '🖼', description: 'Insert image by URL', keywords: ['image', 'picture', 'photo'],\n action: (e) => e},\n];\n\ninterface SlashMenuProps {\n editor: Editor;\n}\n\nconst SlashMenu: React.FC<SlashMenuProps> = ({ editor }) => {\n const [visible, setVisible] = useState(false);\n const [query, setQuery] = useState('');\n const [pos, setPos] = useState({ x: 0, y: 0 });\n const [selected, setSelected] = useState(0);\n const menuRef = useRef<HTMLDivElement>(null);\n const activeRange = useRef<{ from: number; to: number; query: string } | null>(null);\n const dismissed = useRef<string | null>(null);\n const composing = useRef(false);\n\n const getRange = useCallback(() => {\n if (editor.isDestroyed || !editor.isEditable || editor.view.composing || composing.current) return null;\n const selection = editor.state.selection;\n if (!(selection instanceof TextSelection) || !selection.empty || selection.$from.parent.type.spec.code || selection.$from.marks().some((mark) => mark.type.spec.code)) return null;\n const { $from } = selection;\n // textContent drops inline atoms and hard breaks, so its offsets are not document offsets.\n const text = $from.parent.textBetween(0, $from.parentOffset, '\\n', (node) => node.type.name === 'hardBreak' ? '\\n' : '\\ufffc');\n const match = /(?:^|\\s)\\/([^\\s/]*)$/.exec(text);\n if (!match) return null;\n return { from: $from.pos - match[1].length - 1, to: $from.pos, query: match[1] };\n }, [editor]);\n\n const filtered = query\n ? SLASH_ITEMS.filter((item) => {\n const q = query.toLowerCase();\n return item.label.toLowerCase().includes(q)\n || item.description.toLowerCase().includes(q)\n || item.keywords?.some((k) => k.includes(q));\n })\n : SLASH_ITEMS;\n\n const close = useCallback(() => {\n setVisible(false);\n setQuery('');\n const range = activeRange.current;\n if (range) dismissed.current = `${range.from}:${range.to}:${range.query}`;\n activeRange.current = null;\n setSelected(0);\n }, []);\n\n const executeItem = useCallback((item: SlashMenuItem) => {\n const range = getRange();\n const active = activeRange.current;\n if (!range || !active || range.from !== active.from || range.to !== active.to || range.query !== active.query) {\n close();\n return;\n }\n const url = item.label === 'Image' ? window.prompt('Image URL:')?.trim() : undefined;\n if (item.label === 'Image' && !url) { close(); return; }\n close();\n // Delete the trigger and insert/convert in one transaction (one undo step).\n const chain = editor.chain().focus().deleteRange(range);\n (url ? chain.setImage({ src: url }) : item.action(chain)).run();\n }, [editor, getRange, close]);\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const handleUpdate = () => {\n const range = editor.isFocused ? getRange() : null;\n if (!range) {\n activeRange.current = null;\n dismissed.current = null;\n setVisible(false);\n return;\n }\n if (dismissed.current === `${range.from}:${range.to}:${range.query}`) return;\n if (activeRange.current?.query !== range.query || activeRange.current?.from !== range.from) setSelected(0);\n activeRange.current = range;\n setQuery(range.query);\n setVisible(true);\n };\n const start = () => { composing.current = true; close(); };\n const end = () => {\n composing.current = false;\n dismissed.current = null;\n timer = setTimeout(handleUpdate, 0);\n };\n const dom = editor.view.dom;\n editor.on('transaction', handleUpdate);\n editor.on('blur', close);\n dom.addEventListener('compositionstart', start);\n dom.addEventListener('compositionend', end);\n return () => {\n clearTimeout(timer);\n editor.off('transaction', handleUpdate);\n editor.off('blur', close);\n dom.removeEventListener('compositionstart', start);\n dom.removeEventListener('compositionend', end);\n };\n }, [editor, getRange, close]);\n\n useLayoutEffect(() => {\n if (!visible || !filtered.length) return;\n const wrapper = editor.view.dom.closest('.rte-editor-wrapper') as HTMLElement | null;\n const menu = menuRef.current;\n if (!wrapper || !menu) return;\n const place = () => {\n const range = getRange();\n if (!range) { close(); return; }\n const coords = editor.view.coordsAtPos(range.to);\n const rect = wrapper.getBoundingClientRect();\n const left = Math.max(8, rect.left + wrapper.clientLeft);\n const right = Math.min(window.innerWidth - 8, rect.right);\n const top = Math.max(8, rect.top + wrapper.clientTop);\n const bottom = Math.min(window.innerHeight - 8, rect.bottom);\n // Clamp the anchor into the visible area instead of closing: on small /\n // scrollable (phone) containers the cursor can sit at the very edge, and\n // closing the menu makes block insertion feel broken (\" stuck \").\n const anchorTop = Math.min(Math.max(coords.top, top), bottom);\n const anchorBottom = Math.min(Math.max(coords.bottom, top), bottom);\n menu.style.minWidth = '0';\n menu.style.width = `${Math.min(280, Math.max(120, right - left))}px`;\n const below = bottom - anchorBottom - 4;\n const above = anchorTop - top - 4;\n const flip = below < Math.min(300, menu.scrollHeight) && above > below;\n // Keep a minimum visible height: a 0-height menu still hijacks Enter and\n // arrow keys, which looks like a frozen editor.\n menu.style.maxHeight = `${Math.max(120, Math.min(300, flip ? above : below))}px`;\n const x = Math.max(left, Math.min(coords.left, right - menu.offsetWidth));\n const y = flip ? anchorTop - menu.offsetHeight - 4 : anchorBottom + 4;\n setPos({ x: x - rect.left - wrapper.clientLeft + wrapper.scrollLeft,\n y: y - rect.top - wrapper.clientTop + wrapper.scrollTop });\n };\n place();\n window.addEventListener('scroll', place, true);\n window.addEventListener('resize', place);\n editor.on('transaction', place);\n return () => {\n window.removeEventListener('scroll', place, true);\n window.removeEventListener('resize', place);\n editor.off('transaction', place);\n };\n }, [editor, visible, filtered.length, getRange, close]);\n\n useEffect(() => {\n if (!visible) return;\n const menu = menuRef.current;\n const item = menu?.children[selected] as HTMLElement | undefined;\n if (!menu || !item) return;\n if (item.offsetTop < menu.scrollTop) menu.scrollTop = item.offsetTop;\n else if (item.offsetTop + item.offsetHeight > menu.scrollTop + menu.clientHeight) {\n menu.scrollTop = item.offsetTop + item.offsetHeight - menu.clientHeight;\n }\n }, [selected, visible]);\n\n useEffect(() => {\n if (!visible) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (!editor.view.dom.contains(e.target as Node) || !editor.isFocused || e.isComposing || e.keyCode === 229 || editor.view.composing || composing.current || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) return;\n if (!filtered.length && e.key !== 'Escape') return;\n if (['ArrowDown', 'ArrowUp', 'Enter', 'Escape'].includes(e.key)) e.stopImmediatePropagation();\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelected((s) => (s + 1) % filtered.length);\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelected((s) => (s - 1 + filtered.length) % filtered.length);\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (filtered[selected]) executeItem(filtered[selected]);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n close();\n }\n };\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [editor, visible, filtered, selected, executeItem, close]);\n\n useEffect(() => {\n if (!visible) return;\n const handler = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) close();\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [visible, close]);\n\n if (!visible || filtered.length === 0) return null;\n\n return (\n <div ref={menuRef} className=\"rte-slash-menu\" role=\"menu\" aria-label=\"Insert block\" style={{ left: pos.x, top: pos.y }} onMouseDown={(e) => e.preventDefault()}>\n {filtered.map((item, i) => (\n <button\n key={item.label}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={-1}\n className={`rte-slash-menu__item ${i === selected ? 'rte-slash-menu__item--active' : ''}`}\n onClick={() => executeItem(item)}\n onMouseEnter={() => setSelected(i)}\n >\n <span className=\"rte-slash-menu__icon\">{item.icon}</span>\n <div className=\"rte-slash-menu__text\">\n <span className=\"rte-slash-menu__label\">{item.label}</span>\n <span className=\"rte-slash-menu__desc\">{item.description}</span>\n </div>\n </button>\n ))}\n </div>\n );\n};\n\nexport default SlashMenu;\n"],"mappings":"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"}
@@ -4,6 +4,8 @@ interface ColorPickerProps {
4
4
  onChange: (color: string) => void;
5
5
  title?: string;
6
6
  icon: React.ReactNode;
7
+ /** Button class; defaults to the classic toolbar button. Bubble toolbar passes its own. */
8
+ buttonClassName?: string;
7
9
  }
8
10
  export declare const ColorPicker: React.FC<ColorPickerProps>;
9
11
  export {};
@@ -1,40 +1,40 @@
1
1
  import { useEffect as e, useRef as t, useState as n } from "react";
2
2
  import { jsx as r, jsxs as i } from "react/jsx-runtime";
3
3
  //#region src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx
4
- var a = /* @__PURE__ */ "#000000.#434343.#666666.#999999.#cccccc.#eeeeee.#ffffff.#ff0000.#ff4500.#ff8c00.#ffd700.#32cd32.#00bfff.#8a2be2.#ff69b4.#dc143c.#ff6347.#ffa500.#9acd32.#20b2aa.#4169e1.#9370db.#db7093.#b22222.#d2691e.#daa520.#228b22.#008b8b.#191970.#4b0082".split("."), o = ({ value: o, onChange: s, title: c, icon: l }) => {
5
- let [u, d] = n(!1), f = t(null);
4
+ var a = /* @__PURE__ */ "#000000.#434343.#666666.#999999.#cccccc.#eeeeee.#ffffff.#ff0000.#ff4500.#ff8c00.#ffd700.#32cd32.#00bfff.#8a2be2.#ff69b4.#dc143c.#ff6347.#ffa500.#9acd32.#20b2aa.#4169e1.#9370db.#db7093.#b22222.#d2691e.#daa520.#228b22.#008b8b.#191970.#4b0082".split("."), o = ({ value: o, onChange: s, title: c, icon: l, buttonClassName: u = "rte-toolbar__btn" }) => {
5
+ let [d, f] = n(!1), p = t(null);
6
6
  return e(() => {
7
7
  let e = (e) => {
8
- f.current && !f.current.contains(e.target) && d(!1);
8
+ p.current && !p.current.contains(e.target) && f(!1);
9
9
  };
10
10
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
11
11
  }, []), /* @__PURE__ */ i("div", {
12
- ref: f,
12
+ ref: p,
13
13
  className: "rte-toolbar__color-picker",
14
14
  children: [/* @__PURE__ */ i("button", {
15
15
  type: "button",
16
- className: "rte-toolbar__btn",
17
- onClick: () => d(!u),
16
+ className: u,
17
+ onClick: () => f(!d),
18
18
  title: c,
19
19
  children: [l, /* @__PURE__ */ r("span", {
20
20
  className: "rte-toolbar__color-indicator",
21
21
  style: { backgroundColor: o || "#000" }
22
22
  })]
23
- }), u && /* @__PURE__ */ i("div", {
23
+ }), d && /* @__PURE__ */ i("div", {
24
24
  className: "rte-toolbar__color-dropdown",
25
25
  children: [a.map((e) => /* @__PURE__ */ r("button", {
26
26
  type: "button",
27
27
  className: `rte-toolbar__color-swatch ${e === o ? "rte-toolbar__color-swatch--active" : ""}`,
28
28
  style: { backgroundColor: e },
29
29
  onClick: () => {
30
- s(e), d(!1);
30
+ s(e), f(!1);
31
31
  },
32
32
  title: e
33
33
  }, e)), /* @__PURE__ */ r("button", {
34
34
  type: "button",
35
35
  className: "rte-toolbar__color-clear",
36
36
  onClick: () => {
37
- s(""), d(!1);
37
+ s(""), f(!1);
38
38
  },
39
39
  children: "Clear"
40
40
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\n\ninterface ColorPickerProps {\n value: string;\n onChange: (color: string) => void;\n title?: string;\n icon: React.ReactNode;\n}\n\nconst COLORS = [\n '#000000', '#434343', '#666666', '#999999', '#cccccc', '#eeeeee', '#ffffff',\n '#ff0000', '#ff4500', '#ff8c00', '#ffd700', '#32cd32', '#00bfff', '#8a2be2',\n '#ff69b4', '#dc143c', '#ff6347', '#ffa500', '#9acd32', '#20b2aa', '#4169e1',\n '#9370db', '#db7093', '#b22222', '#d2691e', '#daa520', '#228b22', '#008b8b',\n '#191970', '#4b0082',\n];\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, title, icon }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__color-picker\">\n <button\n type=\"button\"\n className=\"rte-toolbar__btn\"\n onClick={() => setIsOpen(!isOpen)}\n title={title}\n >\n {icon}\n <span\n className=\"rte-toolbar__color-indicator\"\n style={{ backgroundColor: value || '#000' }}\n />\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__color-dropdown\">\n {COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`rte-toolbar__color-swatch ${c === value ? 'rte-toolbar__color-swatch--active' : ''}`}\n style={{ backgroundColor: c }}\n onClick={() => { onChange(c); setIsOpen(false); }}\n title={c}\n />\n ))}\n <button\n type=\"button\"\n className=\"rte-toolbar__color-clear\"\n onClick={() => { onChange(''); setIsOpen(false); }}\n >\n Clear\n </button>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;AASA,IAAM,IAAS,2QAMf,GAEa,KAA2C,EAAE,UAAO,aAAU,UAAO,cAAW;CAC3F,IAAM,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAM,EAAuB,IAAI;CAYvC,OAVA,QAAgB;EACd,IAAM,KAAW,MAAkB;GACjC,AAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAU,EAAK;EAEnB;EAEA,OADA,SAAS,iBAAiB,aAAa,CAAO,SACjC,SAAS,oBAAoB,aAAa,CAAO;CAChE,GAAG,CAAC,CAAC,GAGH,kBAAC,OAAD;EAAU;EAAK,WAAU;EAAzB,UAAA,CACE,kBAAC,UAAD;GACE,MAAK;GACL,WAAU;GACV,eAAe,EAAU,CAAC,CAAM;GACzB;GAJT,UAAA,CAMG,GACD,kBAAC,QAAD;IACE,WAAU;IACV,OAAO,EAAE,iBAAiB,KAAS,OAAO;GAC3C,CAAA,CACK;EACP,CAAA,GAAA,KACC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,EAAO,KAAK,MACX,kBAAC,UAAD;IAEE,MAAK;IACL,WAAW,6BAA6B,MAAM,IAAQ,sCAAsC;IAC5F,OAAO,EAAE,iBAAiB,EAAE;IAC5B,eAAe;KAAe,AAAb,EAAS,CAAC,GAAG,EAAU,EAAK;IAAG;IAChD,OAAO;GACR,GANM,CAMN,CACF,GACD,kBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,eAAe;KAAgB,AAAd,EAAS,EAAE,GAAG,EAAU,EAAK;IAAG;IAClD,UAAA;GAEO,CAAA,CACL;EAEJ,CAAA,CAAA;;AAET"}
1
+ {"version":3,"file":"ColorPicker.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/Toolbar/ColorPicker.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react';\n\ninterface ColorPickerProps {\n value: string;\n onChange: (color: string) => void;\n title?: string;\n icon: React.ReactNode;\n /** Button class; defaults to the classic toolbar button. Bubble toolbar passes its own. */\n buttonClassName?: string;\n}\n\nconst COLORS = [\n '#000000', '#434343', '#666666', '#999999', '#cccccc', '#eeeeee', '#ffffff',\n '#ff0000', '#ff4500', '#ff8c00', '#ffd700', '#32cd32', '#00bfff', '#8a2be2',\n '#ff69b4', '#dc143c', '#ff6347', '#ffa500', '#9acd32', '#20b2aa', '#4169e1',\n '#9370db', '#db7093', '#b22222', '#d2691e', '#daa520', '#228b22', '#008b8b',\n '#191970', '#4b0082',\n];\n\nexport const ColorPicker: React.FC<ColorPickerProps> = ({ value, onChange, title, icon, buttonClassName = 'rte-toolbar__btn' }) => {\n const [isOpen, setIsOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, []);\n\n return (\n <div ref={ref} className=\"rte-toolbar__color-picker\">\n <button\n type=\"button\"\n className={buttonClassName}\n onClick={() => setIsOpen(!isOpen)}\n title={title}\n >\n {icon}\n <span\n className=\"rte-toolbar__color-indicator\"\n style={{ backgroundColor: value || '#000' }}\n />\n </button>\n {isOpen && (\n <div className=\"rte-toolbar__color-dropdown\">\n {COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`rte-toolbar__color-swatch ${c === value ? 'rte-toolbar__color-swatch--active' : ''}`}\n style={{ backgroundColor: c }}\n onClick={() => { onChange(c); setIsOpen(false); }}\n title={c}\n />\n ))}\n <button\n type=\"button\"\n className=\"rte-toolbar__color-clear\"\n onClick={() => { onChange(''); setIsOpen(false); }}\n >\n Clear\n </button>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;AAWA,IAAM,IAAS,2QAMf,GAEa,KAA2C,EAAE,UAAO,aAAU,UAAO,SAAM,qBAAkB,yBAAyB;CACjI,IAAM,CAAC,GAAQ,KAAa,EAAS,EAAK,GACpC,IAAM,EAAuB,IAAI;CAYvC,OAVA,QAAgB;EACd,IAAM,KAAW,MAAkB;GACjC,AAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,MAAc,KACvD,EAAU,EAAK;EAEnB;EAEA,OADA,SAAS,iBAAiB,aAAa,CAAO,SACjC,SAAS,oBAAoB,aAAa,CAAO;CAChE,GAAG,CAAC,CAAC,GAGH,kBAAC,OAAD;EAAU;EAAK,WAAU;EAAzB,UAAA,CACE,kBAAC,UAAD;GACE,MAAK;GACL,WAAW;GACX,eAAe,EAAU,CAAC,CAAM;GACzB;GAJT,UAAA,CAMG,GACD,kBAAC,QAAD;IACE,WAAU;IACV,OAAO,EAAE,iBAAiB,KAAS,OAAO;GAC3C,CAAA,CACK;EACP,CAAA,GAAA,KACC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACG,EAAO,KAAK,MACX,kBAAC,UAAD;IAEE,MAAK;IACL,WAAW,6BAA6B,MAAM,IAAQ,sCAAsC;IAC5F,OAAO,EAAE,iBAAiB,EAAE;IAC5B,eAAe;KAAe,AAAb,EAAS,CAAC,GAAG,EAAU,EAAK;IAAG;IAChD,OAAO;GACR,GANM,CAMN,CACF,GACD,kBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,eAAe;KAAgB,AAAd,EAAS,EAAE,GAAG,EAAU,EAAK;IAAG;IAClD,UAAA;GAEO,CAAA,CACL;EAEJ,CAAA,CAAA;;AAET"}
@@ -210,22 +210,17 @@ var a = [
210
210
  children: [
211
211
  /* @__PURE__ */ r("rect", {
212
212
  x: "2",
213
- y: "3",
214
- width: "20",
215
- height: "18",
213
+ y: "4",
214
+ width: "13",
215
+ height: "10",
216
216
  rx: "2"
217
217
  }),
218
+ /* @__PURE__ */ r("path", { d: "M9 10h11a2 2 0 012 2v6a2 2 0 01-2 2H9a2 2 0 01-2-2v-2" }),
218
219
  /* @__PURE__ */ r("line", {
219
- x1: "2",
220
- y1: "8",
221
- x2: "22",
222
- y2: "8"
223
- }),
224
- /* @__PURE__ */ r("line", {
225
- x1: "8",
226
- y1: "3",
227
- x2: "8",
228
- y2: "8"
220
+ x1: "7",
221
+ y1: "14",
222
+ x2: "13",
223
+ y2: "14"
229
224
  })
230
225
  ]
231
226
  }), /* @__PURE__ */ r("svg", {