bridgerte 0.9.1 → 0.9.3

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,137 +0,0 @@
1
- import { defaultMenuSchema as R, resolveToolbarMenu as k } from "./native-spec.js";
2
- import { r as N, d as X, g as H, e as F, f as G, h as O } from "./index-BQAzp56J.js";
3
- const U = 4, V = 8, $ = "button[data-bridgerte-toolbar-item-id]", q = () => {
4
- var e;
5
- return typeof window < "u" && ((e = window.matchMedia) == null ? void 0 : e.call(window, "(hover: hover) and (pointer: fine)").matches) === !0;
6
- }, h = (e) => {
7
- const r = e instanceof Element ? e.closest($) : null;
8
- return r instanceof HTMLButtonElement ? r : null;
9
- }, M = (e, r, c, m, p) => {
10
- const i = F(r, c), a = document.createElement("button"), n = m[r.icon] ?? G[r.icon];
11
- a.type = "button", a.className = "bridgerte__toolbar-button", a.disabled = i.disabled, a.dataset.active = String(i.active), a.dataset.bridgerteToolbarItemId = r.id, a.setAttribute("aria-label", r.label), a.setAttribute("aria-pressed", String(i.active)), p && (a.dataset.tooltip = r.label), O(a, n, r.label), e.append(a);
12
- }, j = (e, r, c, m, p) => {
13
- e.textContent = "";
14
- let i = "", a = null;
15
- r.forEach((n) => {
16
- if (n.type === "separator") {
17
- i = "", a = null;
18
- const d = document.createElement("span");
19
- d.className = "bridgerte__toolbar-separator", d.dataset.separatorId = n.key, d.setAttribute("aria-hidden", "true"), e.append(d);
20
- return;
21
- }
22
- const s = n.type === "button" ? n.item.group : n.key;
23
- (!a || i !== s) && (i = s, a = document.createElement("div"), a.className = "bridgerte__toolbar-group", a.dataset.group = s, n.type === "group" && a.setAttribute("aria-label", n.title), e.append(a));
24
- const g = a;
25
- if (n.type === "button") {
26
- M(
27
- g,
28
- n.item,
29
- c,
30
- m,
31
- p
32
- );
33
- return;
34
- }
35
- n.items.forEach((d) => {
36
- M(
37
- g,
38
- d,
39
- c,
40
- m,
41
- p
42
- );
43
- });
44
- });
45
- };
46
- function J(e, r) {
47
- const c = r.placement ?? "top", m = N(r.menuSchema ?? R, {
48
- menuLabels: r.menuLabels,
49
- payloadPanelConfig: r.payloadPanelConfig
50
- }), p = k(r.toolbarConfig, m), i = p.flatMap((t) => t.type === "button" ? [t.item] : t.type === "group" ? t.items : []), a = r.icons ?? {}, n = q(), s = document.createElement("div"), g = e.closest(".bridgerte") ?? e;
51
- let d = !1, u = null, f = !1;
52
- const _ = X(e, {
53
- targetSelector: "button[data-bridgerte-toolbar-item-id]"
54
- }), T = () => {
55
- g.append(s);
56
- }, E = (t) => {
57
- d || (j(e, p, t, a, n), T());
58
- }, w = () => {
59
- d || E(r.editor.getCommandStates());
60
- }, b = () => {
61
- s.dataset.visible = "false", s.textContent = "";
62
- }, D = (t) => {
63
- const o = t.dataset.tooltip;
64
- if (!n || !o || u) return;
65
- const l = t.getBoundingClientRect();
66
- s.textContent = o, s.dataset.visible = "true", s.style.left = `${l.left + l.width / 2}px`, s.style.top = `${l.top - V}px`;
67
- }, y = (t) => {
68
- const o = h(t.target);
69
- o && D(o);
70
- }, L = (t) => {
71
- const o = t.relatedTarget, l = h(t.target);
72
- l && o instanceof Node && l.contains(o) || b();
73
- }, C = () => {
74
- u = null, delete e.dataset.dragging, document.removeEventListener("pointermove", S), document.removeEventListener("pointerup", v), document.removeEventListener("pointercancel", v);
75
- }, S = (t) => {
76
- if (!u) return;
77
- const o = u.startClientX - t.clientX;
78
- Math.abs(o) > U && (u.hasDragged = !0, f = !0, b()), e.scrollLeft = u.startScrollLeft + o;
79
- }, v = (t) => {
80
- const o = u;
81
- C(), o && t.type !== "pointercancel" && o.pointerType !== "mouse" && !o.hasDragged && o.startButton && (P(o.startButton), f = !0);
82
- }, x = (t) => {
83
- if (t.pointerType === "mouse" && t.button !== 0) return;
84
- const o = h(t.target);
85
- t.preventDefault(), u = {
86
- startClientX: t.clientX,
87
- startScrollLeft: e.scrollLeft,
88
- pointerType: t.pointerType,
89
- hasDragged: !1,
90
- startButton: o ?? void 0
91
- }, e.dataset.dragging = "true", b(), document.addEventListener("pointermove", S), document.addEventListener("pointerup", v), document.addEventListener("pointercancel", v);
92
- }, P = (t) => {
93
- if (!(t instanceof HTMLButtonElement) || t.disabled) return;
94
- const o = i.find((l) => l.id === t.dataset.bridgerteToolbarItemId);
95
- if (o) {
96
- if (r.editor.focus(), o.payloadPanel) {
97
- const l = t.getBoundingClientRect();
98
- r.editor.requestPayloadPanel({
99
- menuId: o.id,
100
- command: o.command,
101
- panel: o.payloadPanel,
102
- currentValues: H(o, r.editor.getCommandStates()),
103
- anchorRect: {
104
- x: l.left,
105
- y: l.top,
106
- width: l.width,
107
- height: l.height
108
- }
109
- });
110
- return;
111
- }
112
- r.editor.executeCommand(o.command);
113
- }
114
- }, B = (t) => {
115
- if (f) {
116
- f = !1, t.preventDefault(), t.stopPropagation();
117
- return;
118
- }
119
- const o = h(t.target);
120
- o && P(o);
121
- };
122
- e.classList.add("bridgerte__toolbar"), s.className = "bridgerte__toolbar-tooltip", s.dataset.visible = "false", e.dataset.placement = c, e.setAttribute("role", "toolbar"), e.setAttribute(
123
- "aria-label",
124
- c === "bottom" ? "BridgeRTE tabbar" : "BridgeRTE toolbar"
125
- ), e.addEventListener("pointerdown", x, !0), e.addEventListener("click", B), n && (e.addEventListener("mouseover", y), e.addEventListener("mouseout", L)), e.addEventListener("focusout", b), T();
126
- const A = r.editor.subscribeCommandStateChange(E);
127
- return {
128
- update: w,
129
- destroy() {
130
- d || (d = !0, C(), A(), e.removeEventListener("pointerdown", x, !0), e.removeEventListener("click", B), n && (e.removeEventListener("mouseover", y), e.removeEventListener("mouseout", L)), _(), e.removeEventListener("focusout", b), s.remove(), e.classList.remove("bridgerte__toolbar"), delete e.dataset.placement, e.textContent = "", e.removeAttribute("role"), e.removeAttribute("aria-label"));
131
- }
132
- };
133
- }
134
- export {
135
- J as c
136
- };
137
- //# sourceMappingURL=index-CeYJbOQi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-CeYJbOQi.js","sources":["../../dom/src/richTextToolbar/index.ts"],"sourcesContent":["import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu,\n type MenuItem,\n type ResolvedToolbarItem\n} from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons\n} from './icons';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getMenuStateForItem,\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport type {\n RichTextToolbarAPI,\n RichTextToolbarIcons,\n RichTextToolbarOptions,\n ToolbarDragState\n} from './type';\n\nconst toolbarDragClickThresholdPx = 4;\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\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>(toolbarButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\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 renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n let currentGroup = '';\n let groupElement: HTMLDivElement | null = null;\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n currentGroup = '';\n groupElement = null;\n\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 const nextGroup = toolbarItem.type === 'button' ? toolbarItem.item.group : toolbarItem.key;\n\n if (!groupElement || currentGroup !== nextGroup) {\n currentGroup = nextGroup;\n groupElement = document.createElement('div');\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = nextGroup;\n if (toolbarItem.type === 'group') {\n groupElement.setAttribute('aria-label', toolbarItem.title);\n }\n toolbarElement.append(groupElement);\n }\n\n const activeGroupElement = groupElement;\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n activeGroupElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n toolbarItem.items.forEach((item) => {\n renderToolbarButton(\n activeGroupElement,\n item,\n commandStates,\n icons,\n enableTooltip\n );\n });\n });\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 overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let dragState: ToolbarDragState | null = null;\n let shouldSuppressNextClick = false;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: 'button[data-bridgerte-toolbar-item-id]'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\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 || dragState) 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 stopToolbarDrag = () => {\n dragState = null;\n\n delete container.dataset.dragging;\n // 拖动过程中监听挂在 document 上,松手或 destroy 必须统一清掉,避免离开 toolbar 后残留滚动状态。\n document.removeEventListener('pointermove', handlePointerMove);\n document.removeEventListener('pointerup', handlePointerUp);\n document.removeEventListener('pointercancel', handlePointerUp);\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n if (!dragState) return;\n\n const deltaX = dragState.startClientX - event.clientX;\n\n if (Math.abs(deltaX) > toolbarDragClickThresholdPx) {\n dragState.hasDragged = true;\n shouldSuppressNextClick = true;\n hideTooltip();\n }\n\n container.scrollLeft = dragState.startScrollLeft + deltaX;\n };\n\n const handlePointerUp = (event: PointerEvent) => {\n const currentDragState = dragState;\n\n stopToolbarDrag();\n if (\n currentDragState\n && event.type !== 'pointercancel'\n && currentDragState.pointerType !== 'mouse'\n && !currentDragState.hasDragged\n && currentDragState.startButton\n ) {\n executeToolbarButton(currentDragState.startButton);\n shouldSuppressNextClick = true;\n }\n };\n\n const handlePointerDown = (event: PointerEvent) => {\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n\n const startButton = getToolbarButtonFromTarget(event.target);\n\n // 点击和拖动 toolbar 都要保留编辑区 selection,命令才能继续作用在原选区。\n event.preventDefault();\n dragState = {\n startClientX: event.clientX,\n startScrollLeft: container.scrollLeft,\n pointerType: event.pointerType,\n hasDragged: false,\n startButton: startButton ?? undefined\n };\n container.dataset.dragging = 'true';\n hideTooltip();\n // pointermove 放到 document,保证用户按住 X 轴拖出 toolbar 后仍能完成滚动和释放。\n document.addEventListener('pointermove', handlePointerMove);\n document.addEventListener('pointerup', handlePointerUp);\n document.addEventListener('pointercancel', handlePointerUp);\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 options.editor.focus();\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 handleClick = (event: MouseEvent) => {\n if (shouldSuppressNextClick) {\n shouldSuppressNextClick = false;\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n executeToolbarButton(button);\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\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', handlePointerDown, true);\n container.addEventListener('click', handleClick);\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 stopToolbarDrag();\n unsubscribe();\n container.removeEventListener('pointerdown', handlePointerDown, true);\n container.removeEventListener('click', handleClick);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.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"],"names":["toolbarDragClickThresholdPx","toolbarTooltipOffsetPx","toolbarButtonSelector","canUseHoverTooltip","_a","getToolbarButtonFromTarget","target","button","renderToolbarButton","groupElement","item","commandStates","icons","enableTooltip","state","getMenuStateForItem","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbar","toolbarElement","toolbarItems","currentGroup","toolbarItem","separatorElement","nextGroup","activeGroupElement","createRichTextToolbar","container","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","overlayHost","destroyed","dragState","shouldSuppressNextClick","clearToolbarPressedState","bindTouchPressedState","mountToolbarOverlays","renderStates","states","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","event","handleTooltipLeave","relatedTarget","stopToolbarDrag","handlePointerMove","handlePointerUp","deltaX","currentDragState","executeToolbarButton","handlePointerDown","startButton","menuItem","getPayloadPanelCurrentValues","handleClick","unsubscribe"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- "use strict";const _=require("./native-spec.cjs"),b=require("./index-Bui5UnkQ.cjs"),N=4,X=8,H="button[data-bridgerte-toolbar-item-id]",q=()=>{var e;return typeof window<"u"&&((e=window.matchMedia)==null?void 0:e.call(window,"(hover: hover) and (pointer: fine)").matches)===!0},T=e=>{const r=e instanceof Element?e.closest(H):null;return r instanceof HTMLButtonElement?r:null},w=(e,r,c,m,p)=>{const i=b.getMenuStateForItem(r,c),a=document.createElement("button"),n=m[r.icon]??b.defaultMenuIcons[r.icon];a.type="button",a.className="bridgerte__toolbar-button",a.disabled=i.disabled,a.dataset.active=String(i.active),a.dataset.bridgerteToolbarItemId=r.id,a.setAttribute("aria-label",r.label),a.setAttribute("aria-pressed",String(i.active)),p&&(a.dataset.tooltip=r.label),b.appendMenuIcon(a,n,r.label),e.append(a)},F=(e,r,c,m,p)=>{e.textContent="";let i="",a=null;r.forEach(n=>{if(n.type==="separator"){i="",a=null;const d=document.createElement("span");d.className="bridgerte__toolbar-separator",d.dataset.separatorId=n.key,d.setAttribute("aria-hidden","true"),e.append(d);return}const s=n.type==="button"?n.item.group:n.key;(!a||i!==s)&&(i=s,a=document.createElement("div"),a.className="bridgerte__toolbar-group",a.dataset.group=s,n.type==="group"&&a.setAttribute("aria-label",n.title),e.append(a));const f=a;if(n.type==="button"){w(f,n.item,c,m,p);return}n.items.forEach(d=>{w(f,d,c,m,p)})})};function G(e,r){const c=r.placement??"top",m=b.resolveMenuSchemaForDom(r.menuSchema??_.defaultMenuSchema,{menuLabels:r.menuLabels,payloadPanelConfig:r.payloadPanelConfig}),p=_.resolveToolbarMenu(r.toolbarConfig,m),i=p.flatMap(t=>t.type==="button"?[t.item]:t.type==="group"?t.items:[]),a=r.icons??{},n=q(),s=document.createElement("div"),f=e.closest(".bridgerte")??e;let d=!1,u=null,v=!1;const D=b.bindTouchPressedState(e,{targetSelector:"button[data-bridgerte-toolbar-item-id]"}),E=()=>{f.append(s)},y=t=>{d||(F(e,p,t,a,n),E())},R=()=>{d||y(r.editor.getCommandStates())},g=()=>{s.dataset.visible="false",s.textContent=""},A=t=>{const o=t.dataset.tooltip;if(!n||!o||u)return;const l=t.getBoundingClientRect();s.textContent=o,s.dataset.visible="true",s.style.left=`${l.left+l.width/2}px`,s.style.top=`${l.top-X}px`},L=t=>{const o=T(t.target);o&&A(o)},S=t=>{const o=t.relatedTarget,l=T(t.target);l&&o instanceof Node&&l.contains(o)||g()},C=()=>{u=null,delete e.dataset.dragging,document.removeEventListener("pointermove",x),document.removeEventListener("pointerup",h),document.removeEventListener("pointercancel",h)},x=t=>{if(!u)return;const o=u.startClientX-t.clientX;Math.abs(o)>N&&(u.hasDragged=!0,v=!0,g()),e.scrollLeft=u.startScrollLeft+o},h=t=>{const o=u;C(),o&&t.type!=="pointercancel"&&o.pointerType!=="mouse"&&!o.hasDragged&&o.startButton&&(B(o.startButton),v=!0)},P=t=>{if(t.pointerType==="mouse"&&t.button!==0)return;const o=T(t.target);t.preventDefault(),u={startClientX:t.clientX,startScrollLeft:e.scrollLeft,pointerType:t.pointerType,hasDragged:!1,startButton:o??void 0},e.dataset.dragging="true",g(),document.addEventListener("pointermove",x),document.addEventListener("pointerup",h),document.addEventListener("pointercancel",h)},B=t=>{if(!(t instanceof HTMLButtonElement)||t.disabled)return;const o=i.find(l=>l.id===t.dataset.bridgerteToolbarItemId);if(o){if(r.editor.focus(),o.payloadPanel){const l=t.getBoundingClientRect();r.editor.requestPayloadPanel({menuId:o.id,command:o.command,panel:o.payloadPanel,currentValues:b.getPayloadPanelCurrentValues(o,r.editor.getCommandStates()),anchorRect:{x:l.left,y:l.top,width:l.width,height:l.height}});return}r.editor.executeCommand(o.command)}},M=t=>{if(v){v=!1,t.preventDefault(),t.stopPropagation();return}const o=T(t.target);o&&B(o)};e.classList.add("bridgerte__toolbar"),s.className="bridgerte__toolbar-tooltip",s.dataset.visible="false",e.dataset.placement=c,e.setAttribute("role","toolbar"),e.setAttribute("aria-label",c==="bottom"?"BridgeRTE tabbar":"BridgeRTE toolbar"),e.addEventListener("pointerdown",P,!0),e.addEventListener("click",M),n&&(e.addEventListener("mouseover",L),e.addEventListener("mouseout",S)),e.addEventListener("focusout",g),E();const k=r.editor.subscribeCommandStateChange(y);return{update:R,destroy(){d||(d=!0,C(),k(),e.removeEventListener("pointerdown",P,!0),e.removeEventListener("click",M),n&&(e.removeEventListener("mouseover",L),e.removeEventListener("mouseout",S)),D(),e.removeEventListener("focusout",g),s.remove(),e.classList.remove("bridgerte__toolbar"),delete e.dataset.placement,e.textContent="",e.removeAttribute("role"),e.removeAttribute("aria-label"))}}}exports.createRichTextToolbar=G;
2
- //# sourceMappingURL=index-DAlyGWXO.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-DAlyGWXO.cjs","sources":["../../dom/src/richTextToolbar/index.ts"],"sourcesContent":["import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu,\n type MenuItem,\n type ResolvedToolbarItem\n} from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons\n} from './icons';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getMenuStateForItem,\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport type {\n RichTextToolbarAPI,\n RichTextToolbarIcons,\n RichTextToolbarOptions,\n ToolbarDragState\n} from './type';\n\nconst toolbarDragClickThresholdPx = 4;\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\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>(toolbarButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\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 renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n let currentGroup = '';\n let groupElement: HTMLDivElement | null = null;\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n currentGroup = '';\n groupElement = null;\n\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 const nextGroup = toolbarItem.type === 'button' ? toolbarItem.item.group : toolbarItem.key;\n\n if (!groupElement || currentGroup !== nextGroup) {\n currentGroup = nextGroup;\n groupElement = document.createElement('div');\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = nextGroup;\n if (toolbarItem.type === 'group') {\n groupElement.setAttribute('aria-label', toolbarItem.title);\n }\n toolbarElement.append(groupElement);\n }\n\n const activeGroupElement = groupElement;\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n activeGroupElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n toolbarItem.items.forEach((item) => {\n renderToolbarButton(\n activeGroupElement,\n item,\n commandStates,\n icons,\n enableTooltip\n );\n });\n });\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 overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let dragState: ToolbarDragState | null = null;\n let shouldSuppressNextClick = false;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: 'button[data-bridgerte-toolbar-item-id]'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\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 || dragState) 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 stopToolbarDrag = () => {\n dragState = null;\n\n delete container.dataset.dragging;\n // 拖动过程中监听挂在 document 上,松手或 destroy 必须统一清掉,避免离开 toolbar 后残留滚动状态。\n document.removeEventListener('pointermove', handlePointerMove);\n document.removeEventListener('pointerup', handlePointerUp);\n document.removeEventListener('pointercancel', handlePointerUp);\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n if (!dragState) return;\n\n const deltaX = dragState.startClientX - event.clientX;\n\n if (Math.abs(deltaX) > toolbarDragClickThresholdPx) {\n dragState.hasDragged = true;\n shouldSuppressNextClick = true;\n hideTooltip();\n }\n\n container.scrollLeft = dragState.startScrollLeft + deltaX;\n };\n\n const handlePointerUp = (event: PointerEvent) => {\n const currentDragState = dragState;\n\n stopToolbarDrag();\n if (\n currentDragState\n && event.type !== 'pointercancel'\n && currentDragState.pointerType !== 'mouse'\n && !currentDragState.hasDragged\n && currentDragState.startButton\n ) {\n executeToolbarButton(currentDragState.startButton);\n shouldSuppressNextClick = true;\n }\n };\n\n const handlePointerDown = (event: PointerEvent) => {\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n\n const startButton = getToolbarButtonFromTarget(event.target);\n\n // 点击和拖动 toolbar 都要保留编辑区 selection,命令才能继续作用在原选区。\n event.preventDefault();\n dragState = {\n startClientX: event.clientX,\n startScrollLeft: container.scrollLeft,\n pointerType: event.pointerType,\n hasDragged: false,\n startButton: startButton ?? undefined\n };\n container.dataset.dragging = 'true';\n hideTooltip();\n // pointermove 放到 document,保证用户按住 X 轴拖出 toolbar 后仍能完成滚动和释放。\n document.addEventListener('pointermove', handlePointerMove);\n document.addEventListener('pointerup', handlePointerUp);\n document.addEventListener('pointercancel', handlePointerUp);\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 options.editor.focus();\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 handleClick = (event: MouseEvent) => {\n if (shouldSuppressNextClick) {\n shouldSuppressNextClick = false;\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n executeToolbarButton(button);\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\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', handlePointerDown, true);\n container.addEventListener('click', handleClick);\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 stopToolbarDrag();\n unsubscribe();\n container.removeEventListener('pointerdown', handlePointerDown, true);\n container.removeEventListener('click', handleClick);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.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"],"names":["toolbarDragClickThresholdPx","toolbarTooltipOffsetPx","toolbarButtonSelector","canUseHoverTooltip","_a","getToolbarButtonFromTarget","target","button","renderToolbarButton","groupElement","item","commandStates","icons","enableTooltip","state","getMenuStateForItem","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbar","toolbarElement","toolbarItems","currentGroup","toolbarItem","separatorElement","nextGroup","activeGroupElement","createRichTextToolbar","container","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","overlayHost","destroyed","dragState","shouldSuppressNextClick","clearToolbarPressedState","bindTouchPressedState","mountToolbarOverlays","renderStates","states","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","event","handleTooltipLeave","relatedTarget","stopToolbarDrag","handlePointerMove","handlePointerUp","deltaX","currentDragState","executeToolbarButton","handlePointerDown","startButton","menuItem","getPayloadPanelCurrentValues","handleClick","unsubscribe"],"mappings":"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"}