@milkdown/plugin-tooltip 6.5.4 → 7.0.0-next.1

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 (45) hide show
  1. package/lib/index.d.ts +2 -7
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.es.js +75 -190
  4. package/lib/index.es.js.map +1 -1
  5. package/lib/tooltip-plugin.d.ts +10 -0
  6. package/lib/tooltip-plugin.d.ts.map +1 -0
  7. package/lib/tooltip-provider.d.ts +20 -0
  8. package/lib/tooltip-provider.d.ts.map +1 -0
  9. package/package.json +12 -8
  10. package/src/index.ts +2 -44
  11. package/src/tooltip-plugin.ts +32 -0
  12. package/src/tooltip-provider.ts +127 -0
  13. package/lib/button-manager/calc-button-pos.d.ts +0 -3
  14. package/lib/button-manager/calc-button-pos.d.ts.map +0 -1
  15. package/lib/button-manager/create-tooltip.d.ts +0 -10
  16. package/lib/button-manager/create-tooltip.d.ts.map +0 -1
  17. package/lib/button-manager/filter-button.d.ts +0 -4
  18. package/lib/button-manager/filter-button.d.ts.map +0 -1
  19. package/lib/button-manager/index.d.ts +0 -10
  20. package/lib/button-manager/index.d.ts.map +0 -1
  21. package/lib/button-manager/no-active.d.ts +0 -4
  22. package/lib/button-manager/no-active.d.ts.map +0 -1
  23. package/lib/button-manager/style.d.ts +0 -3
  24. package/lib/button-manager/style.d.ts.map +0 -1
  25. package/lib/item.d.ts +0 -31
  26. package/lib/item.d.ts.map +0 -1
  27. package/lib/selection-marks-tooltip.d.ts +0 -12
  28. package/lib/selection-marks-tooltip.d.ts.map +0 -1
  29. package/lib/utility/element.d.ts +0 -2
  30. package/lib/utility/element.d.ts.map +0 -1
  31. package/lib/utility/index.d.ts +0 -3
  32. package/lib/utility/index.d.ts.map +0 -1
  33. package/lib/utility/prosemirror.d.ts +0 -12
  34. package/lib/utility/prosemirror.d.ts.map +0 -1
  35. package/src/button-manager/calc-button-pos.ts +0 -29
  36. package/src/button-manager/create-tooltip.ts +0 -33
  37. package/src/button-manager/filter-button.ts +0 -28
  38. package/src/button-manager/index.ts +0 -50
  39. package/src/button-manager/no-active.ts +0 -10
  40. package/src/button-manager/style.ts +0 -51
  41. package/src/item.ts +0 -67
  42. package/src/selection-marks-tooltip.ts +0 -50
  43. package/src/utility/element.ts +0 -3
  44. package/src/utility/index.ts +0 -3
  45. package/src/utility/prosemirror.ts +0 -42
