@milkdown/plugin-slash 6.5.2 → 6.5.3
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/config.d.ts +11 -11
- package/lib/config.d.ts.map +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +111 -106
- package/lib/index.es.js.map +1 -1
- package/lib/item.d.ts +3 -3
- package/lib/item.d.ts.map +1 -1
- package/lib/prose-plugin/dropdown.d.ts +3 -3
- package/lib/prose-plugin/dropdown.d.ts.map +1 -1
- package/lib/prose-plugin/index.d.ts +2 -2
- package/lib/prose-plugin/index.d.ts.map +1 -1
- package/lib/prose-plugin/input.d.ts +3 -3
- package/lib/prose-plugin/input.d.ts.map +1 -1
- package/lib/prose-plugin/props.d.ts +5 -4
- package/lib/prose-plugin/props.d.ts.map +1 -1
- package/lib/prose-plugin/status.d.ts +5 -5
- package/lib/prose-plugin/status.d.ts.map +1 -1
- package/lib/prose-plugin/view.d.ts +4 -4
- package/lib/prose-plugin/view.d.ts.map +1 -1
- package/lib/style.d.ts +1 -1
- package/lib/style.d.ts.map +1 -1
- package/lib/utility.d.ts +3 -3
- package/lib/utility.d.ts.map +1 -1
- package/package.json +15 -15
- package/src/config.ts +126 -121
- package/src/index.ts +25 -24
- package/src/item.ts +14 -14
- package/src/prose-plugin/dropdown.ts +45 -46
- package/src/prose-plugin/index.ts +19 -18
- package/src/prose-plugin/input.ts +122 -108
- package/src/prose-plugin/props.ts +79 -81
- package/src/prose-plugin/status.ts +29 -28
- package/src/prose-plugin/view.ts +104 -102
- package/src/style.ts +20 -18
- package/src/utility.ts +63 -64
package/src/prose-plugin/view.ts
CHANGED
|
@@ -1,110 +1,112 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import { missingRootElement } from '@milkdown/exception'
|
|
3
|
-
import { calculateNodePosition } from '@milkdown/prose'
|
|
4
|
-
import { EditorView } from '@milkdown/prose/view'
|
|
5
|
-
import { ThemeUtils } from '@milkdown/utils'
|
|
2
|
+
import { missingRootElement } from '@milkdown/exception'
|
|
3
|
+
import { calculateNodePosition } from '@milkdown/prose'
|
|
4
|
+
import type { EditorView } from '@milkdown/prose/view'
|
|
5
|
+
import type { ThemeUtils } from '@milkdown/utils'
|
|
6
6
|
|
|
7
|
-
import { createDropdown } from '../utility'
|
|
8
|
-
import { renderDropdown } from './dropdown'
|
|
7
|
+
import { createDropdown } from '../utility'
|
|
8
|
+
import { renderDropdown } from './dropdown'
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from './input'
|
|
17
|
-
import { Status } from './status'
|
|
10
|
+
createMouseManager,
|
|
11
|
+
handleClick,
|
|
12
|
+
handleKeydown,
|
|
13
|
+
handleMouseEnter,
|
|
14
|
+
handleMouseLeave,
|
|
15
|
+
handleMouseMove,
|
|
16
|
+
} from './input'
|
|
17
|
+
import type { Status } from './status'
|
|
18
18
|
|
|
19
19
|
export const defaultCalcPosition = (view: EditorView, dropdownElement: HTMLElement) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
direction === 'top'
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export type CalcPosition = (view: EditorView, dropdownElement: HTMLElement) => void
|
|
20
|
+
calculateNodePosition(view, dropdownElement, (selected, target, parent) => {
|
|
21
|
+
const $editor = dropdownElement.parentElement
|
|
22
|
+
if (!$editor)
|
|
23
|
+
throw missingRootElement()
|
|
24
|
+
|
|
25
|
+
let left = selected.left - parent.left
|
|
26
|
+
|
|
27
|
+
if (left < 0)
|
|
28
|
+
left = 0
|
|
29
|
+
|
|
30
|
+
let direction: 'top' | 'bottom'
|
|
31
|
+
let maxHeight: number | undefined
|
|
32
|
+
const selectedToTop = selected.top - parent.top
|
|
33
|
+
const selectedToBottom = parent.height + parent.top - selected.bottom
|
|
34
|
+
if (selectedToBottom >= target.height + 28) {
|
|
35
|
+
direction = 'bottom'
|
|
36
|
+
}
|
|
37
|
+
else if (selectedToTop >= target.height + 28) {
|
|
38
|
+
direction = 'top'
|
|
39
|
+
}
|
|
40
|
+
else if (selectedToBottom >= selectedToTop) {
|
|
41
|
+
direction = 'bottom'
|
|
42
|
+
maxHeight = selectedToBottom - 28
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
direction = 'top'
|
|
46
|
+
maxHeight = selectedToTop - 28
|
|
47
|
+
}
|
|
48
|
+
if (selectedToTop < 0 || selectedToBottom < 0) {
|
|
49
|
+
maxHeight = parent.height - selected.height - 28
|
|
50
|
+
if (maxHeight > target.height)
|
|
51
|
+
maxHeight = undefined
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const top
|
|
55
|
+
= direction === 'top'
|
|
56
|
+
? selected.top - parent.top - (maxHeight ?? target.height) - 14 + $editor.scrollTop
|
|
57
|
+
: selected.bottom - parent.top + 14 + $editor.scrollTop
|
|
58
|
+
|
|
59
|
+
dropdownElement.style.maxHeight = maxHeight !== undefined && maxHeight > 0 ? `${maxHeight}px` : ''
|
|
60
|
+
|
|
61
|
+
return [top, left]
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type CalcPosition = (view: EditorView, dropdownElement: HTMLElement) => void
|
|
66
66
|
|
|
67
67
|
export const createView = (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
status: Status,
|
|
69
|
+
view: EditorView,
|
|
70
|
+
utils: ThemeUtils,
|
|
71
|
+
className: string,
|
|
72
|
+
calcPosition: CalcPosition,
|
|
73
73
|
) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
74
|
+
const wrapper = view.dom.parentNode
|
|
75
|
+
if (!wrapper)
|
|
76
|
+
return {}
|
|
77
|
+
|
|
78
|
+
const dropdownElement = createDropdown(utils, className)
|
|
79
|
+
const mouseManager = createMouseManager()
|
|
80
|
+
wrapper.appendChild(dropdownElement)
|
|
81
|
+
|
|
82
|
+
const _mouseMove = handleMouseMove(mouseManager)
|
|
83
|
+
const _mouseDown = handleClick(status, view, dropdownElement)
|
|
84
|
+
const _keydown = handleKeydown(status, view, dropdownElement, mouseManager)
|
|
85
|
+
const _mouseEnter = handleMouseEnter(status, mouseManager)
|
|
86
|
+
const _mouseLeave = handleMouseLeave()
|
|
87
|
+
|
|
88
|
+
wrapper.addEventListener('mousemove', _mouseMove)
|
|
89
|
+
wrapper.addEventListener('mousedown', _mouseDown)
|
|
90
|
+
wrapper.addEventListener('keydown', _keydown)
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
update: (view: EditorView) => {
|
|
94
|
+
const show = renderDropdown(status, dropdownElement, {
|
|
95
|
+
mouseEnter: _mouseEnter as EventListener,
|
|
96
|
+
mouseLeave: _mouseLeave as EventListener,
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
if (!show)
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
calcPosition(view, dropdownElement)
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
destroy: () => {
|
|
106
|
+
wrapper.removeEventListener('mousemove', _mouseMove)
|
|
107
|
+
wrapper.removeEventListener('mousedown', _mouseDown)
|
|
108
|
+
wrapper.removeEventListener('keydown', _keydown)
|
|
109
|
+
dropdownElement.remove()
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/style.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
+
import type {
|
|
3
|
+
Color,
|
|
4
|
+
Emotion,
|
|
5
|
+
ThemeManager,
|
|
6
|
+
} from '@milkdown/core'
|
|
2
7
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
ThemeShadow,
|
|
11
|
-
ThemeSize,
|
|
12
|
-
} from '@milkdown/core';
|
|
8
|
+
ThemeBorder,
|
|
9
|
+
ThemeColor,
|
|
10
|
+
ThemeFont,
|
|
11
|
+
ThemeScrollbar,
|
|
12
|
+
ThemeShadow,
|
|
13
|
+
ThemeSize,
|
|
14
|
+
} from '@milkdown/core'
|
|
13
15
|
|
|
14
16
|
const itemStyle = (themeManager: ThemeManager, { css }: Emotion) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity])
|
|
18
|
+
return css`
|
|
17
19
|
.slash-dropdown-item {
|
|
18
20
|
display: flex;
|
|
19
21
|
gap: 32px;
|
|
@@ -46,13 +48,13 @@ const itemStyle = (themeManager: ThemeManager, { css }: Emotion) => {
|
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
+
`
|
|
52
|
+
}
|
|
51
53
|
|
|
52
54
|
export const injectStyle = (themeManager: ThemeManager, emotion: Emotion) => {
|
|
53
|
-
|
|
55
|
+
const palette = (color: Color, opacity = 1) => themeManager.get(ThemeColor, [color, opacity])
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
return emotion.css`
|
|
56
58
|
width: 320px;
|
|
57
59
|
min-height: 48px;
|
|
58
60
|
max-height: 320px;
|
|
@@ -70,5 +72,5 @@ export const injectStyle = (themeManager: ThemeManager, emotion: Emotion) => {
|
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
${itemStyle(themeManager, emotion)}
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
+
`
|
|
76
|
+
}
|
package/src/utility.ts
CHANGED
|
@@ -1,86 +1,85 @@
|
|
|
1
1
|
/* Copyright 2021, Milkdown by Mirone. */
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
2
|
+
import type { ThemeManager } from '@milkdown/core'
|
|
3
|
+
import { ThemeIcon } from '@milkdown/core'
|
|
4
|
+
import type { Icon } from '@milkdown/design-system'
|
|
5
|
+
import { missingIcon } from '@milkdown/exception'
|
|
6
|
+
import type { Node } from '@milkdown/prose/model'
|
|
7
|
+
import type { Command } from '@milkdown/prose/state'
|
|
8
|
+
import type { ThemeUtils } from '@milkdown/utils'
|
|
8
9
|
|
|
9
|
-
import { injectStyle } from './style'
|
|
10
|
+
import { injectStyle } from './style'
|
|
10
11
|
|
|
11
12
|
export const createDropdown = (utils: ThemeUtils, className: string) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
13
|
+
const div = document.createElement('div')
|
|
14
|
+
div.setAttribute('role', 'listbox')
|
|
15
|
+
div.setAttribute('tabindex', '-1')
|
|
16
|
+
utils.themeManager.onFlush(() => {
|
|
17
|
+
const style = utils.getStyle(emotion => injectStyle(utils.themeManager, emotion))
|
|
18
|
+
|
|
19
|
+
if (style)
|
|
20
|
+
div.classList.add(style)
|
|
21
|
+
})
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
div.classList.add(utils.getClassName({}, className), 'hide')
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
}
|
|
25
|
+
return div
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
28
|
+
interface ItemOptions {
|
|
29
|
+
textClassName: string
|
|
30
|
+
}
|
|
31
31
|
export const createDropdownItem = (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
themeManager: ThemeManager,
|
|
33
|
+
text: string,
|
|
34
|
+
icon: Icon,
|
|
35
|
+
options?: Partial<ItemOptions>,
|
|
36
36
|
) => {
|
|
37
|
-
|
|
37
|
+
const textClassName = options?.textClassName ?? 'text'
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const div = document.createElement('div')
|
|
40
|
+
div.setAttribute('role', 'option')
|
|
41
|
+
div.classList.add('slash-dropdown-item')
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
const iconSpan = themeManager.get(ThemeIcon, icon)
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
45
|
+
if (!iconSpan)
|
|
46
|
+
throw missingIcon(icon)
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const textSpan = document.createElement('span')
|
|
49
|
+
textSpan.textContent = text
|
|
50
|
+
textSpan.className = textClassName
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
div.appendChild(iconSpan.dom)
|
|
53
|
+
div.appendChild(textSpan)
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
}
|
|
55
|
+
return div
|
|
56
|
+
}
|
|
58
57
|
|
|
59
58
|
export const getDepth = (node: Node) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
let cur = node
|
|
60
|
+
let depth = 0
|
|
61
|
+
while (cur.childCount) {
|
|
62
|
+
cur = cur.child(0)
|
|
63
|
+
depth += 1
|
|
64
|
+
}
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
}
|
|
66
|
+
return depth
|
|
67
|
+
}
|
|
69
68
|
|
|
70
69
|
const cleanUp: Command = (state, dispatch) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export const cleanUpAndCreateNode
|
|
79
|
-
(createCommand: () => void): Command =>
|
|
80
|
-
|
|
70
|
+
const { selection } = state
|
|
71
|
+
const { $from } = selection
|
|
72
|
+
const tr = state.tr.deleteRange($from.start(), $from.pos)
|
|
73
|
+
dispatch?.(tr)
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const cleanUpAndCreateNode
|
|
78
|
+
= (createCommand: () => void): Command =>
|
|
79
|
+
(state, dispatch, view) => {
|
|
81
80
|
if (view) {
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
cleanUp(state, dispatch, view)
|
|
82
|
+
createCommand()
|
|
84
83
|
}
|
|
85
|
-
return true
|
|
86
|
-
|
|
84
|
+
return true
|
|
85
|
+
}
|