From c830768b3b72c986ba769c92e3ea56a91ccc43ff Mon Sep 17 00:00:00 2001 From: Chrissi2812 Date: Thu, 6 Dec 2018 18:07:08 +0100 Subject: [PATCH 01/18] Adding Table Support --- examples/Components/App/style.scss | 47 +++ examples/Components/Routes/Table/index.vue | 268 ++++++++++++++++++ examples/Components/Subnavigation/index.vue | 3 + .../assets/images/icons/add_col_after.svg | 1 + .../assets/images/icons/add_col_before.svg | 1 + .../assets/images/icons/add_row_after.svg | 1 + .../assets/images/icons/add_row_before.svg | 1 + .../assets/images/icons/combine_cells.svg | 1 + examples/assets/images/icons/delete_col.svg | 1 + examples/assets/images/icons/delete_row.svg | 1 + examples/assets/images/icons/table.svg | 1 + examples/main.js | 7 + packages/tiptap-extensions/src/index.js | 4 + packages/tiptap-extensions/src/nodes/Table.js | 74 +++++ .../tiptap-extensions/src/nodes/TableCell.js | 14 + .../src/nodes/TableHeader.js | 14 + .../tiptap-extensions/src/nodes/TableNodes.js | 20 ++ .../tiptap-extensions/src/nodes/TableRow.js | 14 + 18 files changed, 473 insertions(+) create mode 100644 examples/Components/Routes/Table/index.vue create mode 100644 examples/assets/images/icons/add_col_after.svg create mode 100644 examples/assets/images/icons/add_col_before.svg create mode 100644 examples/assets/images/icons/add_row_after.svg create mode 100644 examples/assets/images/icons/add_row_before.svg create mode 100644 examples/assets/images/icons/combine_cells.svg create mode 100644 examples/assets/images/icons/delete_col.svg create mode 100644 examples/assets/images/icons/delete_row.svg create mode 100644 examples/assets/images/icons/table.svg create mode 100644 packages/tiptap-extensions/src/nodes/Table.js create mode 100644 packages/tiptap-extensions/src/nodes/TableCell.js create mode 100644 packages/tiptap-extensions/src/nodes/TableHeader.js create mode 100644 packages/tiptap-extensions/src/nodes/TableNodes.js create mode 100644 packages/tiptap-extensions/src/nodes/TableRow.js diff --git a/examples/Components/App/style.scss b/examples/Components/App/style.scss index c700022a..4466a809 100644 --- a/examples/Components/App/style.scss +++ b/examples/Components/App/style.scss @@ -79,6 +79,53 @@ border-radius: 3px; } + table { + border-collapse: collapse; + table-layout: fixed; + width: 100%; + margin: 0; + overflow: hidden; + td, th { + min-width: 1em; + border: 1px solid #ddd; + padding: 3px 5px; + vertical-align: top; + box-sizing: border-box; + position: relative; + p { + margin: 0; + } + } + th { + font-weight: bold; + text-align: left; + } + .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: 0; + width: 4px; + z-index: 20; + background-color: #adf; + pointer-events: none; + } + } + .tableWrapper { + margin: 1em 0; + overflow-x: auto; + } + .resize-cursor { + cursor: ew-resize; + cursor: col-resize; + } + } } diff --git a/examples/Components/Routes/Table/index.vue b/examples/Components/Routes/Table/index.vue new file mode 100644 index 00000000..fafdaca0 --- /dev/null +++ b/examples/Components/Routes/Table/index.vue @@ -0,0 +1,268 @@ + + + diff --git a/examples/Components/Subnavigation/index.vue b/examples/Components/Subnavigation/index.vue index aad69c2e..c9971119 100644 --- a/examples/Components/Subnavigation/index.vue +++ b/examples/Components/Subnavigation/index.vue @@ -21,6 +21,9 @@ Todo List + + Table + Suggestions diff --git a/examples/assets/images/icons/add_col_after.svg b/examples/assets/images/icons/add_col_after.svg new file mode 100644 index 00000000..1c898d60 --- /dev/null +++ b/examples/assets/images/icons/add_col_after.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/add_col_before.svg b/examples/assets/images/icons/add_col_before.svg new file mode 100644 index 00000000..dbb5a6f3 --- /dev/null +++ b/examples/assets/images/icons/add_col_before.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/add_row_after.svg b/examples/assets/images/icons/add_row_after.svg new file mode 100644 index 00000000..670681b0 --- /dev/null +++ b/examples/assets/images/icons/add_row_after.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/add_row_before.svg b/examples/assets/images/icons/add_row_before.svg new file mode 100644 index 00000000..ab400f09 --- /dev/null +++ b/examples/assets/images/icons/add_row_before.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/combine_cells.svg b/examples/assets/images/icons/combine_cells.svg new file mode 100644 index 00000000..f7fc3b9f --- /dev/null +++ b/examples/assets/images/icons/combine_cells.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/delete_col.svg b/examples/assets/images/icons/delete_col.svg new file mode 100644 index 00000000..42745536 --- /dev/null +++ b/examples/assets/images/icons/delete_col.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/delete_row.svg b/examples/assets/images/icons/delete_row.svg new file mode 100644 index 00000000..e384a25f --- /dev/null +++ b/examples/assets/images/icons/delete_row.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/assets/images/icons/table.svg b/examples/assets/images/icons/table.svg new file mode 100644 index 00000000..e7dad46f --- /dev/null +++ b/examples/assets/images/icons/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/main.js b/examples/main.js index fae30d10..80b399a9 100644 --- a/examples/main.js +++ b/examples/main.js @@ -54,6 +54,13 @@ const routes = [ githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/HidingMenuBar', }, }, + { + path: '/table', + component: () => import('Components/Routes/Table'), + meta: { + githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Table', + }, + }, { path: '/todo-list', component: () => import('Components/Routes/TodoList'), diff --git a/packages/tiptap-extensions/src/index.js b/packages/tiptap-extensions/src/index.js index 591157fa..8e20e247 100644 --- a/packages/tiptap-extensions/src/index.js +++ b/packages/tiptap-extensions/src/index.js @@ -8,6 +8,10 @@ export { default as Image } from './nodes/Image' export { default as ListItem } from './nodes/ListItem' export { default as Mention } from './nodes/Mention' export { default as OrderedList } from './nodes/OrderedList' +export { default as Table } from './nodes/Table' +export { default as TableHeader } from './nodes/TableHeader' +export { default as TableCell } from './nodes/TableCell' +export { default as TableRow } from './nodes/TableRow' export { default as TodoItem } from './nodes/TodoItem' export { default as TodoList } from './nodes/TodoList' diff --git a/packages/tiptap-extensions/src/nodes/Table.js b/packages/tiptap-extensions/src/nodes/Table.js new file mode 100644 index 00000000..8da767b2 --- /dev/null +++ b/packages/tiptap-extensions/src/nodes/Table.js @@ -0,0 +1,74 @@ +import { Node } from 'tiptap' +import { + tableEditing, + columnResizing, + goToNextCell, + addColumnBefore, + addColumnAfter, + deleteColumn, + addRowBefore, + addRowAfter, + deleteRow, + deleteTable, + mergeCells, + splitCell, + toggleHeaderColumn, + toggleHeaderRow, + toggleHeaderCell, + setCellAttr, + fixTables, +} from 'prosemirror-tables' +import { createTable } from 'prosemirror-utils' +import TableNodes from './TableNodes' + +export default class Table extends Node { + + get name() { + return 'table' + } + + get schema() { + return TableNodes.table + } + + commands({ schema }) { + return { + createTable: ({ rowsCount, colsCount, withHeaderRow }) => ( + (state, dispatch) => { + const nodes = createTable(schema, rowsCount, colsCount, withHeaderRow) + const tr = state.tr.replaceSelectionWith(nodes).scrollIntoView() + dispatch(tr) + } + ), + addColumnBefore: () => addColumnBefore, + addColumnAfter: () => addColumnAfter, + deleteColumn: () => deleteColumn, + addRowBefore: () => addRowBefore, + addRowAfter: () => addRowAfter, + deleteRow: () => deleteRow, + deleteTable: () => deleteTable, + mergeCells: () => mergeCells, + splitCell: () => splitCell, + toggleHeaderColumn: () => toggleHeaderColumn, + toggleHeaderRow: () => toggleHeaderRow, + toggleHeaderCell: () => toggleHeaderCell, + setCellAttr: () => setCellAttr, + fixTables: () => fixTables, + } + } + + keys() { + return { + Tab: goToNextCell(1), + 'Shift-Tab': goToNextCell(-1), + } + } + + get plugins() { + return [ + columnResizing(), + tableEditing(), + ] + } + +} diff --git a/packages/tiptap-extensions/src/nodes/TableCell.js b/packages/tiptap-extensions/src/nodes/TableCell.js new file mode 100644 index 00000000..b7fb691a --- /dev/null +++ b/packages/tiptap-extensions/src/nodes/TableCell.js @@ -0,0 +1,14 @@ +import { Node } from 'tiptap' +import TableNodes from './TableNodes' + +export default class TableCell extends Node { + + get name() { + return 'table_cell' + } + + get schema() { + return TableNodes.table_cell + } + +} diff --git a/packages/tiptap-extensions/src/nodes/TableHeader.js b/packages/tiptap-extensions/src/nodes/TableHeader.js new file mode 100644 index 00000000..d9bce0c9 --- /dev/null +++ b/packages/tiptap-extensions/src/nodes/TableHeader.js @@ -0,0 +1,14 @@ +import { Node } from 'tiptap' +import TableNodes from './TableNodes' + +export default class TableHeader extends Node { + + get name() { + return 'table_header' + } + + get schema() { + return TableNodes.table_header + } + +} diff --git a/packages/tiptap-extensions/src/nodes/TableNodes.js b/packages/tiptap-extensions/src/nodes/TableNodes.js new file mode 100644 index 00000000..95a492ab --- /dev/null +++ b/packages/tiptap-extensions/src/nodes/TableNodes.js @@ -0,0 +1,20 @@ +import { tableNodes } from 'prosemirror-tables' + +export default tableNodes({ + tableGroup: 'block', + cellContent: 'block+', + cellAttributes: { + background: { + default: null, + getFromDOM(dom) { + return dom.style.backgroundColor || null + }, + setDOMAttr(value, attrs) { + if (value) { + const style = { style: `${(attrs.style || '')}background-color: ${value};` } + Object.assign(attrs, style) + } + }, + }, + }, +}) diff --git a/packages/tiptap-extensions/src/nodes/TableRow.js b/packages/tiptap-extensions/src/nodes/TableRow.js new file mode 100644 index 00000000..40a2d85d --- /dev/null +++ b/packages/tiptap-extensions/src/nodes/TableRow.js @@ -0,0 +1,14 @@ +import { Node } from 'tiptap' +import TableNodes from './TableNodes' + +export default class TableRow extends Node { + + get name() { + return 'table_row' + } + + get schema() { + return TableNodes.table_row + } + +} From d3a51cefd4f1d58360a355abb9420dbabad09f33 Mon Sep 17 00:00:00 2001 From: Chrissi2812 Date: Fri, 7 Dec 2018 10:50:20 +0100 Subject: [PATCH 02/18] added deleteTable to example --- examples/Components/Routes/Table/index.vue | 6 ++++++ examples/assets/images/icons/delete_table.svg | 1 + 2 files changed, 7 insertions(+) create mode 100644 examples/assets/images/icons/delete_table.svg diff --git a/examples/Components/Routes/Table/index.vue b/examples/Components/Routes/Table/index.vue index fafdaca0..a8e19691 100644 --- a/examples/Components/Routes/Table/index.vue +++ b/examples/Components/Routes/Table/index.vue @@ -129,6 +129,12 @@ + diff --git a/packages/tiptap-extensions/src/nodes/Table.js b/packages/tiptap-extensions/src/nodes/Table.js index 8da767b2..8ddd3cbc 100644 --- a/packages/tiptap-extensions/src/nodes/Table.js +++ b/packages/tiptap-extensions/src/nodes/Table.js @@ -47,6 +47,14 @@ export default class Table extends Node { addRowAfter: () => addRowAfter, deleteRow: () => deleteRow, deleteTable: () => deleteTable, + toggleCellMerge: () => ( + (state, dispatch) => { + if (mergeCells(state, dispatch)) { + return + } + splitCell(state, dispatch) + } + ), mergeCells: () => mergeCells, splitCell: () => splitCell, toggleHeaderColumn: () => toggleHeaderColumn, From 77bed75cfda110f4fcf2475767fc5990fc520d54 Mon Sep 17 00:00:00 2001 From: Chrissi2812 Date: Fri, 7 Dec 2018 10:54:05 +0100 Subject: [PATCH 04/18] fixed jumping on table resize-handler show --- examples/Components/App/style.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Components/App/style.scss b/examples/Components/App/style.scss index 4466a809..8a877b66 100644 --- a/examples/Components/App/style.scss +++ b/examples/Components/App/style.scss @@ -92,8 +92,8 @@ vertical-align: top; box-sizing: border-box; position: relative; - p { - margin: 0; + > * { + margin-bottom: 0; } } th { From 96b583d94b5c338a7b19142877b169da6c5cdb01 Mon Sep 17 00:00:00 2001 From: Chrissi2812 Date: Fri, 7 Dec 2018 10:55:04 +0100 Subject: [PATCH 05/18] moved history buttons to start of menubar --- examples/Components/Routes/Table/index.vue | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/Components/Routes/Table/index.vue b/examples/Components/Routes/Table/index.vue index 6a4af9f6..2f00fd35 100644 --- a/examples/Components/Routes/Table/index.vue +++ b/examples/Components/Routes/Table/index.vue @@ -3,6 +3,20 @@