bridgerte 0.9.12 → 0.9.14
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 +864 -864
- package/dist/bridge.cjs.map +1 -1
- package/dist/bridge.js.map +1 -1
- package/dist/dom.cjs +1 -1
- package/dist/dom.js +2 -2
- package/dist/{index-DDfgjstx.js → index-9gETEdDG.js} +1242 -1200
- package/dist/index-9gETEdDG.js.map +1 -0
- package/dist/index-BJAl_KEE.cjs +4 -0
- package/dist/index-BJAl_KEE.cjs.map +1 -0
- package/dist/index-CuNKUHed.js.map +1 -1
- package/dist/index-DF8OhKI4.cjs.map +1 -1
- package/dist/index-GaS65GL0.cjs.map +1 -1
- package/dist/index-JS1zNkrD.cjs +36 -0
- package/dist/index-JS1zNkrD.cjs.map +1 -0
- package/dist/index-KfoBS_v8.js +337 -0
- package/dist/index-KfoBS_v8.js.map +1 -0
- package/dist/index-sbZNOcCB.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/native-spec.cjs.map +1 -1
- package/dist/native-spec.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/webview.cjs +1 -1
- package/dist/webview.js +1 -1
- package/package.json +1 -1
- package/dist/index-BBzHVrSi.cjs +0 -4
- package/dist/index-BBzHVrSi.cjs.map +0 -1
- package/dist/index-CQie9v_I.js +0 -296
- package/dist/index-CQie9v_I.js.map +0 -1
- package/dist/index-DDfgjstx.js.map +0 -1
- package/dist/index-DIJtCo91.cjs +0 -36
- package/dist/index-DIJtCo91.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-CuNKUHed.js","sources":["../../core/src/index.ts"],"sourcesContent":["export type * from './type';\nexport { isEditorContentEmpty } from './content';\nexport { resolvePayloadPanelSchema } from './payloadPanel';\n\
|
|
1
|
+
{"version":3,"file":"index-CuNKUHed.js","sources":["../../core/src/index.ts"],"sourcesContent":["export type * from './type';\nexport { isEditorContentEmpty } from './content';\nexport { resolvePayloadPanelSchema } from './payloadPanel';\n\n/**\n * 内容结构版本号,用于后续内容协议升级时做兼容判断。\n */\nexport const BRIDGERTE_CONTENT_VERSION = '0.1.0';\n\n/**\n * 默认表格插入能力上限。\n *\n * schema、自绘和 DOM 命令执行共用这组边界;DOM 默认面板可以用更小的首屏网格展示,\n * 但最终提交和 API 执行都不应超过这里声明的库内置上限。\n */\nexport const BRIDGERTE_TABLE_INSERT_MAX_ROWS = 20;\nexport const BRIDGERTE_TABLE_INSERT_MAX_COLS = 20;\n"],"names":["BRIDGERTE_CONTENT_VERSION","BRIDGERTE_TABLE_INSERT_MAX_ROWS","BRIDGERTE_TABLE_INSERT_MAX_COLS"],"mappings":"AAOO,MAAMA,IAA4B,SAQ5BC,IAAkC,IAClCC,IAAkC;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-DF8OhKI4.cjs","sources":["../../core/src/payloadPanel/index.ts"],"sourcesContent":["import type {\
|
|
1
|
+
{"version":3,"file":"index-DF8OhKI4.cjs","sources":["../../core/src/payloadPanel/index.ts"],"sourcesContent":["import type {\n PayloadPanelConfig,\n PayloadPanelField,\n PayloadPanelFieldConfig,\n PayloadPanelOption,\n PayloadPanelSchema\n} from './type';\n\nexport type * from './type';\n\nconst hasOwnConfigKeys = (config: object | undefined) => (\n config !== undefined && Object.keys(config).length > 0\n);\n\nconst resolveOptionList = (\n options: PayloadPanelOption[],\n config: PayloadPanelFieldConfig\n) => {\n const baseOptions = config.options?.length ? config.options : options;\n const optionByValue = new Map(baseOptions.map((option) => [option.value, option]));\n const includedOptions = config.includeValues?.length\n ? config.includeValues.flatMap((value) => {\n const option = optionByValue.get(value);\n\n return option ? [option] : [];\n })\n : baseOptions;\n const excludeValues = new Set(config.excludeValues ?? []);\n const filteredOptions = includedOptions.filter((option) => !excludeValues.has(option.value));\n const nextOptions = filteredOptions.map((option) => ({\n ...option,\n label: config.optionLabels?.[option.value] ?? option.label,\n value: config.optionValues?.[option.value] ?? option.value\n }));\n\n /*\n * 配置写错时不返回空候选,避免默认 DOM 面板、自绘 request 和原生菜单拿到\n * 无法操作的空列表;业务真要完全隐藏菜单应通过菜单 config 排除入口。\n */\n return nextOptions.length > 0 ? nextOptions : baseOptions;\n};\n\nconst resolveFieldBaseOverride = (\n field: PayloadPanelField,\n config: PayloadPanelFieldConfig\n) => ({\n label: config.label ?? field.label,\n defaultValue: config.defaultValue ?? field.defaultValue,\n placeholder: config.placeholder ?? field.placeholder\n});\n\nconst resolvePayloadPanelField = (\n field: PayloadPanelField,\n config: PayloadPanelFieldConfig | undefined\n): PayloadPanelField => {\n if (!config || !hasOwnConfigKeys(config)) return field;\n\n if (field.type === 'select') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n options: resolveOptionList(field.options, config)\n };\n }\n\n if (field.type === 'color') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n options: resolveOptionList(field.options ?? [], config)\n };\n }\n\n if (field.type === 'number') {\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config),\n min: config.min ?? field.min,\n max: config.max ?? field.max,\n step: config.step ?? field.step\n };\n }\n\n return {\n ...field,\n ...resolveFieldBaseOverride(field, config)\n };\n};\n\n/**\n * 解析参数面板 schema。\n *\n * 这个纯函数只处理 schema 数据,不理解 DOM、Lexical 或具体命令;toolbar、hoverbar、\n * code block header 和 WebView host request 都应先走这里,保证默认 UI 和业务自绘同源。\n */\nexport const resolvePayloadPanelSchema = (\n panel: PayloadPanelSchema,\n config?: PayloadPanelConfig\n): PayloadPanelSchema => {\n const panelConfig = config?.[panel.id];\n\n if (!panelConfig || !hasOwnConfigKeys(panelConfig)) return panel;\n\n return {\n ...panel,\n title: panelConfig.title ?? panel.title,\n description: panelConfig.description ?? panel.description,\n fields: panel.fields.map((field) => resolvePayloadPanelField(\n field,\n panelConfig.fields?.[field.name]\n ))\n };\n};\n"],"names":["hasOwnConfigKeys","config","resolveOptionList","options","baseOptions","_a","optionByValue","option","includedOptions","_b","value","excludeValues","nextOptions","resolveFieldBaseOverride","field","resolvePayloadPanelField","resolvePayloadPanelSchema","panel","panelConfig"],"mappings":"aAUA,MAAMA,EAAoBC,GACxBA,IAAW,QAAa,OAAO,KAAKA,CAAM,EAAE,OAAS,EAGjDC,EAAoB,CACxBC,EACAF,IACG,SACH,MAAMG,GAAcC,EAAAJ,EAAO,UAAP,MAAAI,EAAgB,OAASJ,EAAO,QAAUE,EACxDG,EAAgB,IAAI,IAAIF,EAAY,IAAKG,GAAW,CAACA,EAAO,MAAOA,CAAM,CAAC,CAAC,EAC3EC,GAAkBC,EAAAR,EAAO,gBAAP,MAAAQ,EAAsB,OAC1CR,EAAO,cAAc,QAASS,GAAU,CACxC,MAAMH,EAASD,EAAc,IAAII,CAAK,EAEtC,OAAOH,EAAS,CAACA,CAAM,EAAI,CAAA,CAC7B,CAAC,EACCH,EACEO,EAAgB,IAAI,IAAIV,EAAO,eAAiB,CAAA,CAAE,EAElDW,EADkBJ,EAAgB,OAAQD,GAAW,CAACI,EAAc,IAAIJ,EAAO,KAAK,CAAC,EACvD,IAAKA,GAAA,SAAY,OACnD,GAAGA,EACH,QAAOF,EAAAJ,EAAO,eAAP,YAAAI,EAAsBE,EAAO,SAAUA,EAAO,MACrD,QAAOE,EAAAR,EAAO,eAAP,YAAAQ,EAAsBF,EAAO,SAAUA,EAAO,KAAA,EACrD,EAMF,OAAOK,EAAY,OAAS,EAAIA,EAAcR,CAChD,EAEMS,EAA2B,CAC/BC,EACAb,KACI,CACJ,MAAOA,EAAO,OAASa,EAAM,MAC7B,aAAcb,EAAO,cAAgBa,EAAM,aAC3C,YAAab,EAAO,aAAea,EAAM,WAC3C,GAEMC,EAA2B,CAC/BD,EACAb,IAEI,CAACA,GAAU,CAACD,EAAiBC,CAAM,EAAUa,EAE7CA,EAAM,OAAS,SACV,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,EACzC,QAASC,EAAkBY,EAAM,QAASb,CAAM,CAAA,EAIhDa,EAAM,OAAS,QACV,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,EACzC,QAASC,EAAkBY,EAAM,SAAW,CAAA,EAAIb,CAAM,CAAA,EAItDa,EAAM,OAAS,SACV,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,EACzC,IAAKA,EAAO,KAAOa,EAAM,IACzB,IAAKb,EAAO,KAAOa,EAAM,IACzB,KAAMb,EAAO,MAAQa,EAAM,IAAA,EAIxB,CACL,GAAGA,EACH,GAAGD,EAAyBC,EAAOb,CAAM,CAAA,EAUhCe,EAA4B,CACvCC,EACAhB,IACuB,CACvB,MAAMiB,EAAcjB,GAAA,YAAAA,EAASgB,EAAM,IAEnC,MAAI,CAACC,GAAe,CAAClB,EAAiBkB,CAAW,EAAUD,EAEpD,CACL,GAAGA,EACH,MAAOC,EAAY,OAASD,EAAM,MAClC,YAAaC,EAAY,aAAeD,EAAM,YAC9C,OAAQA,EAAM,OAAO,IAAKH,GAAA,OAAU,OAAAC,EAClCD,GACAT,EAAAa,EAAY,SAAZ,YAAAb,EAAqBS,EAAM,KAAI,EAChC,CAAA,CAEL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-GaS65GL0.cjs","sources":["../../core/src/index.ts"],"sourcesContent":["export type * from './type';\nexport { isEditorContentEmpty } from './content';\nexport { resolvePayloadPanelSchema } from './payloadPanel';\n\
|
|
1
|
+
{"version":3,"file":"index-GaS65GL0.cjs","sources":["../../core/src/index.ts"],"sourcesContent":["export type * from './type';\nexport { isEditorContentEmpty } from './content';\nexport { resolvePayloadPanelSchema } from './payloadPanel';\n\n/**\n * 内容结构版本号,用于后续内容协议升级时做兼容判断。\n */\nexport const BRIDGERTE_CONTENT_VERSION = '0.1.0';\n\n/**\n * 默认表格插入能力上限。\n *\n * schema、自绘和 DOM 命令执行共用这组边界;DOM 默认面板可以用更小的首屏网格展示,\n * 但最终提交和 API 执行都不应超过这里声明的库内置上限。\n */\nexport const BRIDGERTE_TABLE_INSERT_MAX_ROWS = 20;\nexport const BRIDGERTE_TABLE_INSERT_MAX_COLS = 20;\n"],"names":["BRIDGERTE_CONTENT_VERSION"],"mappings":"aAOO,MAAMA,EAA4B"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";const q=require("./native-spec.cjs"),f=require("./index-BJAl_KEE.cjs"),O={toolbarGroup:`
|
|
2
|
+
<svg
|
|
3
|
+
aria-hidden="true"
|
|
4
|
+
class="lucide lucide-ellipsis"
|
|
5
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
6
|
+
width="18"
|
|
7
|
+
height="18"
|
|
8
|
+
viewBox="0 0 24 24"
|
|
9
|
+
fill="none"
|
|
10
|
+
stroke="currentColor"
|
|
11
|
+
stroke-width="2"
|
|
12
|
+
stroke-linecap="round"
|
|
13
|
+
stroke-linejoin="round"
|
|
14
|
+
>
|
|
15
|
+
<circle cx="12" cy="12" r="1" />
|
|
16
|
+
<circle cx="19" cy="12" r="1" />
|
|
17
|
+
<circle cx="5" cy="12" r="1" />
|
|
18
|
+
</svg>
|
|
19
|
+
`,chevronDown:`
|
|
20
|
+
<svg
|
|
21
|
+
aria-hidden="true"
|
|
22
|
+
class="lucide lucide-chevron-down"
|
|
23
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
+
width="12"
|
|
25
|
+
height="12"
|
|
26
|
+
viewBox="0 0 24 24"
|
|
27
|
+
fill="none"
|
|
28
|
+
stroke="currentColor"
|
|
29
|
+
stroke-width="2"
|
|
30
|
+
stroke-linecap="round"
|
|
31
|
+
stroke-linejoin="round"
|
|
32
|
+
>
|
|
33
|
+
<path d="m6 9 6 6 6-6" />
|
|
34
|
+
</svg>
|
|
35
|
+
`},V=t=>Array.from(t.querySelectorAll(".bridgerte__toolbar-group-menu-item")).filter(e=>!e.disabled),j=(t,e)=>{const l=V(t)[e];l&&l.focus()},Z=(t,e,i,l,u)=>{var s,d;const n=V(e),r=document.activeElement instanceof HTMLButtonElement?n.indexOf(document.activeElement):-1,m=v=>{var o;if(n.length===0)return;const h=((r>=0?r:0)+v+n.length)%n.length;(o=n[h])==null||o.focus()};switch(t.key){case"ArrowDown":t.preventDefault(),m(1);break;case"ArrowUp":t.preventDefault(),m(-1);break;case"Home":t.preventDefault(),(s=n[0])==null||s.focus();break;case"End":t.preventDefault(),(d=n.at(-1))==null||d.focus();break;case"Enter":case" ":document.activeElement instanceof HTMLButtonElement&&(t.preventDefault(),l(document.activeElement),u(),i.focus());break;case"Escape":t.preventDefault(),i.focus(),u();break}},x="button[data-bridgerte-toolbar-group-id]",tt="button[data-bridgerte-toolbar-item-id]",M=[tt,".bridgerte__toolbar-group-menu-item"].join(","),et=(t,e)=>{const i=t.map(l=>f.getMenuStateForItem(l,e));return{active:i.some(l=>l.active),disabled:i.length>0&&i.every(l=>l.disabled)}},ot=(t,e,i,l,u)=>{const n=f.getMenuStateForItem(e,i),r=document.createElement("button"),m=l[e.icon]??f.defaultMenuIcons[e.icon];r.type="button",r.className="bridgerte__toolbar-button",r.disabled=n.disabled,r.dataset.active=String(n.active),r.dataset.bridgerteToolbarItemId=e.id,r.setAttribute("aria-label",e.label),r.setAttribute("aria-pressed",String(n.active)),u&&(r.dataset.tooltip=e.label),f.appendMenuIcon(r,m,e.label),t.append(r)},nt=(t,e,i,l,u)=>{const n=document.createElement("button"),r=et(e.items,i),m=e.icon?l[e.icon]??f.defaultMenuIcons[e.icon]:O.toolbarGroup,s=document.createElement("span");n.type="button",n.className="bridgerte__toolbar-button bridgerte__toolbar-group-button",n.disabled=r.disabled,n.dataset.active=String(r.active),n.dataset.bridgerteToolbarGroupId=e.key,n.dataset.open="false",n.setAttribute("aria-label",e.title),n.setAttribute("aria-haspopup","menu"),n.setAttribute("aria-expanded","false"),n.setAttribute("aria-pressed",String(r.active)),u&&(n.dataset.tooltip=e.title),f.appendMenuIcon(n,m,e.title),s.className="bridgerte__toolbar-group-indicator",s.setAttribute("aria-hidden","true"),s.innerHTML=O.chevronDown,n.append(s),t.append(n)},rt=(t,e,i,l,u)=>{t.textContent="",e.forEach(n=>{if(n.type==="separator"){const m=document.createElement("span");m.className="bridgerte__toolbar-separator",m.dataset.separatorId=n.key,m.setAttribute("aria-hidden","true"),t.append(m);return}if(n.type==="button"){ot(t,n.item,i,l,u);return}const r=document.createElement("div");r.className="bridgerte__toolbar-group",r.dataset.group=n.key,r.setAttribute("aria-label",n.title),t.append(r),nt(r,n,i,l,u)})},P=(t,e,i,l)=>{if(t.textContent="",!e){t.dataset.visible="false";return}e.items.forEach(u=>{const n=f.getMenuStateForItem(u,i),r=document.createElement("button"),m=l[u.icon]??f.defaultMenuIcons[u.icon],s=document.createElement("span");r.type="button",r.className="bridgerte__menu-item bridgerte__toolbar-group-menu-item",r.disabled=n.disabled,r.dataset.active=String(n.active),r.dataset.bridgerteToolbarItemId=u.id,r.setAttribute("role","menuitem"),r.setAttribute("aria-label",u.label),r.setAttribute("aria-pressed",String(n.active)),f.appendMenuIcon(r,m,u.label),s.className="bridgerte__toolbar-group-menu-label",s.textContent=u.label,r.append(s),t.append(r)}),t.dataset.visible="true",t.style.minWidth=`${e.button.offsetWidth}px`},D=(t,e)=>{t.querySelectorAll(x).forEach(i=>{const l=(e==null?void 0:e.groupKey)===i.dataset.bridgerteToolbarGroupId;i.dataset.open=String(l),i.setAttribute("aria-expanded",String(l))})},X=(t,e)=>t.find(i=>i.type==="group"&&i.key===e),Y=8,_=(t,e)=>e instanceof Node&&t.contains(e),B=(t,e)=>t instanceof Element?t.closest(e):null,at=(t,e,i,l,u)=>{let n=null,r=null;const m=o=>B(o,x)??(_(e,o)?B(o,M):null),s=o=>{m(o.target)&&o.preventDefault()},d=o=>{const p=o.touches[0],y=B(o.target,x),w=_(e,o.target)?B(o.target,M):null,T=y??w;!T||!p||(o.preventDefault(),n={button:T,kind:y?"group":"menu-item",startX:p.clientX,startY:p.clientY})},v=()=>{n=null},g=o=>{if(!n)return;const p=n,y=o.changedTouches[0],w=m(o.target);if(n=null,!y||w!==p.button)return;const T=Math.abs(y.clientX-p.startX),L=Math.abs(y.clientY-p.startY);if(!(T>Y||L>Y)){if(o.preventDefault(),o.stopPropagation(),r=p.button,p.kind==="group"){i(p.button);return}l(p.button),u()}},h=o=>{_(t,o.target)||_(e,o.target)||u()};return t.addEventListener("pointerdown",s),t.addEventListener("mousedown",s),t.addEventListener("touchstart",d,{passive:!1}),t.addEventListener("touchend",g),t.addEventListener("touchcancel",v),e.addEventListener("pointerdown",s),e.addEventListener("mousedown",s),e.addEventListener("touchstart",d,{passive:!1}),e.addEventListener("touchend",g),e.addEventListener("touchcancel",v),document.addEventListener("pointerdown",h,!0),{consumeSuppressedClick(o){return r!==o?!1:(r=null,!0)},destroy(){t.removeEventListener("pointerdown",s),t.removeEventListener("mousedown",s),t.removeEventListener("touchstart",d),t.removeEventListener("touchend",g),t.removeEventListener("touchcancel",v),e.removeEventListener("pointerdown",s),e.removeEventListener("mousedown",s),e.removeEventListener("touchstart",d),e.removeEventListener("touchend",g),e.removeEventListener("touchcancel",v),document.removeEventListener("pointerdown",h,!0)}}},st=8,it=6,ct=()=>{var t;return typeof window<"u"&&((t=window.matchMedia)==null?void 0:t.call(window,"(hover: hover) and (pointer: fine)").matches)===!0},I=t=>{const e=t instanceof Element?t.closest(M):null;return e instanceof HTMLButtonElement?e:null},U=t=>{const e=t instanceof Element?t.closest(x):null;return e instanceof HTMLButtonElement?e:null};function lt(t,e){const i=e.placement??"top",l=f.resolveMenuSchemaForDom(e.menuSchema??q.defaultMenuSchema,{menuLabels:e.menuLabels,payloadPanelConfig:e.payloadPanelConfig}),u=q.resolveToolbarMenu(e.toolbarConfig,l),n=u.flatMap(a=>a.type==="button"?[a.item]:a.type==="group"?a.items:[]),r=e.icons??{},m=ct(),s=document.createElement("div"),d=document.createElement("div"),v=t.closest(".bridgerte")??t;let g=!1,h=e.editor.getCommandStates(),o=null,p=null;const y=f.bindTouchPressedState(t,{targetSelector:["button[data-bridgerte-toolbar-item-id]","button[data-bridgerte-toolbar-group-id]"].join(",")}),w=f.bindTouchPressedState(d,{targetSelector:".bridgerte__toolbar-group-menu-item"}),T=()=>{v.append(s),v.append(d)},L=()=>{p==null||p.setOpen(!1),p==null||p.destroy(),p=null},H=()=>{o&&(L(),p=f.createFloatingLayer(o.button,d,{placement:i==="bottom"?"top-start":"bottom-start",offset:it,strategy:"fixed"}),p.setOpen(!0))},E=()=>{!o&&!p||(L(),o=null,P(d,o,h,r),D(t,o))},N=a=>{if(!g&&(h=a,o&&L(),rt(t,u,a,r,m),T(),o)){const c=Array.from(t.querySelectorAll(x)).find(Q=>Q.dataset.bridgerteToolbarGroupId===(o==null?void 0:o.groupKey)),b=X(u,o.groupKey);o=c&&b?{groupKey:o.groupKey,button:c,items:b.items}:null,P(d,o,h,r),D(t,o),o&&H()}},W=()=>{g||N(e.editor.getCommandStates())},S=()=>{s.dataset.visible="false",s.textContent=""},z=a=>{const c=a.dataset.tooltip;if(!m||!c)return;const b=a.getBoundingClientRect();s.textContent=c,s.dataset.visible="true",s.style.left=`${b.left+b.width/2}px`,s.style.top=`${b.top-st}px`},F=a=>{const c=I(a.target);c&&z(c)},K=a=>{const c=a.relatedTarget,b=I(a.target);b&&c instanceof Node&&b.contains(c)||S()},C=a=>{if(!(a instanceof HTMLButtonElement)||a.disabled)return;const c=n.find(b=>b.id===a.dataset.bridgerteToolbarItemId);if(c){if(c.payloadPanel){const b=a.getBoundingClientRect();e.editor.requestPayloadPanel({menuId:c.id,command:c.command,panel:c.payloadPanel,currentValues:f.getPayloadPanelCurrentValues(c,e.editor.getCommandStates()),anchorRect:{x:b.left,y:b.top,width:b.width,height:b.height}});return}e.editor.executeCommand(c.command)}},A=(a,c=!1)=>{const b=X(u,a.dataset.bridgerteToolbarGroupId);if(!(!b||a.disabled)){if((o==null?void 0:o.groupKey)===b.key){if(c){j(d,0);return}E();return}o={groupKey:b.key,button:a,items:b.items},S(),P(d,o,h,r),D(t,o),H(),c&&j(d,0)}},k=a=>{const c=U(a.target);if(c){if(a.preventDefault(),a.stopPropagation(),G.consumeSuppressedClick(c))return;A(c);return}const b=I(a.target);b&&(a.preventDefault(),a.stopPropagation(),!G.consumeSuppressedClick(b)&&(C(b),E()))},R=a=>{if(o&&d.contains(document.activeElement)){Z(a,d,o.button,C,E);return}const c=U(a.target);if(c&&(a.key==="Enter"||a.key===" "||a.key==="ArrowDown")){a.preventDefault(),a.stopPropagation(),A(c,!0);return}a.key==="Escape"&&E()};t.classList.add("bridgerte__toolbar"),s.className="bridgerte__toolbar-tooltip",s.dataset.visible="false",d.className="bridgerte__floating-menu bridgerte__toolbar-group-menu",d.dataset.visible="false",d.setAttribute("role","menu"),t.dataset.placement=i,t.setAttribute("role","toolbar"),t.setAttribute("aria-label",i==="bottom"?"BridgeRTE tabbar":"BridgeRTE toolbar"),t.addEventListener("click",k),d.addEventListener("click",k),document.addEventListener("keydown",R),m&&(t.addEventListener("mouseover",F),t.addEventListener("mouseout",K)),t.addEventListener("focusout",S),T();const G=at(t,d,A,C,E),J=e.editor.subscribeCommandStateChange(N);return{update:W,destroy(){g||(g=!0,J(),E(),t.removeEventListener("click",k),d.removeEventListener("click",k),document.removeEventListener("keydown",R),G.destroy(),m&&(t.removeEventListener("mouseover",F),t.removeEventListener("mouseout",K)),y(),w(),t.removeEventListener("focusout",S),s.remove(),d.remove(),t.classList.remove("bridgerte__toolbar"),delete t.dataset.placement,t.textContent="",t.removeAttribute("role"),t.removeAttribute("aria-label"))}}}const ut=/[\u200B-\u200D\uFEFF]/g,dt=["img","video","audio","iframe","table","pre","code","hr","figure","canvas","svg","math",'[data-type="mention"]'].join(","),$=t=>(t==null?void 0:t.replace(ut,"").trim())??"",bt=t=>{if(!$(t))return!1;const e=document.createElement("template");return e.innerHTML=t,!!($(e.content.textContent)||e.content.querySelector(dt))};exports.createRichTextToolbar=lt;exports.hasMeaningfulHtmlContent=bt;
|
|
36
|
+
//# sourceMappingURL=index-JS1zNkrD.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-JS1zNkrD.cjs","sources":["../../dom/src/menuIcon/uiIcons.ts","../../dom/src/richTextToolbar/groupMenuKeyboard.ts","../../dom/src/richTextToolbar/render.ts","../../dom/src/richTextToolbar/groupMenuInteraction.ts","../../dom/src/richTextToolbar/index.ts","../../dom/src/htmlContent/index.ts"],"sourcesContent":["/**\n * DOM UI chrome icon 表。\n *\n * 这里放 toolbar 收纳入口、下拉箭头这类控件自身图标。它们不属于 `MenuItem.icon`\n * 跨端 schema,也不应该进入 `defaultMenuIcons` 的 schema 对齐检查。\n */\nexport const defaultMenuUiIcons = {\n toolbarGroup: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-ellipsis\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <circle cx=\"19\" cy=\"12\" r=\"1\" />\n <circle cx=\"5\" cy=\"12\" r=\"1\" />\n </svg>\n `,\n chevronDown: `\n <svg\n aria-hidden=\"true\"\n class=\"lucide lucide-chevron-down\"\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n} as const;\n","export const getEnabledGroupMenuButtons = (menuElement: HTMLElement) => (\n Array.from(\n menuElement.querySelectorAll<HTMLButtonElement>('.bridgerte__toolbar-group-menu-item')\n ).filter((button) => !button.disabled)\n);\n\nexport const focusToolbarGroupMenuItem = (menuElement: HTMLElement, index: number) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const nextButton = buttons[index];\n\n if (nextButton) nextButton.focus();\n};\n\nexport const handleToolbarGroupMenuKeyDown = (\n event: KeyboardEvent,\n menuElement: HTMLElement,\n returnButton: HTMLButtonElement,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n const buttons = getEnabledGroupMenuButtons(menuElement);\n const activeIndex = document.activeElement instanceof HTMLButtonElement\n ? buttons.indexOf(document.activeElement)\n : -1;\n const focusByOffset = (offset: number) => {\n if (buttons.length === 0) return;\n\n const baseIndex = activeIndex >= 0 ? activeIndex : 0;\n const nextIndex = (baseIndex + offset + buttons.length) % buttons.length;\n\n buttons[nextIndex]?.focus();\n };\n\n /*\n * ARIA menu 语义要求支持 roving focus。这里不改 toolbar 的横向键盘模型,\n * 只在已打开的纵向收纳菜单内处理上下方向、首尾跳转和执行/关闭。\n */\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n focusByOffset(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n focusByOffset(-1);\n break;\n case 'Home':\n event.preventDefault();\n buttons[0]?.focus();\n break;\n case 'End':\n event.preventDefault();\n buttons.at(-1)?.focus();\n break;\n case 'Enter':\n case ' ':\n if (document.activeElement instanceof HTMLButtonElement) {\n event.preventDefault();\n executeToolbarButton(document.activeElement);\n closeGroupMenu();\n returnButton.focus();\n }\n break;\n case 'Escape':\n event.preventDefault();\n returnButton.focus();\n closeGroupMenu();\n break;\n default:\n break;\n }\n};\n","import type { CommandState } from '@bridgerte/core';\nimport type { MenuItem, ResolvedToolbarItem } from '@bridgerte/native-spec';\nimport {\n appendMenuIcon,\n defaultMenuIcons,\n defaultMenuUiIcons\n} from './icons';\nimport { getMenuStateForItem } from '../menuRuntime';\nimport type {\n RichTextToolbarIcons,\n ToolbarGroupMenuState\n} from './type';\n\nexport const toolbarGroupButtonSelector = 'button[data-bridgerte-toolbar-group-id]';\nexport const toolbarButtonSelector = 'button[data-bridgerte-toolbar-item-id]';\n// 可执行按钮同时覆盖 toolbar 主按钮和 group menu 子项,避免浮层子菜单绕过统一命令入口。\nexport const toolbarExecutableButtonSelector = [\n toolbarButtonSelector,\n '.bridgerte__toolbar-group-menu-item'\n].join(',');\n\nconst getGroupMenuState = (items: MenuItem[], commandStates: CommandState[]) => {\n const itemStates = items.map((item) => getMenuStateForItem(item, commandStates));\n\n return {\n active: itemStates.some((state) => state.active),\n disabled: itemStates.length > 0 && itemStates.every((state) => state.disabled)\n };\n};\n\nconst renderToolbarButton = (\n groupElement: HTMLElement,\n item: MenuItem,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n // icon 兜底顺序固定为:业务覆盖 > DOM 默认 SVG > label 文本。\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n if (enableTooltip) button.dataset.tooltip = item.label;\n\n appendMenuIcon(button, iconSvg, item.label);\n\n groupElement.append(button);\n};\n\nconst renderToolbarGroupButton = (\n groupElement: HTMLElement,\n toolbarItem: Extract<ResolvedToolbarItem, { type: 'group' }>,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n const button = document.createElement('button');\n const groupState = getGroupMenuState(toolbarItem.items, commandStates);\n const iconSvg = toolbarItem.icon\n ? icons[toolbarItem.icon] ?? defaultMenuIcons[toolbarItem.icon]\n : defaultMenuUiIcons.toolbarGroup;\n const indicator = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__toolbar-button bridgerte__toolbar-group-button';\n button.disabled = groupState.disabled;\n button.dataset.active = String(groupState.active);\n button.dataset.bridgerteToolbarGroupId = toolbarItem.key;\n button.dataset.open = 'false';\n button.setAttribute('aria-label', toolbarItem.title);\n button.setAttribute('aria-haspopup', 'menu');\n button.setAttribute('aria-expanded', 'false');\n button.setAttribute('aria-pressed', String(groupState.active));\n if (enableTooltip) button.dataset.tooltip = toolbarItem.title;\n\n appendMenuIcon(button, iconSvg, toolbarItem.title);\n\n indicator.className = 'bridgerte__toolbar-group-indicator';\n indicator.setAttribute('aria-hidden', 'true');\n indicator.innerHTML = defaultMenuUiIcons.chevronDown;\n button.append(indicator);\n groupElement.append(button);\n};\n\n/**\n * 渲染 toolbar 横向主入口。\n *\n * 字符串菜单直接渲染为按钮,`|` 渲染分割线。\n * 只有用户显式声明的 group 配置才生成收纳入口,避免 schema 隐式改变 DOM 结构。\n */\nexport const renderToolbar = (\n toolbarElement: HTMLElement,\n toolbarItems: ResolvedToolbarItem[],\n commandStates: CommandState[],\n icons: RichTextToolbarIcons,\n enableTooltip: boolean\n) => {\n toolbarElement.textContent = '';\n\n toolbarItems.forEach((toolbarItem) => {\n if (toolbarItem.type === 'separator') {\n const separatorElement = document.createElement('span');\n\n separatorElement.className = 'bridgerte__toolbar-separator';\n separatorElement.dataset.separatorId = toolbarItem.key;\n separatorElement.setAttribute('aria-hidden', 'true');\n toolbarElement.append(separatorElement);\n return;\n }\n\n if (toolbarItem.type === 'button') {\n renderToolbarButton(\n toolbarElement,\n toolbarItem.item,\n commandStates,\n icons,\n enableTooltip\n );\n return;\n }\n\n /*\n * 收纳菜单是用户在 toolbarConfig 里显式声明的结构;普通菜单不会自动生成 DOM 包裹,\n * 显示分组完全交给用户用 group 配置或 `|` 控制。\n */\n const groupElement = document.createElement('div');\n\n groupElement.className = 'bridgerte__toolbar-group';\n groupElement.dataset.group = toolbarItem.key;\n groupElement.setAttribute('aria-label', toolbarItem.title);\n toolbarElement.append(groupElement);\n\n renderToolbarGroupButton(\n groupElement,\n toolbarItem,\n commandStates,\n icons,\n enableTooltip\n );\n });\n};\n\n/**\n * 渲染 group button 打开的纵向收纳菜单。\n *\n * 浮层只展示 MenuItem 子项并复用现有 item id,点击执行仍由 index.ts 统一走 EditorAPI。\n */\nexport const renderToolbarGroupMenu = (\n menuElement: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null,\n commandStates: CommandState[],\n icons: RichTextToolbarIcons\n) => {\n menuElement.textContent = '';\n\n if (!groupMenuState) {\n menuElement.dataset.visible = 'false';\n return;\n }\n\n groupMenuState.items.forEach((item) => {\n const state = getMenuStateForItem(item, commandStates);\n const button = document.createElement('button');\n const iconSvg = icons[item.icon] ?? defaultMenuIcons[item.icon];\n const labelElement = document.createElement('span');\n\n button.type = 'button';\n button.className = 'bridgerte__menu-item bridgerte__toolbar-group-menu-item';\n button.disabled = state.disabled;\n button.dataset.active = String(state.active);\n button.dataset.bridgerteToolbarItemId = item.id;\n button.setAttribute('role', 'menuitem');\n button.setAttribute('aria-label', item.label);\n button.setAttribute('aria-pressed', String(state.active));\n\n appendMenuIcon(button, iconSvg, item.label);\n labelElement.className = 'bridgerte__toolbar-group-menu-label';\n labelElement.textContent = item.label;\n button.append(labelElement);\n menuElement.append(button);\n });\n\n menuElement.dataset.visible = 'true';\n menuElement.style.minWidth = `${groupMenuState.button.offsetWidth}px`;\n};\n\nexport const syncToolbarGroupButtonState = (\n container: HTMLElement,\n groupMenuState: ToolbarGroupMenuState | null\n) => {\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector).forEach((button) => {\n const open = groupMenuState?.groupKey === button.dataset.bridgerteToolbarGroupId;\n\n button.dataset.open = String(open);\n button.setAttribute('aria-expanded', String(open));\n });\n};\n\nexport const findToolbarGroupMenuItem = (\n toolbarItems: ResolvedToolbarItem[],\n groupKey: string | undefined\n) => toolbarItems.find((item): item is Extract<ResolvedToolbarItem, { type: 'group' }> => (\n item.type === 'group' && item.key === groupKey\n));\n","import {\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\n\nconst toolbarGroupTouchMoveTolerancePx = 8;\n\nconst isInsideNode = (container: HTMLElement, target: EventTarget | null) => (\n target instanceof Node && container.contains(target)\n);\n\nconst getClosestButton = (\n target: EventTarget | null,\n selector: string\n) => (\n target instanceof Element ? target.closest<HTMLButtonElement>(selector) : null\n);\n\n/**\n * 创建 toolbar 收纳菜单交互控制器。\n *\n * 这个控制器只处理 group menu overlay 的交互边界:收纳入口和菜单项在按下阶段不能抢走\n * 编辑器焦点,touch tap 需要在 touchend 主动完成,外部 pointerdown 才关闭菜单。\n */\nexport const createToolbarGroupMenuInteraction = (\n container: HTMLElement,\n groupMenuElement: HTMLElement,\n toggleGroupMenu: (button: HTMLButtonElement) => void,\n executeToolbarButton: (button: HTMLButtonElement) => void,\n closeGroupMenu: () => void\n) => {\n let pendingTouch: {\n button: HTMLButtonElement;\n kind: 'group' | 'menu-item';\n startX: number;\n startY: number;\n } | null = null;\n let suppressNextClickButton: HTMLButtonElement | null = null;\n\n const getInteractiveButtonFromTarget = (target: EventTarget | null) => (\n getClosestButton(target, toolbarGroupButtonSelector)\n ?? (\n isInsideNode(groupMenuElement, target)\n ? getClosestButton(target, toolbarExecutableButtonSelector)\n : null\n )\n );\n\n const handlePressStart = (event: PointerEvent | MouseEvent) => {\n const button = getInteractiveButtonFromTarget(event.target);\n\n if (!button) return;\n\n /*\n * 收纳入口和收纳菜单项都属于编辑器工具区。按下阶段阻止默认 focus 转移,\n * 避免 H5 contenteditable blur 后软键盘收起,宿主随即隐藏 toolbar 和 overlay。\n */\n event.preventDefault();\n };\n\n const handleTouchStart = (event: TouchEvent) => {\n const touch = event.touches[0];\n const groupButton = getClosestButton(event.target, toolbarGroupButtonSelector);\n const menuItemButton = isInsideNode(groupMenuElement, event.target)\n ? getClosestButton(event.target, toolbarExecutableButtonSelector)\n : null;\n const button = groupButton ?? menuItemButton;\n\n if (!button || !touch) return;\n\n event.preventDefault();\n pendingTouch = {\n button,\n kind: groupButton ? 'group' : 'menu-item',\n startX: touch.clientX,\n startY: touch.clientY\n };\n };\n\n const clearPendingTouch = () => {\n pendingTouch = null;\n };\n\n const handleTouchEnd = (event: TouchEvent) => {\n if (!pendingTouch) return;\n\n const touchState = pendingTouch;\n const touch = event.changedTouches[0];\n const endButton = getInteractiveButtonFromTarget(event.target);\n\n pendingTouch = null;\n if (!touch || endButton !== touchState.button) return;\n\n const deltaX = Math.abs(touch.clientX - touchState.startX);\n const deltaY = Math.abs(touch.clientY - touchState.startY);\n\n if (\n deltaX > toolbarGroupTouchMoveTolerancePx\n || deltaY > toolbarGroupTouchMoveTolerancePx\n ) return;\n\n event.preventDefault();\n event.stopPropagation();\n suppressNextClickButton = touchState.button;\n\n if (touchState.kind === 'group') {\n toggleGroupMenu(touchState.button);\n return;\n }\n\n executeToolbarButton(touchState.button);\n closeGroupMenu();\n };\n\n const handleDocumentPointerDown = (event: PointerEvent) => {\n if (\n isInsideNode(container, event.target)\n || isInsideNode(groupMenuElement, event.target)\n ) return;\n\n closeGroupMenu();\n };\n\n container.addEventListener('pointerdown', handlePressStart);\n container.addEventListener('mousedown', handlePressStart);\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchend', handleTouchEnd);\n container.addEventListener('touchcancel', clearPendingTouch);\n groupMenuElement.addEventListener('pointerdown', handlePressStart);\n groupMenuElement.addEventListener('mousedown', handlePressStart);\n groupMenuElement.addEventListener('touchstart', handleTouchStart, { passive: false });\n groupMenuElement.addEventListener('touchend', handleTouchEnd);\n groupMenuElement.addEventListener('touchcancel', clearPendingTouch);\n document.addEventListener('pointerdown', handleDocumentPointerDown, true);\n\n return {\n consumeSuppressedClick(button: HTMLButtonElement) {\n if (suppressNextClickButton !== button) return false;\n\n suppressNextClickButton = null;\n return true;\n },\n destroy() {\n container.removeEventListener('pointerdown', handlePressStart);\n container.removeEventListener('mousedown', handlePressStart);\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchend', handleTouchEnd);\n container.removeEventListener('touchcancel', clearPendingTouch);\n groupMenuElement.removeEventListener('pointerdown', handlePressStart);\n groupMenuElement.removeEventListener('mousedown', handlePressStart);\n groupMenuElement.removeEventListener('touchstart', handleTouchStart);\n groupMenuElement.removeEventListener('touchend', handleTouchEnd);\n groupMenuElement.removeEventListener('touchcancel', clearPendingTouch);\n document.removeEventListener('pointerdown', handleDocumentPointerDown, true);\n }\n };\n};\n","import type { CommandState } from '@bridgerte/core';\nimport {\n defaultMenuSchema,\n resolveToolbarMenu\n} from '@bridgerte/native-spec';\nimport { createFloatingLayer, type RichTextFloatingLayer } from '../floatingLayer';\nimport { bindTouchPressedState } from '../interactionState';\nimport {\n getPayloadPanelCurrentValues,\n resolveMenuSchemaForDom\n} from '../menuRuntime';\nimport {\n focusToolbarGroupMenuItem,\n handleToolbarGroupMenuKeyDown\n} from './groupMenuKeyboard';\nimport { createToolbarGroupMenuInteraction } from './groupMenuInteraction';\nimport {\n findToolbarGroupMenuItem,\n renderToolbar,\n renderToolbarGroupMenu,\n syncToolbarGroupButtonState,\n toolbarExecutableButtonSelector,\n toolbarGroupButtonSelector\n} from './render';\nimport type {\n RichTextToolbarAPI,\n ToolbarGroupMenuState,\n RichTextToolbarOptions\n} from './type';\n\nconst toolbarTooltipOffsetPx = 8;\nconst toolbarGroupMenuOffsetPx = 6;\n\nexport type * from './type';\n\nconst canUseHoverTooltip = () => (\n typeof window !== 'undefined'\n && window.matchMedia?.('(hover: hover) and (pointer: fine)').matches === true\n);\n\nconst getToolbarButtonFromTarget = (target: EventTarget | null) => {\n /*\n * 图标覆盖常用 SVG,H5 pointer 事件可能落在 svg/path 上。\n * 这里用 Element 而不是 HTMLElement,保证触屏兜底和 click 都能向上命中真实按钮。\n */\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarExecutableButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\nconst getToolbarGroupButtonFromTarget = (target: EventTarget | null) => {\n const button = target instanceof Element\n ? target.closest<HTMLButtonElement>(toolbarGroupButtonSelector)\n : null;\n\n return button instanceof HTMLButtonElement ? button : null;\n};\n\n/**\n * 创建独立菜单实例。\n *\n * toolbar/tabbar 只订阅 EditorAPI 状态并派发命令,不接触编辑器内部 DOM 或 Lexical 实例。\n */\nexport function createRichTextToolbar(\n container: HTMLElement,\n options: RichTextToolbarOptions\n): RichTextToolbarAPI {\n const placement = options.placement ?? 'top';\n const menuSchema = resolveMenuSchemaForDom(options.menuSchema ?? defaultMenuSchema, {\n menuLabels: options.menuLabels,\n payloadPanelConfig: options.payloadPanelConfig\n });\n const toolbarItems = resolveToolbarMenu(options.toolbarConfig, menuSchema);\n /*\n * click 事件只需要能执行命令的菜单项。分割线和 group 容器是渲染结构,\n * 先在这里摊平,后续点击时就不用理解 toolbarConfig 的展示层级。\n */\n const executableMenuItems = toolbarItems.flatMap((toolbarItem) => (\n toolbarItem.type === 'button' ? [toolbarItem.item]\n : toolbarItem.type === 'group' ? toolbarItem.items\n : []\n ));\n const icons = options.icons ?? {};\n /*\n * tooltip 只属于 PC 精细指针体验。H5 上即使没有原生 title,部分浏览器也会把 hover/mouseover\n * 模拟成首触摸状态,导致第一次点像是只唤醒提示;所以触屏端不写 tooltip 数据也不挂监听。\n */\n const enableTooltip = canUseHoverTooltip();\n const tooltipElement = document.createElement('div');\n const groupMenuElement = document.createElement('div');\n const overlayHost = container.closest('.bridgerte') ?? container;\n let destroyed = false;\n let latestCommandStates = options.editor.getCommandStates();\n let groupMenuState: ToolbarGroupMenuState | null = null;\n let groupMenuFloatingLayer: RichTextFloatingLayer | null = null;\n const clearToolbarPressedState = bindTouchPressedState(container, {\n targetSelector: [\n 'button[data-bridgerte-toolbar-item-id]',\n 'button[data-bridgerte-toolbar-group-id]'\n ].join(',')\n });\n const clearGroupMenuPressedState = bindTouchPressedState(groupMenuElement, {\n targetSelector: '.bridgerte__toolbar-group-menu-item'\n });\n\n const mountToolbarOverlays = () => {\n // 独立 toolbar 可能不在 `.bridgerte` 内,渲染按钮会清空 container,需要把浮层重新挂回去。\n overlayHost.append(tooltipElement);\n overlayHost.append(groupMenuElement);\n };\n\n const closeGroupMenuFloatingLayer = () => {\n groupMenuFloatingLayer?.setOpen(false);\n groupMenuFloatingLayer?.destroy();\n groupMenuFloatingLayer = null;\n };\n\n const openGroupMenuFloatingLayer = () => {\n if (!groupMenuState) return;\n\n closeGroupMenuFloatingLayer();\n /*\n * group menu 和 hoverbar/mention/slash 一样属于轻浮层,必须走 floatingLayer。\n * 这里按 toolbar placement 给出首选方向,真正的翻转、键盘可视区和左右夹紧交给\n * createFloatingLayer 内部的 visualViewport + flip + shift + clamp 统一处理。\n */\n groupMenuFloatingLayer = createFloatingLayer(groupMenuState.button, groupMenuElement, {\n placement: placement === 'bottom' ? 'top-start' : 'bottom-start',\n offset: toolbarGroupMenuOffsetPx,\n strategy: 'fixed'\n });\n groupMenuFloatingLayer.setOpen(true);\n };\n\n const closeGroupMenu = () => {\n if (!groupMenuState && !groupMenuFloatingLayer) return;\n\n closeGroupMenuFloatingLayer();\n groupMenuState = null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n };\n\n const renderStates = (states: CommandState[]) => {\n if (destroyed) return;\n\n latestCommandStates = states;\n if (groupMenuState) closeGroupMenuFloatingLayer();\n renderToolbar(container, toolbarItems, states, icons, enableTooltip);\n mountToolbarOverlays();\n if (groupMenuState) {\n const nextButton = Array.from(\n container.querySelectorAll<HTMLButtonElement>(toolbarGroupButtonSelector)\n ).find((button) => button.dataset.bridgerteToolbarGroupId === groupMenuState?.groupKey);\n const nextGroupItem = findToolbarGroupMenuItem(toolbarItems, groupMenuState.groupKey);\n\n groupMenuState = nextButton && nextGroupItem\n ? {\n groupKey: groupMenuState.groupKey,\n button: nextButton,\n items: nextGroupItem.items\n }\n : null;\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n if (groupMenuState) openGroupMenuFloatingLayer();\n }\n };\n\n const update = () => {\n if (destroyed) return;\n\n renderStates(options.editor.getCommandStates());\n };\n\n const hideTooltip = () => {\n tooltipElement.dataset.visible = 'false';\n tooltipElement.textContent = '';\n };\n\n const showTooltip = (button: HTMLButtonElement) => {\n const tooltipText = button.dataset.tooltip;\n\n if (!enableTooltip || !tooltipText) return;\n\n const buttonRect = button.getBoundingClientRect();\n\n tooltipElement.textContent = tooltipText;\n tooltipElement.dataset.visible = 'true';\n tooltipElement.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n tooltipElement.style.top = `${buttonRect.top - toolbarTooltipOffsetPx}px`;\n };\n\n const handleTooltipTarget = (event: Event) => {\n const button = getToolbarButtonFromTarget(event.target);\n\n if (button) {\n showTooltip(button);\n }\n };\n\n const handleTooltipLeave = (event: MouseEvent) => {\n const relatedTarget = event.relatedTarget;\n const button = getToolbarButtonFromTarget(event.target);\n\n if (\n button\n && relatedTarget instanceof Node\n && button.contains(relatedTarget)\n ) return;\n\n hideTooltip();\n };\n\n const executeToolbarButton = (button: HTMLButtonElement) => {\n if (!(button instanceof HTMLButtonElement) || button.disabled) return;\n\n const menuItem = executableMenuItems.find((item) => (\n item.id === button.dataset.bridgerteToolbarItemId\n ));\n\n if (!menuItem) return;\n\n if (menuItem.payloadPanel) {\n const buttonRect = button.getBoundingClientRect();\n\n /*\n * 带 payloadPanel 的菜单不直接执行基础 command,而是发起参数请求。\n * DOM 内置面板和业务/RN/Flutter 自绘都走同一个 request,避免后续颜色、\n * 字体、链接等参数菜单各自发明一套协议。\n */\n options.editor.requestPayloadPanel({\n menuId: menuItem.id,\n command: menuItem.command,\n panel: menuItem.payloadPanel,\n currentValues: getPayloadPanelCurrentValues(menuItem, options.editor.getCommandStates()),\n anchorRect: {\n x: buttonRect.left,\n y: buttonRect.top,\n width: buttonRect.width,\n height: buttonRect.height\n }\n });\n return;\n }\n\n options.editor.executeCommand(menuItem.command);\n };\n\n const toggleGroupMenu = (button: HTMLButtonElement, shouldFocusMenu = false) => {\n const groupItem = findToolbarGroupMenuItem(\n toolbarItems,\n button.dataset.bridgerteToolbarGroupId\n );\n\n if (!groupItem || button.disabled) return;\n\n if (groupMenuState?.groupKey === groupItem.key) {\n if (shouldFocusMenu) {\n focusToolbarGroupMenuItem(groupMenuElement, 0);\n return;\n }\n closeGroupMenu();\n return;\n }\n\n groupMenuState = {\n groupKey: groupItem.key,\n button,\n items: groupItem.items\n };\n hideTooltip();\n renderToolbarGroupMenu(groupMenuElement, groupMenuState, latestCommandStates, icons);\n syncToolbarGroupButtonState(container, groupMenuState);\n openGroupMenuFloatingLayer();\n if (shouldFocusMenu) focusToolbarGroupMenuItem(groupMenuElement, 0);\n };\n\n const handleClick = (event: MouseEvent) => {\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (groupButton) {\n event.preventDefault();\n event.stopPropagation();\n if (groupMenuInteraction.consumeSuppressedClick(groupButton)) return;\n\n toggleGroupMenu(groupButton);\n return;\n }\n\n const button = getToolbarButtonFromTarget(event.target);\n if (!button) return;\n\n event.preventDefault();\n event.stopPropagation();\n if (groupMenuInteraction.consumeSuppressedClick(button)) return;\n\n executeToolbarButton(button);\n closeGroupMenu();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (groupMenuState && groupMenuElement.contains(document.activeElement)) {\n handleToolbarGroupMenuKeyDown(\n event,\n groupMenuElement,\n groupMenuState.button,\n executeToolbarButton,\n closeGroupMenu\n );\n return;\n }\n\n const groupButton = getToolbarGroupButtonFromTarget(event.target);\n if (\n groupButton\n && (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown')\n ) {\n /*\n * 指针点击收纳菜单不能抢编辑器焦点;键盘从入口按钮打开时则进入菜单项,\n * 保留 PC 可访问性和方向键 roving focus。\n */\n event.preventDefault();\n event.stopPropagation();\n toggleGroupMenu(groupButton, true);\n return;\n }\n\n if (event.key !== 'Escape') return;\n\n closeGroupMenu();\n };\n\n container.classList.add('bridgerte__toolbar');\n tooltipElement.className = 'bridgerte__toolbar-tooltip';\n tooltipElement.dataset.visible = 'false';\n groupMenuElement.className = 'bridgerte__floating-menu bridgerte__toolbar-group-menu';\n groupMenuElement.dataset.visible = 'false';\n groupMenuElement.setAttribute('role', 'menu');\n container.dataset.placement = placement;\n container.setAttribute('role', 'toolbar');\n container.setAttribute(\n 'aria-label',\n placement === 'bottom' ? 'BridgeRTE tabbar' : 'BridgeRTE toolbar'\n );\n container.addEventListener('click', handleClick);\n groupMenuElement.addEventListener('click', handleClick);\n document.addEventListener('keydown', handleKeyDown);\n if (enableTooltip) {\n container.addEventListener('mouseover', handleTooltipTarget);\n container.addEventListener('mouseout', handleTooltipLeave);\n }\n container.addEventListener('focusout', hideTooltip);\n // 浮层挂在最近的编辑器根容器下,既能继承变量,也不会操作编辑内容 DOM。\n mountToolbarOverlays();\n const groupMenuInteraction = createToolbarGroupMenuInteraction(\n container,\n groupMenuElement,\n toggleGroupMenu,\n executeToolbarButton,\n closeGroupMenu\n );\n\n // 独立 toolbar 只订阅 public API 状态,不依赖 DOM 编辑器内部实现。\n const unsubscribe = options.editor.subscribeCommandStateChange(renderStates);\n\n return {\n update,\n destroy() {\n if (destroyed) return;\n\n destroyed = true;\n unsubscribe();\n closeGroupMenu();\n container.removeEventListener('click', handleClick);\n groupMenuElement.removeEventListener('click', handleClick);\n document.removeEventListener('keydown', handleKeyDown);\n groupMenuInteraction.destroy();\n if (enableTooltip) {\n container.removeEventListener('mouseover', handleTooltipTarget);\n container.removeEventListener('mouseout', handleTooltipLeave);\n }\n clearToolbarPressedState();\n clearGroupMenuPressedState();\n container.removeEventListener('focusout', hideTooltip);\n tooltipElement.remove();\n groupMenuElement.remove();\n container.classList.remove('bridgerte__toolbar');\n delete container.dataset.placement;\n container.textContent = '';\n container.removeAttribute('role');\n container.removeAttribute('aria-label');\n }\n };\n}\n","const invisibleTextPattern = /[\\u200B-\\u200D\\uFEFF]/g;\n\n/*\n * HTML 片段里这些元素没有 textContent 也应算有效内容。\n * 纯排版容器不放进来,避免 `<p><br></p>`、空列表项这类编辑器占位被误判为非空。\n */\nconst meaningfulHtmlContentSelector = [\n 'img',\n 'video',\n 'audio',\n 'iframe',\n 'table',\n 'pre',\n 'code',\n 'hr',\n 'figure',\n 'canvas',\n 'svg',\n 'math',\n '[data-type=\"mention\"]'\n].join(',');\n\nconst normalizeHtmlText = (text: string | null | undefined): string => (\n text?.replace(invisibleTextPattern, '').trim() ?? ''\n);\n\n/**\n * 判断一段 HTML 片段是否包含可保存的富文本内容。\n *\n * 这个工具会使用浏览器 template 解析 HTML,适合只拿到 HTML 字符串的业务表单;如果已经持有\n * `EditorContent`,优先使用 core 的 `isEditorContentEmpty()`,避免额外 DOM parse。\n */\nexport const hasMeaningfulHtmlContent = (html: string): boolean => {\n if (!normalizeHtmlText(html)) return false;\n\n const template = document.createElement('template');\n\n template.innerHTML = html;\n\n return Boolean(\n normalizeHtmlText(template.content.textContent)\n || template.content.querySelector(meaningfulHtmlContentSelector)\n );\n};\n"],"names":["defaultMenuUiIcons","getEnabledGroupMenuButtons","menuElement","button","focusToolbarGroupMenuItem","index","nextButton","handleToolbarGroupMenuKeyDown","event","returnButton","executeToolbarButton","closeGroupMenu","buttons","activeIndex","focusByOffset","offset","nextIndex","_a","_b","toolbarGroupButtonSelector","toolbarButtonSelector","toolbarExecutableButtonSelector","getGroupMenuState","items","commandStates","itemStates","item","getMenuStateForItem","state","renderToolbarButton","groupElement","icons","enableTooltip","iconSvg","defaultMenuIcons","appendMenuIcon","renderToolbarGroupButton","toolbarItem","groupState","indicator","renderToolbar","toolbarElement","toolbarItems","separatorElement","renderToolbarGroupMenu","groupMenuState","labelElement","syncToolbarGroupButtonState","container","open","findToolbarGroupMenuItem","groupKey","toolbarGroupTouchMoveTolerancePx","isInsideNode","target","getClosestButton","selector","createToolbarGroupMenuInteraction","groupMenuElement","toggleGroupMenu","pendingTouch","suppressNextClickButton","getInteractiveButtonFromTarget","handlePressStart","handleTouchStart","touch","groupButton","menuItemButton","clearPendingTouch","handleTouchEnd","touchState","endButton","deltaX","deltaY","handleDocumentPointerDown","toolbarTooltipOffsetPx","toolbarGroupMenuOffsetPx","canUseHoverTooltip","getToolbarButtonFromTarget","getToolbarGroupButtonFromTarget","createRichTextToolbar","options","placement","menuSchema","resolveMenuSchemaForDom","defaultMenuSchema","resolveToolbarMenu","executableMenuItems","tooltipElement","overlayHost","destroyed","latestCommandStates","groupMenuFloatingLayer","clearToolbarPressedState","bindTouchPressedState","clearGroupMenuPressedState","mountToolbarOverlays","closeGroupMenuFloatingLayer","openGroupMenuFloatingLayer","createFloatingLayer","renderStates","states","nextGroupItem","update","hideTooltip","showTooltip","tooltipText","buttonRect","handleTooltipTarget","handleTooltipLeave","relatedTarget","menuItem","getPayloadPanelCurrentValues","shouldFocusMenu","groupItem","handleClick","groupMenuInteraction","handleKeyDown","unsubscribe","invisibleTextPattern","meaningfulHtmlContentSelector","normalizeHtmlText","text","hasMeaningfulHtmlContent","html","template"],"mappings":"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"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { defaultMenuSchema as et, resolveToolbarMenu as ot } from "./native-spec.js";
|
|
2
|
+
import { g as H, d as N, e as K, r as nt, f as q, h as rt, c as at } from "./index-9gETEdDG.js";
|
|
3
|
+
const X = {
|
|
4
|
+
toolbarGroup: `
|
|
5
|
+
<svg
|
|
6
|
+
aria-hidden="true"
|
|
7
|
+
class="lucide lucide-ellipsis"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
width="18"
|
|
10
|
+
height="18"
|
|
11
|
+
viewBox="0 0 24 24"
|
|
12
|
+
fill="none"
|
|
13
|
+
stroke="currentColor"
|
|
14
|
+
stroke-width="2"
|
|
15
|
+
stroke-linecap="round"
|
|
16
|
+
stroke-linejoin="round"
|
|
17
|
+
>
|
|
18
|
+
<circle cx="12" cy="12" r="1" />
|
|
19
|
+
<circle cx="19" cy="12" r="1" />
|
|
20
|
+
<circle cx="5" cy="12" r="1" />
|
|
21
|
+
</svg>
|
|
22
|
+
`,
|
|
23
|
+
chevronDown: `
|
|
24
|
+
<svg
|
|
25
|
+
aria-hidden="true"
|
|
26
|
+
class="lucide lucide-chevron-down"
|
|
27
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
28
|
+
width="12"
|
|
29
|
+
height="12"
|
|
30
|
+
viewBox="0 0 24 24"
|
|
31
|
+
fill="none"
|
|
32
|
+
stroke="currentColor"
|
|
33
|
+
stroke-width="2"
|
|
34
|
+
stroke-linecap="round"
|
|
35
|
+
stroke-linejoin="round"
|
|
36
|
+
>
|
|
37
|
+
<path d="m6 9 6 6 6-6" />
|
|
38
|
+
</svg>
|
|
39
|
+
`
|
|
40
|
+
}, z = (t) => Array.from(
|
|
41
|
+
t.querySelectorAll(".bridgerte__toolbar-group-menu-item")
|
|
42
|
+
).filter((e) => !e.disabled), Y = (t, e) => {
|
|
43
|
+
const c = z(t)[e];
|
|
44
|
+
c && c.focus();
|
|
45
|
+
}, st = (t, e, i, c, d) => {
|
|
46
|
+
var s, u;
|
|
47
|
+
const n = z(e), r = document.activeElement instanceof HTMLButtonElement ? n.indexOf(document.activeElement) : -1, m = (g) => {
|
|
48
|
+
var o;
|
|
49
|
+
if (n.length === 0) return;
|
|
50
|
+
const v = ((r >= 0 ? r : 0) + g + n.length) % n.length;
|
|
51
|
+
(o = n[v]) == null || o.focus();
|
|
52
|
+
};
|
|
53
|
+
switch (t.key) {
|
|
54
|
+
case "ArrowDown":
|
|
55
|
+
t.preventDefault(), m(1);
|
|
56
|
+
break;
|
|
57
|
+
case "ArrowUp":
|
|
58
|
+
t.preventDefault(), m(-1);
|
|
59
|
+
break;
|
|
60
|
+
case "Home":
|
|
61
|
+
t.preventDefault(), (s = n[0]) == null || s.focus();
|
|
62
|
+
break;
|
|
63
|
+
case "End":
|
|
64
|
+
t.preventDefault(), (u = n.at(-1)) == null || u.focus();
|
|
65
|
+
break;
|
|
66
|
+
case "Enter":
|
|
67
|
+
case " ":
|
|
68
|
+
document.activeElement instanceof HTMLButtonElement && (t.preventDefault(), c(document.activeElement), d(), i.focus());
|
|
69
|
+
break;
|
|
70
|
+
case "Escape":
|
|
71
|
+
t.preventDefault(), i.focus(), d();
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}, L = "button[data-bridgerte-toolbar-group-id]", it = "button[data-bridgerte-toolbar-item-id]", I = [
|
|
75
|
+
it,
|
|
76
|
+
".bridgerte__toolbar-group-menu-item"
|
|
77
|
+
].join(","), lt = (t, e) => {
|
|
78
|
+
const i = t.map((c) => H(c, e));
|
|
79
|
+
return {
|
|
80
|
+
active: i.some((c) => c.active),
|
|
81
|
+
disabled: i.length > 0 && i.every((c) => c.disabled)
|
|
82
|
+
};
|
|
83
|
+
}, ct = (t, e, i, c, d) => {
|
|
84
|
+
const n = H(e, i), r = document.createElement("button"), m = c[e.icon] ?? N[e.icon];
|
|
85
|
+
r.type = "button", r.className = "bridgerte__toolbar-button", r.disabled = n.disabled, r.dataset.active = String(n.active), r.dataset.bridgerteToolbarItemId = e.id, r.setAttribute("aria-label", e.label), r.setAttribute("aria-pressed", String(n.active)), d && (r.dataset.tooltip = e.label), K(r, m, e.label), t.append(r);
|
|
86
|
+
}, dt = (t, e, i, c, d) => {
|
|
87
|
+
const n = document.createElement("button"), r = lt(e.items, i), m = e.icon ? c[e.icon] ?? N[e.icon] : X.toolbarGroup, s = document.createElement("span");
|
|
88
|
+
n.type = "button", n.className = "bridgerte__toolbar-button bridgerte__toolbar-group-button", n.disabled = r.disabled, n.dataset.active = String(r.active), n.dataset.bridgerteToolbarGroupId = e.key, n.dataset.open = "false", n.setAttribute("aria-label", e.title), n.setAttribute("aria-haspopup", "menu"), n.setAttribute("aria-expanded", "false"), n.setAttribute("aria-pressed", String(r.active)), d && (n.dataset.tooltip = e.title), K(n, m, e.title), s.className = "bridgerte__toolbar-group-indicator", s.setAttribute("aria-hidden", "true"), s.innerHTML = X.chevronDown, n.append(s), t.append(n);
|
|
89
|
+
}, ut = (t, e, i, c, d) => {
|
|
90
|
+
t.textContent = "", e.forEach((n) => {
|
|
91
|
+
if (n.type === "separator") {
|
|
92
|
+
const m = document.createElement("span");
|
|
93
|
+
m.className = "bridgerte__toolbar-separator", m.dataset.separatorId = n.key, m.setAttribute("aria-hidden", "true"), t.append(m);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (n.type === "button") {
|
|
97
|
+
ct(
|
|
98
|
+
t,
|
|
99
|
+
n.item,
|
|
100
|
+
i,
|
|
101
|
+
c,
|
|
102
|
+
d
|
|
103
|
+
);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const r = document.createElement("div");
|
|
107
|
+
r.className = "bridgerte__toolbar-group", r.dataset.group = n.key, r.setAttribute("aria-label", n.title), t.append(r), dt(
|
|
108
|
+
r,
|
|
109
|
+
n,
|
|
110
|
+
i,
|
|
111
|
+
c,
|
|
112
|
+
d
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
}, G = (t, e, i, c) => {
|
|
116
|
+
if (t.textContent = "", !e) {
|
|
117
|
+
t.dataset.visible = "false";
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
e.items.forEach((d) => {
|
|
121
|
+
const n = H(d, i), r = document.createElement("button"), m = c[d.icon] ?? N[d.icon], s = document.createElement("span");
|
|
122
|
+
r.type = "button", r.className = "bridgerte__menu-item bridgerte__toolbar-group-menu-item", r.disabled = n.disabled, r.dataset.active = String(n.active), r.dataset.bridgerteToolbarItemId = d.id, r.setAttribute("role", "menuitem"), r.setAttribute("aria-label", d.label), r.setAttribute("aria-pressed", String(n.active)), K(r, m, d.label), s.className = "bridgerte__toolbar-group-menu-label", s.textContent = d.label, r.append(s), t.append(r);
|
|
123
|
+
}), t.dataset.visible = "true", t.style.minWidth = `${e.button.offsetWidth}px`;
|
|
124
|
+
}, D = (t, e) => {
|
|
125
|
+
t.querySelectorAll(L).forEach((i) => {
|
|
126
|
+
const c = (e == null ? void 0 : e.groupKey) === i.dataset.bridgerteToolbarGroupId;
|
|
127
|
+
i.dataset.open = String(c), i.setAttribute("aria-expanded", String(c));
|
|
128
|
+
});
|
|
129
|
+
}, U = (t, e) => t.find((i) => i.type === "group" && i.key === e), $ = 8, S = (t, e) => e instanceof Node && t.contains(e), _ = (t, e) => t instanceof Element ? t.closest(e) : null, bt = (t, e, i, c, d) => {
|
|
130
|
+
let n = null, r = null;
|
|
131
|
+
const m = (o) => _(o, L) ?? (S(e, o) ? _(o, I) : null), s = (o) => {
|
|
132
|
+
m(o.target) && o.preventDefault();
|
|
133
|
+
}, u = (o) => {
|
|
134
|
+
const p = o.touches[0], h = _(o.target, L), T = S(e, o.target) ? _(o.target, I) : null, y = h ?? T;
|
|
135
|
+
!y || !p || (o.preventDefault(), n = {
|
|
136
|
+
button: y,
|
|
137
|
+
kind: h ? "group" : "menu-item",
|
|
138
|
+
startX: p.clientX,
|
|
139
|
+
startY: p.clientY
|
|
140
|
+
});
|
|
141
|
+
}, g = () => {
|
|
142
|
+
n = null;
|
|
143
|
+
}, f = (o) => {
|
|
144
|
+
if (!n) return;
|
|
145
|
+
const p = n, h = o.changedTouches[0], T = m(o.target);
|
|
146
|
+
if (n = null, !h || T !== p.button) return;
|
|
147
|
+
const y = Math.abs(h.clientX - p.startX), w = Math.abs(h.clientY - p.startY);
|
|
148
|
+
if (!(y > $ || w > $)) {
|
|
149
|
+
if (o.preventDefault(), o.stopPropagation(), r = p.button, p.kind === "group") {
|
|
150
|
+
i(p.button);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
c(p.button), d();
|
|
154
|
+
}
|
|
155
|
+
}, v = (o) => {
|
|
156
|
+
S(t, o.target) || S(e, o.target) || d();
|
|
157
|
+
};
|
|
158
|
+
return t.addEventListener("pointerdown", s), t.addEventListener("mousedown", s), t.addEventListener("touchstart", u, { passive: !1 }), t.addEventListener("touchend", f), t.addEventListener("touchcancel", g), e.addEventListener("pointerdown", s), e.addEventListener("mousedown", s), e.addEventListener("touchstart", u, { passive: !1 }), e.addEventListener("touchend", f), e.addEventListener("touchcancel", g), document.addEventListener("pointerdown", v, !0), {
|
|
159
|
+
consumeSuppressedClick(o) {
|
|
160
|
+
return r !== o ? !1 : (r = null, !0);
|
|
161
|
+
},
|
|
162
|
+
destroy() {
|
|
163
|
+
t.removeEventListener("pointerdown", s), t.removeEventListener("mousedown", s), t.removeEventListener("touchstart", u), t.removeEventListener("touchend", f), t.removeEventListener("touchcancel", g), e.removeEventListener("pointerdown", s), e.removeEventListener("mousedown", s), e.removeEventListener("touchstart", u), e.removeEventListener("touchend", f), e.removeEventListener("touchcancel", g), document.removeEventListener("pointerdown", v, !0);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}, pt = 8, mt = 6, ft = () => {
|
|
167
|
+
var t;
|
|
168
|
+
return typeof window < "u" && ((t = window.matchMedia) == null ? void 0 : t.call(window, "(hover: hover) and (pointer: fine)").matches) === !0;
|
|
169
|
+
}, P = (t) => {
|
|
170
|
+
const e = t instanceof Element ? t.closest(I) : null;
|
|
171
|
+
return e instanceof HTMLButtonElement ? e : null;
|
|
172
|
+
}, V = (t) => {
|
|
173
|
+
const e = t instanceof Element ? t.closest(L) : null;
|
|
174
|
+
return e instanceof HTMLButtonElement ? e : null;
|
|
175
|
+
};
|
|
176
|
+
function Et(t, e) {
|
|
177
|
+
const i = e.placement ?? "top", c = nt(e.menuSchema ?? et, {
|
|
178
|
+
menuLabels: e.menuLabels,
|
|
179
|
+
payloadPanelConfig: e.payloadPanelConfig
|
|
180
|
+
}), d = ot(e.toolbarConfig, c), n = d.flatMap((a) => a.type === "button" ? [a.item] : a.type === "group" ? a.items : []), r = e.icons ?? {}, m = ft(), s = document.createElement("div"), u = document.createElement("div"), g = t.closest(".bridgerte") ?? t;
|
|
181
|
+
let f = !1, v = e.editor.getCommandStates(), o = null, p = null;
|
|
182
|
+
const h = q(t, {
|
|
183
|
+
targetSelector: [
|
|
184
|
+
"button[data-bridgerte-toolbar-item-id]",
|
|
185
|
+
"button[data-bridgerte-toolbar-group-id]"
|
|
186
|
+
].join(",")
|
|
187
|
+
}), T = q(u, {
|
|
188
|
+
targetSelector: ".bridgerte__toolbar-group-menu-item"
|
|
189
|
+
}), y = () => {
|
|
190
|
+
g.append(s), g.append(u);
|
|
191
|
+
}, w = () => {
|
|
192
|
+
p == null || p.setOpen(!1), p == null || p.destroy(), p = null;
|
|
193
|
+
}, M = () => {
|
|
194
|
+
o && (w(), p = at(o.button, u, {
|
|
195
|
+
placement: i === "bottom" ? "top-start" : "bottom-start",
|
|
196
|
+
offset: mt,
|
|
197
|
+
strategy: "fixed"
|
|
198
|
+
}), p.setOpen(!0));
|
|
199
|
+
}, E = () => {
|
|
200
|
+
!o && !p || (w(), o = null, G(u, o, v, r), D(t, o));
|
|
201
|
+
}, R = (a) => {
|
|
202
|
+
if (!f && (v = a, o && w(), ut(t, d, a, r, m), y(), o)) {
|
|
203
|
+
const l = Array.from(
|
|
204
|
+
t.querySelectorAll(L)
|
|
205
|
+
).find((tt) => tt.dataset.bridgerteToolbarGroupId === (o == null ? void 0 : o.groupKey)), b = U(d, o.groupKey);
|
|
206
|
+
o = l && b ? {
|
|
207
|
+
groupKey: o.groupKey,
|
|
208
|
+
button: l,
|
|
209
|
+
items: b.items
|
|
210
|
+
} : null, G(u, o, v, r), D(t, o), o && M();
|
|
211
|
+
}
|
|
212
|
+
}, J = () => {
|
|
213
|
+
f || R(e.editor.getCommandStates());
|
|
214
|
+
}, x = () => {
|
|
215
|
+
s.dataset.visible = "false", s.textContent = "";
|
|
216
|
+
}, Q = (a) => {
|
|
217
|
+
const l = a.dataset.tooltip;
|
|
218
|
+
if (!m || !l) return;
|
|
219
|
+
const b = a.getBoundingClientRect();
|
|
220
|
+
s.textContent = l, s.dataset.visible = "true", s.style.left = `${b.left + b.width / 2}px`, s.style.top = `${b.top - pt}px`;
|
|
221
|
+
}, F = (a) => {
|
|
222
|
+
const l = P(a.target);
|
|
223
|
+
l && Q(l);
|
|
224
|
+
}, O = (a) => {
|
|
225
|
+
const l = a.relatedTarget, b = P(a.target);
|
|
226
|
+
b && l instanceof Node && b.contains(l) || x();
|
|
227
|
+
}, B = (a) => {
|
|
228
|
+
if (!(a instanceof HTMLButtonElement) || a.disabled) return;
|
|
229
|
+
const l = n.find((b) => b.id === a.dataset.bridgerteToolbarItemId);
|
|
230
|
+
if (l) {
|
|
231
|
+
if (l.payloadPanel) {
|
|
232
|
+
const b = a.getBoundingClientRect();
|
|
233
|
+
e.editor.requestPayloadPanel({
|
|
234
|
+
menuId: l.id,
|
|
235
|
+
command: l.command,
|
|
236
|
+
panel: l.payloadPanel,
|
|
237
|
+
currentValues: rt(l, e.editor.getCommandStates()),
|
|
238
|
+
anchorRect: {
|
|
239
|
+
x: b.left,
|
|
240
|
+
y: b.top,
|
|
241
|
+
width: b.width,
|
|
242
|
+
height: b.height
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
e.editor.executeCommand(l.command);
|
|
248
|
+
}
|
|
249
|
+
}, C = (a, l = !1) => {
|
|
250
|
+
const b = U(
|
|
251
|
+
d,
|
|
252
|
+
a.dataset.bridgerteToolbarGroupId
|
|
253
|
+
);
|
|
254
|
+
if (!(!b || a.disabled)) {
|
|
255
|
+
if ((o == null ? void 0 : o.groupKey) === b.key) {
|
|
256
|
+
if (l) {
|
|
257
|
+
Y(u, 0);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
E();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
o = {
|
|
264
|
+
groupKey: b.key,
|
|
265
|
+
button: a,
|
|
266
|
+
items: b.items
|
|
267
|
+
}, x(), G(u, o, v, r), D(t, o), M(), l && Y(u, 0);
|
|
268
|
+
}
|
|
269
|
+
}, k = (a) => {
|
|
270
|
+
const l = V(a.target);
|
|
271
|
+
if (l) {
|
|
272
|
+
if (a.preventDefault(), a.stopPropagation(), A.consumeSuppressedClick(l)) return;
|
|
273
|
+
C(l);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const b = P(a.target);
|
|
277
|
+
b && (a.preventDefault(), a.stopPropagation(), !A.consumeSuppressedClick(b) && (B(b), E()));
|
|
278
|
+
}, j = (a) => {
|
|
279
|
+
if (o && u.contains(document.activeElement)) {
|
|
280
|
+
st(
|
|
281
|
+
a,
|
|
282
|
+
u,
|
|
283
|
+
o.button,
|
|
284
|
+
B,
|
|
285
|
+
E
|
|
286
|
+
);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const l = V(a.target);
|
|
290
|
+
if (l && (a.key === "Enter" || a.key === " " || a.key === "ArrowDown")) {
|
|
291
|
+
a.preventDefault(), a.stopPropagation(), C(l, !0);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
a.key === "Escape" && E();
|
|
295
|
+
};
|
|
296
|
+
t.classList.add("bridgerte__toolbar"), s.className = "bridgerte__toolbar-tooltip", s.dataset.visible = "false", u.className = "bridgerte__floating-menu bridgerte__toolbar-group-menu", u.dataset.visible = "false", u.setAttribute("role", "menu"), t.dataset.placement = i, t.setAttribute("role", "toolbar"), t.setAttribute(
|
|
297
|
+
"aria-label",
|
|
298
|
+
i === "bottom" ? "BridgeRTE tabbar" : "BridgeRTE toolbar"
|
|
299
|
+
), t.addEventListener("click", k), u.addEventListener("click", k), document.addEventListener("keydown", j), m && (t.addEventListener("mouseover", F), t.addEventListener("mouseout", O)), t.addEventListener("focusout", x), y();
|
|
300
|
+
const A = bt(
|
|
301
|
+
t,
|
|
302
|
+
u,
|
|
303
|
+
C,
|
|
304
|
+
B,
|
|
305
|
+
E
|
|
306
|
+
), Z = e.editor.subscribeCommandStateChange(R);
|
|
307
|
+
return {
|
|
308
|
+
update: J,
|
|
309
|
+
destroy() {
|
|
310
|
+
f || (f = !0, Z(), E(), t.removeEventListener("click", k), u.removeEventListener("click", k), document.removeEventListener("keydown", j), A.destroy(), m && (t.removeEventListener("mouseover", F), t.removeEventListener("mouseout", O)), h(), T(), t.removeEventListener("focusout", x), s.remove(), u.remove(), t.classList.remove("bridgerte__toolbar"), delete t.dataset.placement, t.textContent = "", t.removeAttribute("role"), t.removeAttribute("aria-label"));
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
const gt = /[\u200B-\u200D\uFEFF]/g, vt = [
|
|
315
|
+
"img",
|
|
316
|
+
"video",
|
|
317
|
+
"audio",
|
|
318
|
+
"iframe",
|
|
319
|
+
"table",
|
|
320
|
+
"pre",
|
|
321
|
+
"code",
|
|
322
|
+
"hr",
|
|
323
|
+
"figure",
|
|
324
|
+
"canvas",
|
|
325
|
+
"svg",
|
|
326
|
+
"math",
|
|
327
|
+
'[data-type="mention"]'
|
|
328
|
+
].join(","), W = (t) => (t == null ? void 0 : t.replace(gt, "").trim()) ?? "", Tt = (t) => {
|
|
329
|
+
if (!W(t)) return !1;
|
|
330
|
+
const e = document.createElement("template");
|
|
331
|
+
return e.innerHTML = t, !!(W(e.content.textContent) || e.content.querySelector(vt));
|
|
332
|
+
};
|
|
333
|
+
export {
|
|
334
|
+
Et as c,
|
|
335
|
+
Tt as h
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=index-KfoBS_v8.js.map
|