package/lib/index.d.ts CHANGED
@@ -1,8 +1,3 @@
1
- import { PluginKey } from '@milkdown/prose/state';
2
- import { AtomList } from '@milkdown/utils';
3
- import type { TooltipOptions } from './item';
4
- export declare const key: PluginKey<any>;
5
- export * from './item';
6
- export declare const tooltipPlugin: import("@milkdown/utils").WithExtend<string, TooltipOptions, import("@milkdown/utils").TypeMapping<string, string>, import("@milkdown/utils").PluginRest<string, string>>;
7
- export declare const tooltip: AtomList<import("@milkdown/utils").Metadata<import("@milkdown/utils").GetPlugin<string, TooltipOptions>> & import("@milkdown/core").MilkdownPlugin>;
1
+ export * from './tooltip-provider';
2
+ export * from './tooltip-plugin';
8
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,QAAQ,EAA0B,MAAM,iBAAiB,CAAA;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAI5C,eAAO,MAAM,GAAG,gBAAoC,CAAA;AACpD,cAAc,QAAQ,CAAA;AAEtB,eAAO,MAAM,aAAa,2KA+BxB,CAAA;AAEF,eAAO,MAAM,OAAO,qJAAqC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA"}
package/lib/index.es.js CHANGED
@@ -1,196 +1,81 @@
1
- import { TextSelection as p, PluginKey as T, Plugin as v } from "@milkdown/prose/state";
2
- import { createPlugin as $, AtomList as y } from "@milkdown/utils";
3
- import { schemaCtx as b, themeManagerCtx as L, ThemeIcon as k, commandsCtx as P, ThemeSize as h, ThemeBorder as E, ThemeShadow as x, ThemeColor as B } from "@milkdown/core";
4
- import { findParentNode as C, calculateTextPosition as M } from "@milkdown/prose";
5
- import { missingRootElement as A } from "@milkdown/exception";
6
- const m = (e, t) => {
7
- if (!t)
8
- return !1;
9
- const { from: o, to: s } = e.selection;
10
- return e.doc.rangeHasMark(o, o === s ? s + 1 : s, t);
11
- }, H = (e) => {
12
- const { selection: t } = e;
13
- return t instanceof p ? !!e.doc.textBetween(t.from, t.to) : !1;
14
- }, I = (e) => Boolean(C((t) => !!t.type.spec.code)(e.selection)), O = (e, t) => !H(e) || I(e) || m(e, t), u = (e, t, o, s) => ({
15
- icon: e,
16
- onClick: t,
17
- isHidden: () => (n) => O(n.state, s),
18
- isActive: () => (n) => m(n.state, o),
19
- canAddToDOM: () => (n) => !!o && !!n.state.schema.marks[o.name]
20
- }), w = (e) => {
21
- const t = e.get(b).marks;
22
- return [
23
- u("bold", "ToggleBold", t.strong),
24
- u("italic", "ToggleItalic", t.em),
25
- u("strikeThrough", "ToggleStrikeThrough", t.strike_through),
26
- u("code", "ToggleInlineCode", t.code_inline),
27
- u("link", "ToggleLink", t.link)
28
- ];
29
- }, D = (e, t = w) => {
30
- const o = ({ icon: s, onClick: n, isHidden: l, isActive: i, canAddToDOM: c }) => {
31
- var r;
32
- return {
33
- $: typeof s == "function" ? s(e) : (r = e.get(L).get(k, s)) == null ? void 0 : r.dom,
34
- command: typeof n == "string" ? () => e.get(P).call(n) : n(e),
35
- disable: l(e),
36
- active: i(e),
37
- enable: c(e)
38
- };
39
- };
40
- return t(e).map(o);
41
- }, W = (e, t, o) => {
42
- e.classList.remove("hide"), M(t, e, (s, n, l, i) => {
43
- const c = e.parentElement;
44
- if (!c)
45
- throw A();
46
- const r = n.left - s.left;
47
- let a = s.left - i.left - (l.width - r) / 2, d = s.top - i.top - l.height - 14 + c.scrollTop;
48
- a < 0 && (a = 0);
49
- const f = c.clientWidth - (l.width + 4);
50
- return a > f && (a = f), (d < c.scrollTop || o && i.bottom - s.bottom > l.height) && (d = s.bottom - i.top + 14 + c.scrollTop), [d, a];
51
- });
52
- }, q = (e, { css: t }) => {
53
- const o = (n, l = 1) => e.get(B, [n, l]), s = e.get(h, "lineWidth");
54
- return t`
55
- display: inline-flex;
56
- cursor: pointer;
57
- justify-content: space-evenly;
58
- position: absolute;
59
- border-radius: ${e.get(h, "radius")};
60
- z-index: 2;
61
-
62
- ${e.get(E, void 0)}
63
- ${e.get(x, void 0)}
64
-
65
- overflow: hidden;
66
- background: ${o("surface")};
67
-
68
- .icon {
69
- position: relative;
70
- color: ${o("solid", 0.87)};
71
-
72
- width: 48px;
73
- line-height: 48px;
74
- text-align: center;
75
- transition: all 0.4s ease-in-out;
76
- &:hover {
77
- background-color: ${o("secondary", 0.12)};
78
- }
79
- &.active {
80
- color: ${o("primary")};
81
- }
82
- &:not(:last-child)::after {
83
- content: '';
84
- position: absolute;
85
- top: 0;
86
- right: calc(-0.5 * ${s});
87
- width: ${s};
88
- bottom: 0;
89
- background: ${o("line")};
90
- }
91
- }
92
- &.hide,
93
- .hide {
94
- display: none;
1
+ var R = Object.defineProperty;
2
+ var S = (o, t, e) => t in o ? R(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
3
+ var c = (o, t, e) => (S(o, typeof t != "symbol" ? t + "" : t, e), e), x = (o, t, e) => {
4
+ if (!t.has(o))
5
+ throw TypeError("Cannot " + e);
6
+ };
7
+ var n = (o, t, e) => (x(o, t, "read from private field"), e ? e.call(o) : t.get(o)), r = (o, t, e) => {
8
+ if (t.has(o))
9
+ throw TypeError("Cannot add the same private member more than once");
10
+ t instanceof WeakSet ? t.add(o) : t.set(o, e);
11
+ }, p = (o, t, e, s) => (x(o, t, "write to private field"), s ? s.call(o, e) : t.set(o, e), e);
12
+ var $ = (o, t, e) => (x(o, t, "access private method"), e);
13
+ import { posToDOMRect as _ } from "@milkdown/prose";
14
+ import { TextSelection as w, Plugin as C, PluginKey as E } from "@milkdown/prose/state";
15
+ import F from "lodash.debounce";
16
+ import I from "tippy.js";
17
+ import { $ctx as M, $prose as q } from "@milkdown/utils";
18
+ var i, m, u, a, y, f, b;
19
+ class j {
20
+ constructor(t) {
21
+ r(this, f);
22
+ r(this, i, void 0);
23
+ r(this, m, void 0);
24
+ r(this, u, void 0);
25
+ r(this, a, void 0);
26
+ c(this, "element");
27
+ r(this, y, (t, e) => {
28
+ const { state: s, composing: l } = t, { selection: h, doc: g } = s, { ranges: d } = h, T = Math.min(...d.map((k) => k.$from.pos)), P = Math.max(...d.map((k) => k.$to.pos)), O = e && e.doc.eq(g) && e.selection.eq(h);
29
+ if (n(this, i) ?? p(this, i, I(t.dom, {
30
+ trigger: "manual",
31
+ interactive: !0,
32
+ ...n(this, m),
33
+ content: this.element
34
+ })), !(l || O)) {
35
+ if (!n(this, a).call(this, t, e)) {
36
+ this.hide();
37
+ return;
95
38
  }
96
- `;
97
- }, N = (e, t, o) => {
98
- const s = document.createElement("div");
99
- return t.themeManager.onFlush(() => {
100
- const n = t.getStyle((l) => q(t.themeManager, l)) || "";
101
- n && s.classList.add(n);
102
- }), s.classList.add(t.getClassName({}, o)), {
103
- dom: s,
104
- render: (n) => {
105
- var l;
106
- e.filter((i) => i.enable(n) && i.$ != null).forEach(({ $: i }) => s.appendChild(i)), (l = n.dom.parentNode) == null || l.appendChild(s);
107
- }
108
- };
109
- }, _ = (e, t) => Object.values(e).filter((o) => o.enable(t) && o.$ != null).every(({ $: o }) => o.classList.contains("hide")), j = (e, t) => (e.filter((o) => o.enable(t) && o.$ != null).forEach((o) => {
110
- var l;
111
- if ((l = o.disable) == null ? void 0 : l.call(o, t)) {
112
- o.$.classList.add("hide");
113
- return;
114
- }
115
- if (o.$.classList.remove("hide"), o.active(t)) {
116
- o.$.classList.add("active");
117
- return;
118
- }
119
- o.$.classList.remove("active");
120
- }), _(e, t)), g = (e, t, o, s) => {
121
- const { dom: n, render: l } = N(e, t, s), i = (r) => {
122
- const a = e.find(({ $: d }) => r.target instanceof Element && d.contains(r.target));
123
- !a || (r.stopPropagation(), r.preventDefault(), a.command());
124
- }, c = () => {
125
- n.classList.add("hide");
126
- };
127
- return n.addEventListener("mousedown", i), {
128
- destroy: () => {
129
- n.removeEventListener("mousedown", i), n.remove();
130
- },
131
- hide: c,
132
- update: (r) => {
133
- if (j(e, r)) {
134
- c();
135
- return;
39
+ n(this, i).setProps({
40
+ getReferenceClientRect: () => _(t, T, P)
41
+ }), this.show();
136
42
  }
137
- W(n, r, o);
138
- },
139
- render: l
140
- };
141
- }, z = (e, t, o, s) => {
142
- let n = g(e, t, o, s), l = !1;
143
- const i = () => {
144
- n.hide();
145
- }, c = (r, a) => {
146
- const { state: d } = r;
147
- if (!r.editable || l) {
148
- i();
149
- return;
150
- }
151
- (a == null ? void 0 : a.doc.eq(d.doc)) && a.selection.eq(d.selection) || n.update(r);
152
- };
153
- return {
154
- recreate: (r) => {
155
- n = g(e, t, o, s), n.render(r), c(r);
156
- },
157
- update: c,
158
- destroy: () => {
159
- n.destroy();
160
- },
161
- render: (r) => {
162
- n.render(r), c(r);
163
- },
164
- setHide: (r) => {
165
- l = r;
166
- }
167
- };
168
- }, F = new T("MILKDOWN_TOOLTIP"), K = $((e, t) => ({
169
- id: "tooltip",
170
- prosePlugins: (o, s) => {
171
- var i;
172
- const n = z(D(s, t == null ? void 0 : t.items), e, (i = t == null ? void 0 : t.bottom) != null ? i : !1, "tooltip");
173
- return [new v({
174
- key: F,
175
- props: {
176
- handleClick: (c) => (n.setHide(!1), n.update(c), !1),
177
- handleDOMEvents: {
178
- mousedown: () => (n.setHide(!1), !1)
179
- }
180
- },
181
- view: (c) => (n.recreate(c), {
182
- update: n.update,
183
- destroy: n.destroy
184
- })
185
- })];
43
+ });
44
+ c(this, "update", (t, e) => {
45
+ F(n(this, y), n(this, u))(t, e);
46
+ });
47
+ c(this, "destroy", () => {
48
+ var t;
49
+ (t = n(this, i)) == null || t.destroy();
50
+ });
51
+ c(this, "show", () => {
52
+ var t;
53
+ (t = n(this, i)) == null || t.show();
54
+ });
55
+ c(this, "hide", () => {
56
+ var t;
57
+ (t = n(this, i)) == null || t.hide();
58
+ });
59
+ c(this, "getInstance", () => n(this, i));
60
+ this.element = t.content, p(this, m, t.tippyOptions ?? {}), p(this, u, t.debounce ?? 200), p(this, a, t.shouldShow ?? $(this, f, b));
186
61
  }
187
- })), U = y.create([K()]);
62
+ }
63
+ i = new WeakMap(), m = new WeakMap(), u = new WeakMap(), a = new WeakMap(), y = new WeakMap(), f = new WeakSet(), b = function(t) {
64
+ const { doc: e, selection: s } = t.state, { empty: l, from: h, to: g } = s, d = !e.textBetween(h, g).length && t.state.selection instanceof w, T = this.element.contains(document.activeElement), P = !t.hasFocus() && !T, O = !t.editable;
65
+ return !(P || l || d || O);
66
+ };
67
+ const z = (o) => {
68
+ const t = M({}, `${o}_TOOLTIP_SPEC`), e = q((l) => {
69
+ const h = l.get(t.key);
70
+ return new C({
71
+ key: new E(`${o}_TOOLTIP`),
72
+ ...h
73
+ });
74
+ }), s = [t, e];
75
+ return s.key = t.key, s.pluginKey = e.key, s;
76
+ };
188
77
  export {
189
- D as buttonMap,
190
- u as createToggleIcon,
191
- w as defaultButtons,
192
- F as key,
193
- U as tooltip,
194
- K as tooltipPlugin
78
+ j as TooltipProvider,
79
+ z as tooltipFactory
195
80
  };
