@milkdown/plugin-slash 6.5.2 → 6.5.4

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