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.
- package/README.md +241 -132
- package/dist/bridge.d.ts +13 -5
- package/dist/core.d.ts +12 -4
- package/dist/dom.cjs +1 -1
- package/dist/dom.d.ts +52 -4
- package/dist/dom.js +4 -3
- package/dist/dom.js.map +1 -1
- package/dist/{index-C7IVE5Bd.js → index-BQAzp56J.js} +1778 -1915
- package/dist/index-BQAzp56J.js.map +1 -0
- package/dist/index-Bui5UnkQ.cjs +3 -0
- package/dist/index-Bui5UnkQ.cjs.map +1 -0
- package/dist/index-CeYJbOQi.js +137 -0
- package/dist/index-CeYJbOQi.js.map +1 -0
- package/dist/index-DAlyGWXO.cjs +2 -0
- package/dist/index-DAlyGWXO.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +101 -5
- package/dist/index.js +15 -14
- package/dist/index.js.map +1 -1
- package/dist/native-spec.d.ts +30 -4
- package/dist/style.css +1 -1
- package/dist/webview.cjs +1 -1
- package/dist/webview.d.ts +43 -5
- package/dist/webview.js +1 -1
- package/package.json +8 -8
- package/dist/index-BDgKCpty.cjs +0 -3
- package/dist/index-BDgKCpty.cjs.map +0 -1
- package/dist/index-C7IVE5Bd.js.map +0 -1
|
@@ -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":"oFAwBMA,EAA8B,EAC9BC,EAAyB,EACzBC,EAAwB,yCAIxBC,EAAqB,IAAA,OACzB,cAAO,OAAW,OACbC,EAAA,OAAO,aAAP,YAAAA,EAAA,YAAoB,sCAAsC,WAAY,IAGvEC,EAA8BC,GAA+B,CAKjE,MAAMC,EAASD,aAAkB,QAC7BA,EAAO,QAA2BJ,CAAqB,EACvD,KAEJ,OAAOK,aAAkB,kBAAoBA,EAAS,IACxD,EAEMC,EAAsB,CAC1BC,EACAC,EACAC,EACAC,EACAC,IACG,CACH,MAAMC,EAAQC,EAAAA,oBAAoBL,EAAMC,CAAa,EAC/CJ,EAAS,SAAS,cAAc,QAAQ,EAExCS,EAAUJ,EAAMF,EAAK,IAAI,GAAKO,EAAAA,iBAAiBP,EAAK,IAAI,EAE9DH,EAAO,KAAO,SACdA,EAAO,UAAY,4BACnBA,EAAO,SAAWO,EAAM,SACxBP,EAAO,QAAQ,OAAS,OAAOO,EAAM,MAAM,EAC3CP,EAAO,QAAQ,uBAAyBG,EAAK,GAC7CH,EAAO,aAAa,aAAcG,EAAK,KAAK,EAC5CH,EAAO,aAAa,eAAgB,OAAOO,EAAM,MAAM,CAAC,EACpDD,IAAeN,EAAO,QAAQ,QAAUG,EAAK,OAEjDQ,EAAAA,eAAeX,EAAQS,EAASN,EAAK,KAAK,EAE1CD,EAAa,OAAOF,CAAM,CAC5B,EAEMY,EAAgB,CACpBC,EACAC,EACAV,EACAC,EACAC,IACG,CACHO,EAAe,YAAc,GAE7B,IAAIE,EAAe,GACfb,EAAsC,KAE1CY,EAAa,QAASE,GAAgB,CACpC,GAAIA,EAAY,OAAS,YAAa,CACpCD,EAAe,GACfb,EAAe,KAEf,MAAMe,EAAmB,SAAS,cAAc,MAAM,EAEtDA,EAAiB,UAAY,+BAC7BA,EAAiB,QAAQ,YAAcD,EAAY,IACnDC,EAAiB,aAAa,cAAe,MAAM,EACnDJ,EAAe,OAAOI,CAAgB,EACtC,MACF,CAEA,MAAMC,EAAYF,EAAY,OAAS,SAAWA,EAAY,KAAK,MAAQA,EAAY,KAEnF,CAACd,GAAgBa,IAAiBG,KACpCH,EAAeG,EACfhB,EAAe,SAAS,cAAc,KAAK,EAC3CA,EAAa,UAAY,2BACzBA,EAAa,QAAQ,MAAQgB,EACzBF,EAAY,OAAS,SACvBd,EAAa,aAAa,aAAcc,EAAY,KAAK,EAE3DH,EAAe,OAAOX,CAAY,GAGpC,MAAMiB,EAAqBjB,EAE3B,GAAIc,EAAY,OAAS,SAAU,CACjCf,EACEkB,EACAH,EAAY,KACZZ,EACAC,EACAC,CAAA,EAEF,MACF,CAEAU,EAAY,MAAM,QAASb,GAAS,CAClCF,EACEkB,EACAhB,EACAC,EACAC,EACAC,CAAA,CAEJ,CAAC,CACH,CAAC,CACH,EAOO,SAASc,EACdC,EACAC,EACoB,CACpB,MAAMC,EAAYD,EAAQ,WAAa,MACjCE,EAAaC,EAAAA,wBAAwBH,EAAQ,YAAcI,EAAAA,kBAAmB,CAClF,WAAYJ,EAAQ,WACpB,mBAAoBA,EAAQ,kBAAA,CAC7B,EACKR,EAAea,EAAAA,mBAAmBL,EAAQ,cAAeE,CAAU,EAKnEI,EAAsBd,EAAa,QAASE,GAChDA,EAAY,OAAS,SAAW,CAACA,EAAY,IAAI,EAC7CA,EAAY,OAAS,QAAUA,EAAY,MACzC,EACP,EACKX,EAAQiB,EAAQ,OAAS,CAAA,EAKzBhB,EAAgBV,EAAA,EAChBiC,EAAiB,SAAS,cAAc,KAAK,EAC7CC,EAAcT,EAAU,QAAQ,YAAY,GAAKA,EACvD,IAAIU,EAAY,GACZC,EAAqC,KACrCC,EAA0B,GAC9B,MAAMC,EAA2BC,EAAAA,sBAAsBd,EAAW,CAChE,eAAgB,wCAAA,CACjB,EAEKe,EAAuB,IAAM,CAEjCN,EAAY,OAAOD,CAAc,CACnC,EAEMQ,EAAgBC,GAA2B,CAC3CP,IAEJnB,EAAcS,EAAWP,EAAcwB,EAAQjC,EAAOC,CAAa,EACnE8B,EAAA,EACF,EAEMG,EAAS,IAAM,CACfR,GAEJM,EAAaf,EAAQ,OAAO,kBAAkB,CAChD,EAEMkB,EAAc,IAAM,CACxBX,EAAe,QAAQ,QAAU,QACjCA,EAAe,YAAc,EAC/B,EAEMY,EAAezC,GAA8B,CACjD,MAAM0C,EAAc1C,EAAO,QAAQ,QAEnC,GAAI,CAACM,GAAiB,CAACoC,GAAeV,EAAW,OAEjD,MAAMW,EAAa3C,EAAO,sBAAA,EAE1B6B,EAAe,YAAca,EAC7Bb,EAAe,QAAQ,QAAU,OACjCA,EAAe,MAAM,KAAO,GAAGc,EAAW,KAAOA,EAAW,MAAQ,CAAC,KACrEd,EAAe,MAAM,IAAM,GAAGc,EAAW,IAAMjD,CAAsB,IACvE,EAEMkD,EAAuBC,GAAiB,CAC5C,MAAM7C,EAASF,EAA2B+C,EAAM,MAAM,EAElD7C,GACFyC,EAAYzC,CAAM,CAEtB,EAEM8C,EAAsBD,GAAsB,CAChD,MAAME,EAAgBF,EAAM,cACtB7C,EAASF,EAA2B+C,EAAM,MAAM,EAGpD7C,GACK+C,aAAyB,MACzB/C,EAAO,SAAS+C,CAAa,GAGpCP,EAAA,CACF,EAEMQ,EAAkB,IAAM,CAC5BhB,EAAY,KAEZ,OAAOX,EAAU,QAAQ,SAEzB,SAAS,oBAAoB,cAAe4B,CAAiB,EAC7D,SAAS,oBAAoB,YAAaC,CAAe,EACzD,SAAS,oBAAoB,gBAAiBA,CAAe,CAC/D,EAEMD,EAAqBJ,GAAwB,CACjD,GAAI,CAACb,EAAW,OAEhB,MAAMmB,EAASnB,EAAU,aAAea,EAAM,QAE1C,KAAK,IAAIM,CAAM,EAAI1D,IACrBuC,EAAU,WAAa,GACvBC,EAA0B,GAC1BO,EAAA,GAGFnB,EAAU,WAAaW,EAAU,gBAAkBmB,CACrD,EAEMD,EAAmBL,GAAwB,CAC/C,MAAMO,EAAmBpB,EAEzBgB,EAAA,EAEEI,GACKP,EAAM,OAAS,iBACfO,EAAiB,cAAgB,SACjC,CAACA,EAAiB,YAClBA,EAAiB,cAEtBC,EAAqBD,EAAiB,WAAW,EACjDnB,EAA0B,GAE9B,EAEMqB,EAAqBT,GAAwB,CACjD,GAAIA,EAAM,cAAgB,SAAWA,EAAM,SAAW,EAAG,OAEzD,MAAMU,EAAczD,EAA2B+C,EAAM,MAAM,EAG3DA,EAAM,eAAA,EACNb,EAAY,CACV,aAAca,EAAM,QACpB,gBAAiBxB,EAAU,WAC3B,YAAawB,EAAM,YACnB,WAAY,GACZ,YAAaU,GAAe,MAAA,EAE9BlC,EAAU,QAAQ,SAAW,OAC7BmB,EAAA,EAEA,SAAS,iBAAiB,cAAeS,CAAiB,EAC1D,SAAS,iBAAiB,YAAaC,CAAe,EACtD,SAAS,iBAAiB,gBAAiBA,CAAe,CAC5D,EAEMG,EAAwBrD,GAA8B,CAC1D,GAAI,EAAEA,aAAkB,oBAAsBA,EAAO,SAAU,OAE/D,MAAMwD,EAAW5B,EAAoB,KAAMzB,GACzCA,EAAK,KAAOH,EAAO,QAAQ,sBAC5B,EAED,GAAKwD,EAGL,IADAlC,EAAQ,OAAO,MAAA,EACXkC,EAAS,aAAc,CACzB,MAAMb,EAAa3C,EAAO,sBAAA,EAO1BsB,EAAQ,OAAO,oBAAoB,CACjC,OAAQkC,EAAS,GACjB,QAASA,EAAS,QAClB,MAAOA,EAAS,aAChB,cAAeC,EAAAA,6BAA6BD,EAAUlC,EAAQ,OAAO,kBAAkB,EACvF,WAAY,CACV,EAAGqB,EAAW,KACd,EAAGA,EAAW,IACd,MAAOA,EAAW,MAClB,OAAQA,EAAW,MAAA,CACrB,CACD,EACD,MACF,CAEArB,EAAQ,OAAO,eAAekC,EAAS,OAAO,EAChD,EAEME,EAAeb,GAAsB,CACzC,GAAIZ,EAAyB,CAC3BA,EAA0B,GAC1BY,EAAM,eAAA,EACNA,EAAM,gBAAA,EACN,MACF,CAEA,MAAM7C,EAASF,EAA2B+C,EAAM,MAAM,EACjD7C,GAELqD,EAAqBrD,CAAM,CAC7B,EAEAqB,EAAU,UAAU,IAAI,oBAAoB,EAC5CQ,EAAe,UAAY,6BAC3BA,EAAe,QAAQ,QAAU,QACjCR,EAAU,QAAQ,UAAYE,EAC9BF,EAAU,aAAa,OAAQ,SAAS,EACxCA,EAAU,aACR,aACAE,IAAc,SAAW,mBAAqB,mBAAA,EAEhDF,EAAU,iBAAiB,cAAeiC,EAAmB,EAAI,EACjEjC,EAAU,iBAAiB,QAASqC,CAAW,EAC3CpD,IACFe,EAAU,iBAAiB,YAAauB,CAAmB,EAC3DvB,EAAU,iBAAiB,WAAYyB,CAAkB,GAE3DzB,EAAU,iBAAiB,WAAYmB,CAAW,EAElDJ,EAAA,EAGA,MAAMuB,EAAcrC,EAAQ,OAAO,4BAA4Be,CAAY,EAE3E,MAAO,CACL,OAAAE,EACA,SAAU,CACJR,IAEJA,EAAY,GACZiB,EAAA,EACAW,EAAA,EACAtC,EAAU,oBAAoB,cAAeiC,EAAmB,EAAI,EACpEjC,EAAU,oBAAoB,QAASqC,CAAW,EAC9CpD,IACFe,EAAU,oBAAoB,YAAauB,CAAmB,EAC9DvB,EAAU,oBAAoB,WAAYyB,CAAkB,GAE9DZ,EAAA,EACAb,EAAU,oBAAoB,WAAYmB,CAAW,EACrDX,EAAe,OAAA,EACfR,EAAU,UAAU,OAAO,oBAAoB,EAC/C,OAAOA,EAAU,QAAQ,UACzBA,EAAU,YAAc,GACxBA,EAAU,gBAAgB,MAAM,EAChCA,EAAU,gBAAgB,YAAY,EACxC,CAAA,CAEJ"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
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 内置
|
|
772
|
+
* DOM 内置 hoverbar、slash command 等菜单运行时使用的菜单 schema。
|
|
770
773
|
*
|
|
771
|
-
* 自定义菜单必须先进入 schema
|
|
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
|
|
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' | '
|
|
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
|
|
3
|
-
import { codeBlockLanguagePanel as _, codeBlockLanguagePayloadPanel as s, createDisabledCommandStates as
|
|
4
|
-
import { c as
|
|
5
|
-
import {
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
24
|
+
n as isBridgeMessage,
|
|
24
25
|
S as isCommandStateForCommand,
|
|
25
26
|
g as isMenuItemCommandState,
|
|
26
|
-
|
|
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":";;;;;;"}
|
package/dist/native-spec.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 内置
|
|
772
|
+
* DOM 内置 hoverbar、slash command 等菜单运行时使用的菜单 schema。
|
|
770
773
|
*
|
|
771
|
-
* 自定义菜单必须先进入 schema
|
|
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
|
|
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
|
/**
|