bridgerte 0.9.0 → 0.9.1

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.
@@ -0,0 +1,137 @@
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
@@ -0,0 +1 @@
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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"}
@@ -0,0 +1,2 @@
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
@@ -0,0 +1 @@
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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"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./index-GaS65GL0.cjs"),a=require("./bridge.cjs"),e=require("./native-spec.cjs"),t=require("./index-BDgKCpty.cjs"),r=require("./core.cjs");exports.BRIDGERTE_CONTENT_VERSION=o.BRIDGERTE_CONTENT_VERSION;exports.BRIDGERTE_TABLE_INSERT_MAX_COLS=o.BRIDGERTE_TABLE_INSERT_MAX_COLS;exports.BRIDGERTE_TABLE_INSERT_MAX_ROWS=o.BRIDGERTE_TABLE_INSERT_MAX_ROWS;exports.BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS=a.BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS;exports.BRIDGE_HEIGHT_CHANGE_THROTTLE_MS=a.BRIDGE_HEIGHT_CHANGE_THROTTLE_MS;exports.defaultBridgeEventTiming=a.defaultBridgeEventTiming;exports.isBridgeMessage=a.isBridgeMessage;exports.codeBlockLanguagePanel=e.codeBlockLanguagePanel;exports.codeBlockLanguagePayloadPanel=e.codeBlockLanguagePayloadPanel;exports.createDisabledCommandStates=e.createDisabledCommandStates;exports.defaultMenuSchema=e.defaultMenuSchema;exports.defaultToolbarConfig=e.defaultToolbarConfig;exports.getCommandStateMatchValue=e.getCommandStateMatchValue;exports.isCommandStateForCommand=e.isCommandStateForCommand;exports.isMenuItemCommandState=e.isMenuItemCommandState;exports.resolveToolbarMenu=e.resolveToolbarMenu;exports.tableHeaderMenuItems=e.tableHeaderMenuItems;exports.createFloatingLayer=t.createFloatingLayer;exports.createRichTextEditor=t.createRichTextEditor;exports.createRichTextToolbar=t.createRichTextToolbar;exports.createWebViewBridgeRuntime=t.createWebViewBridgeRuntime;exports.resolvePayloadPanelSchema=r.resolvePayloadPanelSchema;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./index-GaS65GL0.cjs"),a=require("./bridge.cjs"),e=require("./native-spec.cjs"),o=require("./index-Bui5UnkQ.cjs"),r=require("./index-DAlyGWXO.cjs"),n=require("./core.cjs");exports.BRIDGERTE_CONTENT_VERSION=t.BRIDGERTE_CONTENT_VERSION;exports.BRIDGERTE_TABLE_INSERT_MAX_COLS=t.BRIDGERTE_TABLE_INSERT_MAX_COLS;exports.BRIDGERTE_TABLE_INSERT_MAX_ROWS=t.BRIDGERTE_TABLE_INSERT_MAX_ROWS;exports.BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS=a.BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS;exports.BRIDGE_HEIGHT_CHANGE_THROTTLE_MS=a.BRIDGE_HEIGHT_CHANGE_THROTTLE_MS;exports.defaultBridgeEventTiming=a.defaultBridgeEventTiming;exports.isBridgeMessage=a.isBridgeMessage;exports.codeBlockLanguagePanel=e.codeBlockLanguagePanel;exports.codeBlockLanguagePayloadPanel=e.codeBlockLanguagePayloadPanel;exports.createDisabledCommandStates=e.createDisabledCommandStates;exports.defaultMenuSchema=e.defaultMenuSchema;exports.defaultToolbarConfig=e.defaultToolbarConfig;exports.getCommandStateMatchValue=e.getCommandStateMatchValue;exports.isCommandStateForCommand=e.isCommandStateForCommand;exports.isMenuItemCommandState=e.isMenuItemCommandState;exports.resolveToolbarMenu=e.resolveToolbarMenu;exports.tableHeaderMenuItems=e.tableHeaderMenuItems;exports.createFloatingLayer=o.createFloatingLayer;exports.createRichTextEditor=o.createRichTextEditor;exports.createWebViewBridgeRuntime=o.createWebViewBridgeRuntime;exports.createRichTextToolbar=r.createRichTextToolbar;exports.resolvePayloadPanelSchema=n.resolvePayloadPanelSchema;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -756,7 +756,6 @@ export type RichTextEditorIcons = Partial<Record<string, string>>;
756
756
  export type RichTextEditorOptions = {
757
757
  value?: Partial<EditorContent>;
758
758
  readonly?: boolean;
759
- platform?: 'pc' | 'h5' | 'webview';
760
759
  uploadAdapter?: UploadAdapter;
761
760
  /**
762
761
  * 媒体节点没有显式 displayWidthPercent 时的默认展示比例。
@@ -764,14 +763,23 @@ export type RichTextEditorOptions = {
764
763
  * 默认值是 50;业务可以按产品形态改成 20 或 100,内置 UI 仍只提供固定预设。
765
764
  */
766
765
  mediaDefaultWidthPercent?: MediaDisplayWidthPercent;
766
+ /**
767
+ * @deprecated createRichTextEditor 永远只创建编辑器内容实例。
768
+ * toolbar/tabbar 请使用 createRichTextToolbar 或原生侧单独渲染;该字段保留为兼容 no-op。
769
+ */
767
770
  toolbarMode?: 'top' | 'bottom' | 'none' | 'native';
768
771
  /**
769
- * DOM 内置 toolbar/tabbar/hoverbar 使用的菜单 schema。
772
+ * DOM 内置 hoverbar、slash command 等菜单运行时使用的菜单 schema。
770
773
  *
771
- * 自定义菜单必须先进入 schema,再由 `toolbarConfig` `hoverbarConfig` 引用;
774
+ * 自定义菜单必须先进入 schema,再由独立 toolbar `toolbarConfig`、`hoverbarConfig`
775
+ * 或 slash command 配置引用;
772
776
  * 这里不接收 SVG,图标展示仍通过 `icons` 按稳定 icon key 覆盖。
773
777
  */
774
778
  menuSchema?: MenuItem[];
779
+ /**
780
+ * @deprecated editor 不再自动创建 toolbar/tabbar,该字段在 createRichTextEditor 中是 no-op。
781
+ * 请把 toolbarConfig 传给 createRichTextToolbar(container, { editor, toolbarConfig })。
782
+ */
775
783
  toolbarConfig?: ToolbarConfig;
776
784
  /**
777
785
  * DOM 内置 hoverbar 的显示结构配置。
@@ -796,7 +804,7 @@ export type RichTextEditorOptions = {
796
804
  slashCommandConfig?: ToolbarConfig;
797
805
  icons?: RichTextEditorIcons;
798
806
  /**
799
- * DOM 内置 toolbar/tabbar/hoverbar 的菜单 label 覆盖。
807
+ * DOM 内置 hoverbar、slash command 以及独立 toolbar/tabbar 的菜单 label 覆盖。
800
808
  *
801
809
  * key 使用 `MenuItem.id`,只影响按钮文本、tooltip 和 aria-label,不改变命令语义。
802
810
  */
@@ -920,14 +928,27 @@ export declare const isMenuItemCommandState: (item: MenuItem, state: CommandStat
920
928
  */
921
929
  export declare function createDisabledCommandStates(menuSchema?: MenuItem[]): CommandState[];
922
930
 
931
+ /**
932
+ * 已解析 toolbar 按钮项。
933
+ *
934
+ * item 保留完整 MenuItem,原生端可用 id/icon/label/command 映射自己的 UI。
935
+ */
923
936
  export type ResolvedToolbarButtonItem = {
924
937
  type: 'button';
925
938
  item: MenuItem;
926
939
  };
940
+ /**
941
+ * 已解析 toolbar 分隔线。
942
+ */
927
943
  export type ResolvedToolbarSeparatorItem = {
928
944
  type: 'separator';
929
945
  key: string;
930
946
  };
947
+ /**
948
+ * 已解析 toolbar 分组。
949
+ *
950
+ * group 只改变显示结构,不改变内部 MenuItem 的 command 协议。
951
+ */
931
952
  export type ResolvedToolbarGroupItem = {
932
953
  type: 'group';
933
954
  key: string;
@@ -935,6 +956,11 @@ export type ResolvedToolbarGroupItem = {
935
956
  icon?: string;
936
957
  items: MenuItem[];
937
958
  };
959
+ /**
960
+ * toolbar 解析后的渲染项。
961
+ *
962
+ * DOM、RN、Flutter 都应消费这个联合类型,而不是重复解析 ToolbarConfig。
963
+ */
938
964
  export type ResolvedToolbarItem = ResolvedToolbarButtonItem | ResolvedToolbarSeparatorItem | ResolvedToolbarGroupItem;
939
965
 
940
966
  /**
@@ -966,7 +992,7 @@ export type BridgeEventTiming = {
966
992
  *
967
993
  * 只保留可序列化且跨端稳定的字段,避免把函数或宿主对象塞进 bridge。
968
994
  */
969
- export type EditorInitOptions = Pick<RichTextEditorOptions, 'readonly' | 'platform' | 'toolbarMode' | 'placeholder' | 'maxLength' | 'codeBlockLanguagePanel'> & {
995
+ export type EditorInitOptions = Pick<RichTextEditorOptions, 'readonly' | 'placeholder' | 'maxLength' | 'codeBlockLanguagePanel'> & {
970
996
  value?: Partial<EditorContent>;
971
997
  };
972
998
  /**
@@ -1122,7 +1148,17 @@ export declare const defaultBridgeEventTiming: BridgeEventTiming;
1122
1148
  */
1123
1149
  export declare function isBridgeMessage(value: unknown): value is BridgeMessage;
1124
1150
 
1151
+ /**
1152
+ * toolbar icon 覆盖表。
1153
+ *
1154
+ * key 对应 MenuItem.icon 稳定 key,value 是 DOM 侧渲染用 SVG 字符串。
1155
+ */
1125
1156
  export type RichTextToolbarIcons = RichTextEditorIcons;
1157
+ /**
1158
+ * toolbar 横向拖动状态。
1159
+ *
1160
+ * PC/H5 都用同一套 pointer 数据,hasDragged 用于区分拖动滚动和真实点击。
1161
+ */
1126
1162
  export type ToolbarDragState = {
1127
1163
  startClientX: number;
1128
1164
  startScrollLeft: number;
@@ -1130,7 +1166,17 @@ export type ToolbarDragState = {
1130
1166
  hasDragged: boolean;
1131
1167
  startButton?: HTMLButtonElement;
1132
1168
  };
1169
+ /**
1170
+ * toolbar 挂载方向。
1171
+ *
1172
+ * createRichTextToolbar 独立实例只负责自身布局,具体位置由宿主挂载容器决定。
1173
+ */
1133
1174
  export type RichTextToolbarPlacement = 'top' | 'bottom';
1175
+ /**
1176
+ * 独立 toolbar 创建参数。
1177
+ *
1178
+ * editor 提供命令和状态,schema/config 决定展示结构,icons/menuLabels 只覆盖显示层。
1179
+ */
1134
1180
  export type RichTextToolbarOptions = {
1135
1181
  editor: EditorAPI;
1136
1182
  menuSchema?: MenuItem[];
@@ -1140,6 +1186,11 @@ export type RichTextToolbarOptions = {
1140
1186
  menuLabels?: MenuLabelOverrides;
1141
1187
  payloadPanelConfig?: PayloadPanelConfig;
1142
1188
  };
1189
+ /**
1190
+ * toolbar 实例 API。
1191
+ *
1192
+ * update 手动刷新命令状态,destroy 释放 DOM listener 和命令状态订阅。
1193
+ */
1143
1194
  export type RichTextToolbarAPI = {
1144
1195
  update(): void;
1145
1196
  destroy(): void;
@@ -1152,13 +1203,28 @@ export type RichTextToolbarAPI = {
1152
1203
  */
1153
1204
  export declare function createRichTextToolbar(container: HTMLElement, options: RichTextToolbarOptions): RichTextToolbarAPI;
1154
1205
 
1206
+ /**
1207
+ * 浮层相对锚点的放置方向。
1208
+ *
1209
+ * 语义对齐 floating-ui placement,方便 DOM 默认层和业务自绘使用同一套位置配置。
1210
+ */
1155
1211
  export type RichTextFloatingPlacement = 'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end';
1212
+ /**
1213
+ * 通用浮层创建选项。
1214
+ *
1215
+ * root 由实现层持有;这里仅描述定位策略、偏移和边界 padding。
1216
+ */
1156
1217
  export type RichTextFloatingLayerOptions = {
1157
1218
  placement?: RichTextFloatingPlacement;
1158
1219
  offset?: number;
1159
1220
  shiftPadding?: number;
1160
1221
  strategy?: 'absolute' | 'fixed';
1161
1222
  };
1223
+ /**
1224
+ * 通用浮层实例。
1225
+ *
1226
+ * update 会重新计算位置,destroy 释放 floating-ui autoUpdate 和 DOM 引用。
1227
+ */
1162
1228
  export type RichTextFloatingLayer = {
1163
1229
  update(): Promise<void>;
1164
1230
  setOpen(open: boolean): void;
@@ -1178,6 +1244,11 @@ export declare function createFloatingLayer(reference: HTMLElement, floating: HT
1178
1244
  */
1179
1245
  export declare function createRichTextEditor(container: HTMLElement, options?: RichTextEditorOptions): EditorAPI;
1180
1246
 
1247
+ /**
1248
+ * WebView runtime 接收宿主消息的监听函数。
1249
+ *
1250
+ * 只消费 bridge 协议消息,不暴露具体 RN/Flutter 事件对象。
1251
+ */
1181
1252
  export type WebViewBridgeMessageListener = (message: BridgeMessage) => void;
1182
1253
  export type WebViewBridgeRuntimeTransport = {
1183
1254
  /**
@@ -1193,14 +1264,29 @@ export type WebViewBridgeRuntimeTransport = {
1193
1264
  */
1194
1265
  addMessageListener?: (listener: WebViewBridgeMessageListener) => () => void;
1195
1266
  };
1267
+ /**
1268
+ * WebView bridge runtime 创建参数。
1269
+ *
1270
+ * container 是 DOM 编辑器挂载点;transport 是宿主消息通道适配层。
1271
+ */
1196
1272
  export type WebViewBridgeRuntimeOptions = {
1197
1273
  container: HTMLElement;
1198
1274
  transport: WebViewBridgeRuntimeTransport;
1199
1275
  };
1276
+ /**
1277
+ * WebView bridge runtime 实例。
1278
+ *
1279
+ * receive 支持宿主手动转发消息,destroy 会释放编辑器实例和 transport listener。
1280
+ */
1200
1281
  export type WebViewBridgeRuntime = {
1201
1282
  receive(message: NativeToEditorMessage | unknown): void;
1202
1283
  destroy(): void;
1203
1284
  };
1285
+ /**
1286
+ * 等待原生侧返回的上传任务。
1287
+ *
1288
+ * uploadAdapter 来源需要 resolve/reject Promise;nativePicker 来源只等待协议回包更新媒体节点。
1289
+ */
1204
1290
  export type PendingNativeUpload = {
1205
1291
  type: 'image' | 'video';
1206
1292
  assetId: string;
@@ -1211,9 +1297,19 @@ export type PendingNativeUpload = {
1211
1297
  } | {
1212
1298
  source: 'nativePicker';
1213
1299
  });
1300
+ /**
1301
+ * 等待原生侧处理的 payload panel 请求。
1302
+ *
1303
+ * request 内含 submit/cancel 回调,runtime 只保存当前挂起项,避免多个原生面板交叉提交。
1304
+ */
1214
1305
  export type PendingNativePayloadPanelRequest = {
1215
1306
  request: PayloadPanelRequest;
1216
1307
  };
1308
+ /**
1309
+ * 原生上传完成消息。
1310
+ *
1311
+ * resolved/rejected 都回到同一条媒体上传状态管线,保持 DOM 和 WebView 表现一致。
1312
+ */
1217
1313
  export type NativeUploadResultMessage = {
1218
1314
  type: 'editor.uploadResolved';
1219
1315
  payload: UploadResolvedPayload;
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { B as o, a as t, b as r } from "./index-CuNKUHed.js";
2
- import { BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS as m, BRIDGE_HEIGHT_CHANGE_THROTTLE_MS as T, defaultBridgeEventTiming as d, isBridgeMessage as l } from "./bridge.js";
3
- import { codeBlockLanguagePanel as _, codeBlockLanguagePayloadPanel as s, createDisabledCommandStates as i, defaultMenuSchema as R, defaultToolbarConfig as c, getCommandStateMatchValue as B, isCommandStateForCommand as S, isMenuItemCommandState as g, resolveToolbarMenu as C, tableHeaderMenuItems as u } from "./native-spec.js";
4
- import { c as M, a as N, b as f, d as b } from "./index-C7IVE5Bd.js";
5
- import { resolvePayloadPanelSchema as x } from "./core.js";
2
+ import { BRIDGE_CONTENT_CHANGE_DEBOUNCE_MS as m, BRIDGE_HEIGHT_CHANGE_THROTTLE_MS as T, defaultBridgeEventTiming as l, isBridgeMessage as n } from "./bridge.js";
3
+ import { codeBlockLanguagePanel as _, codeBlockLanguagePayloadPanel as s, createDisabledCommandStates as c, defaultMenuSchema as i, defaultToolbarConfig as R, getCommandStateMatchValue as B, isCommandStateForCommand as S, isMenuItemCommandState as g, resolveToolbarMenu as C, tableHeaderMenuItems as u } from "./native-spec.js";
4
+ import { c as f, a as M, b as N } from "./index-BQAzp56J.js";
5
+ import { c as x } from "./index-CeYJbOQi.js";
6
+ import { resolvePayloadPanelSchema as D } from "./core.js";
6
7
  export {
7
8
  o as BRIDGERTE_CONTENT_VERSION,
8
9
  t as BRIDGERTE_TABLE_INSERT_MAX_COLS,
@@ -11,19 +12,19 @@ export {
11
12
  T as BRIDGE_HEIGHT_CHANGE_THROTTLE_MS,
12
13
  _ as codeBlockLanguagePanel,
13
14
  s as codeBlockLanguagePayloadPanel,
14
- i as createDisabledCommandStates,
15
- M as createFloatingLayer,
16
- N as createRichTextEditor,
17
- f as createRichTextToolbar,
18
- b as createWebViewBridgeRuntime,
19
- d as defaultBridgeEventTiming,
20
- R as defaultMenuSchema,
21
- c as defaultToolbarConfig,
15
+ c as createDisabledCommandStates,
16
+ f as createFloatingLayer,
17
+ M as createRichTextEditor,
18
+ x as createRichTextToolbar,
19
+ N as createWebViewBridgeRuntime,
20
+ l as defaultBridgeEventTiming,
21
+ i as defaultMenuSchema,
22
+ R as defaultToolbarConfig,
22
23
  B as getCommandStateMatchValue,
23
- l as isBridgeMessage,
24
+ n as isBridgeMessage,
24
25
  S as isCommandStateForCommand,
25
26
  g as isMenuItemCommandState,
26
- x as resolvePayloadPanelSchema,
27
+ D as resolvePayloadPanelSchema,
27
28
  C as resolveToolbarMenu,
28
29
  u as tableHeaderMenuItems
29
30
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -756,7 +756,6 @@ export type RichTextEditorIcons = Partial<Record<string, string>>;
756
756
  export type RichTextEditorOptions = {
757
757
  value?: Partial<EditorContent>;
758
758
  readonly?: boolean;
759
- platform?: 'pc' | 'h5' | 'webview';
760
759
  uploadAdapter?: UploadAdapter;
761
760
  /**
762
761
  * 媒体节点没有显式 displayWidthPercent 时的默认展示比例。
@@ -764,14 +763,23 @@ export type RichTextEditorOptions = {
764
763
  * 默认值是 50;业务可以按产品形态改成 20 或 100,内置 UI 仍只提供固定预设。
765
764
  */
766
765
  mediaDefaultWidthPercent?: MediaDisplayWidthPercent;
766
+ /**
767
+ * @deprecated createRichTextEditor 永远只创建编辑器内容实例。
768
+ * toolbar/tabbar 请使用 createRichTextToolbar 或原生侧单独渲染;该字段保留为兼容 no-op。
769
+ */
767
770
  toolbarMode?: 'top' | 'bottom' | 'none' | 'native';
768
771
  /**
769
- * DOM 内置 toolbar/tabbar/hoverbar 使用的菜单 schema。
772
+ * DOM 内置 hoverbar、slash command 等菜单运行时使用的菜单 schema。
770
773
  *
771
- * 自定义菜单必须先进入 schema,再由 `toolbarConfig` `hoverbarConfig` 引用;
774
+ * 自定义菜单必须先进入 schema,再由独立 toolbar `toolbarConfig`、`hoverbarConfig`
775
+ * 或 slash command 配置引用;
772
776
  * 这里不接收 SVG,图标展示仍通过 `icons` 按稳定 icon key 覆盖。
773
777
  */
774
778
  menuSchema?: MenuItem[];
779
+ /**
780
+ * @deprecated editor 不再自动创建 toolbar/tabbar,该字段在 createRichTextEditor 中是 no-op。
781
+ * 请把 toolbarConfig 传给 createRichTextToolbar(container, { editor, toolbarConfig })。
782
+ */
775
783
  toolbarConfig?: ToolbarConfig;
776
784
  /**
777
785
  * DOM 内置 hoverbar 的显示结构配置。
@@ -796,7 +804,7 @@ export type RichTextEditorOptions = {
796
804
  slashCommandConfig?: ToolbarConfig;
797
805
  icons?: RichTextEditorIcons;
798
806
  /**
799
- * DOM 内置 toolbar/tabbar/hoverbar 的菜单 label 覆盖。
807
+ * DOM 内置 hoverbar、slash command 以及独立 toolbar/tabbar 的菜单 label 覆盖。
800
808
  *
801
809
  * key 使用 `MenuItem.id`,只影响按钮文本、tooltip 和 aria-label,不改变命令语义。
802
810
  */
@@ -920,14 +928,27 @@ export declare const isMenuItemCommandState: (item: MenuItem, state: CommandStat
920
928
  */
921
929
  export declare function createDisabledCommandStates(menuSchema?: MenuItem[]): CommandState[];
922
930
 
931
+ /**
932
+ * 已解析 toolbar 按钮项。
933
+ *
934
+ * item 保留完整 MenuItem,原生端可用 id/icon/label/command 映射自己的 UI。
935
+ */
923
936
  export type ResolvedToolbarButtonItem = {
924
937
  type: 'button';
925
938
  item: MenuItem;
926
939
  };
940
+ /**
941
+ * 已解析 toolbar 分隔线。
942
+ */
927
943
  export type ResolvedToolbarSeparatorItem = {
928
944
  type: 'separator';
929
945
  key: string;
930
946
  };
947
+ /**
948
+ * 已解析 toolbar 分组。
949
+ *
950
+ * group 只改变显示结构,不改变内部 MenuItem 的 command 协议。
951
+ */
931
952
  export type ResolvedToolbarGroupItem = {
932
953
  type: 'group';
933
954
  key: string;
@@ -935,6 +956,11 @@ export type ResolvedToolbarGroupItem = {
935
956
  icon?: string;
936
957
  items: MenuItem[];
937
958
  };
959
+ /**
960
+ * toolbar 解析后的渲染项。
961
+ *
962
+ * DOM、RN、Flutter 都应消费这个联合类型,而不是重复解析 ToolbarConfig。
963
+ */
938
964
  export type ResolvedToolbarItem = ResolvedToolbarButtonItem | ResolvedToolbarSeparatorItem | ResolvedToolbarGroupItem;
939
965
 
940
966
  /**