bridgerte 0.9.0 → 0.9.2

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,2 @@
1
+ "use strict";const q=require("./native-spec.cjs"),m=require("./index-CkgUKPh3.cjs"),U=e=>Array.from(e.querySelectorAll(".bridgerte__toolbar-group-menu-item")).filter(t=>!t.disabled),Y=(e,t)=>{const i=U(e)[t];i&&i.focus()},Z=e=>{Y(e,0)},ee=(e,t,s,i,p)=>{var l,d;const a=U(t),n=document.activeElement instanceof HTMLButtonElement?a.indexOf(document.activeElement):-1,u=g=>{var y;if(a.length===0)return;const f=((n>=0?n:0)+g+a.length)%a.length;(y=a[f])==null||y.focus()};switch(e.key){case"ArrowDown":e.preventDefault(),u(1);break;case"ArrowUp":e.preventDefault(),u(-1);break;case"Home":e.preventDefault(),(l=a[0])==null||l.focus();break;case"End":e.preventDefault(),(d=a.at(-1))==null||d.focus();break;case"Enter":case" ":document.activeElement instanceof HTMLButtonElement&&(e.preventDefault(),i(document.activeElement),p(),s.focus());break;case"Escape":e.preventDefault(),s.focus(),p();break}},G="button[data-bridgerte-toolbar-group-id]",te="button[data-bridgerte-toolbar-item-id]",oe=[te,".bridgerte__toolbar-group-menu-item"].join(","),ne=(e,t)=>{const s=e.map(i=>m.getMenuStateForItem(i,t));return{active:s.some(i=>i.active),disabled:s.length>0&&s.every(i=>i.disabled)}},re=(e,t,s,i,p)=>{const a=m.getMenuStateForItem(t,s),n=document.createElement("button"),u=i[t.icon]??m.defaultMenuIcons[t.icon];n.type="button",n.className="bridgerte__toolbar-button",n.disabled=a.disabled,n.dataset.active=String(a.active),n.dataset.bridgerteToolbarItemId=t.id,n.setAttribute("aria-label",t.label),n.setAttribute("aria-pressed",String(a.active)),p&&(n.dataset.tooltip=t.label),m.appendMenuIcon(n,u,t.label),e.append(n)},ae=(e,t,s,i,p)=>{const a=document.createElement("button"),n=ne(t.items,s),u=t.icon?i[t.icon]??m.defaultMenuIcons[t.icon]:void 0,l=document.createElement("span");a.type="button",a.className="bridgerte__toolbar-button bridgerte__toolbar-group-button",a.disabled=n.disabled,a.dataset.active=String(n.active),a.dataset.bridgerteToolbarGroupId=t.key,a.dataset.open="false",a.setAttribute("aria-label",t.title),a.setAttribute("aria-haspopup","menu"),a.setAttribute("aria-expanded","false"),a.setAttribute("aria-pressed",String(n.active)),p&&(a.dataset.tooltip=t.title),m.appendMenuIcon(a,u,t.title),l.className="bridgerte__toolbar-group-indicator",l.setAttribute("aria-hidden","true"),l.textContent="⌄",a.append(l),e.append(a)},se=(e,t,s,i,p)=>{e.textContent="";let a="",n=null;t.forEach(u=>{if(u.type==="separator"){a="",n=null;const g=document.createElement("span");g.className="bridgerte__toolbar-separator",g.dataset.separatorId=u.key,g.setAttribute("aria-hidden","true"),e.append(g);return}const l=u.type==="button"?u.item.group:u.key;(!n||a!==l)&&(a=l,n=document.createElement("div"),n.className="bridgerte__toolbar-group",n.dataset.group=l,u.type==="group"&&n.setAttribute("aria-label",u.title),e.append(n));const d=n;if(u.type==="button"){re(d,u.item,s,i,p);return}ae(d,u,s,i,p)})},C=(e,t,s,i)=>{if(e.textContent="",!t){e.dataset.visible="false";return}t.items.forEach(p=>{const a=m.getMenuStateForItem(p,s),n=document.createElement("button"),u=i[p.icon]??m.defaultMenuIcons[p.icon],l=document.createElement("span");n.type="button",n.className="bridgerte__toolbar-group-menu-item",n.disabled=a.disabled,n.dataset.active=String(a.active),n.dataset.bridgerteToolbarItemId=p.id,n.setAttribute("role","menuitem"),n.setAttribute("aria-label",p.label),n.setAttribute("aria-pressed",String(a.active)),m.appendMenuIcon(n,u,p.label),l.className="bridgerte__toolbar-group-menu-label",l.textContent=p.label,n.append(l),e.append(n)}),e.dataset.visible="true",e.style.minWidth=`${t.button.offsetWidth}px`},A=(e,t)=>{e.querySelectorAll(G).forEach(s=>{const i=(t==null?void 0:t.groupKey)===s.dataset.bridgerteToolbarGroupId;s.dataset.open=String(i),s.setAttribute("aria-expanded",String(i))})},X=(e,t)=>e.find(s=>s.type==="group"&&s.key===t),le=4,ie=8,ue=6,de=()=>{var e;return typeof window<"u"&&((e=window.matchMedia)==null?void 0:e.call(window,"(hover: hover) and (pointer: fine)").matches)===!0},_=e=>{const t=e instanceof Element?e.closest(oe):null;return t instanceof HTMLButtonElement?t:null},ce=e=>{const t=e instanceof Element?e.closest(G):null;return t instanceof HTMLButtonElement?t:null};function pe(e,t){const s=t.placement??"top",i=m.resolveMenuSchemaForDom(t.menuSchema??q.defaultMenuSchema,{menuLabels:t.menuLabels,payloadPanelConfig:t.payloadPanelConfig}),p=q.resolveToolbarMenu(t.toolbarConfig,i),a=p.flatMap(o=>o.type==="button"?[o.item]:o.type==="group"?o.items:[]),n=t.icons??{},u=de(),l=document.createElement("div"),d=document.createElement("div"),g=e.closest(".bridgerte")??e;let h=!1,f=null,y=!1,L=t.editor.getCommandStates(),c=null,v=null;const $=m.bindTouchPressedState(e,{targetSelector:["button[data-bridgerte-toolbar-item-id]","button[data-bridgerte-toolbar-group-id]"].join(",")}),j=m.bindTouchPressedState(d,{targetSelector:".bridgerte__toolbar-group-menu-item"}),D=()=>{g.append(l),g.append(d)},k=()=>{v==null||v.setOpen(!1),v==null||v.destroy(),v=null},M=()=>{c&&(k(),v=m.createFloatingLayer(c.button,d,{placement:s==="bottom"?"top-start":"bottom-start",offset:ue,strategy:"fixed"}),v.setOpen(!0))},E=()=>{k(),c=null,C(d,c,L,n),A(e,c)},w=o=>{if(!h&&(L=o,c&&k(),se(e,p,o,n,u),D(),c)){const r=Array.from(e.querySelectorAll(G)).find(Q=>Q.dataset.bridgerteToolbarGroupId===(c==null?void 0:c.groupKey)),b=X(p,c.groupKey);c=r&&b?{groupKey:c.groupKey,button:r,items:b.items}:null,C(d,c,L,n),A(e,c),c&&M()}},V=()=>{h||w(t.editor.getCommandStates())},T=()=>{l.dataset.visible="false",l.textContent=""},W=o=>{const r=o.dataset.tooltip;if(!u||!r||f)return;const b=o.getBoundingClientRect();l.textContent=r,l.dataset.visible="true",l.style.left=`${b.left+b.width/2}px`,l.style.top=`${b.top-ie}px`},P=o=>{const r=_(o.target);r&&W(r)},I=o=>{const r=o.relatedTarget,b=_(o.target);b&&r instanceof Node&&b.contains(r)||T()},N=()=>{f=null,delete e.dataset.dragging,document.removeEventListener("pointermove",K),document.removeEventListener("pointerup",x),document.removeEventListener("pointercancel",x)},K=o=>{if(!f)return;const r=f.startClientX-o.clientX;Math.abs(r)>le&&(f.hasDragged=!0,y=!0,T(),E()),e.scrollLeft=f.startScrollLeft+r},x=o=>{const r=f;N(),r&&o.type!=="pointercancel"&&r.pointerType!=="mouse"&&!r.hasDragged&&r.startButton&&(B(r.startButton),y=!0)},R=o=>{if(o.pointerType==="mouse"&&o.button!==0)return;const r=_(o.target);o.preventDefault(),f={startClientX:o.clientX,startScrollLeft:e.scrollLeft,pointerType:o.pointerType,hasDragged:!1,startButton:r??void 0},e.dataset.dragging="true",T(),document.addEventListener("pointermove",K),document.addEventListener("pointerup",x),document.addEventListener("pointercancel",x)},B=o=>{if(!(o instanceof HTMLButtonElement)||o.disabled)return;const r=a.find(b=>b.id===o.dataset.bridgerteToolbarItemId);if(r){if(r.payloadPanel){const b=o.getBoundingClientRect();t.editor.requestPayloadPanel({menuId:r.id,command:r.command,panel:r.payloadPanel,currentValues:m.getPayloadPanelCurrentValues(r,t.editor.getCommandStates()),anchorRect:{x:b.left,y:b.top,width:b.width,height:b.height}});return}t.editor.executeCommand(r.command)}},z=o=>{const r=X(p,o.dataset.bridgerteToolbarGroupId);if(!(!r||o.disabled)){if((c==null?void 0:c.groupKey)===r.key){E();return}c={groupKey:r.key,button:o,items:r.items},T(),C(d,c,L,n),A(e,c),M(),Z(d)}},S=o=>{if(y){y=!1,o.preventDefault(),o.stopPropagation();return}const r=ce(o.target);if(r){o.preventDefault(),o.stopPropagation(),z(r);return}const b=_(o.target);b&&(o.preventDefault(),o.stopPropagation(),B(b),E())},H=o=>{o.pointerType==="mouse"&&o.button!==0||o.preventDefault()},F=o=>{const r=o.target;r instanceof Node&&(e.contains(r)||d.contains(r))||E()},O=o=>{if(c&&d.contains(document.activeElement)){ee(o,d,c.button,B,E);return}o.key==="Escape"&&E()};e.classList.add("bridgerte__toolbar"),l.className="bridgerte__toolbar-tooltip",l.dataset.visible="false",d.className="bridgerte__toolbar-group-menu",d.dataset.visible="false",d.setAttribute("role","menu"),e.dataset.placement=s,e.setAttribute("role","toolbar"),e.setAttribute("aria-label",s==="bottom"?"BridgeRTE tabbar":"BridgeRTE toolbar"),e.addEventListener("pointerdown",R,!0),e.addEventListener("click",S),d.addEventListener("pointerdown",H,!0),d.addEventListener("click",S),document.addEventListener("click",F),document.addEventListener("keydown",O),u&&(e.addEventListener("mouseover",P),e.addEventListener("mouseout",I)),e.addEventListener("focusout",T),D();const J=t.editor.subscribeCommandStateChange(w);return{update:V,destroy(){h||(h=!0,N(),J(),E(),e.removeEventListener("pointerdown",R,!0),e.removeEventListener("click",S),d.removeEventListener("pointerdown",H,!0),d.removeEventListener("click",S),document.removeEventListener("click",F),document.removeEventListener("keydown",O),u&&(e.removeEventListener("mouseover",P),e.removeEventListener("mouseout",I)),$(),j(),e.removeEventListener("focusout",T),l.remove(),d.remove(),e.classList.remove("bridgerte__toolbar"),delete e.dataset.placement,e.textContent="",e.removeAttribute("role"),e.removeAttribute("aria-label"))}}}exports.createRichTextToolbar=pe;
2
+ //# sourceMappingURL=index-CqOH1_5N.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-CqOH1_5N.cjs","sources":["../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/index.ts"],"sourcesContent":["export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const focusFirstToolbarGroupMenuItem = (menuElement: HTMLElement) => {\n /*\n * group menu 使用 ARIA menu 语义,打开后焦点必须进入第一个可操作项。\n * 这样键盘用户可以继续用方向键浏览,而不是停留在展开按钮上。\n */\n focusToolbarGroupMenuItem(menuElement, 0);\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : undefined;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.textContent = '⌄';\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单渲染为按钮,`|` 渲染分割线,group 只渲染一个收纳入口;组内命令交给\n * renderToolbarGroupMenu 渲染,避免 `menuKeys` 退化成另一种横向分隔语法。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n 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 renderToolbarGroupButton(\n activeGroupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusFirstToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions,\n ToolbarDragState\n} from './type';\n\nconst toolbarDragClickThresholdPx = 4;\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let dragState: ToolbarDragState | null = null;\n let shouldSuppressNextClick = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText || 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 closeGroupMenu();\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 if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n focusFirstToolbarGroupMenuItem(groupMenuElement);\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 groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleGroupMenuPointerDown = (event: PointerEvent) => {\n /*\n * group 菜单浮层挂在 toolbar 容器外,不能复用容器级 pointerdown。\n * 子菜单点击仍要保留编辑区 selection,否则格式命令会丢失原选区。\n */\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n\n event.preventDefault();\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n const target = event.target;\n\n if (\n target instanceof Node\n && (container.contains(target) || groupMenuElement.contains(target))\n ) return;\n\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('pointerdown', handlePointerDown, true);\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('pointerdown', handleGroupMenuPointerDown, true);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('click', handleDocumentClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n stopToolbarDrag();\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('pointerdown', handlePointerDown, true);\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('pointerdown', handleGroupMenuPointerDown, true);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n"],"names":["getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","focusFirstToolbarGroupMenuItem","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","currentGroup","separatorElement","nextGroup","activeGroupElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarDragClickThresholdPx","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","canUseHoverTooltip","getToolbarButtonFromTarget","target","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","groupMenuElement","overlayHost","destroyed","dragState","shouldSuppressNextClick","latestCommandStates","groupMenuFloatingLayer","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","stopToolbarDrag","handlePointerMove","handlePointerUp","deltaX","currentDragState","handlePointerDown","startButton","menuItem","getPayloadPanelCurrentValues","toggleGroupMenu","groupItem","handleClick","groupButton","handleGroupMenuPointerDown","handleDocumentClick","handleKeyDown","unsubscribe"],"mappings":"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"}
@@ -0,0 +1,262 @@
1
+ import { defaultMenuSchema as ee, resolveToolbarMenu as te } from "./native-spec.js";
2
+ import { g as A, d as G, e as D, r as oe, f as U, h as re, c as ne } from "./index-KRuLtGv9.js";
3
+ const j = (e) => Array.from(
4
+ e.querySelectorAll(".bridgerte__toolbar-group-menu-item")
5
+ ).filter((t) => !t.disabled), ae = (e, t) => {
6
+ const i = j(e)[t];
7
+ i && i.focus();
8
+ }, se = (e) => {
9
+ ae(e, 0);
10
+ }, le = (e, t, s, i, p) => {
11
+ var l, u;
12
+ const a = j(t), r = document.activeElement instanceof HTMLButtonElement ? a.indexOf(document.activeElement) : -1, d = (f) => {
13
+ var v;
14
+ if (a.length === 0) return;
15
+ const m = ((r >= 0 ? r : 0) + f + a.length) % a.length;
16
+ (v = a[m]) == null || v.focus();
17
+ };
18
+ switch (e.key) {
19
+ case "ArrowDown":
20
+ e.preventDefault(), d(1);
21
+ break;
22
+ case "ArrowUp":
23
+ e.preventDefault(), d(-1);
24
+ break;
25
+ case "Home":
26
+ e.preventDefault(), (l = a[0]) == null || l.focus();
27
+ break;
28
+ case "End":
29
+ e.preventDefault(), (u = a.at(-1)) == null || u.focus();
30
+ break;
31
+ case "Enter":
32
+ case " ":
33
+ document.activeElement instanceof HTMLButtonElement && (e.preventDefault(), i(document.activeElement), p(), s.focus());
34
+ break;
35
+ case "Escape":
36
+ e.preventDefault(), s.focus(), p();
37
+ break;
38
+ }
39
+ }, w = "button[data-bridgerte-toolbar-group-id]", ie = "button[data-bridgerte-toolbar-item-id]", de = [
40
+ ie,
41
+ ".bridgerte__toolbar-group-menu-item"
42
+ ].join(","), ue = (e, t) => {
43
+ const s = e.map((i) => A(i, t));
44
+ return {
45
+ active: s.some((i) => i.active),
46
+ disabled: s.length > 0 && s.every((i) => i.disabled)
47
+ };
48
+ }, ce = (e, t, s, i, p) => {
49
+ const a = A(t, s), r = document.createElement("button"), d = i[t.icon] ?? G[t.icon];
50
+ r.type = "button", r.className = "bridgerte__toolbar-button", r.disabled = a.disabled, r.dataset.active = String(a.active), r.dataset.bridgerteToolbarItemId = t.id, r.setAttribute("aria-label", t.label), r.setAttribute("aria-pressed", String(a.active)), p && (r.dataset.tooltip = t.label), D(r, d, t.label), e.append(r);
51
+ }, pe = (e, t, s, i, p) => {
52
+ const a = document.createElement("button"), r = ue(t.items, s), d = t.icon ? i[t.icon] ?? G[t.icon] : void 0, l = document.createElement("span");
53
+ a.type = "button", a.className = "bridgerte__toolbar-button bridgerte__toolbar-group-button", a.disabled = r.disabled, a.dataset.active = String(r.active), a.dataset.bridgerteToolbarGroupId = t.key, a.dataset.open = "false", a.setAttribute("aria-label", t.title), a.setAttribute("aria-haspopup", "menu"), a.setAttribute("aria-expanded", "false"), a.setAttribute("aria-pressed", String(r.active)), p && (a.dataset.tooltip = t.title), D(a, d, t.title), l.className = "bridgerte__toolbar-group-indicator", l.setAttribute("aria-hidden", "true"), l.textContent = "⌄", a.append(l), e.append(a);
54
+ }, be = (e, t, s, i, p) => {
55
+ e.textContent = "";
56
+ let a = "", r = null;
57
+ t.forEach((d) => {
58
+ if (d.type === "separator") {
59
+ a = "", r = null;
60
+ const f = document.createElement("span");
61
+ f.className = "bridgerte__toolbar-separator", f.dataset.separatorId = d.key, f.setAttribute("aria-hidden", "true"), e.append(f);
62
+ return;
63
+ }
64
+ const l = d.type === "button" ? d.item.group : d.key;
65
+ (!r || a !== l) && (a = l, r = document.createElement("div"), r.className = "bridgerte__toolbar-group", r.dataset.group = l, d.type === "group" && r.setAttribute("aria-label", d.title), e.append(r));
66
+ const u = r;
67
+ if (d.type === "button") {
68
+ ce(
69
+ u,
70
+ d.item,
71
+ s,
72
+ i,
73
+ p
74
+ );
75
+ return;
76
+ }
77
+ pe(
78
+ u,
79
+ d,
80
+ s,
81
+ i,
82
+ p
83
+ );
84
+ });
85
+ }, B = (e, t, s, i) => {
86
+ if (e.textContent = "", !t) {
87
+ e.dataset.visible = "false";
88
+ return;
89
+ }
90
+ t.items.forEach((p) => {
91
+ const a = A(p, s), r = document.createElement("button"), d = i[p.icon] ?? G[p.icon], l = document.createElement("span");
92
+ r.type = "button", r.className = "bridgerte__toolbar-group-menu-item", r.disabled = a.disabled, r.dataset.active = String(a.active), r.dataset.bridgerteToolbarItemId = p.id, r.setAttribute("role", "menuitem"), r.setAttribute("aria-label", p.label), r.setAttribute("aria-pressed", String(a.active)), D(r, d, p.label), l.className = "bridgerte__toolbar-group-menu-label", l.textContent = p.label, r.append(l), e.append(r);
93
+ }), e.dataset.visible = "true", e.style.minWidth = `${t.button.offsetWidth}px`;
94
+ }, C = (e, t) => {
95
+ e.querySelectorAll(w).forEach((s) => {
96
+ const i = (t == null ? void 0 : t.groupKey) === s.dataset.bridgerteToolbarGroupId;
97
+ s.dataset.open = String(i), s.setAttribute("aria-expanded", String(i));
98
+ });
99
+ }, $ = (e, t) => e.find((s) => s.type === "group" && s.key === t), me = 4, fe = 8, ge = 6, ve = () => {
100
+ var e;
101
+ return typeof window < "u" && ((e = window.matchMedia) == null ? void 0 : e.call(window, "(hover: hover) and (pointer: fine)").matches) === !0;
102
+ }, S = (e) => {
103
+ const t = e instanceof Element ? e.closest(de) : null;
104
+ return t instanceof HTMLButtonElement ? t : null;
105
+ }, ye = (e) => {
106
+ const t = e instanceof Element ? e.closest(w) : null;
107
+ return t instanceof HTMLButtonElement ? t : null;
108
+ };
109
+ function Te(e, t) {
110
+ const s = t.placement ?? "top", i = oe(t.menuSchema ?? ee, {
111
+ menuLabels: t.menuLabels,
112
+ payloadPanelConfig: t.payloadPanelConfig
113
+ }), p = te(t.toolbarConfig, i), a = p.flatMap((o) => o.type === "button" ? [o.item] : o.type === "group" ? o.items : []), r = t.icons ?? {}, d = ve(), l = document.createElement("div"), u = document.createElement("div"), f = e.closest(".bridgerte") ?? e;
114
+ let h = !1, m = null, v = !1, T = t.editor.getCommandStates(), c = null, g = null;
115
+ const V = U(e, {
116
+ targetSelector: [
117
+ "button[data-bridgerte-toolbar-item-id]",
118
+ "button[data-bridgerte-toolbar-group-id]"
119
+ ].join(",")
120
+ }), W = U(u, {
121
+ targetSelector: ".bridgerte__toolbar-group-menu-item"
122
+ }), P = () => {
123
+ f.append(l), f.append(u);
124
+ }, _ = () => {
125
+ g == null || g.setOpen(!1), g == null || g.destroy(), g = null;
126
+ }, M = () => {
127
+ c && (_(), g = ne(c.button, u, {
128
+ placement: s === "bottom" ? "top-start" : "bottom-start",
129
+ offset: ge,
130
+ strategy: "fixed"
131
+ }), g.setOpen(!0));
132
+ }, y = () => {
133
+ _(), c = null, B(u, c, T, r), C(e, c);
134
+ }, N = (o) => {
135
+ if (!h && (T = o, c && _(), be(e, p, o, r, d), P(), c)) {
136
+ const n = Array.from(
137
+ e.querySelectorAll(w)
138
+ ).find((Z) => Z.dataset.bridgerteToolbarGroupId === (c == null ? void 0 : c.groupKey)), b = $(p, c.groupKey);
139
+ c = n && b ? {
140
+ groupKey: c.groupKey,
141
+ button: n,
142
+ items: b.items
143
+ } : null, B(u, c, T, r), C(e, c), c && M();
144
+ }
145
+ }, z = () => {
146
+ h || N(t.editor.getCommandStates());
147
+ }, E = () => {
148
+ l.dataset.visible = "false", l.textContent = "";
149
+ }, J = (o) => {
150
+ const n = o.dataset.tooltip;
151
+ if (!d || !n || m) return;
152
+ const b = o.getBoundingClientRect();
153
+ l.textContent = n, l.dataset.visible = "true", l.style.left = `${b.left + b.width / 2}px`, l.style.top = `${b.top - fe}px`;
154
+ }, K = (o) => {
155
+ const n = S(o.target);
156
+ n && J(n);
157
+ }, H = (o) => {
158
+ const n = o.relatedTarget, b = S(o.target);
159
+ b && n instanceof Node && b.contains(n) || E();
160
+ }, I = () => {
161
+ m = null, delete e.dataset.dragging, document.removeEventListener("pointermove", R), document.removeEventListener("pointerup", L), document.removeEventListener("pointercancel", L);
162
+ }, R = (o) => {
163
+ if (!m) return;
164
+ const n = m.startClientX - o.clientX;
165
+ Math.abs(n) > me && (m.hasDragged = !0, v = !0, E(), y()), e.scrollLeft = m.startScrollLeft + n;
166
+ }, L = (o) => {
167
+ const n = m;
168
+ I(), n && o.type !== "pointercancel" && n.pointerType !== "mouse" && !n.hasDragged && n.startButton && (k(n.startButton), v = !0);
169
+ }, O = (o) => {
170
+ if (o.pointerType === "mouse" && o.button !== 0) return;
171
+ const n = S(o.target);
172
+ o.preventDefault(), m = {
173
+ startClientX: o.clientX,
174
+ startScrollLeft: e.scrollLeft,
175
+ pointerType: o.pointerType,
176
+ hasDragged: !1,
177
+ startButton: n ?? void 0
178
+ }, e.dataset.dragging = "true", E(), document.addEventListener("pointermove", R), document.addEventListener("pointerup", L), document.addEventListener("pointercancel", L);
179
+ }, k = (o) => {
180
+ if (!(o instanceof HTMLButtonElement) || o.disabled) return;
181
+ const n = a.find((b) => b.id === o.dataset.bridgerteToolbarItemId);
182
+ if (n) {
183
+ if (n.payloadPanel) {
184
+ const b = o.getBoundingClientRect();
185
+ t.editor.requestPayloadPanel({
186
+ menuId: n.id,
187
+ command: n.command,
188
+ panel: n.payloadPanel,
189
+ currentValues: re(n, t.editor.getCommandStates()),
190
+ anchorRect: {
191
+ x: b.left,
192
+ y: b.top,
193
+ width: b.width,
194
+ height: b.height
195
+ }
196
+ });
197
+ return;
198
+ }
199
+ t.editor.executeCommand(n.command);
200
+ }
201
+ }, Q = (o) => {
202
+ const n = $(
203
+ p,
204
+ o.dataset.bridgerteToolbarGroupId
205
+ );
206
+ if (!(!n || o.disabled)) {
207
+ if ((c == null ? void 0 : c.groupKey) === n.key) {
208
+ y();
209
+ return;
210
+ }
211
+ c = {
212
+ groupKey: n.key,
213
+ button: o,
214
+ items: n.items
215
+ }, E(), B(u, c, T, r), C(e, c), M(), se(u);
216
+ }
217
+ }, x = (o) => {
218
+ if (v) {
219
+ v = !1, o.preventDefault(), o.stopPropagation();
220
+ return;
221
+ }
222
+ const n = ye(o.target);
223
+ if (n) {
224
+ o.preventDefault(), o.stopPropagation(), Q(n);
225
+ return;
226
+ }
227
+ const b = S(o.target);
228
+ b && (o.preventDefault(), o.stopPropagation(), k(b), y());
229
+ }, F = (o) => {
230
+ o.pointerType === "mouse" && o.button !== 0 || o.preventDefault();
231
+ }, X = (o) => {
232
+ const n = o.target;
233
+ n instanceof Node && (e.contains(n) || u.contains(n)) || y();
234
+ }, q = (o) => {
235
+ if (c && u.contains(document.activeElement)) {
236
+ le(
237
+ o,
238
+ u,
239
+ c.button,
240
+ k,
241
+ y
242
+ );
243
+ return;
244
+ }
245
+ o.key === "Escape" && y();
246
+ };
247
+ e.classList.add("bridgerte__toolbar"), l.className = "bridgerte__toolbar-tooltip", l.dataset.visible = "false", u.className = "bridgerte__toolbar-group-menu", u.dataset.visible = "false", u.setAttribute("role", "menu"), e.dataset.placement = s, e.setAttribute("role", "toolbar"), e.setAttribute(
248
+ "aria-label",
249
+ s === "bottom" ? "BridgeRTE tabbar" : "BridgeRTE toolbar"
250
+ ), e.addEventListener("pointerdown", O, !0), e.addEventListener("click", x), u.addEventListener("pointerdown", F, !0), u.addEventListener("click", x), document.addEventListener("click", X), document.addEventListener("keydown", q), d && (e.addEventListener("mouseover", K), e.addEventListener("mouseout", H)), e.addEventListener("focusout", E), P();
251
+ const Y = t.editor.subscribeCommandStateChange(N);
252
+ return {
253
+ update: z,
254
+ destroy() {
255
+ h || (h = !0, I(), Y(), y(), e.removeEventListener("pointerdown", O, !0), e.removeEventListener("click", x), u.removeEventListener("pointerdown", F, !0), u.removeEventListener("click", x), document.removeEventListener("click", X), document.removeEventListener("keydown", q), d && (e.removeEventListener("mouseover", K), e.removeEventListener("mouseout", H)), V(), W(), e.removeEventListener("focusout", E), l.remove(), u.remove(), e.classList.remove("bridgerte__toolbar"), delete e.dataset.placement, e.textContent = "", e.removeAttribute("role"), e.removeAttribute("aria-label"));
256
+ }
257
+ };
258
+ }
259
+ export {
260
+ Te as c
261
+ };
262
+ //# sourceMappingURL=index-DRWIM218.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DRWIM218.js","sources":["../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/index.ts"],"sourcesContent":["export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const focusFirstToolbarGroupMenuItem = (menuElement: HTMLElement) => {\n /*\n * group menu 使用 ARIA menu 语义,打开后焦点必须进入第一个可操作项。\n * 这样键盘用户可以继续用方向键浏览,而不是停留在展开按钮上。\n */\n focusToolbarGroupMenuItem(menuElement, 0);\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : undefined;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.textContent = '⌄';\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单渲染为按钮,`|` 渲染分割线,group 只渲染一个收纳入口;组内命令交给\n * renderToolbarGroupMenu 渲染,避免 `menuKeys` 退化成另一种横向分隔语法。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n 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 renderToolbarGroupButton(\n activeGroupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusFirstToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions,\n ToolbarDragState\n} from './type';\n\nconst toolbarDragClickThresholdPx = 4;\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let dragState: ToolbarDragState | null = null;\n let shouldSuppressNextClick = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText || 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 closeGroupMenu();\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 if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n focusFirstToolbarGroupMenuItem(groupMenuElement);\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 groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleGroupMenuPointerDown = (event: PointerEvent) => {\n /*\n * group 菜单浮层挂在 toolbar 容器外,不能复用容器级 pointerdown。\n * 子菜单点击仍要保留编辑区 selection,否则格式命令会丢失原选区。\n */\n if (event.pointerType === 'mouse' && event.button !== 0) return;\n\n event.preventDefault();\n };\n\n const handleDocumentClick = (event: MouseEvent) => {\n const target = event.target;\n\n if (\n target instanceof Node\n && (container.contains(target) || groupMenuElement.contains(target))\n ) return;\n\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('pointerdown', handlePointerDown, true);\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('pointerdown', handleGroupMenuPointerDown, true);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('click', handleDocumentClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n stopToolbarDrag();\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('pointerdown', handlePointerDown, true);\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('pointerdown', handleGroupMenuPointerDown, true);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('click', handleDocumentClick);\n document.removeEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n"],"names":["getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","focusFirstToolbarGroupMenuItem","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","currentGroup","separatorElement","nextGroup","activeGroupElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarDragClickThresholdPx","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","canUseHoverTooltip","getToolbarButtonFromTarget","target","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","groupMenuElement","overlayHost","destroyed","dragState","shouldSuppressNextClick","latestCommandStates","groupMenuFloatingLayer","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","stopToolbarDrag","handlePointerMove","handlePointerUp","deltaX","currentDragState","handlePointerDown","startButton","menuItem","getPayloadPanelCurrentValues","toggleGroupMenu","groupItem","handleClick","groupButton","handleGroupMenuPointerDown","handleDocumentClick","handleKeyDown","unsubscribe"],"mappings":"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"}