@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.
@@ -1,12 +1,13 @@
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 { assignStyles } from "./assign-styles-3yY6F1UX.js";
4
- import { cloneElement, deepCloneElement } from "./clone-element-i6RFnyj4.js";
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 = cloneElementWithoutSize(table);
335
+ const [previewTable, previewTableStyle] = cloneElement(table);
336
+ injectStyle(previewRoot, previewTableStyle);
337
+ unsetSize(previewTable);
293
338
  const tableBody = table.querySelector("tbody");
294
- const previewTableBody = tableBody ? cloneElementWithoutSize(tableBody) : table.ownerDocument.createElement("tbody");
339
+ const [previewTableBody, previewTableBodyStyle] = tableBody ? cloneElement(tableBody) : [table.ownerDocument.createElement("tbody"), ""];
340
+ injectStyle(previewRoot, previewTableBodyStyle);
295
341
  unsetSize(previewTableBody);
296
- unsetSize(previewTable);
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 = cloneElementWithoutSize(row);
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
- const typingValue = typing.get();
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.0",
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/ocavue/prosekit#readme",
13
+ "homepage": "https://github.com/prosekit/prosekit#readme",
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "git+https://github.com/ocavue/prosekit.git",
16
+ "url": "git+https://github.com/prosekit/prosekit.git",
17
17
  "directory": "packages/web"
18
18
  },
19
19
  "bugs": {
20
- "url": "https://github.com/ocavue/prosekit/issues"
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.6.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/pm": "^0.1.11",
83
- "@prosekit/extensions": "^0.11.0"
83
+ "@prosekit/extensions": "^0.11.2",
84
+ "@prosekit/pm": "^0.1.11"
84
85
  },
85
86
  "devDependencies": {
86
- "tsdown": "^0.13.1",
87
+ "tsdown": "^0.13.2",
87
88
  "typescript": "~5.8.3",
88
89
  "vitest": "^3.2.4",
89
- "@prosekit/config-tsdown": "0.0.0",
90
- "@prosekit/config-vitest": "0.0.0"
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,10 +0,0 @@
1
- //#region src/utils/assign-styles.ts
2
- /**
3
- * A type-safe version of `Object.assign` for `element.style`.
4
- */
5
- function assignStyles(element, styles) {
6
- Object.assign(element.style, styles);
7
- }
8
-
9
- //#endregion
10
- export { assignStyles };
@@ -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 };