import type { Meta, StoryObj } from '@storybook/react-vite' import { EditorContent, useEditor } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import { TableKit } from '@tiptap/extension-table' import { BlockId } from './BlockNodes' import { EditorBlockHandle, blockDropCursor } from './EditorBlockHandle' import { EditorTableControls } from './EditorTableControls' import { richTextClassName } from './RichText' /** * A table's controls in an editor. Point at a cell: a handle on its row's left * edge and on its column's top edge, and a ➕ bar under the table and right of * it. */ const meta = { title: 'Primitives/EditorTableControls', // The block handle sits 28px left of the content, and the column ➕ 16px right of the table. parameters: { layout: 'padded' }, } satisfies Meta export default meta type Story = StoryObj const text = (t: string) => [{ type: 'paragraph', content: [{ type: 'text', text: t }] }] const row = (type: 'tableHeader' | 'tableCell', ...cells: string[]) => ({ type: 'tableRow', content: cells.map((c) => ({ type, content: text(c) })) }) const DOCUMENT = { type: 'doc', content: [ { type: 'paragraph', content: [{ type: 'text', text: 'Point at a cell for its row and column handles.' }] }, { type: 'table', content: [row('tableHeader', 'Label', 'Label', 'Label'), row('tableCell', 'Item one', 'Value', 'Value'), row('tableCell', 'Item two', 'Value', 'Value')], }, { type: 'paragraph', content: [{ type: 'text', text: 'The bar under the table adds a row; the one right of it, a column.' }] }, ], } const NO_HEADER = { type: 'doc', content: [ { type: 'paragraph', content: [{ type: 'text', text: 'The first row’s handle turns the header row back on.' }] }, { type: 'table', content: [row('tableCell', 'Item one', 'Value', 'Value'), row('tableCell', 'Item two', 'Value', 'Value')] }, ], } function Editing({ editable, content = DOCUMENT }: { editable: boolean; content?: object }) { const editor = useEditor({ extensions: [StarterKit.configure({ dropcursor: blockDropCursor }), TableKit.configure({ table: { resizable: false } }), BlockId], content, editable, editorProps: { attributes: { class: richTextClassName('default', 'outline-none'), 'aria-label': 'Text' } }, }) return ( ) } /** Point at a cell; press a handle for Insert and Delete, or a ➕ bar to add a row or a column at the end. The first row's handle also has Header row, ticked while it is on. */ export const Default: Story = { render: () => , } /** A table with its header row off: the first row is an ordinary row, and its handle's Header row is not ticked. */ export const NoHeaderRow: Story = { render: () => , } /** An editor that is not editable: no controls. */ export const NotEditable: Story = { render: () => , }