Fixed: Checklist items cant be created from shortcuts
Fixed: BlockToolbar not close on unfocus
This commit is contained in:
@@ -84,11 +84,13 @@ export default class BlockInsert extends Component {
|
||||
};
|
||||
|
||||
handleClick = (ev: SyntheticMouseEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
|
||||
this.mouseMovementSinceClick = 0;
|
||||
this.active = false;
|
||||
|
||||
const { editor } = this.props;
|
||||
const type = { type: 'block-toolbar', isVoid: true };
|
||||
|
||||
editor.change(change => {
|
||||
// remove any existing toolbars in the document as a fail safe
|
||||
@@ -101,7 +103,7 @@ export default class BlockInsert extends Component {
|
||||
change
|
||||
.collapseToStartOf(this.closestRootNode)
|
||||
.collapseToEndOfPreviousBlock()
|
||||
.insertBlock(type);
|
||||
.insertBlock({ type: 'block-toolbar', isVoid: true });
|
||||
});
|
||||
};
|
||||
|
||||
@@ -133,7 +135,11 @@ const Trigger = styled.div`
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: ${color.smokeDark};
|
||||
background-color: ${color.slate};
|
||||
|
||||
svg {
|
||||
fill: ${color.white};
|
||||
}
|
||||
}
|
||||
|
||||
${({ active }) =>
|
||||
|
||||
@@ -13,11 +13,8 @@ class Image extends Component {
|
||||
const { editor, node } = this.props;
|
||||
const data = node.data.toObject();
|
||||
|
||||
editor.onChange(
|
||||
editor
|
||||
.getState()
|
||||
.change()
|
||||
.setNodeByKey(node.key, { data: { ...data, alt } })
|
||||
editor.change(change =>
|
||||
change.setNodeByKey(node.key, { data: { ...data, alt } })
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,15 +10,11 @@ export default function ListItem({
|
||||
...props
|
||||
}: SlateNodeProps) {
|
||||
const checked = node.data.get('checked');
|
||||
console.log('ListItem.checked', checked);
|
||||
|
||||
if (checked !== undefined) {
|
||||
return (
|
||||
<TodoItem
|
||||
checked={checked}
|
||||
node={node}
|
||||
attributes={attributes}
|
||||
{...props}
|
||||
>
|
||||
<TodoItem node={node} attributes={attributes} {...props}>
|
||||
{children}
|
||||
</TodoItem>
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { color } from 'shared/styles/constants';
|
||||
import type { SlateNodeProps } from '../types';
|
||||
|
||||
export default class TodoItem extends Component {
|
||||
props: SlateNodeProps & { checked: boolean };
|
||||
props: SlateNodeProps;
|
||||
|
||||
handleChange = (ev: SyntheticInputEvent) => {
|
||||
const checked = ev.target.checked;
|
||||
@@ -16,7 +16,8 @@ export default class TodoItem extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { children, checked, attributes, readOnly } = this.props;
|
||||
const { children, node, attributes, readOnly } = this.props;
|
||||
const checked = node.data.get('checked');
|
||||
|
||||
return (
|
||||
<ListItem checked={checked} {...attributes}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
import React, { Component } from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import keydown from 'react-keydown';
|
||||
import styled from 'styled-components';
|
||||
import getDataTransferFiles from 'utils/getDataTransferFiles';
|
||||
@@ -30,21 +31,30 @@ type Options = {
|
||||
|
||||
class BlockToolbar extends Component {
|
||||
props: Props;
|
||||
bar: HTMLDivElement;
|
||||
file: HTMLInputElement;
|
||||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
const { editor } = this.props;
|
||||
const wasActive = editor.value.selection.hasEdgeIn(this.props.node);
|
||||
const isActive = nextProps.editor.value.selection.hasEdgeIn(nextProps.node);
|
||||
const becameInactive = !isActive && wasActive;
|
||||
|
||||
if (becameInactive) {
|
||||
nextProps.editor.change(change =>
|
||||
change.removeNodeByKey(nextProps.node.key)
|
||||
);
|
||||
}
|
||||
componentDidMount() {
|
||||
window.addEventListener('click', this.handleOutsideMouseClick);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('click', this.handleOutsideMouseClick);
|
||||
}
|
||||
|
||||
handleOutsideMouseClick = (ev: SyntheticMouseEvent) => {
|
||||
const element = findDOMNode(this.bar);
|
||||
|
||||
if (
|
||||
!element ||
|
||||
(ev.target instanceof Node && element.contains(ev.target)) ||
|
||||
(ev.button && ev.button !== 0)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.removeSelf(ev);
|
||||
};
|
||||
|
||||
@keydown('esc')
|
||||
removeSelf(ev: SyntheticEvent) {
|
||||
ev.preventDefault();
|
||||
@@ -59,7 +69,7 @@ class BlockToolbar extends Component {
|
||||
const { editor } = this.props;
|
||||
|
||||
editor.change(change => {
|
||||
splitAndInsertBlock(change, options);
|
||||
change.call(splitAndInsertBlock, options);
|
||||
|
||||
editor.value.document.nodes.forEach(node => {
|
||||
if (node.type === 'block-toolbar') {
|
||||
@@ -130,7 +140,7 @@ class BlockToolbar extends Component {
|
||||
editor.value.isFocused && editor.value.selection.hasEdgeIn(node);
|
||||
|
||||
return (
|
||||
<Bar active={active} {...attributes}>
|
||||
<Bar active={active} {...attributes} ref={ref => (this.bar = ref)}>
|
||||
<HiddenInput
|
||||
type="file"
|
||||
innerRef={ref => (this.file = ref)}
|
||||
|
||||
@@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
||||
import { observable } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Portal } from 'react-portal';
|
||||
import { Editor } from 'slate-react';
|
||||
import { Editor, findDOMNode } from 'slate-react';
|
||||
import { Value } from 'slate';
|
||||
import styled from 'styled-components';
|
||||
import _ from 'lodash';
|
||||
@@ -45,14 +45,14 @@ export default class Toolbar extends Component {
|
||||
const { value } = this.props;
|
||||
|
||||
try {
|
||||
const selectedLinks = value.startBlock
|
||||
const selectedLinks = value.document
|
||||
.getInlinesAtRange(value.selection)
|
||||
.filter(node => node.type === 'link');
|
||||
if (selectedLinks.size) {
|
||||
return selectedLinks.first();
|
||||
}
|
||||
} catch (err) {
|
||||
//
|
||||
// It's okay.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,8 @@ export default class Toolbar extends Component {
|
||||
const firstNode = value.document.nodes.first();
|
||||
if (firstNode === value.startBlock) return;
|
||||
|
||||
// don't display toolbar for code blocks
|
||||
if (value.startBlock.type === 'code') return;
|
||||
// don't display toolbar for code blocks, code-lines inline code.
|
||||
if (value.startBlock.type.match(/code/)) return;
|
||||
|
||||
this.active = true;
|
||||
this.focused = !!link;
|
||||
@@ -84,7 +84,9 @@ export default class Toolbar extends Component {
|
||||
const padding = 16;
|
||||
const selection = window.getSelection();
|
||||
const range = selection.getRangeAt(0);
|
||||
const rect = range.getBoundingClientRect();
|
||||
const rect = link
|
||||
? findDOMNode(link).getBoundingClientRect()
|
||||
: range.getBoundingClientRect();
|
||||
|
||||
if (rect.top === 0 && rect.left === 0) {
|
||||
return;
|
||||
|
||||
@@ -14,7 +14,7 @@ import StrikethroughIcon from 'components/Icon/StrikethroughIcon';
|
||||
class FormattingToolbar extends Component {
|
||||
props: {
|
||||
editor: Editor,
|
||||
onCreateLink: Function,
|
||||
onCreateLink: () => void,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -52,10 +52,10 @@ class FormattingToolbar extends Component {
|
||||
ev.stopPropagation();
|
||||
|
||||
const data = { href: '' };
|
||||
this.props.editor.change(change => {
|
||||
change.wrapInline({ type: 'link', data });
|
||||
this.props.onCreateLink();
|
||||
});
|
||||
this.props.editor.change(change =>
|
||||
change.wrapInline({ type: 'link', data })
|
||||
);
|
||||
this.props.onCreateLink();
|
||||
};
|
||||
|
||||
renderMarkButton = (type: string, IconClass: Function) => {
|
||||
|
||||
Reference in New Issue
Block a user