196
81
  //# sourceMappingURL=index.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/utility/prosemirror.ts","../src/item.ts","../src/button-manager/calc-button-pos.ts","../src/button-manager/style.ts","../src/button-manager/create-tooltip.ts","../src/button-manager/no-active.ts","../src/button-manager/filter-button.ts","../src/button-manager/index.ts","../src/selection-marks-tooltip.ts","../src/index.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport { findParentNode } from '@milkdown/prose'\nimport type { MarkType, Node, NodeType } from '@milkdown/prose/model'\nimport type { EditorState } from '@milkdown/prose/state'\nimport { TextSelection } from '@milkdown/prose/state'\n\nexport interface Position {\n start: number\n end: number\n}\n\nexport const hasMark = (editorState: EditorState, type?: MarkType): boolean => {\n if (!type)\n return false\n\n const { from, to } = editorState.selection\n\n return editorState.doc.rangeHasMark(from, from === to ? to + 1 : to, type)\n}\n\nexport const isTextSelection = (editorState: EditorState): boolean => {\n const { selection } = editorState\n if (selection instanceof TextSelection) {\n const text = editorState.doc.textBetween(selection.from, selection.to)\n\n if (!text)\n return false\n\n return true\n }\n return false\n}\n\nexport const isInCodeFence = (editorState: EditorState): boolean =>\n Boolean(findParentNode(node => !!node.type.spec.code)(editorState.selection))\n\nexport const isTextAndNotHasMark = (editorState: EditorState, mark?: MarkType): boolean =>\n !isTextSelection(editorState) || isInCodeFence(editorState) || hasMark(editorState, mark)\n\nexport const equalNodeType = (nodeType: NodeType, node: Node) => {\n return (Array.isArray(nodeType) && nodeType.includes(node.type)) || node.type === nodeType\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Ctx } from '@milkdown/core'\nimport { ThemeIcon, commandsCtx, schemaCtx, themeManagerCtx } from '@milkdown/core'\nimport type { Icon } from '@milkdown/design-system'\nimport type { MarkType } from '@milkdown/prose/model'\nimport type { EditorView } from '@milkdown/prose/view'\n\nimport { hasMark, isTextAndNotHasMark } from './utility'\n\nexport type Pred = (view: EditorView) => boolean\nexport type Updater = (view: EditorView, $: HTMLElement) => void\nexport type Event2Command = (e: Event) => void\n\nexport type OnClick = (ctx: Ctx) => void\n\nexport interface Item {\n icon: Icon | ((ctx: Ctx) => HTMLElement)\n onClick: string | ((ctx: Ctx) => () => void)\n isHidden: (ctx: Ctx) => Pred\n isActive: (ctx: Ctx) => Pred\n canAddToDOM: (ctx: Ctx) => Pred\n}\n\nexport interface ButtonItem {\n $: HTMLElement\n command: () => void\n active: Pred\n disable?: Pred\n enable: Pred\n}\n\nexport const createToggleIcon = (icon: Icon, onClick: string, mark?: MarkType, disableForMark?: MarkType): Item => ({\n icon,\n onClick,\n isHidden: () => (view: EditorView) => isTextAndNotHasMark(view.state, disableForMark),\n isActive: () => (view: EditorView) => hasMark(view.state, mark),\n canAddToDOM: () => (view: EditorView) => !!mark && !!view.state.schema.marks[mark.name],\n})\n\nexport const defaultButtons = (ctx: Ctx) => {\n const marks = ctx.get(schemaCtx).marks\n return [\n createToggleIcon('bold', 'ToggleBold', marks.strong),\n createToggleIcon('italic', 'ToggleItalic', marks.em),\n createToggleIcon('strikeThrough', 'ToggleStrikeThrough', marks.strike_through),\n createToggleIcon('code', 'ToggleInlineCode', marks.code_inline),\n createToggleIcon('link', 'ToggleLink', marks.link),\n ]\n}\n\nexport type ButtonList = ButtonItem[]\n\nexport interface TooltipOptions {\n bottom: boolean\n items: (ctx: Ctx) => Array<Item>\n}\n\nexport const buttonMap = (ctx: Ctx, items: (ctx: Ctx) => Array<Item> = defaultButtons): ButtonList => {\n const toButton = ({ icon, onClick, isHidden, isActive, canAddToDOM }: Item): ButtonItem => ({\n $: typeof icon === 'function' ? icon(ctx) : (ctx.get(themeManagerCtx).get(ThemeIcon, icon)?.dom as HTMLElement),\n command: typeof onClick === 'string' ? () => ctx.get(commandsCtx).call(onClick) : onClick(ctx),\n disable: isHidden(ctx),\n active: isActive(ctx),\n enable: canAddToDOM(ctx),\n })\n return items(ctx).map(toButton)\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { missingRootElement } from '@milkdown/exception'\nimport { calculateTextPosition } from '@milkdown/prose'\nimport type { EditorView } from '@milkdown/prose/view'\n\nexport const calcButtonPos = (buttons: HTMLElement, view: EditorView, isBottom: boolean) => {\n buttons.classList.remove('hide')\n calculateTextPosition(view, buttons, (start, end, target, parent) => {\n const $editor = buttons.parentElement\n if (!$editor)\n throw missingRootElement()\n\n const selectionWidth = end.left - start.left\n let left = start.left - parent.left - (target.width - selectionWidth) / 2\n let top = start.top - parent.top - target.height - 14 + $editor.scrollTop\n\n if (left < 0)\n left = 0\n\n const maxLeft = $editor.clientWidth - (target.width + 4)\n if (left > maxLeft)\n left = maxLeft\n\n if (top < $editor.scrollTop || (isBottom && parent.bottom - start.bottom > target.height))\n top = start.bottom - parent.top + 14 + $editor.scrollTop\n\n return [top, left]\n })\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { Color, Emotion, ThemeManager } from '@milkdown/core'\nimport { ThemeBorder, ThemeColor, ThemeShadow, ThemeSize } from '@milkdown/core'\n\nexport const injectStyle = (themeManager: ThemeManager, { css }: Emotion) => {\n const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity])\n const lineWidth = themeManager.get(ThemeSize, 'lineWidth')\n return css`\n display: inline-flex;\n cursor: pointer;\n justify-content: space-evenly;\n position: absolute;\n border-radius: ${themeManager.get(ThemeSize, 'radius')};\n z-index: 2;\n\n ${themeManager.get(ThemeBorder, undefined)}\n ${themeManager.get(ThemeShadow, undefined)}\n\n overflow: hidden;\n background: ${palette('surface')};\n\n .icon {\n position: relative;\n color: ${palette('solid', 0.87)};\n\n width: 48px;\n line-height: 48px;\n text-align: center;\n transition: all 0.4s ease-in-out;\n &:hover {\n background-color: ${palette('secondary', 0.12)};\n }\n &.active {\n color: ${palette('primary')};\n }\n &:not(:last-child)::after {\n content: '';\n position: absolute;\n top: 0;\n right: calc(-0.5 * ${lineWidth});\n width: ${lineWidth};\n bottom: 0;\n background: ${palette('line')};\n }\n }\n &.hide,\n .hide {\n display: none;\n }\n `\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { EditorView } from '@milkdown/prose/view'\nimport type { ThemeUtils } from '@milkdown/utils'\n\nimport type { ButtonList } from '../item'\nimport { injectStyle } from './style'\n\ninterface Tooltip {\n dom: HTMLDivElement\n render: (editorView: EditorView) => void\n}\n\nexport const createTooltip = (buttonMap: ButtonList, utils: ThemeUtils, className: string): Tooltip => {\n const div = document.createElement('div')\n utils.themeManager.onFlush(() => {\n const style = utils.getStyle(emotion => injectStyle(utils.themeManager, emotion)) || ''\n if (style)\n div.classList.add(style)\n })\n\n div.classList.add(utils.getClassName({}, className))\n\n return {\n dom: div,\n render: (editorView: EditorView) => {\n buttonMap\n .filter(item => item.enable(editorView) && item.$ != null)\n .forEach(({ $ }) => div.appendChild($))\n\n editorView.dom.parentNode?.appendChild(div)\n },\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { EditorView } from '@milkdown/prose/view'\n\nimport type { ButtonList } from '../item'\n\nexport const noActive = (buttonMap: ButtonList, view: EditorView) => {\n return Object.values(buttonMap)\n .filter(item => item.enable(view) && item.$ != null)\n .every(({ $ }) => $.classList.contains('hide'))\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { EditorView } from '@milkdown/prose/view'\n\nimport type { ButtonList } from '../item'\nimport { noActive } from './no-active'\n\nexport const filterButton = (buttons: ButtonList, view: EditorView) => {\n buttons\n .filter(item => item.enable(view) && item.$ != null)\n .forEach((item) => {\n const disable = item.disable?.(view)\n if (disable) {\n item.$.classList.add('hide')\n return\n }\n\n item.$.classList.remove('hide')\n\n const active = item.active(view)\n if (active) {\n item.$.classList.add('active')\n return\n }\n item.$.classList.remove('active')\n })\n\n return noActive(buttons, view)\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { EditorView } from '@milkdown/prose/view'\nimport type { ThemeUtils } from '@milkdown/utils'\n\nimport type { ButtonList } from '../item'\nimport { calcButtonPos } from './calc-button-pos'\nimport { createTooltip } from './create-tooltip'\nimport { filterButton } from './filter-button'\n\nexport const createButtonManager = (\n buttons: ButtonList,\n utils: ThemeUtils,\n bottom: boolean,\n containerClassName: string,\n) => {\n const { dom: buttonDOM, render } = createTooltip(buttons, utils, containerClassName)\n\n const onClick = (e: Event) => {\n const target = buttons.find(({ $ }) => e.target instanceof Element && $.contains(e.target))\n if (!target)\n return\n\n e.stopPropagation()\n e.preventDefault()\n target.command()\n }\n\n const hide = () => {\n buttonDOM.classList.add('hide')\n }\n\n buttonDOM.addEventListener('mousedown', onClick)\n\n return {\n destroy: () => {\n buttonDOM.removeEventListener('mousedown', onClick)\n buttonDOM.remove()\n },\n hide,\n update: (editorView: EditorView) => {\n const noActive = filterButton(buttons, editorView)\n if (noActive) {\n hide()\n return\n }\n calcButtonPos(buttonDOM, editorView, bottom)\n },\n render,\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport type { EditorState } from '@milkdown/prose/state'\nimport type { EditorView } from '@milkdown/prose/view'\nimport type { ThemeUtils } from '@milkdown/utils'\n\nimport { createButtonManager } from './button-manager'\nimport type { ButtonList } from './item'\n\nexport const createPlugin = (buttonMap: ButtonList, utils: ThemeUtils, bottom: boolean, containerClassName: string) => {\n let buttonManager = createButtonManager(buttonMap, utils, bottom, containerClassName)\n let shouldHide = false\n\n const hide = () => {\n buttonManager.hide()\n }\n\n const update = (view: EditorView, prevState?: EditorState) => {\n const { state } = view\n\n if (!view.editable || shouldHide) {\n hide()\n return\n }\n\n const isEqualSelection = prevState?.doc.eq(state.doc) && prevState.selection.eq(state.selection)\n if (isEqualSelection)\n return\n\n buttonManager.update(view)\n }\n\n return {\n recreate: (editorView: EditorView) => {\n buttonManager = createButtonManager(buttonMap, utils, bottom, containerClassName)\n buttonManager.render(editorView)\n update(editorView)\n },\n update,\n destroy: () => {\n buttonManager.destroy()\n },\n render: (editorView: EditorView) => {\n buttonManager.render(editorView)\n update(editorView)\n },\n setHide: (isTyping: boolean) => {\n shouldHide = isTyping\n },\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport { Plugin, PluginKey } from '@milkdown/prose/state'\nimport { AtomList, createPlugin as create } from '@milkdown/utils'\n\nimport type { TooltipOptions } from './item'\nimport { buttonMap } from './item'\nimport { createPlugin } from './selection-marks-tooltip'\n\nexport const key = new PluginKey('MILKDOWN_TOOLTIP')\nexport * from './item'\n\nexport const tooltipPlugin = create<string, TooltipOptions>((utils, options) => {\n return {\n id: 'tooltip',\n prosePlugins: (_, ctx) => {\n const manager = createPlugin(buttonMap(ctx, options?.items), utils, options?.bottom ?? false, 'tooltip')\n const plugin = new Plugin({\n key,\n props: {\n handleClick: (view) => {\n manager.setHide(false)\n manager.update(view)\n return false\n },\n handleDOMEvents: {\n mousedown: () => {\n manager.setHide(false)\n return false\n },\n },\n },\n view: (editorView) => {\n manager.recreate(editorView)\n return {\n update: manager.update,\n destroy: manager.destroy,\n }\n },\n })\n return [plugin]\n },\n }\n})\n\nexport const tooltip = AtomList.create([tooltipPlugin()])\n"],"names":["hasMark","editorState","type","from","to","isTextSelection","selection","TextSelection","isInCodeFence","findParentNode","node","isTextAndNotHasMark","mark","createToggleIcon","icon","onClick","disableForMark","view","defaultButtons","ctx","marks","schemaCtx","buttonMap","items","toButton","isHidden","isActive","canAddToDOM","_a","themeManagerCtx","ThemeIcon","commandsCtx","calcButtonPos","buttons","isBottom","calculateTextPosition","start","end","target","parent","$editor","missingRootElement","selectionWidth","left","top","maxLeft","injectStyle","themeManager","css","palette","color","opacity","ThemeColor","lineWidth","ThemeSize","ThemeBorder","ThemeShadow","createTooltip","utils","className","div","style","emotion","editorView","item","$","noActive","filterButton","createButtonManager","bottom","containerClassName","buttonDOM","render","e","hide","createPlugin","buttonManager","shouldHide","update","prevState","state","isTyping","key","PluginKey","tooltipPlugin","create","options","_","manager","Plugin","tooltip","AtomList"],"mappings":"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"}
