@openleaf-editor/plugins-table 0.1.0-beta.1 → 0.1.0-beta.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/index.js CHANGED
@@ -12,8 +12,8 @@
12
12
  *
13
13
  * So everyone gets tables that read and write correctly, for about a kilobyte.
14
14
  * What is opt-in is the weight: cell selection, column resizing, the row and
15
- * column commands, and the toolbar controls -- 12.5 KB gzipped that a site
16
- * forbidding tables has no reason to download.
15
+ * column commands, property dialogs, the insert grid, the context menu, and the
16
+ * toolbar controls.
17
17
  *
18
18
  * ## Loading it
19
19
  *
@@ -25,7 +25,7 @@
25
25
  * ```
26
26
  *
27
27
  * The second bundle shares the first one's ProseMirror runtime rather than
28
- * carrying its own copy, which is what keeps it 12.5 KB instead of ~200 KB.
28
+ * carrying its own copy.
29
29
  *
30
30
  * Or as a module:
31
31
  *
@@ -34,12 +34,21 @@
34
34
  * installTableEditing()
35
35
  * ```
36
36
  */
37
- import { canInsert, isNodeActive, registerEditorPlugin } from '@openleaf-editor/core';
38
- import { registerIcons, registerToolbarItem } from '@openleaf-editor/ui';
37
+ import { registerEditorPlugin } from '@openleaf-editor/core';
38
+ import { registerIcons, registerStyles, registerToolbarItem } from '@openleaf-editor/ui';
39
+ import { columnResizing, deleteColumn, deleteRow, deleteTable, mergeCells, splitCell, tableEditing, TableView, } from 'prosemirror-tables';
40
+ import { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, colgroupSyncPlugin, inTable, insertTable, toggleHeaderRow, } from './commands.js';
41
+ import { openCaptionDialog, openCellProperties, openRowProperties, openTableProperties } from './dialogs.js';
42
+ import { buildInsertGrid } from './grid.js';
39
43
  import { TABLE_ICON_PATHS } from './icons.js';
