This commit is contained in:
Michael Freno
2025-12-21 00:27:50 -05:00
parent 9007aa00ea
commit 006207b04b

View File

@@ -354,15 +354,12 @@ export default function TextEditor(props: TextEditorProps) {
const instance = editor();
if (!instance) return;
console.log("Inserting table:", rows, "x", cols);
instance
.chain()
.focus()
.insertTable({ rows, cols, withHeaderRow: true })
.run();
console.log("Table inserted, isActive:", instance.isActive("table"));
setShowTableMenu(false);
};
@@ -375,6 +372,120 @@ export default function TextEditor(props: TextEditorProps) {
setShowTableMenu(!showTableMenu());
};
const deleteTableWithConfirmation = () => {
const instance = editor();
if (!instance) return;
const confirmed = window.confirm(
"Are you sure you want to delete this table?"
);
if (!confirmed) return;
instance.chain().focus().deleteTable().run();
};
const deleteRowWithConfirmation = () => {
const instance = editor();
if (!instance) return;
const { state } = instance;
const { selection } = state;
// Find the row node
let rowNode = null;
let depth = 0;
for (let d = selection.$anchor.depth; d > 0; d--) {
const node = selection.$anchor.node(d);
if (node.type.name === "tableRow") {
rowNode = node;
depth = d;
break;
}
}
if (rowNode) {
let hasContent = false;
rowNode.descendants((node) => {
if (node.textContent.trim().length > 0) {
hasContent = true;
return false;
}
});
if (hasContent) {
const confirmed = window.confirm(
"This row contains content. Are you sure you want to delete it?"
);
if (!confirmed) return;
}
}
instance.chain().focus().deleteRow().run();
};
const deleteColumnWithConfirmation = () => {
const instance = editor();
if (!instance) return;
const { state } = instance;
const { selection } = state;
// Get the current cell position
const cellPos = selection.$anchor;
// Find table and column index
let tableNode = null;
let tableDepth = 0;
for (let d = cellPos.depth; d > 0; d--) {
const node = cellPos.node(d);
if (node.type.name === "table") {
tableNode = node;
tableDepth = d;
break;
}
}
if (tableNode) {
// Find which column we're in
let colIndex = 0;
const cellNode = cellPos.node(cellPos.depth);
const rowNode = cellPos.node(cellPos.depth - 1);
rowNode.forEach((node, offset, index) => {
if (
cellPos.pos >= cellPos.start(cellPos.depth - 1) + offset &&
cellPos.pos <
cellPos.start(cellPos.depth - 1) + offset + node.nodeSize
) {
colIndex = index;
}
});
// Check if this column has content
let hasContent = false;
tableNode.descendants((node, pos, parent) => {
if (parent && parent.type.name === "tableRow") {
let currentCol = 0;
parent.forEach((cell, offset, index) => {
if (index === colIndex && cell.textContent.trim().length > 0) {
hasContent = true;
return false;
}
});
}
});
if (hasContent) {
const confirmed = window.confirm(
"This column contains content. Are you sure you want to delete it?"
);
if (!confirmed) return;
}
}
instance.chain().focus().deleteColumn().run();
};
// Close language selector on outside click
createEffect(() => {
if (showLanguageSelector()) {
@@ -600,6 +711,108 @@ export default function TextEditor(props: TextEditorProps) {
>
Code
</button>
{/* Table controls in bubble menu */}
<Show when={instance().isActive("table")}>
<div class="border-crust mx-1 border-l opacity-30"></div>
<button
type="button"
onClick={() =>
instance().chain().focus().addRowBefore().run()
}
class="hover:bg-crust hover:bg-opacity-30 rounded px-2 py-1"
title="Add Row Before"
>
Row
</button>
<button
type="button"
onClick={() =>
instance().chain().focus().addRowAfter().run()
}
class="hover:bg-crust hover:bg-opacity-30 rounded px-2 py-1"
title="Add Row After"
>
Row
</button>
<button
type="button"
onClick={deleteRowWithConfirmation}
class="hover:bg-red hover:bg-opacity-30 rounded px-2 py-1"
title="Delete Row"
>
Row
</button>
<div class="border-crust mx-1 border-l opacity-30"></div>
<button
type="button"
onClick={() =>
instance().chain().focus().addColumnBefore().run()
}
class="hover:bg-crust hover:bg-opacity-30 rounded px-2 py-1"
title="Add Column Before"
>
Col
</button>
<button
type="button"
onClick={() =>
instance().chain().focus().addColumnAfter().run()
}
class="hover:bg-crust hover:bg-opacity-30 rounded px-2 py-1"
title="Add Column After"
>
Col
</button>
<button
type="button"
onClick={deleteColumnWithConfirmation}
class="hover:bg-red hover:bg-opacity-30 rounded px-2 py-1"
title="Delete Column"
>
Col
</button>
<div class="border-crust mx-1 border-l opacity-30"></div>
<button
type="button"
onClick={() =>
instance().chain().focus().mergeCells().run()
}
class="hover:bg-crust hover:bg-opacity-30 rounded px-2 py-1"
title="Merge Cells"
>
</button>
<button
type="button"
onClick={() =>
instance().chain().focus().splitCell().run()
}
class="hover:bg-crust hover:bg-opacity-30 rounded px-2 py-1"
title="Split Cell"
>
</button>
<button
type="button"
onClick={deleteTableWithConfirmation}
class="hover:bg-red hover:bg-opacity-30 rounded px-2 py-1"
title="Delete Table"
>
Table
</button>
</Show>
</div>
</div>
</Show>
@@ -858,9 +1071,7 @@ export default function TextEditor(props: TextEditorProps) {
<button
type="button"
onClick={() =>
instance().chain().focus().deleteColumn().run()
}
onClick={deleteColumnWithConfirmation}
class="hover:bg-red bg-opacity-20 rounded px-2 py-1 text-xs"
title="Delete Column"
>
@@ -891,7 +1102,7 @@ export default function TextEditor(props: TextEditorProps) {
<button
type="button"
onClick={() => instance().chain().focus().deleteRow().run()}
onClick={deleteRowWithConfirmation}
class="hover:bg-red bg-opacity-20 rounded px-2 py-1 text-xs"
title="Delete Row"
>
@@ -902,7 +1113,7 @@ export default function TextEditor(props: TextEditorProps) {
<button
type="button"
onClick={() => instance().chain().focus().deleteTable().run()}
onClick={deleteTableWithConfirmation}
class="hover:bg-red rounded px-2 py-1 text-xs"
title="Delete Table"
>