@threadlabs/looma 0.1.9 → 0.1.11
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-F4AYF33M.js} +74 -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
|
+
};
|
|
@@ -5307,6 +5307,10 @@ var TableHeader = Node18.create({
|
|
|
5307
5307
|
// src/extensions/table-formatting.ts
|
|
5308
5308
|
var LoomaTable = Table.configure({
|
|
5309
5309
|
resizable: true,
|
|
5310
|
+
// Tiptap also uses this as its inward coordinate probe. The 5px default can
|
|
5311
|
+
// resolve to the row around an empty minimum-width cell instead of the cell.
|
|
5312
|
+
handleWidth: 3,
|
|
5313
|
+
cellMinWidth: 112,
|
|
5310
5314
|
lastColumnResizable: false
|
|
5311
5315
|
});
|
|
5312
5316
|
function normalizeTableCellAlignment(value) {
|
|
@@ -5470,7 +5474,14 @@ function getDefaultEditorExtensions(options = {}) {
|
|
|
5470
5474
|
|
|
5471
5475
|
// src/extensions/table-commands.ts
|
|
5472
5476
|
import { TextSelection as TextSelection4 } from "@tiptap/pm/state";
|
|
5473
|
-
import {
|
|
5477
|
+
import {
|
|
5478
|
+
addColumn,
|
|
5479
|
+
addRow,
|
|
5480
|
+
CellSelection as CellSelection2,
|
|
5481
|
+
cellAround,
|
|
5482
|
+
deleteCellSelection,
|
|
5483
|
+
TableMap
|
|
5484
|
+
} from "@tiptap/pm/tables";
|
|
5474
5485
|
var NO_TABLE_CAPABILITIES = {
|
|
5475
5486
|
canAddRowBefore: false,
|
|
5476
5487
|
canAddRowAfter: false,
|
|
@@ -5548,6 +5559,14 @@ function handleTableAction(editor, detail) {
|
|
|
5548
5559
|
return editor.chain().focus().deleteColumn().run();
|
|
5549
5560
|
case "delete-table":
|
|
5550
5561
|
return editor.chain().focus().deleteTable().run();
|
|
5562
|
+
case "clear-cells": {
|
|
5563
|
+
if (!(editor.state.selection instanceof CellSelection2)) {
|
|
5564
|
+
const cellPos = findSelectedCellPosition(editor);
|
|
5565
|
+
if (cellPos === null) return false;
|
|
5566
|
+
if (!editor.commands.setCellSelection({ anchorCell: cellPos })) return false;
|
|
5567
|
+
}
|
|
5568
|
+
return deleteCellSelection(editor.state, editor.view.dispatch);
|
|
5569
|
+
}
|
|
5551
5570
|
case "merge-cells":
|
|
5552
5571
|
return editor.chain().focus().mergeCells().run();
|
|
5553
5572
|
case "split-cell":
|
|
@@ -5619,17 +5638,6 @@ function normalizeColumnWidths(widths, availableWidth, minWidth) {
|
|
|
5619
5638
|
);
|
|
5620
5639
|
return distributeWidthDelta(scaled, availableWidth, minWidth);
|
|
5621
5640
|
}
|
|
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
5641
|
function findTable(editor) {
|
|
5634
5642
|
const { $from } = editor.state.selection;
|
|
5635
5643
|
for (let d = $from.depth; d > 0; d--) {
|
|
@@ -5640,6 +5648,26 @@ function findTable(editor) {
|
|
|
5640
5648
|
}
|
|
5641
5649
|
return null;
|
|
5642
5650
|
}
|
|
5651
|
+
function findSelectedCellPosition(editor) {
|
|
5652
|
+
return cellAround(editor.state.selection.$from)?.pos ?? null;
|
|
5653
|
+
}
|
|
5654
|
+
function selectTableAxis(editor, axis, rowIndex, columnIndex) {
|
|
5655
|
+
const tableInfo = findTable(editor);
|
|
5656
|
+
if (!tableInfo) return false;
|
|
5657
|
+
const { pos: tablePos, node: table } = tableInfo;
|
|
5658
|
+
const map = TableMap.get(table);
|
|
5659
|
+
const row = Math.min(Math.max(0, rowIndex), map.height - 1);
|
|
5660
|
+
const column = Math.min(Math.max(0, columnIndex), map.width - 1);
|
|
5661
|
+
const start = axis === "row" ? map.positionAt(row, 0, table) : map.positionAt(0, column, table);
|
|
5662
|
+
const end = axis === "row" ? map.positionAt(row, map.width - 1, table) : map.positionAt(map.height - 1, column, table);
|
|
5663
|
+
const tableStart = tablePos + 1;
|
|
5664
|
+
if (!editor.commands.setCellSelection({
|
|
5665
|
+
anchorCell: tableStart + start,
|
|
5666
|
+
headCell: tableStart + end
|
|
5667
|
+
})) return false;
|
|
5668
|
+
editor.commands.focus();
|
|
5669
|
+
return true;
|
|
5670
|
+
}
|
|
5643
5671
|
function insertTableAtRange(editor, range, options = {}) {
|
|
5644
5672
|
const rows = Math.min(10, Math.max(1, options.rows ?? 3));
|
|
5645
5673
|
const cols = Math.min(10, Math.max(1, options.cols ?? 3));
|
|
@@ -5700,45 +5728,57 @@ function normalizeActiveTableColumnWidths(editor, tableElement, minWidth = 25) {
|
|
|
5700
5728
|
function handleTableOverlayAction(editor, detail) {
|
|
5701
5729
|
const tableInfo = findTable(editor);
|
|
5702
5730
|
if (!tableInfo) return false;
|
|
5703
|
-
const { action
|
|
5731
|
+
const { action } = detail;
|
|
5732
|
+
if (action === "select-row" || action === "select-column") {
|
|
5733
|
+
return selectTableAxis(
|
|
5734
|
+
editor,
|
|
5735
|
+
action === "select-row" ? "row" : "column",
|
|
5736
|
+
detail.rowIndex,
|
|
5737
|
+
detail.columnIndex
|
|
5738
|
+
);
|
|
5739
|
+
}
|
|
5740
|
+
if (action === "open-cell-menu") return true;
|
|
5741
|
+
if (!("boundaryIndex" in detail)) return false;
|
|
5742
|
+
const { boundaryIndex } = detail;
|
|
5704
5743
|
const { pos: tablePos, node: table } = tableInfo;
|
|
5705
|
-
const
|
|
5706
|
-
const
|
|
5707
|
-
|
|
5708
|
-
|
|
5744
|
+
const map = TableMap.get(table);
|
|
5745
|
+
const rect = {
|
|
5746
|
+
map,
|
|
5747
|
+
table,
|
|
5748
|
+
tableStart: tablePos + 1,
|
|
5749
|
+
left: 0,
|
|
5750
|
+
top: 0,
|
|
5751
|
+
right: map.width,
|
|
5752
|
+
bottom: map.height
|
|
5753
|
+
};
|
|
5754
|
+
let transaction = editor.state.tr;
|
|
5709
5755
|
switch (action) {
|
|
5710
5756
|
case "add-row-before": {
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
cellPos = getTextPositionInCell(tablePos, table, rowIndex, 0);
|
|
5714
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addRowBefore().run();
|
|
5757
|
+
if (boundaryIndex !== 0) return false;
|
|
5758
|
+
transaction = addRow(transaction, rect, 0);
|
|
5715
5759
|
break;
|
|
5716
5760
|
}
|
|
5717
5761
|
case "add-row-after": {
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
cellPos = getTextPositionInCell(tablePos, table, rowIndex, 0);
|
|
5721
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addRowAfter().run();
|
|
5762
|
+
if (boundaryIndex < 1 || boundaryIndex > map.height) return false;
|
|
5763
|
+
transaction = addRow(transaction, rect, boundaryIndex);
|
|
5722
5764
|
break;
|
|
5723
5765
|
}
|
|
5724
5766
|
case "add-column-before": {
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
cellPos = getTextPositionInCell(tablePos, table, 0, colIndex);
|
|
5728
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addColumnBefore().run();
|
|
5767
|
+
if (boundaryIndex !== 0) return false;
|
|
5768
|
+
transaction = addColumn(transaction, rect, 0);
|
|
5729
5769
|
break;
|
|
5730
5770
|
}
|
|
5731
5771
|
case "add-column-after": {
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
cellPos = getTextPositionInCell(tablePos, table, 0, colIndex);
|
|
5735
|
-
command = () => editor.chain().focus().setTextSelection(cellPos).addColumnAfter().run();
|
|
5772
|
+
if (boundaryIndex < 1 || boundaryIndex > map.width) return false;
|
|
5773
|
+
transaction = addColumn(transaction, rect, boundaryIndex);
|
|
5736
5774
|
break;
|
|
5737
5775
|
}
|
|
5738
5776
|
default:
|
|
5739
5777
|
return false;
|
|
5740
5778
|
}
|
|
5741
|
-
|
|
5779
|
+
editor.view.dispatch(transaction);
|
|
5780
|
+
editor.commands.focus();
|
|
5781
|
+
return true;
|
|
5742
5782
|
}
|
|
5743
5783
|
|
|
5744
5784
|
// 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';
|