@inpageedit/core 0.15.0 → 0.16.0

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.
Files changed (100) hide show
  1. package/dist/{ActionButton-CRjo_l3y.js → ActionButton-B6OUgtHx.js} +2 -2
  2. package/dist/{ActionButton-CRjo_l3y.js.map → ActionButton-B6OUgtHx.js.map} +1 -1
  3. package/dist/CheckBox-Dx3r3LQz.js +13 -0
  4. package/dist/CheckBox-Dx3r3LQz.js.map +1 -0
  5. package/dist/IconQuickDiff-BkbxyY-d.js +29 -0
  6. package/dist/IconQuickDiff-BkbxyY-d.js.map +1 -0
  7. package/dist/IconQuickEdit-BiRYADU_.js +68 -0
  8. package/dist/IconQuickEdit-BiRYADU_.js.map +1 -0
  9. package/dist/IconUpload-Bz4BW_nc.js +27 -0
  10. package/dist/IconUpload-Bz4BW_nc.js.map +1 -0
  11. package/dist/InPageEdit.js +20 -0
  12. package/dist/InPageEdit.js.map +1 -0
  13. package/dist/InputBox-D2ZRTMFP.js +42 -0
  14. package/dist/InputBox-D2ZRTMFP.js.map +1 -0
  15. package/dist/{PluginImagesUsed-Bq_C_rgg.js → PluginImagesUsed-BVyvFA1_.js} +7 -7
  16. package/dist/{PluginImagesUsed-Bq_C_rgg.js.map → PluginImagesUsed-BVyvFA1_.js.map} +1 -1
  17. package/dist/{PluginPrefSync-DP5NyPnI.js → PluginPrefSync-CUKkx4Qk.js} +10 -10
  18. package/dist/{PluginPrefSync-DP5NyPnI.js.map → PluginPrefSync-CUKkx4Qk.js.map} +1 -1
  19. package/dist/{PluginStoreApp-_YWpLgfs.js → PluginStoreApp-CoOAw1fr.js} +4 -4
  20. package/dist/{PluginStoreApp-_YWpLgfs.js.map → PluginStoreApp-CoOAw1fr.js.map} +1 -1
  21. package/dist/{PluginTemplatesUsed-DS_rHctR.js → PluginTemplatesUsed-CdjT1wR4.js} +12 -12
  22. package/dist/{PluginTemplatesUsed-DS_rHctR.js.map → PluginTemplatesUsed-CdjT1wR4.js.map} +1 -1
  23. package/dist/{index-CM_6yF2v.js → Promise.withResolvers-C4chhLB1.js} +17 -11
  24. package/dist/Promise.withResolvers-C4chhLB1.js.map +1 -0
  25. package/dist/{RadioBox-0UuxlcWZ.js → RadioBox-B0z9YHQg.js} +2 -2
  26. package/dist/{RadioBox-0UuxlcWZ.js.map → RadioBox-B0z9YHQg.js.map} +1 -1
  27. package/dist/components/index.js +75 -46
  28. package/dist/components/index.js.map +1 -1
  29. package/dist/{BasePlugin-BCVSn9QJ.js → core.js} +28 -10
  30. package/dist/core.js.map +1 -0
  31. package/dist/{index-n5KKWE9v.js → index-1tsXE6ax.js} +9 -8
  32. package/dist/{index-n5KKWE9v.js.map → index-1tsXE6ax.js.map} +1 -1
  33. package/dist/{index-CS1kidKF.js → index-B32tFyLB.js} +57 -57
  34. package/dist/{index-CS1kidKF.js.map → index-B32tFyLB.js.map} +1 -1
  35. package/dist/{index-Cq8xPcEY.js → index-BPTMltVf.js} +35 -35
  36. package/dist/index-BPTMltVf.js.map +1 -0
  37. package/dist/{index-rKL4D_7I.js → index-BYlcHc-O.js} +22 -24
  38. package/dist/index-BYlcHc-O.js.map +1 -0
  39. package/dist/{index-DjyjqpeO.js → index-C4qm_X_A.js} +11 -11
  40. package/dist/{index-DjyjqpeO.js.map → index-C4qm_X_A.js.map} +1 -1
  41. package/dist/index-CAtPo7xJ.js +793 -0
  42. package/dist/index-CAtPo7xJ.js.map +1 -0
  43. package/dist/{index-DPA1ptYq.js → index-CVCy0wPP.js} +8 -7
  44. package/dist/{index-DPA1ptYq.js.map → index-CVCy0wPP.js.map} +1 -1
  45. package/dist/index-CYfkwXRf.js +1631 -0
  46. package/dist/index-CYfkwXRf.js.map +1 -0
  47. package/dist/{index-mFwJhDwE.js → index-DZa9mxN4.js} +11 -11
  48. package/dist/{index-mFwJhDwE.js.map → index-DZa9mxN4.js.map} +1 -1
  49. package/dist/{index-B9VO3swL.js → index-Dm2vgYkZ.js} +58 -81
  50. package/dist/index-Dm2vgYkZ.js.map +1 -0
  51. package/dist/{index-C3t-Xj3e.js → index-NWWeW3tX.js} +10 -10
  52. package/dist/{index-C3t-Xj3e.js.map → index-NWWeW3tX.js.map} +1 -1
  53. package/dist/index-QnWieXQc.js +4932 -0
  54. package/dist/index-QnWieXQc.js.map +1 -0
  55. package/dist/{index-CbdkXGs7.js → index-bQ0CVu3l.js} +13 -17
  56. package/dist/{index-CbdkXGs7.js.map → index-bQ0CVu3l.js.map} +1 -1
  57. package/dist/{index-Cb2_vqBl.js → index-ygc4AMy4.js} +10 -10
  58. package/dist/{index-Cb2_vqBl.js.map → index-ygc4AMy4.js.map} +1 -1
  59. package/dist/{index-DD5CVCfD.js → index-z_qDGCMT.js} +2 -2
  60. package/dist/{index-DD5CVCfD.js.map → index-z_qDGCMT.js.map} +1 -1
  61. package/dist/index.d.ts +98 -36
  62. package/dist/index.js +24 -26
  63. package/dist/index.js.map +1 -1
  64. package/dist/{makeCallable-LDU0xZMJ.js → makeCallable-Cg4zUG4c.js} +2 -2
  65. package/dist/{makeCallable-LDU0xZMJ.js.map → makeCallable-Cg4zUG4c.js.map} +1 -1
  66. package/dist/models/index.js +7 -7
  67. package/dist/models/index.js.map +1 -1
  68. package/dist/plugins/index.js +12 -12
  69. package/dist/services/index.js +5 -4
  70. package/dist/style.css +1 -1
  71. package/dist/{vueHooks-l04s8cIl.js → vueHooks-Bs93iP61.js} +1519 -1492
  72. package/dist/vueHooks-Bs93iP61.js.map +1 -0
  73. package/lib/index.umd.js +19 -15
  74. package/lib/index.umd.js.map +1 -1
  75. package/lib/style.css +1 -1
  76. package/package.json +36 -27
  77. package/dist/BasePlugin-BCVSn9QJ.js.map +0 -1
  78. package/dist/IconQuickEdit-CMCQncyj.js +0 -27
  79. package/dist/IconQuickEdit-CMCQncyj.js.map +0 -1
  80. package/dist/InputBox-CZ1v4_l3.js +0 -50
  81. package/dist/InputBox-CZ1v4_l3.js.map +0 -1
  82. package/dist/Preferences-DqtjY7XU.js +0 -1541
  83. package/dist/Preferences-DqtjY7XU.js.map +0 -1
  84. package/dist/WatchlistAction-BbNAyryN.js +0 -5
  85. package/dist/WatchlistAction-BbNAyryN.js.map +0 -1
  86. package/dist/browser-DR-yCqVg.js +0 -1160
  87. package/dist/browser-DR-yCqVg.js.map +0 -1
  88. package/dist/index-B9VO3swL.js.map +0 -1
  89. package/dist/index-CG38LlAh.js +0 -46
  90. package/dist/index-CG38LlAh.js.map +0 -1
  91. package/dist/index-CM_6yF2v.js.map +0 -1
  92. package/dist/index-CcAmmXbb.js +0 -3290
  93. package/dist/index-CcAmmXbb.js.map +0 -1
  94. package/dist/index-Cq8xPcEY.js.map +0 -1
  95. package/dist/index-DVvsTsLI.js +0 -505
  96. package/dist/index-DVvsTsLI.js.map +0 -1
  97. package/dist/index-FvMu0Ka0.js +0 -342
  98. package/dist/index-FvMu0Ka0.js.map +0 -1
  99. package/dist/index-rKL4D_7I.js.map +0 -1
  100. package/dist/vueHooks-l04s8cIl.js.map +0 -1
