@milkdown/plugin-tooltip 6.5.4 → 7.0.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +2 -7
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +76 -190
- package/lib/index.es.js.map +1 -1
- package/lib/tooltip-plugin.d.ts +11 -0
- package/lib/tooltip-plugin.d.ts.map +1 -0
- package/lib/tooltip-provider.d.ts +20 -0
- package/lib/tooltip-provider.d.ts.map +1 -0
- package/package.json +12 -8
- package/src/index.ts +2 -44
- package/src/tooltip-plugin.ts +31 -0
- package/src/tooltip-provider.ts +109 -0
- package/lib/button-manager/calc-button-pos.d.ts +0 -3
- package/lib/button-manager/calc-button-pos.d.ts.map +0 -1
- package/lib/button-manager/create-tooltip.d.ts +0 -10
- package/lib/button-manager/create-tooltip.d.ts.map +0 -1
- package/lib/button-manager/filter-button.d.ts +0 -4
- package/lib/button-manager/filter-button.d.ts.map +0 -1
- package/lib/button-manager/index.d.ts +0 -10
- package/lib/button-manager/index.d.ts.map +0 -1
- package/lib/button-manager/no-active.d.ts +0 -4
- package/lib/button-manager/no-active.d.ts.map +0 -1
- package/lib/button-manager/style.d.ts +0 -3
- package/lib/button-manager/style.d.ts.map +0 -1
- package/lib/item.d.ts +0 -31
- package/lib/item.d.ts.map +0 -1
- package/lib/selection-marks-tooltip.d.ts +0 -12
- package/lib/selection-marks-tooltip.d.ts.map +0 -1
- package/lib/utility/element.d.ts +0 -2
- package/lib/utility/element.d.ts.map +0 -1
- package/lib/utility/index.d.ts +0 -3
- package/lib/utility/index.d.ts.map +0 -1
- package/lib/utility/prosemirror.d.ts +0 -12
- package/lib/utility/prosemirror.d.ts.map +0 -1
- package/src/button-manager/calc-button-pos.ts +0 -29
- package/src/button-manager/create-tooltip.ts +0 -33
- package/src/button-manager/filter-button.ts +0 -28
- package/src/button-manager/index.ts +0 -50
- package/src/button-manager/no-active.ts +0 -10
- package/src/button-manager/style.ts +0 -51
- package/src/item.ts +0 -67
- package/src/selection-marks-tooltip.ts +0 -50
- package/src/utility/element.ts +0 -3
- package/src/utility/index.ts +0 -3
- package/src/utility/prosemirror.ts +0 -42
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,
|
|
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,82 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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 I = Object.defineProperty;
|
|
2
|
+
var M = (o, t, e) => t in o ? I(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
3
|
+
var c = (o, t, e) => (M(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 R } from "@milkdown/prose";
|
|
14
|
+
import { TextSelection as S, Plugin as _, PluginKey as w } from "@milkdown/prose/state";
|
|
15
|
+
import C from "lodash.debounce";
|
|
16
|
+
import E from "tippy.js";
|
|
17
|
+
import { $ctx as F, $prose as K } from "@milkdown/utils";
|
|
18
|
+
var i, m, u, a, y, f, b;
|
|
19
|
+
class W {
|
|
20
|
+
constructor(t) {
|
|
21
|
+
r(this, f);
|
|
22
|
+
r(this, i, void 0);
|
|
23
|
+
c(this, "element");
|
|
24
|
+
r(this, m, void 0);
|
|
25
|
+
r(this, u, void 0);
|
|
26
|
+
r(this, a, void 0);
|
|
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)), O = Math.max(...d.map((k) => k.$to.pos)), P = e && e.doc.eq(g) && e.selection.eq(h);
|
|
29
|
+
if (n(this, i) ?? p(this, i, E(t.dom, {
|
|
30
|
+
trigger: "manual",
|
|
31
|
+
interactive: !0,
|
|
32
|
+
...n(this, m),
|
|
33
|
+
content: this.element
|
|
34
|
+
})), !(l || P)) {
|
|
35
|
+
if (!n(this, a).call(this, t, e)) {
|
|
36
|
+
this.hide();
|
|
37
|
+
return;
|
|
95
38
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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: () => R(t, T, O)
|
|
41
|
+
}), this.show();
|
|
136
42
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
+
C(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
|
-
}
|
|
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 S, T = this.element.contains(document.activeElement), O = !t.hasFocus() && !T, P = !t.editable;
|
|
65
|
+
return !(O || l || d || P);
|
|
66
|
+
};
|
|
67
|
+
const L = (o) => {
|
|
68
|
+
const t = F({}, `${o}_TOOLTIP_SPEC`), e = K((l) => {
|
|
69
|
+
const h = l.get(t.key);
|
|
70
|
+
return new _({
|
|
71
|
+
key: new w(`${o}_TOOLTIP`),
|
|
72
|
+
...h
|
|
73
|
+
});
|
|
74
|
+
}), s = [t, e];
|
|
75
|
+
return s.key = t.key, s.pluginKey = e.key, s;
|
|
76
|
+
}, j = L("MILKDOWN");
|
|
188
77
|
export {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
F as key,
|
|
193
|
-
U as tooltip,
|
|
194
|
-
K as tooltipPlugin
|
|
78
|
+
W as TooltipProvider,
|
|
79
|
+
j as tooltip,
|
|
80
|
+
L as tooltipFactory
|
|
195
81
|
};
|
|
196
82
|
//# sourceMappingURL=index.es.js.map
|
package/lib/index.es.js.map
CHANGED
|
@@ -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\nexport type TooltipProviderOptions = {\n content: HTMLElement\n tippyOptions?: Partial<Props>\n debounce?: number\n shouldShow?: (view: EditorView, prevState?: EditorState) => boolean\n}\n\nexport class TooltipProvider {\n #tippy: Instance | undefined\n\n element: HTMLElement\n\n #tippyOptions: Partial<Props>\n\n #debounce: number\n\n #shouldShow: (view: EditorView, prevState?: EditorState) => boolean\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 #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 = (view: EditorView, prevState?: EditorState): void => {\n const updater = debounce(this.#onUpdate, this.#debounce)\n\n updater(view, prevState)\n }\n\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 = () => {\n this.#tippy?.destroy()\n }\n\n show = () => {\n this.#tippy?.show()\n }\n\n hide = () => {\n this.#tippy?.hide()\n }\n\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\nexport type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`\n\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\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\nexport const tooltip = tooltipFactory('MILKDOWN')\n"],"names":["TooltipProvider","options","__privateAdd","__shouldShow","_tippy","__publicField","_tippyOptions","_debounce","_shouldShow","_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","tooltip"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
export declare const tooltip: TooltipPlugin<"MILKDOWN", any>;
|
|
11
|
+
//# 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;AAGnD,MAAM,MAAM,aAAa,CAAC,EAAE,SAAS,MAAM,IAAI,GAAG,EAAE,eAAe,CAAA;AAEnE,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;AAED,eAAO,MAAM,cAAc,oEAc1B,CAAA;AAED,eAAO,MAAM,OAAO,gCAA6B,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;AAG/C,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,WAAW,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,WAAW,KAAK,OAAO,CAAA;CACpE,CAAA;AAED,qBAAa,eAAe;;IAG1B,OAAO,EAAE,WAAW,CAAA;gBAQR,OAAO,EAAE,sBAAsB;IAqC3C,MAAM,SAAU,UAAU,cAAc,WAAW,KAAG,IAAI,CAIzD;IAyBD,OAAO,aAEN;IAED,IAAI,aAEH;IAED,IAAI,aAEH;IAED,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": "
|
|
4
|
+
"version": "7.0.0-next.0",
|
|
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": "^
|
|
24
|
-
"@milkdown/
|
|
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": "
|
|
29
|
-
"@milkdown/utils": "
|
|
32
|
+
"@milkdown/exception": "7.0.0-next.0",
|
|
33
|
+
"@milkdown/utils": "7.0.0-next.0"
|
|
30
34
|
},
|
|
31
35
|
"devDependencies": {
|
|
32
|
-
"@milkdown/core": "
|
|
33
|
-
"@milkdown/
|
|
34
|
-
"@milkdown/prose": "
|
|
36
|
+
"@milkdown/core": "7.0.0-next.0",
|
|
37
|
+
"@milkdown/ctx": "7.0.0-next.0",
|
|
38
|
+
"@milkdown/prose": "7.0.0-next.0"
|
|
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
|
-
|
|
3
|
-
|
|
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,31 @@
|
|
|
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
|
+
export type TooltipSpecId<Id extends string> = `${Id}_TOOLTIP_SPEC`
|
|
9
|
+
|
|
10
|
+
export type TooltipPlugin<Id extends string, State = any> = [$Ctx<PluginSpec<State>, TooltipSpecId<Id>>, $Prose] & {
|
|
11
|
+
key: SliceType<PluginSpec<State>, TooltipSpecId<Id>>
|
|
12
|
+
pluginKey: $Prose['key']
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const tooltipFactory = <Id extends string, State = any>(id: Id) => {
|
|
16
|
+
const tooltipSpec = $ctx<PluginSpec<State>, TooltipSpecId<Id>>({}, `${id}_TOOLTIP_SPEC`)
|
|
17
|
+
const tooltipPlugin = $prose((ctx) => {
|
|
18
|
+
const spec = ctx.get(tooltipSpec.key)
|
|
19
|
+
return new Plugin({
|
|
20
|
+
key: new PluginKey(`${id}_TOOLTIP`),
|
|
21
|
+
...spec,
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
const result = [tooltipSpec, tooltipPlugin] as TooltipPlugin<Id>
|
|
25
|
+
result.key = tooltipSpec.key
|
|
26
|
+
result.pluginKey = tooltipPlugin.key
|
|
27
|
+
|
|
28
|
+
return result
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const tooltip = tooltipFactory('MILKDOWN')
|
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
export type TooltipProviderOptions = {
|
|
11
|
+
content: HTMLElement
|
|
12
|
+
tippyOptions?: Partial<Props>
|
|
13
|
+
debounce?: number
|
|
14
|
+
shouldShow?: (view: EditorView, prevState?: EditorState) => boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class TooltipProvider {
|
|
18
|
+
#tippy: Instance | undefined
|
|
19
|
+
|
|
20
|
+
element: HTMLElement
|
|
21
|
+
|
|
22
|
+
#tippyOptions: Partial<Props>
|
|
23
|
+
|
|
24
|
+
#debounce: number
|
|
25
|
+
|
|
26
|
+
#shouldShow: (view: EditorView, prevState?: EditorState) => boolean
|
|
27
|
+
|
|
28
|
+
constructor(options: TooltipProviderOptions) {
|
|
29
|
+
this.element = options.content
|
|
30
|
+
this.#tippyOptions = options.tippyOptions ?? {}
|
|
31
|
+
this.#debounce = options.debounce ?? 200
|
|
32
|
+
this.#shouldShow = options.shouldShow ?? this.#_shouldShow
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#onUpdate = (view: EditorView, prevState?: EditorState): void => {
|
|
36
|
+
const { state, composing } = view
|
|
37
|
+
const { selection, doc } = state
|
|
38
|
+
const { ranges } = selection
|
|
39
|
+
const from = Math.min(...ranges.map(range => range.$from.pos))
|
|
40
|
+
const to = Math.max(...ranges.map(range => range.$to.pos))
|
|
41
|
+
const isSame = prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)
|
|
42
|
+
|
|
43
|
+
this.#tippy ??= tippy(view.dom, {
|
|
44
|
+
trigger: 'manual',
|
|
45
|
+
interactive: true,
|
|
46
|
+
...this.#tippyOptions,
|
|
47
|
+
content: this.element,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
if (composing || isSame)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
if (!this.#shouldShow(view, prevState)) {
|
|
54
|
+
this.hide()
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.#tippy.setProps({
|
|
59
|
+
getReferenceClientRect: () => posToDOMRect(view, from, to),
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
this.show()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
update = (view: EditorView, prevState?: EditorState): void => {
|
|
66
|
+
const updater = debounce(this.#onUpdate, this.#debounce)
|
|
67
|
+
|
|
68
|
+
updater(view, prevState)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#_shouldShow(view: EditorView): boolean {
|
|
72
|
+
const { doc, selection } = view.state
|
|
73
|
+
const { empty, from, to } = selection
|
|
74
|
+
|
|
75
|
+
const isEmptyTextBlock = !doc.textBetween(from, to).length && view.state.selection instanceof TextSelection
|
|
76
|
+
|
|
77
|
+
const isTooltipChildren = this.element.contains(document.activeElement)
|
|
78
|
+
|
|
79
|
+
const notHasFocus = !view.hasFocus() && !isTooltipChildren
|
|
80
|
+
|
|
81
|
+
const isReadonly = !view.editable
|
|
82
|
+
|
|
83
|
+
if (
|
|
84
|
+
notHasFocus
|
|
85
|
+
|| empty
|
|
86
|
+
|| isEmptyTextBlock
|
|
87
|
+
|| isReadonly
|
|
88
|
+
)
|
|
89
|
+
return false
|
|
90
|
+
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
destroy = () => {
|
|
95
|
+
this.#tippy?.destroy()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
show = () => {
|
|
99
|
+
this.#tippy?.show()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
hide = () => {
|
|
103
|
+
this.#tippy?.hide()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
getInstance = () => {
|
|
107
|
+
return this.#tippy
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -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 +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 +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 +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"}
|
package/lib/utility/element.d.ts
DELETED
|
@@ -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"}
|
package/lib/utility/index.d.ts
DELETED
|
@@ -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
|
-
}
|
package/src/utility/element.ts
DELETED
package/src/utility/index.ts
DELETED
|
@@ -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
|
-
}
|