@prosekit/web 0.7.0 → 0.7.2
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/dist/{get-safe-editor-view-CqJWgxo1.js → get-default-state-CIEy7xrl.js} +1 -11
- package/dist/get-safe-editor-view-DENm4avv.js +11 -0
- package/dist/inject-style-RwRNoINh.js +79 -0
- package/dist/prosekit-web-autocomplete.d.ts +58 -58
- package/dist/prosekit-web-autocomplete.js +2 -1
- package/dist/prosekit-web-block-handle.d.ts +48 -33
- package/dist/prosekit-web-block-handle.js +86 -67
- package/dist/prosekit-web-drop-indicator.d.ts +11 -11
- package/dist/prosekit-web-drop-indicator.js +5 -2
- package/dist/prosekit-web-inline-popover.d.ts +49 -49
- package/dist/prosekit-web-resizable.d.ts +9 -9
- package/dist/prosekit-web-table-handle.d.ts +90 -60
- package/dist/prosekit-web-table-handle.js +110 -48
- package/dist/use-scrolling-BNfsQs3S.js +35 -0
- package/package.json +13 -12
- package/dist/assign-styles-3yY6F1UX.js +0 -10
- package/dist/clone-element-i6RFnyj4.js +0 -41
|
@@ -8,14 +8,4 @@ function getStateWithDefaults(state, props) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
//#endregion
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @internal
|
|
14
|
-
*/
|
|
15
|
-
function getSafeEditorView(editor) {
|
|
16
|
-
if (!editor || !editor.mounted) return;
|
|
17
|
-
return editor.view;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
//#endregion
|
|
21
|
-
export { getSafeEditorView, getStateWithDefaults };
|
|
11
|
+
export { getStateWithDefaults };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { getDocument, getId } from "@ocavue/utils";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/clone-element.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates a deep clone of an Element, including all computed styles so that
|
|
6
|
+
* it looks almost exactly the same as the original element.
|
|
7
|
+
*/
|
|
8
|
+
function deepCloneElement(element) {
|
|
9
|
+
const clonedElement = element.cloneNode(true);
|
|
10
|
+
const style = deepCopyStyles(element, clonedElement);
|
|
11
|
+
return [clonedElement, style];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a clone of an Element, including all computed styles so that
|
|
15
|
+
* it looks similar enough to the original element.
|
|
16
|
+
*/
|
|
17
|
+
function cloneElement(element) {
|
|
18
|
+
const clonedElement = element.cloneNode();
|
|
19
|
+
const style = copyStyles(element, clonedElement);
|
|
20
|
+
return [clonedElement, style];
|
|
21
|
+
}
|
|
22
|
+
function deepCopyStyles(source, target) {
|
|
23
|
+
const sources = [source];
|
|
24
|
+
const targets = [target];
|
|
25
|
+
const styles = [];
|
|
26
|
+
while (sources.length > 0 && sources.length === targets.length) {
|
|
27
|
+
const source$1 = sources.pop();
|
|
28
|
+
const target$1 = targets.pop();
|
|
29
|
+
if (!source$1 || !target$1) break;
|
|
30
|
+
const style = copyStyles(source$1, target$1);
|
|
31
|
+
if (style) styles.push(style);
|
|
32
|
+
sources.push(...source$1.children);
|
|
33
|
+
targets.push(...target$1.children);
|
|
34
|
+
}
|
|
35
|
+
return styles.join("\n");
|
|
36
|
+
}
|
|
37
|
+
function copyStyles(source, target) {
|
|
38
|
+
if (!source || !target) return "";
|
|
39
|
+
const view = source.ownerDocument?.defaultView;
|
|
40
|
+
if (!view) return "";
|
|
41
|
+
const sourceStyle = view.getComputedStyle(source);
|
|
42
|
+
const targetStyle = target.style;
|
|
43
|
+
if (!sourceStyle || !targetStyle) return "";
|
|
44
|
+
for (const key of sourceStyle) targetStyle.setProperty(key, sourceStyle.getPropertyValue(key), sourceStyle.getPropertyPriority(key));
|
|
45
|
+
const styles = [];
|
|
46
|
+
for (const pseudoSelector of [":before", ":after"]) {
|
|
47
|
+
const sourcePseudoStyle = view.getComputedStyle(source, pseudoSelector);
|
|
48
|
+
const targetPseudoStyle = view.getComputedStyle(target, pseudoSelector);
|
|
49
|
+
if (!sourcePseudoStyle) continue;
|
|
50
|
+
const content = sourcePseudoStyle.getPropertyValue("content");
|
|
51
|
+
const hasPseudoElement = content && content !== "none" && content !== "normal";
|
|
52
|
+
if (!hasPseudoElement) continue;
|
|
53
|
+
const cssProps = [];
|
|
54
|
+
for (const property of sourcePseudoStyle) {
|
|
55
|
+
const sourceValue = sourcePseudoStyle.getPropertyValue(property);
|
|
56
|
+
const sourcePriority = sourcePseudoStyle.getPropertyPriority(property);
|
|
57
|
+
const targetValue = targetPseudoStyle.getPropertyValue(property);
|
|
58
|
+
const targetPriority = targetPseudoStyle.getPropertyPriority(property);
|
|
59
|
+
if (sourceValue !== targetValue || sourcePriority !== targetPriority) cssProps.push(`${property}: ${sourceValue}${sourcePriority ? " !important" : ""};`);
|
|
60
|
+
}
|
|
61
|
+
const uniqueClassName = `clone-pseudo-element-${getId()}`;
|
|
62
|
+
target.classList.add(uniqueClassName);
|
|
63
|
+
styles.push(`.${uniqueClassName}${pseudoSelector} { ${cssProps.join(" ")} }`);
|
|
64
|
+
}
|
|
65
|
+
return styles.join("\n");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/utils/inject-style.ts
|
|
70
|
+
function injectStyle(container, styleText) {
|
|
71
|
+
if (!styleText) return;
|
|
72
|
+
const document = getDocument(container);
|
|
73
|
+
const style = document.createElement("style");
|
|
74
|
+
style.textContent = styleText;
|
|
75
|
+
container.appendChild(style);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { cloneElement, deepCloneElement, injectStyle };
|
|
@@ -20,19 +20,19 @@ declare class AutocompleteEmptyElement extends AutocompleteEmptyElementBase {}
|
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/components/autocomplete/autocomplete-empty/setup.d.ts
|
|
22
22
|
/**
|
|
23
|
-
* @internal
|
|
24
|
-
*/
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
25
|
declare const useAutocompleteEmpty: typeof useListboxEmpty;
|
|
26
26
|
//#endregion
|
|
27
27
|
//#region src/components/autocomplete/autocomplete-item/types.d.ts
|
|
28
28
|
interface AutocompleteItemProps {
|
|
29
29
|
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
* The value of the item, which will be matched against the query.
|
|
31
|
+
*
|
|
32
|
+
* If not provided, the value is the item's text content.
|
|
33
|
+
*
|
|
34
|
+
* @default ""
|
|
35
|
+
*/
|
|
36
36
|
value: string;
|
|
37
37
|
}
|
|
38
38
|
/** @internal */
|
|
@@ -47,21 +47,21 @@ declare class AutocompleteItemElement extends AutocompleteItemElementBase {}
|
|
|
47
47
|
//#endregion
|
|
48
48
|
//#region src/components/autocomplete/autocomplete-item/setup.d.ts
|
|
49
49
|
/**
|
|
50
|
-
* @internal
|
|
51
|
-
*/
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
52
|
declare function useAutocompleteItem(element: ConnectableElement, {
|
|
53
53
|
state,
|
|
54
54
|
emit
|
|
55
55
|
}: SetupOptions<AutocompleteItemProps, AutocompleteItemEvents>): void;
|
|
56
56
|
//#endregion
|
|
57
57
|
//#region src/components/autocomplete/autocomplete-list/types.d.ts
|
|
58
|
-
interface AutocompleteListProps extends Pick<ListboxProps,
|
|
58
|
+
interface AutocompleteListProps extends Pick<ListboxProps, 'filter'> {
|
|
59
59
|
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
* The ProseKit editor instance.
|
|
61
|
+
*
|
|
62
|
+
* @default null
|
|
63
|
+
* @hidden
|
|
64
|
+
*/
|
|
65
65
|
editor: Editor | null;
|
|
66
66
|
}
|
|
67
67
|
declare const autocompleteListProps: PropDeclarations<AutocompleteListProps>;
|
|
@@ -74,8 +74,8 @@ declare class AutocompleteListElement extends AutocompleteListElementBase {}
|
|
|
74
74
|
//#endregion
|
|
75
75
|
//#region src/components/autocomplete/autocomplete-list/setup.d.ts
|
|
76
76
|
/**
|
|
77
|
-
* @internal
|
|
78
|
-
*/
|
|
77
|
+
* @internal
|
|
78
|
+
*/
|
|
79
79
|
declare function useAutocompleteList(element: ConnectableElement, {
|
|
80
80
|
state,
|
|
81
81
|
emit
|
|
@@ -84,61 +84,61 @@ declare function useAutocompleteList(element: ConnectableElement, {
|
|
|
84
84
|
//#region src/components/autocomplete/autocomplete-popover/types.d.ts
|
|
85
85
|
interface AutocompletePopoverProps extends OverlayPositionerProps {
|
|
86
86
|
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
* The ProseKit editor instance.
|
|
88
|
+
*
|
|
89
|
+
* @default null
|
|
90
|
+
* @hidden
|
|
91
|
+
*/
|
|
92
92
|
editor: Editor | null;
|
|
93
93
|
/**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
* The regular expression to match the query text to autocomplete.
|
|
95
|
+
*
|
|
96
|
+
* @default null
|
|
97
|
+
*/
|
|
98
98
|
regex: RegExp | null;
|
|
99
99
|
/**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
placement: OverlayPositionerProps[
|
|
100
|
+
* The placement of the popover, relative to the text cursor.
|
|
101
|
+
*
|
|
102
|
+
* @default "bottom-start"
|
|
103
|
+
*/
|
|
104
|
+
placement: OverlayPositionerProps['placement'];
|
|
105
105
|
/**
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
offset: OverlayPositionerProps[
|
|
106
|
+
* The distance between the popover and the hovered block.
|
|
107
|
+
*
|
|
108
|
+
* @default 4
|
|
109
|
+
*/
|
|
110
|
+
offset: OverlayPositionerProps['offset'];
|
|
111
111
|
/**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
inline: OverlayPositionerProps[
|
|
112
|
+
* @default true
|
|
113
|
+
*/
|
|
114
|
+
inline: OverlayPositionerProps['inline'];
|
|
115
115
|
/**
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
hoist: OverlayPositionerProps[
|
|
116
|
+
* @default true
|
|
117
|
+
*/
|
|
118
|
+
hoist: OverlayPositionerProps['hoist'];
|
|
119
119
|
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
fitViewport: OverlayPositionerProps[
|
|
120
|
+
* @default true
|
|
121
|
+
*/
|
|
122
|
+
fitViewport: OverlayPositionerProps['fitViewport'];
|
|
123
123
|
/**
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
boundary: OverlayPositionerProps[
|
|
124
|
+
* @default "The body element"
|
|
125
|
+
*/
|
|
126
|
+
boundary: OverlayPositionerProps['boundary'];
|
|
127
127
|
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
overflowPadding: OverlayPositionerProps[
|
|
128
|
+
* @default 8
|
|
129
|
+
*/
|
|
130
|
+
overflowPadding: OverlayPositionerProps['overflowPadding'];
|
|
131
131
|
}
|
|
132
132
|
/** @internal */
|
|
133
133
|
declare const autocompletePopoverProps: PropDeclarations<AutocompletePopoverProps>;
|
|
134
134
|
interface AutocompletePopoverEvents extends OverlayPositionerEvents {
|
|
135
135
|
/**
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
* Fired when the open state changes.
|
|
137
|
+
*/
|
|
138
138
|
openChange: CustomEvent<boolean>;
|
|
139
139
|
/**
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
* Fired when the query changes.
|
|
141
|
+
*/
|
|
142
142
|
queryChange: CustomEvent<string>;
|
|
143
143
|
}
|
|
144
144
|
/** @internal */
|
|
@@ -150,8 +150,8 @@ declare class AutocompletePopoverElement extends AutocompletePopoverElementBase
|
|
|
150
150
|
//#endregion
|
|
151
151
|
//#region src/components/autocomplete/autocomplete-popover/setup.d.ts
|
|
152
152
|
/**
|
|
153
|
-
* @internal
|
|
154
|
-
*/
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
155
155
|
declare function useAutocompletePopover(host: ConnectableElement, {
|
|
156
156
|
state,
|
|
157
157
|
emit
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getStateWithDefaults } from "./get-default-state-CIEy7xrl.js";
|
|
2
2
|
import { useEditorExtension } from "./use-editor-extension-Cc7ZG7uj.js";
|
|
3
|
+
import { getSafeEditorView } from "./get-safe-editor-view-DENm4avv.js";
|
|
3
4
|
import { createComputed, createContext, createSignal, defineCustomElement, registerCustomElement, useAnimationFrame, useAttribute, useEffect, useEventListener } from "@aria-ui/core";
|
|
4
5
|
import { listboxProps, useListbox, useListboxEmpty, useListboxItem } from "@aria-ui/listbox/elements";
|
|
5
6
|
import { listboxEvents, listboxItemEvents, listboxProps as listboxProps$1 } from "@aria-ui/listbox";
|
|
@@ -7,11 +7,11 @@ import { Placement } from "@floating-ui/dom";
|
|
|
7
7
|
//#region src/components/block-handle/block-handle-add/types.d.ts
|
|
8
8
|
interface BlockHandleAddProps {
|
|
9
9
|
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
* The ProseKit editor instance.
|
|
11
|
+
*
|
|
12
|
+
* @default null
|
|
13
|
+
* @hidden
|
|
14
|
+
*/
|
|
15
15
|
editor: Editor | null;
|
|
16
16
|
}
|
|
17
17
|
/** @internal */
|
|
@@ -27,8 +27,8 @@ declare class BlockHandleAddElement extends BlockHandleAddElementBase {}
|
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region src/components/block-handle/block-handle-add/setup.d.ts
|
|
29
29
|
/**
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
32
|
declare function useBlockHandleAdd(host: ConnectableElement, {
|
|
33
33
|
state
|
|
34
34
|
}: {
|
|
@@ -38,11 +38,11 @@ declare function useBlockHandleAdd(host: ConnectableElement, {
|
|
|
38
38
|
//#region src/components/block-handle/block-handle-draggable/types.d.ts
|
|
39
39
|
interface BlockHandleDraggableProps {
|
|
40
40
|
/**
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
* The ProseKit editor instance.
|
|
42
|
+
*
|
|
43
|
+
* @default null
|
|
44
|
+
* @hidden
|
|
45
|
+
*/
|
|
46
46
|
editor: Editor | null;
|
|
47
47
|
}
|
|
48
48
|
/** @internal */
|
|
@@ -58,8 +58,8 @@ declare class BlockHandleDraggableElement extends BlockHandleDraggableElementBas
|
|
|
58
58
|
//#endregion
|
|
59
59
|
//#region src/components/block-handle/block-handle-draggable/setup.d.ts
|
|
60
60
|
/**
|
|
61
|
-
* @internal
|
|
62
|
-
*/
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
63
|
declare function useBlockHandleDraggable(host: ConnectableElement, {
|
|
64
64
|
state
|
|
65
65
|
}: {
|
|
@@ -67,34 +67,49 @@ declare function useBlockHandleDraggable(host: ConnectableElement, {
|
|
|
67
67
|
}): void;
|
|
68
68
|
//#endregion
|
|
69
69
|
//#region src/components/block-handle/block-handle-popover/types.d.ts
|
|
70
|
-
interface BlockHandlePopoverProps extends Omit<OverlayPositionerProps,
|
|
70
|
+
interface BlockHandlePopoverProps extends Omit<OverlayPositionerProps, 'placement' | 'hoist' | 'flip' | 'shift' | 'hide'> {
|
|
71
71
|
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
* The ProseKit editor instance.
|
|
73
|
+
*
|
|
74
|
+
* @default null
|
|
75
|
+
* @hidden
|
|
76
|
+
*/
|
|
77
77
|
editor: Editor | null;
|
|
78
78
|
/**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
* The placement of the popover, relative to the hovered block.
|
|
80
|
+
*
|
|
81
|
+
* @default "left"
|
|
82
|
+
*/
|
|
83
83
|
placement: Placement;
|
|
84
84
|
/**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
* Whether to use the browser [Popover API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API)
|
|
86
|
+
* to place the floating element on top of other page content.
|
|
87
|
+
*
|
|
88
|
+
* @default false
|
|
89
|
+
*/
|
|
90
90
|
hoist: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* @default false
|
|
93
|
+
* @hidden
|
|
94
|
+
*/
|
|
95
|
+
flip: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* @default false
|
|
98
|
+
* @hidden
|
|
99
|
+
*/
|
|
100
|
+
shift: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* @default true
|
|
103
|
+
* @hidden
|
|
104
|
+
*/
|
|
105
|
+
hide: boolean;
|
|
91
106
|
}
|
|
92
107
|
/** @internal */
|
|
93
108
|
declare const blockHandlePopoverProps: PropDeclarations<BlockHandlePopoverProps>;
|
|
94
109
|
interface BlockHandlePopoverEvents extends OverlayPositionerEvents {
|
|
95
110
|
/**
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
* Fired when the hovered block changes.
|
|
112
|
+
*/
|
|
98
113
|
stateChange: CustomEvent<{
|
|
99
114
|
node: ProseMirrorNode;
|
|
100
115
|
pos: number;
|
|
@@ -109,8 +124,8 @@ declare class BlockHandlePopoverElement extends BlockHandlePopoverElementBase {}
|
|
|
109
124
|
//#endregion
|
|
110
125
|
//#region src/components/block-handle/block-handle-popover/setup.d.ts
|
|
111
126
|
/**
|
|
112
|
-
* @internal
|
|
113
|
-
*/
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
114
129
|
declare function useBlockHandlePopover(host: ConnectableElement, {
|
|
115
130
|
state,
|
|
116
131
|
emit
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEditorExtension } from "./use-editor-extension-Cc7ZG7uj.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { getSafeEditorView } from "./get-safe-editor-view-DENm4avv.js";
|
|
3
|
+
import { assignStyles, useScrolling } from "./use-scrolling-BNfsQs3S.js";
|
|
4
|
+
import { deepCloneElement, injectStyle } from "./inject-style-RwRNoINh.js";
|
|
4
5
|
import { createComputed, createContext, createSignal, defineCustomElement, registerCustomElement, useAttribute, useEffect, useEventListener } from "@aria-ui/core";
|
|
5
6
|
import { defineDOMEventHandler, insertDefaultBlock, union } from "@prosekit/core";
|
|
6
7
|
import { overlayPositionerEvents, overlayPositionerProps, useOverlayPositionerState } from "@aria-ui/overlay/elements";
|
|
@@ -55,6 +56,38 @@ const BlockHandleAddElementBase = defineCustomElement({
|
|
|
55
56
|
var BlockHandleAddElement = class extends BlockHandleAddElementBase {};
|
|
56
57
|
registerCustomElement("prosekit-block-handle-add", BlockHandleAddElement);
|
|
57
58
|
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/utils/get-client-rect.ts
|
|
61
|
+
/**
|
|
62
|
+
* Similar to `element.getBoundingClientRect`, but handles `display: contents` elements.
|
|
63
|
+
*/
|
|
64
|
+
function getClientRect(element) {
|
|
65
|
+
const rect = element.getBoundingClientRect();
|
|
66
|
+
if (rect.width === 0 && rect.height === 0 && rect.x === 0 && rect.y === 0) {
|
|
67
|
+
if (element.getClientRects().length === 0) {
|
|
68
|
+
const children = Array.from(element.children);
|
|
69
|
+
const rects = children.map((child) => getClientRect(child));
|
|
70
|
+
if (rects.length === 0) return rect;
|
|
71
|
+
if (rects.length === 1) return rects[0];
|
|
72
|
+
let { top, bottom, left, right } = rects[0];
|
|
73
|
+
for (let i = 1; i < rects.length; i++) {
|
|
74
|
+
const r = rects[i];
|
|
75
|
+
if (r.top < top) top = r.top;
|
|
76
|
+
if (r.bottom > bottom) bottom = r.bottom;
|
|
77
|
+
if (r.left < left) left = r.left;
|
|
78
|
+
if (r.right > right) right = r.right;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
top,
|
|
82
|
+
bottom,
|
|
83
|
+
left,
|
|
84
|
+
right
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return rect;
|
|
89
|
+
}
|
|
90
|
+
|
|
58
91
|
//#endregion
|
|
59
92
|
//#region src/utils/max-z-index.ts
|
|
60
93
|
const maxZIndex = "2147483647";
|
|
@@ -73,8 +106,11 @@ const maxZIndex = "2147483647";
|
|
|
73
106
|
* - Removes the container from the document body after the next frame.
|
|
74
107
|
*/
|
|
75
108
|
function setDragPreview(event, element) {
|
|
76
|
-
const
|
|
77
|
-
const
|
|
109
|
+
const { top, bottom, left, right } = getClientRect(element);
|
|
110
|
+
const width = right - left;
|
|
111
|
+
const height = bottom - top;
|
|
112
|
+
const elementX = left;
|
|
113
|
+
const elementY = top;
|
|
78
114
|
const { clientX, clientY } = event;
|
|
79
115
|
const document = element.ownerDocument;
|
|
80
116
|
const container = document.createElement("div");
|
|
@@ -93,13 +129,14 @@ function setDragPreview(event, element) {
|
|
|
93
129
|
width: `${width + borderX}px`,
|
|
94
130
|
height: `${height + borderY}px`
|
|
95
131
|
});
|
|
96
|
-
const clonedElement = deepCloneElement(element);
|
|
132
|
+
const [clonedElement, styleText] = deepCloneElement(element);
|
|
97
133
|
assignStyles(clonedElement, {
|
|
98
|
-
|
|
99
|
-
|
|
134
|
+
opacity: "0.5",
|
|
135
|
+
margin: "0"
|
|
100
136
|
});
|
|
101
137
|
document.body.appendChild(container);
|
|
102
138
|
container.appendChild(clonedElement);
|
|
139
|
+
injectStyle(container, styleText);
|
|
103
140
|
event.dataTransfer?.setDragImage(container, Math.max(-outsideX, 0), Math.max(-outsideY, 0));
|
|
104
141
|
requestAnimationFrame(() => {
|
|
105
142
|
container.remove();
|
|
@@ -113,12 +150,27 @@ function setDragPreview(event, element) {
|
|
|
113
150
|
*/
|
|
114
151
|
function useBlockHandleDraggable(host, { state }) {
|
|
115
152
|
const context = blockPopoverContext.consume(host);
|
|
153
|
+
const dragging = draggingContext.consume(host);
|
|
116
154
|
useEffect(host, () => {
|
|
117
155
|
host.draggable = true;
|
|
118
156
|
});
|
|
119
157
|
usePointerDownHandler(host, context, state.editor);
|
|
120
|
-
|
|
121
|
-
|
|
158
|
+
useEventListener(host, "dragstart", (event) => {
|
|
159
|
+
dragging.set(true);
|
|
160
|
+
const view = getSafeEditorView(state.editor.get());
|
|
161
|
+
const hoverState = context.get();
|
|
162
|
+
if (view && hoverState) {
|
|
163
|
+
view.dom.classList.add("prosekit-dragging");
|
|
164
|
+
createDraggingPreview(view, hoverState, event);
|
|
165
|
+
setViewDragging(view, hoverState);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
useEventListener(host, "dragend", () => {
|
|
169
|
+
dragging.set(false);
|
|
170
|
+
const view = getSafeEditorView(state.editor.get());
|
|
171
|
+
if (view) view.dom.classList.remove("prosekit-dragging");
|
|
172
|
+
});
|
|
173
|
+
useAttribute(host, "data-dragging", () => dragging.get() ? "" : void 0);
|
|
122
174
|
}
|
|
123
175
|
function usePointerDownHandler(host, context, editor) {
|
|
124
176
|
useEventListener(host, "pointerdown", () => {
|
|
@@ -131,39 +183,24 @@ function usePointerDownHandler(host, context, editor) {
|
|
|
131
183
|
});
|
|
132
184
|
});
|
|
133
185
|
}
|
|
134
|
-
function
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
event.dataTransfer.setData("text/html", element.outerHTML);
|
|
144
|
-
event.dataTransfer.effectAllowed = "copyMove";
|
|
145
|
-
setDragPreview(event, element);
|
|
146
|
-
const dragging = {
|
|
147
|
-
slice: new Slice(Fragment.from(node), 0, 0),
|
|
148
|
-
move: true,
|
|
149
|
-
node: NodeSelection.create(view.state.doc, pos)
|
|
150
|
-
};
|
|
151
|
-
view.dragging = dragging;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
function useDataDraggingAttribute(host) {
|
|
155
|
-
const dragging = useDragging(host);
|
|
156
|
-
useAttribute(host, "data-dragging", () => dragging.get() ? "" : void 0);
|
|
186
|
+
function createDraggingPreview(view, hoverState, event) {
|
|
187
|
+
if (!event.dataTransfer) return;
|
|
188
|
+
const { pos } = hoverState;
|
|
189
|
+
const element = view.nodeDOM(pos);
|
|
190
|
+
if (!element || !isHTMLElement(element)) return;
|
|
191
|
+
event.dataTransfer.clearData();
|
|
192
|
+
event.dataTransfer.setData("text/html", element.outerHTML);
|
|
193
|
+
event.dataTransfer.effectAllowed = "copyMove";
|
|
194
|
+
setDragPreview(event, element);
|
|
157
195
|
}
|
|
158
|
-
function
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return dragging;
|
|
196
|
+
function setViewDragging(view, hoverState) {
|
|
197
|
+
const { node, pos } = hoverState;
|
|
198
|
+
const dragging = {
|
|
199
|
+
slice: new Slice(Fragment.from(node), 0, 0),
|
|
200
|
+
move: true,
|
|
201
|
+
node: NodeSelection.create(view.state.doc, pos)
|
|
202
|
+
};
|
|
203
|
+
view.dragging = dragging;
|
|
167
204
|
}
|
|
168
205
|
|
|
169
206
|
//#endregion
|
|
@@ -183,30 +220,6 @@ const BlockHandleDraggableElementBase = defineCustomElement({
|
|
|
183
220
|
var BlockHandleDraggableElement = class extends BlockHandleDraggableElementBase {};
|
|
184
221
|
registerCustomElement("prosekit-block-handle-draggable", BlockHandleDraggableElement);
|
|
185
222
|
|
|
186
|
-
//#endregion
|
|
187
|
-
//#region src/utils/get-client-rect.ts
|
|
188
|
-
/**
|
|
189
|
-
* Similar to `element.getBoundingClientRect`, but handles `display: contents` elements.
|
|
190
|
-
*/
|
|
191
|
-
function getClientRect(element) {
|
|
192
|
-
const rect = element.getBoundingClientRect();
|
|
193
|
-
if (rect.width === 0 && rect.height === 0 && rect.x === 0 && rect.y === 0) {
|
|
194
|
-
if (element.getClientRects().length === 0) {
|
|
195
|
-
const children = Array.from(element.children);
|
|
196
|
-
const rects = children.map((child) => getClientRect(child));
|
|
197
|
-
if (rects.length === 0) return rect;
|
|
198
|
-
if (rects.length === 1) return rects[0];
|
|
199
|
-
return {
|
|
200
|
-
top: Math.min(...rects.map((rect$1) => rect$1.top)),
|
|
201
|
-
right: Math.max(...rects.map((rect$1) => rect$1.right)),
|
|
202
|
-
bottom: Math.max(...rects.map((rect$1) => rect$1.bottom)),
|
|
203
|
-
left: Math.min(...rects.map((rect$1) => rect$1.left))
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return rect;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
223
|
//#endregion
|
|
211
224
|
//#region src/utils/throttle.ts
|
|
212
225
|
/**
|
|
@@ -409,7 +422,10 @@ function useBlockHandlePopover(host, { state, emit }) {
|
|
|
409
422
|
blockPopoverContext.provide(host, context);
|
|
410
423
|
const dragging = createSignal(false);
|
|
411
424
|
draggingContext.provide(host, dragging);
|
|
412
|
-
const
|
|
425
|
+
const scrolling = useScrolling(host);
|
|
426
|
+
const open = createComputed(() => {
|
|
427
|
+
return !!context.get() && !scrolling.get();
|
|
428
|
+
});
|
|
413
429
|
useHoverExtension(host, editor, (referenceValue, hoverState) => {
|
|
414
430
|
reference.set(referenceValue);
|
|
415
431
|
context.set(hoverState);
|
|
@@ -444,7 +460,10 @@ const blockHandlePopoverProps = {
|
|
|
444
460
|
...overlayPositionerProps,
|
|
445
461
|
editor: { default: null },
|
|
446
462
|
placement: { default: "left" },
|
|
447
|
-
hoist: { default: false }
|
|
463
|
+
hoist: { default: false },
|
|
464
|
+
flip: { default: false },
|
|
465
|
+
shift: { default: false },
|
|
466
|
+
hide: { default: true }
|
|
448
467
|
};
|
|
449
468
|
/** @internal */
|
|
450
469
|
const blockHandlePopoverEvents = {
|