1
+ {"version":3,"file":"index.es.js","sources":["../src/tooltip-provider.ts","../src/tooltip-plugin.ts"],"sourcesContent":["/* Copyright 2021, Milkdown by Mirone. */\nimport { posToDOMRect } from '@milkdown/prose'\nimport 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 { Instance, Props } from 'tippy.js'\nimport tippy from 'tippy.js'\n\n/// Options for tooltip provider.\nexport type TooltipProviderOptions = {\n /// The tooltip content.\n content: HTMLElement\n /// The options for creating [tippy.js](https://atomiks.github.io/tippyjs/) instance.\n tippyOptions?: Partial<Props>\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}\n\n/// A provider for creating tooltip.\nexport class TooltipProvider {\n /// @internal\n #tippy: Instance | undefined\n\n /// @internal\n #tippyOptions: Partial<Props>\n\n /// @internal\n #debounce: number\n\n /// @internal\n #shouldShow: (view: EditorView, prevState?: EditorState) => boolean\n\n /// The root element of the tooltip.\n element: HTMLElement\n\n constructor(options: TooltipProviderOptions) {\n this.element = options.content\n this.#tippyOptions = options.tippyOptions ?? {}\n this.#debounce = options.debounce ?? 200\n this.#shouldShow = options.shouldShow ?? this.#_shouldShow\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 this.#tippy ??= tippy(view.dom, {\n trigger: 'manual',\n interactive: true,\n ...this.#tippyOptions,\n content: this.element,\n })\n\n if (composing || isSame)\n return\n\n if (!this.#shouldShow(view, prevState)) {\n this.hide()\n return\n }\n\n this.#tippy.setProps({\n getReferenceClientRect: () => posToDOMRect(view, from, to),\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 this.#tippy?.destroy()\n }\n\n /// Show the tooltip.\n show = () => {\n this.#tippy?.show()\n }\n\n /// Hide the tooltip.\n hide = () => {\n this.#tippy?.hide()\n }\n\n /// Get the [tippy.js](https://atomiks.github.io/tippyjs/) instance.\n getInstance = () => {\n return this.#tippy\n }\n}\n","/* Copyright 2021, Milkdown by Mirone. */\nimport 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 const 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\n return result\n}\n"],"names":["TooltipProvider","options","__privateAdd","__shouldShow","_tippy","_tippyOptions","_debounce","_shouldShow","__publicField","_onUpdate","view","prevState","state","composing","selection","doc","ranges","from","range","to","isSame","__privateGet","__privateSet","tippy","posToDOMRect","debounce","_a","__privateMethod","_shouldShow_fn","empty","isEmptyTextBlock","TextSelection","isTooltipChildren","notHasFocus","isReadonly","tooltipFactory","id","tooltipSpec","$ctx","tooltipPlugin","$prose","ctx","spec","Plugin","PluginKey","result"],"mappings":";;;;;;;;;;;;;;;;;;AAsBO,MAAMA,EAAgB;AAAA,EAgB3B,YAAYC,GAAiC;AA8C7C,IAAAC,EAAA,MAAAC;AA5DA,IAAAD,EAAA,MAAAE,GAAA;AAGA,IAAAF,EAAA,MAAAG,GAAA;AAGA,IAAAH,EAAA,MAAAI,GAAA;AAGA,IAAAJ,EAAA,MAAAK,GAAA;AAGA,IAAAC,EAAA;AAUA,IAAAN,EAAA,MAAAO,GAAY,CAACC,GAAkBC,MAAkC;AACzD,YAAA,EAAE,OAAAC,GAAO,WAAAC,EAAc,IAAAH,GACvB,EAAE,WAAAI,GAAW,KAAAC,EAAQ,IAAAH,GACrB,EAAE,QAAAI,EAAW,IAAAF,GACbG,IAAO,KAAK,IAAI,GAAGD,EAAO,IAAI,CAASE,MAAAA,EAAM,MAAM,GAAG,CAAC,GACvDC,IAAK,KAAK,IAAI,GAAGH,EAAO,IAAI,CAASE,MAAAA,EAAM,IAAI,GAAG,CAAC,GACnDE,IAAST,KAAaA,EAAU,IAAI,GAAGI,CAAG,KAAKJ,EAAU,UAAU,GAAGG,CAAS;AASrF,UAPKO,EAAA,MAAAjB,MAAAkB,EAAA,MAAAlB,GAAWmB,EAAMb,EAAK,KAAK;AAAA,QAC9B,SAAS;AAAA,QACT,aAAa;AAAA,QACb,GAAGW,EAAA,MAAKhB;AAAA,QACR,SAAS,KAAK;AAAA,MAAA,CACf,IAEG,EAAAQ,KAAaO,IAGjB;AAAA,YAAI,CAACC,EAAA,MAAKd,GAAL,WAAiBG,GAAMC,IAAY;AACtC,eAAK,KAAK;AACV;AAAA,QACF;AAEA,QAAAU,EAAA,MAAKjB,GAAO,SAAS;AAAA,UACnB,wBAAwB,MAAMoB,EAAad,GAAMO,GAAME,CAAE;AAAA,QAAA,CAC1D,GAED,KAAK,KAAK;AAAA;AAAA,IAAA;AAIZ,IAAAX,EAAA,gBAAS,CAACE,GAAkBC,MAAkC;AAG5D,MAFgBc,EAASJ,EAAA,MAAKZ,IAAWY,EAAA,MAAKf,EAAS,EAE/CI,GAAMC,CAAS;AAAA,IAAA;AA4BzB,IAAAH,EAAA,iBAAU,MAAM;;AACd,OAAAkB,IAAAL,EAAA,MAAKjB,OAAL,QAAAsB,EAAa;AAAA,IAAQ;AAIvB,IAAAlB,EAAA,cAAO,MAAM;;AACX,OAAAkB,IAAAL,EAAA,MAAKjB,OAAL,QAAAsB,EAAa;AAAA,IAAK;AAIpB,IAAAlB,EAAA,cAAO,MAAM;;AACX,OAAAkB,IAAAL,EAAA,MAAKjB,OAAL,QAAAsB,EAAa;AAAA,IAAK;AAIpB,IAAAlB,EAAA,qBAAc,MACLa,EAAA,MAAKjB;AArFZ,SAAK,UAAUH,EAAQ,SAClBqB,EAAA,MAAAjB,GAAgBJ,EAAQ,gBAAgB,CAAA,IACxCqB,EAAA,MAAAhB,GAAYL,EAAQ,YAAY,MAChCqB,EAAA,MAAAf,GAAcN,EAAQ,cAAc0B,EAAA,MAAKxB,GAAAyB;AAAA,EAChD;AAmFF;AAtGExB,IAAA,eAGAC,IAAA,eAGAC,IAAA,eAGAC,IAAA,eAaAE,IAAA,eAsCAN,IAAA,eAAAyB,aAAalB,GAA2B;AACtC,QAAM,EAAE,KAAAK,GAAK,WAAAD,MAAcJ,EAAK,OAC1B,EAAE,OAAAmB,GAAO,MAAAZ,GAAM,IAAAE,EAAA,IAAOL,GAEtBgB,IAAmB,CAACf,EAAI,YAAYE,GAAME,CAAE,EAAE,UAAUT,EAAK,MAAM,qBAAqBqB,GAExFC,IAAoB,KAAK,QAAQ,SAAS,SAAS,aAAa,GAEhEC,IAAc,CAACvB,EAAK,cAAc,CAACsB,GAEnCE,IAAa,CAACxB,EAAK;AAGvB,SAAA,EAAAuB,KACGJ,KACAC,KACAI;AAKP;ACxFW,MAAAC,IAAiB,CAAiCC,MAAW;AACxE,QAAMC,IAAcC,EAA2C,CAAC,GAAG,GAAGF,gBAAiB,GACjFG,IAAgBC,EAAO,CAACC,MAAQ;AACpC,UAAMC,IAAOD,EAAI,IAAIJ,EAAY,GAAG;AACpC,WAAO,IAAIM,EAAO;AAAA,MAChB,KAAK,IAAIC,EAAU,GAAGR,WAAY;AAAA,MAClC,GAAGM;AAAA,IAAA,CACJ;AAAA,EAAA,CACF,GACKG,IAAS,CAACR,GAAaE,CAAa;AAC1C,SAAAM,EAAO,MAAMR,EAAY,KACzBQ,EAAO,YAAYN,EAAc,KAE1BM;AACT;"}
@@ -0,0 +1,10 @@
1
+ import type { SliceType } from '@milkdown/ctx';
2
+ import type { PluginSpec } from '@milkdown/prose/state';
3
+ import type { $Ctx, $Prose } from '@milkdown/utils';
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] & {
6
+ key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>;
7
+ pluginKey: $Prose['key'];
8
+ };
9
+ export declare const tooltipFactory: <Id extends string, State = any>(id: Id) => TooltipPlugin<Id, any>;
10
+ //# sourceMappingURL=tooltip-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip-plugin.d.ts","sourceRoot":"","sources":["../src/tooltip-plugin.ts"],"names":[],"mappings":"AACA,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,eAAO,MAAM,cAAc,oEAc1B,CAAA"}
@@ -0,0 +1,20 @@
1
+ import type { EditorState } from '@milkdown/prose/state';
2
+ import type { EditorView } from '@milkdown/prose/view';
3
+ import type { Instance, Props } from 'tippy.js';
4
+ export type TooltipProviderOptions = {
5
+ content: HTMLElement;
6
+ tippyOptions?: Partial<Props>;
7
+ debounce?: number;
8
+ shouldShow?: (view: EditorView, prevState?: EditorState) => boolean;
9
+ };
10
+ export declare class TooltipProvider {
11
+ #private;
12
+ element: HTMLElement;
13
+ constructor(options: TooltipProviderOptions);
14
+ update: (view: EditorView, prevState?: EditorState) => void;
15
+ destroy: () => void;
16
+ show: () => void;
17
+ hide: () => void;
18
+ getInstance: () => Instance<Props> | undefined;
19
+ }
20
+ //# sourceMappingURL=tooltip-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip-provider.d.ts","sourceRoot":"","sources":["../src/tooltip-provider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAI/C,MAAM,MAAM,sBAAsB,GAAG;IAEnC,OAAO,EAAE,WAAW,CAAA;IAEpB,YAAY,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IAE7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,WAAW,KAAK,OAAO,CAAA;CACpE,CAAA;AAGD,qBAAa,eAAe;;IAc1B,OAAO,EAAE,WAAW,CAAA;gBAER,OAAO,EAAE,sBAAsB;IAuC3C,MAAM,SAAU,UAAU,cAAc,WAAW,KAAG,IAAI,CAIzD;IA2BD,OAAO,aAEN;IAGD,IAAI,aAEH;IAGD,IAAI,aAEH;IAGD,WAAW,oCAEV;CACF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@milkdown/plugin-tooltip",
3
3
  "type": "module",
