@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 +54 -52
- package/lib/index.es.js.map +1 -1
- package/lib/tooltip-plugin.d.ts +4 -1
- package/lib/tooltip-plugin.d.ts.map +1 -1
- package/lib/tooltip-provider.d.ts +3 -1
- package/lib/tooltip-provider.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/tooltip-plugin.ts +8 -2
- package/src/tooltip-provider.ts +54 -40
package/lib/index.es.js
CHANGED
|
@@ -1,81 +1,83 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
throw TypeError("Cannot " + e);
|
|
1
|
+
var S = (o) => {
|
|
2
|
+
throw TypeError(o);
|
|
4
3
|
};
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
16
|
+
n(this, r);
|
|
21
17
|
/// @internal
|
|
22
|
-
|
|
18
|
+
n(this, d);
|
|
23
19
|
/// @internal
|
|
24
|
-
|
|
25
|
-
l(this, c, void 0);
|
|
20
|
+
n(this, u);
|
|
26
21
|
/// @internal
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
},
|
|
32
|
-
var
|
|
33
|
-
const { state:
|
|
34
|
-
if (
|
|
35
|
-
|
|
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
|
-
|
|
41
|
-
getBoundingClientRect: () =>
|
|
37
|
+
C({
|
|
38
|
+
getBoundingClientRect: () => q(e, k, O)
|
|
42
39
|
}, this.element, {
|
|
43
40
|
placement: "top",
|
|
44
|
-
middleware: [
|
|
45
|
-
}).then(({ x:
|
|
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: `${
|
|
48
|
-
top: `${
|
|
44
|
+
left: `${p}px`,
|
|
45
|
+
top: `${F}px`
|
|
49
46
|
});
|
|
50
47
|
}), this.show();
|
|
51
48
|
}), this.update = (e, s) => {
|
|
52
|
-
|
|
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 &&
|
|
52
|
+
this.element.dataset.show = "true", e && C(e, this.element, {
|
|
56
53
|
placement: "top",
|
|
57
|
-
middleware: [
|
|
58
|
-
|
|
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: `${
|
|
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,
|
|
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(),
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
74
|
-
const t =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
+
V as TooltipProvider,
|
|
93
|
+
W as tooltipFactory
|
|
92
94
|
};
|
|
93
95
|
//# sourceMappingURL=index.es.js.map
|
package/lib/index.es.js.map
CHANGED
|
@@ -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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"}
|
package/lib/tooltip-plugin.d.ts
CHANGED
|
@@ -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> = [
|
|
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,
|
|
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,
|
|
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.
|
|
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.
|
|
39
|
-
"@milkdown/utils": "7.5.
|
|
38
|
+
"@milkdown/exception": "7.5.9",
|
|
39
|
+
"@milkdown/utils": "7.5.9"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@milkdown/core": "7.5.
|
|
43
|
-
"@milkdown/ctx": "7.5.
|
|
44
|
-
"@milkdown/prose": "7.5.
|
|
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": {
|
package/src/tooltip-plugin.ts
CHANGED
|
@@ -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> = [
|
|
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>>(
|
|
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({
|
package/src/tooltip-provider.ts
CHANGED
|
@@ -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 {
|
|
6
|
-
|
|
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?:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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?:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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 =
|
|
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
|
-
.
|
|
90
|
-
|
|
91
|
-
|
|
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 =
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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()
|