@@ -1,22 +1,22 @@
1
- import { j as l } from "./index-CM_6yF2v.js";
2
- import { c as M, g as f, R as I, I as L, S as v } from "./Preferences-DqtjY7XU.js";
3
- var N = Object.create, x = Object.defineProperty, q = Object.getOwnPropertyDescriptor, _ = (i, t) => (t = Symbol[i]) ? t : Symbol.for("Symbol." + i), w = (i) => {
1
+ import { j as l } from "./Promise.withResolvers-C4chhLB1.js";
2
+ import { d as M, g as f, R as L, a as I, S as v } from "./index-QnWieXQc.js";
3
+ var N = Object.create, x = Object.defineProperty, q = Object.getOwnPropertyDescriptor, _ = (i, t) => (t = Symbol[i]) ? t : /* @__PURE__ */ Symbol.for("Symbol." + i), w = (i) => {
4
4
  throw TypeError(i);
5
5
  }, A = (i, t, e) => t in i ? x(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e, T = (i, t) => x(i, "name", { value: t, configurable: !0 }), C = (i) => [, , , N(i?.[_("metadata")] ?? null)], E = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"], P = (i) => i !== void 0 && typeof i != "function" ? w("Function expected") : i, k = (i, t, e, n, o) => ({ kind: E[i], name: t, metadata: n, addInitializer: (r) => e._ ? w("Already initialized") : o.push(P(r || null)) }), D = (i, t) => A(t, _("metadata"), i[3]), z = (i, t, e, n) => {
6
6
  for (var o = 0, r = i[t >> 1], s = r && r.length; o < s; o++) r[o].call(e);
7
7
  return n;
8
8
  }, O = (i, t, e, n, o, r) => {
9
- var s, u, a, c = t & 7, d = !1, h = 0, B = i[h] || (i[h] = []), p = c && (o = o.prototype, c < 5 && (c > 3 || !d) && q(o, e));
9
+ var s, u, a, c = t & 7, h = !1, d = 0, B = i[d] || (i[d] = []), p = c && (o = o.prototype, c < 5 && (c > 3 || !h) && q(o, e));
10
10
  T(o, e);
11
11
  for (var g = n.length - 1; g >= 0; g--)
12
12
  a = k(c, e, u = {}, i[3], B), s = (0, n[g])(o, a), u._ = 1, P(s) && (o = s);
13
- return D(i, o), p && x(o, e, p), d ? c ^ 4 ? r : p : o;
13
+ return D(i, o), p && x(o, e, p), h ? c ^ 4 ? r : p : o;
14
14
  }, S, m, y;
15
- S = [I(
15
+ S = [L(
16
16
  v.object({
17
17
  toolboxAlwaysShow: v.boolean().description("Make the toolbox opened by default").default(!1)
18
18
  }).description("Toolbox preferences")
19
- ), L(["preferences"])];
19
+ ), I(["preferences"])];
20
20
  class b extends (y = M) {
21
21
  // id -> seq
22
22
  constructor(t) {
@@ -154,10 +154,10 @@ class b extends (y = M) {
154
154
  id: `${c}-btn`,
155
155
  "data-id": t.id,
156
156
  class: "ipe-toolbox-btn",
157
- onClick: (h) => {
158
- a?.(h), this.ctx.emit("toolbox/button-clicked", {
157
+ onClick: (d) => {
158
+ a?.(d), this.ctx.emit("toolbox/button-clicked", {
159
159
  ctx: this.ctx,
160
- event: h,
160
+ event: d,
161
161
  payload: t
162
162
  });
163
163
  },
@@ -192,4 +192,4 @@ z(m, 1, b);
192
192
  export {
193
193
  b as PluginToolbox
194
194
  };
195
- //# sourceMappingURL=index-DjyjqpeO.js.map
195
+ //# sourceMappingURL=index-C4qm_X_A.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-DjyjqpeO.js","sources":["../src/plugins/toolbox/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema, Service } from '@/InPageEdit'\nimport { JSX, ReactElement } from 'jsx-dom'\nimport './styles.scss'\nimport { ComputeAbleSync } from '@/utils/computeable.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n toolbox: PluginToolbox\n }\n interface Events {\n 'toolbox/button-added'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-removed'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-clicked'(payload: {\n ctx: InPageEdit\n event: MouseEvent\n payload: ToolboxButton\n }): void\n 'toolbox/toggle'(payload: { ctx: InPageEdit; opened: boolean }): void\n }\n interface PreferencesMap {\n toolboxAlwaysShow: boolean\n }\n}\n\ninterface ToolboxButton {\n id: string\n group?: 'auto' | 'group1' | 'group2'\n icon: ComputeAbleSync<string | HTMLElement | SVGElement | ReactElement>\n tooltip?: ComputeAbleSync<string | HTMLElement>\n itemProps?: JSX.IntrinsicElements['li']\n buttonProps?: JSX.IntrinsicElements['button']\n onClick?: (event: MouseEvent) => void\n index?: number // 任意数值均可:负数靠前、正数靠后、Infinity 末尾、未传时按插入顺序\n}\n\n@RegisterPreferences(\n Schema.object({\n toolboxAlwaysShow: Schema.boolean()\n .description('Make the toolbox opened by default')\n .default(false),\n }).description('Toolbox preferences')\n)\n@Inject(['preferences'])\nexport class PluginToolbox extends Service {\n container!: HTMLElement\n\n // ==== 内部状态 ====\n private buttons: ToolboxButton[] = []\n\n // 插入顺序序列号:用于当 index 未给时保持“自然顺序”\n private seqCounter = 0\n private seqMap = new Map<string, number>() // id -> seq\n\n constructor(public ctx: InPageEdit) {\n super(ctx, 'toolbox', false)\n }\n\n protected async start(): Promise<void> {\n this.container = this.createToolbox()\n this.ctx.preferences.get('toolboxAlwaysShow').then((val) => {\n if (val) {\n this.container.classList.add('is-persistent')\n }\n })\n this.setupHoverLogic()\n document.body.appendChild(this.container)\n\n // 国际化变化时重新渲染\n this.ctx.on('i18n/changed', () => {\n console.info('i18n/changed', this.buttons)\n this.renderAll()\n })\n }\n\n protected stop(): void | Promise<void> {\n this.container?.remove()\n }\n\n private get isPersistent() {\n return this.container.classList.contains('is-persistent')\n }\n\n private setupHoverLogic() {\n let hoverTimeout: number | null = null\n\n // 鼠标进入时暂时展开\n this.container.addEventListener('mouseenter', () => {\n if (hoverTimeout) {\n clearTimeout(hoverTimeout)\n hoverTimeout = null\n }\n\n // 如果不在持久化状态,则添加hover展开效果\n if (!this.isPersistent) {\n this.container.classList.add('is-hovered')\n }\n })\n\n // 鼠标离开时收起(如果不是持久化状态)\n this.container.addEventListener('mouseleave', () => {\n if (!this.isPersistent) {\n hoverTimeout = window.setTimeout(() => {\n this.container.classList.remove('is-hovered')\n }, 150) // 延迟150ms收起,避免快速移动鼠标时闪烁\n }\n })\n }\n\n /**\n * 计算按钮动画延迟\n * @param index 按钮索引(从0开始)\n * @param totalCount 总按钮数量\n * @returns 延迟时间(秒)\n */\n private calculateButtonDelay(index: number, totalCount: number): number {\n if (totalCount <= 1) return 0\n\n // 总动画时长150ms = 0.15s\n const totalDuration = 0.15\n // 使用平方根函数创建非线性延迟,差值逐渐缩小\n const normalizedIndex = index / (totalCount - 1)\n const delay = totalDuration * Math.sqrt(normalizedIndex)\n\n return Math.round(delay * 1000) / 1000 // 保留3位小数\n }\n\n /**\n * 更新按钮组的动画延迟\n */\n private updateButtonDelays() {\n const btnGroups = this.container.querySelectorAll('.btn-group')\n\n btnGroups.forEach((group) => {\n const buttons = group.querySelectorAll('.btn-tip-group')\n const totalCount = buttons.length\n\n buttons.forEach((button, index) => {\n const delay = this.calculateButtonDelay(index, totalCount)\n ;(button as HTMLElement).style.setProperty('--transition-delay', `${delay}s`)\n ;(button as HTMLElement).style.setProperty('--max-transition-delay', '0.15s')\n })\n })\n }\n\n private createToolbox() {\n const toggler = (\n <button\n className=\"ipe-toolbox-btn\"\n id=\"toolbox-toggler\"\n onClick={() => {\n this.toggle()\n }}\n >\n {/* Font Awesome 5 Solid: Plus */}\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"448\" height=\"512\" viewBox=\"0 0 448 512\">\n <rect width=\"448\" height=\"512\" fill=\"none\" />\n <path\n fill=\"currentColor\"\n d=\"M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32\"\n />\n </svg>\n </button>\n )\n const element = (\n <div id=\"ipe-edit-toolbox\">\n <ul className=\"btn-group group1\" style={{ display: 'flex', flexDirection: 'column' }}></ul>\n <ul className=\"btn-group group2\" style={{ display: 'flex', flexDirection: 'row' }}></ul>\n {toggler}\n </div>\n )\n\n return element as HTMLElement\n }\n\n private normalizeButtonId(id: string) {\n if (!id) {\n id = Math.random().toString(36).substring(2, 8)\n }\n // 修复:正确替换空白/点/井号(保留语义,修正正则)\n return `ipe-toolbox__${id.trim()}`.replace(/[\\s.#]+/g, '-')\n }\n\n // ====== 排序与分组 ======\n private chooseAutoGroup(): 'group1' | 'group2' {\n const g1 = this.buttons.filter((b) => b.group === 'group1').length\n const g2 = this.buttons.filter((b) => b.group === 'group2').length\n return g1 <= g2 ? 'group1' : 'group2'\n }\n\n // 归一化排序键:\n // 1) 若 index 是有限数值 => 直接使用(允许负数/小数/很大数);\n // 2) 若为 Infinity / -Infinity => 自然比较;\n // 3) 若 NaN / 未提供 => 返回 null,后续用插入顺序(seq)比较。\n private orderKey(btn: ToolboxButton): number | null {\n const idx = (btn as any).index\n if (typeof idx === 'number') {\n if (Number.isNaN(idx)) return null\n return idx // 包含 Infinity 与 -Infinity\n }\n return null\n }\n\n private compareButtons = (a: ToolboxButton, b: ToolboxButton) => {\n const ak = this.orderKey(a) // number | null\n const bk = this.orderKey(b)\n\n const va = ak ?? 0\n const vb = bk ?? 0\n\n if (va < vb) return -1\n if (va > vb) return 1\n\n // 有效值相等时的细化:\n const sa = this.seqMap.get(a.id) ?? 0\n const sb = this.seqMap.get(b.id) ?? 0\n\n if (ak === null && bk === null) {\n if (sa !== sb) return sa - sb\n return 0 // 不以 id 再兜底,保持稳定排序\n }\n\n if (ak === null && bk !== null) return -1 // 无 index(按0) 优先于 数值 index=0\n if (ak !== null && bk === null) return 1\n\n // 双方都有 index 且值相等,退化到 seq;仍然相等时返回 0\n if (sa !== sb) return sa - sb\n return 0\n }\n\n // ====== 对外 API:新增/替换/删除 ======\n addButton(payload: ToolboxButton) {\n // 统一化 id(保留原意:若缺失则补)\n payload.id = (payload.id || '').trim()\n if (!payload.id) {\n this.ctx.logger('toolbox').warn('Button id is empty, generating a random one.')\n payload.id = Math.random().toString(36).slice(2, 10)\n }\n\n const existingIndex = this.buttons.findIndex((button) => button.id === payload.id)\n\n // 分组:新增时 auto,替换时默认保留原组,除非明确指定\n const nextGroup: 'group1' | 'group2' = (() => {\n if (existingIndex !== -1) {\n const old = this.buttons[existingIndex]\n return !payload.group || payload.group === 'auto' ? (old.group as any) : payload.group\n }\n return !payload.group || payload.group === 'auto' ? this.chooseAutoGroup() : payload.group\n })()\n\n // 序列号:用于 index 未提供时,保持插入顺序\n if (!this.seqMap.has(payload.id)) {\n this.seqMap.set(payload.id, this.seqCounter++)\n }\n\n if (existingIndex !== -1) {\n // 替换:保留旧的 seq,不动;index 未传则沿用旧值\n const old = this.buttons[existingIndex]\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : old.index\n const merged: ToolboxButton = { ...old, ...payload, group: nextGroup, index: incomingIndex }\n\n this.buttons.splice(existingIndex, 1, merged)\n } else {\n // 新增:按给定 index 或留空;只设置组\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : undefined\n const fresh: ToolboxButton = { ...payload, group: nextGroup, index: incomingIndex }\n this.buttons.push(fresh)\n }\n\n this.ctx.emit('toolbox/button-added', { ctx: this.ctx, payload })\n this.renderAll()\n }\n\n removeButton(id: string) {\n const index = this.buttons.findIndex((button) => button.id === id)\n if (index !== -1) {\n const payload = this.buttons[index]\n this.buttons.splice(index, 1)\n // 可选择是否保留 seq,使得将来同 id 重加时仍按旧顺序;这里删除时保留更合理\n this.ctx.emit('toolbox/button-removed', { ctx: this.ctx, payload })\n this.renderAll()\n }\n }\n\n // ====== 渲染 ======\n private renderButton(payload: ToolboxButton) {\n let { id, icon, index, tooltip, itemProps, buttonProps, onClick } = payload\n const normalizedId = this.normalizeButtonId(id)\n\n // 结构尽量保持,避免在 <li> 上绑定 click 造成双触发\n const element = (\n <li class=\"btn-tip-group\" id={normalizedId} data-id={id} data-index={index} {...itemProps}>\n <div class=\"btn-tip\">{computeFallbackSync(tooltip)}</div>\n <button\n id={`${normalizedId}-btn`}\n data-id={payload.id}\n class=\"ipe-toolbox-btn\"\n onClick={(e: any) => {\n onClick?.(e as MouseEvent)\n this.ctx.emit('toolbox/button-clicked', {\n ctx: this.ctx,\n event: e as MouseEvent,\n payload,\n })\n }}\n {...buttonProps}\n >\n {computeFallbackSync(icon)}\n </button>\n </li>\n )\n\n return element as HTMLElement\n }\n\n private renderAll() {\n const group1 = this.buttons\n .filter((b) => b.group === 'group1')\n .slice()\n .sort(this.compareButtons)\n const group2 = this.buttons\n .filter((b) => b.group === 'group2')\n .slice()\n .sort(this.compareButtons)\n\n const group1El = this.container.querySelector('.btn-group.group1') as HTMLElement\n const group2El = this.container.querySelector('.btn-group.group2') as HTMLElement\n\n group1El.innerHTML = ''\n group2El.innerHTML = ''\n\n group1.forEach((button) => {\n group1El.appendChild(this.renderButton(button))\n })\n group2.forEach((button) => {\n group2El.appendChild(this.renderButton(button))\n })\n\n // 统一更新动画延迟\n this.updateButtonDelays()\n }\n\n getContainer() {\n return this.container\n }\n\n get isOpened() {\n return (\n this.container.classList.contains('is-persistent') ||\n this.container.classList.contains('is-hovered')\n )\n }\n\n toggle(force?: boolean) {\n const isPersistent = this.isPersistent\n const newPersistent = typeof force === 'boolean' ? force : !isPersistent\n this.container.classList.toggle('is-persistent', newPersistent)\n this.container.classList.remove('is-hovered')\n this.ctx.preferences.set('toolboxAlwaysShow', newPersistent)\n this.ctx.emit('toolbox/toggle', { ctx: this.ctx, opened: this.isOpened })\n }\n}\n"],"names":["_PluginToolbox_decorators","_init","_a","RegisterPreferences","Schema","Inject","PluginToolbox","Service","ctx","a","b","ak","bk","va","vb","sa","sb","val","hoverTimeout","index","totalCount","totalDuration","normalizedIndex","delay","group","buttons","button","jsxs","jsx","id","g1","g2","btn","idx","payload","existingIndex","nextGroup","old","incomingIndex","merged","fresh","icon","tooltip","itemProps","buttonProps","onClick","normalizedId","computeFallbackSync","e","group1","group2","group1El","group2El","force","isPersistent","newPersistent","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}
1
+ {"version":3,"file":"index-C4qm_X_A.js","sources":["../src/plugins/toolbox/index.tsx"],"sourcesContent":["import { Inject, InPageEdit, Schema, Service } from '@/InPageEdit'\nimport { JSX, ReactElement } from 'jsx-dom'\nimport './styles.scss'\nimport { ComputeAbleSync } from '@/utils/computeable.js'\n\ndeclare module '@/InPageEdit' {\n interface InPageEdit {\n toolbox: PluginToolbox\n }\n interface Events {\n 'toolbox/button-added'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-removed'(payload: { ctx: InPageEdit; payload: ToolboxButton }): void\n 'toolbox/button-clicked'(payload: {\n ctx: InPageEdit\n event: MouseEvent\n payload: ToolboxButton\n }): void\n 'toolbox/toggle'(payload: { ctx: InPageEdit; opened: boolean }): void\n }\n interface PreferencesMap {\n toolboxAlwaysShow: boolean\n }\n}\n\ninterface ToolboxButton {\n id: string\n group?: 'auto' | 'group1' | 'group2'\n icon: ComputeAbleSync<string | HTMLElement | SVGElement | ReactElement>\n tooltip?: ComputeAbleSync<string | HTMLElement>\n itemProps?: JSX.IntrinsicElements['li']\n buttonProps?: JSX.IntrinsicElements['button']\n onClick?: (event: MouseEvent) => void\n index?: number // 任意数值均可:负数靠前、正数靠后、Infinity 末尾、未传时按插入顺序\n}\n\n@RegisterPreferences(\n Schema.object({\n toolboxAlwaysShow: Schema.boolean()\n .description('Make the toolbox opened by default')\n .default(false),\n }).description('Toolbox preferences')\n)\n@Inject(['preferences'])\nexport class PluginToolbox extends Service {\n container!: HTMLElement\n\n // ==== 内部状态 ====\n private buttons: ToolboxButton[] = []\n\n // 插入顺序序列号:用于当 index 未给时保持“自然顺序”\n private seqCounter = 0\n private seqMap = new Map<string, number>() // id -> seq\n\n constructor(public ctx: InPageEdit) {\n super(ctx, 'toolbox', false)\n }\n\n protected async start(): Promise<void> {\n this.container = this.createToolbox()\n this.ctx.preferences.get('toolboxAlwaysShow').then((val) => {\n if (val) {\n this.container.classList.add('is-persistent')\n }\n })\n this.setupHoverLogic()\n document.body.appendChild(this.container)\n\n // 国际化变化时重新渲染\n this.ctx.on('i18n/changed', () => {\n console.info('i18n/changed', this.buttons)\n this.renderAll()\n })\n }\n\n protected stop(): void | Promise<void> {\n this.container?.remove()\n }\n\n private get isPersistent() {\n return this.container.classList.contains('is-persistent')\n }\n\n private setupHoverLogic() {\n let hoverTimeout: number | null = null\n\n // 鼠标进入时暂时展开\n this.container.addEventListener('mouseenter', () => {\n if (hoverTimeout) {\n clearTimeout(hoverTimeout)\n hoverTimeout = null\n }\n\n // 如果不在持久化状态,则添加hover展开效果\n if (!this.isPersistent) {\n this.container.classList.add('is-hovered')\n }\n })\n\n // 鼠标离开时收起(如果不是持久化状态)\n this.container.addEventListener('mouseleave', () => {\n if (!this.isPersistent) {\n hoverTimeout = window.setTimeout(() => {\n this.container.classList.remove('is-hovered')\n }, 150) // 延迟150ms收起,避免快速移动鼠标时闪烁\n }\n })\n }\n\n /**\n * 计算按钮动画延迟\n * @param index 按钮索引(从0开始)\n * @param totalCount 总按钮数量\n * @returns 延迟时间(秒)\n */\n private calculateButtonDelay(index: number, totalCount: number): number {\n if (totalCount <= 1) return 0\n\n // 总动画时长150ms = 0.15s\n const totalDuration = 0.15\n // 使用平方根函数创建非线性延迟,差值逐渐缩小\n const normalizedIndex = index / (totalCount - 1)\n const delay = totalDuration * Math.sqrt(normalizedIndex)\n\n return Math.round(delay * 1000) / 1000 // 保留3位小数\n }\n\n /**\n * 更新按钮组的动画延迟\n */\n private updateButtonDelays() {\n const btnGroups = this.container.querySelectorAll('.btn-group')\n\n btnGroups.forEach((group) => {\n const buttons = group.querySelectorAll('.btn-tip-group')\n const totalCount = buttons.length\n\n buttons.forEach((button, index) => {\n const delay = this.calculateButtonDelay(index, totalCount)\n ;(button as HTMLElement).style.setProperty('--transition-delay', `${delay}s`)\n ;(button as HTMLElement).style.setProperty('--max-transition-delay', '0.15s')\n })\n })\n }\n\n private createToolbox() {\n const toggler = (\n <button\n className=\"ipe-toolbox-btn\"\n id=\"toolbox-toggler\"\n onClick={() => {\n this.toggle()\n }}\n >\n {/* Font Awesome 5 Solid: Plus */}\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"448\" height=\"512\" viewBox=\"0 0 448 512\">\n <rect width=\"448\" height=\"512\" fill=\"none\" />\n <path\n fill=\"currentColor\"\n d=\"M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32\"\n />\n </svg>\n </button>\n )\n const element = (\n <div id=\"ipe-edit-toolbox\">\n <ul className=\"btn-group group1\" style={{ display: 'flex', flexDirection: 'column' }}></ul>\n <ul className=\"btn-group group2\" style={{ display: 'flex', flexDirection: 'row' }}></ul>\n {toggler}\n </div>\n )\n\n return element as HTMLElement\n }\n\n private normalizeButtonId(id: string) {\n if (!id) {\n id = Math.random().toString(36).substring(2, 8)\n }\n // 修复:正确替换空白/点/井号(保留语义,修正正则)\n return `ipe-toolbox__${id.trim()}`.replace(/[\\s.#]+/g, '-')\n }\n\n // ====== 排序与分组 ======\n private chooseAutoGroup(): 'group1' | 'group2' {\n const g1 = this.buttons.filter((b) => b.group === 'group1').length\n const g2 = this.buttons.filter((b) => b.group === 'group2').length\n return g1 <= g2 ? 'group1' : 'group2'\n }\n\n // 归一化排序键:\n // 1) 若 index 是有限数值 => 直接使用(允许负数/小数/很大数);\n // 2) 若为 Infinity / -Infinity => 自然比较;\n // 3) 若 NaN / 未提供 => 返回 null,后续用插入顺序(seq)比较。\n private orderKey(btn: ToolboxButton): number | null {\n const idx = (btn as any).index\n if (typeof idx === 'number') {\n if (Number.isNaN(idx)) return null\n return idx // 包含 Infinity 与 -Infinity\n }\n return null\n }\n\n private compareButtons = (a: ToolboxButton, b: ToolboxButton) => {\n const ak = this.orderKey(a) // number | null\n const bk = this.orderKey(b)\n\n const va = ak ?? 0\n const vb = bk ?? 0\n\n if (va < vb) return -1\n if (va > vb) return 1\n\n // 有效值相等时的细化:\n const sa = this.seqMap.get(a.id) ?? 0\n const sb = this.seqMap.get(b.id) ?? 0\n\n if (ak === null && bk === null) {\n if (sa !== sb) return sa - sb\n return 0 // 不以 id 再兜底,保持稳定排序\n }\n\n if (ak === null && bk !== null) return -1 // 无 index(按0) 优先于 数值 index=0\n if (ak !== null && bk === null) return 1\n\n // 双方都有 index 且值相等,退化到 seq;仍然相等时返回 0\n if (sa !== sb) return sa - sb\n return 0\n }\n\n // ====== 对外 API:新增/替换/删除 ======\n addButton(payload: ToolboxButton) {\n // 统一化 id(保留原意:若缺失则补)\n payload.id = (payload.id || '').trim()\n if (!payload.id) {\n this.ctx.logger('toolbox').warn('Button id is empty, generating a random one.')\n payload.id = Math.random().toString(36).slice(2, 10)\n }\n\n const existingIndex = this.buttons.findIndex((button) => button.id === payload.id)\n\n // 分组:新增时 auto,替换时默认保留原组,除非明确指定\n const nextGroup: 'group1' | 'group2' = (() => {\n if (existingIndex !== -1) {\n const old = this.buttons[existingIndex]\n return !payload.group || payload.group === 'auto' ? (old.group as any) : payload.group\n }\n return !payload.group || payload.group === 'auto' ? this.chooseAutoGroup() : payload.group\n })()\n\n // 序列号:用于 index 未提供时,保持插入顺序\n if (!this.seqMap.has(payload.id)) {\n this.seqMap.set(payload.id, this.seqCounter++)\n }\n\n if (existingIndex !== -1) {\n // 替换:保留旧的 seq,不动;index 未传则沿用旧值\n const old = this.buttons[existingIndex]\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : old.index\n const merged: ToolboxButton = { ...old, ...payload, group: nextGroup, index: incomingIndex }\n\n this.buttons.splice(existingIndex, 1, merged)\n } else {\n // 新增:按给定 index 或留空;只设置组\n const incomingIndex =\n typeof payload.index === 'number' && !Number.isNaN(payload.index)\n ? payload.index\n : undefined\n const fresh: ToolboxButton = { ...payload, group: nextGroup, index: incomingIndex }\n this.buttons.push(fresh)\n }\n\n this.ctx.emit('toolbox/button-added', { ctx: this.ctx, payload })\n this.renderAll()\n }\n\n removeButton(id: string) {\n const index = this.buttons.findIndex((button) => button.id === id)\n if (index !== -1) {\n const payload = this.buttons[index]\n this.buttons.splice(index, 1)\n // 可选择是否保留 seq,使得将来同 id 重加时仍按旧顺序;这里删除时保留更合理\n this.ctx.emit('toolbox/button-removed', { ctx: this.ctx, payload })\n this.renderAll()\n }\n }\n\n // ====== 渲染 ======\n private renderButton(payload: ToolboxButton) {\n let { id, icon, index, tooltip, itemProps, buttonProps, onClick } = payload\n const normalizedId = this.normalizeButtonId(id)\n\n // 结构尽量保持,避免在 <li> 上绑定 click 造成双触发\n const element = (\n <li class=\"btn-tip-group\" id={normalizedId} data-id={id} data-index={index} {...itemProps}>\n <div class=\"btn-tip\">{computeFallbackSync(tooltip)}</div>\n <button\n id={`${normalizedId}-btn`}\n data-id={payload.id}\n class=\"ipe-toolbox-btn\"\n onClick={(e: any) => {\n onClick?.(e as MouseEvent)\n this.ctx.emit('toolbox/button-clicked', {\n ctx: this.ctx,\n event: e as MouseEvent,\n payload,\n })\n }}\n {...buttonProps}\n >\n {computeFallbackSync(icon)}\n </button>\n </li>\n )\n\n return element as HTMLElement\n }\n\n private renderAll() {\n const group1 = this.buttons\n .filter((b) => b.group === 'group1')\n .slice()\n .sort(this.compareButtons)\n const group2 = this.buttons\n .filter((b) => b.group === 'group2')\n .slice()\n .sort(this.compareButtons)\n\n const group1El = this.container.querySelector('.btn-group.group1') as HTMLElement\n const group2El = this.container.querySelector('.btn-group.group2') as HTMLElement\n\n group1El.innerHTML = ''\n group2El.innerHTML = ''\n\n group1.forEach((button) => {\n group1El.appendChild(this.renderButton(button))\n })\n group2.forEach((button) => {\n group2El.appendChild(this.renderButton(button))\n })\n\n // 统一更新动画延迟\n this.updateButtonDelays()\n }\n\n getContainer() {\n return this.container\n }\n\n get isOpened() {\n return (\n this.container.classList.contains('is-persistent') ||\n this.container.classList.contains('is-hovered')\n )\n }\n\n toggle(force?: boolean) {\n const isPersistent = this.isPersistent\n const newPersistent = typeof force === 'boolean' ? force : !isPersistent\n this.container.classList.toggle('is-persistent', newPersistent)\n this.container.classList.remove('is-hovered')\n this.ctx.preferences.set('toolboxAlwaysShow', newPersistent)\n this.ctx.emit('toolbox/toggle', { ctx: this.ctx, opened: this.isOpened })\n }\n}\n"],"names":["_PluginToolbox_decorators","_init","_a","RegisterPreferences","Schema","Inject","PluginToolbox","Service","ctx","a","b","ak","bk","va","vb","sa","sb","val","hoverTimeout","index","totalCount","totalDuration","normalizedIndex","delay","group","buttons","button","jsxs","jsx","id","g1","g2","btn","idx","payload","existingIndex","nextGroup","old","incomingIndex","merged","fresh","icon","tooltip","itemProps","buttonProps","onClick","normalizedId","computeFallbackSync","e","group1","group2","group1El","group2El","force","isPersistent","newPersistent","__decoratorStart","__decorateElement","__runInitializers"],"mappings":"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"}