add react demo for tables

This commit is contained in:
Philipp Kühn
2021-06-25 11:39:27 +02:00
parent 68d64baf99
commit 2ff148d040
6 changed files with 339 additions and 62 deletions

View File

@@ -0,0 +1,160 @@
import React from 'react'
import { useEditor, EditorContent } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import Table from '@tiptap/extension-table'
import TableRow from '@tiptap/extension-table-row'
import TableCell from '@tiptap/extension-table-cell'
import TableHeader from '@tiptap/extension-table-header'
import './styles.scss'
const CustomTableCell = TableCell.extend({
addAttributes() {
return {
// extend the existing attributes …
...this.parent?.(),
// and add a new one …
backgroundColor: {
default: null,
parseHTML: element => {
return {
backgroundColor: element.getAttribute('data-background-color'),
}
},
renderHTML: attributes => {
return {
'data-background-color': attributes.backgroundColor,
style: `background-color: ${attributes.backgroundColor}`,
}
},
},
}
},
})
const MenuBar = ({ editor }) => {
if (!editor) {
return null
}
return (
<>
<button onClick={() => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}>
insertTable
</button>
<button onClick={() => editor.chain().focus().addColumnBefore().run()} disabled={!editor.can().addColumnBefore()}>
addColumnBefore
</button>
<button onClick={() => editor.chain().focus().addColumnAfter().run()} disabled={!editor.can().addColumnAfter()}>
addColumnAfter
</button>
<button onClick={() => editor.chain().focus().deleteColumn().run()} disabled={!editor.can().deleteColumn()}>
deleteColumn
</button>
<button onClick={() => editor.chain().focus().addRowBefore().run()} disabled={!editor.can().addRowBefore()}>
addRowBefore
</button>
<button onClick={() => editor.chain().focus().addRowAfter().run()} disabled={!editor.can().addRowAfter()}>
addRowAfter
</button>
<button onClick={() => editor.chain().focus().deleteRow().run()} disabled={!editor.can().deleteRow()}>
deleteRow
</button>
<button onClick={() => editor.chain().focus().deleteTable().run()} disabled={!editor.can().deleteTable()}>
deleteTable
</button>
<button onClick={() => editor.chain().focus().mergeCells().run()} disabled={!editor.can().mergeCells()}>
mergeCells
</button>
<button onClick={() => editor.chain().focus().splitCell().run()} disabled={!editor.can().splitCell()}>
splitCell
</button>
<button onClick={() => editor.chain().focus().toggleHeaderColumn().run()} disabled={!editor.can().toggleHeaderColumn()}>
toggleHeaderColumn
</button>
<button onClick={() => editor.chain().focus().toggleHeaderRow().run()} disabled={!editor.can().toggleHeaderRow()}>
toggleHeaderRow
</button>
<button onClick={() => editor.chain().focus().toggleHeaderCell().run()} disabled={!editor.can().toggleHeaderCell()}>
toggleHeaderCell
</button>
<button onClick={() => editor.chain().focus().mergeOrSplit().run()} disabled={!editor.can().mergeOrSplit()}>
mergeOrSplit
</button>
<button onClick={() => editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()} disabled={!editor.can().setCellAttribute('backgroundColor', '#FAF594')}>
setCellAttribute
</button>
<button onClick={() => editor.chain().focus().fixTables().run()} disabled={!editor.can().fixTables()}>
fixTables
</button>
<button onClick={() => editor.chain().focus().goToNextCell().run()} disabled={!editor.can().goToNextCell()}>
goToNextCell
</button>
<button onClick={() => editor.chain().focus().goToPreviousCell().run()} disabled={!editor.can().goToPreviousCell()}>
goToPreviousCell
</button>
</>
)
}
export default () => {
const editor = useEditor({
extensions: [
StarterKit,
Table.configure({
resizable: true,
}),
TableRow,
TableHeader,
// Default TableCell
// TableCell,
// Custom TableCell with backgroundColor attribute
CustomTableCell,
],
content: `
<h3>
Have you seen our tables? They are amazing!
</h3>
<ul>
<li>tables with rows, cells and headers (optional)</li>
<li>support for <code>colgroup</code> and <code>rowspan</code></li>
<li>and even resizable columns (optional)</li>
</ul>
<p>
Here is an example:
</p>
<table>
<tbody>
<tr>
<th>Name</th>
<th colspan="3">Description</th>
</tr>
<tr>
<td>Cyndi Lauper</td>
<td>singer</td>
<td>songwriter</td>
<td>actress</td>
</tr>
<tr>
<td>Philipp Kühn</td>
<td>designer</td>
<td>developer</td>
<td>maker</td>
</tr>
<tr>
<td>Hans Pagel</td>
<td>wrote this</td>
<td colspan="2">thats it</td>
</tr>
</tbody>
</table>
`,
})
return (
<div>
<MenuBar editor={editor} />
<EditorContent editor={editor} />
</div>
)
}

