bridgerte 0.9.17 → 0.9.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- import { defaultMenuSchema as ot, resolveToolbarMenu as nt } from "./native-spec.js";
2
- import { g as N, d as K, e as M, r as rt, f as X, h as at, c as st } from "./index-IG7bnHAR.js";
3
- const Y = {
1
+ import { defaultMenuSchema as et, resolveToolbarMenu as ot } from "./native-spec.js";
2
+ import { g as H, d as N, e as K, r as nt, f as q, h as rt, c as at } from "./index-8kI8r7zm.js";
3
+ const X = {
4
4
  toolbarGroup: `
5
5
  <svg
6
6
  aria-hidden="true"
@@ -37,14 +37,14 @@ const Y = {
37
37
  <path d="m6 9 6 6 6-6" />
38
38
  </svg>
39
39
  `
40
- }, J = (t) => Array.from(
40
+ }, z = (t) => Array.from(
41
41
  t.querySelectorAll(".bridgerte__toolbar-group-menu-item")
42
- ).filter((e) => !e.disabled), U = (t, e) => {
43
- const c = J(t)[e];
42
+ ).filter((e) => !e.disabled), Y = (t, e) => {
43
+ const c = z(t)[e];
44
44
  c && c.focus();
45
- }, it = (t, e, i, c, d) => {
45
+ }, st = (t, e, i, c, d) => {
46
46
  var s, u;
47
- const n = J(e), r = document.activeElement instanceof HTMLButtonElement ? n.indexOf(document.activeElement) : -1, m = (g) => {
47
+ const n = z(e), r = document.activeElement instanceof HTMLButtonElement ? n.indexOf(document.activeElement) : -1, m = (g) => {
48
48
  var o;
49
49
  if (n.length === 0) return;
50
50
  const v = ((r >= 0 ? r : 0) + g + n.length) % n.length;
@@ -71,21 +71,21 @@ const Y = {
71
71
  t.preventDefault(), i.focus(), d();
72
72
  break;
73
73
  }
74
- }, x = "button[data-bridgerte-toolbar-group-id]", I = "button[data-bridgerte-toolbar-item-id]", H = [
75
- I,
74
+ }, L = "button[data-bridgerte-toolbar-group-id]", it = "button[data-bridgerte-toolbar-item-id]", I = [
75
+ it,
76
76
  ".bridgerte__toolbar-group-menu-item"
77
77
  ].join(","), lt = (t, e) => {
78
- const i = t.map((c) => N(c, e));
78
+ const i = t.map((c) => H(c, e));
79
79
  return {
80
80
  active: i.some((c) => c.active),
81
81
  disabled: i.length > 0 && i.every((c) => c.disabled)
82
82
  };
83
83
  }, ct = (t, e, i, c, d) => {
84
- const n = N(e, i), r = document.createElement("button"), m = c[e.icon] ?? K[e.icon];
85
- r.type = "button", r.className = "bridgerte__toolbar-button", r.disabled = n.disabled, r.dataset.active = String(n.active), r.dataset.bridgerteToolbarItemId = e.id, r.setAttribute("aria-label", e.label), r.setAttribute("aria-pressed", String(n.active)), d && (r.dataset.tooltip = e.label), M(r, m, e.label), t.append(r);
84
+ const n = H(e, i), r = document.createElement("button"), m = c[e.icon] ?? N[e.icon];
85
+ r.type = "button", r.className = "bridgerte__toolbar-button", r.disabled = n.disabled, r.dataset.active = String(n.active), r.dataset.bridgerteToolbarItemId = e.id, r.setAttribute("aria-label", e.label), r.setAttribute("aria-pressed", String(n.active)), d && (r.dataset.tooltip = e.label), K(r, m, e.label), t.append(r);
86
86
  }, dt = (t, e, i, c, d) => {
87
- const n = document.createElement("button"), r = lt(e.items, i), m = e.icon ? c[e.icon] ?? K[e.icon] : Y.toolbarGroup, s = document.createElement("span");
88
- 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 = e.key, n.dataset.open = "false", n.setAttribute("aria-label", e.title), n.setAttribute("aria-haspopup", "menu"), n.setAttribute("aria-expanded", "false"), n.setAttribute("aria-pressed", String(r.active)), d && (n.dataset.tooltip = e.title), M(n, m, e.title), s.className = "bridgerte__toolbar-group-indicator", s.setAttribute("aria-hidden", "true"), s.innerHTML = Y.chevronDown, n.append(s), t.append(n);
87
+ const n = document.createElement("button"), r = lt(e.items, i), m = e.icon ? c[e.icon] ?? N[e.icon] : X.toolbarGroup, s = document.createElement("span");
88
+ 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 = e.key, n.dataset.open = "false", n.setAttribute("aria-label", e.title), n.setAttribute("aria-haspopup", "menu"), n.setAttribute("aria-expanded", "false"), n.setAttribute("aria-pressed", String(r.active)), d && (n.dataset.tooltip = e.title), K(n, m, e.title), s.className = "bridgerte__toolbar-group-indicator", s.setAttribute("aria-hidden", "true"), s.innerHTML = X.chevronDown, n.append(s), t.append(n);
89
89
  }, ut = (t, e, i, c, d) => {
90
90
  t.textContent = "", e.forEach((n) => {
91
91
  if (n.type === "separator") {
@@ -118,23 +118,23 @@ const Y = {
118
118
  return;
119
119
  }
120
120
  e.items.forEach((d) => {
121
- const n = N(d, i), r = document.createElement("button"), m = c[d.icon] ?? K[d.icon], s = document.createElement("span");
122
- 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 = d.id, r.setAttribute("role", "menuitem"), r.setAttribute("aria-label", d.label), r.setAttribute("aria-pressed", String(n.active)), M(r, m, d.label), s.className = "bridgerte__toolbar-group-menu-label", s.textContent = d.label, r.append(s), t.append(r);
121
+ const n = H(d, i), r = document.createElement("button"), m = c[d.icon] ?? N[d.icon], s = document.createElement("span");
122
+ 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 = d.id, r.setAttribute("role", "menuitem"), r.setAttribute("aria-label", d.label), r.setAttribute("aria-pressed", String(n.active)), K(r, m, d.label), s.className = "bridgerte__toolbar-group-menu-label", s.textContent = d.label, r.append(s), t.append(r);
123
123
  }), t.dataset.visible = "true", t.style.minWidth = `${e.button.offsetWidth}px`;
124
- }, D = (t, e) => {
125
- t.querySelectorAll(x).forEach((i) => {
124
+ }, P = (t, e) => {
125
+ t.querySelectorAll(L).forEach((i) => {
126
126
  const c = (e == null ? void 0 : e.groupKey) === i.dataset.bridgerteToolbarGroupId;
127
127
  i.dataset.open = String(c), i.setAttribute("aria-expanded", String(c));
128
128
  });
129
- }, $ = (t, e) => t.find((i) => i.type === "group" && i.key === e), V = 8, B = (t, e) => e instanceof Node && t.contains(e), w = (t, e) => t instanceof Element ? t.closest(e) : null, bt = (t, e, i, c, d) => {
129
+ }, U = (t, e) => t.find((i) => i.type === "group" && i.key === e), $ = 8, S = (t, e) => e instanceof Node && t.contains(e), _ = (t, e) => t instanceof Element ? t.closest(e) : null, bt = (t, e, i, c, d) => {
130
130
  let n = null, r = null;
131
- const m = (o) => w(o, x) ?? w(o, I) ?? (B(e, o) ? w(o, H) : null), s = (o) => {
132
- m(o.target) && o.preventDefault();
131
+ const m = (o) => _(o, L) ?? (S(e, o) ? _(o, I) : null), s = (o) => {
132
+ m(o.target) && (o instanceof PointerEvent && o.pointerType !== "mouse" || o.preventDefault());
133
133
  }, u = (o) => {
134
- const p = o.touches[0], h = w(o.target, x), L = w(o.target, I), E = B(e, o.target) ? w(o.target, H) : null, y = h ?? L ?? E;
135
- !y || !p || (o.preventDefault(), n = {
134
+ const p = o.touches[0], h = _(o.target, L), T = S(e, o.target) ? _(o.target, I) : null, y = h ?? T;
135
+ !y || !p || (n = {
136
136
  button: y,
137
- kind: h ? "group" : E ? "menu-item" : "button",
137
+ kind: h ? "group" : "menu-item",
138
138
  startX: p.clientX,
139
139
  startY: p.clientY
140
140
  });
@@ -142,10 +142,10 @@ const Y = {
142
142
  n = null;
143
143
  }, f = (o) => {
144
144
  if (!n) return;
145
- const p = n, h = o.changedTouches[0], L = m(o.target);
146
- if (n = null, !h || L !== p.button) return;
147
- const E = Math.abs(h.clientX - p.startX), y = Math.abs(h.clientY - p.startY);
148
- if (!(E > V || y > V)) {
145
+ const p = n, h = o.changedTouches[0], T = m(o.target);
146
+ if (n = null, !h || T !== p.button) return;
147
+ const y = Math.abs(h.clientX - p.startX), w = Math.abs(h.clientY - p.startY);
148
+ if (!(y > $ || w > $)) {
149
149
  if (o.preventDefault(), o.stopPropagation(), r = p.button, p.kind === "group") {
150
150
  i(p.button);
151
151
  return;
@@ -153,7 +153,7 @@ const Y = {
153
153
  c(p.button), d();
154
154
  }
155
155
  }, v = (o) => {
156
- B(t, o.target) || B(e, o.target) || d();
156
+ S(t, o.target) || S(e, o.target) || d();
157
157
  };
158
158
  return t.addEventListener("pointerdown", s), t.addEventListener("mousedown", s), t.addEventListener("touchstart", u, { passive: !1 }), t.addEventListener("touchend", f), t.addEventListener("touchcancel", g), e.addEventListener("pointerdown", s), e.addEventListener("mousedown", s), e.addEventListener("touchstart", u, { passive: !1 }), e.addEventListener("touchend", f), e.addEventListener("touchcancel", g), document.addEventListener("pointerdown", v, !0), {
159
159
  consumeSuppressedClick(o) {
@@ -166,65 +166,65 @@ const Y = {
166
166
  }, pt = 8, mt = 6, ft = () => {
167
167
  var t;
168
168
  return typeof window < "u" && ((t = window.matchMedia) == null ? void 0 : t.call(window, "(hover: hover) and (pointer: fine)").matches) === !0;
169
- }, P = (t) => {
170
- const e = t instanceof Element ? t.closest(H) : null;
169
+ }, D = (t) => {
170
+ const e = t instanceof Element ? t.closest(I) : null;
171
171
  return e instanceof HTMLButtonElement ? e : null;
172
- }, W = (t) => {
173
- const e = t instanceof Element ? t.closest(x) : null;
172
+ }, V = (t) => {
173
+ const e = t instanceof Element ? t.closest(L) : null;
174
174
  return e instanceof HTMLButtonElement ? e : null;
175
175
  };
176
176
  function Et(t, e) {
177
- const i = e.placement ?? "top", c = rt(e.menuSchema ?? ot, {
177
+ const i = e.placement ?? "top", c = nt(e.menuSchema ?? et, {
178
178
  menuLabels: e.menuLabels,
179
179
  payloadPanelConfig: e.payloadPanelConfig
180
- }), d = nt(e.toolbarConfig, c), n = d.flatMap((a) => a.type === "button" ? [a.item] : a.type === "group" ? a.items : []), r = e.icons ?? {}, m = ft(), s = document.createElement("div"), u = document.createElement("div"), g = t.closest(".bridgerte") ?? t;
180
+ }), d = ot(e.toolbarConfig, c), n = d.flatMap((a) => a.type === "button" ? [a.item] : a.type === "group" ? a.items : []), r = e.icons ?? {}, m = ft(), s = document.createElement("div"), u = document.createElement("div"), g = t.closest(".bridgerte") ?? t;
181
181
  let f = !1, v = e.editor.getCommandStates(), o = null, p = null;
182
- const h = X(t, {
182
+ const h = q(t, {
183
183
  targetSelector: [
184
184
  "button[data-bridgerte-toolbar-item-id]",
185
185
  "button[data-bridgerte-toolbar-group-id]"
186
186
  ].join(",")
187
- }), L = X(u, {
187
+ }), T = q(u, {
188
188
  targetSelector: ".bridgerte__toolbar-group-menu-item"
189
- }), E = () => {
189
+ }), y = () => {
190
190
  g.append(s), g.append(u);
191
- }, y = () => {
191
+ }, w = () => {
192
192
  p == null || p.setOpen(!1), p == null || p.destroy(), p = null;
193
- }, R = () => {
194
- o && (y(), p = st(o.button, u, {
193
+ }, M = () => {
194
+ o && (w(), p = at(o.button, u, {
195
195
  placement: i === "bottom" ? "top-start" : "bottom-start",
196
196
  offset: mt,
197
197
  strategy: "fixed"
198
198
  }), p.setOpen(!0));
199
- }, T = () => {
200
- !o && !p || (y(), o = null, G(u, o, v, r), D(t, o));
201
- }, F = (a) => {
202
- if (!f && (v = a, o && y(), ut(t, d, a, r, m), E(), o)) {
199
+ }, E = () => {
200
+ !o && !p || (w(), o = null, G(u, o, v, r), P(t, o));
201
+ }, R = (a) => {
202
+ if (!f && (v = a, o && w(), ut(t, d, a, r, m), y(), o)) {
203
203
  const l = Array.from(
204
- t.querySelectorAll(x)
205
- ).find((et) => et.dataset.bridgerteToolbarGroupId === (o == null ? void 0 : o.groupKey)), b = $(d, o.groupKey);
204
+ t.querySelectorAll(L)
205
+ ).find((tt) => tt.dataset.bridgerteToolbarGroupId === (o == null ? void 0 : o.groupKey)), b = U(d, o.groupKey);
206
206
  o = l && b ? {
207
207
  groupKey: o.groupKey,
208
208
  button: l,
209
209
  items: b.items
210
- } : null, G(u, o, v, r), D(t, o), o && R();
210
+ } : null, G(u, o, v, r), P(t, o), o && M();
211
211
  }
212
- }, Q = () => {
213
- f || F(e.editor.getCommandStates());
214
- }, k = () => {
212
+ }, J = () => {
213
+ f || R(e.editor.getCommandStates());
214
+ }, x = () => {
215
215
  s.dataset.visible = "false", s.textContent = "";
216
- }, Z = (a) => {
216
+ }, Q = (a) => {
217
217
  const l = a.dataset.tooltip;
218
218
  if (!m || !l) return;
219
219
  const b = a.getBoundingClientRect();
220
220
  s.textContent = l, s.dataset.visible = "true", s.style.left = `${b.left + b.width / 2}px`, s.style.top = `${b.top - pt}px`;
221
+ }, F = (a) => {
222
+ const l = D(a.target);
223
+ l && Q(l);
221
224
  }, O = (a) => {
222
- const l = P(a.target);
223
- l && Z(l);
224
- }, j = (a) => {
225
- const l = a.relatedTarget, b = P(a.target);
226
- b && l instanceof Node && b.contains(l) || k();
227
- }, _ = (a) => {
225
+ const l = a.relatedTarget, b = D(a.target);
226
+ b && l instanceof Node && b.contains(l) || x();
227
+ }, B = (a) => {
228
228
  if (!(a instanceof HTMLButtonElement) || a.disabled) return;
229
229
  const l = n.find((b) => b.id === a.dataset.bridgerteToolbarItemId);
230
230
  if (l) {
@@ -234,7 +234,7 @@ function Et(t, e) {
234
234
  menuId: l.id,
235
235
  command: l.command,
236
236
  panel: l.payloadPanel,
237
- currentValues: at(l, e.editor.getCommandStates()),
237
+ currentValues: rt(l, e.editor.getCommandStates()),
238
238
  anchorRect: {
239
239
  x: b.left,
240
240
  y: b.top,
@@ -247,67 +247,67 @@ function Et(t, e) {
247
247
  e.editor.executeCommand(l.command);
248
248
  }
249
249
  }, C = (a, l = !1) => {
250
- const b = $(
250
+ const b = U(
251
251
  d,
252
252
  a.dataset.bridgerteToolbarGroupId
253
253
  );
254
254
  if (!(!b || a.disabled)) {
255
255
  if ((o == null ? void 0 : o.groupKey) === b.key) {
256
256
  if (l) {
257
- U(u, 0);
257
+ Y(u, 0);
258
258
  return;
259
259
  }
260
- T();
260
+ E();
261
261
  return;
262
262
  }
263
263
  o = {
264
264
  groupKey: b.key,
265
265
  button: a,
266
266
  items: b.items
267
- }, k(), G(u, o, v, r), D(t, o), R(), l && U(u, 0);
267
+ }, x(), G(u, o, v, r), P(t, o), M(), l && Y(u, 0);
268
268
  }
269
- }, S = (a) => {
270
- const l = W(a.target);
269
+ }, k = (a) => {
270
+ const l = V(a.target);
271
271
  if (l) {
272
272
  if (a.preventDefault(), a.stopPropagation(), A.consumeSuppressedClick(l)) return;
273
273
  C(l);
274
274
  return;
275
275
  }
276
- const b = P(a.target);
277
- b && (a.preventDefault(), a.stopPropagation(), !A.consumeSuppressedClick(b) && (_(b), T()));
278
- }, q = (a) => {
276
+ const b = D(a.target);
277
+ b && (a.preventDefault(), a.stopPropagation(), !A.consumeSuppressedClick(b) && (B(b), E()));
278
+ }, j = (a) => {
279
279
  if (o && u.contains(document.activeElement)) {
280
- it(
280
+ st(
281
281
  a,
282
282
  u,
283
283
  o.button,
284
- _,
285
- T
284
+ B,
285
+ E
286
286
  );
287
287
  return;
288
288
  }
289
- const l = W(a.target);
289
+ const l = V(a.target);
290
290
  if (l && (a.key === "Enter" || a.key === " " || a.key === "ArrowDown")) {
291
291
  a.preventDefault(), a.stopPropagation(), C(l, !0);
292
292
  return;
293
293
  }
294
- a.key === "Escape" && T();
294
+ a.key === "Escape" && E();
295
295
  };
296
296
  t.classList.add("bridgerte__toolbar"), s.className = "bridgerte__toolbar-tooltip", s.dataset.visible = "false", u.className = "bridgerte__floating-menu bridgerte__toolbar-group-menu", u.dataset.visible = "false", u.setAttribute("role", "menu"), t.dataset.placement = i, t.setAttribute("role", "toolbar"), t.setAttribute(
297
297
  "aria-label",
298
298
  i === "bottom" ? "BridgeRTE tabbar" : "BridgeRTE toolbar"
299
- ), t.addEventListener("click", S), u.addEventListener("click", S), document.addEventListener("keydown", q), m && (t.addEventListener("mouseover", O), t.addEventListener("mouseout", j)), t.addEventListener("focusout", k), E();
299
+ ), t.addEventListener("click", k), u.addEventListener("click", k), document.addEventListener("keydown", j), m && (t.addEventListener("mouseover", F), t.addEventListener("mouseout", O)), t.addEventListener("focusout", x), y();
300
300
  const A = bt(
301
301
  t,
302
302
  u,
303
303
  C,
304
- _,
305
- T
306
- ), tt = e.editor.subscribeCommandStateChange(F);
304
+ B,
305
+ E
306
+ ), Z = e.editor.subscribeCommandStateChange(R);
307
307
  return {
308
- update: Q,
308
+ update: J,
309
309
  destroy() {
310
- f || (f = !0, tt(), T(), t.removeEventListener("click", S), u.removeEventListener("click", S), document.removeEventListener("keydown", q), A.destroy(), m && (t.removeEventListener("mouseover", O), t.removeEventListener("mouseout", j)), h(), L(), t.removeEventListener("focusout", k), s.remove(), u.remove(), t.classList.remove("bridgerte__toolbar"), delete t.dataset.placement, t.textContent = "", t.removeAttribute("role"), t.removeAttribute("aria-label"));
310
+ f || (f = !0, Z(), E(), t.removeEventListener("click", k), u.removeEventListener("click", k), document.removeEventListener("keydown", j), A.destroy(), m && (t.removeEventListener("mouseover", F), t.removeEventListener("mouseout", O)), h(), T(), t.removeEventListener("focusout", x), s.remove(), u.remove(), t.classList.remove("bridgerte__toolbar"), delete t.dataset.placement, t.textContent = "", t.removeAttribute("role"), t.removeAttribute("aria-label"));
311
311
  }
312
312
  };
313
313
  }
@@ -325,13 +325,13 @@ const gt = /[\u200B-\u200D\uFEFF]/g, vt = [
325
325
  "svg",
326
326
  "math",
327
327
  '[data-type="mention"]'
328
- ].join(","), z = (t) => (t == null ? void 0 : t.replace(gt, "").trim()) ?? "", Tt = (t) => {
329
- if (!z(t)) return !1;
328
+ ].join(","), W = (t) => (t == null ? void 0 : t.replace(gt, "").trim()) ?? "", Tt = (t) => {
329
+ if (!W(t)) return !1;
330
330
  const e = document.createElement("template");
331
- return e.innerHTML = t, !!(z(e.content.textContent) || e.content.querySelector(vt));
331
+ return e.innerHTML = t, !!(W(e.content.textContent) || e.content.querySelector(vt));
332
332
  };
333
333
  export {
334
334
  Et as c,
335
335
  Tt as h
336
336
  };
337
- //# sourceMappingURL=index-ZeQUaPbe.js.map
337
+ //# sourceMappingURL=index-Bit2Kbbe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Bit2Kbbe.js","sources":["../../dom/src/menuIcon/uiIcons.ts","../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/groupMenuInteraction.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 {\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\n\nconst toolbarGroupTouchMoveTolerancePx = 8;\n\nconst isInsideNode = (container: HTMLElement, target: EventTarget | null) => (\n target instanceof Node && container.contains(target)\n);\n\nconst getClosestButton = (\n target: EventTarget | null,\n selector: string\n) => (\n target instanceof Element ? target.closest<HTMLButtonElement>(selector) : null\n);\n\n/**\n * 创建 toolbar 收纳菜单交互控制器。\n *\n * 这个控制器只接管收纳菜单链路:更多入口和收纳菜单项。\n * 普通 toolbar 按钮保留原生 click,避免 H5 横向滚动和点击链路被菜单控制器误拦;\n * 收纳菜单仍在 PC 鼠标按下阶段保护 selection,H5 tap 在 touchend 判定后提交。\n */\nexport const createToolbarGroupMenuInteraction = (\n container: HTMLElement,\n groupMenuElement: HTMLElement,\n toggleGroupMenu: (button: HTMLButtonElement) => void,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n let pendingTouch: {\n button: HTMLButtonElement;\n kind: 'group' | 'menu-item';\n startX: number;\n startY: number;\n } | null = null;\n let suppressNextClickButton: HTMLButtonElement | null = null;\n\n const getInteractiveButtonFromTarget = (target: EventTarget | null) => (\n getClosestButton(target, toolbarGroupButtonSelector)\n ?? (\n isInsideNode(groupMenuElement, target)\n ? getClosestButton(target, toolbarExecutableButtonSelector)\n : null\n )\n );\n\n const handlePressStart = (event: PointerEvent | MouseEvent) => {\n const button = getInteractiveButtonFromTarget(event.target);\n\n if (!button) return;\n\n /*\n * toolbar 按钮属于编辑器工具区。鼠标按下阶段阻止默认 focus 转移,保留正文\n * selection;触屏不能在这里拦截,否则 H5 横向滚动会被当成按钮按下吞掉。\n */\n if (event instanceof PointerEvent && event.pointerType !== 'mouse') return;\n\n event.preventDefault();\n };\n\n const handleTouchStart = (event: TouchEvent) => {\n const touch = event.touches[0];\n const groupButton = getClosestButton(event.target, toolbarGroupButtonSelector);\n const menuItemButton = isInsideNode(groupMenuElement, event.target)\n ? getClosestButton(event.target, toolbarExecutableButtonSelector)\n : null;\n const button = groupButton ?? menuItemButton;\n\n if (!button || !touch) return;\n\n /*\n * touchstart 只记录候选 tap,不阻止默认行为。移动端需要先让浏览器识别横向滚动;\n * 真正的点击会在 touchend 里按位移阈值提交并拦截尾随 click。\n */\n pendingTouch = {\n button,\n kind: groupButton ? 'group' : 'menu-item',\n startX: touch.clientX,\n startY: touch.clientY\n };\n };\n\n const clearPendingTouch = () => {\n pendingTouch = null;\n };\n\n const handleTouchEnd = (event: TouchEvent) => {\n if (!pendingTouch) return;\n\n const touchState = pendingTouch;\n const touch = event.changedTouches[0];\n const endButton = getInteractiveButtonFromTarget(event.target);\n\n pendingTouch = null;\n if (!touch || endButton !== touchState.button) return;\n\n const deltaX = Math.abs(touch.clientX - touchState.startX);\n const deltaY = Math.abs(touch.clientY - touchState.startY);\n\n if (\n deltaX > toolbarGroupTouchMoveTolerancePx\n || deltaY > toolbarGroupTouchMoveTolerancePx\n ) return;\n\n event.preventDefault();\n event.stopPropagation();\n suppressNextClickButton = touchState.button;\n\n if (touchState.kind === 'group') {\n toggleGroupMenu(touchState.button);\n return;\n }\n\n executeToolbarButton(touchState.button);\n closeGroupMenu();\n };\n\n const handleDocumentPointerDown = (event: PointerEvent) => {\n if (\n isInsideNode(container, event.target)\n || isInsideNode(groupMenuElement, event.target)\n ) return;\n\n closeGroupMenu();\n };\n\n container.addEventListener('pointerdown', handlePressStart);\n container.addEventListener('mousedown', handlePressStart);\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchend', handleTouchEnd);\n container.addEventListener('touchcancel', clearPendingTouch);\n groupMenuElement.addEventListener('pointerdown', handlePressStart);\n groupMenuElement.addEventListener('mousedown', handlePressStart);\n groupMenuElement.addEventListener('touchstart', handleTouchStart, { passive: false });\n groupMenuElement.addEventListener('touchend', handleTouchEnd);\n groupMenuElement.addEventListener('touchcancel', clearPendingTouch);\n document.addEventListener('pointerdown', handleDocumentPointerDown, true);\n\n return {\n consumeSuppressedClick(button: HTMLButtonElement) {\n if (suppressNextClickButton !== button) return false;\n\n suppressNextClickButton = null;\n return true;\n },\n destroy() {\n container.removeEventListener('pointerdown', handlePressStart);\n container.removeEventListener('mousedown', handlePressStart);\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchend', handleTouchEnd);\n container.removeEventListener('touchcancel', clearPendingTouch);\n groupMenuElement.removeEventListener('pointerdown', handlePressStart);\n groupMenuElement.removeEventListener('mousedown', handlePressStart);\n groupMenuElement.removeEventListener('touchstart', handleTouchStart);\n groupMenuElement.removeEventListener('touchend', handleTouchEnd);\n groupMenuElement.removeEventListener('touchcancel', clearPendingTouch);\n document.removeEventListener('pointerdown', handleDocumentPointerDown, true);\n }\n };\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 { createToolbarGroupMenuInteraction } from './groupMenuInteraction';\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 if (!groupMenuState && !groupMenuFloatingLayer) return;\n\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 if (groupMenuInteraction.consumeSuppressedClick(groupButton)) 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 (groupMenuInteraction.consumeSuppressedClick(button)) return;\n\n executeToolbarButton(button);\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('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 const groupMenuInteraction = createToolbarGroupMenuInteraction(\n container,\n groupMenuElement,\n toggleGroupMenu,\n executeToolbarButton,\n closeGroupMenu\n );\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('keydown', handleKeyDown);\n groupMenuInteraction.destroy();\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","toolbarGroupTouchMoveTolerancePx","isInsideNode","target","getClosestButton","selector","createToolbarGroupMenuInteraction","groupMenuElement","toggleGroupMenu","pendingTouch","suppressNextClickButton","getInteractiveButtonFromTarget","handlePressStart","handleTouchStart","touch","groupButton","menuItemButton","clearPendingTouch","handleTouchEnd","touchState","endButton","deltaX","deltaY","handleDocumentPointerDown","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","canUseHoverTooltip","getToolbarButtonFromTarget","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","overlayHost","destroyed","latestCommandStates","groupMenuFloatingLayer","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","menuItem","getPayloadPanelCurrentValues","shouldFocusMenu","groupItem","handleClick","groupMenuInteraction","handleKeyDown","unsubscribe","invisibleTextPattern","meaningfulHtmlContentSelector","normalizeHtmlText","text","hasMeaningfulHtmlContent","html","template"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ "use strict";const q=require("./native-spec.cjs"),f=require("./index-BTtX4aJu.cjs"),O={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
+ `},V=t=>Array.from(t.querySelectorAll(".bridgerte__toolbar-group-menu-item")).filter(e=>!e.disabled),j=(t,e)=>{const l=V(t)[e];l&&l.focus()},Z=(t,e,i,l,u)=>{var s,d;const n=V(e),r=document.activeElement instanceof HTMLButtonElement?n.indexOf(document.activeElement):-1,m=v=>{var o;if(n.length===0)return;const h=((r>=0?r:0)+v+n.length)%n.length;(o=n[h])==null||o.focus()};switch(t.key){case"ArrowDown":t.preventDefault(),m(1);break;case"ArrowUp":t.preventDefault(),m(-1);break;case"Home":t.preventDefault(),(s=n[0])==null||s.focus();break;case"End":t.preventDefault(),(d=n.at(-1))==null||d.focus();break;case"Enter":case" ":document.activeElement instanceof HTMLButtonElement&&(t.preventDefault(),l(document.activeElement),u(),i.focus());break;case"Escape":t.preventDefault(),i.focus(),u();break}},x="button[data-bridgerte-toolbar-group-id]",tt="button[data-bridgerte-toolbar-item-id]",M=[tt,".bridgerte__toolbar-group-menu-item"].join(","),et=(t,e)=>{const i=t.map(l=>f.getMenuStateForItem(l,e));return{active:i.some(l=>l.active),disabled:i.length>0&&i.every(l=>l.disabled)}},ot=(t,e,i,l,u)=>{const n=f.getMenuStateForItem(e,i),r=document.createElement("button"),m=l[e.icon]??f.defaultMenuIcons[e.icon];r.type="button",r.className="bridgerte__toolbar-button",r.disabled=n.disabled,r.dataset.active=String(n.active),r.dataset.bridgerteToolbarItemId=e.id,r.setAttribute("aria-label",e.label),r.setAttribute("aria-pressed",String(n.active)),u&&(r.dataset.tooltip=e.label),f.appendMenuIcon(r,m,e.label),t.append(r)},nt=(t,e,i,l,u)=>{const n=document.createElement("button"),r=et(e.items,i),m=e.icon?l[e.icon]??f.defaultMenuIcons[e.icon]:O.toolbarGroup,s=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=e.key,n.dataset.open="false",n.setAttribute("aria-label",e.title),n.setAttribute("aria-haspopup","menu"),n.setAttribute("aria-expanded","false"),n.setAttribute("aria-pressed",String(r.active)),u&&(n.dataset.tooltip=e.title),f.appendMenuIcon(n,m,e.title),s.className="bridgerte__toolbar-group-indicator",s.setAttribute("aria-hidden","true"),s.innerHTML=O.chevronDown,n.append(s),t.append(n)},rt=(t,e,i,l,u)=>{t.textContent="",e.forEach(n=>{if(n.type==="separator"){const m=document.createElement("span");m.className="bridgerte__toolbar-separator",m.dataset.separatorId=n.key,m.setAttribute("aria-hidden","true"),t.append(m);return}if(n.type==="button"){ot(t,n.item,i,l,u);return}const r=document.createElement("div");r.className="bridgerte__toolbar-group",r.dataset.group=n.key,r.setAttribute("aria-label",n.title),t.append(r),nt(r,n,i,l,u)})},G=(t,e,i,l)=>{if(t.textContent="",!e){t.dataset.visible="false";return}e.items.forEach(u=>{const n=f.getMenuStateForItem(u,i),r=document.createElement("button"),m=l[u.icon]??f.defaultMenuIcons[u.icon],s=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)),f.appendMenuIcon(r,m,u.label),s.className="bridgerte__toolbar-group-menu-label",s.textContent=u.label,r.append(s),t.append(r)}),t.dataset.visible="true",t.style.minWidth=`${e.button.offsetWidth}px`},I=(t,e)=>{t.querySelectorAll(x).forEach(i=>{const l=(e==null?void 0:e.groupKey)===i.dataset.bridgerteToolbarGroupId;i.dataset.open=String(l),i.setAttribute("aria-expanded",String(l))})},X=(t,e)=>t.find(i=>i.type==="group"&&i.key===e),Y=8,_=(t,e)=>e instanceof Node&&t.contains(e),B=(t,e)=>t instanceof Element?t.closest(e):null,at=(t,e,i,l,u)=>{let n=null,r=null;const m=o=>B(o,x)??(_(e,o)?B(o,M):null),s=o=>{m(o.target)&&(o instanceof PointerEvent&&o.pointerType!=="mouse"||o.preventDefault())},d=o=>{const p=o.touches[0],y=B(o.target,x),w=_(e,o.target)?B(o.target,M):null,T=y??w;!T||!p||(n={button:T,kind:y?"group":"menu-item",startX:p.clientX,startY:p.clientY})},v=()=>{n=null},g=o=>{if(!n)return;const p=n,y=o.changedTouches[0],w=m(o.target);if(n=null,!y||w!==p.button)return;const T=Math.abs(y.clientX-p.startX),L=Math.abs(y.clientY-p.startY);if(!(T>Y||L>Y)){if(o.preventDefault(),o.stopPropagation(),r=p.button,p.kind==="group"){i(p.button);return}l(p.button),u()}},h=o=>{_(t,o.target)||_(e,o.target)||u()};return t.addEventListener("pointerdown",s),t.addEventListener("mousedown",s),t.addEventListener("touchstart",d,{passive:!1}),t.addEventListener("touchend",g),t.addEventListener("touchcancel",v),e.addEventListener("pointerdown",s),e.addEventListener("mousedown",s),e.addEventListener("touchstart",d,{passive:!1}),e.addEventListener("touchend",g),e.addEventListener("touchcancel",v),document.addEventListener("pointerdown",h,!0),{consumeSuppressedClick(o){return r!==o?!1:(r=null,!0)},destroy(){t.removeEventListener("pointerdown",s),t.removeEventListener("mousedown",s),t.removeEventListener("touchstart",d),t.removeEventListener("touchend",g),t.removeEventListener("touchcancel",v),e.removeEventListener("pointerdown",s),e.removeEventListener("mousedown",s),e.removeEventListener("touchstart",d),e.removeEventListener("touchend",g),e.removeEventListener("touchcancel",v),document.removeEventListener("pointerdown",h,!0)}}},st=8,it=6,ct=()=>{var t;return typeof window<"u"&&((t=window.matchMedia)==null?void 0:t.call(window,"(hover: hover) and (pointer: fine)").matches)===!0},D=t=>{const e=t instanceof Element?t.closest(M):null;return e instanceof HTMLButtonElement?e:null},U=t=>{const e=t instanceof Element?t.closest(x):null;return e instanceof HTMLButtonElement?e:null};function lt(t,e){const i=e.placement??"top",l=f.resolveMenuSchemaForDom(e.menuSchema??q.defaultMenuSchema,{menuLabels:e.menuLabels,payloadPanelConfig:e.payloadPanelConfig}),u=q.resolveToolbarMenu(e.toolbarConfig,l),n=u.flatMap(a=>a.type==="button"?[a.item]:a.type==="group"?a.items:[]),r=e.icons??{},m=ct(),s=document.createElement("div"),d=document.createElement("div"),v=t.closest(".bridgerte")??t;let g=!1,h=e.editor.getCommandStates(),o=null,p=null;const y=f.bindTouchPressedState(t,{targetSelector:["button[data-bridgerte-toolbar-item-id]","button[data-bridgerte-toolbar-group-id]"].join(",")}),w=f.bindTouchPressedState(d,{targetSelector:".bridgerte__toolbar-group-menu-item"}),T=()=>{v.append(s),v.append(d)},L=()=>{p==null||p.setOpen(!1),p==null||p.destroy(),p=null},H=()=>{o&&(L(),p=f.createFloatingLayer(o.button,d,{placement:i==="bottom"?"top-start":"bottom-start",offset:it,strategy:"fixed"}),p.setOpen(!0))},E=()=>{!o&&!p||(L(),o=null,G(d,o,h,r),I(t,o))},N=a=>{if(!g&&(h=a,o&&L(),rt(t,u,a,r,m),T(),o)){const c=Array.from(t.querySelectorAll(x)).find(Q=>Q.dataset.bridgerteToolbarGroupId===(o==null?void 0:o.groupKey)),b=X(u,o.groupKey);o=c&&b?{groupKey:o.groupKey,button:c,items:b.items}:null,G(d,o,h,r),I(t,o),o&&H()}},W=()=>{g||N(e.editor.getCommandStates())},S=()=>{s.dataset.visible="false",s.textContent=""},z=a=>{const c=a.dataset.tooltip;if(!m||!c)return;const b=a.getBoundingClientRect();s.textContent=c,s.dataset.visible="true",s.style.left=`${b.left+b.width/2}px`,s.style.top=`${b.top-st}px`},F=a=>{const c=D(a.target);c&&z(c)},K=a=>{const c=a.relatedTarget,b=D(a.target);b&&c instanceof Node&&b.contains(c)||S()},C=a=>{if(!(a instanceof HTMLButtonElement)||a.disabled)return;const c=n.find(b=>b.id===a.dataset.bridgerteToolbarItemId);if(c){if(c.payloadPanel){const b=a.getBoundingClientRect();e.editor.requestPayloadPanel({menuId:c.id,command:c.command,panel:c.payloadPanel,currentValues:f.getPayloadPanelCurrentValues(c,e.editor.getCommandStates()),anchorRect:{x:b.left,y:b.top,width:b.width,height:b.height}});return}e.editor.executeCommand(c.command)}},A=(a,c=!1)=>{const b=X(u,a.dataset.bridgerteToolbarGroupId);if(!(!b||a.disabled)){if((o==null?void 0:o.groupKey)===b.key){if(c){j(d,0);return}E();return}o={groupKey:b.key,button:a,items:b.items},S(),G(d,o,h,r),I(t,o),H(),c&&j(d,0)}},k=a=>{const c=U(a.target);if(c){if(a.preventDefault(),a.stopPropagation(),P.consumeSuppressedClick(c))return;A(c);return}const b=D(a.target);b&&(a.preventDefault(),a.stopPropagation(),!P.consumeSuppressedClick(b)&&(C(b),E()))},R=a=>{if(o&&d.contains(document.activeElement)){Z(a,d,o.button,C,E);return}const c=U(a.target);if(c&&(a.key==="Enter"||a.key===" "||a.key==="ArrowDown")){a.preventDefault(),a.stopPropagation(),A(c,!0);return}a.key==="Escape"&&E()};t.classList.add("bridgerte__toolbar"),s.className="bridgerte__toolbar-tooltip",s.dataset.visible="false",d.className="bridgerte__floating-menu bridgerte__toolbar-group-menu",d.dataset.visible="false",d.setAttribute("role","menu"),t.dataset.placement=i,t.setAttribute("role","toolbar"),t.setAttribute("aria-label",i==="bottom"?"BridgeRTE tabbar":"BridgeRTE toolbar"),t.addEventListener("click",k),d.addEventListener("click",k),document.addEventListener("keydown",R),m&&(t.addEventListener("mouseover",F),t.addEventListener("mouseout",K)),t.addEventListener("focusout",S),T();const P=at(t,d,A,C,E),J=e.editor.subscribeCommandStateChange(N);return{update:W,destroy(){g||(g=!0,J(),E(),t.removeEventListener("click",k),d.removeEventListener("click",k),document.removeEventListener("keydown",R),P.destroy(),m&&(t.removeEventListener("mouseover",F),t.removeEventListener("mouseout",K)),y(),w(),t.removeEventListener("focusout",S),s.remove(),d.remove(),t.classList.remove("bridgerte__toolbar"),delete t.dataset.placement,t.textContent="",t.removeAttribute("role"),t.removeAttribute("aria-label"))}}}const ut=/[\u200B-\u200D\uFEFF]/g,dt=["img","video","audio","iframe","table","pre","code","hr","figure","canvas","svg","math",'[data-type="mention"]'].join(","),$=t=>(t==null?void 0:t.replace(ut,"").trim())??"",bt=t=>{if(!$(t))return!1;const e=document.createElement("template");return e.innerHTML=t,!!($(e.content.textContent)||e.content.querySelector(dt))};exports.createRichTextToolbar=lt;exports.hasMeaningfulHtmlContent=bt;
36
+ //# sourceMappingURL=index-DBHtvXqM.cjs.map