| import { NodeViewWrapper, NodeViewContent } from "@tiptap/react"; |
| import { useCallback } from "react"; |
| import type { NodeViewProps } from "@tiptap/react"; |
|
|
| const GAP_MAP: Record<string, string> = { |
| small: "8px", |
| medium: "16px", |
| large: "24px", |
| }; |
|
|
| const LAYOUT_OPTIONS = ["2-column", "3-column", "4-column"]; |
| const GAP_OPTIONS = ["small", "medium", "large"]; |
|
|
| export function StackView({ node, updateAttributes, editor, getPos }: NodeViewProps) { |
| const layout = (node.attrs.layout as string) || "2-column"; |
| const gap = (node.attrs.gap as string) || "medium"; |
| const colCount = parseInt(layout) || 2; |
|
|
| const handleLayoutChange = useCallback( |
| (e: React.ChangeEvent<HTMLSelectElement>) => { |
| const newLayout = e.target.value; |
| const newColCount = parseInt(newLayout) || 2; |
| const pos = getPos(); |
| if (typeof pos === "number") { |
| editor.commands.setStackColumns(pos, newColCount); |
| } |
| }, |
| [editor, getPos], |
| ); |
|
|
| const handleGapChange = useCallback( |
| (e: React.ChangeEvent<HTMLSelectElement>) => updateAttributes({ gap: e.target.value }), |
| [updateAttributes], |
| ); |
|
|
| return ( |
| <NodeViewWrapper data-component="stack" className="stack-wrapper"> |
| <div className="stack-container"> |
| <div contentEditable={false} className="stack-header"> |
| <span className="stack-header-icon">▥</span> |
| <span className="stack-header-label">Stack</span> |
| <select |
| value={layout} |
| onChange={handleLayoutChange} |
| className="stack-header-select" |
| > |
| {LAYOUT_OPTIONS.map((opt) => ( |
| <option key={opt} value={opt}>{opt}</option> |
| ))} |
| </select> |
| <select |
| value={gap} |
| onChange={handleGapChange} |
| className="stack-header-select" |
| > |
| {GAP_OPTIONS.map((opt) => ( |
| <option key={opt} value={opt}>{opt}</option> |
| ))} |
| </select> |
| </div> |
| |
| <div |
| className="stack-grid" |
| style={{ |
| display: "grid", |
| gridTemplateColumns: `repeat(${colCount}, 1fr)`, |
| gap: GAP_MAP[gap] || "16px", |
| padding: "10px 12px", |
| }} |
| > |
| <NodeViewContent className="stack-columns" /> |
| </div> |
| </div> |
| </NodeViewWrapper> |
| ); |
| } |
|
|