4
- "version": "6.5.4",
4
+ "version": "7.0.0-next.1",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -20,18 +20,22 @@
20
20
  "src"
21
21
  ],
22
22
  "peerDependencies": {
23
- "@milkdown/core": "^6.0.1",
24
- "@milkdown/prose": "^6.0.1"
23
+ "@milkdown/core": "^7.0.0-next.0",
24
+ "@milkdown/ctx": "^7.0.0-next.0",
25
+ "@milkdown/prose": "^7.0.0-next.0"
25
26
  },
26
27
  "dependencies": {
28
+ "@types/lodash.debounce": "^4.0.7",
29
+ "lodash.debounce": "^4.0.8",
30
+ "tippy.js": "^6.3.7",
27
31
  "tslib": "^2.4.0",
28
- "@milkdown/exception": "6.5.4",
29
- "@milkdown/utils": "6.5.4"
32
+ "@milkdown/exception": "7.0.0-next.1",
33
+ "@milkdown/utils": "7.0.0-next.1"
30
34
  },
31
35
  "devDependencies": {
32
- "@milkdown/core": "6.5.4",
33
- "@milkdown/design-system": "6.5.4",
34
- "@milkdown/prose": "6.5.4"
36
+ "@milkdown/core": "7.0.0-next.1",
37
+ "@milkdown/ctx": "7.0.0-next.1",
38
+ "@milkdown/prose": "7.0.0-next.1"
35
39
  },
