Merge branch 'master' into ui-improves
This commit is contained in:
@@ -1,27 +1,87 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import type { Props } from '../types';
|
||||
import { color } from 'styles/constants';
|
||||
import styled from 'styled-components';
|
||||
|
||||
class Image extends Component {
|
||||
props: Props;
|
||||
|
||||
handleChange = (ev: SyntheticInputEvent) => {
|
||||
const alt = ev.target.value;
|
||||
const { editor, node } = this.props;
|
||||
const data = node.data.toObject();
|
||||
const state = editor
|
||||
.getState()
|
||||
.transform()
|
||||
.setNodeByKey(node.key, { data: { ...data, alt } })
|
||||
.apply();
|
||||
|
||||
editor.onChange(state);
|
||||
};
|
||||
|
||||
handleClick = (ev: SyntheticInputEvent) => {
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { attributes, state, node, readOnly } = this.props;
|
||||
const loading = node.data.get('loading');
|
||||
const caption = node.data.get('alt');
|
||||
const src = node.data.get('src');
|
||||
const active = state.isFocused && state.selection.hasEdgeIn(node);
|
||||
const showCaption = !readOnly || caption;
|
||||
|
||||
return (
|
||||
<CenteredImage>
|
||||
<StyledImg
|
||||
{...attributes}
|
||||
src={src}
|
||||
alt={caption}
|
||||
active={active}
|
||||
loading={loading}
|
||||
/>
|
||||
{showCaption &&
|
||||
<Caption
|
||||
type="text"
|
||||
placeholder="Write a caption"
|
||||
onChange={this.handleChange}
|
||||
onClick={this.handleClick}
|
||||
defaultValue={caption}
|
||||
contentEditable={false}
|
||||
disabled={readOnly}
|
||||
tabIndex={-1}
|
||||
/>}
|
||||
</CenteredImage>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const StyledImg = styled.img`
|
||||
box-shadow: ${props => (props.active ? `0 0 0 3px ${color.slate}` : '0')};
|
||||
box-shadow: ${props => (props.active ? `0 0 0 2px ${color.slate}` : '0')};
|
||||
border-radius: ${props => (props.active ? `2px` : '0')};
|
||||
opacity: ${props => (props.loading ? 0.5 : 1)};
|
||||
`;
|
||||
|
||||
export default function Image({ attributes, state, node }: Props) {
|
||||
const loading = node.data.get('loading');
|
||||
const alt = node.data.get('alt');
|
||||
const src = node.data.get('src');
|
||||
const active = state.isFocused && state.selection.hasEdgeIn(node);
|
||||
const CenteredImage = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
return (
|
||||
<StyledImg
|
||||
{...attributes}
|
||||
src={src}
|
||||
alt={alt}
|
||||
active={active}
|
||||
loading={loading}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const Caption = styled.input`
|
||||
border: 0;
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-style: italic;
|
||||
color: ${color.slate};
|
||||
padding: 2px 0;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
|
||||
&::placeholder {
|
||||
color: ${color.slate};
|
||||
}
|
||||
`;
|
||||
|
||||
export default Image;
|
||||
|
||||
@@ -22,6 +22,11 @@ export default function KeyboardShortcuts() {
|
||||
return this.toggleMark(state, 'underlined');
|
||||
case 'd':
|
||||
return this.toggleMark(state, 'deleted');
|
||||
case 'k':
|
||||
return state
|
||||
.transform()
|
||||
.wrapInline({ type: 'link', data: { href: '' } })
|
||||
.apply();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -215,6 +215,19 @@ export default function MarkdownShortcuts() {
|
||||
return this.onBackspace(ev, state);
|
||||
if (endOffset !== startBlock.length) return;
|
||||
|
||||
// Hitting enter while an image is selected should jump caret below and
|
||||
// insert a new paragraph
|
||||
if (startBlock.type === 'image') {
|
||||
ev.preventDefault();
|
||||
return state
|
||||
.transform()
|
||||
.collapseToEnd()
|
||||
.insertBlock('paragraph')
|
||||
.apply();
|
||||
}
|
||||
|
||||
// Hitting enter in a heading or blockquote will split the node at that
|
||||
// point and make the new node a paragraph
|
||||
if (
|
||||
startBlock.type !== 'heading1' &&
|
||||
startBlock.type !== 'heading2' &&
|
||||
@@ -228,7 +241,6 @@ export default function MarkdownShortcuts() {
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
|
||||
return state.transform().splitBlock().setBlock('paragraph').apply();
|
||||
},
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import styled from 'styled-components';
|
||||
import { color } from 'styles/constants';
|
||||
|
||||
const HelpText = styled.p`
|
||||
margin-top: 0;
|
||||
color: ${color.slateDark};
|
||||
`;
|
||||
|
||||
|
||||
3
frontend/components/Key/index.js
Normal file
3
frontend/components/Key/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
// @flow
|
||||
import Key from './key';
|
||||
export default Key;
|
||||
19
frontend/components/Key/key.js
Normal file
19
frontend/components/Key/key.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// @flow
|
||||
import styled from 'styled-components';
|
||||
import { color } from 'styles/constants';
|
||||
|
||||
const Key = styled.kbd`
|
||||
display: inline-block;
|
||||
padding: 4px 6px;
|
||||
font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
line-height: 10px;
|
||||
color: ${color.text};
|
||||
vertical-align: middle;
|
||||
background-color: ${color.smokeLight};
|
||||
border: solid 1px ${color.slateLight};
|
||||
border-bottom-color: ${color.slate};
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 -1px 0 ${color.slate};
|
||||
`;
|
||||
|
||||
export default Key;
|
||||
@@ -69,7 +69,7 @@ type Props = {
|
||||
}
|
||||
|
||||
@keydown('shift+/')
|
||||
goToOpenKeyboardShortcuts() {
|
||||
openKeyboardShortcuts() {
|
||||
this.props.ui.setActiveModal('keyboard-shortcuts');
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ type Props = {
|
||||
const Modal = ({
|
||||
children,
|
||||
isOpen,
|
||||
title = 'Untitled Modal',
|
||||
title = 'Untitled',
|
||||
onRequestClose,
|
||||
...rest
|
||||
}: Props) => {
|
||||
@@ -61,7 +61,8 @@ const StyledModal = styled(ReactModal)`
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
background: white;
|
||||
padding: 15vh 2rem 2rem
|
||||
padding: 13vh 2rem 2rem;
|
||||
outline: none;
|
||||
`;
|
||||
|
||||
const Close = styled.a`
|
||||
|
||||
@@ -1,23 +1,117 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import Key from 'components/Key';
|
||||
import Flex from 'components/Flex';
|
||||
import HelpText from 'components/HelpText';
|
||||
import HtmlContent from 'components/HtmlContent';
|
||||
import flatpages from 'static/flatpages';
|
||||
import { convertToMarkdown } from 'utils/markdown';
|
||||
|
||||
const htmlContent = convertToMarkdown(flatpages.keyboard);
|
||||
|
||||
function KeyboardShortcuts() {
|
||||
return (
|
||||
<Flex column>
|
||||
<HelpText>
|
||||
Atlas is designed to be super fast and easy to use.
|
||||
All of your usual keyboard shortcuts work here.
|
||||
All of your usual keyboard shortcuts work here, and there
|
||||
{"'"}
|
||||
s Markdown too.
|
||||
</HelpText>
|
||||
<HtmlContent dangerouslySetInnerHTML={{ __html: htmlContent }} />
|
||||
|
||||
<h2>Navigation</h2>
|
||||
<List>
|
||||
<Keys><Key>e</Key></Keys>
|
||||
<Label>Edit current document</Label>
|
||||
|
||||
<Keys><Key>m</Key></Keys>
|
||||
<Label>Move current document</Label>
|
||||
|
||||
<Keys><Key>/</Key> or <Key>t</Key></Keys>
|
||||
<Label>Jump to search</Label>
|
||||
|
||||
<Keys><Key>d</Key></Keys>
|
||||
<Label>Jump to dashboard</Label>
|
||||
|
||||
<Keys><Key>⌘</Key> + <Key>/</Key></Keys>
|
||||
<Label>Open this guide</Label>
|
||||
</List>
|
||||
|
||||
<h2>Editor</h2>
|
||||
<List>
|
||||
<Keys><Key>⌘</Key> + <Key>Enter</Key></Keys>
|
||||
<Label>Save and exit document edit mode</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>S</Key></Keys>
|
||||
<Label>Save document and continue editing</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>Esc</Key></Keys>
|
||||
<Label>Cancel editing</Label>
|
||||
|
||||
<Keys><Key>⌘</Key> + <Key>b</Key></Keys>
|
||||
<Label>Bold</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>i</Key></Keys>
|
||||
<Label>Italic</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>u</Key></Keys>
|
||||
<Label>Underline</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>d</Key></Keys>
|
||||
<Label>Strikethrough</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>k</Key></Keys>
|
||||
<Label>Link</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>z</Key></Keys>
|
||||
<Label>Undo</Label>
|
||||
<Keys><Key>⌘</Key> + <Key>Shift</Key> + <Key>z</Key></Keys>
|
||||
<Label>Redo</Label>
|
||||
</List>
|
||||
|
||||
<h2>Markdown</h2>
|
||||
<List>
|
||||
<Keys><Key>#</Key> <Key>Space</Key></Keys>
|
||||
<Label>Large header</Label>
|
||||
<Keys><Key>##</Key> <Key>Space</Key></Keys>
|
||||
<Label>Medium header</Label>
|
||||
<Keys><Key>###</Key> <Key>Space</Key></Keys>
|
||||
<Label>Small header</Label>
|
||||
|
||||
<Keys><Key>1.</Key> <Key>Space</Key></Keys>
|
||||
<Label>Numbered list</Label>
|
||||
<Keys><Key>-</Key> <Key>Space</Key></Keys>
|
||||
<Label>Bulleted list</Label>
|
||||
<Keys><Key>[ ]</Key> <Key>Space</Key></Keys>
|
||||
<Label>Todo list</Label>
|
||||
<Keys><Key>></Key> <Key>Space</Key></Keys>
|
||||
<Label>Blockquote</Label>
|
||||
<Keys><Key>---</Key></Keys>
|
||||
<Label>Horizontal divider</Label>
|
||||
<Keys><Key>{'```'}</Key></Keys>
|
||||
<Label>Code block</Label>
|
||||
|
||||
<Keys>_italic_</Keys>
|
||||
<Label>Italic</Label>
|
||||
<Keys>**bold**</Keys>
|
||||
<Label>Bold</Label>
|
||||
<Keys>~~strikethrough~~</Keys>
|
||||
<Label>Strikethrough</Label>
|
||||
<Keys>{'`code`'}</Keys>
|
||||
<Label>Inline code</Label>
|
||||
</List>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
const List = styled.dl`
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin: 0
|
||||
`;
|
||||
|
||||
const Keys = styled.dt`
|
||||
float: left;
|
||||
width: 25%;
|
||||
padding: 0 0 4px;
|
||||
margin: 0
|
||||
`;
|
||||
|
||||
const Label = styled.dd`
|
||||
float: left;
|
||||
width: 75%;
|
||||
padding: 0 0 4px;
|
||||
margin: 0
|
||||
`;
|
||||
|
||||
export default KeyboardShortcuts;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// @flow
|
||||
import api from './api.md';
|
||||
import keyboard from './keyboard.md';
|
||||
|
||||
export default {
|
||||
api,
|
||||
keyboard,
|
||||
};
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
- `Cmd+Enter` - Save and exit document editor
|
||||
- `Cmd+s` - Save document and continue editing
|
||||
- `Cmd+Esc` - Cancel edit
|
||||
- `/` or `t` - Jump to search
|
||||
- `d` - Jump to dashboard
|
||||
- `c` - Compose within a collection
|
||||
- `e` - Edit document
|
||||
- `m` - Move document
|
||||
- `?` - This guide
|
||||
@@ -137,3 +137,7 @@ hr {
|
||||
.activeDropZone a {
|
||||
color: #FFF !important;
|
||||
}
|
||||
|
||||
.ReactModal__Body--open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user