40
- import { addColumnAfter as addColumnAfterRaw, addColumnBefore as addColumnBeforeRaw, addRowAfter as addRowAfterRaw, addRowBefore as addRowBeforeRaw, columnResizing, deleteColumn, deleteRow, deleteTable, mergeCells, splitCell, tableEditing, toggleHeaderRow as toggleHeaderRowRaw, } from 'prosemirror-tables';
44
+ import { tableContextMenu } from './menu.js';
45
+ import { TABLE_UI_CSS } from './styles.js';
41
46
  export const TABLE_TOOLBAR_ITEMS = [
42
47
  'insertTable',
48
+ 'tableProperties',
49
+ 'rowProperties',
50
+ 'cellProperties',
51
+ 'tableCaption',
43
52
  'addRowBefore',
44
53
  'addRowAfter',
45
54
  'deleteRow',
@@ -53,112 +62,90 @@ export const TABLE_TOOLBAR_ITEMS = [
53
62
  ];
54
63
  /** A layout string for the default toolbar plus the table controls. */
55
64
  export const TABLE_LAYOUT_SUFFIX = ` | ${TABLE_TOOLBAR_ITEMS.join(' ')}`;
56
- /** Is the selection inside a table? Table commands are useless outside one. */
57
- export function inTable(state) {
58
- return isNodeActive(state, 'table');
59
- }
60
65
  /**
61
- * Insert a table with a header row.
66
+ * `TableView`, plus the caption it does not know about.
62
67
  *
63
- * A header row by default rather than a plain grid: a table without headers is
64
- * an accessibility problem that authors rarely go back and fix, and defaults
65
- * decide what most documents look like.
66
- */
67
- export function insertTable(rows = 3, cols = 3) {
68
- return (state, dispatch) => {
69
- if (!canInsert(state, 'table'))
70
- return false;
71
- if (dispatch) {
72
- // From the state's schema, not an imported singleton: a plugin that
73
- // captured one schema would build nodes the editor's schema rejects.
74
- const cell = state.schema.nodes['table_cell'];
75
- const header = state.schema.nodes['table_header'];
76
- const row = state.schema.nodes['table_row'];
77
- const tableType = state.schema.nodes['table'];
78
- if (!cell || !header || !row || !tableType)
79
- return false;
80
- const headerCells = Array.from({ length: cols }, () => header.createAndFill({ scope: 'col' })).filter((n) => n !== null);
81
- const bodyRows = Array.from({ length: Math.max(0, rows - 1) }, () => row.create(null, Array.from({ length: cols }, () => cell.createAndFill()).filter((n) => n !== null)));
82
- const table = tableType.create(null, [row.create(null, headerCells), ...bodyRows]);
83
- dispatch(state.tr.replaceSelectionWith(table).scrollIntoView());
84
- }
85
- return true;
86
- };
87
- }
88
- /**
89
- * Keep `scope` valid when cells change role.
68
+ * `columnResizing` installs a node view for tables, and that node view builds
69
+ * the element itself: a wrapper div, a `<colgroup>` it owns for resize widths,
70
+ * and a `<tbody>`. It never consults the table node's `toDOM`, so once this
71
+ * bundle loads, the caption core renders is simply absent from the editor.
90
72
  *
91
- * `td` and `th` share an attribute set, so the upstream toggle copies `scope`
92
- * onto a body cell (invalid HTML) and creates header cells without it.
93
- * Inserting a table already writes `scope="col"`; toggling and adding columns
94
- * should not undo that.
73
+ * That produced the worst version of the bug it was meant to fix. Saving still
74
+ * kept the caption -- serialization goes through `toDOM` and never through a
75
+ * node view -- so the caption was invisible while editing and reappeared in the
76
+ * stored HTML. An author would reasonably conclude it had been deleted, and the
77
+ * only way to find out otherwise is to read the database.
78
+ *
79
+ * Only the caption is re-added. The preserved `<colgroup>` markup deliberately
80
+ * is not: this view's own colgroup is what drives column resizing, and a second
81
+ * one would fight it for the same columns. The author's colgroup is still
82
+ * stored and still emitted on save; it is the resize widths that win on screen,
83
+ * which is the same bargain the resizing feature already makes.
95
84
  */
96
- function applyCellScope(tr) {
97
- const header = tr.doc.type.schema.nodes['table_header'];
98
- const cell = tr.doc.type.schema.nodes['table_cell'];
99
- if (!header || !cell)
100
- return tr;
101
- let tablePos = -1;
102
- for (let depth = tr.selection.$from.depth; depth > 0; depth -= 1) {
103
- if (tr.selection.$from.node(depth).type.spec['tableRole'] === 'table') {
104
- tablePos = tr.selection.$from.before(depth);
105
- break;
85
+ class CaptionedTableView extends TableView {
86
+ constructor(node, defaultCellMinWidth) {
87
+ super(node, defaultCellMinWidth);
88
+ this.syncCaption(node);
89
+ }
90
+ update(node) {
91
+ const handled = super.update(node);
92
+ if (handled)
93
+ this.syncCaption(node);
94
+ return handled;
95
+ }
96
+ ignoreMutation(record) {
97
+ // The caption is ours, not content. Without this, ProseMirror treats a
98
+ // change inside it as an edit to the document and tries to re-read it.
99
+ const caption = this.currentCaption();
100
+ if (caption && record.target instanceof Node && caption.contains(record.target))
101
+ return true;
102
+ return super.ignoreMutation(record);
103
+ }
104
+ currentCaption() {
105
+ const first = this.table.firstElementChild;
106
+ return first && first.nodeName === 'CAPTION' ? first : null;
107
+ }
108
+ syncCaption(node) {
109
+ const html = node.attrs['caption'] ?? null;
110
+ const existing = this.currentCaption();
111
+ if (!html) {
112
+ existing?.remove();
113
+ return;
114
+ }
115
+ // Rebuild only when the markup actually changed. Replacing it on every
116
+ // update would discard the DOM under the user's selection on every
117
+ // keystroke inside the table.
118
+ if (existing && existing.getAttribute('data-openleaf-caption') === html)
119
+ return;
120
+ const tpl = document.createElement('template');
121
+ tpl.innerHTML = html;
122
+ const rebuilt = tpl.content.firstElementChild;
123
+ if (!rebuilt || rebuilt.nodeName !== 'CAPTION') {
124
+ existing?.remove();
125
+ return;
106
126
  }
127
+ // Editor-only, exactly as in core's `toDOM`: the caption renders inside the
128
+ // editable area but is not part of `contentDOM`, so a caret must not enter
129
+ // it. Neither attribute reaches the stored HTML, which is produced by
130
+ // serialization and never by this view.
131
+ rebuilt.setAttribute('contenteditable', 'false');
132
+ rebuilt.setAttribute('data-openleaf-caption', html);
133
+ // A caption must be the table's first child for the browser to render it.
134
+ if (existing)
135
+ existing.replaceWith(rebuilt);
136
+ else
137
+ this.table.insertBefore(rebuilt, this.table.firstChild);
107
138
  }
108
- if (tablePos < 0)
109
- return tr;
110
- const table = tr.doc.nodeAt(tablePos);
111
- if (!table)
112
- return tr;
113
- // Walked by row and column rather than as a flat descendant list, because a
114
- // header's scope depends on where it sits. `setNodeMarkup` only changes
115
- // attributes, so every node keeps its size and these positions stay valid.
116
- table.forEach((row, rowOffset, rowIndex) => {
117
- const rowPos = tablePos + 1 + rowOffset;
118
- row.forEach((cellNode, cellOffset, cellIndex) => {
119
- const pos = rowPos + 1 + cellOffset;
120
- if (cellNode.type === cell && cellNode.attrs['scope']) {
121
- tr.setNodeMarkup(pos, undefined, { ...cellNode.attrs, scope: null });
122
- return;
123
- }
124
- if (cellNode.type !== header)
125
- return;
126
- const scope = cellNode.attrs['scope'];
127
- if (scope !== null && scope !== undefined && scope !== '')
128
- return;
129
- // A header in the top row labels a column. A header that opens a later
130
- // row labels that row -- writing "col" there tells a screen reader the
131
- // opposite of the truth, which is worse than the missing scope this
132
- // replaces.
133
- tr.setNodeMarkup(pos, undefined, {
134
- ...cellNode.attrs,
135
- scope: rowIndex === 0 || cellIndex > 0 ? 'col' : 'row',
136
- });
137
- });
138
- });
139
- return tr;
140
- }
141
- function withCellScope(command) {
142
- return (state, dispatch, view) => {
143
- if (!dispatch)
144
- return command(state, undefined, view);
145
- return command(state, (tr) => {
146
- dispatch(applyCellScope(tr));
147
- }, view);
148
- };
149
139
  }
150
- export const addColumnAfter = withCellScope(addColumnAfterRaw);
151
- export const addColumnBefore = withCellScope(addColumnBeforeRaw);
152
- export const addRowAfter = withCellScope(addRowAfterRaw);
153
- export const addRowBefore = withCellScope(addRowBeforeRaw);
154
- export const toggleHeaderRow = withCellScope(toggleHeaderRowRaw);
155
140
  /** The ProseMirror plugins table editing needs. */
156
141
  export function tableEditingPlugins() {
157
142
  return [
158
143
  // Resizing must come first: it reads cell geometry that tableEditing's
159
144
  // selection handling would otherwise have already consumed.
160
- columnResizing(),
145
+ columnResizing({ View: CaptionedTableView }),
161
146
  tableEditing({ allowTableNodeSelection: true }),
147
+ colgroupSyncPlugin(),
148
+ tableContextMenu(),
162
149
  ];
163
150
  }
164
151
  let installed = false;
@@ -173,15 +160,35 @@ export function installTableEditing() {
173
160
  return;
174
161
  installed = true;
175
162
  registerIcons(TABLE_ICON_PATHS);
163
+ registerStyles(TABLE_UI_CSS);
176
164
  registerEditorPlugin(() => tableEditingPlugins());
177
165
  registerToolbarItem({
178
166
  id: 'insertTable',
179
- type: 'button',
180
- kind: 'action',
167
+ type: 'custom',
181
168
  label: 'Insert table',
182
169
  icon: 'table',
183
- command: insertTable(),
170
+ render: (ctx) => buildInsertGrid(ctx),
171
+ isEnabled: (state) => insertTable()(state),
184
172
  });
173
+ const dialogs = [
174
+ ['tableProperties', 'Table properties', 'tableProperties', openTableProperties],
175
+ ['rowProperties', 'Row properties', 'rowProperties', openRowProperties],
176
+ ['cellProperties', 'Cell properties', 'cellProperties', openCellProperties],
177
+ ['tableCaption', 'Table caption', 'tableCaption', openCaptionDialog],
178
+ ];
179
+ for (const [id, label, icon, open] of dialogs) {
180
+ registerToolbarItem({
181
+ id,
182
+ type: 'button',
183
+ kind: 'action',
184
+ label,
185
+ icon,
186
+ run: ({ view, host }) => {
187
+ void open(view, host);
188
+ },
189
+ isEnabled: (state) => inTable(state),
190
+ });
191
+ }
185
192
  const commands = [
186
193
  ['addRowBefore', 'Insert row above', addRowBefore],
187
194
  ['addRowAfter', 'Insert row below', addRowAfter],
@@ -214,12 +221,12 @@ export function installTableEditing() {
214
221
  label,
215
222
  ...(icons[id] ? { icon: icons[id] } : {}),
216
223
  command,
217
- // Every one of these is meaningless outside a table. Reporting them as
218
- // disabled rather than letting them silently no-op is the difference
219
- // between a control that looks broken and one that looks unavailable.
220
224
  isEnabled: (state) => inTable(state) && command(state),
221
225
  });
222
226
  }
223
227
  }
228
+ export { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, colgroupHtmlWithWidths, colgroupSyncPlugin, inTable, insertTable, mergeStyle, setCellAttrs, setCellVerticalAlign, setRowAttrs, setTableAttrs, setTableCaption, setTableColgroup, styleValueOrNull, toggleHeaderRow, widthsFromColgroup, } from './commands.js';
229
+ export { buildInsertGrid, GRID_SIZE } from './grid.js';
230
+ export { tableContextMenu } from './menu.js';
224
231
  export { deleteColumn, deleteRow, deleteTable, mergeCells, splitCell, } from 'prosemirror-tables';
225
232
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAIxF,OAAO,EACL,cAAc,EACd,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,EACT,YAAY,EACZ,SAAS,GACV,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,cAAc,EACd,eAAe,EACf,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAC5G,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,aAAa;IACb,iBAAiB;IACjB,eAAe;IACf,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,aAAa;IACb,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,WAAW;IACX,iBAAiB;IACjB,aAAa;CACL,CAAA;AAEV,uEAAuE;AACvE,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;AAExE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,kBAAmB,SAAQ,SAAS;IACxC,YAAY,IAAY,EAAE,mBAA2B;QACnD,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAA;QAChC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IAEQ,MAAM,CAAC,IAAY;QAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAClC,IAAI,OAAO;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QACnC,OAAO,OAAO,CAAA;IAChB,CAAC;IAEQ,cAAc,CAAC,MAA0B;QAChD,uEAAuE;QACvE,uEAAuE;QACvE,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QACrC,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,YAAY,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAA;QAC5F,OAAO,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;IAEO,cAAc;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAA;QAC1C,OAAO,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAE,KAAqB,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9E,CAAC;IAEO,WAAW,CAAC,IAAY;QAC9B,MAAM,IAAI,GAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAmB,IAAI,IAAI,CAAA;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QAEtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,QAAQ,EAAE,MAAM,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QAED,uEAAuE;QACvE,mEAAmE;QACnE,8BAA8B;QAC9B,IAAI,QAAQ,IAAI,QAAQ,CAAC,YAAY,CAAC,uBAAuB,CAAC,KAAK,IAAI;YAAE,OAAM;QAE/E,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;QAC9C,GAAG,CAAC,SAAS,GAAG,IAAI,CAAA;QACpB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAA;QAC7C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC/C,QAAQ,EAAE,MAAM,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QAED,4EAA4E;QAC5E,2EAA2E;QAC3E,sEAAsE;QACtE,wCAAwC;QACxC,OAAO,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;QAChD,OAAO,CAAC,YAAY,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAA;QAEnD,0EAA0E;QAC1E,IAAI,QAAQ;YAAE,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;;YACtC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IAC9D,CAAC;CACF;AAED,mDAAmD;AACnD,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,uEAAuE;QACvE,4DAA4D;QAC5D,cAAc,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;QAC5C,YAAY,CAAC,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC;QAC/C,kBAAkB,EAAE;QACpB,gBAAgB,EAAE;KACnB,CAAA;AACH,CAAC;AAED,IAAI,SAAS,GAAG,KAAK,CAAA;AAErB;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,SAAS;QAAE,OAAM;IACrB,SAAS,GAAG,IAAI,CAAA;IAEhB,aAAa,CAAC,gBAAgB,CAAC,CAAA;IAC/B,cAAc,CAAC,YAAY,CAAC,CAAA;IAC5B,oBAAoB,CAAC,GAAG,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAA;IAEjD,mBAAmB,CAAC;QAClB,EAAE,EAAE,aAAa;QACjB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,cAAc;QACrB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC;QACrC,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;KAC3C,CAAC,CAAA;IAEF,MAAM,OAAO,GAA2H;QACtI,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,CAAC;QAC/E,CAAC,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,CAAC;QACvE,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,CAAC;QAC3E,CAAC,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,CAAC;KACrE,CAAA;IAED,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QAC9C,mBAAmB,CAAC;YAClB,EAAE;YACF,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;YACd,KAAK;YACL,IAAI;YACJ,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;gBACtB,KAAK,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACvB,CAAC;YACD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;SACrC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,QAAQ,GAAqC;QACjD,CAAC,cAAc,EAAE,kBAAkB,EAAE,YAAY,CAAC;QAClD,CAAC,aAAa,EAAE,kBAAkB,EAAE,WAAW,CAAC;QAChD,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC;QACtC,CAAC,iBAAiB,EAAE,sBAAsB,EAAE,eAAe,CAAC;QAC5D,CAAC,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,CAAC;QACzD,CAAC,cAAc,EAAE,eAAe,EAAE,YAAY,CAAC;QAC/C,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC;QACzC,CAAC,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC;QACtC,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,eAAe,CAAC;QACzD,CAAC,aAAa,EAAE,cAAc,EAAE,WAAW,CAAC;KAC7C,CAAA;IAED,MAAM,KAAK,GAA2B;QACpC,YAAY,EAAE,WAAW;QACzB,WAAW,EAAE,UAAU;QACvB,SAAS,EAAE,WAAW;QACtB,eAAe,EAAE,cAAc;QAC/B,cAAc,EAAE,aAAa;QAC7B,YAAY,EAAE,cAAc;QAC5B,UAAU,EAAE,YAAY;QACxB,SAAS,EAAE,WAAW;QACtB,eAAe,EAAE,WAAW;QAC5B,WAAW,EAAE,aAAa;KAC3B,CAAA;IAED,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC5C,mBAAmB,CAAC;YAClB,EAAE;YACF,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;YACd,KAAK;YACL,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,OAAO;YACP,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC;SACvD,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,OAAO,EACL,cAAc,EACd,eAAe,EACf,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,UAAU,EACV,YAAY,EACZ,oBAAoB,EACpB,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,OAAO,EACL,YAAY,EACZ,SAAS,EACT,WAAW,EACX,UAAU,EACV,SAAS,GACV,MAAM,oBAAoB,CAAA"}
package/dist/menu.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Table context menu.
3
+ *
4
+ * Right-click (and Shift+F10, which fires `contextmenu`) on a table opens the
5
+ * same commands the toolbar exposes, plus the property dialogs. Authors who
6
+ * live in the document rather than the bar should not have to leave the cell
7
+ * they are editing to add a row.
8
+ *
9
+ * Bound on `view.dom` rather than `handleDOMEvents`, because cell-selection
10
+ * handling in `prosemirror-tables` can swallow the event before a later plugin
11
+ * sees it. A capture listener on the editable surface always runs first.
12
+ */
13
+ import { Plugin } from 'prosemirror-state';
14
+ export declare function tableContextMenu(): Plugin;
15
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,MAAM,EAAiB,MAAM,mBAAmB,CAAA;AAuFzD,wBAAgB,gBAAgB,IAAI,MAAM,CAqHzC"}
package/dist/menu.js ADDED
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Table context menu.
3
+ *
4
+ * Right-click (and Shift+F10, which fires `contextmenu`) on a table opens the
5
+ * same commands the toolbar exposes, plus the property dialogs. Authors who
6
+ * live in the document rather than the bar should not have to leave the cell
7
+ * they are editing to add a row.
8
+ *
9
+ * Bound on `view.dom` rather than `handleDOMEvents`, because cell-selection
10
+ * handling in `prosemirror-tables` can swallow the event before a later plugin
11
+ * sees it. A capture listener on the editable surface always runs first.
12
+ */
13
+ import { Plugin, TextSelection } from 'prosemirror-state';
14
+ import { deleteColumn, deleteRow, deleteTable, mergeCells, splitCell } from 'prosemirror-tables';
15
+ import { addColumnAfter, addColumnBefore, addRowAfter, addRowBefore, findTable, inTable, toggleHeaderRow, } from './commands.js';
16
+ import { openCaptionDialog, openCellProperties, openRowProperties, openTableProperties } from './dialogs.js';
17
+ function commandItem(label, command) {
18
+ return {
19
+ label,
20
+ enabled: (view) => command(view.state),
21
+ run: (view) => {
22
+ command(view.state, view.dispatch, view);
23
+ },
24
+ };
25
+ }
26
+ function groups() {
27
+ return [
28
+ {
29
+ items: [
30
+ commandItem('Insert row above', addRowBefore),
31
+ commandItem('Insert row below', addRowAfter),
32
+ commandItem('Delete row', deleteRow),
33
+ ],
34
+ },
35
+ {
36
+ items: [
37
+ commandItem('Insert column before', addColumnBefore),
38
+ commandItem('Insert column after', addColumnAfter),
39
+ commandItem('Delete column', deleteColumn),
40
+ ],
41
+ },
42
+ {
43
+ items: [
44
+ commandItem('Merge cells', mergeCells),
45
+ commandItem('Split cell', splitCell),
46
+ commandItem('Toggle header row', toggleHeaderRow),
47
+ ],
48
+ },
49
+ {
50
+ items: [
51
+ {
52
+ label: 'Table properties',
53
+ run: (view, host) => {
54
+ void openTableProperties(view, host);
55
+ },
56
+ },
57
+ {
58
+ label: 'Row properties',
59
+ run: (view, host) => {
60
+ void openRowProperties(view, host);
61
+ },
62
+ },
63
+ {
64
+ label: 'Cell properties',
65
+ run: (view, host) => {
66
+ void openCellProperties(view, host);
67
+ },
68
+ },
69
+ {
70
+ label: 'Caption',
71
+ run: (view, host) => {
72
+ void openCaptionDialog(view, host);
73
+ },
74
+ },
75
+ ],
76
+ },
77
+ {
78
+ items: [commandItem('Delete table', deleteTable)],
79
+ },
80
+ ];
81
+ }
82
+ export function tableContextMenu() {
83
+ return new Plugin({
84
+ view(view) {
85
+ let menu = null;
86
+ let open = false;
87
+ const hostFor = () => view.dom.closest('openleaf-editor') ??
88
+ view.dom.parentElement ??
89
+ view.dom;
90
+ const close = () => {
91
+ if (!open || !menu)
92
+ return;
93
+ menu.hidden = true;
94
+ open = false;
95
+ view.dom.ownerDocument.removeEventListener('pointerdown', onPointerDown, true);
96
+ };
97
+ const onPointerDown = (event) => {
98
+ const target = event.target;
99
+ if (!(target instanceof Node) || menu?.contains(target))
100
+ return;
101
+ close();
102
+ };
103
+ const fill = () => {
104
+ if (!menu)
105
+ return;
106
+ menu.replaceChildren();
107
+ const doc = menu.ownerDocument;
108
+ for (const group of groups()) {
109
+ const list = doc.createElement('div');
110
+ list.className = 'ol-table-menu-group';
111
+ for (const item of group.items) {
112
+ const button = doc.createElement('button');
113
+ button.type = 'button';
114
+ button.className = 'ol-table-menu-item';
115
+ button.setAttribute('role', 'menuitem');
116
+ button.textContent = item.label;
117
+ const enabled = item.enabled ? item.enabled(view) : true;
118
+ button.setAttribute('aria-disabled', enabled ? 'false' : 'true');
119
+ button.addEventListener('click', () => {
120
+ if (!enabled)
121
+ return;
122
+ close();
123
+ item.run(view, hostFor());
124
+ });
125
+ list.appendChild(button);
126
+ }
127
+ menu.appendChild(list);
128
+ }
129
+ };
130
+ const showAt = (x, y) => {
131
+ const host = hostFor();
132
+ if (!menu) {
133
+ menu = host.ownerDocument.createElement('div');
134
+ menu.className = 'ol-table-menu';
135
+ menu.setAttribute('role', 'menu');
136
+ menu.setAttribute('aria-label', 'Table');
137
+ host.appendChild(menu);
138
+ }
139
+ fill();
140
+ menu.hidden = false;
141
+ menu.style.position = 'fixed';
142
+ menu.style.left = `${Math.round(x)}px`;
143
+ menu.style.top = `${Math.round(y)}px`;
144
+ open = true;
145
+ view.dom.ownerDocument.addEventListener('pointerdown', onPointerDown, true);
146
+ menu.querySelector('button:not([aria-disabled="true"])')?.focus();
147
+ };
148
+ const onContextMenu = (event) => {
149
+ if (!(event instanceof MouseEvent))
150
+ return;
151
+ // Every item in this menu acts on `state.selection`, and a secondary
152
+ // click does not always move it -- right-clicking a second table while a
153
+ // cell selection is live in the first leaves the old one in place. Read
154
+ // the position under the pointer and work from that, or Delete table
155
+ // deletes the table the author did not click.
156
+ const at = view.posAtCoords({ left: event.clientX, top: event.clientY });
157
+ if (!at)
158
+ return;
159
+ const $pos = view.state.doc.resolve(at.pos);
160
+ if (!findTable($pos))
161
+ return;
162
+ // Only retargeted when the click lands outside the current selection: a
163
+ // right-click inside a multi-cell selection has to keep it, or "Delete
164
+ // row" would silently narrow to the one row under the pointer.
165
+ const { from, to } = view.state.selection;
166
+ if (at.pos < from || at.pos > to) {
167
+ view.dispatch(view.state.tr.setSelection(TextSelection.near($pos)));
168
+ }
169
+ if (!inTable(view.state))
170
+ return;
171
+ event.preventDefault();
172
+ event.stopPropagation();
173
+ showAt(event.clientX, event.clientY);
174
+ };
175
+ const onKeyDown = (event) => {
176
+ if (event.key === 'Escape' && open) {
177
+ event.preventDefault();
178
+ close();
179
+ view.focus();
180
+ }
181
+ };
182
+ view.dom.addEventListener('contextmenu', onContextMenu);
183
+ view.dom.addEventListener('keydown', onKeyDown);
184
+ return {
185
+ destroy() {
186
+ view.dom.removeEventListener('contextmenu', onContextMenu);
187
+ view.dom.removeEventListener('keydown', onKeyDown);
188
+ close();
189
+ menu?.remove();
190
+ },
191
+ };
192
+ },
193
+ });
194
+ }
195
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Styles for the insert grid and the table context menu.
3
+ *
4
+ * Registered through `registerStyles` so they ride the same constructable
5
+ * stylesheet path as the toolbar -- no `<style>` injection, which a strict CSP
6
+ * would block silently.
7
+ */
8
+ export declare const TABLE_UI_CSS = "\n.ol-table-grid { display: inline-flex; }\n.ol-table-pop, .ol-table-menu {\n box-sizing: border-box;\n margin: 0;\n padding: 8px;\n border: 1px solid var(--openleaf-color-border, #d1d9e0);\n border-radius: var(--openleaf-radius, 6px);\n background: var(--openleaf-color-surface, #fff);\n color: var(--openleaf-color-text, #1f2328);\n box-shadow: 0 8px 24px rgb(0 0 0 / 18%);\n font-family: var(--openleaf-font, system-ui, -apple-system, sans-serif);\n font-size: var(--openleaf-font-size, 14px);\n z-index: var(--openleaf-z-index, 1);\n}\n.ol-table-pop[hidden], .ol-table-menu[hidden] { display: none; }\n.ol-table-pop-status {\n margin: 0 0 6px;\n font-size: .9em;\n opacity: .8;\n text-align: center;\n}\n.ol-table-size { display: grid; gap: 2px; }\n.ol-table-size-row { display: flex; gap: 2px; }\n.ol-table-size-cell {\n box-sizing: border-box;\n width: 16px;\n height: 16px;\n padding: 0;\n border: 1px solid var(--openleaf-color-border, #d1d9e0);\n border-radius: 2px;\n background: var(--openleaf-color-surface, #fff);\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n}\n.ol-table-size-cell[aria-pressed=\"true\"] {\n background: var(--openleaf-color-surface-active, #dbe9ff);\n border-color: var(--openleaf-color-accent, #0550ae);\n}\n.ol-table-size-cell:focus-visible {\n outline: 2px solid var(--openleaf-color-focus, #0969da);\n outline-offset: 1px;\n}\n.ol-table-menu {\n min-width: 12rem;\n padding: 4px;\n}\n.ol-table-menu-group + .ol-table-menu-group {\n margin-top: 4px;\n padding-top: 4px;\n border-top: 1px solid var(--openleaf-color-border, #d1d9e0);\n}\n.ol-table-menu-item {\n display: block;\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n padding: 6px 10px;\n border: 0;\n border-radius: var(--openleaf-radius, 4px);\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: start;\n cursor: pointer;\n appearance: none;\n -webkit-appearance: none;\n}\n.ol-table-menu-item:hover, .ol-table-menu-item:focus-visible {\n background: var(--openleaf-color-surface-hover, #f0f1f3);\n}\n.ol-table-menu-item:focus-visible {\n outline: 2px solid var(--openleaf-color-focus, #0969da);\n outline-offset: -2px;\n}\n.ol-table-menu-item[aria-disabled=\"true\"] {\n opacity: .55;\n cursor: default;\n}\n@media (forced-colors: active) {\n .ol-table-size-cell { border: 1px solid ButtonBorder; }\n .ol-table-size-cell[aria-pressed=\"true\"] { outline: 2px solid Highlight; }\n}\n";
9
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,YAAY,27EAoFxB,CAAA"}