-
-
Notifications
You must be signed in to change notification settings - Fork 721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Table actions #68
Table actions #68
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React from 'react'; | ||
import { Editor } from 'slate'; | ||
import { useSlate } from 'slate-react'; | ||
import { ToolbarButton, ToolbarButtonProps } from '../../../common/components'; | ||
import { isSelectionInTable } from '../queries'; | ||
|
||
export interface ToolbarTableProps extends ToolbarButtonProps { | ||
action: (editor: Editor) => void; | ||
} | ||
|
||
export const ToolbarTable = (props: ToolbarTableProps) => { | ||
const editor = useSlate(); | ||
const isTableActive = isSelectionInTable(editor); | ||
|
||
return ( | ||
<ToolbarButton | ||
{...props} | ||
active={isTableActive} | ||
onMouseDown={(event: Event) => { | ||
event.preventDefault(); | ||
props.action(editor); | ||
}} | ||
/> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './ToolbarTable'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
export * from './components'; | ||
export * from './deserializeTable'; | ||
export * from './queries'; | ||
export * from './renderElementTable'; | ||
export * from './TablePlugin'; | ||
export * from './types'; | ||
export * from './transforms'; | ||
export * from './withTable'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './isSelectionInTable'; | ||
export * from './isTable'; | ||
export * from './isTableCell'; | ||
export * from './isTableRow'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { Editor } from 'slate'; | ||
import { isBlockActive } from '../../queries'; | ||
import { TableType } from '../types'; | ||
|
||
export const isSelectionInTable = (editor: Editor): boolean => | ||
isBlockActive(editor, TableType.TABLE); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { Node } from 'slate'; | ||
import { TableType } from '../types'; | ||
|
||
export const isTable = (n: Node) => n.type === TableType.TABLE; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { Node } from 'slate'; | ||
import { TableType } from '../types'; | ||
|
||
export const isTableCell = (n: Node) => n.type === TableType.CELL; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { Node } from 'slate'; | ||
import { TableType } from '../types'; | ||
|
||
export const isTableRow = (n: Node) => n.type === TableType.ROW; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Editor, Path, Transforms } from 'slate'; | ||
import { isSelectionInTable, isTable, isTableCell } from '../queries'; | ||
import { emptyCell } from '../types'; | ||
|
||
export const addColumn = (editor: Editor) => { | ||
if (isSelectionInTable(editor)) { | ||
const currentCellItem = Editor.above(editor, { | ||
match: isTableCell, | ||
}); | ||
const currentTableItem = Editor.above(editor, { | ||
match: isTable, | ||
}); | ||
if (currentCellItem && currentTableItem) { | ||
const nextCellPath = Path.next(currentCellItem[1]); | ||
const newCellPath = nextCellPath.slice(); | ||
const replacePathPos = newCellPath.length - 2; | ||
const currentRowIdx = nextCellPath[replacePathPos]; | ||
|
||
currentTableItem[0].children.forEach((row, rowIdx) => { | ||
newCellPath[replacePathPos] = rowIdx; | ||
|
||
Transforms.insertNodes(editor, emptyCell(), { | ||
at: newCellPath, | ||
select: rowIdx === currentRowIdx, | ||
}); | ||
}); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Editor, Path, Transforms } from 'slate'; | ||
import { isSelectionInTable, isTableRow } from '../queries'; | ||
import { emptyRow } from '../types'; | ||
|
||
export const addRow = (editor: Editor) => { | ||
if (isSelectionInTable(editor)) { | ||
const currentRowItem = Editor.above(editor, { | ||
match: isTableRow, | ||
}); | ||
if (currentRowItem) { | ||
const [currentRowElem, currentRowPath] = currentRowItem; | ||
Transforms.insertNodes(editor, emptyRow(currentRowElem.children.length), { | ||
at: Path.next(currentRowPath), | ||
select: true, | ||
}); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Editor, Transforms } from 'slate'; | ||
import { | ||
isSelectionInTable, | ||
isTable, | ||
isTableCell, | ||
isTableRow, | ||
} from '../queries'; | ||
|
||
export const deleteColumn = (editor: Editor) => { | ||
if (isSelectionInTable(editor)) { | ||
const currentCellItem = Editor.above(editor, { | ||
match: isTableCell, | ||
}); | ||
const currentRowItem = Editor.above(editor, { | ||
match: isTableRow, | ||
}); | ||
const currentTableItem = Editor.above(editor, { | ||
match: isTable, | ||
}); | ||
if ( | ||
currentCellItem && | ||
currentRowItem && | ||
currentTableItem && | ||
// Cannot delete the last cell | ||
currentRowItem[0].children.length > 1 | ||
) { | ||
const currentCellPath = currentCellItem[1]; | ||
const pathToDelete = currentCellPath.slice(); | ||
const replacePathPos = pathToDelete.length - 2; | ||
|
||
currentTableItem[0].children.forEach((row, rowIdx) => { | ||
pathToDelete[replacePathPos] = rowIdx; | ||
|
||
Transforms.removeNodes(editor, { | ||
at: pathToDelete, | ||
}); | ||
}); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Editor, Transforms } from 'slate'; | ||
import { isSelectionInTable, isTable, isTableRow } from '../queries'; | ||
|
||
export const deleteRow = (editor: Editor) => { | ||
if (isSelectionInTable(editor)) { | ||
const currentTableItem = Editor.above(editor, { | ||
match: isTable, | ||
}); | ||
const currentRowItem = Editor.above(editor, { | ||
match: isTableRow, | ||
}); | ||
if ( | ||
currentRowItem && | ||
currentTableItem && | ||
// Cannot delete the last row | ||
currentTableItem[0].children.length > 1 | ||
) { | ||
Transforms.removeNodes(editor, { | ||
at: currentRowItem[1], | ||
}); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Editor, Transforms } from 'slate'; | ||
import { isSelectionInTable, isTable } from '../queries'; | ||
|
||
export const deleteTable = (editor: Editor) => { | ||
if (isSelectionInTable(editor)) { | ||
const tableItem = Editor.above(editor, { | ||
match: isTable, | ||
}); | ||
if (tableItem) { | ||
Transforms.removeNodes(editor, { | ||
at: tableItem[1], | ||
}); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export * from './addColumn'; | ||
export * from './addRow'; | ||
export * from './deleteColumn'; | ||
export * from './deleteRow'; | ||
export * from './deleteTable'; | ||
export * from './insertTable'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Editor, Transforms } from 'slate'; | ||
import { isSelectionInTable } from '../queries'; | ||
import { emptyTable } from '../types'; | ||
|
||
export const insertTable = (editor: Editor) => { | ||
if (!isSelectionInTable(editor)) { | ||
Transforms.insertNodes(editor, emptyTable()); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,12 +3,33 @@ import { boolean } from '@storybook/addon-knobs'; | |
import { createEditor } from 'slate'; | ||
import { withHistory } from 'slate-history'; | ||
import { Slate, withReact } from 'slate-react'; | ||
|
||
import { | ||
BorderAll, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Random choice of icons for the example buttons.. |
||
BorderClear, | ||
BorderBottom, | ||
BorderTop, | ||
BorderLeft, | ||
BorderRight, | ||
FormatBold | ||
} from '@material-ui/icons'; | ||
|
||
import { | ||
BoldPlugin, | ||
EditablePlugins, | ||
renderElementTable, | ||
TablePlugin, | ||
HeadingToolbar, | ||
withTable, | ||
ToolbarMark, | ||
ToolbarTable, | ||
MARK_BOLD, | ||
addColumn, | ||
addRow, | ||
deleteColumn, | ||
deleteRow, | ||
insertTable, | ||
deleteTable, | ||
} from '../../packages/slate-plugins/src'; | ||
import { initialValueTables } from '../config/initialValues'; | ||
|
||
|
@@ -36,6 +57,15 @@ export const Example = () => { | |
value={value} | ||
onChange={newValue => setValue(newValue)} | ||
> | ||
<HeadingToolbar> | ||
<ToolbarMark format={MARK_BOLD} icon={<FormatBold />} /> | ||
<ToolbarTable action={insertTable} icon={<BorderAll />} /> | ||
<ToolbarTable action={deleteTable} icon={<BorderClear />} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the future we can add a floating delete button. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
<ToolbarTable action={addRow} icon={<BorderBottom />} /> | ||
<ToolbarTable action={deleteRow} icon={<BorderTop />} /> | ||
<ToolbarTable action={addColumn} icon={<BorderLeft />} /> | ||
<ToolbarTable action={deleteColumn} icon={<BorderRight />} /> | ||
</HeadingToolbar> | ||
<EditablePlugins plugins={plugins} /> | ||
</Slate> | ||
); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Full table width fits better as long as we can't position other elements next to the table anyway. Maybe this could be configurable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes resizing the table, the columns and the rows would be nice in the future.