View File

@@ -0,0 +1,117 @@
/* Basic editor styles */
.ProseMirror {
margin: 1rem 0;
> * + * {
margin-top: 0.75em;
}
ul,
ol {
padding: 0 1rem;
}
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.1;
}
code {
background-color: rgba(#616161, 0.1);
color: #616161;
}
pre {
background: #0D0D0D;
color: #FFF;
font-family: 'JetBrainsMono', monospace;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
code {
color: inherit;
padding: 0;
background: none;
font-size: 0.8rem;
}
}
img {
max-width: 100%;
height: auto;
}
blockquote {
padding-left: 1rem;
border-left: 2px solid rgba(#0D0D0D, 0.1);
}
hr {
border: none;
border-top: 2px solid rgba(#0D0D0D, 0.1);
margin: 2rem 0;
}
}
/* Table-specific styling */
.ProseMirror {
table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
margin: 0;
overflow: hidden;
td,
th {
min-width: 1em;
border: 2px solid #ced4da;
padding: 3px 5px;
vertical-align: top;
box-sizing: border-box;
position: relative;
> * {
margin-bottom: 0;
}
}
th {
font-weight: bold;
text-align: left;
background-color: #f1f3f5;
}
.selectedCell:after {
z-index: 2;
position: absolute;
content: "";
left: 0; right: 0; top: 0; bottom: 0;
background: rgba(200, 200, 255, 0.4);
pointer-events: none;
}
.column-resize-handle {
position: absolute;
right: -2px;
top: 0;
bottom: -2px;
width: 4px;
background-color: #adf;
pointer-events: none;
}
}
}
.tableWrapper {
overflow-x: auto;
}
.resize-cursor {
cursor: ew-resize;
cursor: col-resize;
}

View File

@@ -0,0 +1,7 @@
context('/demos/Examples/Tables/Vue', () => {
before(() => {
cy.visit('/demos/Examples/Tables/Vue')
})
// TODO: Write tests
})

View File

@@ -3,60 +3,57 @@
<button @click="editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()"> <button @click="editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()">
insertTable insertTable
</button> </button>
<button @click="editor.chain().focus().addColumnBefore().run()" :disabled="!editor.can().addColumnBefore()">
<template> addColumnBefore
<button @click="editor.chain().focus().addColumnBefore().run()" :disabled="!editor.can().addColumnBefore()"> </button>
addColumnBefore <button @click="editor.chain().focus().addColumnAfter().run()" :disabled="!editor.can().addColumnAfter()">
</button> addColumnAfter
<button @click="editor.chain().focus().addColumnAfter().run()" :disabled="!editor.can().addColumnAfter()"> </button>
addColumnAfter <button @click="editor.chain().focus().deleteColumn().run()" :disabled="!editor.can().deleteColumn()">
</button> deleteColumn
<button @click="editor.chain().focus().deleteColumn().run()" :disabled="!editor.can().deleteColumn()"> </button>
deleteColumn <button @click="editor.chain().focus().addRowBefore().run()" :disabled="!editor.can().addRowBefore()">
</button> addRowBefore
<button @click="editor.chain().focus().addRowBefore().run()" :disabled="!editor.can().addRowBefore()"> </button>
addRowBefore <button @click="editor.chain().focus().addRowAfter().run()" :disabled="!editor.can().addRowAfter()">
</button> addRowAfter
<button @click="editor.chain().focus().addRowAfter().run()" :disabled="!editor.can().addRowAfter()"> </button>
addRowAfter <button @click="editor.chain().focus().deleteRow().run()" :disabled="!editor.can().deleteRow()">
</button> deleteRow
<button @click="editor.chain().focus().deleteRow().run()" :disabled="!editor.can().deleteRow()"> </button>
deleteRow <button @click="editor.chain().focus().deleteTable().run()" :disabled="!editor.can().deleteTable()">
</button> deleteTable
<button @click="editor.chain().focus().deleteTable().run()" :disabled="!editor.can().deleteTable()"> </button>
deleteTable <button @click="editor.chain().focus().mergeCells().run()" :disabled="!editor.can().mergeCells()">
</button> mergeCells
<button @click="editor.chain().focus().mergeCells().run()" :disabled="!editor.can().mergeCells()"> </button>
mergeCells <button @click="editor.chain().focus().splitCell().run()" :disabled="!editor.can().splitCell()">
</button> splitCell
<button @click="editor.chain().focus().splitCell().run()" :disabled="!editor.can().splitCell()"> </button>
splitCell <button @click="editor.chain().focus().toggleHeaderColumn().run()" :disabled="!editor.can().toggleHeaderColumn()">
</button> toggleHeaderColumn
<button @click="editor.chain().focus().toggleHeaderColumn().run()" :disabled="!editor.can().toggleHeaderColumn()"> </button>
toggleHeaderColumn <button @click="editor.chain().focus().toggleHeaderRow().run()" :disabled="!editor.can().toggleHeaderRow()">
</button> toggleHeaderRow
<button @click="editor.chain().focus().toggleHeaderRow().run()" :disabled="!editor.can().toggleHeaderRow()"> </button>
toggleHeaderRow <button @click="editor.chain().focus().toggleHeaderCell().run()" :disabled="!editor.can().toggleHeaderCell()">
</button> toggleHeaderCell
<button @click="editor.chain().focus().toggleHeaderCell().run()" :disabled="!editor.can().toggleHeaderCell()"> </button>
toggleHeaderCell <button @click="editor.chain().focus().mergeOrSplit().run()" :disabled="!editor.can().mergeOrSplit()">
</button> mergeOrSplit
<button @click="editor.chain().focus().mergeOrSplit().run()" :disabled="!editor.can().mergeOrSplit()"> </button>
mergeOrSplit <button @click="editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()" :disabled="!editor.can().setCellAttribute('backgroundColor', '#FAF594')">
</button> setCellAttribute
<button @click="editor.chain().focus().setCellAttribute('backgroundColor', '#FAF594').run()" :disabled="!editor.can().setCellAttribute('backgroundColor', '#FAF594')"> </button>
setCellAttribute <button @click="editor.chain().focus().fixTables().run()" :disabled="!editor.can().fixTables()">
</button> fixTables
<button @click="editor.chain().focus().fixTables().run()" :disabled="!editor.can().fixTables()"> </button>
fixTables <button @click="editor.chain().focus().goToNextCell().run()" :disabled="!editor.can().goToNextCell()">
</button> goToNextCell
<button @click="editor.chain().focus().goToNextCell().run()" :disabled="!editor.can().goToNextCell()"> </button>
goToNextCell <button @click="editor.chain().focus().goToPreviousCell().run()" :disabled="!editor.can().goToPreviousCell()">
</button> goToPreviousCell
<button @click="editor.chain().focus().goToPreviousCell().run()" :disabled="!editor.can().goToPreviousCell()"> </button>
goToPreviousCell
</button>
</template>
<editor-content :editor="editor" /> <editor-content :editor="editor" />
</div> </div>

View File

@@ -1,7 +0,0 @@
context('/demos/Examples/Tables', () => {
before(() => {
cy.visit('/demos/Examples/Tables')
})
// TODO: Write tests
})

View File

@@ -4,4 +4,7 @@
Using this extension in a commercial project? [Become a sponsor](/sponsor) to fund its development! Using this extension in a commercial project? [Become a sponsor](/sponsor) to fund its development!
::: :::
<demo name="Examples/Tables" /> <demos :items="{
Vue: 'Examples/Tables/Vue',
React: 'Examples/Tables/React',
}" />