File size: 3,044 Bytes
561e6f0 76fc93a 561e6f0 76fc93a 561e6f0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | import { Node, mergeAttributes } from "@tiptap/core";
import { ReactNodeViewRenderer } from "@tiptap/react";
import { StackView } from "../StackView";
declare module "@tiptap/core" {
interface Commands<ReturnType> {
stack: {
insertStack: (columns?: number) => ReturnType;
setStackColumns: (pos: number, columns: number) => ReturnType;
};
}
}
export const StackColumn = Node.create({
name: "stackColumn",
group: "stackColumn",
content: "block+",
defining: true,
isolating: true,
parseHTML() {
return [{ tag: 'div[data-type="stack-column"]' }];
},
renderHTML({ HTMLAttributes }) {
return ["div", mergeAttributes(HTMLAttributes, { "data-type": "stack-column" }), 0];
},
});
export const Stack = Node.create({
name: "stack",
group: "block",
content: "stackColumn{2,4}",
defining: true,
isolating: true,
addAttributes() {
return {
layout: { default: "2-column" },
gap: { default: "medium" },
};
},
parseHTML() {
return [{ tag: 'div[data-component="stack"]' }];
},
renderHTML({ HTMLAttributes }) {
return [
"div",
mergeAttributes(HTMLAttributes, { "data-component": "stack" }),
0,
];
},
addCommands() {
return {
insertStack:
(columns = 2) =>
({ commands }) => {
const cols = Array.from({ length: Math.min(Math.max(columns, 2), 4) }, () => ({
type: "stackColumn",
content: [{ type: "paragraph" }],
}));
return commands.insertContent({
type: "stack",
attrs: { layout: `${columns}-column` },
content: cols,
});
},
setStackColumns:
(pos, columns) =>
({ tr, state, dispatch }) => {
const target = Math.min(Math.max(columns, 2), 4);
const node = state.doc.nodeAt(pos);
if (!node || node.type.name !== "stack") return false;
const current = node.childCount;
if (current === target) {
tr.setNodeMarkup(pos, undefined, { ...node.attrs, layout: `${target}-column` });
dispatch?.(tr);
return true;
}
tr.setNodeMarkup(pos, undefined, { ...node.attrs, layout: `${target}-column` });
if (target > current) {
const colType = state.schema.nodes.stackColumn;
const pType = state.schema.nodes.paragraph;
const insertPos = pos + node.nodeSize - 1;
for (let i = 0; i < target - current; i++) {
tr.insert(insertPos + i, colType.create(null, pType.create()));
}
} else {
let removeFrom = pos + 1;
for (let i = 0; i < target; i++) {
removeFrom += node.child(i).nodeSize;
}
const removeTo = pos + node.nodeSize - 1;
tr.delete(removeFrom, removeTo);
}
dispatch?.(tr);
return true;
},
};
},
addNodeView() {
return ReactNodeViewRenderer(StackView);
},
});
|