@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
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getStateWithDefaults } from "./get-default-state-CIEy7xrl.js";
|
|
2
2
|
import { useEditorExtension } from "./use-editor-extension-Cc7ZG7uj.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { getSafeEditorView } from "./get-safe-editor-view-DENm4avv.js";
|
|
4
|
+
import { assignStyles, useScrolling } from "./use-scrolling-BNfsQs3S.js";
|
|
5
|
+
import { cloneElement, deepCloneElement, injectStyle } from "./inject-style-RwRNoINh.js";
|
|
5
6
|
import { createComputed, createContext, createSignal, defineCustomElement, defineEmit, registerCustomElement, useAttribute, useEffect, useEventListener } from "@aria-ui/core";
|
|
6
7
|
import { defineDOMEventHandler, union } from "@prosekit/core";
|
|
7
8
|
import { useOverlayPositionerState } from "@aria-ui/overlay/elements";
|
|
8
9
|
import { usePresence } from "@aria-ui/presence";
|
|
9
|
-
import { isHTMLElement } from "@ocavue/utils";
|
|
10
|
+
import { isHTMLElement, once } from "@ocavue/utils";
|
|
10
11
|
import { overlayPositionerEvents as overlayPositionerEvents$1, overlayPositionerProps as overlayPositionerProps$1 } from "@aria-ui/overlay";
|
|
11
12
|
import { menuContentEvents, menuContentProps, menuRootEvents, menuRootProps, useMenuContent, useMenuItem, useMenuRoot, useMenuTrigger } from "@aria-ui/menu/elements";
|
|
12
13
|
import { moveTableColumn, moveTableRow, selectTableColumn, selectTableRow } from "@prosekit/extensions/table";
|
|
@@ -77,7 +78,10 @@ const tableHandleColumnRootProps = Object.freeze({
|
|
|
77
78
|
...overlayPositionerProps$1,
|
|
78
79
|
editor: { default: null },
|
|
79
80
|
placement: { default: "top" },
|
|
80
|
-
hoist: { default: false }
|
|
81
|
+
hoist: { default: false },
|
|
82
|
+
flip: { default: false },
|
|
83
|
+
shift: { default: false },
|
|
84
|
+
hide: { default: true }
|
|
81
85
|
});
|
|
82
86
|
/** @internal */
|
|
83
87
|
const tableHandleColumnRootEvents = overlayPositionerEvents$1;
|
|
@@ -282,6 +286,45 @@ function getDndRelatedDOMs(view, cellPos, draggingIndex, direction) {
|
|
|
282
286
|
};
|
|
283
287
|
}
|
|
284
288
|
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region src/utils/css-feature-detection.ts
|
|
291
|
+
const isColorMixSupported = once(() => {
|
|
292
|
+
try {
|
|
293
|
+
return CSS.supports("background-color", "color-mix(in srgb, red, blue)");
|
|
294
|
+
} catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/utils/fade-color.ts
|
|
301
|
+
/**
|
|
302
|
+
* Convert a color to a color with opacity
|
|
303
|
+
* @param color - The color to convert
|
|
304
|
+
* @param opacity - The opacity to apply
|
|
305
|
+
* @returns The converted color if color-mix is supported, otherwise undefined
|
|
306
|
+
*/
|
|
307
|
+
function fadeColor(color, opacity) {
|
|
308
|
+
if (isColorMixSupported()) {
|
|
309
|
+
const transparentWeight = (1 - opacity) * 100;
|
|
310
|
+
const colorWeight = opacity * 100;
|
|
311
|
+
return `color-mix(in srgb, ${color} ${colorWeight}%, transparent ${transparentWeight}%)`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
//#endregion
|
|
316
|
+
//#region src/utils/get-effective-background-color.ts
|
|
317
|
+
function getEffectiveBackgroundColor(element) {
|
|
318
|
+
let current = element;
|
|
319
|
+
while (current) {
|
|
320
|
+
const style = current.ownerDocument.defaultView?.getComputedStyle(current);
|
|
321
|
+
const backgroundColor = style?.backgroundColor;
|
|
322
|
+
if (backgroundColor && backgroundColor !== "transparent" && backgroundColor !== "rgba(0, 0, 0, 0)") return backgroundColor;
|
|
323
|
+
current = current.parentElement;
|
|
324
|
+
}
|
|
325
|
+
return void 0;
|
|
326
|
+
}
|
|
327
|
+
|
|
285
328
|
//#endregion
|
|
286
329
|
//#region src/components/table-handle/table-handle-drag-preview/render-preview.ts
|
|
287
330
|
function clearPreviewDOM(previewRoot) {
|
|
@@ -289,35 +332,40 @@ function clearPreviewDOM(previewRoot) {
|
|
|
289
332
|
}
|
|
290
333
|
function createPreviewDOM(table, previewRoot, index, direction) {
|
|
291
334
|
clearPreviewDOM(previewRoot);
|
|
292
|
-
const previewTable =
|
|
335
|
+
const [previewTable, previewTableStyle] = cloneElement(table);
|
|
336
|
+
injectStyle(previewRoot, previewTableStyle);
|
|
337
|
+
unsetSize(previewTable);
|
|
293
338
|
const tableBody = table.querySelector("tbody");
|
|
294
|
-
const previewTableBody = tableBody ?
|
|
339
|
+
const [previewTableBody, previewTableBodyStyle] = tableBody ? cloneElement(tableBody) : [table.ownerDocument.createElement("tbody"), ""];
|
|
340
|
+
injectStyle(previewRoot, previewTableBodyStyle);
|
|
295
341
|
unsetSize(previewTableBody);
|
|
296
|
-
|
|
342
|
+
const backgroundColor = getEffectiveBackgroundColor(table);
|
|
343
|
+
if (backgroundColor) {
|
|
344
|
+
const backgroundColorWithOpacity = fadeColor(backgroundColor, .8);
|
|
345
|
+
if (backgroundColorWithOpacity) assignStyles(previewTable, { backgroundColor: backgroundColorWithOpacity });
|
|
346
|
+
}
|
|
297
347
|
previewTable.appendChild(previewTableBody);
|
|
298
348
|
previewRoot.appendChild(previewTable);
|
|
299
349
|
const rows = table.querySelectorAll("tr");
|
|
300
350
|
if (direction === "row") {
|
|
301
351
|
const row = rows[index];
|
|
302
|
-
const previewRow = deepCloneElement(row);
|
|
352
|
+
const [previewRow, previewRowStyle] = deepCloneElement(row);
|
|
353
|
+
injectStyle(previewRoot, previewRowStyle);
|
|
303
354
|
previewTableBody.appendChild(previewRow);
|
|
304
355
|
} else rows.forEach((row) => {
|
|
305
|
-
const previewRow =
|
|
356
|
+
const [previewRow, previewRowStyle] = cloneElement(row);
|
|
357
|
+
injectStyle(previewRoot, previewRowStyle);
|
|
306
358
|
unsetSize(previewRow);
|
|
307
359
|
const cells = row.querySelectorAll("td");
|
|
308
360
|
const cell = cells[index];
|
|
309
361
|
if (cell) {
|
|
310
|
-
const previewCell = deepCloneElement(cell);
|
|
362
|
+
const [previewCell, previewCellStyle] = deepCloneElement(cell);
|
|
363
|
+
injectStyle(previewRoot, previewCellStyle);
|
|
311
364
|
previewRow.appendChild(previewCell);
|
|
312
365
|
previewTableBody.appendChild(previewRow);
|
|
313
366
|
}
|
|
314
367
|
});
|
|
315
368
|
}
|
|
316
|
-
function cloneElementWithoutSize(element) {
|
|
317
|
-
const clonedElement = cloneElement(element);
|
|
318
|
-
unsetSize(clonedElement);
|
|
319
|
-
return clonedElement;
|
|
320
|
-
}
|
|
321
369
|
function unsetSize(element) {
|
|
322
370
|
assignStyles(element, {
|
|
323
371
|
width: "unset",
|
|
@@ -706,6 +754,43 @@ function useEditorTyping(host, editor) {
|
|
|
706
754
|
return typing;
|
|
707
755
|
}
|
|
708
756
|
|
|
757
|
+
//#endregion
|
|
758
|
+
//#region src/hooks/use-selecting.ts
|
|
759
|
+
/**
|
|
760
|
+
* Detect if the user is selecting text inside the editor, in which case some
|
|
761
|
+
* components should be disabled or hidden.
|
|
762
|
+
*/
|
|
763
|
+
function useSelecting(host, editor, enabled) {
|
|
764
|
+
const selecting = createSignal(false);
|
|
765
|
+
const isPointerDown = createSignal(false);
|
|
766
|
+
useEffect(host, () => {
|
|
767
|
+
if (!enabled.get()) return;
|
|
768
|
+
const view = getSafeEditorView(editor.peek());
|
|
769
|
+
if (!view) return;
|
|
770
|
+
const { dom, root } = view;
|
|
771
|
+
if (!root) return;
|
|
772
|
+
const handlePointerDown = () => {
|
|
773
|
+
selecting.set(true);
|
|
774
|
+
isPointerDown.set(true);
|
|
775
|
+
};
|
|
776
|
+
const handlePointerUp = () => {
|
|
777
|
+
isPointerDown.set(false);
|
|
778
|
+
};
|
|
779
|
+
const handleMouseMove = () => {
|
|
780
|
+
if (!isPointerDown.get()) selecting.set(false);
|
|
781
|
+
};
|
|
782
|
+
dom.addEventListener("pointerdown", handlePointerDown);
|
|
783
|
+
root.addEventListener("pointerup", handlePointerUp);
|
|
784
|
+
root.addEventListener("pointermove", handleMouseMove);
|
|
785
|
+
return () => {
|
|
786
|
+
dom.removeEventListener("pointerdown", handlePointerDown);
|
|
787
|
+
root.removeEventListener("pointerup", handlePointerUp);
|
|
788
|
+
root.removeEventListener("pointermove", handleMouseMove);
|
|
789
|
+
};
|
|
790
|
+
});
|
|
791
|
+
return selecting;
|
|
792
|
+
}
|
|
793
|
+
|
|
709
794
|
//#endregion
|
|
710
795
|
//#region src/components/table-handle/hooks/use-drop.ts
|
|
711
796
|
function useDrop(host, editor, dndContext) {
|
|
@@ -816,11 +901,12 @@ function useTableHandleRoot(host, { state }) {
|
|
|
816
901
|
const typing = useEditorTyping(host, editor);
|
|
817
902
|
const isInTable = createComputed(() => !!hoveringCell.get());
|
|
818
903
|
const selecting = useSelecting(host, editor, isInTable);
|
|
904
|
+
const scrolling = useScrolling(host);
|
|
905
|
+
const canShow = createComputed(() => {
|
|
906
|
+
return !typing.get() && !selecting.get() && !scrolling.get();
|
|
907
|
+
});
|
|
819
908
|
useEffect(host, () => {
|
|
820
|
-
|
|
821
|
-
const selectingValue = selecting.get();
|
|
822
|
-
const hoveringCellValue = hoveringCell.get();
|
|
823
|
-
context.set(typingValue || selectingValue ? null : hoveringCellValue);
|
|
909
|
+
context.set(canShow.get() ? hoveringCell.get() : null);
|
|
824
910
|
});
|
|
825
911
|
tableHandleRootContext.provide(host, context);
|
|
826
912
|
tableHandleDndContext.provide(host, dndContext);
|
|
@@ -842,33 +928,6 @@ function defineCellHoverHandler(handler) {
|
|
|
842
928
|
};
|
|
843
929
|
return defineDOMEventHandler("pointerover", pointerHandler);
|
|
844
930
|
}
|
|
845
|
-
/**
|
|
846
|
-
* Detect if the user is selecting text by dragging.
|
|
847
|
-
*/
|
|
848
|
-
function useSelecting(host, editor, isInTable) {
|
|
849
|
-
const selecting = createSignal(false);
|
|
850
|
-
useEffect(host, () => {
|
|
851
|
-
if (!isInTable.get()) return;
|
|
852
|
-
const view = getSafeEditorView(editor.peek());
|
|
853
|
-
const root = view?.root;
|
|
854
|
-
if (!root) return;
|
|
855
|
-
const pointerDownHandler = (event) => {
|
|
856
|
-
const target = event.target;
|
|
857
|
-
if (!target || host.contains(event.target)) return;
|
|
858
|
-
selecting.set(true);
|
|
859
|
-
};
|
|
860
|
-
const pointerUpHandler = () => {
|
|
861
|
-
selecting.set(false);
|
|
862
|
-
};
|
|
863
|
-
root.addEventListener("pointerdown", pointerDownHandler);
|
|
864
|
-
root.addEventListener("pointerup", pointerUpHandler);
|
|
865
|
-
return () => {
|
|
866
|
-
root.removeEventListener("pointerdown", pointerDownHandler);
|
|
867
|
-
root.removeEventListener("pointerup", pointerUpHandler);
|
|
868
|
-
};
|
|
869
|
-
});
|
|
870
|
-
return selecting;
|
|
871
|
-
}
|
|
872
931
|
|
|
873
932
|
//#endregion
|
|
874
933
|
//#region src/components/table-handle/table-handle-root/types.ts
|
|
@@ -927,7 +986,10 @@ const tableHandleRowRootProps = {
|
|
|
927
986
|
...overlayPositionerProps$1,
|
|
928
987
|
editor: { default: null },
|
|
929
988
|
placement: { default: "left" },
|
|
930
|
-
hoist: { default: false }
|
|
989
|
+
hoist: { default: false },
|
|
990
|
+
flip: { default: false },
|
|
991
|
+
shift: { default: false },
|
|
992
|
+
hide: { default: true }
|
|
931
993
|
};
|
|
932
994
|
/** @internal */
|
|
933
995
|
const tableHandleRowRootEvents = {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createSignal, useEffect } from "@aria-ui/core";
|
|
2
|
+
import { getNearestOverflowAncestor } from "@zag-js/dom-query";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/assign-styles.ts
|
|
5
|
+
/**
|
|
6
|
+
* A type-safe version of `Object.assign` for `element.style`.
|
|
7
|
+
*/
|
|
8
|
+
function assignStyles(element, styles) {
|
|
9
|
+
Object.assign(element.style, styles);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/hooks/use-scrolling.ts
|
|
14
|
+
function useScrolling(host) {
|
|
15
|
+
const scrolling = createSignal(false);
|
|
16
|
+
useEffect(host, () => {
|
|
17
|
+
const scrollableParent = getNearestOverflowAncestor(host);
|
|
18
|
+
const handleScroll = () => {
|
|
19
|
+
scrolling.set(true);
|
|
20
|
+
};
|
|
21
|
+
const handleMouseMove = () => {
|
|
22
|
+
scrolling.set(false);
|
|
23
|
+
};
|
|
24
|
+
scrollableParent.addEventListener("scroll", handleScroll, { passive: true });
|
|
25
|
+
window.addEventListener("mousemove", handleMouseMove, { passive: true });
|
|
26
|
+
return () => {
|
|
27
|
+
scrollableParent.removeEventListener("scroll", handleScroll);
|
|
28
|
+
window.removeEventListener("mousemove", handleMouseMove);
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
return scrolling;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { assignStyles, useScrolling };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosekit/web",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.2",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "A collection of web components for ProseKit",
|
|
7
7
|
"author": {
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
},
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"funding": "https://github.com/sponsors/ocavue",
|
|
13
|
-
"homepage": "https://github.com/
|
|
13
|
+
"homepage": "https://github.com/prosekit/prosekit#readme",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/
|
|
16
|
+
"url": "git+https://github.com/prosekit/prosekit.git",
|
|
17
17
|
"directory": "packages/web"
|
|
18
18
|
},
|
|
19
19
|
"bugs": {
|
|
20
|
-
"url": "https://github.com/
|
|
20
|
+
"url": "https://github.com/prosekit/prosekit/issues"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [
|
|
23
23
|
"ProseMirror"
|
|
@@ -76,18 +76,19 @@
|
|
|
76
76
|
"@aria-ui/presence": "^0.0.19",
|
|
77
77
|
"@aria-ui/tooltip": "^0.0.29",
|
|
78
78
|
"@floating-ui/dom": "^1.7.3",
|
|
79
|
-
"@ocavue/utils": "^0.
|
|
79
|
+
"@ocavue/utils": "^0.7.1",
|
|
80
|
+
"@zag-js/dom-query": "^1.21.1",
|
|
80
81
|
"prosemirror-tables": "^1.7.1",
|
|
81
82
|
"@prosekit/core": "^0.8.3",
|
|
82
|
-
"@prosekit/
|
|
83
|
-
"@prosekit/
|
|
83
|
+
"@prosekit/extensions": "^0.11.2",
|
|
84
|
+
"@prosekit/pm": "^0.1.11"
|
|
84
85
|
},
|
|
85
86
|
"devDependencies": {
|
|
86
|
-
"tsdown": "^0.13.
|
|
87
|
+
"tsdown": "^0.13.2",
|
|
87
88
|
"typescript": "~5.8.3",
|
|
88
89
|
"vitest": "^3.2.4",
|
|
89
|
-
"@prosekit/config-
|
|
90
|
-
"@prosekit/config-
|
|
90
|
+
"@prosekit/config-vitest": "0.0.0",
|
|
91
|
+
"@prosekit/config-tsdown": "0.0.0"
|
|
91
92
|
},
|
|
92
93
|
"publishConfig": {
|
|
93
94
|
"dev": {}
|
|
@@ -97,12 +98,12 @@
|
|
|
97
98
|
"prosekit-web": "./src/index.ts",
|
|
98
99
|
"prosekit-web-autocomplete": "./src/components/autocomplete/index.gen.ts",
|
|
99
100
|
"prosekit-web-block-handle": "./src/components/block-handle/index.gen.ts",
|
|
101
|
+
"prosekit-web-drop-indicator": "./src/components/drop-indicator/index.gen.ts",
|
|
100
102
|
"prosekit-web-inline-popover": "./src/components/inline-popover/index.gen.ts",
|
|
101
103
|
"prosekit-web-popover": "./src/components/popover/index.gen.ts",
|
|
102
104
|
"prosekit-web-resizable": "./src/components/resizable/index.gen.ts",
|
|
103
105
|
"prosekit-web-table-handle": "./src/components/table-handle/index.gen.ts",
|
|
104
|
-
"prosekit-web-tooltip": "./src/components/tooltip/index.gen.ts"
|
|
105
|
-
"prosekit-web-drop-indicator": "./src/components/drop-indicator/index.gen.ts"
|
|
106
|
+
"prosekit-web-tooltip": "./src/components/tooltip/index.gen.ts"
|
|
106
107
|
}
|
|
107
108
|
},
|
|
108
109
|
"scripts": {
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
//#region src/utils/clone-element.ts
|
|
2
|
-
/**
|
|
3
|
-
* Creates a deep clone of an Element, including all computed styles so that
|
|
4
|
-
* it looks the same as the original element.
|
|
5
|
-
*/
|
|
6
|
-
function deepCloneElement(element) {
|
|
7
|
-
const clonedElement = element.cloneNode(true);
|
|
8
|
-
deepCopyStyles(element, clonedElement);
|
|
9
|
-
return clonedElement;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Creates a clone of an Element, including all computed styles so that
|
|
13
|
-
* it looks similar enough to the original element.
|
|
14
|
-
*/
|
|
15
|
-
function cloneElement(element) {
|
|
16
|
-
const clonedElement = element.cloneNode();
|
|
17
|
-
copyStyles(element, clonedElement);
|
|
18
|
-
return clonedElement;
|
|
19
|
-
}
|
|
20
|
-
function deepCopyStyles(source, target) {
|
|
21
|
-
const sources = [source];
|
|
22
|
-
const targets = [target];
|
|
23
|
-
while (sources.length > 0 && sources.length === targets.length) {
|
|
24
|
-
const source$1 = sources.pop();
|
|
25
|
-
const target$1 = targets.pop();
|
|
26
|
-
if (!source$1 || !target$1) return;
|
|
27
|
-
copyStyles(source$1, target$1);
|
|
28
|
-
sources.push(...source$1.children);
|
|
29
|
-
targets.push(...target$1.children);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function copyStyles(source, target) {
|
|
33
|
-
if (!source || !target) return;
|
|
34
|
-
const sourceStyle = source.ownerDocument?.defaultView?.getComputedStyle(source);
|
|
35
|
-
const targetStyle = target.style;
|
|
36
|
-
if (!sourceStyle || !targetStyle) return;
|
|
37
|
-
for (const key of sourceStyle) targetStyle.setProperty(key, sourceStyle.getPropertyValue(key), sourceStyle.getPropertyPriority(key));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
//#endregion
|
|
41
|
-
export { cloneElement, deepCloneElement };
|