@milkdown/plugin-tooltip 7.5.3 → 7.5.9

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/lib/index.es.js CHANGED
@@ -1,81 +1,83 @@
1
- var k = (o, t, e) => {
2
- if (!t.has(o))
3
- throw TypeError("Cannot " + e);
1
+ var S = (o) => {
2
+ throw TypeError(o);
4
3
  };
5
- var n = (o, t, e) => (k(o, t, "read from private field"), e ? e.call(o) : t.get(o)), l = (o, t, e) => {
6
- if (t.has(o))
7
- throw TypeError("Cannot add the same private member more than once");
8
- t instanceof WeakSet ? t.add(o) : t.set(o, e);
9
- }, h = (o, t, e, s) => (k(o, t, "write to private field"), s ? s.call(o, e) : t.set(o, e), e);
10
- var T = (o, t, e) => (k(o, t, "access private method"), e);
11
- import { TextSelection as B, Plugin as F, PluginKey as H } from "@milkdown/prose/state";
12
- import M from "lodash.debounce";
13
- import { computePosition as O, flip as S, offset as b } from "@floating-ui/dom";
14
- import { posToDOMRect as R } from "@milkdown/prose";
15
- import { $ctx as j, $prose as q } from "@milkdown/utils";
16
- var r, d, c, a, u, y, C;
17
- class A {
4
+ var P = (o, t, e) => t.has(o) || S("Cannot " + e);
5
+ var i = (o, t, e) => (P(o, t, "read from private field"), e ? e.call(o) : t.get(o)), n = (o, t, e) => t.has(o) ? S("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(o) : t.set(o, e), l = (o, t, e, s) => (P(o, t, "write to private field"), s ? s.call(o, e) : t.set(o, e), e), b = (o, t, e) => (P(o, t, "access private method"), e);
6
+ import { TextSelection as H, Plugin as M, PluginKey as R } from "@milkdown/prose/state";
7
+ import U from "lodash.debounce";
8
+ import { computePosition as C, flip as E, offset as I, shift as j } from "@floating-ui/dom";
9
+ import { posToDOMRect as q } from "@milkdown/prose";
10
+ import { $ctx as K, $prose as L } from "@milkdown/utils";
11
+ var r, d, u, f, a, c, g, $, _;
12
+ class V {
18
13
  constructor(t) {
14
+ n(this, $);
19
15
  /// @internal
20
- l(this, y);
16
+ n(this, r);
21
17
  /// @internal
22
- l(this, r, void 0);
18
+ n(this, d);
23
19
  /// @internal
24
- l(this, d, void 0);
25
- l(this, c, void 0);
20
+ n(this, u);
26
21
  /// @internal
27
- l(this, a, void 0);
28
- l(this, u, void 0);
29
- h(this, c, !1), this.onShow = () => {
22
+ n(this, f);
23
+ n(this, a);
24
+ /// @internal
25
+ n(this, c);
26
+ n(this, g);
27
+ l(this, a, !1), this.onShow = () => {
30
28
  }, this.onHide = () => {
31
- }, h(this, u, (e, s) => {
32
- var P;
33
- const { state: i, composing: p } = e, { selection: f, doc: w } = i, { ranges: g } = f, $ = Math.min(...g.map((m) => m.$from.pos)), x = Math.max(...g.map((m) => m.$to.pos)), E = s && s.doc.eq(w) && s.selection.eq(f);
34
- if (n(this, c) || ((P = e.dom.parentElement) == null || P.appendChild(this.element), h(this, c, !0)), p || E)
35
- return;
36
- if (!n(this, d).call(this, e, s)) {
29
+ }, l(this, g, (e, s) => {
30
+ var T;
31
+ const { state: h, composing: m } = e, { selection: y, doc: x } = h, { ranges: w } = y, k = Math.min(...w.map((p) => p.$from.pos)), O = Math.max(...w.map((p) => p.$to.pos)), B = s && s.doc.eq(x) && s.selection.eq(y);
32
+ if (i(this, a) || ((T = e.dom.parentElement) == null || T.appendChild(this.element), l(this, a, !0)), m || B) return;
33
+ if (!i(this, d).call(this, e, s)) {
37
34
  this.hide();
38
35
  return;
39
36
  }
40
- O({
41
- getBoundingClientRect: () => R(e, $, x)
37
+ C({
38
+ getBoundingClientRect: () => q(e, k, O)
42
39
  }, this.element, {
43
40
  placement: "top",
44
- middleware: [S(), b(n(this, a))]
45
- }).then(({ x: m, y: _ }) => {
41
+ middleware: [E(), I(i(this, c)), j(), ...i(this, u)]
42
+ }).then(({ x: p, y: F }) => {
46
43
  Object.assign(this.element.style, {
47
- left: `${m}px`,
48
- top: `${_}px`
44
+ left: `${p}px`,
45
+ top: `${F}px`
49
46
  });
50
47
  }), this.show();
51
48
  }), this.update = (e, s) => {
52
- M(n(this, u), n(this, r))(e, s);
49
+ U(i(this, g), i(this, r))(e, s);
53
50
  }, this.destroy = () => {
54
51
  }, this.show = (e) => {
55
- this.element.dataset.show = "true", e && O(e, this.element, {
52
+ this.element.dataset.show = "true", e && C(e, this.element, {
56
53
  placement: "top",
57
- middleware: [S(), b(n(this, a))]
58
- }).then(({ x: s, y: i }) => {
54
+ middleware: [E(), I(i(this, c))],
55
+ ...i(this, f)
56
+ }).then(({ x: s, y: h }) => {
59
57
  Object.assign(this.element.style, {
60
58
  left: `${s}px`,
61
- top: `${i}px`
59
+ top: `${h}px`
62
60
  });
63
61
  }), this.onShow();
64
62
  }, this.hide = () => {
65
63
  this.element.dataset.show !== "false" && (this.element.dataset.show = "false", this.onHide());
66
- }, this.element = t.content, h(this, r, t.debounce ?? 200), h(this, d, t.shouldShow ?? T(this, y, C)), h(this, a, t.offset), this.element.dataset.show = "false";
64
+ }, this.element = t.content, l(this, r, t.debounce ?? 200), l(this, d, t.shouldShow ?? b(this, $, _)), l(this, c, t.offset), l(this, u, t.middleware ?? []), l(this, f, t.floatingUIOptions ?? {}), this.element.dataset.show = "false";
67
65
  }
68
66
  }
69
- r = new WeakMap(), d = new WeakMap(), c = new WeakMap(), a = new WeakMap(), u = new WeakMap(), y = new WeakSet(), C = function(t) {
70
- const { doc: e, selection: s } = t.state, { empty: i, from: p, to: f } = s, w = !e.textBetween(p, f).length && t.state.selection instanceof B, g = this.element.contains(document.activeElement), $ = !t.hasFocus() && !g, x = !t.editable;
71
- return !($ || i || w || x);
67
+ r = new WeakMap(), d = new WeakMap(), u = new WeakMap(), f = new WeakMap(), a = new WeakMap(), c = new WeakMap(), g = new WeakMap(), $ = new WeakSet(), /// @internal
68
+ _ = function(t) {
69
+ const { doc: e, selection: s } = t.state, { empty: h, from: m, to: y } = s, x = !e.textBetween(m, y).length && t.state.selection instanceof H, w = this.element.contains(document.activeElement), k = !t.hasFocus() && !w, O = !t.editable;
70
+ return !(k || h || x || O);
72
71
  };
73
- function G(o) {
74
- const t = j({}, `${o}_TOOLTIP_SPEC`), e = q((i) => {
75
- const p = i.get(t.key);
76
- return new F({
77
- key: new H(`${o}_TOOLTIP`),
78
- ...p
72
+ function W(o) {
73
+ const t = K(
74
+ {},
75
+ `${o}_TOOLTIP_SPEC`
76
+ ), e = L((h) => {
77
+ const m = h.get(t.key);
78
+ return new M({
79
+ key: new R(`${o}_TOOLTIP`),
80
+ ...m
79
81
  });
80
82
  }), s = [t, e];
81
83
  return s.key = t.key, s.pluginKey = e.key, t.meta = {
@@ -87,7 +89,7 @@ function G(o) {
87
89
  }, s;
88
90
  }
89
91
  export {
90
- A as TooltipProvider,
91
- G as tooltipFactory
92
+ V as TooltipProvider,
93
+ W as tooltipFactory
92
94
  };
93
95
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/tooltip-provider.ts","../src/tooltip-plugin.ts"],"sourcesContent":["import type { EditorState } from '@milkdown/prose/state'\nimport { TextSelection } from '@milkdown/prose/state'\nimport type { EditorView } from '@milkdown/prose/view'\nimport debounce from 'lodash.debounce'\nimport type { VirtualElement } from '@floating-ui/dom'\nimport { computePosition, flip, offset } from '@floating-ui/dom'\nimport { posToDOMRect } from '@milkdown/prose'\n\n/// Options for tooltip provider.\nexport interface TooltipProviderOptions {\n /// The tooltip content.\n content: HTMLElement\n /// The debounce time for updating tooltip, 200ms by default.\n debounce?: number\n /// The function to determine whether the tooltip should be shown.\n shouldShow?: (view: EditorView, prevState?: EditorState) => boolean\n /// The offset to get the block. Default is 0.\n offset?: number | {\n mainAxis?: number\n crossAxis?: number\n alignmentAxis?: number | null\n }\n}\n\n/// A provider for creating tooltip.\nexport class TooltipProvider {\n /// @internal\n readonly #debounce: number\n\n /// @internal\n readonly #shouldShow: (view: EditorView, prevState?: EditorState) => boolean\n\n /// @internal\n #initialized = false\n\n /// @internal\n readonly #offset?: number | {\n mainAxis?: number\n crossAxis?: number\n alignmentAxis?: number | null\n }\n\n /// The root element of the tooltip.\n element: HTMLElement\n\n /// On show callback.\n onShow = () => {}\n\n /// On hide callback.\n onHide = () => {}\n\n constructor(options: TooltipProviderOptions) {\n this.element = options.content\n this.#debounce = options.debounce ?? 200\n this.#shouldShow = options.shouldShow ?? this.#_shouldShow\n this.#offset = options.offset\n this.element.dataset.show = 'false'\n }\n\n /// @internal\n #onUpdate = (view: EditorView, prevState?: EditorState): void => {\n const { state, composing } = view\n const { selection, doc } = state\n const { ranges } = selection\n const from = Math.min(...ranges.map(range => range.$from.pos))\n const to = Math.max(...ranges.map(range => range.$to.pos))\n const isSame = prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)\n\n if (!this.#initialized) {\n view.dom.parentElement?.appendChild(this.element)\n this.#initialized = true\n }\n\n if (composing || isSame)\n return\n\n if (!this.#shouldShow(view, prevState)) {\n this.hide()\n return\n }\n\n const virtualEl: VirtualElement = {\n getBoundingClientRect: () => posToDOMRect(view, from, to),\n }\n computePosition(virtualEl, this.element, {\n placement: 'top',\n middleware: [flip(), offset(this.#offset)],\n })\n .then(({ x, y }) => {\n Object.assign(this.element.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n\n this.show()\n }\n\n /// Update provider state by editor view.\n update = (view: EditorView, prevState?: EditorState): void => {\n const updater = debounce(this.#onUpdate, this.#debounce)\n\n updater(view, prevState)\n }\n\n /// @internal\n #_shouldShow(view: EditorView): boolean {\n const { doc, selection } = view.state\n const { empty, from, to } = selection\n\n const isEmptyTextBlock = !doc.textBetween(from, to).length && view.state.selection instanceof TextSelection\n\n const isTooltipChildren = this.element.contains(document.activeElement)\n\n const notHasFocus = !view.hasFocus() && !isTooltipChildren\n\n const isReadonly = !view.editable\n\n if (\n notHasFocus\n || empty\n || isEmptyTextBlock\n || isReadonly\n )\n return false\n\n return true\n }\n\n /// Destroy the tooltip.\n destroy = () => {}\n\n /// Show the tooltip.\n show = (virtualElement?: VirtualElement) => {\n this.element.dataset.show = 'true'\n\n if (virtualElement) {\n computePosition(virtualElement, this.element, {\n placement: 'top',\n middleware: [flip(), offset(this.#offset)],\n })\n .then(({ x, y }) => {\n Object.assign(this.element.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n }\n\n this.onShow()\n }\n\n /// Hide the tooltip.\n hide = () => {\n if (this.element.dataset.show === 'false')\n return\n this.element.dataset.show = 'false'\n\n this.onHide()\n }\n}\n","import type { SliceType } from '@milkdown/ctx'\nimport type { PluginSpec } from '@milkdown/prose/state'\nimport { Plugin, PluginKey } from '@milkdown/prose/state'\nimport type { $Ctx, $Prose } from '@milkdown/utils'\nimport { $ctx, $prose } from '@milkdown/utils'\n\n/// @internal\nexport type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`\n\n/// @internal\nexport type TooltipPlugin<Id extends string, State = any> = [$Ctx<PluginSpec<State>, TooltipSpecId<Id>>, $Prose] & {\n key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>\n pluginKey: $Prose['key']\n}\n\n/// Create a tooltip plugin with a unique id.\nexport function tooltipFactory<Id extends string, State = any>(id: Id) {\n const tooltipSpec = $ctx<PluginSpec<State>, TooltipSpecId<Id>>({}, `${id}_TOOLTIP_SPEC`)\n const tooltipPlugin = $prose((ctx) => {\n const spec = ctx.get(tooltipSpec.key)\n return new Plugin({\n key: new PluginKey(`${id}_TOOLTIP`),\n ...spec,\n })\n })\n const result = [tooltipSpec, tooltipPlugin] as TooltipPlugin<Id>\n result.key = tooltipSpec.key\n result.pluginKey = tooltipPlugin.key\n tooltipSpec.meta = {\n package: '@milkdown/plugin-tooltip',\n displayName: `Ctx<tooltipSpec>|${id}`,\n }\n tooltipPlugin.meta = {\n package: '@milkdown/plugin-tooltip',\n displayName: `Prose<tooltip>|${id}`,\n }\n\n return result\n}\n"],"names":["TooltipProvider","options","__privateAdd","__shouldShow","_debounce","_shouldShow","_initialized","_offset","_onUpdate","__privateSet","view","prevState","state","composing","selection","doc","ranges","from","range","to","isSame","__privateGet","_a","computePosition","posToDOMRect","flip","offset","x","y","debounce","virtualElement","__privateMethod","_shouldShow_fn","empty","isEmptyTextBlock","TextSelection","isTooltipChildren","notHasFocus","isReadonly","tooltipFactory","id","tooltipSpec","$ctx","tooltipPlugin","$prose","ctx","spec","Plugin","PluginKey","result"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/tooltip-provider.ts","../src/tooltip-plugin.ts"],"sourcesContent":["import type { EditorState } from '@milkdown/prose/state'\nimport { TextSelection } from '@milkdown/prose/state'\nimport type { EditorView } from '@milkdown/prose/view'\nimport debounce from 'lodash.debounce'\nimport type {\n ComputePositionConfig,\n Middleware,\n VirtualElement,\n} from '@floating-ui/dom'\nimport { computePosition, flip, offset, shift } from '@floating-ui/dom'\nimport { posToDOMRect } from '@milkdown/prose'\n\n/// Options for tooltip provider.\nexport interface TooltipProviderOptions {\n /// The tooltip content.\n content: HTMLElement\n /// The debounce time for updating tooltip, 200ms by default.\n debounce?: number\n /// The function to determine whether the tooltip should be shown.\n shouldShow?: (view: EditorView, prevState?: EditorState) => boolean\n /// The offset to get the block. Default is 0.\n offset?:\n | number\n | {\n mainAxis?: number\n crossAxis?: number\n alignmentAxis?: number | null\n }\n /// Other middlewares for floating ui. This will be added after the internal middlewares.\n middleware?: Middleware[]\n /// Options for floating ui. If you pass `middleware` or `placement`, it will override the internal settings.\n floatingUIOptions?: Partial<ComputePositionConfig>\n}\n\n/// A provider for creating tooltip.\nexport class TooltipProvider {\n /// @internal\n readonly #debounce: number\n\n /// @internal\n readonly #shouldShow: (view: EditorView, prevState?: EditorState) => boolean\n\n /// @internal\n readonly #middleware: Middleware[]\n\n /// @internal\n readonly #floatingUIOptions: Partial<ComputePositionConfig>\n\n /// @internal\n #initialized = false\n\n /// @internal\n readonly #offset?:\n | number\n | {\n mainAxis?: number\n crossAxis?: number\n alignmentAxis?: number | null\n }\n\n /// The root element of the tooltip.\n element: HTMLElement\n\n /// On show callback.\n onShow = () => {}\n\n /// On hide callback.\n onHide = () => {}\n\n constructor(options: TooltipProviderOptions) {\n this.element = options.content\n this.#debounce = options.debounce ?? 200\n this.#shouldShow = options.shouldShow ?? this.#_shouldShow\n this.#offset = options.offset\n this.#middleware = options.middleware ?? []\n this.#floatingUIOptions = options.floatingUIOptions ?? {}\n this.element.dataset.show = 'false'\n }\n\n /// @internal\n #onUpdate = (view: EditorView, prevState?: EditorState): void => {\n const { state, composing } = view\n const { selection, doc } = state\n const { ranges } = selection\n const from = Math.min(...ranges.map((range) => range.$from.pos))\n const to = Math.max(...ranges.map((range) => range.$to.pos))\n const isSame =\n prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)\n\n if (!this.#initialized) {\n view.dom.parentElement?.appendChild(this.element)\n this.#initialized = true\n }\n\n if (composing || isSame) return\n\n if (!this.#shouldShow(view, prevState)) {\n this.hide()\n return\n }\n\n const virtualEl: VirtualElement = {\n getBoundingClientRect: () => posToDOMRect(view, from, to),\n }\n computePosition(virtualEl, this.element, {\n placement: 'top',\n middleware: [flip(), offset(this.#offset), shift(), ...this.#middleware],\n }).then(({ x, y }) => {\n Object.assign(this.element.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n\n this.show()\n }\n\n /// Update provider state by editor view.\n update = (view: EditorView, prevState?: EditorState): void => {\n const updater = debounce(this.#onUpdate, this.#debounce)\n\n updater(view, prevState)\n }\n\n /// @internal\n #_shouldShow(view: EditorView): boolean {\n const { doc, selection } = view.state\n const { empty, from, to } = selection\n\n const isEmptyTextBlock =\n !doc.textBetween(from, to).length &&\n view.state.selection instanceof TextSelection\n\n const isTooltipChildren = this.element.contains(document.activeElement)\n\n const notHasFocus = !view.hasFocus() && !isTooltipChildren\n\n const isReadonly = !view.editable\n\n if (notHasFocus || empty || isEmptyTextBlock || isReadonly) return false\n\n return true\n }\n\n /// Destroy the tooltip.\n destroy = () => {}\n\n /// Show the tooltip.\n show = (virtualElement?: VirtualElement) => {\n this.element.dataset.show = 'true'\n\n if (virtualElement) {\n computePosition(virtualElement, this.element, {\n placement: 'top',\n middleware: [flip(), offset(this.#offset)],\n ...this.#floatingUIOptions,\n }).then(({ x, y }) => {\n Object.assign(this.element.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n }\n\n this.onShow()\n }\n\n /// Hide the tooltip.\n hide = () => {\n if (this.element.dataset.show === 'false') return\n this.element.dataset.show = 'false'\n\n this.onHide()\n }\n}\n","import type { SliceType } from '@milkdown/ctx'\nimport type { PluginSpec } from '@milkdown/prose/state'\nimport { Plugin, PluginKey } from '@milkdown/prose/state'\nimport type { $Ctx, $Prose } from '@milkdown/utils'\nimport { $ctx, $prose } from '@milkdown/utils'\n\n/// @internal\nexport type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`\n\n/// @internal\nexport type TooltipPlugin<Id extends string, State = any> = [\n $Ctx<PluginSpec<State>, TooltipSpecId<Id>>,\n $Prose,\n] & {\n key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>\n pluginKey: $Prose['key']\n}\n\n/// Create a tooltip plugin with a unique id.\nexport function tooltipFactory<Id extends string, State = any>(id: Id) {\n const tooltipSpec = $ctx<PluginSpec<State>, TooltipSpecId<Id>>(\n {},\n `${id}_TOOLTIP_SPEC`\n )\n const tooltipPlugin = $prose((ctx) => {\n const spec = ctx.get(tooltipSpec.key)\n return new Plugin({\n key: new PluginKey(`${id}_TOOLTIP`),\n ...spec,\n })\n })\n const result = [tooltipSpec, tooltipPlugin] as TooltipPlugin<Id>\n result.key = tooltipSpec.key\n result.pluginKey = tooltipPlugin.key\n tooltipSpec.meta = {\n package: '@milkdown/plugin-tooltip',\n displayName: `Ctx<tooltipSpec>|${id}`,\n }\n tooltipPlugin.meta = {\n package: '@milkdown/plugin-tooltip',\n displayName: `Prose<tooltip>|${id}`,\n }\n\n return result\n}\n"],"names":["TooltipProvider","options","__privateAdd","_TooltipProvider_instances","_debounce","_shouldShow","_middleware","_floatingUIOptions","_initialized","_offset","_onUpdate","__privateSet","view","prevState","state","composing","selection","doc","ranges","from","range","to","isSame","__privateGet","_a","computePosition","posToDOMRect","flip","offset","shift","x","y","debounce","virtualElement","__privateMethod","_shouldShow_fn","empty","isEmptyTextBlock","TextSelection","isTooltipChildren","notHasFocus","isReadonly","tooltipFactory","id","tooltipSpec","$ctx","tooltipPlugin","$prose","ctx","spec","Plugin","PluginKey","result"],"mappings":"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"}
@@ -2,7 +2,10 @@ import type { SliceType } from '@milkdown/ctx';
2
2
  import type { PluginSpec } from '@milkdown/prose/state';
3
3
  import type { $Ctx, $Prose } from '@milkdown/utils';
4
4
  export type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`;
5
- export type TooltipPlugin<Id extends string, State = any> = [$Ctx<PluginSpec<State>, TooltipSpecId<Id>>, $Prose] & {
5
+ export type TooltipPlugin<Id extends string, State = any> = [
6
+ $Ctx<PluginSpec<State>, TooltipSpecId<Id>>,
7
+ $Prose
8
+ ] & {
6
9
  key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>;
7
10
  pluginKey: $Prose['key'];
8
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip-plugin.d.ts","sourceRoot":"","sources":["../src/tooltip-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAInD,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,MAAM,IAAI,GAAG,EAAE,eAAe,CAAA;AAGnE,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG;IACjH,GAAG,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;IACpD,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;CACzB,CAAA;AAGD,wBAAgB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,0BAsBpE"}
1
+ {"version":3,"file":"tooltip-plugin.d.ts","sourceRoot":"","sources":["../src/tooltip-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAInD,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,MAAM,IAAI,GAAG,EAAE,eAAe,CAAA;AAGnE,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,GAAG,GAAG,IAAI;IAC1D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM;CACP,GAAG;IACF,GAAG,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;IACpD,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;CACzB,CAAA;AAGD,wBAAgB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,GAAG,GAAG,EAAE,EAAE,EAAE,EAAE,0BAyBpE"}
@@ -1,6 +1,6 @@
1
1
  import type { EditorState } from '@milkdown/prose/state';
2
2
  import type { EditorView } from '@milkdown/prose/view';
3
- import type { VirtualElement } from '@floating-ui/dom';
3
+ import type { ComputePositionConfig, Middleware, VirtualElement } from '@floating-ui/dom';
4
4
  export interface TooltipProviderOptions {
5
5
  content: HTMLElement;
6
6
  debounce?: number;
@@ -10,6 +10,8 @@ export interface TooltipProviderOptions {
10
10
  crossAxis?: number;
11
11
  alignmentAxis?: number | null;
12
12
  };
13
+ middleware?: Middleware[];
14
+ floatingUIOptions?: Partial<ComputePositionConfig>;
13
15
  }
14
16
  export declare class TooltipProvider {
15
17
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"tooltip-provider.d.ts","sourceRoot":"","sources":["../src/tooltip-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAKtD,MAAM,WAAW,sBAAsB;IAErC,OAAO,EAAE,WAAW,CAAA;IAEpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,WAAW,KAAK,OAAO,CAAA;IAEnE,MAAM,CAAC,EAAE,MAAM,GAAG;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC9B,CAAA;CACF;AAGD,qBAAa,eAAe;;IAkB1B,OAAO,EAAE,WAAW,CAAA;IAGpB,MAAM,aAAW;IAGjB,MAAM,aAAW;gBAEL,OAAO,EAAE,sBAAsB;IAgD3C,MAAM,SAAU,UAAU,cAAc,WAAW,KAAG,IAAI,CAIzD;IA2BD,OAAO,aAAW;IAGlB,IAAI,oBAAqB,cAAc,UAiBtC;IAGD,IAAI,aAMH;CACF"}
1
+ {"version":3,"file":"tooltip-provider.d.ts","sourceRoot":"","sources":["../src/tooltip-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EACV,qBAAqB,EACrB,UAAU,EACV,cAAc,EACf,MAAM,kBAAkB,CAAA;AAKzB,MAAM,WAAW,sBAAsB;IAErC,OAAO,EAAE,WAAW,CAAA;IAEpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,WAAW,KAAK,OAAO,CAAA;IAEnE,MAAM,CAAC,EACH,MAAM,GACN;QACE,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC9B,CAAA;IAEL,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IAEzB,iBAAiB,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAA;CACnD;AAGD,qBAAa,eAAe;;IA0B1B,OAAO,EAAE,WAAW,CAAA;IAGpB,MAAM,aAAW;IAGjB,MAAM,aAAW;gBAEL,OAAO,EAAE,sBAAsB;IAiD3C,MAAM,SAAU,UAAU,cAAc,WAAW,KAAG,IAAI,CAIzD;IAuBD,OAAO,aAAW;IAGlB,IAAI,oBAAqB,cAAc,UAiBtC;IAGD,IAAI,aAKH;CACF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@milkdown/plugin-tooltip",
3
3
  "type": "module",
4
- "version": "7.5.3",
4
+ "version": "7.5.9",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -35,13 +35,13 @@
35
35
  "lodash.debounce": "^4.0.8",
36
36
  "tippy.js": "^6.3.7",
37
37
  "tslib": "^2.5.0",
38
- "@milkdown/exception": "7.5.0",
39
- "@milkdown/utils": "7.5.0"
38
+ "@milkdown/exception": "7.5.9",
39
+ "@milkdown/utils": "7.5.9"
40
40
  },
41
41
  "devDependencies": {
42
- "@milkdown/core": "7.5.0",
43
- "@milkdown/ctx": "7.5.0",
44
- "@milkdown/prose": "7.5.0"
42
+ "@milkdown/core": "7.5.9",
43
+ "@milkdown/ctx": "7.5.9",
44
+ "@milkdown/prose": "7.5.9"
45
45
  },
46
46
  "nx": {
47
47
  "targets": {
@@ -8,14 +8,20 @@ import { $ctx, $prose } from '@milkdown/utils'
8
8
  export type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`
9
9
 
10
10
  /// @internal
11
- export type TooltipPlugin<Id extends string, State = any> = [$Ctx<PluginSpec<State>, TooltipSpecId<Id>>, $Prose] & {
11
+ export type TooltipPlugin<Id extends string, State = any> = [
12
+ $Ctx<PluginSpec<State>, TooltipSpecId<Id>>,
13
+ $Prose,
14
+ ] & {
12
15
  key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>
13
16
  pluginKey: $Prose['key']
14
17
  }
15
18
 
16
19
  /// Create a tooltip plugin with a unique id.
17
20
  export function tooltipFactory<Id extends string, State = any>(id: Id) {
18
- const tooltipSpec = $ctx<PluginSpec<State>, TooltipSpecId<Id>>({}, `${id}_TOOLTIP_SPEC`)
21
+ const tooltipSpec = $ctx<PluginSpec<State>, TooltipSpecId<Id>>(
22
+ {},
23
+ `${id}_TOOLTIP_SPEC`
24
+ )
19
25
  const tooltipPlugin = $prose((ctx) => {
20
26
  const spec = ctx.get(tooltipSpec.key)
21
27
  return new Plugin({
@@ -2,8 +2,12 @@ import type { EditorState } from '@milkdown/prose/state'
2
2
  import { TextSelection } from '@milkdown/prose/state'
3
3
  import type { EditorView } from '@milkdown/prose/view'
4
4
  import debounce from 'lodash.debounce'
5
- import type { VirtualElement } from '@floating-ui/dom'
6
- import { computePosition, flip, offset } from '@floating-ui/dom'
5
+ import type {
6
+ ComputePositionConfig,
7
+ Middleware,
8
+ VirtualElement,
9
+ } from '@floating-ui/dom'
10
+ import { computePosition, flip, offset, shift } from '@floating-ui/dom'
7
11
  import { posToDOMRect } from '@milkdown/prose'
8
12
 
9
13
  /// Options for tooltip provider.
@@ -15,11 +19,17 @@ export interface TooltipProviderOptions {
15
19
  /// The function to determine whether the tooltip should be shown.
16
20
  shouldShow?: (view: EditorView, prevState?: EditorState) => boolean
17
21
  /// The offset to get the block. Default is 0.
18
- offset?: number | {
19
- mainAxis?: number
20
- crossAxis?: number
21
- alignmentAxis?: number | null
22
- }
22
+ offset?:
23
+ | number
24
+ | {
25
+ mainAxis?: number
26
+ crossAxis?: number
27
+ alignmentAxis?: number | null
28
+ }
29
+ /// Other middlewares for floating ui. This will be added after the internal middlewares.
30
+ middleware?: Middleware[]
31
+ /// Options for floating ui. If you pass `middleware` or `placement`, it will override the internal settings.
32
+ floatingUIOptions?: Partial<ComputePositionConfig>
23
33
  }
24
34
 
25
35
  /// A provider for creating tooltip.
@@ -30,15 +40,23 @@ export class TooltipProvider {
30
40
  /// @internal
31
41
  readonly #shouldShow: (view: EditorView, prevState?: EditorState) => boolean
32
42
 
43
+ /// @internal
44
+ readonly #middleware: Middleware[]
45
+
46
+ /// @internal
47
+ readonly #floatingUIOptions: Partial<ComputePositionConfig>
48
+
33
49
  /// @internal
34
50
  #initialized = false
35
51
 
36
52
  /// @internal
37
- readonly #offset?: number | {
38
- mainAxis?: number
39
- crossAxis?: number
40
- alignmentAxis?: number | null
41
- }
53
+ readonly #offset?:
54
+ | number
55
+ | {
56
+ mainAxis?: number
57
+ crossAxis?: number
58
+ alignmentAxis?: number | null
59
+ }
42
60
 
43
61
  /// The root element of the tooltip.
44
62
  element: HTMLElement
@@ -54,6 +72,8 @@ export class TooltipProvider {
54
72
  this.#debounce = options.debounce ?? 200
55
73
  this.#shouldShow = options.shouldShow ?? this.#_shouldShow
56
74
  this.#offset = options.offset
75
+ this.#middleware = options.middleware ?? []
76
+ this.#floatingUIOptions = options.floatingUIOptions ?? {}
57
77
  this.element.dataset.show = 'false'
58
78
  }
59
79
 
@@ -62,17 +82,17 @@ export class TooltipProvider {
62
82
  const { state, composing } = view
63
83
  const { selection, doc } = state
64
84
  const { ranges } = selection
65
- const from = Math.min(...ranges.map(range => range.$from.pos))
66
- const to = Math.max(...ranges.map(range => range.$to.pos))
67
- const isSame = prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)
85
+ const from = Math.min(...ranges.map((range) => range.$from.pos))
86
+ const to = Math.max(...ranges.map((range) => range.$to.pos))
87
+ const isSame =
88
+ prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)
68
89
 
69
90
  if (!this.#initialized) {
70
91
  view.dom.parentElement?.appendChild(this.element)
71
92
  this.#initialized = true
72
93
  }
73
94
 
74
- if (composing || isSame)
75
- return
95
+ if (composing || isSame) return
76
96
 
77
97
  if (!this.#shouldShow(view, prevState)) {
78
98
  this.hide()
@@ -84,14 +104,13 @@ export class TooltipProvider {
84
104
  }
85
105
  computePosition(virtualEl, this.element, {
86
106
  placement: 'top',
87
- middleware: [flip(), offset(this.#offset)],
88
- })
89
- .then(({ x, y }) => {
90
- Object.assign(this.element.style, {
91
- left: `${x}px`,
92
- top: `${y}px`,
93
- })
107
+ middleware: [flip(), offset(this.#offset), shift(), ...this.#middleware],
108
+ }).then(({ x, y }) => {
109
+ Object.assign(this.element.style, {
110
+ left: `${x}px`,
111
+ top: `${y}px`,
94
112
  })
113
+ })
95
114
 
96
115
  this.show()
97
116
  }
@@ -108,7 +127,9 @@ export class TooltipProvider {
108
127
  const { doc, selection } = view.state
109
128
  const { empty, from, to } = selection
110
129
 
111
- const isEmptyTextBlock = !doc.textBetween(from, to).length && view.state.selection instanceof TextSelection
130
+ const isEmptyTextBlock =
131
+ !doc.textBetween(from, to).length &&
132
+ view.state.selection instanceof TextSelection
112
133
 
113
134
  const isTooltipChildren = this.element.contains(document.activeElement)
114
135
 
@@ -116,13 +137,7 @@ export class TooltipProvider {
116
137
 
117
138
  const isReadonly = !view.editable
118
139
 
119
- if (
120
- notHasFocus
121
- || empty
122
- || isEmptyTextBlock
123
- || isReadonly
124
- )
125
- return false
140
+ if (notHasFocus || empty || isEmptyTextBlock || isReadonly) return false
126
141
 
127
142
  return true
128
143
  }
@@ -138,13 +153,13 @@ export class TooltipProvider {
138
153
  computePosition(virtualElement, this.element, {
139
154
  placement: 'top',
140
155
  middleware: [flip(), offset(this.#offset)],
141
- })
142
- .then(({ x, y }) => {
143
- Object.assign(this.element.style, {
144
- left: `${x}px`,
145
- top: `${y}px`,
146
- })
156
+ ...this.#floatingUIOptions,
157
+ }).then(({ x, y }) => {
158
+ Object.assign(this.element.style, {
159
+ left: `${x}px`,
160
+ top: `${y}px`,
147
161
  })
162
+ })
148
163
  }
149
164
 
150
165
  this.onShow()
@@ -152,8 +167,7 @@ export class TooltipProvider {
152
167
 
153
168
  /// Hide the tooltip.
154
169
  hide = () => {
155
- if (this.element.dataset.show === 'false')
156
- return
170
+ if (this.element.dataset.show === 'false') return
157
171
  this.element.dataset.show = 'false'
158
172
 
159
173
  this.onHide()