bridgerte 0.9.10 → 0.9.11
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/dom.cjs +1 -1
- package/dist/dom.js +1 -1
- package/dist/index-BnoAWUt3.js +296 -0
- package/dist/index-BnoAWUt3.js.map +1 -0
- package/dist/index-DZaMmHfF.cjs +36 -0
- package/dist/index-DZaMmHfF.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/index-DH5duOs3.js +0 -346
- package/dist/index-DH5duOs3.js.map +0 -1
- package/dist/index-D_3O19qd.cjs +0 -36
- package/dist/index-D_3O19qd.cjs.map +0 -1
package/dist/dom.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-B5xR6zve.cjs"),t=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-B5xR6zve.cjs"),t=require("./index-DZaMmHfF.cjs");exports.createFloatingLayer=e.createFloatingLayer;exports.createRichTextEditor=e.createRichTextEditor;exports.createWebViewBridgeRuntime=e.createWebViewBridgeRuntime;exports.createRichTextToolbar=t.createRichTextToolbar;exports.hasMeaningfulHtmlContent=t.hasMeaningfulHtmlContent;
|
|
2
2
|
//# sourceMappingURL=dom.cjs.map
|
package/dist/dom.js
CHANGED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { defaultMenuSchema as X, resolveToolbarMenu as Y } from "./native-spec.js";
|
|
2
|
+
import { g as _, d as S, e as B, r as Z, f as K, h as ee, c as te } from "./index-DNqqQycS.js";
|
|
3
|
+
const R = {
|
|
4
|
+
toolbarGroup: `
|
|
5
|
+
<svg
|
|
6
|
+
aria-hidden="true"
|
|
7
|
+
class="lucide lucide-ellipsis"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
width="18"
|
|
10
|
+
height="18"
|
|
11
|
+
viewBox="0 0 24 24"
|
|
12
|
+
fill="none"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
stroke-width="2"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
>
|
|
18
|
+
<circle cx="12" cy="12" r="1" />
|
|
19
|
+
<circle cx="19" cy="12" r="1" />
|
|
20
|
+
<circle cx="5" cy="12" r="1" />
|
|
21
|
+
</svg>
|
|
22
|
+
`,
|
|
23
|
+
chevronDown: `
|
|
24
|
+
<svg
|
|
25
|
+
aria-hidden="true"
|
|
26
|
+
class="lucide lucide-chevron-down"
|
|
27
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
28
|
+
width="12"
|
|
29
|
+
height="12"
|
|
30
|
+
viewBox="0 0 24 24"
|
|
31
|
+
fill="none"
|
|
32
|
+
stroke="currentColor"
|
|
33
|
+
stroke-width="2"
|
|
34
|
+
stroke-linecap="round"
|
|
35
|
+
stroke-linejoin="round"
|
|
36
|
+
>
|
|
37
|
+
<path d="m6 9 6 6 6-6" />
|
|
38
|
+
</svg>
|
|
39
|
+
`
|
|
40
|
+
}, U = (e) => Array.from(
|
|
41
|
+
e.querySelectorAll(".bridgerte__toolbar-group-menu-item")
|
|
42
|
+
).filter((t) => !t.disabled), O = (e, t) => {
|
|
43
|
+
const i = U(e)[t];
|
|
44
|
+
i && i.focus();
|
|
45
|
+
}, oe = (e, t, s, i, d) => {
|
|
46
|
+
var u, b;
|
|
47
|
+
const r = U(t), n = document.activeElement instanceof HTMLButtonElement ? r.indexOf(document.activeElement) : -1, p = (y) => {
|
|
48
|
+
var l;
|
|
49
|
+
if (r.length === 0) return;
|
|
50
|
+
const f = ((n >= 0 ? n : 0) + y + r.length) % r.length;
|
|
51
|
+
(l = r[f]) == null || l.focus();
|
|
52
|
+
};
|
|
53
|
+
switch (e.key) {
|
|
54
|
+
case "ArrowDown":
|
|
55
|
+
e.preventDefault(), p(1);
|
|
56
|
+
break;
|
|
57
|
+
case "ArrowUp":
|
|
58
|
+
e.preventDefault(), p(-1);
|
|
59
|
+
break;
|
|
60
|
+
case "Home":
|
|
61
|
+
e.preventDefault(), (u = r[0]) == null || u.focus();
|
|
62
|
+
break;
|
|
63
|
+
case "End":
|
|
64
|
+
e.preventDefault(), (b = r.at(-1)) == null || b.focus();
|
|
65
|
+
break;
|
|
66
|
+
case "Enter":
|
|
67
|
+
case " ":
|
|
68
|
+
document.activeElement instanceof HTMLButtonElement && (e.preventDefault(), i(document.activeElement), d(), s.focus());
|
|
69
|
+
break;
|
|
70
|
+
case "Escape":
|
|
71
|
+
e.preventDefault(), s.focus(), d();
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}, A = "button[data-bridgerte-toolbar-group-id]", re = "button[data-bridgerte-toolbar-item-id]", ne = [
|
|
75
|
+
re,
|
|
76
|
+
".bridgerte__toolbar-group-menu-item"
|
|
77
|
+
].join(","), ae = (e, t) => {
|
|
78
|
+
const s = e.map((i) => _(i, t));
|
|
79
|
+
return {
|
|
80
|
+
active: s.some((i) => i.active),
|
|
81
|
+
disabled: s.length > 0 && s.every((i) => i.disabled)
|
|
82
|
+
};
|
|
83
|
+
}, se = (e, t, s, i, d) => {
|
|
84
|
+
const r = _(t, s), n = document.createElement("button"), p = i[t.icon] ?? S[t.icon];
|
|
85
|
+
n.type = "button", n.className = "bridgerte__toolbar-button", n.disabled = r.disabled, n.dataset.active = String(r.active), n.dataset.bridgerteToolbarItemId = t.id, n.setAttribute("aria-label", t.label), n.setAttribute("aria-pressed", String(r.active)), d && (n.dataset.tooltip = t.label), B(n, p, t.label), e.append(n);
|
|
86
|
+
}, le = (e, t, s, i, d) => {
|
|
87
|
+
const r = document.createElement("button"), n = ae(t.items, s), p = t.icon ? i[t.icon] ?? S[t.icon] : R.toolbarGroup, u = document.createElement("span");
|
|
88
|
+
r.type = "button", r.className = "bridgerte__toolbar-button bridgerte__toolbar-group-button", r.disabled = n.disabled, r.dataset.active = String(n.active), r.dataset.bridgerteToolbarGroupId = t.key, r.dataset.open = "false", r.setAttribute("aria-label", t.title), r.setAttribute("aria-haspopup", "menu"), r.setAttribute("aria-expanded", "false"), r.setAttribute("aria-pressed", String(n.active)), d && (r.dataset.tooltip = t.title), B(r, p, t.title), u.className = "bridgerte__toolbar-group-indicator", u.setAttribute("aria-hidden", "true"), u.innerHTML = R.chevronDown, r.append(u), e.append(r);
|
|
89
|
+
}, ie = (e, t, s, i, d) => {
|
|
90
|
+
e.textContent = "", t.forEach((r) => {
|
|
91
|
+
if (r.type === "separator") {
|
|
92
|
+
const p = document.createElement("span");
|
|
93
|
+
p.className = "bridgerte__toolbar-separator", p.dataset.separatorId = r.key, p.setAttribute("aria-hidden", "true"), e.append(p);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (r.type === "button") {
|
|
97
|
+
se(
|
|
98
|
+
e,
|
|
99
|
+
r.item,
|
|
100
|
+
s,
|
|
101
|
+
i,
|
|
102
|
+
d
|
|
103
|
+
);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const n = document.createElement("div");
|
|
107
|
+
n.className = "bridgerte__toolbar-group", n.dataset.group = r.key, n.setAttribute("aria-label", r.title), e.append(n), le(
|
|
108
|
+
n,
|
|
109
|
+
r,
|
|
110
|
+
s,
|
|
111
|
+
i,
|
|
112
|
+
d
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
}, x = (e, t, s, i) => {
|
|
116
|
+
if (e.textContent = "", !t) {
|
|
117
|
+
e.dataset.visible = "false";
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
t.items.forEach((d) => {
|
|
121
|
+
const r = _(d, s), n = document.createElement("button"), p = i[d.icon] ?? S[d.icon], u = document.createElement("span");
|
|
122
|
+
n.type = "button", n.className = "bridgerte__menu-item bridgerte__toolbar-group-menu-item", n.disabled = r.disabled, n.dataset.active = String(r.active), n.dataset.bridgerteToolbarItemId = d.id, n.setAttribute("role", "menuitem"), n.setAttribute("aria-label", d.label), n.setAttribute("aria-pressed", String(r.active)), B(n, p, d.label), u.className = "bridgerte__toolbar-group-menu-label", u.textContent = d.label, n.append(u), e.append(n);
|
|
123
|
+
}), e.dataset.visible = "true", e.style.minWidth = `${t.button.offsetWidth}px`;
|
|
124
|
+
}, k = (e, t) => {
|
|
125
|
+
e.querySelectorAll(A).forEach((s) => {
|
|
126
|
+
const i = (t == null ? void 0 : t.groupKey) === s.dataset.bridgerteToolbarGroupId;
|
|
127
|
+
s.dataset.open = String(i), s.setAttribute("aria-expanded", String(i));
|
|
128
|
+
});
|
|
129
|
+
}, F = (e, t) => e.find((s) => s.type === "group" && s.key === t), ce = 8, de = 6, ue = () => {
|
|
130
|
+
var e;
|
|
131
|
+
return typeof window < "u" && ((e = window.matchMedia) == null ? void 0 : e.call(window, "(hover: hover) and (pointer: fine)").matches) === !0;
|
|
132
|
+
}, w = (e) => {
|
|
133
|
+
const t = e instanceof Element ? e.closest(ne) : null;
|
|
134
|
+
return t instanceof HTMLButtonElement ? t : null;
|
|
135
|
+
}, j = (e) => {
|
|
136
|
+
const t = e instanceof Element ? e.closest(A) : null;
|
|
137
|
+
return t instanceof HTMLButtonElement ? t : null;
|
|
138
|
+
};
|
|
139
|
+
function ge(e, t) {
|
|
140
|
+
const s = t.placement ?? "top", i = Z(t.menuSchema ?? X, {
|
|
141
|
+
menuLabels: t.menuLabels,
|
|
142
|
+
payloadPanelConfig: t.payloadPanelConfig
|
|
143
|
+
}), d = Y(t.toolbarConfig, i), r = d.flatMap((o) => o.type === "button" ? [o.item] : o.type === "group" ? o.items : []), n = t.icons ?? {}, p = ue(), u = document.createElement("div"), b = document.createElement("div"), y = e.closest(".bridgerte") ?? e;
|
|
144
|
+
let v = !1, f = t.editor.getCommandStates(), l = null, m = null;
|
|
145
|
+
const $ = K(e, {
|
|
146
|
+
targetSelector: [
|
|
147
|
+
"button[data-bridgerte-toolbar-item-id]",
|
|
148
|
+
"button[data-bridgerte-toolbar-group-id]"
|
|
149
|
+
].join(",")
|
|
150
|
+
}), V = K(b, {
|
|
151
|
+
targetSelector: ".bridgerte__toolbar-group-menu-item"
|
|
152
|
+
}), C = () => {
|
|
153
|
+
y.append(u), y.append(b);
|
|
154
|
+
}, T = () => {
|
|
155
|
+
m == null || m.setOpen(!1), m == null || m.destroy(), m = null;
|
|
156
|
+
}, L = () => {
|
|
157
|
+
l && (T(), m = te(l.button, b, {
|
|
158
|
+
placement: s === "bottom" ? "top-start" : "bottom-start",
|
|
159
|
+
offset: de,
|
|
160
|
+
strategy: "fixed"
|
|
161
|
+
}), m.setOpen(!0));
|
|
162
|
+
}, g = () => {
|
|
163
|
+
T(), l = null, x(b, l, f, n), k(e, l);
|
|
164
|
+
}, G = (o) => {
|
|
165
|
+
if (!v && (f = o, l && T(), ie(e, d, o, n, p), C(), l)) {
|
|
166
|
+
const a = Array.from(
|
|
167
|
+
e.querySelectorAll(A)
|
|
168
|
+
).find((Q) => Q.dataset.bridgerteToolbarGroupId === (l == null ? void 0 : l.groupKey)), c = F(d, l.groupKey);
|
|
169
|
+
l = a && c ? {
|
|
170
|
+
groupKey: l.groupKey,
|
|
171
|
+
button: a,
|
|
172
|
+
items: c.items
|
|
173
|
+
} : null, x(b, l, f, n), k(e, l), l && L();
|
|
174
|
+
}
|
|
175
|
+
}, W = () => {
|
|
176
|
+
v || G(t.editor.getCommandStates());
|
|
177
|
+
}, h = () => {
|
|
178
|
+
u.dataset.visible = "false", u.textContent = "";
|
|
179
|
+
}, z = (o) => {
|
|
180
|
+
const a = o.dataset.tooltip;
|
|
181
|
+
if (!p || !a) return;
|
|
182
|
+
const c = o.getBoundingClientRect();
|
|
183
|
+
u.textContent = a, u.dataset.visible = "true", u.style.left = `${c.left + c.width / 2}px`, u.style.top = `${c.top - ce}px`;
|
|
184
|
+
}, D = (o) => {
|
|
185
|
+
const a = w(o.target);
|
|
186
|
+
a && z(a);
|
|
187
|
+
}, M = (o) => {
|
|
188
|
+
const a = o.relatedTarget, c = w(o.target);
|
|
189
|
+
c && a instanceof Node && c.contains(a) || h();
|
|
190
|
+
}, P = (o) => {
|
|
191
|
+
if (!(o instanceof HTMLButtonElement) || o.disabled) return;
|
|
192
|
+
const a = r.find((c) => c.id === o.dataset.bridgerteToolbarItemId);
|
|
193
|
+
if (a) {
|
|
194
|
+
if (a.payloadPanel) {
|
|
195
|
+
const c = o.getBoundingClientRect();
|
|
196
|
+
t.editor.requestPayloadPanel({
|
|
197
|
+
menuId: a.id,
|
|
198
|
+
command: a.command,
|
|
199
|
+
panel: a.payloadPanel,
|
|
200
|
+
currentValues: ee(a, t.editor.getCommandStates()),
|
|
201
|
+
anchorRect: {
|
|
202
|
+
x: c.left,
|
|
203
|
+
y: c.top,
|
|
204
|
+
width: c.width,
|
|
205
|
+
height: c.height
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
t.editor.executeCommand(a.command);
|
|
211
|
+
}
|
|
212
|
+
}, H = (o, a = !1) => {
|
|
213
|
+
const c = F(
|
|
214
|
+
d,
|
|
215
|
+
o.dataset.bridgerteToolbarGroupId
|
|
216
|
+
);
|
|
217
|
+
if (!(!c || o.disabled)) {
|
|
218
|
+
if ((l == null ? void 0 : l.groupKey) === c.key) {
|
|
219
|
+
if (a) {
|
|
220
|
+
O(b, 0);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
g();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
l = {
|
|
227
|
+
groupKey: c.key,
|
|
228
|
+
button: o,
|
|
229
|
+
items: c.items
|
|
230
|
+
}, h(), x(b, l, f, n), k(e, l), L(), a && O(b, 0);
|
|
231
|
+
}
|
|
232
|
+
}, E = (o) => {
|
|
233
|
+
const a = j(o.target);
|
|
234
|
+
if (a) {
|
|
235
|
+
o.preventDefault(), o.stopPropagation(), H(a);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const c = w(o.target);
|
|
239
|
+
c && (o.preventDefault(), o.stopPropagation(), P(c), g());
|
|
240
|
+
}, I = (o) => {
|
|
241
|
+
const a = o.target;
|
|
242
|
+
a instanceof Node && (e.contains(a) || b.contains(a)) || g();
|
|
243
|
+
}, N = (o) => {
|
|
244
|
+
if (l && b.contains(document.activeElement)) {
|
|
245
|
+
oe(
|
|
246
|
+
o,
|
|
247
|
+
b,
|
|
248
|
+
l.button,
|
|
249
|
+
P,
|
|
250
|
+
g
|
|
251
|
+
);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const a = j(o.target);
|
|
255
|
+
if (a && (o.key === "Enter" || o.key === " " || o.key === "ArrowDown")) {
|
|
256
|
+
o.preventDefault(), o.stopPropagation(), H(a, !0);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
o.key === "Escape" && g();
|
|
260
|
+
};
|
|
261
|
+
e.classList.add("bridgerte__toolbar"), u.className = "bridgerte__toolbar-tooltip", u.dataset.visible = "false", b.className = "bridgerte__floating-menu bridgerte__toolbar-group-menu", b.dataset.visible = "false", b.setAttribute("role", "menu"), e.dataset.placement = s, e.setAttribute("role", "toolbar"), e.setAttribute(
|
|
262
|
+
"aria-label",
|
|
263
|
+
s === "bottom" ? "BridgeRTE tabbar" : "BridgeRTE toolbar"
|
|
264
|
+
), e.addEventListener("click", E), b.addEventListener("click", E), document.addEventListener("click", I), document.addEventListener("keydown", N), p && (e.addEventListener("mouseover", D), e.addEventListener("mouseout", M)), e.addEventListener("focusout", h), C();
|
|
265
|
+
const J = t.editor.subscribeCommandStateChange(G);
|
|
266
|
+
return {
|
|
267
|
+
update: W,
|
|
268
|
+
destroy() {
|
|
269
|
+
v || (v = !0, J(), g(), e.removeEventListener("click", E), b.removeEventListener("click", E), document.removeEventListener("click", I), document.removeEventListener("keydown", N), p && (e.removeEventListener("mouseover", D), e.removeEventListener("mouseout", M)), $(), V(), e.removeEventListener("focusout", h), u.remove(), b.remove(), e.classList.remove("bridgerte__toolbar"), delete e.dataset.placement, e.textContent = "", e.removeAttribute("role"), e.removeAttribute("aria-label"));
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
const be = /[\u200B-\u200D\uFEFF]/g, pe = [
|
|
274
|
+
"img",
|
|
275
|
+
"video",
|
|
276
|
+
"audio",
|
|
277
|
+
"iframe",
|
|
278
|
+
"table",
|
|
279
|
+
"pre",
|
|
280
|
+
"code",
|
|
281
|
+
"hr",
|
|
282
|
+
"figure",
|
|
283
|
+
"canvas",
|
|
284
|
+
"svg",
|
|
285
|
+
"math",
|
|
286
|
+
'[data-type="mention"]'
|
|
287
|
+
].join(","), q = (e) => (e == null ? void 0 : e.replace(be, "").trim()) ?? "", ve = (e) => {
|
|
288
|
+
if (!q(e)) return !1;
|
|
289
|
+
const t = document.createElement("template");
|
|
290
|
+
return t.innerHTML = e, !!(q(t.content.textContent) || t.content.querySelector(pe));
|
|
291
|
+
};
|
|
292
|
+
export {
|
|
293
|
+
ge as c,
|
|
294
|
+
ve as h
|
|
295
|
+
};
|
|
296
|
+
//# sourceMappingURL=index-BnoAWUt3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BnoAWUt3.js","sources":["../../dom/src/menuIcon/uiIcons.ts","../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/index.ts","../../dom/src/htmlContent/index.ts"],"sourcesContent":["/**\n * DOM UI chrome icon 表。\n *\n * 这里放 toolbar 收纳入口、下拉箭头这类控件自身图标。它们不属于 `MenuItem.icon`\n * 跨端 schema,也不应该进入 `defaultMenuIcons` 的 schema 对齐检查。\n */\nexport const defaultMenuUiIcons = {\n toolbarGroup: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-ellipsis\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n `,\n chevronDown: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-chevron-down\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n} as const;\n","export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons,\n defaultMenuUiIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : defaultMenuUiIcons.toolbarGroup;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.innerHTML = defaultMenuUiIcons.chevronDown;\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单直接渲染为按钮,`|` 渲染分割线。\n * 只有用户显式声明的 group 配置才生成收纳入口,避免 schema 隐式改变 DOM 结构。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n const separatorElement = document.createElement('span');\n\n separatorElement.className = 'bridgerte__toolbar-separator';\n separatorElement.dataset.separatorId = toolbarItem.key;\n separatorElement.setAttribute('aria-hidden', 'true');\n toolbarElement.append(separatorElement);\n return;\n }\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n toolbarElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n /*\n * 收纳菜单是用户在 toolbarConfig 里显式声明的结构;普通菜单不会自动生成 DOM 包裹,\n * 显示分组完全交给用户用 group 配置或 `|` 控制。\n */\n const groupElement = document.createElement('div');\n\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = toolbarItem.key;\n groupElement.setAttribute('aria-label', toolbarItem.title);\n toolbarElement.append(groupElement);\n\n renderToolbarGroupButton(\n groupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__menu-item bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions\n} from './type';\n\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText) return;\n\n const buttonRect = button.getBoundingClientRect();\n\n tooltipElement.textContent = tooltipText;\n tooltipElement.dataset.visible = 'true';\n tooltipElement.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n tooltipElement.style.top = `${buttonRect.top - toolbarTooltipOffsetPx}px`;\n };\n\n const handleTooltipTarget = (event: Event) => {\n const button = getToolbarButtonFromTarget(event.target);\n\n if (button) {\n showTooltip(button);\n }\n };\n\n const handleTooltipLeave = (event: MouseEvent) => {\n const relatedTarget = event.relatedTarget;\n const button = getToolbarButtonFromTarget(event.target);\n\n if (\n button\n && relatedTarget instanceof Node\n && button.contains(relatedTarget)\n ) return;\n\n hideTooltip();\n };\n\n const executeToolbarButton = (button: HTMLButtonElement) => {\n if (!(button instanceof HTMLButtonElement) || button.disabled) return;\n\n const menuItem = executableMenuItems.find((item) => (\n item.id === button.dataset.bridgerteToolbarItemId\n ));\n\n if (!menuItem) return;\n\n if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement, shouldFocusMenu = false) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n if (shouldFocusMenu) {\n focusToolbarGroupMenuItem(groupMenuElement, 0);\n return;\n }\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n if (shouldFocusMenu) focusToolbarGroupMenuItem(groupMenuElement, 0);\n };\n\n const handleClick = (event: MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n const target = event.target;\n\n if (\n target instanceof Node\n && (container.contains(target) || groupMenuElement.contains(target))\n ) return;\n\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (\n groupButton\n && (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown')\n ) {\n /*\n * 指针点击收纳菜单不能抢编辑器焦点;键盘从入口按钮打开时则进入菜单项,\n * 保留 PC 可访问性和方向键 roving focus。\n */\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton, true);\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__floating-menu bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('click', handleDocumentClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n","const invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\n\n/*\n * HTML 片段里这些元素没有 textContent 也应算有效内容。\n * 纯排版容器不放进来,避免 `<p><br></p>`、空列表项这类编辑器占位被误判为非空。\n */\nconst meaningfulHtmlContentSelector = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math',\n '[data-type=\"mention\"]'\n].join(',');\n\nconst normalizeHtmlText = (text: string | null | undefined): string => (\n text?.replace(invisibleTextPattern, '').trim() ?? ''\n);\n\n/**\n * 判断一段 HTML 片段是否包含可保存的富文本内容。\n *\n * 这个工具会使用浏览器 template 解析 HTML,适合只拿到 HTML 字符串的业务表单;如果已经持有\n * `EditorContent`,优先使用 core 的 `isEditorContentEmpty()`,避免额外 DOM parse。\n */\nexport const hasMeaningfulHtmlContent = (html: string): boolean => {\n if (!normalizeHtmlText(html)) return false;\n\n const template = document.createElement('template');\n\n template.innerHTML = html;\n\n return Boolean(\n normalizeHtmlText(template.content.textContent)\n || template.content.querySelector(meaningfulHtmlContentSelector)\n );\n};\n"],"names":["defaultMenuUiIcons","getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","separatorElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","canUseHoverTooltip","getToolbarButtonFromTarget","target","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","groupMenuElement","overlayHost","destroyed","latestCommandStates","groupMenuFloatingLayer","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","menuItem","getPayloadPanelCurrentValues","toggleGroupMenu","shouldFocusMenu","groupItem","handleClick","groupButton","handleDocumentClick","handleKeyDown","unsubscribe","invisibleTextPattern","meaningfulHtmlContentSelector","normalizeHtmlText","text","hasMeaningfulHtmlContent","html","template"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";const H=require("./native-spec.cjs"),m=require("./index-B5xR6zve.cjs"),N={toolbarGroup:`
|
|
2
|
+
<svg
|
|
3
|
+
aria-hidden="true"
|
|
4
|
+
class="lucide lucide-ellipsis"
|
|
5
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
6
|
+
width="18"
|
|
7
|
+
height="18"
|
|
8
|
+
viewBox="0 0 24 24"
|
|
9
|
+
fill="none"
|
|
10
|
+
stroke="currentColor"
|
|
11
|
+
stroke-width="2"
|
|
12
|
+
stroke-linecap="round"
|
|
13
|
+
stroke-linejoin="round"
|
|
14
|
+
>
|
|
15
|
+
<circle cx="12" cy="12" r="1" />
|
|
16
|
+
<circle cx="19" cy="12" r="1" />
|
|
17
|
+
<circle cx="5" cy="12" r="1" />
|
|
18
|
+
</svg>
|
|
19
|
+
`,chevronDown:`
|
|
20
|
+
<svg
|
|
21
|
+
aria-hidden="true"
|
|
22
|
+
class="lucide lucide-chevron-down"
|
|
23
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
+
width="12"
|
|
25
|
+
height="12"
|
|
26
|
+
viewBox="0 0 24 24"
|
|
27
|
+
fill="none"
|
|
28
|
+
stroke="currentColor"
|
|
29
|
+
stroke-width="2"
|
|
30
|
+
stroke-linecap="round"
|
|
31
|
+
stroke-linejoin="round"
|
|
32
|
+
>
|
|
33
|
+
<path d="m6 9 6 6 6-6" />
|
|
34
|
+
</svg>
|
|
35
|
+
`},O=e=>Array.from(e.querySelectorAll(".bridgerte__toolbar-group-menu-item")).filter(t=>!t.disabled),K=(e,t)=>{const l=O(e)[t];l&&l.focus()},J=(e,t,s,l,u)=>{var d,b;const n=O(t),r=document.activeElement instanceof HTMLButtonElement?n.indexOf(document.activeElement):-1,p=y=>{var i;if(n.length===0)return;const g=((r>=0?r:0)+y+n.length)%n.length;(i=n[g])==null||i.focus()};switch(e.key){case"ArrowDown":e.preventDefault(),p(1);break;case"ArrowUp":e.preventDefault(),p(-1);break;case"Home":e.preventDefault(),(d=n[0])==null||d.focus();break;case"End":e.preventDefault(),(b=n.at(-1))==null||b.focus();break;case"Enter":case" ":document.activeElement instanceof HTMLButtonElement&&(e.preventDefault(),l(document.activeElement),u(),s.focus());break;case"Escape":e.preventDefault(),s.focus(),u();break}},S="button[data-bridgerte-toolbar-group-id]",Q="button[data-bridgerte-toolbar-item-id]",X=[Q,".bridgerte__toolbar-group-menu-item"].join(","),Y=(e,t)=>{const s=e.map(l=>m.getMenuStateForItem(l,t));return{active:s.some(l=>l.active),disabled:s.length>0&&s.every(l=>l.disabled)}},Z=(e,t,s,l,u)=>{const n=m.getMenuStateForItem(t,s),r=document.createElement("button"),p=l[t.icon]??m.defaultMenuIcons[t.icon];r.type="button",r.className="bridgerte__toolbar-button",r.disabled=n.disabled,r.dataset.active=String(n.active),r.dataset.bridgerteToolbarItemId=t.id,r.setAttribute("aria-label",t.label),r.setAttribute("aria-pressed",String(n.active)),u&&(r.dataset.tooltip=t.label),m.appendMenuIcon(r,p,t.label),e.append(r)},ee=(e,t,s,l,u)=>{const n=document.createElement("button"),r=Y(t.items,s),p=t.icon?l[t.icon]??m.defaultMenuIcons[t.icon]:N.toolbarGroup,d=document.createElement("span");n.type="button",n.className="bridgerte__toolbar-button bridgerte__toolbar-group-button",n.disabled=r.disabled,n.dataset.active=String(r.active),n.dataset.bridgerteToolbarGroupId=t.key,n.dataset.open="false",n.setAttribute("aria-label",t.title),n.setAttribute("aria-haspopup","menu"),n.setAttribute("aria-expanded","false"),n.setAttribute("aria-pressed",String(r.active)),u&&(n.dataset.tooltip=t.title),m.appendMenuIcon(n,p,t.title),d.className="bridgerte__toolbar-group-indicator",d.setAttribute("aria-hidden","true"),d.innerHTML=N.chevronDown,n.append(d),e.append(n)},te=(e,t,s,l,u)=>{e.textContent="",t.forEach(n=>{if(n.type==="separator"){const p=document.createElement("span");p.className="bridgerte__toolbar-separator",p.dataset.separatorId=n.key,p.setAttribute("aria-hidden","true"),e.append(p);return}if(n.type==="button"){Z(e,n.item,s,l,u);return}const r=document.createElement("div");r.className="bridgerte__toolbar-group",r.dataset.group=n.key,r.setAttribute("aria-label",n.title),e.append(r),ee(r,n,s,l,u)})},k=(e,t,s,l)=>{if(e.textContent="",!t){e.dataset.visible="false";return}t.items.forEach(u=>{const n=m.getMenuStateForItem(u,s),r=document.createElement("button"),p=l[u.icon]??m.defaultMenuIcons[u.icon],d=document.createElement("span");r.type="button",r.className="bridgerte__menu-item bridgerte__toolbar-group-menu-item",r.disabled=n.disabled,r.dataset.active=String(n.active),r.dataset.bridgerteToolbarItemId=u.id,r.setAttribute("role","menuitem"),r.setAttribute("aria-label",u.label),r.setAttribute("aria-pressed",String(n.active)),m.appendMenuIcon(r,p,u.label),d.className="bridgerte__toolbar-group-menu-label",d.textContent=u.label,r.append(d),e.append(r)}),e.dataset.visible="true",e.style.minWidth=`${t.button.offsetWidth}px`},w=(e,t)=>{e.querySelectorAll(S).forEach(s=>{const l=(t==null?void 0:t.groupKey)===s.dataset.bridgerteToolbarGroupId;s.dataset.open=String(l),s.setAttribute("aria-expanded",String(l))})},R=(e,t)=>e.find(s=>s.type==="group"&&s.key===t),oe=8,ne=6,re=()=>{var e;return typeof window<"u"&&((e=window.matchMedia)==null?void 0:e.call(window,"(hover: hover) and (pointer: fine)").matches)===!0},_=e=>{const t=e instanceof Element?e.closest(X):null;return t instanceof HTMLButtonElement?t:null},F=e=>{const t=e instanceof Element?e.closest(S):null;return t instanceof HTMLButtonElement?t:null};function ae(e,t){const s=t.placement??"top",l=m.resolveMenuSchemaForDom(t.menuSchema??H.defaultMenuSchema,{menuLabels:t.menuLabels,payloadPanelConfig:t.payloadPanelConfig}),u=H.resolveToolbarMenu(t.toolbarConfig,l),n=u.flatMap(o=>o.type==="button"?[o.item]:o.type==="group"?o.items:[]),r=t.icons??{},p=re(),d=document.createElement("div"),b=document.createElement("div"),y=e.closest(".bridgerte")??e;let h=!1,g=t.editor.getCommandStates(),i=null,f=null;const j=m.bindTouchPressedState(e,{targetSelector:["button[data-bridgerte-toolbar-item-id]","button[data-bridgerte-toolbar-group-id]"].join(",")}),U=m.bindTouchPressedState(b,{targetSelector:".bridgerte__toolbar-group-menu-item"}),B=()=>{y.append(d),y.append(b)},x=()=>{f==null||f.setOpen(!1),f==null||f.destroy(),f=null},C=()=>{i&&(x(),f=m.createFloatingLayer(i.button,b,{placement:s==="bottom"?"top-start":"bottom-start",offset:ne,strategy:"fixed"}),f.setOpen(!0))},v=()=>{x(),i=null,k(b,i,g,r),w(e,i)},A=o=>{if(!h&&(g=o,i&&x(),te(e,u,o,r,p),B(),i)){const a=Array.from(e.querySelectorAll(S)).find(z=>z.dataset.bridgerteToolbarGroupId===(i==null?void 0:i.groupKey)),c=R(u,i.groupKey);i=a&&c?{groupKey:i.groupKey,button:a,items:c.items}:null,k(b,i,g,r),w(e,i),i&&C()}},$=()=>{h||A(t.editor.getCommandStates())},T=()=>{d.dataset.visible="false",d.textContent=""},V=o=>{const a=o.dataset.tooltip;if(!p||!a)return;const c=o.getBoundingClientRect();d.textContent=a,d.dataset.visible="true",d.style.left=`${c.left+c.width/2}px`,d.style.top=`${c.top-oe}px`},L=o=>{const a=_(o.target);a&&V(a)},M=o=>{const a=o.relatedTarget,c=_(o.target);c&&a instanceof Node&&c.contains(a)||T()},G=o=>{if(!(o instanceof HTMLButtonElement)||o.disabled)return;const a=n.find(c=>c.id===o.dataset.bridgerteToolbarItemId);if(a){if(a.payloadPanel){const c=o.getBoundingClientRect();t.editor.requestPayloadPanel({menuId:a.id,command:a.command,panel:a.payloadPanel,currentValues:m.getPayloadPanelCurrentValues(a,t.editor.getCommandStates()),anchorRect:{x:c.left,y:c.top,width:c.width,height:c.height}});return}t.editor.executeCommand(a.command)}},D=(o,a=!1)=>{const c=R(u,o.dataset.bridgerteToolbarGroupId);if(!(!c||o.disabled)){if((i==null?void 0:i.groupKey)===c.key){if(a){K(b,0);return}v();return}i={groupKey:c.key,button:o,items:c.items},T(),k(b,i,g,r),w(e,i),C(),a&&K(b,0)}},E=o=>{const a=F(o.target);if(a){o.preventDefault(),o.stopPropagation(),D(a);return}const c=_(o.target);c&&(o.preventDefault(),o.stopPropagation(),G(c),v())},P=o=>{const a=o.target;a instanceof Node&&(e.contains(a)||b.contains(a))||v()},I=o=>{if(i&&b.contains(document.activeElement)){J(o,b,i.button,G,v);return}const a=F(o.target);if(a&&(o.key==="Enter"||o.key===" "||o.key==="ArrowDown")){o.preventDefault(),o.stopPropagation(),D(a,!0);return}o.key==="Escape"&&v()};e.classList.add("bridgerte__toolbar"),d.className="bridgerte__toolbar-tooltip",d.dataset.visible="false",b.className="bridgerte__floating-menu bridgerte__toolbar-group-menu",b.dataset.visible="false",b.setAttribute("role","menu"),e.dataset.placement=s,e.setAttribute("role","toolbar"),e.setAttribute("aria-label",s==="bottom"?"BridgeRTE tabbar":"BridgeRTE toolbar"),e.addEventListener("click",E),b.addEventListener("click",E),document.addEventListener("click",P),document.addEventListener("keydown",I),p&&(e.addEventListener("mouseover",L),e.addEventListener("mouseout",M)),e.addEventListener("focusout",T),B();const W=t.editor.subscribeCommandStateChange(A);return{update:$,destroy(){h||(h=!0,W(),v(),e.removeEventListener("click",E),b.removeEventListener("click",E),document.removeEventListener("click",P),document.removeEventListener("keydown",I),p&&(e.removeEventListener("mouseover",L),e.removeEventListener("mouseout",M)),j(),U(),e.removeEventListener("focusout",T),d.remove(),b.remove(),e.classList.remove("bridgerte__toolbar"),delete e.dataset.placement,e.textContent="",e.removeAttribute("role"),e.removeAttribute("aria-label"))}}}const se=/[\u200B-\u200D\uFEFF]/g,ie=["img","video","audio","iframe","table","pre","code","hr","figure","canvas","svg","math",'[data-type="mention"]'].join(","),q=e=>(e==null?void 0:e.replace(se,"").trim())??"",le=e=>{if(!q(e))return!1;const t=document.createElement("template");return t.innerHTML=e,!!(q(t.content.textContent)||t.content.querySelector(ie))};exports.createRichTextToolbar=ae;exports.hasMeaningfulHtmlContent=le;
|
|
36
|
+
//# sourceMappingURL=index-DZaMmHfF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DZaMmHfF.cjs","sources":["../../dom/src/menuIcon/uiIcons.ts","../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/index.ts","../../dom/src/htmlContent/index.ts"],"sourcesContent":["/**\n * DOM UI chrome icon 表。\n *\n * 这里放 toolbar 收纳入口、下拉箭头这类控件自身图标。它们不属于 `MenuItem.icon`\n * 跨端 schema,也不应该进入 `defaultMenuIcons` 的 schema 对齐检查。\n */\nexport const defaultMenuUiIcons = {\n toolbarGroup: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-ellipsis\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n `,\n chevronDown: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-chevron-down\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n} as const;\n","export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons,\n defaultMenuUiIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : defaultMenuUiIcons.toolbarGroup;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.innerHTML = defaultMenuUiIcons.chevronDown;\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单直接渲染为按钮,`|` 渲染分割线。\n * 只有用户显式声明的 group 配置才生成收纳入口,避免 schema 隐式改变 DOM 结构。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n const separatorElement = document.createElement('span');\n\n separatorElement.className = 'bridgerte__toolbar-separator';\n separatorElement.dataset.separatorId = toolbarItem.key;\n separatorElement.setAttribute('aria-hidden', 'true');\n toolbarElement.append(separatorElement);\n return;\n }\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n toolbarElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n /*\n * 收纳菜单是用户在 toolbarConfig 里显式声明的结构;普通菜单不会自动生成 DOM 包裹,\n * 显示分组完全交给用户用 group 配置或 `|` 控制。\n */\n const groupElement = document.createElement('div');\n\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = toolbarItem.key;\n groupElement.setAttribute('aria-label', toolbarItem.title);\n toolbarElement.append(groupElement);\n\n renderToolbarGroupButton(\n groupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__menu-item bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions\n} from './type';\n\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText) return;\n\n const buttonRect = button.getBoundingClientRect();\n\n tooltipElement.textContent = tooltipText;\n tooltipElement.dataset.visible = 'true';\n tooltipElement.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n tooltipElement.style.top = `${buttonRect.top - toolbarTooltipOffsetPx}px`;\n };\n\n const handleTooltipTarget = (event: Event) => {\n const button = getToolbarButtonFromTarget(event.target);\n\n if (button) {\n showTooltip(button);\n }\n };\n\n const handleTooltipLeave = (event: MouseEvent) => {\n const relatedTarget = event.relatedTarget;\n const button = getToolbarButtonFromTarget(event.target);\n\n if (\n button\n && relatedTarget instanceof Node\n && button.contains(relatedTarget)\n ) return;\n\n hideTooltip();\n };\n\n const executeToolbarButton = (button: HTMLButtonElement) => {\n if (!(button instanceof HTMLButtonElement) || button.disabled) return;\n\n const menuItem = executableMenuItems.find((item) => (\n item.id === button.dataset.bridgerteToolbarItemId\n ));\n\n if (!menuItem) return;\n\n if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement, shouldFocusMenu = false) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n if (shouldFocusMenu) {\n focusToolbarGroupMenuItem(groupMenuElement, 0);\n return;\n }\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n if (shouldFocusMenu) focusToolbarGroupMenuItem(groupMenuElement, 0);\n };\n\n const handleClick = (event: MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n const target = event.target;\n\n if (\n target instanceof Node\n && (container.contains(target) || groupMenuElement.contains(target))\n ) return;\n\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (\n groupButton\n && (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown')\n ) {\n /*\n * 指针点击收纳菜单不能抢编辑器焦点;键盘从入口按钮打开时则进入菜单项,\n * 保留 PC 可访问性和方向键 roving focus。\n */\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton, true);\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__floating-menu bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('click', handleDocumentClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n","const invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\n\n/*\n * HTML 片段里这些元素没有 textContent 也应算有效内容。\n * 纯排版容器不放进来,避免 `<p><br></p>`、空列表项这类编辑器占位被误判为非空。\n */\nconst meaningfulHtmlContentSelector = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math',\n '[data-type=\"mention\"]'\n].join(',');\n\nconst normalizeHtmlText = (text: string | null | undefined): string => (\n text?.replace(invisibleTextPattern, '').trim() ?? ''\n);\n\n/**\n * 判断一段 HTML 片段是否包含可保存的富文本内容。\n *\n * 这个工具会使用浏览器 template 解析 HTML,适合只拿到 HTML 字符串的业务表单;如果已经持有\n * `EditorContent`,优先使用 core 的 `isEditorContentEmpty()`,避免额外 DOM parse。\n */\nexport const hasMeaningfulHtmlContent = (html: string): boolean => {\n if (!normalizeHtmlText(html)) return false;\n\n const template = document.createElement('template');\n\n template.innerHTML = html;\n\n return Boolean(\n normalizeHtmlText(template.content.textContent)\n || template.content.querySelector(meaningfulHtmlContentSelector)\n );\n};\n"],"names":["defaultMenuUiIcons","getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","separatorElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","canUseHoverTooltip","getToolbarButtonFromTarget","target","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","groupMenuElement","overlayHost","destroyed","latestCommandStates","groupMenuFloatingLayer","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","menuItem","getPayloadPanelCurrentValues","toggleGroupMenu","shouldFocusMenu","groupItem","handleClick","groupButton","handleDocumentClick","handleKeyDown","unsubscribe","invisibleTextPattern","meaningfulHtmlContentSelector","normalizeHtmlText","text","hasMeaningfulHtmlContent","html","template"],"mappings":"oFAMaA,EAAqB,CAChC,aAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAmBd,YAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAiBf,EC3CaC,EAA8BC,GACzC,MAAM,KACJA,EAAY,iBAAoC,qCAAqC,CACvF,EAAE,OAAQC,GAAW,CAACA,EAAO,QAAQ,EAG1BC,EAA4B,CAACF,EAA0BG,IAAkB,CAEpF,MAAMC,EADUL,EAA2BC,CAAW,EAC3BG,CAAK,EAE5BC,KAAuB,MAAA,CAC7B,EAEaC,EAAgC,CAC3CC,EACAN,EACAO,EACAC,EACAC,IACG,SACH,MAAMC,EAAUX,EAA2BC,CAAW,EAChDW,EAAc,SAAS,yBAAyB,kBAClDD,EAAQ,QAAQ,SAAS,aAAa,EACtC,GACEE,EAAiBC,GAAmB,OACxC,GAAIH,EAAQ,SAAW,EAAG,OAG1B,MAAMI,IADYH,GAAe,EAAIA,EAAc,GACpBE,EAASH,EAAQ,QAAUA,EAAQ,QAElEK,EAAAL,EAAQI,CAAS,IAAjB,MAAAC,EAAoB,OACtB,EAMA,OAAQT,EAAM,IAAA,CACZ,IAAK,YACHA,EAAM,eAAA,EACNM,EAAc,CAAC,EACf,MACF,IAAK,UACHN,EAAM,eAAA,EACNM,EAAc,EAAE,EAChB,MACF,IAAK,OACHN,EAAM,eAAA,GACNS,EAAAL,EAAQ,CAAC,IAAT,MAAAK,EAAY,QACZ,MACF,IAAK,MACHT,EAAM,eAAA,GACNU,EAAAN,EAAQ,GAAG,EAAE,IAAb,MAAAM,EAAgB,QAChB,MACF,IAAK,QACL,IAAK,IACC,SAAS,yBAAyB,oBACpCV,EAAM,eAAA,EACNE,EAAqB,SAAS,aAAa,EAC3CC,EAAA,EACAF,EAAa,MAAA,GAEf,MACF,IAAK,SACHD,EAAM,eAAA,EACNC,EAAa,MAAA,EACbE,EAAA,EACA,KAEA,CAEN,EC1DaQ,EAA6B,0CAC7BC,EAAwB,yCAExBC,EAAkC,CAC7CD,EACA,qCACF,EAAE,KAAK,GAAG,EAEJE,EAAoB,CAACC,EAAmBC,IAAkC,CAC9E,MAAMC,EAAaF,EAAM,IAAKG,GAASC,sBAAoBD,EAAMF,CAAa,CAAC,EAE/E,MAAO,CACL,OAAQC,EAAW,KAAMG,GAAUA,EAAM,MAAM,EAC/C,SAAUH,EAAW,OAAS,GAAKA,EAAW,MAAOG,GAAUA,EAAM,QAAQ,CAAA,CAEjF,EAEMC,EAAsB,CAC1BC,EACAJ,EACAF,EACAO,EACAC,IACG,CACH,MAAMJ,EAAQD,EAAAA,oBAAoBD,EAAMF,CAAa,EAC/CrB,EAAS,SAAS,cAAc,QAAQ,EAExC8B,EAAUF,EAAML,EAAK,IAAI,GAAKQ,EAAAA,iBAAiBR,EAAK,IAAI,EAE9DvB,EAAO,KAAO,SACdA,EAAO,UAAY,4BACnBA,EAAO,SAAWyB,EAAM,SACxBzB,EAAO,QAAQ,OAAS,OAAOyB,EAAM,MAAM,EAC3CzB,EAAO,QAAQ,uBAAyBuB,EAAK,GAC7CvB,EAAO,aAAa,aAAcuB,EAAK,KAAK,EAC5CvB,EAAO,aAAa,eAAgB,OAAOyB,EAAM,MAAM,CAAC,EACpDI,IAAe7B,EAAO,QAAQ,QAAUuB,EAAK,OAEjDS,EAAAA,eAAehC,EAAQ8B,EAASP,EAAK,KAAK,EAE1CI,EAAa,OAAO3B,CAAM,CAC5B,EAEMiC,GAA2B,CAC/BN,EACAO,EACAb,EACAO,EACAC,IACG,CACH,MAAM7B,EAAS,SAAS,cAAc,QAAQ,EACxCmC,EAAahB,EAAkBe,EAAY,MAAOb,CAAa,EAC/DS,EAAUI,EAAY,KACxBN,EAAMM,EAAY,IAAI,GAAKH,EAAAA,iBAAiBG,EAAY,IAAI,EAC5DrC,EAAmB,aACjBuC,EAAY,SAAS,cAAc,MAAM,EAE/CpC,EAAO,KAAO,SACdA,EAAO,UAAY,4DACnBA,EAAO,SAAWmC,EAAW,SAC7BnC,EAAO,QAAQ,OAAS,OAAOmC,EAAW,MAAM,EAChDnC,EAAO,QAAQ,wBAA0BkC,EAAY,IACrDlC,EAAO,QAAQ,KAAO,QACtBA,EAAO,aAAa,aAAckC,EAAY,KAAK,EACnDlC,EAAO,aAAa,gBAAiB,MAAM,EAC3CA,EAAO,aAAa,gBAAiB,OAAO,EAC5CA,EAAO,aAAa,eAAgB,OAAOmC,EAAW,MAAM,CAAC,EACzDN,IAAe7B,EAAO,QAAQ,QAAUkC,EAAY,OAExDF,EAAAA,eAAehC,EAAQ8B,EAASI,EAAY,KAAK,EAEjDE,EAAU,UAAY,qCACtBA,EAAU,aAAa,cAAe,MAAM,EAC5CA,EAAU,UAAYvC,EAAmB,YACzCG,EAAO,OAAOoC,CAAS,EACvBT,EAAa,OAAO3B,CAAM,CAC5B,EAQaqC,GAAgB,CAC3BC,EACAC,EACAlB,EACAO,EACAC,IACG,CACHS,EAAe,YAAc,GAE7BC,EAAa,QAASL,GAAgB,CACpC,GAAIA,EAAY,OAAS,YAAa,CACpC,MAAMM,EAAmB,SAAS,cAAc,MAAM,EAEtDA,EAAiB,UAAY,+BAC7BA,EAAiB,QAAQ,YAAcN,EAAY,IACnDM,EAAiB,aAAa,cAAe,MAAM,EACnDF,EAAe,OAAOE,CAAgB,EACtC,MACF,CAEA,GAAIN,EAAY,OAAS,SAAU,CACjCR,EACEY,EACAJ,EAAY,KACZb,EACAO,EACAC,CAAA,EAEF,MACF,CAMA,MAAMF,EAAe,SAAS,cAAc,KAAK,EAEjDA,EAAa,UAAY,2BACzBA,EAAa,QAAQ,MAAQO,EAAY,IACzCP,EAAa,aAAa,aAAcO,EAAY,KAAK,EACzDI,EAAe,OAAOX,CAAY,EAElCM,GACEN,EACAO,EACAb,EACAO,EACAC,CAAA,CAEJ,CAAC,CACH,EAOaY,EAAyB,CACpC1C,EACA2C,EACArB,EACAO,IACG,CAGH,GAFA7B,EAAY,YAAc,GAEtB,CAAC2C,EAAgB,CACnB3C,EAAY,QAAQ,QAAU,QAC9B,MACF,CAEA2C,EAAe,MAAM,QAASnB,GAAS,CACrC,MAAME,EAAQD,EAAAA,oBAAoBD,EAAMF,CAAa,EAC/CrB,EAAS,SAAS,cAAc,QAAQ,EACxC8B,EAAUF,EAAML,EAAK,IAAI,GAAKQ,EAAAA,iBAAiBR,EAAK,IAAI,EACxDoB,EAAe,SAAS,cAAc,MAAM,EAElD3C,EAAO,KAAO,SACdA,EAAO,UAAY,0DACnBA,EAAO,SAAWyB,EAAM,SACxBzB,EAAO,QAAQ,OAAS,OAAOyB,EAAM,MAAM,EAC3CzB,EAAO,QAAQ,uBAAyBuB,EAAK,GAC7CvB,EAAO,aAAa,OAAQ,UAAU,EACtCA,EAAO,aAAa,aAAcuB,EAAK,KAAK,EAC5CvB,EAAO,aAAa,eAAgB,OAAOyB,EAAM,MAAM,CAAC,EAExDO,EAAAA,eAAehC,EAAQ8B,EAASP,EAAK,KAAK,EAC1CoB,EAAa,UAAY,sCACzBA,EAAa,YAAcpB,EAAK,MAChCvB,EAAO,OAAO2C,CAAY,EAC1B5C,EAAY,OAAOC,CAAM,CAC3B,CAAC,EAEDD,EAAY,QAAQ,QAAU,OAC9BA,EAAY,MAAM,SAAW,GAAG2C,EAAe,OAAO,WAAW,IACnE,EAEaE,EAA8B,CACzCC,EACAH,IACG,CACHG,EAAU,iBAAoC7B,CAA0B,EAAE,QAAShB,GAAW,CAC5F,MAAM8C,GAAOJ,GAAA,YAAAA,EAAgB,YAAa1C,EAAO,QAAQ,wBAEzDA,EAAO,QAAQ,KAAO,OAAO8C,CAAI,EACjC9C,EAAO,aAAa,gBAAiB,OAAO8C,CAAI,CAAC,CACnD,CAAC,CACH,EAEaC,EAA2B,CACtCR,EACAS,IACGT,EAAa,KAAMhB,GACtBA,EAAK,OAAS,SAAWA,EAAK,MAAQyB,CACvC,ECrLKC,GAAyB,EACzBC,GAA2B,EAI3BC,GAAqB,IAAA,OACzB,cAAO,OAAW,OACbrC,EAAA,OAAO,aAAP,YAAAA,EAAA,YAAoB,sCAAsC,WAAY,IAGvEsC,EAA8BC,GAA+B,CAKjE,MAAMrD,EAASqD,aAAkB,QAC7BA,EAAO,QAA2BnC,CAA+B,EACjE,KAEJ,OAAOlB,aAAkB,kBAAoBA,EAAS,IACxD,EAEMsD,EAAmCD,GAA+B,CACtE,MAAMrD,EAASqD,aAAkB,QAC7BA,EAAO,QAA2BrC,CAA0B,EAC5D,KAEJ,OAAOhB,aAAkB,kBAAoBA,EAAS,IACxD,EAOO,SAASuD,GACdV,EACAW,EACoB,CACpB,MAAMC,EAAYD,EAAQ,WAAa,MACjCE,EAAaC,EAAAA,wBAAwBH,EAAQ,YAAcI,EAAAA,kBAAmB,CAClF,WAAYJ,EAAQ,WACpB,mBAAoBA,EAAQ,kBAAA,CAC7B,EACKjB,EAAesB,EAAAA,mBAAmBL,EAAQ,cAAeE,CAAU,EAKnEI,EAAsBvB,EAAa,QAASL,GAChDA,EAAY,OAAS,SAAW,CAACA,EAAY,IAAI,EAC7CA,EAAY,OAAS,QAAUA,EAAY,MACzC,EACP,EACKN,EAAQ4B,EAAQ,OAAS,CAAA,EAKzB3B,EAAgBsB,GAAA,EAChBY,EAAiB,SAAS,cAAc,KAAK,EAC7CC,EAAmB,SAAS,cAAc,KAAK,EAC/CC,EAAcpB,EAAU,QAAQ,YAAY,GAAKA,EACvD,IAAIqB,EAAY,GACZC,EAAsBX,EAAQ,OAAO,iBAAA,EACrCd,EAA+C,KAC/C0B,EAAuD,KAC3D,MAAMC,EAA2BC,EAAAA,sBAAsBzB,EAAW,CAChE,eAAgB,CACd,yCACA,yCAAA,EACA,KAAK,GAAG,CAAA,CACX,EACK0B,EAA6BD,EAAAA,sBAAsBN,EAAkB,CACzE,eAAgB,qCAAA,CACjB,EAEKQ,EAAuB,IAAM,CAEjCP,EAAY,OAAOF,CAAc,EACjCE,EAAY,OAAOD,CAAgB,CACrC,EAEMS,EAA8B,IAAM,CACxCL,GAAA,MAAAA,EAAwB,QAAQ,IAChCA,GAAA,MAAAA,EAAwB,UACxBA,EAAyB,IAC3B,EAEMM,EAA6B,IAAM,CAClChC,IAEL+B,EAAA,EAMAL,EAAyBO,EAAAA,oBAAoBjC,EAAe,OAAQsB,EAAkB,CACpF,UAAWP,IAAc,SAAW,YAAc,eAClD,OAAQP,GACR,SAAU,OAAA,CACX,EACDkB,EAAuB,QAAQ,EAAI,EACrC,EAEM5D,EAAiB,IAAM,CAC3BiE,EAAA,EACA/B,EAAiB,KACjBD,EAAuBuB,EAAkBtB,EAAgByB,EAAqBvC,CAAK,EACnFgB,EAA4BC,EAAWH,CAAc,CACvD,EAEMkC,EAAgBC,GAA2B,CAC/C,GAAI,CAAAX,IAEJC,EAAsBU,EAClBnC,GAAgB+B,EAAA,EACpBpC,GAAcQ,EAAWN,EAAcsC,EAAQjD,EAAOC,CAAa,EACnE2C,EAAA,EACI9B,GAAgB,CAClB,MAAMvC,EAAa,MAAM,KACvB0C,EAAU,iBAAoC7B,CAA0B,CAAA,EACxE,KAAMhB,GAAWA,EAAO,QAAQ,2BAA4B0C,GAAA,YAAAA,EAAgB,SAAQ,EAChFoC,EAAgB/B,EAAyBR,EAAcG,EAAe,QAAQ,EAEpFA,EAAiBvC,GAAc2E,EAC3B,CACA,SAAUpC,EAAe,SACzB,OAAQvC,EACR,MAAO2E,EAAc,KAAA,EAErB,KACJrC,EAAuBuB,EAAkBtB,EAAgByB,EAAqBvC,CAAK,EACnFgB,EAA4BC,EAAWH,CAAc,EACjDA,GAAgBgC,EAAA,CACtB,CACF,EAEMK,EAAS,IAAM,CACfb,GAEJU,EAAapB,EAAQ,OAAO,kBAAkB,CAChD,EAEMwB,EAAc,IAAM,CACxBjB,EAAe,QAAQ,QAAU,QACjCA,EAAe,YAAc,EAC/B,EAEMkB,EAAejF,GAA8B,CACjD,MAAMkF,EAAclF,EAAO,QAAQ,QAEnC,GAAI,CAAC6B,GAAiB,CAACqD,EAAa,OAEpC,MAAMC,EAAanF,EAAO,sBAAA,EAE1B+D,EAAe,YAAcmB,EAC7BnB,EAAe,QAAQ,QAAU,OACjCA,EAAe,MAAM,KAAO,GAAGoB,EAAW,KAAOA,EAAW,MAAQ,CAAC,KACrEpB,EAAe,MAAM,IAAM,GAAGoB,EAAW,IAAMlC,EAAsB,IACvE,EAEMmC,EAAuB/E,GAAiB,CAC5C,MAAML,EAASoD,EAA2B/C,EAAM,MAAM,EAElDL,GACFiF,EAAYjF,CAAM,CAEtB,EAEMqF,EAAsBhF,GAAsB,CAChD,MAAMiF,EAAgBjF,EAAM,cACtBL,EAASoD,EAA2B/C,EAAM,MAAM,EAGpDL,GACKsF,aAAyB,MACzBtF,EAAO,SAASsF,CAAa,GAGpCN,EAAA,CACF,EAEMzE,EAAwBP,GAA8B,CAC1D,GAAI,EAAEA,aAAkB,oBAAsBA,EAAO,SAAU,OAE/D,MAAMuF,EAAWzB,EAAoB,KAAMvC,GACzCA,EAAK,KAAOvB,EAAO,QAAQ,sBAC5B,EAED,GAAKuF,EAEL,IAAIA,EAAS,aAAc,CACzB,MAAMJ,EAAanF,EAAO,sBAAA,EAO1BwD,EAAQ,OAAO,oBAAoB,CACjC,OAAQ+B,EAAS,GACjB,QAASA,EAAS,QAClB,MAAOA,EAAS,aAChB,cAAeC,EAAAA,6BAA6BD,EAAU/B,EAAQ,OAAO,kBAAkB,EACvF,WAAY,CACV,EAAG2B,EAAW,KACd,EAAGA,EAAW,IACd,MAAOA,EAAW,MAClB,OAAQA,EAAW,MAAA,CACrB,CACD,EACD,MACF,CAEA3B,EAAQ,OAAO,eAAe+B,EAAS,OAAO,EAChD,EAEME,EAAkB,CAACzF,EAA2B0F,EAAkB,KAAU,CAC9E,MAAMC,EAAY5C,EAChBR,EACAvC,EAAO,QAAQ,uBAAA,EAGjB,GAAI,GAAC2F,GAAa3F,EAAO,UAEzB,KAAI0C,GAAA,YAAAA,EAAgB,YAAaiD,EAAU,IAAK,CAC9C,GAAID,EAAiB,CACnBzF,EAA0B+D,EAAkB,CAAC,EAC7C,MACF,CACAxD,EAAA,EACA,MACF,CAEAkC,EAAiB,CACf,SAAUiD,EAAU,IACpB,OAAA3F,EACA,MAAO2F,EAAU,KAAA,EAEnBX,EAAA,EACAvC,EAAuBuB,EAAkBtB,EAAgByB,EAAqBvC,CAAK,EACnFgB,EAA4BC,EAAWH,CAAc,EACrDgC,EAAA,EACIgB,GAAiBzF,EAA0B+D,EAAkB,CAAC,EACpE,EAEM4B,EAAevF,GAAsB,CACzC,MAAMwF,EAAcvC,EAAgCjD,EAAM,MAAM,EAChE,GAAIwF,EAAa,CACfxF,EAAM,eAAA,EACNA,EAAM,gBAAA,EACNoF,EAAgBI,CAAW,EAC3B,MACF,CAEA,MAAM7F,EAASoD,EAA2B/C,EAAM,MAAM,EACjDL,IAELK,EAAM,eAAA,EACNA,EAAM,gBAAA,EACNE,EAAqBP,CAAM,EAC3BQ,EAAA,EACF,EAEMsF,EAAuBzF,GAAsB,CACjD,MAAMgD,EAAShD,EAAM,OAGnBgD,aAAkB,OACZR,EAAU,SAASQ,CAAM,GAAKW,EAAiB,SAASX,CAAM,IAGtE7C,EAAA,CACF,EAEMuF,EAAiB1F,GAAyB,CAC9C,GAAIqC,GAAkBsB,EAAiB,SAAS,SAAS,aAAa,EAAG,CACvE5D,EACEC,EACA2D,EACAtB,EAAe,OACfnC,EACAC,CAAA,EAEF,MACF,CAEA,MAAMqF,EAAcvC,EAAgCjD,EAAM,MAAM,EAChE,GACEwF,IACMxF,EAAM,MAAQ,SAAWA,EAAM,MAAQ,KAAOA,EAAM,MAAQ,aAClE,CAKAA,EAAM,eAAA,EACNA,EAAM,gBAAA,EACNoF,EAAgBI,EAAa,EAAI,EACjC,MACF,CAEIxF,EAAM,MAAQ,UAElBG,EAAA,CACF,EAEAqC,EAAU,UAAU,IAAI,oBAAoB,EAC5CkB,EAAe,UAAY,6BAC3BA,EAAe,QAAQ,QAAU,QACjCC,EAAiB,UAAY,yDAC7BA,EAAiB,QAAQ,QAAU,QACnCA,EAAiB,aAAa,OAAQ,MAAM,EAC5CnB,EAAU,QAAQ,UAAYY,EAC9BZ,EAAU,aAAa,OAAQ,SAAS,EACxCA,EAAU,aACR,aACAY,IAAc,SAAW,mBAAqB,mBAAA,EAEhDZ,EAAU,iBAAiB,QAAS+C,CAAW,EAC/C5B,EAAiB,iBAAiB,QAAS4B,CAAW,EACtD,SAAS,iBAAiB,QAASE,CAAmB,EACtD,SAAS,iBAAiB,UAAWC,CAAa,EAC9ClE,IACFgB,EAAU,iBAAiB,YAAauC,CAAmB,EAC3DvC,EAAU,iBAAiB,WAAYwC,CAAkB,GAE3DxC,EAAU,iBAAiB,WAAYmC,CAAW,EAElDR,EAAA,EAGA,MAAMwB,EAAcxC,EAAQ,OAAO,4BAA4BoB,CAAY,EAE3E,MAAO,CACL,OAAAG,EACA,SAAU,CACJb,IAEJA,EAAY,GACZ8B,EAAA,EACAxF,EAAA,EACAqC,EAAU,oBAAoB,QAAS+C,CAAW,EAClD5B,EAAiB,oBAAoB,QAAS4B,CAAW,EACzD,SAAS,oBAAoB,QAASE,CAAmB,EACzD,SAAS,oBAAoB,UAAWC,CAAa,EACjDlE,IACFgB,EAAU,oBAAoB,YAAauC,CAAmB,EAC9DvC,EAAU,oBAAoB,WAAYwC,CAAkB,GAE9DhB,EAAA,EACAE,EAAA,EACA1B,EAAU,oBAAoB,WAAYmC,CAAW,EACrDjB,EAAe,OAAA,EACfC,EAAiB,OAAA,EACjBnB,EAAU,UAAU,OAAO,oBAAoB,EAC/C,OAAOA,EAAU,QAAQ,UACzBA,EAAU,YAAc,GACxBA,EAAU,gBAAgB,MAAM,EAChCA,EAAU,gBAAgB,YAAY,EACxC,CAAA,CAEJ,CCzYA,MAAMoD,GAAuB,yBAMvBC,GAAgC,CACpC,MACA,QACA,QACA,SACA,QACA,MACA,OACA,KACA,SACA,SACA,MACA,OACA,uBACF,EAAE,KAAK,GAAG,EAEJC,EAAqBC,IACzBA,GAAA,YAAAA,EAAM,QAAQH,GAAsB,IAAI,SAAU,GASvCI,GAA4BC,GAA0B,CACjE,GAAI,CAACH,EAAkBG,CAAI,EAAG,MAAO,GAErC,MAAMC,EAAW,SAAS,cAAc,UAAU,EAElD,OAAAA,EAAS,UAAYD,EAEd,GACLH,EAAkBI,EAAS,QAAQ,WAAW,GAC3CA,EAAS,QAAQ,cAAcL,EAA6B,EAEnE"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./index-GaS65GL0.cjs"),a=require("./bridge.cjs"),e=require("./native-spec.cjs"),n=require("./index-B5xR6zve.cjs"),o=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./index-GaS65GL0.cjs"),a=require("./bridge.cjs"),e=require("./native-spec.cjs"),n=require("./index-B5xR6zve.cjs"),o=require("./index-DZaMmHfF.cjs"),r=require("./core.cjs"),i=require("./index-DF8OhKI4.cjs");exports.BRIDGERTE_CONTENT_VERSION=t.BRIDGERTE_CONTENT_VERSION;exports.BRIDGERTE_TABLE_INSERT_MAX_COLS=t.BRIDGERTE_TABLE_INSERT_MAX_COLS;exports.BRIDGERTE_TABLE_INSERT_MAX_ROWS=t.BRIDGERTE_TABLE_INSERT_MAX_ROWS;exports.BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS=a.BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS;exports.BRIDGE_HEIGHT_CHANGE_THROTTLE_MS=a.BRIDGE_HEIGHT_CHANGE_THROTTLE_MS;exports.defaultBridgeEventTiming=a.defaultBridgeEventTiming;exports.isBridgeMessage=a.isBridgeMessage;exports.codeBlockLanguagePanel=e.codeBlockLanguagePanel;exports.codeBlockLanguagePayloadPanel=e.codeBlockLanguagePayloadPanel;exports.createDisabledCommandStates=e.createDisabledCommandStates;exports.defaultMenuSchema=e.defaultMenuSchema;exports.defaultToolbarConfig=e.defaultToolbarConfig;exports.getCommandStateMatchValue=e.getCommandStateMatchValue;exports.isCommandStateForCommand=e.isCommandStateForCommand;exports.isMenuItemCommandState=e.isMenuItemCommandState;exports.resolveToolbarMenu=e.resolveToolbarMenu;exports.tableHeaderMenuItems=e.tableHeaderMenuItems;exports.createFloatingLayer=n.createFloatingLayer;exports.createRichTextEditor=n.createRichTextEditor;exports.createWebViewBridgeRuntime=n.createWebViewBridgeRuntime;exports.createRichTextToolbar=o.createRichTextToolbar;exports.hasMeaningfulHtmlContent=o.hasMeaningfulHtmlContent;exports.isEditorContentEmpty=r.isEditorContentEmpty;exports.resolvePayloadPanelSchema=i.resolvePayloadPanelSchema;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { B as t, a as o, b as r } from "./index-CuNKUHed.js";
|
|
|
2
2
|
import { BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS as n, BRIDGE_HEIGHT_CHANGE_THROTTLE_MS as E, defaultBridgeEventTiming as l, isBridgeMessage as s } from "./bridge.js";
|
|
3
3
|
import { codeBlockLanguagePanel as d, codeBlockLanguagePayloadPanel as i, createDisabledCommandStates as _, defaultMenuSchema as c, defaultToolbarConfig as R, getCommandStateMatchValue as B, isCommandStateForCommand as C, isMenuItemCommandState as g, resolveToolbarMenu as S, tableHeaderMenuItems as f } from "./native-spec.js";
|
|
4
4
|
import { c as I, a as M, b as N } from "./index-DNqqQycS.js";
|
|
5
|
-
import { c as b, h as p } from "./index-
|
|
5
|
+
import { c as b, h as p } from "./index-BnoAWUt3.js";
|
|
6
6
|
import { isEditorContentEmpty as h } from "./core.js";
|
|
7
7
|
import { r as H } from "./index-sbZNOcCB.js";
|
|
8
8
|
export {
|
package/package.json
CHANGED
package/dist/index-DH5duOs3.js
DELETED
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
import { defaultMenuSchema as pt, resolveToolbarMenu as mt } from "./native-spec.js";
|
|
2
|
-
import { g as N, d as X, e as Y, r as ft, f as Z, h as gt, c as ht } from "./index-DNqqQycS.js";
|
|
3
|
-
const tt = {
|
|
4
|
-
toolbarGroup: `
|
|
5
|
-
<svg
|
|
6
|
-
aria-hidden="true"
|
|
7
|
-
class="lucide lucide-ellipsis"
|
|
8
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
-
width="18"
|
|
10
|
-
height="18"
|
|
11
|
-
viewBox="0 0 24 24"
|
|
12
|
-
fill="none"
|
|
13
|
-
stroke="currentColor"
|
|
14
|
-
stroke-width="2"
|
|
15
|
-
stroke-linecap="round"
|
|
16
|
-
stroke-linejoin="round"
|
|
17
|
-
>
|
|
18
|
-
<circle cx="12" cy="12" r="1" />
|
|
19
|
-
<circle cx="19" cy="12" r="1" />
|
|
20
|
-
<circle cx="5" cy="12" r="1" />
|
|
21
|
-
</svg>
|
|
22
|
-
`,
|
|
23
|
-
chevronDown: `
|
|
24
|
-
<svg
|
|
25
|
-
aria-hidden="true"
|
|
26
|
-
class="lucide lucide-chevron-down"
|
|
27
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
28
|
-
width="12"
|
|
29
|
-
height="12"
|
|
30
|
-
viewBox="0 0 24 24"
|
|
31
|
-
fill="none"
|
|
32
|
-
stroke="currentColor"
|
|
33
|
-
stroke-width="2"
|
|
34
|
-
stroke-linecap="round"
|
|
35
|
-
stroke-linejoin="round"
|
|
36
|
-
>
|
|
37
|
-
<path d="m6 9 6 6 6-6" />
|
|
38
|
-
</svg>
|
|
39
|
-
`
|
|
40
|
-
}, rt = (t) => Array.from(
|
|
41
|
-
t.querySelectorAll(".bridgerte__toolbar-group-menu-item")
|
|
42
|
-
).filter((o) => !o.disabled), et = (t, o) => {
|
|
43
|
-
const u = rt(t)[o];
|
|
44
|
-
u && u.focus();
|
|
45
|
-
}, vt = (t, o, l, u, c) => {
|
|
46
|
-
var d, b;
|
|
47
|
-
const r = rt(o), a = document.activeElement instanceof HTMLButtonElement ? r.indexOf(document.activeElement) : -1, p = (y) => {
|
|
48
|
-
var i;
|
|
49
|
-
if (r.length === 0) return;
|
|
50
|
-
const h = ((a >= 0 ? a : 0) + y + r.length) % r.length;
|
|
51
|
-
(i = r[h]) == null || i.focus();
|
|
52
|
-
};
|
|
53
|
-
switch (t.key) {
|
|
54
|
-
case "ArrowDown":
|
|
55
|
-
t.preventDefault(), p(1);
|
|
56
|
-
break;
|
|
57
|
-
case "ArrowUp":
|
|
58
|
-
t.preventDefault(), p(-1);
|
|
59
|
-
break;
|
|
60
|
-
case "Home":
|
|
61
|
-
t.preventDefault(), (d = r[0]) == null || d.focus();
|
|
62
|
-
break;
|
|
63
|
-
case "End":
|
|
64
|
-
t.preventDefault(), (b = r.at(-1)) == null || b.focus();
|
|
65
|
-
break;
|
|
66
|
-
case "Enter":
|
|
67
|
-
case " ":
|
|
68
|
-
document.activeElement instanceof HTMLButtonElement && (t.preventDefault(), u(document.activeElement), c(), l.focus());
|
|
69
|
-
break;
|
|
70
|
-
case "Escape":
|
|
71
|
-
t.preventDefault(), l.focus(), c();
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
}, _ = "button[data-bridgerte-toolbar-group-id]", Tt = "button[data-bridgerte-toolbar-item-id]", Et = [
|
|
75
|
-
Tt,
|
|
76
|
-
".bridgerte__toolbar-group-menu-item"
|
|
77
|
-
].join(","), yt = (t, o) => {
|
|
78
|
-
const l = t.map((u) => N(u, o));
|
|
79
|
-
return {
|
|
80
|
-
active: l.some((u) => u.active),
|
|
81
|
-
disabled: l.length > 0 && l.every((u) => u.disabled)
|
|
82
|
-
};
|
|
83
|
-
}, wt = (t, o, l, u, c) => {
|
|
84
|
-
const r = N(o, l), a = document.createElement("button"), p = u[o.icon] ?? X[o.icon];
|
|
85
|
-
a.type = "button", a.className = "bridgerte__toolbar-button", a.disabled = r.disabled, a.dataset.active = String(r.active), a.dataset.bridgerteToolbarItemId = o.id, a.setAttribute("aria-label", o.label), a.setAttribute("aria-pressed", String(r.active)), c && (a.dataset.tooltip = o.label), Y(a, p, o.label), t.append(a);
|
|
86
|
-
}, Lt = (t, o, l, u, c) => {
|
|
87
|
-
const r = document.createElement("button"), a = yt(o.items, l), p = o.icon ? u[o.icon] ?? X[o.icon] : tt.toolbarGroup, d = document.createElement("span");
|
|
88
|
-
r.type = "button", r.className = "bridgerte__toolbar-button bridgerte__toolbar-group-button", r.disabled = a.disabled, r.dataset.active = String(a.active), r.dataset.bridgerteToolbarGroupId = o.key, r.dataset.open = "false", r.setAttribute("aria-label", o.title), r.setAttribute("aria-haspopup", "menu"), r.setAttribute("aria-expanded", "false"), r.setAttribute("aria-pressed", String(a.active)), c && (r.dataset.tooltip = o.title), Y(r, p, o.title), d.className = "bridgerte__toolbar-group-indicator", d.setAttribute("aria-hidden", "true"), d.innerHTML = tt.chevronDown, r.append(d), t.append(r);
|
|
89
|
-
}, xt = (t, o, l, u, c) => {
|
|
90
|
-
t.textContent = "", o.forEach((r) => {
|
|
91
|
-
if (r.type === "separator") {
|
|
92
|
-
const p = document.createElement("span");
|
|
93
|
-
p.className = "bridgerte__toolbar-separator", p.dataset.separatorId = r.key, p.setAttribute("aria-hidden", "true"), t.append(p);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
if (r.type === "button") {
|
|
97
|
-
wt(
|
|
98
|
-
t,
|
|
99
|
-
r.item,
|
|
100
|
-
l,
|
|
101
|
-
u,
|
|
102
|
-
c
|
|
103
|
-
);
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const a = document.createElement("div");
|
|
107
|
-
a.className = "bridgerte__toolbar-group", a.dataset.group = r.key, a.setAttribute("aria-label", r.title), t.append(a), Lt(
|
|
108
|
-
a,
|
|
109
|
-
r,
|
|
110
|
-
l,
|
|
111
|
-
u,
|
|
112
|
-
c
|
|
113
|
-
);
|
|
114
|
-
});
|
|
115
|
-
}, I = (t, o, l, u) => {
|
|
116
|
-
if (t.textContent = "", !o) {
|
|
117
|
-
t.dataset.visible = "false";
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
o.items.forEach((c) => {
|
|
121
|
-
const r = N(c, l), a = document.createElement("button"), p = u[c.icon] ?? X[c.icon], d = document.createElement("span");
|
|
122
|
-
a.type = "button", a.className = "bridgerte__menu-item bridgerte__toolbar-group-menu-item", a.disabled = r.disabled, a.dataset.active = String(r.active), a.dataset.bridgerteToolbarItemId = c.id, a.setAttribute("role", "menuitem"), a.setAttribute("aria-label", c.label), a.setAttribute("aria-pressed", String(r.active)), Y(a, p, c.label), d.className = "bridgerte__toolbar-group-menu-label", d.textContent = c.label, a.append(d), t.append(a);
|
|
123
|
-
}), t.dataset.visible = "true", t.style.minWidth = `${o.button.offsetWidth}px`;
|
|
124
|
-
}, H = (t, o) => {
|
|
125
|
-
t.querySelectorAll(_).forEach((l) => {
|
|
126
|
-
const u = (o == null ? void 0 : o.groupKey) === l.dataset.bridgerteToolbarGroupId;
|
|
127
|
-
l.dataset.open = String(u), l.setAttribute("aria-expanded", String(u));
|
|
128
|
-
});
|
|
129
|
-
}, ot = (t, o) => t.find((l) => l.type === "group" && l.key === o), kt = 8, Bt = 6, x = 8, _t = () => {
|
|
130
|
-
var t;
|
|
131
|
-
return typeof window < "u" && ((t = window.matchMedia) == null ? void 0 : t.call(window, "(hover: hover) and (pointer: fine)").matches) === !0;
|
|
132
|
-
}, k = (t) => {
|
|
133
|
-
const o = t instanceof Element ? t.closest(Et) : null;
|
|
134
|
-
return o instanceof HTMLButtonElement ? o : null;
|
|
135
|
-
}, B = (t) => {
|
|
136
|
-
const o = t instanceof Element ? t.closest(_) : null;
|
|
137
|
-
return o instanceof HTMLButtonElement ? o : null;
|
|
138
|
-
};
|
|
139
|
-
function Pt(t, o) {
|
|
140
|
-
const l = o.placement ?? "top", u = ft(o.menuSchema ?? pt, {
|
|
141
|
-
menuLabels: o.menuLabels,
|
|
142
|
-
payloadPanelConfig: o.payloadPanelConfig
|
|
143
|
-
}), c = mt(o.toolbarConfig, u), r = c.flatMap((e) => e.type === "button" ? [e.item] : e.type === "group" ? e.items : []), a = o.icons ?? {}, p = _t(), d = document.createElement("div"), b = document.createElement("div"), y = t.closest(".bridgerte") ?? t;
|
|
144
|
-
let v = !1, h = o.editor.getCommandStates(), i = null, m = null, T = null, f = null, S = null, E = null;
|
|
145
|
-
const at = Z(t, {
|
|
146
|
-
targetSelector: [
|
|
147
|
-
"button[data-bridgerte-toolbar-item-id]",
|
|
148
|
-
"button[data-bridgerte-toolbar-group-id]"
|
|
149
|
-
].join(",")
|
|
150
|
-
}), st = Z(b, {
|
|
151
|
-
targetSelector: ".bridgerte__toolbar-group-menu-item"
|
|
152
|
-
}), K = () => {
|
|
153
|
-
y.append(d), y.append(b);
|
|
154
|
-
}, C = () => {
|
|
155
|
-
m == null || m.setOpen(!1), m == null || m.destroy(), m = null;
|
|
156
|
-
}, R = () => {
|
|
157
|
-
i && (C(), m = ht(i.button, b, {
|
|
158
|
-
placement: l === "bottom" ? "top-start" : "bottom-start",
|
|
159
|
-
offset: Bt,
|
|
160
|
-
strategy: "fixed"
|
|
161
|
-
}), m.setOpen(!0));
|
|
162
|
-
}, g = () => {
|
|
163
|
-
C(), i = null, I(b, i, h, a), H(t, i);
|
|
164
|
-
}, O = (e) => {
|
|
165
|
-
if (!v && (h = e, i && C(), xt(t, c, e, a, p), K(), i)) {
|
|
166
|
-
const n = Array.from(
|
|
167
|
-
t.querySelectorAll(_)
|
|
168
|
-
).find((D) => D.dataset.bridgerteToolbarGroupId === (i == null ? void 0 : i.groupKey)), s = ot(c, i.groupKey);
|
|
169
|
-
i = n && s ? {
|
|
170
|
-
groupKey: i.groupKey,
|
|
171
|
-
button: n,
|
|
172
|
-
items: s.items
|
|
173
|
-
} : null, I(b, i, h, a), H(t, i), i && R();
|
|
174
|
-
}
|
|
175
|
-
}, lt = () => {
|
|
176
|
-
v || O(o.editor.getCommandStates());
|
|
177
|
-
}, w = () => {
|
|
178
|
-
d.dataset.visible = "false", d.textContent = "";
|
|
179
|
-
}, it = (e) => {
|
|
180
|
-
const n = e.dataset.tooltip;
|
|
181
|
-
if (!p || !n) return;
|
|
182
|
-
const s = e.getBoundingClientRect();
|
|
183
|
-
d.textContent = n, d.dataset.visible = "true", d.style.left = `${s.left + s.width / 2}px`, d.style.top = `${s.top - kt}px`;
|
|
184
|
-
}, F = (e) => {
|
|
185
|
-
const n = k(e.target);
|
|
186
|
-
n && it(n);
|
|
187
|
-
}, j = (e) => {
|
|
188
|
-
const n = e.relatedTarget, s = k(e.target);
|
|
189
|
-
s && n instanceof Node && s.contains(n) || w();
|
|
190
|
-
}, G = (e) => {
|
|
191
|
-
if (!(e instanceof HTMLButtonElement) || e.disabled) return;
|
|
192
|
-
const n = r.find((s) => s.id === e.dataset.bridgerteToolbarItemId);
|
|
193
|
-
if (n) {
|
|
194
|
-
if (n.payloadPanel) {
|
|
195
|
-
const s = e.getBoundingClientRect();
|
|
196
|
-
o.editor.requestPayloadPanel({
|
|
197
|
-
menuId: n.id,
|
|
198
|
-
command: n.command,
|
|
199
|
-
panel: n.payloadPanel,
|
|
200
|
-
currentValues: gt(n, o.editor.getCommandStates()),
|
|
201
|
-
anchorRect: {
|
|
202
|
-
x: s.left,
|
|
203
|
-
y: s.top,
|
|
204
|
-
width: s.width,
|
|
205
|
-
height: s.height
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
o.editor.executeCommand(n.command);
|
|
211
|
-
}
|
|
212
|
-
}, ut = (e) => {
|
|
213
|
-
window.setTimeout(() => {
|
|
214
|
-
E === e && (E = null);
|
|
215
|
-
}, 0);
|
|
216
|
-
}, A = (e, n = !1) => {
|
|
217
|
-
const s = ot(
|
|
218
|
-
c,
|
|
219
|
-
e.dataset.bridgerteToolbarGroupId
|
|
220
|
-
);
|
|
221
|
-
if (!(!s || e.disabled)) {
|
|
222
|
-
if ((i == null ? void 0 : i.groupKey) === s.key) {
|
|
223
|
-
if (n) {
|
|
224
|
-
et(b, 0);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
g();
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
i = {
|
|
231
|
-
groupKey: s.key,
|
|
232
|
-
button: e,
|
|
233
|
-
items: s.items
|
|
234
|
-
}, w(), I(b, i, h, a), H(t, i), R(), n && et(b, 0);
|
|
235
|
-
}
|
|
236
|
-
}, L = (e) => {
|
|
237
|
-
const n = B(e.target);
|
|
238
|
-
if (n) {
|
|
239
|
-
if (e.preventDefault(), e.stopPropagation(), S === n) {
|
|
240
|
-
S = null;
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
A(n);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const s = k(e.target);
|
|
247
|
-
if (s) {
|
|
248
|
-
if (e.preventDefault(), e.stopPropagation(), E === s.dataset.bridgerteToolbarItemId) {
|
|
249
|
-
E = null;
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
G(s), g();
|
|
253
|
-
}
|
|
254
|
-
}, P = (e) => {
|
|
255
|
-
B(e.target) && e.preventDefault();
|
|
256
|
-
}, q = (e) => {
|
|
257
|
-
if (P(e), e.pointerType !== "touch" || e.button !== 0) return;
|
|
258
|
-
const n = k(e.target), s = n == null ? void 0 : n.dataset.bridgerteToolbarItemId;
|
|
259
|
-
!n || !s || n.disabled || (f = {
|
|
260
|
-
button: n,
|
|
261
|
-
itemId: s,
|
|
262
|
-
startX: e.clientX,
|
|
263
|
-
startY: e.clientY
|
|
264
|
-
});
|
|
265
|
-
}, M = () => {
|
|
266
|
-
f = null;
|
|
267
|
-
}, U = (e) => {
|
|
268
|
-
if (!f || e.pointerType !== "touch") return;
|
|
269
|
-
const n = Math.abs(e.clientX - f.startX), s = Math.abs(e.clientY - f.startY);
|
|
270
|
-
(n > x || s > x) && M();
|
|
271
|
-
}, $ = (e) => {
|
|
272
|
-
if (!f || e.pointerType !== "touch") return;
|
|
273
|
-
const n = f;
|
|
274
|
-
f = null, G(n.button), g(), E = n.itemId, ut(n.itemId);
|
|
275
|
-
}, V = (e) => {
|
|
276
|
-
const n = B(e.target), s = e.touches[0];
|
|
277
|
-
!n || !s || (e.preventDefault(), T = {
|
|
278
|
-
button: n,
|
|
279
|
-
startX: s.clientX,
|
|
280
|
-
startY: s.clientY
|
|
281
|
-
});
|
|
282
|
-
}, W = () => {
|
|
283
|
-
T = null;
|
|
284
|
-
}, z = (e) => {
|
|
285
|
-
if (!T) return;
|
|
286
|
-
const n = T, s = e.changedTouches[0], D = e.target instanceof Element ? e.target.closest(_) : null;
|
|
287
|
-
if (T = null, !s || D !== n.button) return;
|
|
288
|
-
const dt = Math.abs(s.clientX - n.startX), bt = Math.abs(s.clientY - n.startY);
|
|
289
|
-
dt > x || bt > x || (e.preventDefault(), e.stopPropagation(), S = n.button, A(n.button));
|
|
290
|
-
}, J = (e) => {
|
|
291
|
-
const n = e.target;
|
|
292
|
-
n instanceof Node && (t.contains(n) || b.contains(n)) || g();
|
|
293
|
-
}, Q = (e) => {
|
|
294
|
-
if (i && b.contains(document.activeElement)) {
|
|
295
|
-
vt(
|
|
296
|
-
e,
|
|
297
|
-
b,
|
|
298
|
-
i.button,
|
|
299
|
-
G,
|
|
300
|
-
g
|
|
301
|
-
);
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
const n = B(e.target);
|
|
305
|
-
if (n && (e.key === "Enter" || e.key === " " || e.key === "ArrowDown")) {
|
|
306
|
-
e.preventDefault(), e.stopPropagation(), A(n, !0);
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
e.key === "Escape" && g();
|
|
310
|
-
};
|
|
311
|
-
t.classList.add("bridgerte__toolbar"), d.className = "bridgerte__toolbar-tooltip", d.dataset.visible = "false", b.className = "bridgerte__floating-menu bridgerte__toolbar-group-menu", b.dataset.visible = "false", b.setAttribute("role", "menu"), t.dataset.placement = l, t.setAttribute("role", "toolbar"), t.setAttribute(
|
|
312
|
-
"aria-label",
|
|
313
|
-
l === "bottom" ? "BridgeRTE tabbar" : "BridgeRTE toolbar"
|
|
314
|
-
), t.addEventListener("pointerdown", q), t.addEventListener("mousedown", P), document.addEventListener("pointermove", U), document.addEventListener("pointerup", $), document.addEventListener("pointercancel", M), t.addEventListener("touchstart", V, { passive: !1 }), t.addEventListener("touchend", z), t.addEventListener("touchcancel", W), t.addEventListener("click", L), b.addEventListener("click", L), document.addEventListener("click", J), document.addEventListener("keydown", Q), p && (t.addEventListener("mouseover", F), t.addEventListener("mouseout", j)), t.addEventListener("focusout", w), K();
|
|
315
|
-
const ct = o.editor.subscribeCommandStateChange(O);
|
|
316
|
-
return {
|
|
317
|
-
update: lt,
|
|
318
|
-
destroy() {
|
|
319
|
-
v || (v = !0, ct(), g(), t.removeEventListener("pointerdown", q), t.removeEventListener("mousedown", P), document.removeEventListener("pointermove", U), document.removeEventListener("pointerup", $), document.removeEventListener("pointercancel", M), t.removeEventListener("touchstart", V), t.removeEventListener("touchend", z), t.removeEventListener("touchcancel", W), t.removeEventListener("click", L), b.removeEventListener("click", L), document.removeEventListener("click", J), document.removeEventListener("keydown", Q), p && (t.removeEventListener("mouseover", F), t.removeEventListener("mouseout", j)), at(), st(), t.removeEventListener("focusout", w), d.remove(), b.remove(), t.classList.remove("bridgerte__toolbar"), delete t.dataset.placement, t.textContent = "", t.removeAttribute("role"), t.removeAttribute("aria-label"));
|
|
320
|
-
}
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
const St = /[\u200B-\u200D\uFEFF]/g, Ct = [
|
|
324
|
-
"img",
|
|
325
|
-
"video",
|
|
326
|
-
"audio",
|
|
327
|
-
"iframe",
|
|
328
|
-
"table",
|
|
329
|
-
"pre",
|
|
330
|
-
"code",
|
|
331
|
-
"hr",
|
|
332
|
-
"figure",
|
|
333
|
-
"canvas",
|
|
334
|
-
"svg",
|
|
335
|
-
"math",
|
|
336
|
-
'[data-type="mention"]'
|
|
337
|
-
].join(","), nt = (t) => (t == null ? void 0 : t.replace(St, "").trim()) ?? "", Mt = (t) => {
|
|
338
|
-
if (!nt(t)) return !1;
|
|
339
|
-
const o = document.createElement("template");
|
|
340
|
-
return o.innerHTML = t, !!(nt(o.content.textContent) || o.content.querySelector(Ct));
|
|
341
|
-
};
|
|
342
|
-
export {
|
|
343
|
-
Pt as c,
|
|
344
|
-
Mt as h
|
|
345
|
-
};
|
|
346
|
-
//# sourceMappingURL=index-DH5duOs3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DH5duOs3.js","sources":["../../dom/src/menuIcon/uiIcons.ts","../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/index.ts","../../dom/src/htmlContent/index.ts"],"sourcesContent":["/**\n * DOM UI chrome icon 表。\n *\n * 这里放 toolbar 收纳入口、下拉箭头这类控件自身图标。它们不属于 `MenuItem.icon`\n * 跨端 schema,也不应该进入 `defaultMenuIcons` 的 schema 对齐检查。\n */\nexport const defaultMenuUiIcons = {\n toolbarGroup: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-ellipsis\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n `,\n chevronDown: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-chevron-down\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n} as const;\n","export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons,\n defaultMenuUiIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : defaultMenuUiIcons.toolbarGroup;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.innerHTML = defaultMenuUiIcons.chevronDown;\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单直接渲染为按钮,`|` 渲染分割线。\n * 只有用户显式声明的 group 配置才生成收纳入口,避免 schema 隐式改变 DOM 结构。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n const separatorElement = document.createElement('span');\n\n separatorElement.className = 'bridgerte__toolbar-separator';\n separatorElement.dataset.separatorId = toolbarItem.key;\n separatorElement.setAttribute('aria-hidden', 'true');\n toolbarElement.append(separatorElement);\n return;\n }\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n toolbarElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n /*\n * 收纳菜单是用户在 toolbarConfig 里显式声明的结构;普通菜单不会自动生成 DOM 包裹,\n * 显示分组完全交给用户用 group 配置或 `|` 控制。\n */\n const groupElement = document.createElement('div');\n\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = toolbarItem.key;\n groupElement.setAttribute('aria-label', toolbarItem.title);\n toolbarElement.append(groupElement);\n\n renderToolbarGroupButton(\n groupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__menu-item bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions\n} from './type';\n\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\nconst toolbarTouchMoveTolerancePx = 8;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n let pendingGroupTouch: {\n button: HTMLButtonElement;\n startX: number;\n startY: number;\n } | null = null;\n let pendingToolbarTouch: {\n button: HTMLButtonElement;\n itemId: string;\n startX: number;\n startY: number;\n } | null = null;\n let suppressNextGroupClickButton: HTMLButtonElement | null = null;\n let suppressNextToolbarClickItemId: string | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText) return;\n\n const buttonRect = button.getBoundingClientRect();\n\n tooltipElement.textContent = tooltipText;\n tooltipElement.dataset.visible = 'true';\n tooltipElement.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n tooltipElement.style.top = `${buttonRect.top - toolbarTooltipOffsetPx}px`;\n };\n\n const handleTooltipTarget = (event: Event) => {\n const button = getToolbarButtonFromTarget(event.target);\n\n if (button) {\n showTooltip(button);\n }\n };\n\n const handleTooltipLeave = (event: MouseEvent) => {\n const relatedTarget = event.relatedTarget;\n const button = getToolbarButtonFromTarget(event.target);\n\n if (\n button\n && relatedTarget instanceof Node\n && button.contains(relatedTarget)\n ) return;\n\n hideTooltip();\n };\n\n const executeToolbarButton = (button: HTMLButtonElement) => {\n if (!(button instanceof HTMLButtonElement) || button.disabled) return;\n\n const menuItem = executableMenuItems.find((item) => (\n item.id === button.dataset.bridgerteToolbarItemId\n ));\n\n if (!menuItem) return;\n\n if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const clearSuppressedToolbarClickSoon = (itemId: string) => {\n window.setTimeout(() => {\n if (suppressNextToolbarClickItemId === itemId) {\n suppressNextToolbarClickItemId = null;\n }\n }, 0);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement, shouldFocusMenu = false) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n if (shouldFocusMenu) {\n focusToolbarGroupMenuItem(groupMenuElement, 0);\n return;\n }\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n if (shouldFocusMenu) focusToolbarGroupMenuItem(groupMenuElement, 0);\n };\n\n const handleClick = (event: MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n if (suppressNextGroupClickButton === groupButton) {\n suppressNextGroupClickButton = null;\n return;\n }\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n if (suppressNextToolbarClickItemId === button.dataset.bridgerteToolbarItemId) {\n suppressNextToolbarClickItemId = null;\n return;\n }\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleGroupButtonPressStart = (event: PointerEvent | MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n\n if (!groupButton) return;\n\n /*\n * H5 软键盘会在按下 button 时因为 contenteditable blur 而关闭;\n * 这里只保护收纳/更多入口,不影响普通按钮、颜色面板或 toolbar 原生滚动。\n */\n event.preventDefault();\n };\n\n const handleToolbarPointerDown = (event: PointerEvent) => {\n handleGroupButtonPressStart(event);\n\n if (event.pointerType !== 'touch' || event.button !== 0) return;\n\n const button = getToolbarButtonFromTarget(event.target);\n const itemId = button?.dataset.bridgerteToolbarItemId;\n\n if (!button || !itemId || button.disabled) return;\n\n /*\n * 触屏端普通按钮在 pointerup 提交,解决 WebView/H5 不稳定补发 click 时菜单无响应。\n * 不 preventDefault,保留 toolbar 横向滚动和宿主手势;移动超阈值时按滚动处理。\n */\n pendingToolbarTouch = {\n button,\n itemId,\n startX: event.clientX,\n startY: event.clientY\n };\n };\n\n const clearPendingToolbarTouch = () => {\n pendingToolbarTouch = null;\n };\n\n const handleToolbarPointerMove = (event: PointerEvent) => {\n if (!pendingToolbarTouch || event.pointerType !== 'touch') return;\n\n const deltaX = Math.abs(event.clientX - pendingToolbarTouch.startX);\n const deltaY = Math.abs(event.clientY - pendingToolbarTouch.startY);\n\n if (deltaX > toolbarTouchMoveTolerancePx || deltaY > toolbarTouchMoveTolerancePx) {\n clearPendingToolbarTouch();\n }\n };\n\n const handleToolbarPointerUp = (event: PointerEvent) => {\n if (!pendingToolbarTouch || event.pointerType !== 'touch') return;\n\n const toolbarTouch = pendingToolbarTouch;\n\n pendingToolbarTouch = null;\n\n executeToolbarButton(toolbarTouch.button);\n closeGroupMenu();\n suppressNextToolbarClickItemId = toolbarTouch.itemId;\n clearSuppressedToolbarClickSoon(toolbarTouch.itemId);\n };\n\n const handleGroupButtonTouchStart = (event: TouchEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n const touch = event.touches[0];\n\n if (!groupButton || !touch) return;\n\n /*\n * 部分 H5/WebView 会早于 pointerdown,在 touchstart 阶段因为 button 命中导致\n * contenteditable blur。这里只兜底收纳入口,不拦普通菜单和 payloadPanel 入口。\n */\n event.preventDefault();\n pendingGroupTouch = {\n button: groupButton,\n startX: touch.clientX,\n startY: touch.clientY\n };\n };\n\n const clearPendingGroupTouch = () => {\n pendingGroupTouch = null;\n };\n\n const handleGroupButtonTouchEnd = (event: TouchEvent) => {\n if (!pendingGroupTouch) return;\n\n const groupTouch = pendingGroupTouch;\n const touch = event.changedTouches[0];\n const endTargetButton = event.target instanceof Element\n ? event.target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n pendingGroupTouch = null;\n if (!touch || endTargetButton !== groupTouch.button) return;\n\n const deltaX = Math.abs(touch.clientX - groupTouch.startX);\n const deltaY = Math.abs(touch.clientY - groupTouch.startY);\n\n if (\n deltaX > toolbarTouchMoveTolerancePx\n || deltaY > toolbarTouchMoveTolerancePx\n ) return;\n\n event.preventDefault();\n event.stopPropagation();\n suppressNextGroupClickButton = groupTouch.button;\n toggleGroupMenu(groupTouch.button);\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n const target = event.target;\n\n if (\n target instanceof Node\n && (container.contains(target) || groupMenuElement.contains(target))\n ) return;\n\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (\n groupButton\n && (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown')\n ) {\n /*\n * 指针点击收纳菜单不能抢编辑器焦点;键盘从入口按钮打开时则进入菜单项,\n * 保留 PC 可访问性和方向键 roving focus。\n */\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton, true);\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__floating-menu bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('pointerdown', handleToolbarPointerDown);\n container.addEventListener('mousedown', handleGroupButtonPressStart);\n document.addEventListener('pointermove', handleToolbarPointerMove);\n document.addEventListener('pointerup', handleToolbarPointerUp);\n document.addEventListener('pointercancel', clearPendingToolbarTouch);\n container.addEventListener('touchstart', handleGroupButtonTouchStart, { passive: false });\n container.addEventListener('touchend', handleGroupButtonTouchEnd);\n container.addEventListener('touchcancel', clearPendingGroupTouch);\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('click', handleDocumentClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('pointerdown', handleToolbarPointerDown);\n container.removeEventListener('mousedown', handleGroupButtonPressStart);\n document.removeEventListener('pointermove', handleToolbarPointerMove);\n document.removeEventListener('pointerup', handleToolbarPointerUp);\n document.removeEventListener('pointercancel', clearPendingToolbarTouch);\n container.removeEventListener('touchstart', handleGroupButtonTouchStart);\n container.removeEventListener('touchend', handleGroupButtonTouchEnd);\n container.removeEventListener('touchcancel', clearPendingGroupTouch);\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n","const invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\n\n/*\n * HTML 片段里这些元素没有 textContent 也应算有效内容。\n * 纯排版容器不放进来,避免 `<p><br></p>`、空列表项这类编辑器占位被误判为非空。\n */\nconst meaningfulHtmlContentSelector = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math',\n '[data-type=\"mention\"]'\n].join(',');\n\nconst normalizeHtmlText = (text: string | null | undefined): string => (\n text?.replace(invisibleTextPattern, '').trim() ?? ''\n);\n\n/**\n * 判断一段 HTML 片段是否包含可保存的富文本内容。\n *\n * 这个工具会使用浏览器 template 解析 HTML,适合只拿到 HTML 字符串的业务表单;如果已经持有\n * `EditorContent`,优先使用 core 的 `isEditorContentEmpty()`,避免额外 DOM parse。\n */\nexport const hasMeaningfulHtmlContent = (html: string): boolean => {\n if (!normalizeHtmlText(html)) return false;\n\n const template = document.createElement('template');\n\n template.innerHTML = html;\n\n return Boolean(\n normalizeHtmlText(template.content.textContent)\n || template.content.querySelector(meaningfulHtmlContentSelector)\n );\n};\n"],"names":["defaultMenuUiIcons","getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","separatorElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","toolbarTouchMoveTolerancePx","canUseHoverTooltip","getToolbarButtonFromTarget","target","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","groupMenuElement","overlayHost","destroyed","latestCommandStates","groupMenuFloatingLayer","pendingGroupTouch","pendingToolbarTouch","suppressNextGroupClickButton","suppressNextToolbarClickItemId","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","menuItem","getPayloadPanelCurrentValues","clearSuppressedToolbarClickSoon","itemId","toggleGroupMenu","shouldFocusMenu","groupItem","handleClick","groupButton","handleGroupButtonPressStart","handleToolbarPointerDown","clearPendingToolbarTouch","handleToolbarPointerMove","deltaX","deltaY","handleToolbarPointerUp","toolbarTouch","handleGroupButtonTouchStart","touch","clearPendingGroupTouch","handleGroupButtonTouchEnd","groupTouch","endTargetButton","handleDocumentClick","handleKeyDown","unsubscribe","invisibleTextPattern","meaningfulHtmlContentSelector","normalizeHtmlText","text","hasMeaningfulHtmlContent","html","template"],"mappings":"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"}
|
package/dist/index-D_3O19qd.cjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";const J=require("./native-spec.cjs"),m=require("./index-B5xR6zve.cjs"),Q={toolbarGroup:`
|
|
2
|
-
<svg
|
|
3
|
-
aria-hidden="true"
|
|
4
|
-
class="lucide lucide-ellipsis"
|
|
5
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
6
|
-
width="18"
|
|
7
|
-
height="18"
|
|
8
|
-
viewBox="0 0 24 24"
|
|
9
|
-
fill="none"
|
|
10
|
-
stroke="currentColor"
|
|
11
|
-
stroke-width="2"
|
|
12
|
-
stroke-linecap="round"
|
|
13
|
-
stroke-linejoin="round"
|
|
14
|
-
>
|
|
15
|
-
<circle cx="12" cy="12" r="1" />
|
|
16
|
-
<circle cx="19" cy="12" r="1" />
|
|
17
|
-
<circle cx="5" cy="12" r="1" />
|
|
18
|
-
</svg>
|
|
19
|
-
`,chevronDown:`
|
|
20
|
-
<svg
|
|
21
|
-
aria-hidden="true"
|
|
22
|
-
class="lucide lucide-chevron-down"
|
|
23
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
-
width="12"
|
|
25
|
-
height="12"
|
|
26
|
-
viewBox="0 0 24 24"
|
|
27
|
-
fill="none"
|
|
28
|
-
stroke="currentColor"
|
|
29
|
-
stroke-width="2"
|
|
30
|
-
stroke-linecap="round"
|
|
31
|
-
stroke-linejoin="round"
|
|
32
|
-
>
|
|
33
|
-
<path d="m6 9 6 6 6-6" />
|
|
34
|
-
</svg>
|
|
35
|
-
`},ot=t=>Array.from(t.querySelectorAll(".bridgerte__toolbar-group-menu-item")).filter(o=>!o.disabled),Z=(t,o)=>{const u=ot(t)[o];u&&u.focus()},dt=(t,o,l,u,c)=>{var d,b;const r=ot(o),a=document.activeElement instanceof HTMLButtonElement?r.indexOf(document.activeElement):-1,p=w=>{var i;if(r.length===0)return;const v=((a>=0?a:0)+w+r.length)%r.length;(i=r[v])==null||i.focus()};switch(t.key){case"ArrowDown":t.preventDefault(),p(1);break;case"ArrowUp":t.preventDefault(),p(-1);break;case"Home":t.preventDefault(),(d=r[0])==null||d.focus();break;case"End":t.preventDefault(),(b=r.at(-1))==null||b.focus();break;case"Enter":case" ":document.activeElement instanceof HTMLButtonElement&&(t.preventDefault(),u(document.activeElement),c(),l.focus());break;case"Escape":t.preventDefault(),l.focus(),c();break}},_="button[data-bridgerte-toolbar-group-id]",bt="button[data-bridgerte-toolbar-item-id]",pt=[bt,".bridgerte__toolbar-group-menu-item"].join(","),mt=(t,o)=>{const l=t.map(u=>m.getMenuStateForItem(u,o));return{active:l.some(u=>u.active),disabled:l.length>0&&l.every(u=>u.disabled)}},ft=(t,o,l,u,c)=>{const r=m.getMenuStateForItem(o,l),a=document.createElement("button"),p=u[o.icon]??m.defaultMenuIcons[o.icon];a.type="button",a.className="bridgerte__toolbar-button",a.disabled=r.disabled,a.dataset.active=String(r.active),a.dataset.bridgerteToolbarItemId=o.id,a.setAttribute("aria-label",o.label),a.setAttribute("aria-pressed",String(r.active)),c&&(a.dataset.tooltip=o.label),m.appendMenuIcon(a,p,o.label),t.append(a)},gt=(t,o,l,u,c)=>{const r=document.createElement("button"),a=mt(o.items,l),p=o.icon?u[o.icon]??m.defaultMenuIcons[o.icon]:Q.toolbarGroup,d=document.createElement("span");r.type="button",r.className="bridgerte__toolbar-button bridgerte__toolbar-group-button",r.disabled=a.disabled,r.dataset.active=String(a.active),r.dataset.bridgerteToolbarGroupId=o.key,r.dataset.open="false",r.setAttribute("aria-label",o.title),r.setAttribute("aria-haspopup","menu"),r.setAttribute("aria-expanded","false"),r.setAttribute("aria-pressed",String(a.active)),c&&(r.dataset.tooltip=o.title),m.appendMenuIcon(r,p,o.title),d.className="bridgerte__toolbar-group-indicator",d.setAttribute("aria-hidden","true"),d.innerHTML=Q.chevronDown,r.append(d),t.append(r)},ht=(t,o,l,u,c)=>{t.textContent="",o.forEach(r=>{if(r.type==="separator"){const p=document.createElement("span");p.className="bridgerte__toolbar-separator",p.dataset.separatorId=r.key,p.setAttribute("aria-hidden","true"),t.append(p);return}if(r.type==="button"){ft(t,r.item,l,u,c);return}const a=document.createElement("div");a.className="bridgerte__toolbar-group",a.dataset.group=r.key,a.setAttribute("aria-label",r.title),t.append(a),gt(a,r,l,u,c)})},H=(t,o,l,u)=>{if(t.textContent="",!o){t.dataset.visible="false";return}o.items.forEach(c=>{const r=m.getMenuStateForItem(c,l),a=document.createElement("button"),p=u[c.icon]??m.defaultMenuIcons[c.icon],d=document.createElement("span");a.type="button",a.className="bridgerte__menu-item bridgerte__toolbar-group-menu-item",a.disabled=r.disabled,a.dataset.active=String(r.active),a.dataset.bridgerteToolbarItemId=c.id,a.setAttribute("role","menuitem"),a.setAttribute("aria-label",c.label),a.setAttribute("aria-pressed",String(r.active)),m.appendMenuIcon(a,p,c.label),d.className="bridgerte__toolbar-group-menu-label",d.textContent=c.label,a.append(d),t.append(a)}),t.dataset.visible="true",t.style.minWidth=`${o.button.offsetWidth}px`},N=(t,o)=>{t.querySelectorAll(_).forEach(l=>{const u=(o==null?void 0:o.groupKey)===l.dataset.bridgerteToolbarGroupId;l.dataset.open=String(u),l.setAttribute("aria-expanded",String(u))})},tt=(t,o)=>t.find(l=>l.type==="group"&&l.key===o),vt=8,Tt=6,k=8,Et=()=>{var t;return typeof window<"u"&&((t=window.matchMedia)==null?void 0:t.call(window,"(hover: hover) and (pointer: fine)").matches)===!0},S=t=>{const o=t instanceof Element?t.closest(pt):null;return o instanceof HTMLButtonElement?o:null},B=t=>{const o=t instanceof Element?t.closest(_):null;return o instanceof HTMLButtonElement?o:null};function yt(t,o){const l=o.placement??"top",u=m.resolveMenuSchemaForDom(o.menuSchema??J.defaultMenuSchema,{menuLabels:o.menuLabels,payloadPanelConfig:o.payloadPanelConfig}),c=J.resolveToolbarMenu(o.toolbarConfig,u),r=c.flatMap(e=>e.type==="button"?[e.item]:e.type==="group"?e.items:[]),a=o.icons??{},p=Et(),d=document.createElement("div"),b=document.createElement("div"),w=t.closest(".bridgerte")??t;let T=!1,v=o.editor.getCommandStates(),i=null,f=null,E=null,g=null,C=null,y=null;const nt=m.bindTouchPressedState(t,{targetSelector:["button[data-bridgerte-toolbar-item-id]","button[data-bridgerte-toolbar-group-id]"].join(",")}),rt=m.bindTouchPressedState(b,{targetSelector:".bridgerte__toolbar-group-menu-item"}),X=()=>{w.append(d),w.append(b)},M=()=>{f==null||f.setOpen(!1),f==null||f.destroy(),f=null},Y=()=>{i&&(M(),f=m.createFloatingLayer(i.button,b,{placement:l==="bottom"?"top-start":"bottom-start",offset:Tt,strategy:"fixed"}),f.setOpen(!0))},h=()=>{M(),i=null,H(b,i,v,a),N(t,i)},K=e=>{if(!T&&(v=e,i&&M(),ht(t,c,e,a,p),X(),i)){const n=Array.from(t.querySelectorAll(_)).find(D=>D.dataset.bridgerteToolbarGroupId===(i==null?void 0:i.groupKey)),s=tt(c,i.groupKey);i=n&&s?{groupKey:i.groupKey,button:n,items:s.items}:null,H(b,i,v,a),N(t,i),i&&Y()}},at=()=>{T||K(o.editor.getCommandStates())},L=()=>{d.dataset.visible="false",d.textContent=""},st=e=>{const n=e.dataset.tooltip;if(!p||!n)return;const s=e.getBoundingClientRect();d.textContent=n,d.dataset.visible="true",d.style.left=`${s.left+s.width/2}px`,d.style.top=`${s.top-vt}px`},R=e=>{const n=S(e.target);n&&st(n)},F=e=>{const n=e.relatedTarget,s=S(e.target);s&&n instanceof Node&&s.contains(n)||L()},G=e=>{if(!(e instanceof HTMLButtonElement)||e.disabled)return;const n=r.find(s=>s.id===e.dataset.bridgerteToolbarItemId);if(n){if(n.payloadPanel){const s=e.getBoundingClientRect();o.editor.requestPayloadPanel({menuId:n.id,command:n.command,panel:n.payloadPanel,currentValues:m.getPayloadPanelCurrentValues(n,o.editor.getCommandStates()),anchorRect:{x:s.left,y:s.top,width:s.width,height:s.height}});return}o.editor.executeCommand(n.command)}},lt=e=>{window.setTimeout(()=>{y===e&&(y=null)},0)},A=(e,n=!1)=>{const s=tt(c,e.dataset.bridgerteToolbarGroupId);if(!(!s||e.disabled)){if((i==null?void 0:i.groupKey)===s.key){if(n){Z(b,0);return}h();return}i={groupKey:s.key,button:e,items:s.items},L(),H(b,i,v,a),N(t,i),Y(),n&&Z(b,0)}},x=e=>{const n=B(e.target);if(n){if(e.preventDefault(),e.stopPropagation(),C===n){C=null;return}A(n);return}const s=S(e.target);if(s){if(e.preventDefault(),e.stopPropagation(),y===s.dataset.bridgerteToolbarItemId){y=null;return}G(s),h()}},I=e=>{B(e.target)&&e.preventDefault()},q=e=>{if(I(e),e.pointerType!=="touch"||e.button!==0)return;const n=S(e.target),s=n==null?void 0:n.dataset.bridgerteToolbarItemId;!n||!s||n.disabled||(g={button:n,itemId:s,startX:e.clientX,startY:e.clientY})},P=()=>{g=null},O=e=>{if(!g||e.pointerType!=="touch")return;const n=Math.abs(e.clientX-g.startX),s=Math.abs(e.clientY-g.startY);(n>k||s>k)&&P()},j=e=>{if(!g||e.pointerType!=="touch")return;const n=g;g=null,G(n.button),h(),y=n.itemId,lt(n.itemId)},U=e=>{const n=B(e.target),s=e.touches[0];!n||!s||(e.preventDefault(),E={button:n,startX:s.clientX,startY:s.clientY})},$=()=>{E=null},V=e=>{if(!E)return;const n=E,s=e.changedTouches[0],D=e.target instanceof Element?e.target.closest(_):null;if(E=null,!s||D!==n.button)return;const ut=Math.abs(s.clientX-n.startX),ct=Math.abs(s.clientY-n.startY);ut>k||ct>k||(e.preventDefault(),e.stopPropagation(),C=n.button,A(n.button))},W=e=>{const n=e.target;n instanceof Node&&(t.contains(n)||b.contains(n))||h()},z=e=>{if(i&&b.contains(document.activeElement)){dt(e,b,i.button,G,h);return}const n=B(e.target);if(n&&(e.key==="Enter"||e.key===" "||e.key==="ArrowDown")){e.preventDefault(),e.stopPropagation(),A(n,!0);return}e.key==="Escape"&&h()};t.classList.add("bridgerte__toolbar"),d.className="bridgerte__toolbar-tooltip",d.dataset.visible="false",b.className="bridgerte__floating-menu bridgerte__toolbar-group-menu",b.dataset.visible="false",b.setAttribute("role","menu"),t.dataset.placement=l,t.setAttribute("role","toolbar"),t.setAttribute("aria-label",l==="bottom"?"BridgeRTE tabbar":"BridgeRTE toolbar"),t.addEventListener("pointerdown",q),t.addEventListener("mousedown",I),document.addEventListener("pointermove",O),document.addEventListener("pointerup",j),document.addEventListener("pointercancel",P),t.addEventListener("touchstart",U,{passive:!1}),t.addEventListener("touchend",V),t.addEventListener("touchcancel",$),t.addEventListener("click",x),b.addEventListener("click",x),document.addEventListener("click",W),document.addEventListener("keydown",z),p&&(t.addEventListener("mouseover",R),t.addEventListener("mouseout",F)),t.addEventListener("focusout",L),X();const it=o.editor.subscribeCommandStateChange(K);return{update:at,destroy(){T||(T=!0,it(),h(),t.removeEventListener("pointerdown",q),t.removeEventListener("mousedown",I),document.removeEventListener("pointermove",O),document.removeEventListener("pointerup",j),document.removeEventListener("pointercancel",P),t.removeEventListener("touchstart",U),t.removeEventListener("touchend",V),t.removeEventListener("touchcancel",$),t.removeEventListener("click",x),b.removeEventListener("click",x),document.removeEventListener("click",W),document.removeEventListener("keydown",z),p&&(t.removeEventListener("mouseover",R),t.removeEventListener("mouseout",F)),nt(),rt(),t.removeEventListener("focusout",L),d.remove(),b.remove(),t.classList.remove("bridgerte__toolbar"),delete t.dataset.placement,t.textContent="",t.removeAttribute("role"),t.removeAttribute("aria-label"))}}}const wt=/[\u200B-\u200D\uFEFF]/g,Lt=["img","video","audio","iframe","table","pre","code","hr","figure","canvas","svg","math",'[data-type="mention"]'].join(","),et=t=>(t==null?void 0:t.replace(wt,"").trim())??"",xt=t=>{if(!et(t))return!1;const o=document.createElement("template");return o.innerHTML=t,!!(et(o.content.textContent)||o.content.querySelector(Lt))};exports.createRichTextToolbar=yt;exports.hasMeaningfulHtmlContent=xt;
|
|
36
|
-
//# sourceMappingURL=index-D_3O19qd.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-D_3O19qd.cjs","sources":["../../dom/src/menuIcon/uiIcons.ts","../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/index.ts","../../dom/src/htmlContent/index.ts"],"sourcesContent":["/**\n * DOM UI chrome icon 表。\n *\n * 这里放 toolbar 收纳入口、下拉箭头这类控件自身图标。它们不属于 `MenuItem.icon`\n * 跨端 schema,也不应该进入 `defaultMenuIcons` 的 schema 对齐检查。\n */\nexport const defaultMenuUiIcons = {\n toolbarGroup: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-ellipsis\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n `,\n chevronDown: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-chevron-down\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n} as const;\n","export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons,\n defaultMenuUiIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : defaultMenuUiIcons.toolbarGroup;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.innerHTML = defaultMenuUiIcons.chevronDown;\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单直接渲染为按钮,`|` 渲染分割线。\n * 只有用户显式声明的 group 配置才生成收纳入口,避免 schema 隐式改变 DOM 结构。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n const separatorElement = document.createElement('span');\n\n separatorElement.className = 'bridgerte__toolbar-separator';\n separatorElement.dataset.separatorId = toolbarItem.key;\n separatorElement.setAttribute('aria-hidden', 'true');\n toolbarElement.append(separatorElement);\n return;\n }\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n toolbarElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n /*\n * 收纳菜单是用户在 toolbarConfig 里显式声明的结构;普通菜单不会自动生成 DOM 包裹,\n * 显示分组完全交给用户用 group 配置或 `|` 控制。\n */\n const groupElement = document.createElement('div');\n\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = toolbarItem.key;\n groupElement.setAttribute('aria-label', toolbarItem.title);\n toolbarElement.append(groupElement);\n\n renderToolbarGroupButton(\n groupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__menu-item bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions\n} from './type';\n\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\nconst toolbarTouchMoveTolerancePx = 8;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n let pendingGroupTouch: {\n button: HTMLButtonElement;\n startX: number;\n startY: number;\n } | null = null;\n let pendingToolbarTouch: {\n button: HTMLButtonElement;\n itemId: string;\n startX: number;\n startY: number;\n } | null = null;\n let suppressNextGroupClickButton: HTMLButtonElement | null = null;\n let suppressNextToolbarClickItemId: string | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText) return;\n\n const buttonRect = button.getBoundingClientRect();\n\n tooltipElement.textContent = tooltipText;\n tooltipElement.dataset.visible = 'true';\n tooltipElement.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n tooltipElement.style.top = `${buttonRect.top - toolbarTooltipOffsetPx}px`;\n };\n\n const handleTooltipTarget = (event: Event) => {\n const button = getToolbarButtonFromTarget(event.target);\n\n if (button) {\n showTooltip(button);\n }\n };\n\n const handleTooltipLeave = (event: MouseEvent) => {\n const relatedTarget = event.relatedTarget;\n const button = getToolbarButtonFromTarget(event.target);\n\n if (\n button\n && relatedTarget instanceof Node\n && button.contains(relatedTarget)\n ) return;\n\n hideTooltip();\n };\n\n const executeToolbarButton = (button: HTMLButtonElement) => {\n if (!(button instanceof HTMLButtonElement) || button.disabled) return;\n\n const menuItem = executableMenuItems.find((item) => (\n item.id === button.dataset.bridgerteToolbarItemId\n ));\n\n if (!menuItem) return;\n\n if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const clearSuppressedToolbarClickSoon = (itemId: string) => {\n window.setTimeout(() => {\n if (suppressNextToolbarClickItemId === itemId) {\n suppressNextToolbarClickItemId = null;\n }\n }, 0);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement, shouldFocusMenu = false) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n if (shouldFocusMenu) {\n focusToolbarGroupMenuItem(groupMenuElement, 0);\n return;\n }\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n if (shouldFocusMenu) focusToolbarGroupMenuItem(groupMenuElement, 0);\n };\n\n const handleClick = (event: MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n if (suppressNextGroupClickButton === groupButton) {\n suppressNextGroupClickButton = null;\n return;\n }\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n if (suppressNextToolbarClickItemId === button.dataset.bridgerteToolbarItemId) {\n suppressNextToolbarClickItemId = null;\n return;\n }\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleGroupButtonPressStart = (event: PointerEvent | MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n\n if (!groupButton) return;\n\n /*\n * H5 软键盘会在按下 button 时因为 contenteditable blur 而关闭;\n * 这里只保护收纳/更多入口,不影响普通按钮、颜色面板或 toolbar 原生滚动。\n */\n event.preventDefault();\n };\n\n const handleToolbarPointerDown = (event: PointerEvent) => {\n handleGroupButtonPressStart(event);\n\n if (event.pointerType !== 'touch' || event.button !== 0) return;\n\n const button = getToolbarButtonFromTarget(event.target);\n const itemId = button?.dataset.bridgerteToolbarItemId;\n\n if (!button || !itemId || button.disabled) return;\n\n /*\n * 触屏端普通按钮在 pointerup 提交,解决 WebView/H5 不稳定补发 click 时菜单无响应。\n * 不 preventDefault,保留 toolbar 横向滚动和宿主手势;移动超阈值时按滚动处理。\n */\n pendingToolbarTouch = {\n button,\n itemId,\n startX: event.clientX,\n startY: event.clientY\n };\n };\n\n const clearPendingToolbarTouch = () => {\n pendingToolbarTouch = null;\n };\n\n const handleToolbarPointerMove = (event: PointerEvent) => {\n if (!pendingToolbarTouch || event.pointerType !== 'touch') return;\n\n const deltaX = Math.abs(event.clientX - pendingToolbarTouch.startX);\n const deltaY = Math.abs(event.clientY - pendingToolbarTouch.startY);\n\n if (deltaX > toolbarTouchMoveTolerancePx || deltaY > toolbarTouchMoveTolerancePx) {\n clearPendingToolbarTouch();\n }\n };\n\n const handleToolbarPointerUp = (event: PointerEvent) => {\n if (!pendingToolbarTouch || event.pointerType !== 'touch') return;\n\n const toolbarTouch = pendingToolbarTouch;\n\n pendingToolbarTouch = null;\n\n executeToolbarButton(toolbarTouch.button);\n closeGroupMenu();\n suppressNextToolbarClickItemId = toolbarTouch.itemId;\n clearSuppressedToolbarClickSoon(toolbarTouch.itemId);\n };\n\n const handleGroupButtonTouchStart = (event: TouchEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n const touch = event.touches[0];\n\n if (!groupButton || !touch) return;\n\n /*\n * 部分 H5/WebView 会早于 pointerdown,在 touchstart 阶段因为 button 命中导致\n * contenteditable blur。这里只兜底收纳入口,不拦普通菜单和 payloadPanel 入口。\n */\n event.preventDefault();\n pendingGroupTouch = {\n button: groupButton,\n startX: touch.clientX,\n startY: touch.clientY\n };\n };\n\n const clearPendingGroupTouch = () => {\n pendingGroupTouch = null;\n };\n\n const handleGroupButtonTouchEnd = (event: TouchEvent) => {\n if (!pendingGroupTouch) return;\n\n const groupTouch = pendingGroupTouch;\n const touch = event.changedTouches[0];\n const endTargetButton = event.target instanceof Element\n ? event.target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n pendingGroupTouch = null;\n if (!touch || endTargetButton !== groupTouch.button) return;\n\n const deltaX = Math.abs(touch.clientX - groupTouch.startX);\n const deltaY = Math.abs(touch.clientY - groupTouch.startY);\n\n if (\n deltaX > toolbarTouchMoveTolerancePx\n || deltaY > toolbarTouchMoveTolerancePx\n ) return;\n\n event.preventDefault();\n event.stopPropagation();\n suppressNextGroupClickButton = groupTouch.button;\n toggleGroupMenu(groupTouch.button);\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n const target = event.target;\n\n if (\n target instanceof Node\n && (container.contains(target) || groupMenuElement.contains(target))\n ) return;\n\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (\n groupButton\n && (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown')\n ) {\n /*\n * 指针点击收纳菜单不能抢编辑器焦点;键盘从入口按钮打开时则进入菜单项,\n * 保留 PC 可访问性和方向键 roving focus。\n */\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton, true);\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__floating-menu bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('pointerdown', handleToolbarPointerDown);\n container.addEventListener('mousedown', handleGroupButtonPressStart);\n document.addEventListener('pointermove', handleToolbarPointerMove);\n document.addEventListener('pointerup', handleToolbarPointerUp);\n document.addEventListener('pointercancel', clearPendingToolbarTouch);\n container.addEventListener('touchstart', handleGroupButtonTouchStart, { passive: false });\n container.addEventListener('touchend', handleGroupButtonTouchEnd);\n container.addEventListener('touchcancel', clearPendingGroupTouch);\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('click', handleDocumentClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('pointerdown', handleToolbarPointerDown);\n container.removeEventListener('mousedown', handleGroupButtonPressStart);\n document.removeEventListener('pointermove', handleToolbarPointerMove);\n document.removeEventListener('pointerup', handleToolbarPointerUp);\n document.removeEventListener('pointercancel', clearPendingToolbarTouch);\n container.removeEventListener('touchstart', handleGroupButtonTouchStart);\n container.removeEventListener('touchend', handleGroupButtonTouchEnd);\n container.removeEventListener('touchcancel', clearPendingGroupTouch);\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n","const invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\n\n/*\n * HTML 片段里这些元素没有 textContent 也应算有效内容。\n * 纯排版容器不放进来,避免 `<p><br></p>`、空列表项这类编辑器占位被误判为非空。\n */\nconst meaningfulHtmlContentSelector = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math',\n '[data-type=\"mention\"]'\n].join(',');\n\nconst normalizeHtmlText = (text: string | null | undefined): string => (\n text?.replace(invisibleTextPattern, '').trim() ?? ''\n);\n\n/**\n * 判断一段 HTML 片段是否包含可保存的富文本内容。\n *\n * 这个工具会使用浏览器 template 解析 HTML,适合只拿到 HTML 字符串的业务表单;如果已经持有\n * `EditorContent`,优先使用 core 的 `isEditorContentEmpty()`,避免额外 DOM parse。\n */\nexport const hasMeaningfulHtmlContent = (html: string): boolean => {\n if (!normalizeHtmlText(html)) return false;\n\n const template = document.createElement('template');\n\n template.innerHTML = html;\n\n return Boolean(\n normalizeHtmlText(template.content.textContent)\n || template.content.querySelector(meaningfulHtmlContentSelector)\n );\n};\n"],"names":["defaultMenuUiIcons","getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","separatorElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","toolbarTouchMoveTolerancePx","canUseHoverTooltip","getToolbarButtonFromTarget","target","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","groupMenuElement","overlayHost","destroyed","latestCommandStates","groupMenuFloatingLayer","pendingGroupTouch","pendingToolbarTouch","suppressNextGroupClickButton","suppressNextToolbarClickItemId","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","menuItem","getPayloadPanelCurrentValues","clearSuppressedToolbarClickSoon","itemId","toggleGroupMenu","shouldFocusMenu","groupItem","handleClick","groupButton","handleGroupButtonPressStart","handleToolbarPointerDown","clearPendingToolbarTouch","handleToolbarPointerMove","deltaX","deltaY","handleToolbarPointerUp","toolbarTouch","handleGroupButtonTouchStart","touch","clearPendingGroupTouch","handleGroupButtonTouchEnd","groupTouch","endTargetButton","handleDocumentClick","handleKeyDown","unsubscribe","invisibleTextPattern","meaningfulHtmlContentSelector","normalizeHtmlText","text","hasMeaningfulHtmlContent","html","template"],"mappings":"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"}
|