@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.
@@ -8,14 +8,4 @@ function getStateWithDefaults(state, props) {
8
8
  }
9
9
 
10
10
  //#endregion
11
- //#region src/utils/get-safe-editor-view.ts
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,11 @@
1
+ //#region src/utils/get-safe-editor-view.ts
2
+ /**
3
+ * @internal
4
+ */
5
+ function getSafeEditorView(editor) {
6
+ if (!editor || !editor.mounted) return;
7
+ return editor.view;
8
+ }
9
+
10
+ //#endregion
11
+ export { getSafeEditorView };
@@ -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
- * 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
- */
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, "filter"> {
58
+ interface AutocompleteListProps extends Pick<ListboxProps, 'filter'> {
59
59
  /**
60
- * The ProseKit editor instance.
61
- *
62
- * @default null
63
- * @hidden
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
- * The ProseKit editor instance.
88
- *
89
- * @default null
90
- * @hidden
91
- */
87
+ * The ProseKit editor instance.
88
+ *
89
+ * @default null
90
+ * @hidden
91
+ */
92
92
  editor: Editor | null;
93
93
  /**
94
- * The regular expression to match the query text to autocomplete.
95
- *
96
- * @default null
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
- * The placement of the popover, relative to the text cursor.
101
- *
102
- * @default "bottom-start"
103
- */
104
- placement: OverlayPositionerProps["placement"];
100
+ * The placement of the popover, relative to the text cursor.
101
+ *
102
+ * @default "bottom-start"
103
+ */
104
+ placement: OverlayPositionerProps['placement'];
105
105
  /**
106
- * The distance between the popover and the hovered block.
107
- *
108
- * @default 4
109
- */
110
- offset: OverlayPositionerProps["offset"];
106
+ * The distance between the popover and the hovered block.
107
+ *
108
+ * @default 4
109
+ */
110
+ offset: OverlayPositionerProps['offset'];
111
111
  /**
112
- * @default true
113
- */
114
- inline: OverlayPositionerProps["inline"];
112
+ * @default true
113
+ */
114
+ inline: OverlayPositionerProps['inline'];
115
115
  /**
116
- * @default true
117
- */
118
- hoist: OverlayPositionerProps["hoist"];
116
+ * @default true
117
+ */
118
+ hoist: OverlayPositionerProps['hoist'];
119
119
  /**
120
- * @default true
121
- */
122
- fitViewport: OverlayPositionerProps["fitViewport"];
120
+ * @default true
121
+ */
122
+ fitViewport: OverlayPositionerProps['fitViewport'];
123
123
  /**
124
- * @default "The body element"
125
- */
126
- boundary: OverlayPositionerProps["boundary"];
124
+ * @default "The body element"
125
+ */
126
+ boundary: OverlayPositionerProps['boundary'];
127
127
  /**
128
- * @default 8
129
- */
130
- overflowPadding: OverlayPositionerProps["overflowPadding"];
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
- * Fired when the open state changes.
137
- */
136
+ * Fired when the open state changes.
137
+ */
138
138
  openChange: CustomEvent<boolean>;
139
139
  /**
140
- * Fired when the query changes.
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 { getSafeEditorView, getStateWithDefaults } from "./get-safe-editor-view-CqJWgxo1.js";
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
- * The ProseKit editor instance.
11
- *
12
- * @default null
13
- * @hidden
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
- * The ProseKit editor instance.
42
- *
43
- * @default null
44
- * @hidden
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, "placement" | "hoist"> {
70
+ interface BlockHandlePopoverProps extends Omit<OverlayPositionerProps, 'placement' | 'hoist' | 'flip' | 'shift' | 'hide'> {
71
71
  /**
72
- * The ProseKit editor instance.
73
- *
74
- * @default null
75
- * @hidden
76
- */
72
+ * The ProseKit editor instance.
73
+ *
74
+ * @default null
75
+ * @hidden
76
+ */
77
77
  editor: Editor | null;
78
78
  /**
79
- * The placement of the popover, relative to the hovered block.
80
- *
81
- * @default "left"
82
- */
79
+ * The placement of the popover, relative to the hovered block.
80
+ *
81
+ * @default "left"
82
+ */
83
83
  placement: Placement;
84
84
  /**
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
- */
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
- * Fired when the hovered block changes.
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 { assignStyles } from "./assign-styles-3yY6F1UX.js";
3
- import { deepCloneElement } from "./clone-element-i6RFnyj4.js";
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 rect = element.getBoundingClientRect();
77
- const { width, height, x: elementX, y: elementY } = rect;
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
- outline: "none",
99
- opacity: "0.5"
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
- useDraggingPreview(host, context, state.editor);
121
- useDataDraggingAttribute(host);
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 useDraggingPreview(host, context, editor) {
135
- useEventListener(host, "dragstart", (event) => {
136
- const hoverState = context.get();
137
- const { view } = editor.get() ?? {};
138
- if (!hoverState || !view || !event.dataTransfer) return;
139
- const { node, pos } = hoverState;
140
- const element = view.nodeDOM(pos);
141
- if (!element || !isHTMLElement(element)) return;
142
- event.dataTransfer.clearData();
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 useDragging(host) {
159
- const dragging = draggingContext.consume(host);
160
- useEventListener(host, "dragstart", () => {
161
- dragging.set(true);
162
- });
163
- useEventListener(host, "dragend", () => {
164
- dragging.set(false);
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 open = createComputed(() => !!context.get());
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 = {