36
40
  "nx": {
37
41
  "targets": {
package/src/index.ts CHANGED
@@ -1,45 +1,3 @@
1
1
  /* Copyright 2021, Milkdown by Mirone. */
2
- import { Plugin, PluginKey } from '@milkdown/prose/state'
3
- import { AtomList, createPlugin as create } from '@milkdown/utils'
4
-
5
- import type { TooltipOptions } from './item'
6
- import { buttonMap } from './item'
7
- import { createPlugin } from './selection-marks-tooltip'
8
-
9
- export const key = new PluginKey('MILKDOWN_TOOLTIP')
10
- export * from './item'
11
-
12
- export const tooltipPlugin = create<string, TooltipOptions>((utils, options) => {
13
- return {
14
- id: 'tooltip',
15
- prosePlugins: (_, ctx) => {
16
- const manager = createPlugin(buttonMap(ctx, options?.items), utils, options?.bottom ?? false, 'tooltip')
17
- const plugin = new Plugin({
18
- key,
19
- props: {
20
- handleClick: (view) => {
21
- manager.setHide(false)
22
- manager.update(view)
23
- return false
24
- },
25
- handleDOMEvents: {
26
- mousedown: () => {
27
- manager.setHide(false)
28
- return false
29
- },
30
- },
31
- },
32
- view: (editorView) => {
33
- manager.recreate(editorView)
34
- return {
35
- update: manager.update,
36
- destroy: manager.destroy,
37
- }
38
- },
39
- })
40
- return [plugin]
41
- },
42
- }
43
- })
44
-
45
- export const tooltip = AtomList.create([tooltipPlugin()])
2
+ export * from './tooltip-provider'
3
+ export * from './tooltip-plugin'
@@ -0,0 +1,32 @@
1
+ /* Copyright 2021, Milkdown by Mirone. */
2
+ import type { SliceType } from '@milkdown/ctx'
3
+ import type { PluginSpec } from '@milkdown/prose/state'
4
+ import { Plugin, PluginKey } from '@milkdown/prose/state'
5
+ import type { $Ctx, $Prose } from '@milkdown/utils'
6
+ import { $ctx, $prose } from '@milkdown/utils'
7
+
8
+ /// @internal
9
+ export type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`
10
+
11
+ /// @internal
12
+ export type TooltipPlugin<Id extends string, State = any> = [$Ctx<PluginSpec<State>, TooltipSpecId<Id>>, $Prose] & {
13
+ key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>
14
+ pluginKey: $Prose['key']
15
+ }
16
+
17
+ /// Create a tooltip plugin with a unique id.
18
+ export const tooltipFactory = <Id extends string, State = any>(id: Id) => {
19
+ const tooltipSpec = $ctx<PluginSpec<State>, TooltipSpecId<Id>>({}, `${id}_TOOLTIP_SPEC`)
20
+ const tooltipPlugin = $prose((ctx) => {
21
+ const spec = ctx.get(tooltipSpec.key)
22
+ return new Plugin({
23
+ key: new PluginKey(`${id}_TOOLTIP`),
24
+ ...spec,
25
+ })
26
+ })
27
+ const result = [tooltipSpec, tooltipPlugin] as TooltipPlugin<Id>
28
+ result.key = tooltipSpec.key
29
+ result.pluginKey = tooltipPlugin.key
30
+
31
+ return result
32
+ }
@@ -0,0 +1,127 @@
1
+ /* Copyright 2021, Milkdown by Mirone. */
2
+ import { posToDOMRect } from '@milkdown/prose'
3
+ import type { EditorState } from '@milkdown/prose/state'
4
+ import { TextSelection } from '@milkdown/prose/state'
5
+ import type { EditorView } from '@milkdown/prose/view'
6
+ import debounce from 'lodash.debounce'
7
+ import type { Instance, Props } from 'tippy.js'
8
+ import tippy from 'tippy.js'
9
+
10
+ /// Options for tooltip provider.
11
+ export type TooltipProviderOptions = {
12
+ /// The tooltip content.
13
+ content: HTMLElement
14
+ /// The options for creating [tippy.js](https://atomiks.github.io/tippyjs/) instance.
15
+ tippyOptions?: Partial<Props>
16
+ /// The debounce time for updating tooltip, 200ms by default.
17
+ debounce?: number
18
+ /// The function to determine whether the tooltip should be shown.
19
+ shouldShow?: (view: EditorView, prevState?: EditorState) => boolean
20
+ }
21
+
22
+ /// A provider for creating tooltip.
23
+ export class TooltipProvider {
24
+ /// @internal
25
+ #tippy: Instance | undefined
26
+
27
+ /// @internal
28
+ #tippyOptions: Partial<Props>
29
+
30
+ /// @internal
31
+ #debounce: number
32
+
33
+ /// @internal
34
+ #shouldShow: (view: EditorView, prevState?: EditorState) => boolean
35
+
36
+ /// The root element of the tooltip.
37
+ element: HTMLElement
38
+
39
+ constructor(options: TooltipProviderOptions) {
40
+ this.element = options.content
41
+ this.#tippyOptions = options.tippyOptions ?? {}
42
+ this.#debounce = options.debounce ?? 200
43
+ this.#shouldShow = options.shouldShow ?? this.#_shouldShow
44
+ }
45
+
46
+ /// @internal
47
+ #onUpdate = (view: EditorView, prevState?: EditorState): void => {
48
+ const { state, composing } = view
49
+ const { selection, doc } = state
50
+ const { ranges } = selection
51
+ const from = Math.min(...ranges.map(range => range.$from.pos))
52
+ const to = Math.max(...ranges.map(range => range.$to.pos))
53
+ const isSame = prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)
54
+
55
+ this.#tippy ??= tippy(view.dom, {
56
+ trigger: 'manual',
57
+ interactive: true,
58
+ ...this.#tippyOptions,
59
+ content: this.element,
60
+ })
61
+
62
+ if (composing || isSame)
63
+ return
64
+
65
+ if (!this.#shouldShow(view, prevState)) {
66
+ this.hide()
67
+ return
68
+ }
69
+
70
+ this.#tippy.setProps({
71
+ getReferenceClientRect: () => posToDOMRect(view, from, to),
72
+ })
73
+
74
+ this.show()
75
+ }
76
+
77
+ /// Update provider state by editor view.
78
+ update = (view: EditorView, prevState?: EditorState): void => {
79
+ const updater = debounce(this.#onUpdate, this.#debounce)
80
+
81
+ updater(view, prevState)
82
+ }
83
+
84
+ /// @internal
85
+ #_shouldShow(view: EditorView): boolean {
86
+ const { doc, selection } = view.state
87
+ const { empty, from, to } = selection
88
+
89
+ const isEmptyTextBlock = !doc.textBetween(from, to).length && view.state.selection instanceof TextSelection
90
+
91
+ const isTooltipChildren = this.element.contains(document.activeElement)
92
+
93
+ const notHasFocus = !view.hasFocus() && !isTooltipChildren
94
+
95
+ const isReadonly = !view.editable
96
+
97
+ if (
98
+ notHasFocus
99
+ || empty
100
+ || isEmptyTextBlock
101
+ || isReadonly
102
+ )
103
+ return false
104
+
105
+ return true
106
+ }
107
+
108
+ /// Destroy the tooltip.
109
+ destroy = () => {
110
+ this.#tippy?.destroy()
111
+ }
112
+
113
+ /// Show the tooltip.
114
+ show = () => {
115
+ this.#tippy?.show()
116
+ }
117
+
118
+ /// Hide the tooltip.
119
+ hide = () => {
120
+ this.#tippy?.hide()
121
+ }
122
+
123
+ /// Get the [tippy.js](https://atomiks.github.io/tippyjs/) instance.
124
+ getInstance = () => {
125
+ return this.#tippy
126
+ }
127
+ }
@@ -1,3 +0,0 @@
1
- import type { EditorView } from '@milkdown/prose/view';
2
- export declare const calcButtonPos: (buttons: HTMLElement, view: EditorView, isBottom: boolean) => void;
3
- //# sourceMappingURL=calc-button-pos.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"calc-button-pos.d.ts","sourceRoot":"","sources":["../../src/button-manager/calc-button-pos.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,eAAO,MAAM,aAAa,YAAa,WAAW,QAAQ,UAAU,YAAY,OAAO,SAuBtF,CAAA"}
@@ -1,10 +0,0 @@
1
- import type { EditorView } from '@milkdown/prose/view';
2
- import type { ThemeUtils } from '@milkdown/utils';
3
- import type { ButtonList } from '../item';
4
- interface Tooltip {
5
- dom: HTMLDivElement;
6
- render: (editorView: EditorView) => void;
7
- }
8
- export declare const createTooltip: (buttonMap: ButtonList, utils: ThemeUtils, className: string) => Tooltip;
9
- export {};
10
- //# sourceMappingURL=create-tooltip.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-tooltip.d.ts","sourceRoot":"","sources":["../../src/button-manager/create-tooltip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,UAAU,OAAO;IACf,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAA;CACzC;AAED,eAAO,MAAM,aAAa,iCAAkC,UAAU,aAAa,MAAM,KAAG,OAoB3F,CAAA"}
@@ -1,4 +0,0 @@
1
- import type { EditorView } from '@milkdown/prose/view';
2
- import type { ButtonList } from '../item';
3
- export declare const filterButton: (buttons: ButtonList, view: EditorView) => boolean;
4
- //# sourceMappingURL=filter-button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter-button.d.ts","sourceRoot":"","sources":["../../src/button-manager/filter-button.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,eAAO,MAAM,YAAY,8BAA+B,UAAU,YAqBjE,CAAA"}
@@ -1,10 +0,0 @@
1
- import type { EditorView } from '@milkdown/prose/view';
2
- import type { ThemeUtils } from '@milkdown/utils';
3
- import type { ButtonList } from '../item';
4
- export declare const createButtonManager: (buttons: ButtonList, utils: ThemeUtils, bottom: boolean, containerClassName: string) => {
5
- destroy: () => void;
6
- hide: () => void;
7
- update: (editorView: EditorView) => void;
8
- render: (editorView: EditorView) => void;
9
- };
10
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/button-manager/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAKzC,eAAO,MAAM,mBAAmB,+BAEvB,UAAU,UACT,OAAO,sBACK,MAAM;;;yBA0BH,UAAU;;CAUlC,CAAA"}
@@ -1,4 +0,0 @@
1
- import type { EditorView } from '@milkdown/prose/view';
2
- import type { ButtonList } from '../item';
3
- export declare const noActive: (buttonMap: ButtonList, view: EditorView) => boolean;
4
- //# sourceMappingURL=no-active.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"no-active.d.ts","sourceRoot":"","sources":["../../src/button-manager/no-active.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,eAAO,MAAM,QAAQ,gCAAiC,UAAU,YAI/D,CAAA"}
@@ -1,3 +0,0 @@
1
- import type { Emotion, ThemeManager } from '@milkdown/core';
2
- export declare const injectStyle: (themeManager: ThemeManager, { css }: Emotion) => string;
3
- //# sourceMappingURL=style.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"style.d.ts","sourceRoot":"","sources":["../../src/button-manager/style.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAS,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAGlE,eAAO,MAAM,WAAW,iBAAkB,YAAY,WAAW,OAAO,WA8CvE,CAAA"}
package/lib/item.d.ts DELETED
@@ -1,31 +0,0 @@
1
- import type { Ctx } from '@milkdown/core';
2
- import type { Icon } from '@milkdown/design-system';
3
- import type { MarkType } from '@milkdown/prose/model';
4
- import type { EditorView } from '@milkdown/prose/view';
5
- export type Pred = (view: EditorView) => boolean;
6
- export type Updater = (view: EditorView, $: HTMLElement) => void;
7
- export type Event2Command = (e: Event) => void;
8
- export type OnClick = (ctx: Ctx) => void;
9
- export interface Item {
10
- icon: Icon | ((ctx: Ctx) => HTMLElement);
11
- onClick: string | ((ctx: Ctx) => () => void);
12
- isHidden: (ctx: Ctx) => Pred;
13
- isActive: (ctx: Ctx) => Pred;
14
- canAddToDOM: (ctx: Ctx) => Pred;
15
- }
16
- export interface ButtonItem {
17
- $: HTMLElement;
18
- command: () => void;
19
- active: Pred;
20
- disable?: Pred;
21
- enable: Pred;
22
- }
23
- export declare const createToggleIcon: (icon: Icon, onClick: string, mark?: MarkType, disableForMark?: MarkType) => Item;
24
- export declare const defaultButtons: (ctx: Ctx) => Item[];
25
- export type ButtonList = ButtonItem[];
26
- export interface TooltipOptions {
27
- bottom: boolean;
28
- items: (ctx: Ctx) => Array<Item>;
29
- }
30
- export declare const buttonMap: (ctx: Ctx, items?: (ctx: Ctx) => Array<Item>) => ButtonList;
31
- //# sourceMappingURL=item.d.ts.map
package/lib/item.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../src/item.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAItD,MAAM,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAA;AAChD,MAAM,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,KAAK,IAAI,CAAA;AAChE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;AAE9C,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;AAExC,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,WAAW,CAAC,CAAA;IACxC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,IAAI,CAAC,CAAA;IAC5C,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC5B,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC5B,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,WAAW,CAAA;IACd,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,EAAE,IAAI,CAAA;IACZ,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;CACb;AAED,eAAO,MAAM,gBAAgB,SAAU,IAAI,WAAW,MAAM,SAAS,QAAQ,mBAAmB,QAAQ,KAAG,IAMzG,CAAA;AAEF,eAAO,MAAM,cAAc,QAAS,GAAG,WAStC,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,EAAE,CAAA;AAErC,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,CAAA;CACjC;AAED,eAAO,MAAM,SAAS,QAAS,GAAG,gBAAe,GAAG,KAAK,MAAM,IAAI,CAAC,eASnE,CAAA"}
@@ -1,12 +0,0 @@
1
- import type { EditorState } from '@milkdown/prose/state';
2
- import type { EditorView } from '@milkdown/prose/view';
3
- import type { ThemeUtils } from '@milkdown/utils';
4
- import type { ButtonList } from './item';
5
- export declare const createPlugin: (buttonMap: ButtonList, utils: ThemeUtils, bottom: boolean, containerClassName: string) => {
6
- recreate: (editorView: EditorView) => void;
7
- update: (view: EditorView, prevState?: EditorState) => void;
8
- destroy: () => void;
9
- render: (editorView: EditorView) => void;
10
- setHide: (isTyping: boolean) => void;
11
- };
12
- //# sourceMappingURL=selection-marks-tooltip.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"selection-marks-tooltip.d.ts","sourceRoot":"","sources":["../src/selection-marks-tooltip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAGjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAExC,eAAO,MAAM,YAAY,iCAAkC,UAAU,UAAU,OAAO,sBAAsB,MAAM;2BAwBvF,UAAU;mBAhBb,UAAU,cAAc,WAAW;;yBAyBlC,UAAU;wBAIX,OAAO;CAI9B,CAAA"}
@@ -1,2 +0,0 @@
1
- export declare const elementIsTag: (element: HTMLElement, tagName: string) => boolean;
2
- //# sourceMappingURL=element.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../../src/utility/element.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,YAAY,YAAa,WAAW,WAAW,MAAM,KAAG,OAC1B,CAAA"}
@@ -1,3 +0,0 @@
1
- export * from './element';
2
- export * from './prosemirror';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utility/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA"}
@@ -1,12 +0,0 @@
1
- import type { MarkType, Node, NodeType } from '@milkdown/prose/model';
2
- import type { EditorState } from '@milkdown/prose/state';
3
- export interface Position {
4
- start: number;
5
- end: number;
6
- }
7
- export declare const hasMark: (editorState: EditorState, type?: MarkType) => boolean;
8
- export declare const isTextSelection: (editorState: EditorState) => boolean;
9
- export declare const isInCodeFence: (editorState: EditorState) => boolean;
10
- export declare const isTextAndNotHasMark: (editorState: EditorState, mark?: MarkType) => boolean;
11
- export declare const equalNodeType: (nodeType: NodeType, node: Node) => boolean;
12
- //# sourceMappingURL=prosemirror.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prosemirror.d.ts","sourceRoot":"","sources":["../../src/utility/prosemirror.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGxD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,eAAO,MAAM,OAAO,gBAAiB,WAAW,SAAS,QAAQ,KAAG,OAOnE,CAAA;AAED,eAAO,MAAM,eAAe,gBAAiB,WAAW,KAAG,OAW1D,CAAA;AAED,eAAO,MAAM,aAAa,gBAAiB,WAAW,KAAG,OACsB,CAAA;AAE/E,eAAO,MAAM,mBAAmB,gBAAiB,WAAW,SAAS,QAAQ,KAAG,OACW,CAAA;AAE3F,eAAO,MAAM,aAAa,aAAc,QAAQ,QAAQ,IAAI,YAE3D,CAAA"}
@@ -1,29 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import { missingRootElement } from '@milkdown/exception'
3
- import { calculateTextPosition } from '@milkdown/prose'
4
- import type { EditorView } from '@milkdown/prose/view'
5
-
6
- export const calcButtonPos = (buttons: HTMLElement, view: EditorView, isBottom: boolean) => {
7
- buttons.classList.remove('hide')
8
- calculateTextPosition(view, buttons, (start, end, target, parent) => {
9
- const $editor = buttons.parentElement
10
- if (!$editor)
11
- throw missingRootElement()
12
-
13
- const selectionWidth = end.left - start.left
14
- let left = start.left - parent.left - (target.width - selectionWidth) / 2
15
- let top = start.top - parent.top - target.height - 14 + $editor.scrollTop
16
-
17
- if (left < 0)
18
- left = 0
19
-
20
- const maxLeft = $editor.clientWidth - (target.width + 4)
21
- if (left > maxLeft)
22
- left = maxLeft
23
-
24
- if (top < $editor.scrollTop || (isBottom && parent.bottom - start.bottom > target.height))
25
- top = start.bottom - parent.top + 14 + $editor.scrollTop
26
-
27
- return [top, left]
28
- })
29
- }
@@ -1,33 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { EditorView } from '@milkdown/prose/view'
3
- import type { ThemeUtils } from '@milkdown/utils'
4
-
5
- import type { ButtonList } from '../item'
6
- import { injectStyle } from './style'
7
-
8
- interface Tooltip {
9
- dom: HTMLDivElement
10
- render: (editorView: EditorView) => void
11
- }
12
-
13
- export const createTooltip = (buttonMap: ButtonList, utils: ThemeUtils, className: string): Tooltip => {
14
- const div = document.createElement('div')
15
- utils.themeManager.onFlush(() => {
16
- const style = utils.getStyle(emotion => injectStyle(utils.themeManager, emotion)) || ''
17
- if (style)
18
- div.classList.add(style)
19
- })
20
-
21
- div.classList.add(utils.getClassName({}, className))
22
-
23
- return {
24
- dom: div,
25
- render: (editorView: EditorView) => {
26
- buttonMap
27
- .filter(item => item.enable(editorView) && item.$ != null)
28
- .forEach(({ $ }) => div.appendChild($))
29
-
30
- editorView.dom.parentNode?.appendChild(div)
31
- },
32
- }
33
- }
@@ -1,28 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { EditorView } from '@milkdown/prose/view'
3
-
4
- import type { ButtonList } from '../item'
5
- import { noActive } from './no-active'
6
-
7
- export const filterButton = (buttons: ButtonList, view: EditorView) => {
8
- buttons
9
- .filter(item => item.enable(view) && item.$ != null)
10
- .forEach((item) => {
11
- const disable = item.disable?.(view)
12
- if (disable) {
13
- item.$.classList.add('hide')
14
- return
15
- }
16
-
17
- item.$.classList.remove('hide')
18
-
19
- const active = item.active(view)
20
- if (active) {
21
- item.$.classList.add('active')
22
- return
23
- }
24
- item.$.classList.remove('active')
25
- })
26
-
27
- return noActive(buttons, view)
28
- }
@@ -1,50 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { EditorView } from '@milkdown/prose/view'
3
- import type { ThemeUtils } from '@milkdown/utils'
4
-
5
- import type { ButtonList } from '../item'
6
- import { calcButtonPos } from './calc-button-pos'
7
- import { createTooltip } from './create-tooltip'
8
- import { filterButton } from './filter-button'
9
-
10
- export const createButtonManager = (
11
- buttons: ButtonList,
12
- utils: ThemeUtils,
13
- bottom: boolean,
14
- containerClassName: string,
15
- ) => {
16
- const { dom: buttonDOM, render } = createTooltip(buttons, utils, containerClassName)
17
-
18
- const onClick = (e: Event) => {
19
- const target = buttons.find(({ $ }) => e.target instanceof Element && $.contains(e.target))
20
- if (!target)
21
- return
22
-
23
- e.stopPropagation()
24
- e.preventDefault()
25
- target.command()
26
- }
27
-
28
- const hide = () => {
29
- buttonDOM.classList.add('hide')
30
- }
31
-
32
- buttonDOM.addEventListener('mousedown', onClick)
33
-
34
- return {
35
- destroy: () => {
36
- buttonDOM.removeEventListener('mousedown', onClick)
37
- buttonDOM.remove()
38
- },
39
- hide,
40
- update: (editorView: EditorView) => {
41
- const noActive = filterButton(buttons, editorView)
42
- if (noActive) {
43
- hide()
44
- return
45
- }
46
- calcButtonPos(buttonDOM, editorView, bottom)
47
- },
48
- render,
49
- }
50
- }
@@ -1,10 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { EditorView } from '@milkdown/prose/view'
3
-
4
- import type { ButtonList } from '../item'
5
-
6
- export const noActive = (buttonMap: ButtonList, view: EditorView) => {
7
- return Object.values(buttonMap)
8
- .filter(item => item.enable(view) && item.$ != null)
9
- .every(({ $ }) => $.classList.contains('hide'))
10
- }
@@ -1,51 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { Color, Emotion, ThemeManager } from '@milkdown/core'
3
- import { ThemeBorder, ThemeColor, ThemeShadow, ThemeSize } from '@milkdown/core'
4
-
5
- export const injectStyle = (themeManager: ThemeManager, { css }: Emotion) => {
6
- const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity])
7
- const lineWidth = themeManager.get(ThemeSize, 'lineWidth')
8
- return css`
9
- display: inline-flex;
10
- cursor: pointer;
11
- justify-content: space-evenly;
12
- position: absolute;
13
- border-radius: ${themeManager.get(ThemeSize, 'radius')};
14
- z-index: 2;
15
-
16
- ${themeManager.get(ThemeBorder, undefined)}
17
- ${themeManager.get(ThemeShadow, undefined)}
18
-
19
- overflow: hidden;
20
- background: ${palette('surface')};
21
-
22
- .icon {
23
- position: relative;
24
- color: ${palette('solid', 0.87)};
25
-
26
- width: 48px;
27
- line-height: 48px;
28
- text-align: center;
29
- transition: all 0.4s ease-in-out;
30
- &:hover {
31
- background-color: ${palette('secondary', 0.12)};
32
- }
33
- &.active {
34
- color: ${palette('primary')};
35
- }
36
- &:not(:last-child)::after {
37
- content: '';
38
- position: absolute;
39
- top: 0;
40
- right: calc(-0.5 * ${lineWidth});
41
- width: ${lineWidth};
42
- bottom: 0;
43
- background: ${palette('line')};
44
- }
45
- }
46
- &.hide,
47
- .hide {
48
- display: none;
49
- }
50
- `
51
- }
package/src/item.ts DELETED
@@ -1,67 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { Ctx } from '@milkdown/core'
3
- import { ThemeIcon, commandsCtx, schemaCtx, themeManagerCtx } from '@milkdown/core'
4
- import type { Icon } from '@milkdown/design-system'
5
- import type { MarkType } from '@milkdown/prose/model'
6
- import type { EditorView } from '@milkdown/prose/view'
7
-
8
- import { hasMark, isTextAndNotHasMark } from './utility'
9
-
10
- export type Pred = (view: EditorView) => boolean
11
- export type Updater = (view: EditorView, $: HTMLElement) => void
12
- export type Event2Command = (e: Event) => void
13
-
14
- export type OnClick = (ctx: Ctx) => void
15
-
16
- export interface Item {
17
- icon: Icon | ((ctx: Ctx) => HTMLElement)
18
- onClick: string | ((ctx: Ctx) => () => void)
19
- isHidden: (ctx: Ctx) => Pred
20
- isActive: (ctx: Ctx) => Pred
21
- canAddToDOM: (ctx: Ctx) => Pred
22
- }
23
-
24
- export interface ButtonItem {
25
- $: HTMLElement
26
- command: () => void
27
- active: Pred
28
- disable?: Pred
29
- enable: Pred
30
- }
31
-
32
- export const createToggleIcon = (icon: Icon, onClick: string, mark?: MarkType, disableForMark?: MarkType): Item => ({
33
- icon,
34
- onClick,
35
- isHidden: () => (view: EditorView) => isTextAndNotHasMark(view.state, disableForMark),
36
- isActive: () => (view: EditorView) => hasMark(view.state, mark),
37
- canAddToDOM: () => (view: EditorView) => !!mark && !!view.state.schema.marks[mark.name],
38
- })
39
-
40
- export const defaultButtons = (ctx: Ctx) => {
41
- const marks = ctx.get(schemaCtx).marks
42
- return [
43
- createToggleIcon('bold', 'ToggleBold', marks.strong),
44
- createToggleIcon('italic', 'ToggleItalic', marks.em),
45
- createToggleIcon('strikeThrough', 'ToggleStrikeThrough', marks.strike_through),
46
- createToggleIcon('code', 'ToggleInlineCode', marks.code_inline),
47
- createToggleIcon('link', 'ToggleLink', marks.link),
48
- ]
49
- }
50
-
51
- export type ButtonList = ButtonItem[]
52
-
53
- export interface TooltipOptions {
54
- bottom: boolean
55
- items: (ctx: Ctx) => Array<Item>
56
- }
57
-
58
- export const buttonMap = (ctx: Ctx, items: (ctx: Ctx) => Array<Item> = defaultButtons): ButtonList => {
59
- const toButton = ({ icon, onClick, isHidden, isActive, canAddToDOM }: Item): ButtonItem => ({
60
- $: typeof icon === 'function' ? icon(ctx) : (ctx.get(themeManagerCtx).get(ThemeIcon, icon)?.dom as HTMLElement),
61
- command: typeof onClick === 'string' ? () => ctx.get(commandsCtx).call(onClick) : onClick(ctx),
62
- disable: isHidden(ctx),
63
- active: isActive(ctx),
64
- enable: canAddToDOM(ctx),
65
- })
66
- return items(ctx).map(toButton)
67
- }
@@ -1,50 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import type { EditorState } from '@milkdown/prose/state'
3
- import type { EditorView } from '@milkdown/prose/view'
4
- import type { ThemeUtils } from '@milkdown/utils'
5
-
6
- import { createButtonManager } from './button-manager'
7
- import type { ButtonList } from './item'
8
-
9
- export const createPlugin = (buttonMap: ButtonList, utils: ThemeUtils, bottom: boolean, containerClassName: string) => {
10
- let buttonManager = createButtonManager(buttonMap, utils, bottom, containerClassName)
11
- let shouldHide = false
12
-
13
- const hide = () => {
14
- buttonManager.hide()
15
- }
16
-
17
- const update = (view: EditorView, prevState?: EditorState) => {
18
- const { state } = view
19
-
20
- if (!view.editable || shouldHide) {
21
- hide()
22
- return
23
- }
24
-
25
- const isEqualSelection = prevState?.doc.eq(state.doc) && prevState.selection.eq(state.selection)
26
- if (isEqualSelection)
27
- return
28
-
29
- buttonManager.update(view)
30
- }
31
-
32
- return {
33
- recreate: (editorView: EditorView) => {
34
- buttonManager = createButtonManager(buttonMap, utils, bottom, containerClassName)
35
- buttonManager.render(editorView)
36
- update(editorView)
37
- },
38
- update,
39
- destroy: () => {
40
- buttonManager.destroy()
41
- },
42
- render: (editorView: EditorView) => {
43
- buttonManager.render(editorView)
44
- update(editorView)
45
- },
46
- setHide: (isTyping: boolean) => {
47
- shouldHide = isTyping
48
- },
49
- }
50
- }
@@ -1,3 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- export const elementIsTag = (element: HTMLElement, tagName: string): boolean =>
3
- element.tagName === tagName.toUpperCase()
@@ -1,3 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- export * from './element'
3
- export * from './prosemirror'
@@ -1,42 +0,0 @@
1
- /* Copyright 2021, Milkdown by Mirone. */
2
- import { findParentNode } from '@milkdown/prose'
3
- import type { MarkType, Node, NodeType } from '@milkdown/prose/model'
4
- import type { EditorState } from '@milkdown/prose/state'
5
- import { TextSelection } from '@milkdown/prose/state'
6
-
7
- export interface Position {
8
- start: number
9
- end: number
10
- }
11
-
12
- export const hasMark = (editorState: EditorState, type?: MarkType): boolean => {
13
- if (!type)
14
- return false
15
-
16
- const { from, to } = editorState.selection
17
-
18
- return editorState.doc.rangeHasMark(from, from === to ? to + 1 : to, type)
19
- }
20
-
21
- export const isTextSelection = (editorState: EditorState): boolean => {
22
- const { selection } = editorState
23
- if (selection instanceof TextSelection) {
24
- const text = editorState.doc.textBetween(selection.from, selection.to)
25
-
26
- if (!text)
27
- return false
28
-
29
- return true
30
- }
31
- return false
32
- }
33
-
34
- export const isInCodeFence = (editorState: EditorState): boolean =>
35
- Boolean(findParentNode(node => !!node.type.spec.code)(editorState.selection))
36
-
37
- export const isTextAndNotHasMark = (editorState: EditorState, mark?: MarkType): boolean =>
38
- !isTextSelection(editorState) || isInCodeFence(editorState) || hasMark(editorState, mark)
39
-
40
- export const equalNodeType = (nodeType: NodeType, node: Node) => {
41
- return (Array.isArray(nodeType) && nodeType.includes(node.type)) || node.type === nodeType
42
- }