@threadlabs/looma 0.1.9 → 0.1.10
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/{chunk-UMFO4QNN.js → chunk-DYIMEQY7.js} +27 -26
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/looma.cjs.js +1 -1
- package/dist/cjs/ui-affordance-scope.cjs.entry.js +152 -0
- package/dist/cjs/ui-avatar-group.cjs.entry.js +1 -1
- package/dist/cjs/ui-avatar.cjs.entry.js +1 -1
- package/dist/cjs/ui-badge.cjs.entry.js +1 -1
- package/dist/cjs/ui-button.cjs.entry.js +1 -1
- package/dist/cjs/ui-checkbox.cjs.entry.js +1 -1
- package/dist/cjs/ui-context-menu.cjs.entry.js +1 -1
- package/dist/cjs/ui-dialog.cjs.entry.js +1 -1
- package/dist/cjs/ui-disclosure.cjs.entry.js +1 -1
- package/dist/cjs/ui-floating-action-button.cjs.entry.js +1 -1
- package/dist/cjs/ui-form-field.cjs.entry.js +1 -1
- package/dist/cjs/ui-icon-button.cjs.entry.js +4 -2
- package/dist/cjs/ui-input.cjs.entry.js +1 -1
- package/dist/cjs/ui-menu-item.cjs.entry.js +1 -1
- package/dist/cjs/ui-menu.cjs.entry.js +1 -1
- package/dist/cjs/ui-popover.cjs.entry.js +1 -1
- package/dist/cjs/ui-radio-group.cjs.entry.js +1 -1
- package/dist/cjs/ui-radio.cjs.entry.js +1 -1
- package/dist/cjs/ui-search-result-row.cjs.entry.js +1 -1
- package/dist/cjs/ui-search-shell.cjs.entry.js +1 -1
- package/dist/cjs/ui-select.cjs.entry.js +1 -1
- package/dist/cjs/ui-switch.cjs.entry.js +2 -2
- package/dist/cjs/ui-tabs.cjs.entry.js +1 -1
- package/dist/cjs/ui-textarea.cjs.entry.js +1 -1
- package/dist/cjs/ui-toast-region.cjs.entry.js +1 -1
- package/dist/cjs/ui-tooltip.cjs.entry.js +1 -1
- package/dist/cjs/ui-top-bar.cjs.entry.js +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/ui-affordance-scope/ui-affordance-scope.css +8 -0
- package/dist/collection/components/ui-affordance-scope/ui-affordance-scope.js +70 -0
- package/dist/collection/components/ui-avatar/ui-avatar.js +1 -1
- package/dist/collection/components/ui-avatar-group/ui-avatar-group.js +1 -1
- package/dist/collection/components/ui-badge/ui-badge.js +1 -1
- package/dist/collection/components/ui-button/ui-button.js +1 -1
- package/dist/collection/components/ui-checkbox/ui-checkbox.js +1 -1
- package/dist/collection/components/ui-context-menu/ui-context-menu.js +1 -1
- package/dist/collection/components/ui-dialog/ui-dialog.js +1 -1
- package/dist/collection/components/ui-disclosure/ui-disclosure.js +1 -1
- package/dist/collection/components/ui-floating-action-button/ui-floating-action-button.js +1 -1
- package/dist/collection/components/ui-form-field/ui-form-field.js +1 -1
- package/dist/collection/components/ui-icon-button/ui-icon-button.css +53 -0
- package/dist/collection/components/ui-icon-button/ui-icon-button.js +23 -1
- package/dist/collection/components/ui-input/ui-input.js +1 -1
- package/dist/collection/components/ui-menu/ui-menu.js +1 -1
- package/dist/collection/components/ui-menu-item/ui-menu-item.js +1 -1
- package/dist/collection/components/ui-popover/ui-popover.js +1 -1
- package/dist/collection/components/ui-radio/ui-radio.js +1 -1
- package/dist/collection/components/ui-radio-group/ui-radio-group.js +1 -1
- package/dist/collection/components/ui-search-result-row/ui-search-result-row.js +1 -1
- package/dist/collection/components/ui-search-shell/ui-search-shell.js +1 -1
- package/dist/collection/components/ui-select/ui-select.js +1 -1
- package/dist/collection/components/ui-switch/ui-switch.js +2 -2
- package/dist/collection/components/ui-tabs/ui-tabs.js +1 -1
- package/dist/collection/components/ui-textarea/ui-textarea.js +1 -1
- package/dist/collection/components/ui-toast-region/ui-toast-region.js +1 -1
- package/dist/collection/components/ui-tooltip/ui-tooltip.js +1 -1
- package/dist/collection/components/ui-top-bar/ui-top-bar.js +1 -1
- package/dist/collection/overlay/positioning.js +135 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +1 -1
- package/dist/components/{p-gHC_Ei92.js → p-QiwSQmKJ.js} +1 -1
- package/dist/components/ui-affordance-scope.d.ts +11 -0
- package/dist/components/ui-affordance-scope.js +1 -0
- package/dist/components/ui-avatar-group.js +1 -1
- package/dist/components/ui-avatar.js +1 -1
- package/dist/components/ui-badge.js +1 -1
- package/dist/components/ui-button.js +1 -1
- package/dist/components/ui-checkbox.js +1 -1
- package/dist/components/ui-context-menu.js +1 -1
- package/dist/components/ui-dialog.js +1 -1
- package/dist/components/ui-disclosure.js +1 -1
- package/dist/components/ui-floating-action-button.js +1 -1
- package/dist/components/ui-form-field.js +1 -1
- package/dist/components/ui-icon-button.js +1 -1
- package/dist/components/ui-input.js +1 -1
- package/dist/components/ui-menu-item.js +1 -1
- package/dist/components/ui-menu.js +1 -1
- package/dist/components/ui-popover.js +1 -1
- package/dist/components/ui-radio-group.js +1 -1
- package/dist/components/ui-radio.js +1 -1
- package/dist/components/ui-search-result-row.js +1 -1
- package/dist/components/ui-search-shell.js +1 -1
- package/dist/components/ui-select.js +1 -1
- package/dist/components/ui-switch.js +1 -1
- package/dist/components/ui-tabs.js +1 -1
- package/dist/components/ui-textarea.js +1 -1
- package/dist/components/ui-toast-region.js +1 -1
- package/dist/components/ui-tooltip.js +1 -1
- package/dist/components/ui-top-bar.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/looma.js +1 -1
- package/dist/esm/ui-affordance-scope.entry.js +150 -0
- package/dist/esm/ui-avatar-group.entry.js +1 -1
- package/dist/esm/ui-avatar.entry.js +1 -1
- package/dist/esm/ui-badge.entry.js +1 -1
- package/dist/esm/ui-button.entry.js +1 -1
- package/dist/esm/ui-checkbox.entry.js +1 -1
- package/dist/esm/ui-context-menu.entry.js +1 -1
- package/dist/esm/ui-dialog.entry.js +1 -1
- package/dist/esm/ui-disclosure.entry.js +1 -1
- package/dist/esm/ui-floating-action-button.entry.js +1 -1
- package/dist/esm/ui-form-field.entry.js +1 -1
- package/dist/esm/ui-icon-button.entry.js +4 -2
- package/dist/esm/ui-input.entry.js +1 -1
- package/dist/esm/ui-menu-item.entry.js +1 -1
- package/dist/esm/ui-menu.entry.js +1 -1
- package/dist/esm/ui-popover.entry.js +1 -1
- package/dist/esm/ui-radio-group.entry.js +1 -1
- package/dist/esm/ui-radio.entry.js +1 -1
- package/dist/esm/ui-search-result-row.entry.js +1 -1
- package/dist/esm/ui-search-shell.entry.js +1 -1
- package/dist/esm/ui-select.entry.js +1 -1
- package/dist/esm/ui-switch.entry.js +2 -2
- package/dist/esm/ui-tabs.entry.js +1 -1
- package/dist/esm/ui-textarea.entry.js +1 -1
- package/dist/esm/ui-toast-region.entry.js +1 -1
- package/dist/esm/ui-tooltip.entry.js +1 -1
- package/dist/esm/ui-top-bar.entry.js +1 -1
- package/dist/index.cjs +306 -29
- package/dist/index.d.cts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +127 -2
- package/dist/looma/looma.esm.js +1 -1
- package/dist/looma/p-0198bb21.entry.js +1 -0
- package/dist/looma/{p-d39905f9.entry.js → p-051f578c.entry.js} +1 -1
- package/dist/looma/{p-c14233bc.entry.js → p-0584a051.entry.js} +1 -1
- package/dist/looma/{p-cb15e8e3.entry.js → p-078f9fb8.entry.js} +1 -1
- package/dist/looma/{p-dc857ed4.entry.js → p-0f45c5f0.entry.js} +1 -1
- package/dist/looma/{p-201243dc.entry.js → p-1681b218.entry.js} +1 -1
- package/dist/looma/{p-41d62a83.entry.js → p-2ae73d5b.entry.js} +1 -1
- package/dist/looma/{p-5a645647.entry.js → p-2ed7e241.entry.js} +1 -1
- package/dist/looma/{p-5717a4c4.entry.js → p-34417499.entry.js} +1 -1
- package/dist/looma/{p-610b2eca.entry.js → p-4b422d40.entry.js} +1 -1
- package/dist/looma/{p-15e619fd.entry.js → p-5ba9d496.entry.js} +1 -1
- package/dist/looma/p-5d4713a6.entry.js +1 -0
- package/dist/looma/{p-96de71ad.entry.js → p-624ba086.entry.js} +1 -1
- package/dist/looma/{p-01425a37.entry.js → p-65c25c94.entry.js} +1 -1
- package/dist/looma/{p-66a203a1.entry.js → p-7e94d90d.entry.js} +1 -1
- package/dist/looma/p-8c09c724.entry.js +1 -0
- package/dist/looma/{p-4c54d489.entry.js → p-8d5adb17.entry.js} +1 -1
- package/dist/looma/p-95340a13.entry.js +1 -0
- package/dist/looma/{p-07167650.entry.js → p-95cd639d.entry.js} +1 -1
- package/dist/looma/{p-03f0594b.entry.js → p-96f73d07.entry.js} +1 -1
- package/dist/looma/p-a33522a2.entry.js +1 -0
- package/dist/looma/{p-ee31c7b4.entry.js → p-a5127c7d.entry.js} +1 -1
- package/dist/looma/{p-dfcb2cca.entry.js → p-a9f46811.entry.js} +1 -1
- package/dist/looma/{p-93ce1c62.entry.js → p-b7aa4488.entry.js} +1 -1
- package/dist/looma/{p-5df568d8.entry.js → p-c6721aba.entry.js} +1 -1
- package/dist/looma/{p-3ecd7120.entry.js → p-d273b857.entry.js} +1 -1
- package/dist/looma/{p-24d7aa5b.entry.js → p-ed5abf6d.entry.js} +1 -1
- package/dist/types/components/ui-affordance-scope/ui-affordance-scope.d.ts +11 -0
- package/dist/types/components/ui-icon-button/ui-icon-button.d.ts +2 -0
- package/dist/types/components.d.ts +37 -0
- package/dist/types/overlay/positioning.d.ts +40 -0
- package/dist/ui-affordance-scope.entry-ZKUJ5AT4.js +144 -0
- package/dist/{ui-avatar-group.entry-S6DFXYB7.js → ui-avatar-group.entry-I4XM44BI.js} +2 -2
- package/dist/{ui-avatar.entry-MDRGXLWQ.js → ui-avatar.entry-ZZAMZAVF.js} +2 -2
- package/dist/{ui-badge.entry-RLL4YKPD.js → ui-badge.entry-DQXYMC3E.js} +2 -2
- package/dist/{ui-button.entry-IYMYLBFY.js → ui-button.entry-DM7BUZLI.js} +2 -2
- package/dist/{ui-checkbox.entry-K5FGWDG2.js → ui-checkbox.entry-X3PPWKIJ.js} +2 -2
- package/dist/{ui-context-menu.entry-KWXXJ3ZV.js → ui-context-menu.entry-KAW4NIFE.js} +2 -2
- package/dist/{ui-dialog.entry-RKHLQLQM.js → ui-dialog.entry-D23SNXWB.js} +2 -2
- package/dist/{ui-disclosure.entry-FRZKGEJP.js → ui-disclosure.entry-DOG6JZU7.js} +2 -2
- package/dist/{ui-floating-action-button.entry-BH4FDSTL.js → ui-floating-action-button.entry-VPQ7VBFS.js} +2 -2
- package/dist/{ui-form-field.entry-3CR2KSUH.js → ui-form-field.entry-SYZ6XSCG.js} +2 -2
- package/dist/ui-icon-button.entry-2SZBOIH5.js +26 -0
- package/dist/{ui-input.entry-5PQR37HS.js → ui-input.entry-PALICYLZ.js} +2 -2
- package/dist/{ui-menu-item.entry-2T3QWHLK.js → ui-menu-item.entry-W6TEFP5Y.js} +2 -2
- package/dist/{ui-menu.entry-Q5Z5YO5P.js → ui-menu.entry-7NARDV6S.js} +2 -2
- package/dist/{ui-popover.entry-4P2NWWAY.js → ui-popover.entry-ZXYHLDTP.js} +2 -2
- package/dist/{ui-radio-group.entry-QKPRNV26.js → ui-radio-group.entry-XEUKMD6J.js} +2 -2
- package/dist/{ui-radio.entry-O4DOMFNU.js → ui-radio.entry-4ABBHDLN.js} +2 -2
- package/dist/{ui-search-result-row.entry-BR5O3UCH.js → ui-search-result-row.entry-3HHM7OV4.js} +2 -2
- package/dist/{ui-search-shell.entry-2ZBP7SA3.js → ui-search-shell.entry-PJTFOBPT.js} +2 -2
- package/dist/{ui-select.entry-L75HQY72.js → ui-select.entry-A3RI5XCG.js} +2 -2
- package/dist/{ui-switch.entry-L5QWD3BT.js → ui-switch.entry-JNRS2YTN.js} +3 -3
- package/dist/{ui-tabs.entry-KWRD6Y7J.js → ui-tabs.entry-MQ4V5XCP.js} +2 -2
- package/dist/{ui-textarea.entry-JC3HPEBS.js → ui-textarea.entry-JJXJQZQR.js} +2 -2
- package/dist/{ui-toast-region.entry-C6KK4OM4.js → ui-toast-region.entry-STHVESL5.js} +2 -2
- package/dist/{ui-tooltip.entry-G5EOCWP4.js → ui-tooltip.entry-4W7CRIKI.js} +2 -2
- package/dist/{ui-top-bar.entry-YLKVAQFH.js → ui-top-bar.entry-WM3SS2HR.js} +2 -2
- package/editor/{chunk-OK5NARJI.js → chunk-4VGVEHU2.js} +244 -70
- package/editor/{chunk-NJ2KAMS2.js → chunk-CCDKTWYA.js} +70 -34
- package/editor/extensions/index.d.ts +2 -2
- package/editor/extensions/index.js +1 -1
- package/editor/index.d.ts +1 -1
- package/editor/index.js +7 -2
- package/editor/table-overlay-jjvdARTJ.d.ts +95 -0
- package/editor/ui.d.ts +1 -1
- package/editor/ui.js +7 -2
- package/editor.css +232 -73
- package/layout/index.cjs +5 -0
- package/layout/index.css +22 -3
- package/layout/index.js +5 -0
- package/layout.css +24 -3
- package/package.json +1 -1
- package/tokens.css +9 -0
- package/vue/{chunk-5ELJ4UPG.js → chunk-YN4IUYVY.js} +14 -2
- package/vue/editor/index.js +94 -37
- package/vue/index.d.ts +5 -1
- package/vue/index.js +3 -1
- package/dist/looma/p-754cfff3.entry.js +0 -1
- package/dist/looma/p-940a931a.entry.js +0 -1
- package/dist/looma/p-941221ad.entry.js +0 -1
- package/dist/looma/p-955fb814.entry.js +0 -1
- package/dist/ui-icon-button.entry-LB54U25M.js +0 -24
- package/editor/table-overlay-Bq0F5xPg.d.ts +0 -64
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-CX4QDKSV.js";
|
|
4
4
|
|
|
5
5
|
// src/table-context-menu.ts
|
|
6
|
+
import { clampRectToViewport, getVisualViewportRect } from "@threadlabs/looma/core";
|
|
6
7
|
var TAG = "ui-editor-table-context-menu";
|
|
7
8
|
function dispatchTableAction(element, action) {
|
|
8
9
|
element.dispatchEvent(
|
|
@@ -68,14 +69,11 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
68
69
|
if (!menu) return;
|
|
69
70
|
menu.style.translate = "";
|
|
70
71
|
const rect = menu.getBoundingClientRect();
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const viewportBottom = viewportTop + (visualViewport?.height ?? window.innerHeight);
|
|
77
|
-
const offsetX = rect.right > viewportRight - gutter ? viewportRight - gutter - rect.right : Math.max(0, viewportLeft + gutter - rect.left);
|
|
78
|
-
const offsetY = rect.bottom > viewportBottom - gutter ? viewportBottom - gutter - rect.bottom : Math.max(0, viewportTop + gutter - rect.top);
|
|
72
|
+
const { x: offsetX, y: offsetY } = clampRectToViewport(
|
|
73
|
+
rect,
|
|
74
|
+
getVisualViewportRect(window),
|
|
75
|
+
12
|
|
76
|
+
);
|
|
79
77
|
if (offsetX !== 0 || offsetY !== 0) {
|
|
80
78
|
menu.style.translate = `${offsetX}px ${offsetY}px`;
|
|
81
79
|
}
|
|
@@ -107,6 +105,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
107
105
|
{
|
|
108
106
|
heading: "Cells",
|
|
109
107
|
actions: [
|
|
108
|
+
{ action: "clear-cells", label: "Clear selected cells" },
|
|
110
109
|
{ action: "merge-cells", label: "Merge cells", can: "can-merge-cells" },
|
|
111
110
|
{ action: "split-cell", label: "Split cell", can: "can-split-cell" }
|
|
112
111
|
]
|
|
@@ -126,7 +125,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
126
125
|
}
|
|
127
126
|
return {
|
|
128
127
|
...section,
|
|
129
|
-
actions: section.actions.filter((action) => this.getBoolAttr(action.can))
|
|
128
|
+
actions: section.actions.filter((action) => !action.can || this.getBoolAttr(action.can))
|
|
130
129
|
};
|
|
131
130
|
}).filter((section) => "backgrounds" in section ? section.backgrounds.length > 0 : section.actions.length > 0);
|
|
132
131
|
let html = '<div class="ui-editor-table-context-menu" role="menu">';
|
|
@@ -277,6 +276,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
277
276
|
{
|
|
278
277
|
heading: "Cells",
|
|
279
278
|
actions: [
|
|
279
|
+
{ action: "clear-cells", label: "Clear selected cells" },
|
|
280
280
|
{ action: "merge-cells", label: "Merge selected cells", can: "can-merge-cells" },
|
|
281
281
|
{ action: "split-cell", label: "Split merged cell", can: "can-split-cell" }
|
|
282
282
|
]
|
|
@@ -292,7 +292,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
292
292
|
];
|
|
293
293
|
const availableOverflowSections = overflowSections.map((section) => ({
|
|
294
294
|
...section,
|
|
295
|
-
actions: section.actions.filter((action) => this.getBoolAttr(action.can))
|
|
295
|
+
actions: section.actions.filter((action) => !action.can || this.getBoolAttr(action.can))
|
|
296
296
|
})).filter((section) => section.actions.length > 0);
|
|
297
297
|
this.innerHTML = [
|
|
298
298
|
'<div class="ui-editor-table-toolbar" role="toolbar" aria-label="Table actions">',
|
|
@@ -467,17 +467,112 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
// src/table-overlay.ts
|
|
470
|
+
import {
|
|
471
|
+
createProximityCoordinator
|
|
472
|
+
} from "@threadlabs/looma/core";
|
|
470
473
|
var TAG4 = "ui-editor-table-overlay";
|
|
471
474
|
var DEFAULT_ROWS = 3;
|
|
472
475
|
var DEFAULT_COLS = 3;
|
|
476
|
+
function sameNumbers(left, right) {
|
|
477
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
478
|
+
}
|
|
479
|
+
function sameActiveCell(left, right) {
|
|
480
|
+
if (left === right) return true;
|
|
481
|
+
if (!left || !right) return false;
|
|
482
|
+
return left.left === right.left && left.top === right.top && left.width === right.width && left.height === right.height && left.rowIndex === right.rowIndex && left.columnIndex === right.columnIndex;
|
|
483
|
+
}
|
|
484
|
+
function sameGeometry(left, right) {
|
|
485
|
+
if (left === right) return true;
|
|
486
|
+
if (!left || !right) return false;
|
|
487
|
+
return sameNumbers(left.rowBoundaries, right.rowBoundaries) && sameNumbers(left.columnBoundaries, right.columnBoundaries) && sameActiveCell(left.activeCell, right.activeCell);
|
|
488
|
+
}
|
|
489
|
+
function mapTableCells(table) {
|
|
490
|
+
const rows = Array.from(table.rows);
|
|
491
|
+
const grid = [];
|
|
492
|
+
const coordinates = /* @__PURE__ */ new Map();
|
|
493
|
+
rows.forEach((row, rowIndex) => {
|
|
494
|
+
grid[rowIndex] ??= [];
|
|
495
|
+
let columnIndex = 0;
|
|
496
|
+
for (const cell of Array.from(row.cells)) {
|
|
497
|
+
while (grid[rowIndex]?.[columnIndex]) columnIndex += 1;
|
|
498
|
+
coordinates.set(cell, { rowIndex, columnIndex });
|
|
499
|
+
const rowSpan = cell.rowSpan === 0 ? rows.length - rowIndex : Math.max(1, cell.rowSpan);
|
|
500
|
+
const columnSpan = Math.max(1, cell.colSpan);
|
|
501
|
+
for (let rowOffset = 0; rowOffset < rowSpan; rowOffset += 1) {
|
|
502
|
+
const gridRow = grid[rowIndex + rowOffset] ??= [];
|
|
503
|
+
for (let columnOffset = 0; columnOffset < columnSpan; columnOffset += 1) {
|
|
504
|
+
gridRow[columnIndex + columnOffset] = cell;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
columnIndex += columnSpan;
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
return { grid, coordinates };
|
|
511
|
+
}
|
|
512
|
+
function resolveTableCellAt(table, rowIndex, columnIndex) {
|
|
513
|
+
return mapTableCells(table).grid[rowIndex]?.[columnIndex] ?? null;
|
|
514
|
+
}
|
|
515
|
+
function uniqueSorted(values) {
|
|
516
|
+
return values.sort((left, right) => left - right).filter((value, index, all) => index === 0 || Math.abs(value - (all[index - 1] ?? value)) >= 0.5).map((value) => Math.round(value * 100) / 100);
|
|
517
|
+
}
|
|
518
|
+
function measureTableOverlayGeometry(table, activeCell) {
|
|
519
|
+
const tableRect = table.getBoundingClientRect();
|
|
520
|
+
const rows = Array.from(table.rows);
|
|
521
|
+
const cells = rows.flatMap((row) => Array.from(row.cells));
|
|
522
|
+
const { coordinates } = mapTableCells(table);
|
|
523
|
+
const rowBoundaries = uniqueSorted(rows.flatMap((row) => {
|
|
524
|
+
const rect = row.getBoundingClientRect();
|
|
525
|
+
return [rect.top - tableRect.top, rect.bottom - tableRect.top];
|
|
526
|
+
}));
|
|
527
|
+
const columnBoundaries = uniqueSorted(cells.flatMap((cell) => {
|
|
528
|
+
const rect = cell.getBoundingClientRect();
|
|
529
|
+
return [rect.left - tableRect.left, rect.right - tableRect.left];
|
|
530
|
+
}));
|
|
531
|
+
if (!activeCell || !table.contains(activeCell)) {
|
|
532
|
+
return { rowBoundaries, columnBoundaries, activeCell: null };
|
|
533
|
+
}
|
|
534
|
+
const cellRect = activeCell.getBoundingClientRect();
|
|
535
|
+
const coordinate = coordinates.get(activeCell);
|
|
536
|
+
return {
|
|
537
|
+
rowBoundaries,
|
|
538
|
+
columnBoundaries,
|
|
539
|
+
activeCell: {
|
|
540
|
+
left: Math.round((cellRect.left - tableRect.left) * 100) / 100,
|
|
541
|
+
top: Math.round((cellRect.top - tableRect.top) * 100) / 100,
|
|
542
|
+
width: Math.round(cellRect.width * 100) / 100,
|
|
543
|
+
height: Math.round(cellRect.height * 100) / 100,
|
|
544
|
+
rowIndex: coordinate?.rowIndex ?? 0,
|
|
545
|
+
columnIndex: coordinate?.columnIndex ?? 0
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function finiteNumbers(value) {
|
|
550
|
+
if (!value) return [];
|
|
551
|
+
const values = value.split(",").map((part) => Number(part.trim()));
|
|
552
|
+
return values.every(Number.isFinite) ? values : [];
|
|
553
|
+
}
|
|
554
|
+
function fallbackBoundaries(segments, length) {
|
|
555
|
+
return Array.from({ length: segments + 1 }, (_, index) => index * length / segments);
|
|
556
|
+
}
|
|
473
557
|
if (typeof HTMLElement !== "undefined") {
|
|
474
558
|
class UIEditorTableOverlayElement extends HTMLElement {
|
|
475
559
|
static get observedAttributes() {
|
|
476
|
-
return ["open", "rows", "cols"];
|
|
560
|
+
return ["open", "rows", "cols", "row-boundaries", "column-boundaries", "active-cell"];
|
|
477
561
|
}
|
|
478
562
|
#rows = DEFAULT_ROWS;
|
|
479
563
|
#cols = DEFAULT_COLS;
|
|
480
564
|
#activeControlKey = null;
|
|
565
|
+
#proximity = null;
|
|
566
|
+
#geometry = null;
|
|
567
|
+
#renderPending = false;
|
|
568
|
+
get geometry() {
|
|
569
|
+
return this.#geometry;
|
|
570
|
+
}
|
|
571
|
+
set geometry(value) {
|
|
572
|
+
if (sameGeometry(this.#geometry, value)) return;
|
|
573
|
+
this.#geometry = value;
|
|
574
|
+
this.#scheduleRender();
|
|
575
|
+
}
|
|
481
576
|
connectedCallback() {
|
|
482
577
|
this.#rows = this.#readBoundedNumber("rows", DEFAULT_ROWS);
|
|
483
578
|
this.#cols = this.#readBoundedNumber("cols", DEFAULT_COLS);
|
|
@@ -487,6 +582,10 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
487
582
|
this.addEventListener("pointerout", this.onPointerOut);
|
|
488
583
|
this.addEventListener("focusin", this.onFocusIn);
|
|
489
584
|
this.addEventListener("focusout", this.onFocusOut);
|
|
585
|
+
this.#proximity = createProximityCoordinator(this, {
|
|
586
|
+
pointerTarget: this.ownerDocument,
|
|
587
|
+
anchorSelector: ".ui-editor-table-overlay__handle[data-ui-affordance]"
|
|
588
|
+
});
|
|
490
589
|
}
|
|
491
590
|
disconnectedCallback() {
|
|
492
591
|
this.removeEventListener("click", this.onClick);
|
|
@@ -494,68 +593,139 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
494
593
|
this.removeEventListener("pointerout", this.onPointerOut);
|
|
495
594
|
this.removeEventListener("focusin", this.onFocusIn);
|
|
496
595
|
this.removeEventListener("focusout", this.onFocusOut);
|
|
596
|
+
this.#proximity?.destroy();
|
|
597
|
+
this.#proximity = null;
|
|
497
598
|
}
|
|
498
599
|
attributeChangedCallback(name) {
|
|
499
600
|
if (name === "rows") this.#rows = this.#readBoundedNumber("rows", DEFAULT_ROWS);
|
|
500
601
|
if (name === "cols") this.#cols = this.#readBoundedNumber("cols", DEFAULT_COLS);
|
|
501
|
-
this
|
|
602
|
+
this.#scheduleRender();
|
|
603
|
+
}
|
|
604
|
+
#scheduleRender() {
|
|
605
|
+
if (!this.isConnected || this.#renderPending) return;
|
|
606
|
+
this.#renderPending = true;
|
|
607
|
+
queueMicrotask(() => {
|
|
608
|
+
this.#renderPending = false;
|
|
609
|
+
if (this.isConnected) this.render();
|
|
610
|
+
});
|
|
502
611
|
}
|
|
503
612
|
#readBoundedNumber(name, fallback) {
|
|
504
|
-
const parsed = parseInt(this.getAttribute(name) ?? String(fallback), 10);
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
613
|
+
const parsed = Number.parseInt(this.getAttribute(name) ?? String(fallback), 10);
|
|
614
|
+
return Number.isFinite(parsed) ? Math.min(100, Math.max(1, parsed)) : fallback;
|
|
615
|
+
}
|
|
616
|
+
#boundaries(name, segments) {
|
|
617
|
+
if (this.#geometry) {
|
|
618
|
+
return name === "row-boundaries" ? this.#geometry.rowBoundaries : this.#geometry.columnBoundaries;
|
|
619
|
+
}
|
|
620
|
+
const explicit = finiteNumbers(this.getAttribute(name));
|
|
621
|
+
if (explicit.length === segments + 1) return explicit;
|
|
622
|
+
const length = name === "row-boundaries" ? this.getBoundingClientRect().height : this.getBoundingClientRect().width;
|
|
623
|
+
return fallbackBoundaries(segments, length);
|
|
624
|
+
}
|
|
625
|
+
#activeCell() {
|
|
626
|
+
if (this.#geometry) return this.#geometry.activeCell;
|
|
627
|
+
const values = finiteNumbers(this.getAttribute("active-cell"));
|
|
628
|
+
if (values.length !== 6) return null;
|
|
629
|
+
const [left, top, width, height, rowIndex, columnIndex] = values;
|
|
630
|
+
if (left === void 0 || top === void 0 || width === void 0 || height === void 0 || rowIndex === void 0 || columnIndex === void 0) return null;
|
|
631
|
+
return { left, top, width, height, rowIndex, columnIndex };
|
|
632
|
+
}
|
|
633
|
+
dispatch(detail) {
|
|
634
|
+
this.dispatchEvent(new CustomEvent(
|
|
635
|
+
"looma-editor-table-overlay-action",
|
|
636
|
+
{ detail, bubbles: true, composed: true }
|
|
637
|
+
));
|
|
509
638
|
}
|
|
510
639
|
onClick = (event) => {
|
|
511
|
-
const target = event.target.closest("[data-action]");
|
|
512
|
-
if (!target)
|
|
640
|
+
const target = event.target.closest("button[data-action]");
|
|
641
|
+
if (!target) return;
|
|
642
|
+
const action = target.dataset.action;
|
|
643
|
+
if (!action) return;
|
|
644
|
+
if (action === "select-row" || action === "select-column") {
|
|
645
|
+
const rowIndex = Number.parseInt(target.dataset.rowIndex ?? "", 10);
|
|
646
|
+
const columnIndex = Number.parseInt(target.dataset.columnIndex ?? "", 10);
|
|
647
|
+
if (Number.isFinite(rowIndex) && Number.isFinite(columnIndex)) {
|
|
648
|
+
this.dispatch({ action, rowIndex, columnIndex });
|
|
649
|
+
}
|
|
513
650
|
return;
|
|
514
651
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
652
|
+
if (action === "open-cell-menu") {
|
|
653
|
+
const rowIndex = Number.parseInt(target.dataset.rowIndex ?? "", 10);
|
|
654
|
+
const columnIndex = Number.parseInt(target.dataset.columnIndex ?? "", 10);
|
|
655
|
+
if (!Number.isFinite(rowIndex) || !Number.isFinite(columnIndex)) return;
|
|
656
|
+
const rect = target.getBoundingClientRect();
|
|
657
|
+
this.dispatch({
|
|
658
|
+
action,
|
|
659
|
+
rowIndex,
|
|
660
|
+
columnIndex,
|
|
661
|
+
anchor: { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }
|
|
662
|
+
});
|
|
518
663
|
return;
|
|
519
664
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
bubbles: true,
|
|
524
|
-
composed: true
|
|
525
|
-
})
|
|
526
|
-
);
|
|
665
|
+
const boundaryIndex = Number.parseInt(target.dataset.boundaryIndex ?? "", 10);
|
|
666
|
+
if (!Number.isFinite(boundaryIndex) || boundaryIndex < 0) return;
|
|
667
|
+
this.dispatch({ action, boundaryIndex });
|
|
527
668
|
};
|
|
528
669
|
onPointerOver = (event) => {
|
|
529
670
|
const control = event.target.closest("[data-control-key]");
|
|
530
671
|
this.#setActiveControl(control?.dataset.controlKey ?? null);
|
|
531
672
|
};
|
|
532
673
|
onPointerOut = (event) => {
|
|
533
|
-
const
|
|
534
|
-
const
|
|
535
|
-
this.#setActiveControl(
|
|
674
|
+
const related = event.relatedTarget;
|
|
675
|
+
const next = related instanceof Element ? related.closest("[data-control-key]") : null;
|
|
676
|
+
this.#setActiveControl(next?.dataset.controlKey ?? null);
|
|
536
677
|
};
|
|
537
678
|
onFocusIn = (event) => {
|
|
538
679
|
const control = event.target.closest("[data-control-key]");
|
|
539
680
|
this.#setActiveControl(control?.dataset.controlKey ?? null);
|
|
540
681
|
};
|
|
541
682
|
onFocusOut = (event) => {
|
|
542
|
-
const
|
|
543
|
-
const
|
|
544
|
-
this.#setActiveControl(
|
|
683
|
+
const related = event.relatedTarget;
|
|
684
|
+
const next = related instanceof Element ? related.closest("[data-control-key]") : null;
|
|
685
|
+
this.#setActiveControl(next?.dataset.controlKey ?? null);
|
|
545
686
|
};
|
|
546
687
|
#setActiveControl(controlKey) {
|
|
547
|
-
if (this.#activeControlKey === controlKey)
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
688
|
+
if (this.#activeControlKey === controlKey) return;
|
|
550
689
|
this.#activeControlKey = controlKey;
|
|
551
690
|
this.#syncActiveControl();
|
|
552
691
|
}
|
|
553
692
|
#syncActiveControl() {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
control.dataset.active = this.#activeControlKey && control.dataset.controlKey === this.#activeControlKey ? "true" : "false";
|
|
693
|
+
this.querySelectorAll("[data-control-key]").forEach((control) => {
|
|
694
|
+
control.dataset.active = this.#activeControlKey === control.dataset.controlKey ? "true" : "false";
|
|
557
695
|
});
|
|
558
696
|
}
|
|
697
|
+
#insertionControl(axis, index, position) {
|
|
698
|
+
const first = index === 0;
|
|
699
|
+
const action = axis === "row" ? first ? "add-row-before" : "add-row-after" : first ? "add-column-before" : "add-column-after";
|
|
700
|
+
const noun = axis === "row" ? "row" : "column";
|
|
701
|
+
const relation = first ? axis === "row" ? "above" : "left" : axis === "row" ? "below" : "right";
|
|
702
|
+
const label = `Insert ${noun} ${relation}`;
|
|
703
|
+
const controlKey = `${axis}:${index}`;
|
|
704
|
+
const positionStyle = axis === "row" ? `top:${position}px;` : `left:${position}px;`;
|
|
705
|
+
return [
|
|
706
|
+
`<div class="ui-editor-table-overlay__control ui-editor-table-overlay__control--${axis}"`,
|
|
707
|
+
` style="${positionStyle}" data-control-key="${controlKey}"`,
|
|
708
|
+
` data-active="${this.#activeControlKey === controlKey ? "true" : "false"}">`,
|
|
709
|
+
'<span class="ui-editor-table-overlay__line" aria-hidden="true"></span>',
|
|
710
|
+
'<span class="ui-editor-table-overlay__guide" data-ui-guide aria-hidden="true"></span>',
|
|
711
|
+
`<button type="button" class="ui-editor-table-overlay__handle" data-ui-affordance="insert-${noun}"`,
|
|
712
|
+
` data-action="${action}" data-boundary-index="${index}" aria-label="${label}">`,
|
|
713
|
+
'<span aria-hidden="true">+</span>',
|
|
714
|
+
`<span class="ui-editor-table-overlay__tooltip" role="tooltip">${label}</span>`,
|
|
715
|
+
"</button>",
|
|
716
|
+
"</div>"
|
|
717
|
+
].join("");
|
|
718
|
+
}
|
|
719
|
+
#activeCellControls(cell) {
|
|
720
|
+
const centerX = cell.left + cell.width / 2;
|
|
721
|
+
const centerY = cell.top + cell.height / 2;
|
|
722
|
+
const indexes = `data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}"`;
|
|
723
|
+
return [
|
|
724
|
+
`<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--row" style="top:${centerY}px" data-action="select-row" ${indexes} title="Select row" aria-label="Select row"><span aria-hidden="true"></span></button>`,
|
|
725
|
+
`<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--column" style="left:${centerX}px" data-action="select-column" ${indexes} title="Select column" aria-label="Select column"><span aria-hidden="true"></span></button>`,
|
|
726
|
+
`<button type="button" class="ui-editor-table-overlay__cell-menu" style="left:${cell.left + cell.width - 30}px;top:${cell.top + 6}px" data-action="open-cell-menu" ${indexes} title="Cell actions" aria-label="Cell actions"><span aria-hidden="true">\u2304</span></button>`
|
|
727
|
+
].join("");
|
|
728
|
+
}
|
|
559
729
|
render() {
|
|
560
730
|
const open = this.hasAttribute("open") && this.getAttribute("open") !== "false";
|
|
561
731
|
this.hidden = !open;
|
|
@@ -563,24 +733,22 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
563
733
|
this.#setActiveControl(null);
|
|
564
734
|
return;
|
|
565
735
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
html += "</div>";
|
|
581
|
-
html += "</div>";
|
|
582
|
-
this.innerHTML = html;
|
|
736
|
+
const rows = this.#boundaries("row-boundaries", this.#rows);
|
|
737
|
+
const columns = this.#boundaries("column-boundaries", this.#cols);
|
|
738
|
+
const cell = this.#activeCell();
|
|
739
|
+
this.innerHTML = [
|
|
740
|
+
'<div class="ui-editor-table-overlay" aria-label="Table controls">',
|
|
741
|
+
'<div class="ui-editor-table-overlay__rows">',
|
|
742
|
+
rows.map((position, index) => this.#insertionControl("row", index, position)).join(""),
|
|
743
|
+
"</div>",
|
|
744
|
+
'<div class="ui-editor-table-overlay__cols">',
|
|
745
|
+
columns.map((position, index) => this.#insertionControl("col", index, position)).join(""),
|
|
746
|
+
"</div>",
|
|
747
|
+
cell ? this.#activeCellControls(cell) : "",
|
|
748
|
+
"</div>"
|
|
749
|
+
].join("");
|
|
583
750
|
this.#syncActiveControl();
|
|
751
|
+
this.#proximity?.refresh();
|
|
584
752
|
}
|
|
585
753
|
}
|
|
586
754
|
if (typeof window !== "undefined" && !customElements.get(TAG4)) {
|
|
@@ -589,6 +757,7 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
589
757
|
}
|
|
590
758
|
|
|
591
759
|
// src/slash-menu.ts
|
|
760
|
+
import { getVisualViewportRect as getVisualViewportRect2 } from "@threadlabs/looma/core";
|
|
592
761
|
var TAG5 = "ui-editor-slash-menu";
|
|
593
762
|
var MOBILE_BREAKPOINT = 768;
|
|
594
763
|
var MENU_HEIGHT_ESTIMATE = 320;
|
|
@@ -737,9 +906,9 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
737
906
|
this.style.display = "none";
|
|
738
907
|
return;
|
|
739
908
|
}
|
|
740
|
-
const
|
|
741
|
-
const viewportWidth =
|
|
742
|
-
const viewportHeight =
|
|
909
|
+
const viewport = getVisualViewportRect2(window);
|
|
910
|
+
const viewportWidth = viewport.width;
|
|
911
|
+
const viewportHeight = viewport.height;
|
|
743
912
|
this.style.display = "block";
|
|
744
913
|
this.style.position = "fixed";
|
|
745
914
|
this.style.zIndex = "500";
|
|
@@ -749,30 +918,30 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
749
918
|
MENU_HEIGHT_ESTIMATE,
|
|
750
919
|
Math.max(0, viewportHeight - toolbarReserve)
|
|
751
920
|
);
|
|
752
|
-
this.style.left = `${
|
|
921
|
+
this.style.left = `${viewport.left}px`;
|
|
753
922
|
this.style.right = "";
|
|
754
923
|
this.style.bottom = "";
|
|
755
|
-
this.style.top = `${
|
|
924
|
+
this.style.top = `${viewport.top + viewportHeight - menuHeight - toolbarReserve}px`;
|
|
756
925
|
this.style.width = `${viewportWidth}px`;
|
|
757
926
|
this.style.maxHeight = `${menuHeight}px`;
|
|
758
927
|
return;
|
|
759
928
|
}
|
|
760
929
|
let top;
|
|
761
|
-
const spaceBelow =
|
|
762
|
-
const spaceAbove = rect.top - OFFSET;
|
|
930
|
+
const spaceBelow = viewport.bottom - rect.bottom - OFFSET;
|
|
931
|
+
const spaceAbove = rect.top - viewport.top - OFFSET;
|
|
763
932
|
if (spaceBelow >= MENU_HEIGHT_ESTIMATE || spaceBelow >= spaceAbove) {
|
|
764
933
|
top = rect.bottom + OFFSET;
|
|
765
934
|
} else {
|
|
766
935
|
top = rect.top - OFFSET - MENU_HEIGHT_ESTIMATE;
|
|
767
936
|
}
|
|
768
937
|
let left = rect.left;
|
|
769
|
-
if (left + MENU_WIDTH >
|
|
770
|
-
left =
|
|
938
|
+
if (left + MENU_WIDTH > viewport.right - 8) {
|
|
939
|
+
left = viewport.right - MENU_WIDTH - 8;
|
|
771
940
|
}
|
|
772
|
-
if (left < 8) {
|
|
773
|
-
left = 8;
|
|
941
|
+
if (left < viewport.left + 8) {
|
|
942
|
+
left = viewport.left + 8;
|
|
774
943
|
}
|
|
775
|
-
this.style.top = `${Math.max(8, top)}px`;
|
|
944
|
+
this.style.top = `${Math.max(viewport.top + 8, top)}px`;
|
|
776
945
|
this.style.left = `${left}px`;
|
|
777
946
|
this.style.right = "";
|
|
778
947
|
this.style.bottom = "";
|
|
@@ -840,3 +1009,8 @@ if (typeof HTMLElement !== "undefined") {
|
|
|
840
1009
|
customElements.define(TAG6, UIEditorToolbarElement);
|
|
841
1010
|
}
|
|
842
1011
|
}
|
|
1012
|
+
|
|
1013
|
+
export {
|
|
1014
|
+
resolveTableCellAt,
|
|
1015
|
+
measureTableOverlayGeometry
|
|
1016
|
+
};
|
|
@@ -5470,7 +5470,14 @@ function getDefaultEditorExtensions(options = {}) {
|
|
|
5470
5470
|
|
|
5471
5471
|
// src/extensions/table-commands.ts
|
|
5472
5472
|
import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
|
|
5473
|
-
import {
|
|
5473
|
+
import {
|
|
5474
|
+
addColumn,
|
|
5475
|
+
addRow,
|
|
5476
|
+
CellSelection as CellSelection2,
|
|
5477
|
+
cellAround,
|
|
5478
|
+
deleteCellSelection,
|
|
5479
|
+
TableMap
|
|
5480
|
+
} from "@tiptap/pm/tables";
|
|
5474
5481
|
var NO_TABLE_CAPABILITIES = {
|
|
5475
5482
|
canAddRowBefore: false,
|
|
5476
5483
|
canAddRowAfter: false,
|
|
@@ -5548,6 +5555,14 @@ function handleTableAction(editor, detail) {
|
|
|
5548
5555
|
return editor.chain().focus().deleteColumn().run();
|
|
5549
5556
|
case "delete-table":
|
|
5550
5557
|
return editor.chain().focus().deleteTable().run();
|
|
5558
|
+
case "clear-cells": {
|
|
5559
|
+
if (!(editor.state.selection instanceof CellSelection2)) {
|
|
5560
|
+
const cellPos = findSelectedCellPosition(editor);
|
|
5561
|
+
if (cellPos === null) return false;
|
|
5562
|
+
if (!editor.commands.setCellSelection({ anchorCell: cellPos })) return false;
|
|
5563
|
+
}
|
|
5564
|
+
return deleteCellSelection(editor.state, editor.view.dispatch);
|
|
5565
|
+
}
|
|
5551
5566
|
case "merge-cells":
|
|
5552
5567
|
return editor.chain().focus().mergeCells().run();
|
|
5553
5568
|
case "split-cell":
|
|
@@ -5619,17 +5634,6 @@ function normalizeColumnWidths(widths, availableWidth, minWidth) {
|
|
|
5619
5634
|
);
|
|
5620
5635
|
return distributeWidthDelta(scaled, availableWidth, minWidth);
|
|
5621
5636
|
}
|
|
5622
|
-
function getTextPositionInCell(tablePos, table, rowIndex, colIndex) {
|
|
5623
|
-
let pos = tablePos + 1;
|
|
5624
|
-
for (let r = 0; r < rowIndex; r++) {
|
|
5625
|
-
pos += table.child(r).nodeSize;
|
|
5626
|
-
}
|
|
5627
|
-
const row = table.child(rowIndex);
|
|
5628
|
-
for (let c = 0; c < colIndex; c++) {
|
|
5629
|
-
pos += row.child(c).nodeSize;
|
|
5630
|
-
}
|
|
5631
|
-
return pos + 3;
|
|
5632
|
-
}
|
|
5633
5637
|
function findTable(editor) {
|
|
5634
5638
|
const { $from } = editor.state.selection;
|
|
5635
5639
|
for (let d = $from.depth; d > 0; d--) {
|
|
@@ -5640,6 +5644,26 @@ function findTable(editor) {
|
|
|
5640
5644
|
}
|
|
5641
5645
|
return null;
|
|
5642
5646
|
}
|
|
5647
|
+
function findSelectedCellPosition(editor) {
|
|
5648
|
+
return cellAround(editor.state.selection.$from)?.pos ?? null;
|
|
5649
|
+
}
|
|
5650
|
+
function selectTableAxis(editor, axis, rowIndex, columnIndex) {
|
|
5651
|
+
const tableInfo = findTable(editor);
|
|
5652
|
+
if (!tableInfo) return false;
|
|
5653
|
+
const { pos: tablePos, node: table } = tableInfo;
|
|
5654
|
+
const map = TableMap.get(table);
|
|
5655
|
+
const row = Math.min(Math.max(0, rowIndex), map.height - 1);
|
|
5656
|
+
const column = Math.min(Math.max(0, columnIndex), map.width - 1);
|
|
5657
|
+
const start = axis === "row" ? map.positionAt(row, 0, table) : map.positionAt(0, column, table);
|
|
5658
|
+
const end = axis === "row" ? map.positionAt(row, map.width - 1, table) : map.positionAt(map.height - 1, column, table);
|
|
5659
|
+
const tableStart = tablePos + 1;
|
|
5660
|
+
if (!editor.commands.setCellSelection({
|
|
5661
|
+
anchorCell: tableStart + start,
|
|
5662
|
+
headCell: tableStart + end
|
|
5663
|
+
})) return false;
|
|
5664
|
+
editor.commands.focus();
|
|
5665
|
+
return true;
|
|
5666
|
+
}
|
|
5643
5667
|
function insertTableAtRange(editor, range, options = {}) {
|
|
5644
5668
|
const rows = Math.min(10, Math.max(1, options.rows ?? 3));
|
|
5645
5669
|
const cols = Math.min(10, Math.max(1, options.cols ?? 3));
|
|
@@ -5700,45 +5724,57 @@ function normalizeActiveTableColumnWidths(editor, tableElement, minWidth = 25) {
|
|
|
5700
5724
|
function handleTableOverlayAction(editor, detail) {
|
|
5701
5725
|
const tableInfo = findTable(editor);
|
|
5702
5726
|
if (!tableInfo) return false;
|
|
5703
|
-
const { action
|
|
5727
|
+
const { action } = detail;
|
|
5728
|
+
if (action === "select-row" || action === "select-column") {
|
|
5729
|
+
return selectTableAxis(
|
|
5730
|
+
editor,
|
|
5731
|
+
action === "select-row" ? "row" : "column",
|
|
5732
|
+
detail.rowIndex,
|
|
5733
|
+
detail.columnIndex
|
|
5734
|
+
);
|
|
5735
|
+
}
|
|
5736
|
+
if (action === "open-cell-menu") return true;
|
|
5737
|
+
if (!("boundaryIndex" in detail)) return false;
|
|
5738
|
+
const { boundaryIndex } = detail;
|
|
5704
5739
|
const { pos: tablePos, node: table } = tableInfo;
|
|
5705
|
-
const
|
|
5706
|
-
const
|
|
5707
|
-
|
|
5708
|
-
|
|
5740
|
+
const map = TableMap.get(table);
|
|
5741
|
+
const rect = {
|
|
5742
|
+
map,
|
|
5743
|
+
table,
|
|
5744
|
+
tableStart: tablePos + 1,
|
|
5745
|
+
left: 0,
|
|
5746
|
+
top: 0,
|
|
5747
|
+
right: map.width,
|
|
5748
|
+
bottom: map.height
|
|
5749
|
+
};
|
|
5750
|
+
let transaction = editor.state.tr;
|
|
5709
5751
|
switch (action) {
|
|
5710
5752
|
case "add-row-before": {
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
cellPos = getTextPositionInCell(tablePos, table, rowIndex, 0);
|
|
5714
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addRowBefore().run();
|
|
5753
|
+
if (boundaryIndex !== 0) return false;
|
|
5754
|
+
transaction = addRow(transaction, rect, 0);
|
|
5715
5755
|
break;
|
|
5716
5756
|
}
|
|
5717
5757
|
case "add-row-after": {
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
cellPos = getTextPositionInCell(tablePos, table, rowIndex, 0);
|
|
5721
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addRowAfter().run();
|
|
5758
|
+
if (boundaryIndex < 1 || boundaryIndex > map.height) return false;
|
|
5759
|
+
transaction = addRow(transaction, rect, boundaryIndex);
|
|
5722
5760
|
break;
|
|
5723
5761
|
}
|
|
5724
5762
|
case "add-column-before": {
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
cellPos = getTextPositionInCell(tablePos, table, 0, colIndex);
|
|
5728
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addColumnBefore().run();
|
|
5763
|
+
if (boundaryIndex !== 0) return false;
|
|
5764
|
+
transaction = addColumn(transaction, rect, 0);
|
|
5729
5765
|
break;
|
|
5730
5766
|
}
|
|
5731
5767
|
case "add-column-after": {
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
cellPos = getTextPositionInCell(tablePos, table, 0, colIndex);
|
|
5735
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addColumnAfter().run();
|
|
5768
|
+
if (boundaryIndex < 1 || boundaryIndex > map.width) return false;
|
|
5769
|
+
transaction = addColumn(transaction, rect, boundaryIndex);
|
|
5736
5770
|
break;
|
|
5737
5771
|
}
|
|
5738
5772
|
default:
|
|
5739
5773
|
return false;
|
|
5740
5774
|
}
|
|
5741
|
-
|
|
5775
|
+
editor.view.dispatch(transaction);
|
|
5776
|
+
editor.commands.focus();
|
|
5777
|
+
return true;
|
|
5742
5778
|
}
|
|
5743
5779
|
|
|
5744
5780
|
// src/extensions/slash-command.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnyExtension, Editor, Range, Extension } from '@tiptap/core';
|
|
2
|
-
import { d as TableContextMenuActionEventDetail,
|
|
3
|
-
export { a as TABLE_CELL_BACKGROUND_PRESETS } from '../table-overlay-
|
|
2
|
+
import { d as TableContextMenuActionEventDetail, g as TableOverlayActionEventDetail } from '../table-overlay-jjvdARTJ.js';
|
|
3
|
+
export { a as TABLE_CELL_BACKGROUND_PRESETS } from '../table-overlay-jjvdARTJ.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Default Tiptap extension preset for Looma editor.
|
package/editor/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as
|
|
1
|
+
export { A as ActiveCellRect, T as TABLE_CELL_BACKGROUND_OPTIONS, a as TABLE_CELL_BACKGROUND_PRESETS, b as TableCellBackgroundAction, c as TableContextMenuAction, d as TableContextMenuActionEventDetail, e as TableInsertionAction, f as TableOverlayAction, g as TableOverlayActionEventDetail, h as TableOverlayGeometry, d as TableToolbarActionEventDetail, m as measureTableOverlayGeometry, r as resolveTableCellAt } from './table-overlay-jjvdARTJ.js';
|
|
2
2
|
export { InsertTableEventDetail, SlashMenuAnchorRect, SlashMenuHighlightEventDetail, SlashMenuItem, SlashMenuSelectEventDetail } from './ui.js';
|
|
3
3
|
export { ActiveTableUiState, DefaultEditorExtensionsOptions, InsertTableAtRangeOptions, LoomaSlashCommand, LoomaSlashCommandContext, LoomaSlashCommand as LoomaSlashCommandItem, LoomaSlashCommandOptions, LoomaSlashMenuSnapshot, LoomaTable, LoomaTableCell, LoomaTableHeader, LoomaTableKit, TableActionCapabilities, TableCellAlignment, TableCellBackground, createLoomaSlashCommandExtension, getActiveTableCellAlignment, getActiveTableCellBackground, getActiveTableUiState, getDefaultEditorExtensions, getDefaultSlashCommands, getLoomaTableExtensions, handleTableAction, handleTableOverlayAction, insertTableAtRange, normalizeActiveTableColumnWidths, setActiveTableCellAlignment, setActiveTableCellBackground, shouldShowTextFormattingToolbar } from './extensions/index.js';
|
|
4
4
|
import '@tiptap/core';
|