@openleaf-editor/plugins-table 0.1.0-beta.3 → 0.1.0-beta.5

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/resize.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Nested-table column-resize hit-testing.
3
+ *
4
+ * `columnResizing()` is installed once for the document. Its own
5
+ * `domCellAround` walks to the innermost `TD`/`TH`, so a pointer over a nested
6
+ * table can never grab an outer column — even when it is sitting on that
7
+ * column's border. Nested tables are legal (`table_cell` is `block+`; Insert
8
+ * table inside a cell is tested), and that hit-test is inside the third-party
9
+ * plugin, not behind an option.
10
+ *
11
+ * Forking the plugin would mean owning `handleMouseMove` / `edgeCell` /
12
+ * `handleDecorations` for every upstream change. The wrapping plugin below is
13
+ * the smaller seam: it shares `columnResizingPluginKey` and the same handle
14
+ * width, and on `mousemove` it looks at every ancestor cell. An outer border
15
+ * within the handle width wins; otherwise it returns false and the upstream
16
+ * plugin handles the innermost table as before.
17
+ *
18
+ * Plugin order is load-bearing. `EditorView.someProp` walks from the start of
19
+ * the plugin list and stops at the first `handleDOMEvents` handler that returns
20
+ * true, so this plugin must sit *before* `columnResizing`. Returning true after
21
+ * setting the outer handle is what stops the innermost walk from overwriting it.
22
+ * `mousedown` is deliberately not claimed: once `activeHandle` points at the
23
+ * outer cell, the upstream drag logic is the right one to run.
24
+ */
25
+ import { Plugin, PluginKey } from 'prosemirror-state';
26
+ import { columnResizingPluginKey, pointsAtCell, TableMap, } from 'prosemirror-tables';
27
+ /** Matches `columnResizing`'s default. Keep the two in lockstep in `index.ts`. */
28
+ export const COLUMN_RESIZE_HANDLE_WIDTH = 5;
29
+ const nestedColumnResizeKey = new PluginKey('openleaf-nested-column-resize');
30
+ export function nestedColumnResizePlugin(handleWidth = COLUMN_RESIZE_HANDLE_WIDTH) {
31
+ return new Plugin({
32
+ key: nestedColumnResizeKey,
33
+ props: {
34
+ handleDOMEvents: {
35
+ mousemove: (view, event) => {
36
+ if (!view.editable)
37
+ return false;
38
+ if (!(event instanceof MouseEvent))
39
+ return false;
40
+ const pluginState = columnResizingPluginKey.getState(view.state);
41
+ if (!pluginState || pluginState.dragging)
42
+ return false;
43
+ const cell = nestedHandleCell(view, event, handleWidth);
44
+ if (cell == null)
45
+ return false;
46
+ if (cell !== pluginState.activeHandle) {
47
+ view.dispatch(view.state.tr.setMeta(columnResizingPluginKey, { setHandle: cell }));
48
+ }
49
+ return true;
50
+ },
51
+ },
52
+ },
53
+ });
54
+ }
55
+ /**
56
+ * The cell whose column should be resized, or `null` to leave the decision to
57
+ * `columnResizing`.
58
+ *
59
+ * `null` covers "no nesting", "pointer is not on an outer edge", and "the only
60
+ * matching edge is the innermost one". Those are all cases the upstream plugin
61
+ * already handles, and intercepting them would mean reimplementing it.
62
+ */
63
+ function nestedHandleCell(view, event, handleWidth) {
64
+ const cells = ancestorCells(event.target);
65
+ if (cells.length < 2)
66
+ return null;
67
+ for (let i = cells.length - 1; i >= 0; i -= 1) {
68
+ const td = cells[i];
69
+ const { left, right } = td.getBoundingClientRect();
70
+ let side = null;
71
+ if (event.clientX - left <= handleWidth)
72
+ side = 'left';
73
+ else if (right - event.clientX <= handleWidth)
74
+ side = 'right';
75
+ if (!side)
76
+ continue;
77
+ const cellPos = cellPosFromDOM(view, td);
78
+ if (cellPos == null)
79
+ continue;
80
+ const handle = handleCellForSide(view, cellPos, side);
81
+ if (handle < 0)
82
+ continue;
83
+ if (!pointsAtCell(view.state.doc.resolve(handle)))
84
+ continue;
85
+ // Innermost match: `columnResizing` will pick the same cell.
86
+ if (i === 0)
87
+ return null;
88
+ return handle;
89
+ }
90
+ return null;
91
+ }
92
+ /** Innermost first, walking out through nested tables to the editor root. */
93
+ function ancestorCells(target) {
94
+ const cells = [];
95
+ let node = target instanceof Node ? target : null;
96
+ while (node) {
97
+ if (node instanceof HTMLElement) {
98
+ if (node.nodeName === 'TD' || node.nodeName === 'TH')
99
+ cells.push(node);
100
+ if (node.classList.contains('ProseMirror'))
101
+ break;
102
+ }
103
+ node = node.parentNode;
104
+ }
105
+ return cells;
106
+ }
107
+ function cellPosFromDOM(view, td) {
108
+ let pos;
109
+ try {
110
+ pos = view.posAtDOM(td, 0);
111
+ }
112
+ catch {
113
+ return null;
114
+ }
115
+ const $pos = view.state.doc.resolve(pos);
116
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
117
+ const role = $pos.node(depth).type.spec['tableRole'];
118
+ if (role !== 'cell' && role !== 'header_cell')
119
+ continue;
120
+ const cellPos = $pos.before(depth);
121
+ const dom = view.nodeDOM(cellPos);
122
+ if (!dom)
123
+ continue;
124
+ if (dom === td)
125
+ return cellPos;
126
+ if (td.contains(dom))
127
+ return cellPos;
128
+ if (dom instanceof Node && dom.contains(td))
129
+ return cellPos;
130
+ }
131
+ return null;
132
+ }
133
+ /**
134
+ * Same mapping as upstream `edgeCell`: the right edge resizes this cell's
135
+ * column, the left edge resizes the previous one, and the first column's left
136
+ * edge is not a handle.
137
+ *
138
+ * `edgeCell` itself cannot be reused. It calls `posAtCoords` and then
139
+ * `cellAround`, both of which resolve to the innermost cell under the pointer
140
+ * — the original bug.
141
+ */
142
+ function handleCellForSide(view, cellPos, side) {
143
+ const $cell = view.state.doc.resolve(cellPos);
144
+ const role = $cell.nodeAfter?.type.spec['tableRole'];
145
+ if (role !== 'cell' && role !== 'header_cell')
146
+ return -1;
147
+ if (side === 'right')
148
+ return $cell.pos;
149
+ const table = $cell.node(-1);
150
+ if (table.type.spec['tableRole'] !== 'table')
151
+ return -1;
152
+ const map = TableMap.get(table);
153
+ const start = $cell.start(-1);
154
+ const index = map.map.indexOf($cell.pos - start);
155
+ if (index < 0)
156
+ return -1;
157
+ if (index % map.width === 0)
158
+ return -1;
159
+ const prev = map.map[index - 1];
160
+ return prev == null ? -1 : start + prev;
161
+ }
162
+ //# sourceMappingURL=resize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resize.js","sourceRoot":"","sources":["../src/resize.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openleaf-editor/plugins-table",
3
- "version": "0.1.0-beta.3",
3
+ "version": "0.1.0-beta.5",
4
4
  "description": "Opt-in table editing for OpenLeaf: cell selection, column resizing, property dialogs, captions, insert grid, context menu, and row/column commands. The table schema itself lives in @openleaf-editor/core so every deployment reads tables faithfully.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -34,16 +34,16 @@
34
34
  "peerDependencies": {
35
35
  "prosemirror-state": "^1.4.3",
36
36
  "prosemirror-tables": "^1.6.4",
37
- "@openleaf-editor/ui": "^0.1.0-beta.3",
38
- "@openleaf-editor/core": "^0.1.0-beta.3"
37
+ "@openleaf-editor/ui": "^0.1.0-beta.5",
38
+ "@openleaf-editor/core": "^0.1.0-beta.5"
39
39
  },
40
40
  "devDependencies": {
41
41
  "prosemirror-model": "^1.24.1",
42
42
  "prosemirror-state": "^1.4.3",
43
43
  "prosemirror-tables": "^1.6.4",
44
44
  "prosemirror-view": "^1.37.0",
45
- "@openleaf-editor/ui": "0.1.0-beta.3",
46
- "@openleaf-editor/core": "0.1.0-beta.3"
45
+ "@openleaf-editor/ui": "0.1.0-beta.5",
46
+ "@openleaf-editor/core": "0.1.0-beta.5"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsc -p tsconfig.json"