chore: Move to prettier standard double quotes (#1309)

This commit is contained in:
Tom Moor
2020-06-20 13:59:15 -07:00
committed by GitHub
parent 2a3b9e2104
commit f43deb7940
444 changed files with 5988 additions and 5977 deletions

View File

@ -6,7 +6,10 @@
"plugin:import/warnings", "plugin:import/warnings",
"plugin:flowtype/recommended" "plugin:flowtype/recommended"
], ],
"plugins": ["prettier", "flowtype"], "plugins": [
"prettier",
"flowtype"
],
"rules": { "rules": {
"eqeqeq": 2, "eqeqeq": 2,
"no-unused-vars": 2, "no-unused-vars": 2,
@ -18,14 +21,19 @@
"annotationStyle": "line" "annotationStyle": "line"
} }
], ],
"flowtype/space-after-type-colon": [2, "always"], "flowtype/space-after-type-colon": [
"flowtype/space-before-type-colon": [2, "never"], 2,
"always"
],
"flowtype/space-before-type-colon": [
2,
"never"
],
"prettier/prettier": [ "prettier/prettier": [
"error", "error",
{ {
"printWidth": 80, "printWidth": 80,
"trailingComma": "es5", "trailingComma": "es5"
"singleQuote": true
} }
] ]
}, },
@ -38,7 +46,10 @@
}, },
"import/resolver": { "import/resolver": {
"node": { "node": {
"paths": ["app", "."] "paths": [
"app",
"."
]
} }
}, },
"flowtype": { "flowtype": {

View File

@ -1,7 +1,7 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
import breakpoint from 'styled-components-breakpoint'; import breakpoint from "styled-components-breakpoint";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
export const Action = styled(Flex)` export const Action = styled(Flex)`
justify-content: center; justify-content: center;
@ -40,7 +40,7 @@ const Actions = styled(Flex)`
display: none; display: none;
} }
${breakpoint('tablet')` ${breakpoint("tablet")`
left: auto; left: auto;
padding: 24px; padding: 24px;
`}; `};

View File

@ -1,18 +1,18 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
children: React.Node, children: React.Node,
type?: 'info' | 'success' | 'warning' | 'danger' | 'offline', type?: "info" | "success" | "warning" | "danger" | "offline",
}; };
@observer @observer
class Alert extends React.Component<Props> { class Alert extends React.Component<Props> {
defaultProps = { defaultProps = {
type: 'info', type: "info",
}; };
render() { render() {

View File

@ -1,6 +1,6 @@
// @flow // @flow
/* global ga */ /* global ga */
import * as React from 'react'; import * as React from "react";
type Props = { type Props = {
children?: React.Node, children?: React.Node,
@ -20,12 +20,12 @@ export default class Analytics extends React.Component<Props> {
// $FlowIssue // $FlowIssue
ga.l = +new Date(); ga.l = +new Date();
ga('create', process.env.GOOGLE_ANALYTICS_ID, 'auto'); ga("create", process.env.GOOGLE_ANALYTICS_ID, "auto");
ga('set', { dimension1: 'true' }); ga("set", { dimension1: "true" });
ga('send', 'pageview'); ga("send", "pageview");
const script = document.createElement('script'); const script = document.createElement("script");
script.src = 'https://www.google-analytics.com/analytics.js'; script.src = "https://www.google-analytics.com/analytics.js";
script.async = true; script.async = true;
if (document.body) { if (document.body) {

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import AuthStore from 'stores/AuthStore'; import AuthStore from "stores/AuthStore";
import LoadingIndicator from 'components/LoadingIndicator'; import LoadingIndicator from "components/LoadingIndicator";
import { isCustomSubdomain } from 'shared/utils/domains'; import { isCustomSubdomain } from "shared/utils/domains";
type Props = { type Props = {
auth: AuthStore, auth: AuthStore,
@ -38,4 +38,4 @@ const Authenticated = observer(({ auth, children }: Props) => {
return null; return null;
}); });
export default inject('auth')(Authenticated); export default inject("auth")(Authenticated);

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import placeholder from './placeholder.png'; import placeholder from "./placeholder.png";
type Props = { type Props = {
src: string, src: string,

View File

@ -1,14 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import styled from 'styled-components'; import styled from "styled-components";
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now'; import distanceInWordsToNow from "date-fns/distance_in_words_to_now";
import Avatar from 'components/Avatar'; import Avatar from "components/Avatar";
import Tooltip from 'components/Tooltip'; import Tooltip from "components/Tooltip";
import User from 'models/User'; import User from "models/User";
import UserProfile from 'scenes/UserProfile'; import UserProfile from "scenes/UserProfile";
import { EditIcon } from 'outline-icons'; import { EditIcon } from "outline-icons";
type Props = { type Props = {
user: User, user: User,
@ -44,10 +44,10 @@ class AvatarWithPresence extends React.Component<Props> {
<Tooltip <Tooltip
tooltip={ tooltip={
<Centered> <Centered>
<strong>{user.name}</strong> {isCurrentUser && '(You)'} <strong>{user.name}</strong> {isCurrentUser && "(You)"}
<br /> <br />
{isPresent {isPresent
? isEditing ? 'currently editing' : 'currently viewing' ? isEditing ? "currently editing" : "currently viewing"
: `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`} : `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`}
</Centered> </Centered>
} }

View File

@ -1,6 +1,6 @@
// @flow // @flow
import Avatar from './Avatar'; import Avatar from "./Avatar";
import AvatarWithPresence from './AvatarWithPresence'; import AvatarWithPresence from "./AvatarWithPresence";
export { AvatarWithPresence }; export { AvatarWithPresence };
export default Avatar; export default Avatar;

View File

@ -1,5 +1,5 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const Badge = styled.span` const Badge = styled.span`
margin-left: 10px; margin-left: 10px;

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { darken, lighten } from 'polished'; import { darken, lighten } from "polished";
import { ExpandedIcon } from 'outline-icons'; import { ExpandedIcon } from "outline-icons";
const RealButton = styled.button` const RealButton = styled.button`
display: inline-block; display: inline-block;
@ -54,10 +54,10 @@ const RealButton = styled.button`
background: ${props.theme.buttonNeutralBackground}; background: ${props.theme.buttonNeutralBackground};
color: ${props.theme.buttonNeutralText}; color: ${props.theme.buttonNeutralText};
box-shadow: ${ box-shadow: ${
props.borderOnHover ? 'none' : 'rgba(0, 0, 0, 0.07) 0px 1px 2px' props.borderOnHover ? "none" : "rgba(0, 0, 0, 0.07) 0px 1px 2px"
}; };
border: 1px solid ${ border: 1px solid ${
props.borderOnHover ? 'transparent' : props.theme.buttonNeutralBorder props.borderOnHover ? "transparent" : props.theme.buttonNeutralBorder
}; };
svg { svg {
@ -102,7 +102,7 @@ const Label = styled.span`
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
${props => props.hasIcon && 'padding-left: 4px;'}; ${props => props.hasIcon && "padding-left: 4px;"};
`; `;
export const Inner = styled.span` export const Inner = styled.span`
@ -113,8 +113,8 @@ export const Inner = styled.span`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
${props => props.hasIcon && props.hasText && 'padding-left: 4px;'}; ${props => props.hasIcon && props.hasText && "padding-left: 4px;"};
${props => props.hasIcon && !props.hasText && 'padding: 0 4px;'}; ${props => props.hasIcon && !props.hasText && "padding: 0 4px;"};
`; `;
export type Props = { export type Props = {
@ -130,7 +130,7 @@ export type Props = {
}; };
function Button({ function Button({
type = 'text', type = "text",
icon, icon,
children, children,
value, value,

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import breakpoint from 'styled-components-breakpoint'; import breakpoint from "styled-components-breakpoint";
type Props = { type Props = {
children?: React.Node, children?: React.Node,
@ -11,7 +11,7 @@ const Container = styled.div`
width: 100%; width: 100%;
padding: 60px 20px; padding: 60px 20px;
${breakpoint('tablet')` ${breakpoint("tablet")`
padding: 60px; padding: 60px;
`}; `};
`; `;

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import HelpText from 'components/HelpText'; import HelpText from "components/HelpText";
import VisuallyHidden from 'components/VisuallyHidden'; import VisuallyHidden from "components/VisuallyHidden";
export type Props = { export type Props = {
checked?: boolean, checked?: boolean,
@ -15,13 +15,13 @@ export type Props = {
const LabelText = styled.span` const LabelText = styled.span`
font-weight: 500; font-weight: 500;
margin-left: ${props => (props.small ? '6px' : '10px')}; margin-left: ${props => (props.small ? "6px" : "10px")};
${props => (props.small ? `color: ${props.theme.textSecondary}` : '')}; ${props => (props.small ? `color: ${props.theme.textSecondary}` : "")};
`; `;
const Wrapper = styled.div` const Wrapper = styled.div`
padding-bottom: 8px; padding-bottom: 8px;
${props => (props.small ? 'font-size: 14px' : '')}; ${props => (props.small ? "font-size: 14px" : "")};
`; `;
const Label = styled.label` const Label = styled.label`

View File

@ -1,9 +1,9 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const ClickablePadding = styled.div` const ClickablePadding = styled.div`
min-height: 10em; min-height: 10em;
cursor: ${({ onClick }) => (onClick ? 'text' : 'default')}; cursor: ${({ onClick }) => (onClick ? "text" : "default")};
${({ grow }) => grow && `flex-grow: 100;`}; ${({ grow }) => grow && `flex-grow: 100;`};
`; `;

View File

@ -1,14 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import { sortBy, keyBy } from 'lodash'; import { sortBy, keyBy } from "lodash";
import { MAX_AVATAR_DISPLAY } from 'shared/constants'; import { MAX_AVATAR_DISPLAY } from "shared/constants";
import { AvatarWithPresence } from 'components/Avatar'; import { AvatarWithPresence } from "components/Avatar";
import Facepile from 'components/Facepile'; import Facepile from "components/Facepile";
import Document from 'models/Document'; import Document from "models/Document";
import ViewsStore from 'stores/ViewsStore'; import ViewsStore from "stores/ViewsStore";
import DocumentPresenceStore from 'stores/DocumentPresenceStore'; import DocumentPresenceStore from "stores/DocumentPresenceStore";
type Props = { type Props = {
views: ViewsStore, views: ViewsStore,
@ -73,4 +73,4 @@ class Collaborators extends React.Component<Props> {
} }
} }
export default inject('views', 'presence')(Collaborators); export default inject("views", "presence")(Collaborators);

View File

@ -1,11 +1,11 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { inject, observer } from 'mobx-react'; import { inject, observer } from "mobx-react";
import { getLuminance } from 'polished'; import { getLuminance } from "polished";
import { PrivateCollectionIcon, CollectionIcon } from 'outline-icons'; import { PrivateCollectionIcon, CollectionIcon } from "outline-icons";
import Collection from 'models/Collection'; import Collection from "models/Collection";
import { icons } from 'components/IconPicker'; import { icons } from "components/IconPicker";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
type Props = { type Props = {
collection: Collection, collection: Collection,
@ -18,18 +18,18 @@ function ResolvedCollectionIcon({ collection, expanded, size, ui }: Props) {
// If the chosen icon color is very dark then we invert it in dark mode // If the chosen icon color is very dark then we invert it in dark mode
// otherwise it will be impossible to see against the dark background. // otherwise it will be impossible to see against the dark background.
const color = const color =
ui.resolvedTheme === 'dark' ui.resolvedTheme === "dark"
? getLuminance(collection.color) > 0.12 ? getLuminance(collection.color) > 0.12
? collection.color ? collection.color
: 'currentColor' : "currentColor"
: collection.color; : collection.color;
if (collection.icon && collection.icon !== 'collection') { if (collection.icon && collection.icon !== "collection") {
try { try {
const Component = icons[collection.icon].component; const Component = icons[collection.icon].component;
return <Component color={color} size={size} />; return <Component color={color} size={size} />;
} catch (error) { } catch (error) {
console.warn('Failed to render custom icon ' + collection.icon); console.warn("Failed to render custom icon " + collection.icon);
} }
} }
@ -42,4 +42,4 @@ function ResolvedCollectionIcon({ collection, expanded, size, ui }: Props) {
return <CollectionIcon color={color} expanded={expanded} size={size} />; return <CollectionIcon color={color} expanded={expanded} size={size} />;
} }
export default inject('ui')(observer(ResolvedCollectionIcon)); export default inject("ui")(observer(ResolvedCollectionIcon));

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import copy from 'copy-to-clipboard'; import copy from "copy-to-clipboard";
type Props = { type Props = {
text: string, text: string,
@ -19,7 +19,7 @@ class CopyToClipboard extends React.PureComponent<Props> {
if (onCopy) onCopy(); if (onCopy) onCopy();
if (elem && elem.props && typeof elem.props.onClick === 'function') { if (elem && elem.props && typeof elem.props.onClick === "function") {
elem.props.onClick(ev); elem.props.onClick(ev);
} }
}; };

View File

@ -1,20 +1,20 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable, action } from 'mobx'; import { observable, action } from "mobx";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import type { RouterHistory } from 'react-router-dom'; import type { RouterHistory } from "react-router-dom";
import styled from 'styled-components'; import styled from "styled-components";
import { Waypoint } from 'react-waypoint'; import { Waypoint } from "react-waypoint";
import ArrowKeyNavigation from 'boundless-arrow-key-navigation'; import ArrowKeyNavigation from "boundless-arrow-key-navigation";
import { DEFAULT_PAGINATION_LIMIT } from 'stores/BaseStore'; import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
import RevisionsStore from 'stores/RevisionsStore'; import RevisionsStore from "stores/RevisionsStore";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import { ListPlaceholder } from 'components/LoadingPlaceholder'; import { ListPlaceholder } from "components/LoadingPlaceholder";
import Revision from './components/Revision'; import Revision from "./components/Revision";
import { documentHistoryUrl } from 'utils/routeHelpers'; import { documentHistoryUrl } from "utils/routeHelpers";
type Props = { type Props = {
match: Object, match: Object,
@ -146,4 +146,4 @@ const Sidebar = styled(Flex)`
z-index: 1; z-index: 1;
`; `;
export default inject('documents', 'revisions')(DocumentHistory); export default inject("documents", "revisions")(DocumentHistory);

View File

@ -1,18 +1,18 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { NavLink } from 'react-router-dom'; import { NavLink } from "react-router-dom";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import format from 'date-fns/format'; import format from "date-fns/format";
import { MoreIcon } from 'outline-icons'; import { MoreIcon } from "outline-icons";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Time from 'shared/components/Time'; import Time from "shared/components/Time";
import Avatar from 'components/Avatar'; import Avatar from "components/Avatar";
import RevisionMenu from 'menus/RevisionMenu'; import RevisionMenu from "menus/RevisionMenu";
import Document from 'models/Document'; import Document from "models/Document";
import Revision from 'models/Revision'; import Revision from "models/Revision";
import { documentHistoryUrl } from 'utils/routeHelpers'; import { documentHistoryUrl } from "utils/routeHelpers";
type Props = { type Props = {
theme: Object, theme: Object,
@ -32,12 +32,12 @@ class RevisionListItem extends React.Component<Props> {
activeStyle={{ background: theme.primary, color: theme.white }} activeStyle={{ background: theme.primary, color: theme.white }}
> >
<Author> <Author>
<StyledAvatar src={revision.createdBy.avatarUrl} />{' '} <StyledAvatar src={revision.createdBy.avatarUrl} />{" "}
{revision.createdBy.name} {revision.createdBy.name}
</Author> </Author>
<Meta> <Meta>
<Time dateTime={revision.createdAt}> <Time dateTime={revision.createdAt}>
{format(revision.createdAt, 'MMMM Do, YYYY h:mm a')} {format(revision.createdAt, "MMMM Do, YYYY h:mm a")}
</Time> </Time>
</Meta> </Meta>
{showMenu && ( {showMenu && (

View File

@ -1,3 +1,3 @@
// @flow // @flow
import DocumentHistory from './DocumentHistory'; import DocumentHistory from "./DocumentHistory";
export default DocumentHistory; export default DocumentHistory;

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import Document from 'models/Document'; import Document from "models/Document";
import DocumentPreview from 'components/DocumentPreview'; import DocumentPreview from "components/DocumentPreview";
import ArrowKeyNavigation from 'boundless-arrow-key-navigation'; import ArrowKeyNavigation from "boundless-arrow-key-navigation";
type Props = { type Props = {
documents: Document[], documents: Document[],

View File

@ -1,16 +1,16 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { Link } from 'react-router-dom'; import { Link } from "react-router-dom";
import { StarredIcon } from 'outline-icons'; import { StarredIcon } from "outline-icons";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Badge from 'components/Badge'; import Badge from "components/Badge";
import Tooltip from 'components/Tooltip'; import Tooltip from "components/Tooltip";
import Highlight from 'components/Highlight'; import Highlight from "components/Highlight";
import PublishingInfo from 'components/PublishingInfo'; import PublishingInfo from "components/PublishingInfo";
import DocumentMenu from 'menus/DocumentMenu'; import DocumentMenu from "menus/DocumentMenu";
import Document from 'models/Document'; import Document from "models/Document";
type Props = { type Props = {
document: Document, document: Document,
@ -26,7 +26,7 @@ const StyledStar = withTheme(styled(({ solid, theme, ...props }) => (
<StarredIcon color={theme.text} {...props} /> <StarredIcon color={theme.text} {...props} />
))` ))`
flex-shrink: 0; flex-shrink: 0;
opacity: ${props => (props.solid ? '1 !important' : 0)}; opacity: ${props => (props.solid ? "1 !important" : 0)};
transition: all 100ms ease-in-out; transition: all 100ms ease-in-out;
&:hover { &:hover {
@ -82,8 +82,8 @@ const Heading = styled.h3`
margin-bottom: 0.25em; margin-bottom: 0.25em;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
`; `;
const Actions = styled(Flex)` const Actions = styled(Flex)`
@ -124,7 +124,7 @@ class DocumentPreview extends React.Component<Props> {
replaceResultMarks = (tag: string) => { replaceResultMarks = (tag: string) => {
// don't use SEARCH_RESULT_REGEX here as it causes // don't use SEARCH_RESULT_REGEX here as it causes
// an infinite loop to trigger a regex inside it's own callback // an infinite loop to trigger a regex inside it's own callback
return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, '$1'); return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, "$1");
}; };
render() { render() {
@ -152,7 +152,7 @@ class DocumentPreview extends React.Component<Props> {
{...rest} {...rest}
> >
<Heading> <Heading>
<Title text={document.title || 'Untitled'} highlight={highlight} /> <Title text={document.title || "Untitled"} highlight={highlight} />
{!document.isDraft && {!document.isDraft &&
!document.isArchived && ( !document.isArchived && (
<Actions> <Actions>

View File

@ -1,3 +1,3 @@
// @flow // @flow
import DocumentPreview from './DocumentPreview'; import DocumentPreview from "./DocumentPreview";
export default DocumentPreview; export default DocumentPreview;

View File

@ -1,14 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import { withRouter, type RouterHistory } from 'react-router-dom'; import { withRouter, type RouterHistory } from "react-router-dom";
import { createGlobalStyle } from 'styled-components'; import { createGlobalStyle } from "styled-components";
import invariant from 'invariant'; import invariant from "invariant";
import importFile from 'utils/importFile'; import importFile from "utils/importFile";
import Dropzone from 'react-dropzone'; import Dropzone from "react-dropzone";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
import LoadingIndicator from 'components/LoadingIndicator'; import LoadingIndicator from "components/LoadingIndicator";
const EMPTY_OBJECT = {}; const EMPTY_OBJECT = {};
let importingLock = false; let importingLock = false;
@ -56,7 +56,7 @@ class DropToImport extends React.Component<Props> {
if (documentId && !collectionId) { if (documentId && !collectionId) {
const document = await this.props.documents.fetch(documentId); const document = await this.props.documents.fetch(documentId);
invariant(document, 'Document not available'); invariant(document, "Document not available");
collectionId = document.collectionId; collectionId = document.collectionId;
} }
@ -110,4 +110,4 @@ class DropToImport extends React.Component<Props> {
} }
} }
export default inject('documents')(withRouter(DropToImport)); export default inject("documents")(withRouter(DropToImport));

View File

@ -1,14 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import invariant from 'invariant'; import invariant from "invariant";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { PortalWithState } from 'react-portal'; import { PortalWithState } from "react-portal";
import { MoreIcon } from 'outline-icons'; import { MoreIcon } from "outline-icons";
import styled from 'styled-components'; import styled from "styled-components";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import { fadeAndScaleIn } from 'shared/styles/animations'; import { fadeAndScaleIn } from "shared/styles/animations";
import NudeButton from 'components/NudeButton'; import NudeButton from "components/NudeButton";
let previousClosePortal; let previousClosePortal;
let counter = 0; let counter = 0;
@ -25,7 +25,7 @@ type Props = {
className?: string, className?: string,
hover?: boolean, hover?: boolean,
style?: Object, style?: Object,
position?: 'left' | 'right' | 'center', position?: "left" | "right" | "center",
}; };
@observer @observer
@ -37,7 +37,7 @@ class DropdownMenu extends React.Component<Props> {
@observable bottom: ?number; @observable bottom: ?number;
@observable right: ?number; @observable right: ?number;
@observable left: ?number; @observable left: ?number;
@observable position: 'left' | 'right' | 'center'; @observable position: "left" | "right" | "center";
@observable fixed: ?boolean; @observable fixed: ?boolean;
@observable bodyRect: ClientRect; @observable bodyRect: ClientRect;
@observable labelRect: ClientRect; @observable labelRect: ClientRect;
@ -51,21 +51,21 @@ class DropdownMenu extends React.Component<Props> {
return (ev: SyntheticMouseEvent<HTMLElement>) => { return (ev: SyntheticMouseEvent<HTMLElement>) => {
ev.preventDefault(); ev.preventDefault();
const currentTarget = ev.currentTarget; const currentTarget = ev.currentTarget;
invariant(document.body, 'why you not here'); invariant(document.body, "why you not here");
if (currentTarget instanceof HTMLDivElement) { if (currentTarget instanceof HTMLDivElement) {
this.bodyRect = document.body.getBoundingClientRect(); this.bodyRect = document.body.getBoundingClientRect();
this.labelRect = currentTarget.getBoundingClientRect(); this.labelRect = currentTarget.getBoundingClientRect();
this.top = this.labelRect.bottom - this.bodyRect.top; this.top = this.labelRect.bottom - this.bodyRect.top;
this.bottom = undefined; this.bottom = undefined;
this.position = this.props.position || 'left'; this.position = this.props.position || "left";
if (currentTarget.parentElement) { if (currentTarget.parentElement) {
const triggerParentStyle = getComputedStyle( const triggerParentStyle = getComputedStyle(
currentTarget.parentElement currentTarget.parentElement
); );
if (triggerParentStyle.position === 'static') { if (triggerParentStyle.position === "static") {
this.fixed = true; this.fixed = true;
this.top = this.labelRect.bottom; this.top = this.labelRect.bottom;
} }
@ -84,10 +84,10 @@ class DropdownMenu extends React.Component<Props> {
}; };
initPosition() { initPosition() {
if (this.position === 'left') { if (this.position === "left") {
this.right = this.right =
this.bodyRect.width - this.labelRect.left - this.labelRect.width; this.bodyRect.width - this.labelRect.left - this.labelRect.width;
} else if (this.position === 'center') { } else if (this.position === "center") {
this.left = this.labelRect.left + this.labelRect.width / 2; this.left = this.labelRect.left + this.labelRect.width / 2;
} else { } else {
this.left = this.labelRect.left; this.left = this.labelRect.left;
@ -95,7 +95,7 @@ class DropdownMenu extends React.Component<Props> {
} }
onOpen = () => { onOpen = () => {
if (typeof this.props.onOpen === 'function') { if (typeof this.props.onOpen === "function") {
this.props.onOpen(); this.props.onOpen();
} }
this.fitOnTheScreen(); this.fitOnTheScreen();
@ -114,18 +114,18 @@ class DropdownMenu extends React.Component<Props> {
this.bottom = undefined; this.bottom = undefined;
} }
if (this.position === 'left' || this.position === 'right') { if (this.position === "left" || this.position === "right") {
const totalWidth = const totalWidth =
Math.sign(this.position === 'left' ? -1 : 1) * el.offsetLeft + Math.sign(this.position === "left" ? -1 : 1) * el.offsetLeft +
el.scrollWidth; el.scrollWidth;
const isVisible = totalWidth < window.innerWidth; const isVisible = totalWidth < window.innerWidth;
if (!isVisible) { if (!isVisible) {
if (this.position === 'right') { if (this.position === "right") {
this.position = 'left'; this.position = "left";
this.left = undefined; this.left = undefined;
} else if (this.position === 'left') { } else if (this.position === "left") {
this.position = 'right'; this.position = "right";
this.right = undefined; this.right = undefined;
} }
} }
@ -177,7 +177,7 @@ class DropdownMenu extends React.Component<Props> {
<NudeButton <NudeButton
id={`${this.id}button`} id={`${this.id}button`}
aria-haspopup="true" aria-haspopup="true"
aria-expanded={isOpen ? 'true' : 'false'} aria-expanded={isOpen ? "true" : "false"}
aria-controls={this.id} aria-controls={this.id}
> >
<MoreIcon /> <MoreIcon />
@ -201,7 +201,7 @@ class DropdownMenu extends React.Component<Props> {
hover ? this.closeAfterTimeout(closePortal) : undefined hover ? this.closeAfterTimeout(closePortal) : undefined
} }
onClick={ onClick={
typeof children === 'function' typeof children === "function"
? undefined ? undefined
: ev => { : ev => {
ev.stopPropagation(); ev.stopPropagation();
@ -213,7 +213,7 @@ class DropdownMenu extends React.Component<Props> {
aria-labelledby={`${this.id}button`} aria-labelledby={`${this.id}button`}
role="menu" role="menu"
> >
{typeof children === 'function' {typeof children === "function"
? children({ closePortal }) ? children({ closePortal })
: children} : children}
</Menu> </Menu>
@ -228,35 +228,35 @@ class DropdownMenu extends React.Component<Props> {
} }
const Label = styled(Flex).attrs({ const Label = styled(Flex).attrs({
justify: 'center', justify: "center",
align: 'center', align: "center",
})` })`
z-index: 1000; z-index: 1000;
cursor: pointer; cursor: pointer;
`; `;
const Position = styled.div` const Position = styled.div`
position: ${({ fixed }) => (fixed ? 'fixed' : 'absolute')}; position: ${({ fixed }) => (fixed ? "fixed" : "absolute")};
display: flex; display: flex;
${({ left }) => (left !== undefined ? `left: ${left}px` : '')}; ${({ left }) => (left !== undefined ? `left: ${left}px` : "")};
${({ right }) => (right !== undefined ? `right: ${right}px` : '')}; ${({ right }) => (right !== undefined ? `right: ${right}px` : "")};
${({ top }) => (top !== undefined ? `top: ${top}px` : '')}; ${({ top }) => (top !== undefined ? `top: ${top}px` : "")};
${({ bottom }) => (bottom !== undefined ? `bottom: ${bottom}px` : '')}; ${({ bottom }) => (bottom !== undefined ? `bottom: ${bottom}px` : "")};
max-height: 75%; max-height: 75%;
z-index: 1000; z-index: 1000;
transform: ${props => transform: ${props =>
props.position === 'center' ? 'translateX(-50%)' : 'initial'}; props.position === "center" ? "translateX(-50%)" : "initial"};
pointer-events: none; pointer-events: none;
`; `;
const Menu = styled.div` const Menu = styled.div`
animation: ${fadeAndScaleIn} 200ms ease; animation: ${fadeAndScaleIn} 200ms ease;
transform-origin: ${props => (props.left !== undefined ? '25%' : '75%')} 0; transform-origin: ${props => (props.left !== undefined ? "25%" : "75%")} 0;
background: ${props => props.theme.menuBackground}; background: ${props => props.theme.menuBackground};
${props => ${props =>
props.theme.menuBorder props.theme.menuBorder
? `border: 1px solid ${props.theme.menuBorder}` ? `border: 1px solid ${props.theme.menuBorder}`
: ''}; : ""};
border-radius: 2px; border-radius: 2px;
padding: 0.5em 0; padding: 0.5em 0;
min-width: 180px; min-width: 180px;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { CheckmarkIcon } from 'outline-icons'; import { CheckmarkIcon } from "outline-icons";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
onClick?: (SyntheticEvent<>) => void | Promise<void>, onClick?: (SyntheticEvent<>) => void | Promise<void>,
@ -28,7 +28,7 @@ const DropdownMenuItem = ({
{selected !== undefined && ( {selected !== undefined && (
<React.Fragment> <React.Fragment>
<CheckmarkIcon <CheckmarkIcon
color={selected === false ? 'transparent' : undefined} color={selected === false ? "transparent" : undefined}
/>&nbsp; />&nbsp;
</React.Fragment> </React.Fragment>
)} )}
@ -57,12 +57,12 @@ const MenuItem = styled.a`
} }
svg { svg {
opacity: ${props => (props.disabled ? '.5' : 1)}; opacity: ${props => (props.disabled ? ".5" : 1)};
} }
${props => ${props =>
props.disabled props.disabled
? 'pointer-events: none;' ? "pointer-events: none;"
: ` : `
&:hover { &:hover {

View File

@ -1,3 +1,3 @@
// @flow // @flow
export { default as DropdownMenu } from './DropdownMenu'; export { default as DropdownMenu } from "./DropdownMenu";
export { default as DropdownMenuItem } from './DropdownMenuItem'; export { default as DropdownMenuItem } from "./DropdownMenuItem";

View File

@ -1,16 +1,16 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { withRouter, type RouterHistory } from 'react-router-dom'; import { withRouter, type RouterHistory } from "react-router-dom";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { lighten } from 'polished'; import { lighten } from "polished";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import RichMarkdownEditor from 'rich-markdown-editor'; import RichMarkdownEditor from "rich-markdown-editor";
import { uploadFile } from 'utils/uploadFile'; import { uploadFile } from "utils/uploadFile";
import isInternalUrl from 'utils/isInternalUrl'; import isInternalUrl from "utils/isInternalUrl";
import Tooltip from 'components/Tooltip'; import Tooltip from "components/Tooltip";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
import embeds from '../../embeds'; import embeds from "../../embeds";
const EMPTY_ARRAY = []; const EMPTY_ARRAY = [];
@ -36,7 +36,7 @@ class Editor extends React.Component<Props> {
onClickLink = (href: string) => { onClickLink = (href: string) => {
// on page hash // on page hash
if (href[0] === '#') { if (href[0] === "#") {
window.location.href = href; window.location.href = href;
return; return;
} }
@ -46,7 +46,7 @@ class Editor extends React.Component<Props> {
let navigateTo = href; let navigateTo = href;
// probably absolute // probably absolute
if (href[0] !== '/') { if (href[0] !== "/") {
try { try {
const url = new URL(href); const url = new URL(href);
navigateTo = url.pathname + url.hash; navigateTo = url.pathname + url.hash;
@ -57,7 +57,7 @@ class Editor extends React.Component<Props> {
this.props.history.push(navigateTo); this.props.history.push(navigateTo);
} else { } else {
window.open(href, '_blank'); window.open(href, "_blank");
} }
}; };

View File

@ -1,3 +1,3 @@
// @flow // @flow
import Editor from './Editor'; import Editor from "./Editor";
export default Editor; export default Editor;

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
children: React.Node, children: React.Node,

View File

@ -1,13 +1,13 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { observable } from 'mobx'; import { observable } from "mobx";
import HelpText from 'components/HelpText'; import HelpText from "components/HelpText";
import Button from 'components/Button'; import Button from "components/Button";
import CenteredContent from 'components/CenteredContent'; import CenteredContent from "components/CenteredContent";
import PageTitle from 'components/PageTitle'; import PageTitle from "components/PageTitle";
import { githubIssuesUrl } from '../../shared/utils/routeHelpers'; import { githubIssuesUrl } from "../../shared/utils/routeHelpers";
type Props = { type Props = {
children: React.Node, children: React.Node,
@ -49,12 +49,12 @@ class ErrorBoundary extends React.Component<Props> {
<h1>Something Unexpected Happened</h1> <h1>Something Unexpected Happened</h1>
<HelpText> <HelpText>
Sorry, an unrecoverable error occurred{isReported && Sorry, an unrecoverable error occurred{isReported &&
' our engineers have been notified'}. Please try reloading the " our engineers have been notified"}. Please try reloading the
page, it may have been a temporary glitch. page, it may have been a temporary glitch.
</HelpText> </HelpText>
{this.showDetails && <Pre>{this.error.toString()}</Pre>} {this.showDetails && <Pre>{this.error.toString()}</Pre>}
<p> <p>
<Button onClick={this.handleReload}>Reload</Button>{' '} <Button onClick={this.handleReload}>Reload</Button>{" "}
{this.showDetails ? ( {this.showDetails ? (
<Button onClick={this.handleReportBug} neutral> <Button onClick={this.handleReportBug} neutral>
Report a Bug Report a Bug

View File

@ -1,10 +1,10 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Avatar from 'components/Avatar'; import Avatar from "components/Avatar";
import User from 'models/User'; import User from "models/User";
type Props = { type Props = {
users: User[], users: User[],
@ -73,4 +73,4 @@ const Avatars = styled(Flex)`
cursor: pointer; cursor: pointer;
`; `;
export default inject('views', 'presence')(withTheme(Facepile)); export default inject("views", "presence")(withTheme(Facepile));

View File

@ -1,9 +1,9 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
import { fadeIn } from 'shared/styles/animations'; import { fadeIn } from "shared/styles/animations";
const Fade = styled.span` const Fade = styled.span`
animation: ${fadeIn} ${props => props.timing || '250ms'} ease-in-out; animation: ${fadeIn} ${props => props.timing || "250ms"} ease-in-out;
`; `;
export default Fade; export default Fade;

View File

@ -1,17 +1,17 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import { MAX_AVATAR_DISPLAY } from 'shared/constants'; import { MAX_AVATAR_DISPLAY } from "shared/constants";
import Modal from 'components/Modal'; import Modal from "components/Modal";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Facepile from 'components/Facepile'; import Facepile from "components/Facepile";
import GroupMembers from 'scenes/GroupMembers'; import GroupMembers from "scenes/GroupMembers";
import ListItem from 'components/List/Item'; import ListItem from "components/List/Item";
import Group from 'models/Group'; import Group from "models/Group";
import CollectionGroupMembership from 'models/CollectionGroupMembership'; import CollectionGroupMembership from "models/CollectionGroupMembership";
import GroupMembershipsStore from 'stores/GroupMembershipsStore'; import GroupMembershipsStore from "stores/GroupMembershipsStore";
type Props = { type Props = {
group: Group, group: Group,
@ -53,7 +53,7 @@ class GroupListItem extends React.Component<Props> {
} }
subtitle={ subtitle={
<React.Fragment> <React.Fragment>
{memberCount} member{memberCount === 1 ? '' : 's'} {memberCount} member{memberCount === 1 ? "" : "s"}
</React.Fragment> </React.Fragment>
} }
actions={ actions={
@ -91,4 +91,4 @@ const Title = styled.span`
} }
`; `;
export default inject('groupMemberships')(GroupListItem); export default inject("groupMemberships")(GroupListItem);

View File

@ -1,5 +1,5 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const Heading = styled.h1` const Heading = styled.h1`
display: flex; display: flex;

View File

@ -1,10 +1,10 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const HelpText = styled.p` const HelpText = styled.p`
margin-top: 0; margin-top: 0;
color: ${props => props.theme.textSecondary}; color: ${props => props.theme.textSecondary};
font-size: ${props => (props.small ? '13px' : 'inherit')}; font-size: ${props => (props.small ? "13px" : "inherit")};
`; `;
export default HelpText; export default HelpText;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import replace from 'string-replace-to-array'; import replace from "string-replace-to-array";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
highlight: ?string | RegExp, highlight: ?string | RegExp,
@ -22,8 +22,8 @@ function Highlight({
regex = highlight; regex = highlight;
} else { } else {
regex = new RegExp( regex = new RegExp(
(highlight || '').replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'), (highlight || "").replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"),
caseSensitive ? 'g' : 'gi' caseSensitive ? "g" : "gi"
); );
} }
return ( return (

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { TwitterPicker } from 'react-color'; import { TwitterPicker } from "react-color";
import { import {
CollectionIcon, CollectionIcon,
CoinsIcon, CoinsIcon,
@ -22,99 +22,99 @@ import {
QuestionMarkIcon, QuestionMarkIcon,
SunIcon, SunIcon,
VehicleIcon, VehicleIcon,
} from 'outline-icons'; } from "outline-icons";
import styled from 'styled-components'; import styled from "styled-components";
import { LabelText } from 'components/Input'; import { LabelText } from "components/Input";
import { DropdownMenu } from 'components/DropdownMenu'; import { DropdownMenu } from "components/DropdownMenu";
import NudeButton from 'components/NudeButton'; import NudeButton from "components/NudeButton";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
export const icons = { export const icons = {
collection: { collection: {
component: CollectionIcon, component: CollectionIcon,
keywords: 'collection', keywords: "collection",
}, },
coins: { coins: {
component: CoinsIcon, component: CoinsIcon,
keywords: 'coins money finance sales income revenue cash', keywords: "coins money finance sales income revenue cash",
}, },
academicCap: { academicCap: {
component: AcademicCapIcon, component: AcademicCapIcon,
keywords: 'learn teach lesson guide tutorial onboarding training', keywords: "learn teach lesson guide tutorial onboarding training",
}, },
beaker: { beaker: {
component: BeakerIcon, component: BeakerIcon,
keywords: 'lab research experiment test', keywords: "lab research experiment test",
}, },
buildingBlocks: { buildingBlocks: {
component: BuildingBlocksIcon, component: BuildingBlocksIcon,
keywords: 'app blocks product prototype', keywords: "app blocks product prototype",
}, },
cloud: { cloud: {
component: CloudIcon, component: CloudIcon,
keywords: 'cloud service aws infrastructure', keywords: "cloud service aws infrastructure",
}, },
code: { code: {
component: CodeIcon, component: CodeIcon,
keywords: 'developer api code development engineering programming', keywords: "developer api code development engineering programming",
}, },
eye: { eye: {
component: EyeIcon, component: EyeIcon,
keywords: 'eye view', keywords: "eye view",
}, },
leaf: { leaf: {
component: LeafIcon, component: LeafIcon,
keywords: 'leaf plant outdoors nature ecosystem climate', keywords: "leaf plant outdoors nature ecosystem climate",
}, },
lightbulb: { lightbulb: {
component: LightBulbIcon, component: LightBulbIcon,
keywords: 'lightbulb idea', keywords: "lightbulb idea",
}, },
moon: { moon: {
component: MoonIcon, component: MoonIcon,
keywords: 'night moon dark', keywords: "night moon dark",
}, },
notepad: { notepad: {
component: NotepadIcon, component: NotepadIcon,
keywords: 'journal notepad write notes', keywords: "journal notepad write notes",
}, },
padlock: { padlock: {
component: PadlockIcon, component: PadlockIcon,
keywords: 'padlock private security authentication authorization auth', keywords: "padlock private security authentication authorization auth",
}, },
palette: { palette: {
component: PaletteIcon, component: PaletteIcon,
keywords: 'design palette art brand', keywords: "design palette art brand",
}, },
pencil: { pencil: {
component: EditIcon, component: EditIcon,
keywords: 'copy writing post blog', keywords: "copy writing post blog",
}, },
question: { question: {
component: QuestionMarkIcon, component: QuestionMarkIcon,
keywords: 'question help support faq', keywords: "question help support faq",
}, },
sun: { sun: {
component: SunIcon, component: SunIcon,
keywords: 'day sun weather', keywords: "day sun weather",
}, },
vehicle: { vehicle: {
component: VehicleIcon, component: VehicleIcon,
keywords: 'truck car travel transport', keywords: "truck car travel transport",
}, },
}; };
const colors = [ const colors = [
'#4E5C6E', "#4E5C6E",
'#0366d6', "#0366d6",
'#7F6BFF', "#7F6BFF",
'#E76F51', "#E76F51",
'#FC2D2D', "#FC2D2D",
'#FFBE0B', "#FFBE0B",
'#2A9D8F', "#2A9D8F",
'#00D084', "#00D084",
'#EE84F0', "#EE84F0",
'#2F362F', "#2F362F",
]; ];
type Props = { type Props = {
@ -134,11 +134,11 @@ class IconPicker extends React.Component<Props> {
node: ?HTMLElement; node: ?HTMLElement;
componentDidMount() { componentDidMount() {
window.addEventListener('click', this.handleClickOutside); window.addEventListener("click", this.handleClickOutside);
} }
componentWillUnmount() { componentWillUnmount() {
window.removeEventListener('click', this.handleClickOutside); window.removeEventListener("click", this.handleClickOutside);
} }
handleClose = () => { handleClose = () => {
@ -163,7 +163,7 @@ class IconPicker extends React.Component<Props> {
}; };
render() { render() {
const Component = icons[this.props.icon || 'collection'].component; const Component = icons[this.props.icon || "collection"].component;
return ( return (
<Wrapper ref={ref => (this.node = ref)}> <Wrapper ref={ref => (this.node = ref)}>
@ -230,7 +230,7 @@ const ColorPicker = styled(TwitterPicker)`
background: transparent !important; background: transparent !important;
`; `;
const Wrapper = styled('div')` const Wrapper = styled("div")`
display: inline-block; display: inline-block;
position: relative; position: relative;
`; `;

View File

@ -1,15 +1,15 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { observable } from 'mobx'; import { observable } from "mobx";
import styled from 'styled-components'; import styled from "styled-components";
import VisuallyHidden from 'components/VisuallyHidden'; import VisuallyHidden from "components/VisuallyHidden";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
const RealTextarea = styled.textarea` const RealTextarea = styled.textarea`
border: 0; border: 0;
flex: 1; flex: 1;
padding: 8px 12px 8px ${props => (props.hasIcon ? '8px' : '12px')}; padding: 8px 12px 8px ${props => (props.hasIcon ? "8px" : "12px")};
outline: none; outline: none;
background: none; background: none;
color: ${props => props.theme.text}; color: ${props => props.theme.text};
@ -23,7 +23,7 @@ const RealTextarea = styled.textarea`
const RealInput = styled.input` const RealInput = styled.input`
border: 0; border: 0;
flex: 1; flex: 1;
padding: 8px 12px 8px ${props => (props.hasIcon ? '8px' : '12px')}; padding: 8px 12px 8px ${props => (props.hasIcon ? "8px" : "12px")};
outline: none; outline: none;
background: none; background: none;
color: ${props => props.theme.text}; color: ${props => props.theme.text};
@ -40,10 +40,10 @@ const RealInput = styled.input`
`; `;
const Wrapper = styled.div` const Wrapper = styled.div`
flex: ${props => (props.flex ? '1' : '0')}; flex: ${props => (props.flex ? "1" : "0")};
max-width: ${props => (props.short ? '350px' : '100%')}; max-width: ${props => (props.short ? "350px" : "100%")};
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '0')}; min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : "0")};
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : 'initial')}; max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : "initial")};
`; `;
const IconWrapper = styled.span` const IconWrapper = styled.span`
@ -56,13 +56,13 @@ const IconWrapper = styled.span`
export const Outline = styled(Flex)` export const Outline = styled(Flex)`
display: flex; display: flex;
flex: 1; flex: 1;
margin: ${props => (props.margin !== undefined ? props.margin : '0 0 16px')}; margin: ${props => (props.margin !== undefined ? props.margin : "0 0 16px")};
color: inherit; color: inherit;
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
border-color: ${props => border-color: ${props =>
props.hasError props.hasError
? 'red' ? "red"
: props.focused : props.focused
? props.theme.inputBorderFocused ? props.theme.inputBorderFocused
: props.theme.inputBorder}; : props.theme.inputBorder};
@ -118,7 +118,7 @@ class Input extends React.Component<Props> {
render() { render() {
const { const {
type = 'text', type = "text",
icon, icon,
label, label,
margin, margin,
@ -131,7 +131,7 @@ class Input extends React.Component<Props> {
...rest ...rest
} = this.props; } = this.props;
const InputComponent = type === 'textarea' ? RealTextarea : RealInput; const InputComponent = type === "textarea" ? RealTextarea : RealInput;
const wrappedLabel = <LabelText>{label}</LabelText>; const wrappedLabel = <LabelText>{label}</LabelText>;
return ( return (
@ -149,7 +149,7 @@ class Input extends React.Component<Props> {
ref={ref => (this.input = ref)} ref={ref => (this.input = ref)}
onBlur={this.handleBlur} onBlur={this.handleBlur}
onFocus={this.handleFocus} onFocus={this.handleFocus}
type={type === 'textarea' ? undefined : type} type={type === "textarea" ? undefined : type}
hasIcon={!!icon} hasIcon={!!icon}
{...rest} {...rest}
/> />

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import { LabelText, Outline } from 'components/Input'; import { LabelText, Outline } from "components/Input";
type Props = { type Props = {
label: string, label: string,
@ -31,7 +31,7 @@ class InputRich extends React.Component<Props> {
loadEditor = async () => { loadEditor = async () => {
try { try {
const EditorImport = await import('./Editor'); const EditorImport = await import("./Editor");
this.editorComponent = EditorImport.default; this.editorComponent = EditorImport.default;
} catch (err) { } catch (err) {
console.error(err); console.error(err);
@ -64,7 +64,7 @@ class InputRich extends React.Component<Props> {
{...rest} {...rest}
/> />
) : ( ) : (
'Loading…' "Loading…"
)} )}
</StyledOutline> </StyledOutline>
</React.Fragment> </React.Fragment>
@ -74,8 +74,8 @@ class InputRich extends React.Component<Props> {
const StyledOutline = styled(Outline)` const StyledOutline = styled(Outline)`
padding: 8px 12px; padding: 8px 12px;
min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : '0')}; min-height: ${({ minHeight }) => (minHeight ? `${minHeight}px` : "0")};
max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : 'auto')}; max-height: ${({ maxHeight }) => (maxHeight ? `${maxHeight}px` : "auto")};
overflow-y: auto; overflow-y: auto;
> * { > * {

View File

@ -1,13 +1,13 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import keydown from 'react-keydown'; import keydown from "react-keydown";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { withRouter, type RouterHistory } from 'react-router-dom'; import { withRouter, type RouterHistory } from "react-router-dom";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import { SearchIcon } from 'outline-icons'; import { SearchIcon } from "outline-icons";
import { searchUrl } from 'utils/routeHelpers'; import { searchUrl } from "utils/routeHelpers";
import Input from './Input'; import Input from "./Input";
type Props = { type Props = {
history: RouterHistory, history: RouterHistory,
@ -21,7 +21,7 @@ class InputSearch extends React.Component<Props> {
input: ?Input; input: ?Input;
@observable focused: boolean = false; @observable focused: boolean = false;
@keydown('meta+f') @keydown("meta+f")
focus(ev) { focus(ev) {
ev.preventDefault(); ev.preventDefault();
@ -46,7 +46,7 @@ class InputSearch extends React.Component<Props> {
}; };
render() { render() {
const { theme, placeholder = 'Search…' } = this.props; const { theme, placeholder = "Search…" } = this.props;
return ( return (
<InputMaxWidth <InputMaxWidth

View File

@ -1,10 +1,10 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { observable } from 'mobx'; import { observable } from "mobx";
import styled from 'styled-components'; import styled from "styled-components";
import VisuallyHidden from 'components/VisuallyHidden'; import VisuallyHidden from "components/VisuallyHidden";
import { Outline, LabelText } from './Input'; import { Outline, LabelText } from "./Input";
const Select = styled.select` const Select = styled.select`
border: 0; border: 0;

View File

@ -1,10 +1,10 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const Key = styled.kbd` const Key = styled.kbd`
display: inline-block; display: inline-block;
padding: 4px 6px; padding: 4px 6px;
font: 11px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
monospace; monospace;
line-height: 10px; line-height: 10px;
color: ${props => props.theme.almostBlack}; color: ${props => props.theme.almostBlack};

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
label: React.Node | string, label: React.Node | string,

View File

@ -1,32 +1,32 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { Switch, Route, Redirect } from 'react-router-dom'; import { Switch, Route, Redirect } from "react-router-dom";
import { Helmet } from 'react-helmet'; import { Helmet } from "react-helmet";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import breakpoint from 'styled-components-breakpoint'; import breakpoint from "styled-components-breakpoint";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import keydown from 'react-keydown'; import keydown from "react-keydown";
import Analytics from 'components/Analytics'; import Analytics from "components/Analytics";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import { import {
homeUrl, homeUrl,
searchUrl, searchUrl,
matchDocumentSlug as slug, matchDocumentSlug as slug,
} from 'utils/routeHelpers'; } from "utils/routeHelpers";
import { LoadingIndicatorBar } from 'components/LoadingIndicator'; import { LoadingIndicatorBar } from "components/LoadingIndicator";
import { GlobalStyles } from 'components/DropToImport'; import { GlobalStyles } from "components/DropToImport";
import Sidebar from 'components/Sidebar'; import Sidebar from "components/Sidebar";
import SettingsSidebar from 'components/Sidebar/Settings'; import SettingsSidebar from "components/Sidebar/Settings";
import Modals from 'components/Modals'; import Modals from "components/Modals";
import DocumentHistory from 'components/DocumentHistory'; import DocumentHistory from "components/DocumentHistory";
import Modal from 'components/Modal'; import Modal from "components/Modal";
import KeyboardShortcuts from 'scenes/KeyboardShortcuts'; import KeyboardShortcuts from "scenes/KeyboardShortcuts";
import ErrorSuspended from 'scenes/ErrorSuspended'; import ErrorSuspended from "scenes/ErrorSuspended";
import AuthStore from 'stores/AuthStore'; import AuthStore from "stores/AuthStore";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
type Props = { type Props = {
documents: DocumentsStore, documents: DocumentsStore,
@ -62,7 +62,7 @@ class Layout extends React.Component<Props> {
window.document.body.style.background = this.props.theme.background; window.document.body.style.background = this.props.theme.background;
} }
@keydown('shift+/') @keydown("shift+/")
handleOpenKeyboardShortcuts() { handleOpenKeyboardShortcuts() {
if (this.props.ui.editMode) return; if (this.props.ui.editMode) return;
this.keyboardShortcutsOpen = true; this.keyboardShortcutsOpen = true;
@ -72,7 +72,7 @@ class Layout extends React.Component<Props> {
this.keyboardShortcutsOpen = false; this.keyboardShortcutsOpen = false;
}; };
@keydown(['t', '/', 'meta+k']) @keydown(["t", "/", "meta+k"])
goToSearch(ev) { goToSearch(ev) {
if (this.props.ui.editMode) return; if (this.props.ui.editMode) return;
ev.preventDefault(); ev.preventDefault();
@ -80,7 +80,7 @@ class Layout extends React.Component<Props> {
this.redirectTo = searchUrl(); this.redirectTo = searchUrl();
} }
@keydown('d') @keydown("d")
goToDashboard() { goToDashboard() {
if (this.props.ui.editMode) return; if (this.props.ui.editMode) return;
this.redirectTo = homeUrl(); this.redirectTo = homeUrl();
@ -157,9 +157,9 @@ const Content = styled(Flex)`
margin: 0; margin: 0;
} }
${breakpoint('tablet')` ${breakpoint("tablet")`
margin-left: ${props => (props.editMode ? 0 : props.theme.sidebarWidth)}; margin-left: ${props => (props.editMode ? 0 : props.theme.sidebarWidth)};
`}; `};
`; `;
export default inject('auth', 'ui', 'documents')(withTheme(Layout)); export default inject("auth", "ui", "documents")(withTheme(Layout));

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
type Props = { type Props = {
image?: React.Node, image?: React.Node,
@ -16,7 +16,7 @@ const ListItem = ({ image, title, subtitle, actions }: Props) => {
return ( return (
<Wrapper compact={compact}> <Wrapper compact={compact}>
{image && <Image>{image}</Image>} {image && <Image>{image}</Image>}
<Content align={compact ? 'center' : undefined} column={!compact}> <Content align={compact ? "center" : undefined} column={!compact}>
<Heading>{title}</Heading> <Heading>{title}</Heading>
{subtitle && <Subtitle>{subtitle}</Subtitle>} {subtitle && <Subtitle>{subtitle}</Subtitle>}
</Content> </Content>
@ -27,7 +27,7 @@ const ListItem = ({ image, title, subtitle, actions }: Props) => {
const Wrapper = styled.li` const Wrapper = styled.li`
display: flex; display: flex;
padding: ${props => (props.compact ? '8px' : '12px')} 0; padding: ${props => (props.compact ? "8px" : "12px")} 0;
margin: 0; margin: 0;
border-bottom: 1px solid ${props => props.theme.divider}; border-bottom: 1px solid ${props => props.theme.divider};

View File

@ -1,5 +1,5 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const List = styled.ol` const List = styled.ol`
margin: 0; margin: 0;

View File

@ -1,10 +1,10 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { times } from 'lodash'; import { times } from "lodash";
import styled from 'styled-components'; import styled from "styled-components";
import Mask from 'components/Mask'; import Mask from "components/Mask";
import Fade from 'components/Fade'; import Fade from "components/Fade";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
type Props = { type Props = {
count?: number, count?: number,

View File

@ -1,3 +1,3 @@
// @flow // @flow
import List from './List'; import List from "./List";
export default List; export default List;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { inject, observer } from 'mobx-react'; import { inject, observer } from "mobx-react";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
type Props = { type Props = {
ui: UiStore, ui: UiStore,
@ -22,4 +22,4 @@ class LoadingIndicator extends React.Component<Props> {
} }
} }
export default inject('ui')(LoadingIndicator); export default inject("ui")(LoadingIndicator);

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled, { keyframes } from 'styled-components'; import styled, { keyframes } from "styled-components";
const LoadingIndicatorBar = () => { const LoadingIndicatorBar = () => {
return ( return (

View File

@ -1,5 +1,5 @@
// @flow // @flow
import LoadingIndicator from './LoadingIndicator'; import LoadingIndicator from "./LoadingIndicator";
import LoadingIndicatorBar from './LoadingIndicatorBar'; import LoadingIndicatorBar from "./LoadingIndicatorBar";
export default LoadingIndicator; export default LoadingIndicator;
export { LoadingIndicatorBar }; export { LoadingIndicatorBar };

View File

@ -1,10 +1,10 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { times } from 'lodash'; import { times } from "lodash";
import styled from 'styled-components'; import styled from "styled-components";
import Mask from 'components/Mask'; import Mask from "components/Mask";
import Fade from 'components/Fade'; import Fade from "components/Fade";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
type Props = { type Props = {
count?: number, count?: number,

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import Mask from 'components/Mask'; import Mask from "components/Mask";
import Fade from 'components/Fade'; import Fade from "components/Fade";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
export default function LoadingPlaceholder(props: Object) { export default function LoadingPlaceholder(props: Object) {
return ( return (

View File

@ -1,6 +1,6 @@
// @flow // @flow
import LoadingPlaceholder from './LoadingPlaceholder'; import LoadingPlaceholder from "./LoadingPlaceholder";
import ListPlaceholder from './ListPlaceholder'; import ListPlaceholder from "./ListPlaceholder";
export default LoadingPlaceholder; export default LoadingPlaceholder;
export { ListPlaceholder }; export { ListPlaceholder };

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { pulsate } from 'shared/styles/animations'; import { pulsate } from "shared/styles/animations";
import { randomInteger } from 'shared/random'; import { randomInteger } from "shared/random";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
type Props = { type Props = {
header?: boolean, header?: boolean,

View File

@ -1,16 +1,16 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import styled, { createGlobalStyle } from 'styled-components'; import styled, { createGlobalStyle } from "styled-components";
import breakpoint from 'styled-components-breakpoint'; import breakpoint from "styled-components-breakpoint";
import ReactModal from 'react-modal'; import ReactModal from "react-modal";
import { transparentize } from 'polished'; import { transparentize } from "polished";
import { CloseIcon, BackIcon } from 'outline-icons'; import { CloseIcon, BackIcon } from "outline-icons";
import NudeButton from 'components/NudeButton'; import NudeButton from "components/NudeButton";
import { fadeAndScaleIn } from 'shared/styles/animations'; import { fadeAndScaleIn } from "shared/styles/animations";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
ReactModal.setAppElement('#root'); ReactModal.setAppElement("#root");
type Props = { type Props = {
children?: React.Node, children?: React.Node,
@ -26,7 +26,7 @@ const GlobalStyles = createGlobalStyle`
z-index: 100; z-index: 100;
} }
${breakpoint('tablet')` ${breakpoint("tablet")`
.ReactModalPortal + .ReactModalPortal { .ReactModalPortal + .ReactModalPortal {
.ReactModal__Overlay { .ReactModal__Overlay {
margin-left: 12px; margin-left: 12px;
@ -57,7 +57,7 @@ const GlobalStyles = createGlobalStyle`
const Modal = ({ const Modal = ({
children, children,
isOpen, isOpen,
title = 'Untitled', title = "Untitled",
onRequestClose, onRequestClose,
...rest ...rest
}: Props) => { }: Props) => {
@ -114,7 +114,7 @@ const StyledModal = styled(ReactModal)`
padding: 8vh 2rem 2rem; padding: 8vh 2rem 2rem;
outline: none; outline: none;
${breakpoint('tablet')` ${breakpoint("tablet")`
padding-top: 13vh; padding-top: 13vh;
`}; `};
`; `;
@ -141,7 +141,7 @@ const Close = styled(NudeButton)`
opacity: 1; opacity: 1;
} }
${breakpoint('tablet')` ${breakpoint("tablet")`
display: none; display: none;
`}; `};
`; `;
@ -161,7 +161,7 @@ const Back = styled(NudeButton)`
opacity: 1; opacity: 1;
} }
${breakpoint('tablet')` ${breakpoint("tablet")`
display: flex; display: flex;
`}; `};
`; `;

View File

@ -1,14 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import BaseModal from 'components/Modal'; import BaseModal from "components/Modal";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
import CollectionNew from 'scenes/CollectionNew'; import CollectionNew from "scenes/CollectionNew";
import CollectionEdit from 'scenes/CollectionEdit'; import CollectionEdit from "scenes/CollectionEdit";
import CollectionDelete from 'scenes/CollectionDelete'; import CollectionDelete from "scenes/CollectionDelete";
import CollectionExport from 'scenes/CollectionExport'; import CollectionExport from "scenes/CollectionExport";
import DocumentDelete from 'scenes/DocumentDelete'; import DocumentDelete from "scenes/DocumentDelete";
import DocumentShare from 'scenes/DocumentShare'; import DocumentShare from "scenes/DocumentShare";
type Props = { type Props = {
ui: UiStore, ui: UiStore,

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { lighten } from 'polished'; import { lighten } from "polished";
const Button = styled.button` const Button = styled.button`
width: 24px; width: 24px;

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { Helmet } from 'react-helmet'; import { Helmet } from "react-helmet";
type Props = { type Props = {
title: string, title: string,
@ -13,7 +13,7 @@ const PageTitle = ({ title, favicon }: Props) => (
<link <link
rel="shortcut icon" rel="shortcut icon"
type="image/png" type="image/png"
href={favicon || '/favicon-32.png'} href={favicon || "/favicon-32.png"}
sizes="32x32" sizes="32x32"
/> />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import Document from 'models/Document'; import Document from "models/Document";
import DocumentPreview from 'components/DocumentPreview'; import DocumentPreview from "components/DocumentPreview";
import PaginatedList from 'components/PaginatedList'; import PaginatedList from "components/PaginatedList";
type Props = { type Props = {
documents: Document[], documents: Document[],

View File

@ -1,12 +1,12 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable, action } from 'mobx'; import { observable, action } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { Waypoint } from 'react-waypoint'; import { Waypoint } from "react-waypoint";
import ArrowKeyNavigation from 'boundless-arrow-key-navigation'; import ArrowKeyNavigation from "boundless-arrow-key-navigation";
import { DEFAULT_PAGINATION_LIMIT } from 'stores/BaseStore'; import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
import { ListPlaceholder } from 'components/LoadingPlaceholder'; import { ListPlaceholder } from "components/LoadingPlaceholder";
type Props = { type Props = {
fetch?: (options: ?Object) => Promise<void>, fetch?: (options: ?Object) => Promise<void>,

View File

@ -1,21 +1,21 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import styled from 'styled-components'; import styled from "styled-components";
import { GoToIcon } from 'outline-icons'; import { GoToIcon } from "outline-icons";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Document from 'models/Document'; import Document from "models/Document";
import Collection from 'models/Collection'; import Collection from "models/Collection";
import type { DocumentPath } from 'stores/CollectionsStore'; import type { DocumentPath } from "stores/CollectionsStore";
import CollectionIcon from 'components/CollectionIcon'; import CollectionIcon from "components/CollectionIcon";
type Props = { type Props = {
result: DocumentPath, result: DocumentPath,
document?: ?Document, document?: ?Document,
collection: ?Collection, collection: ?Collection,
onSuccess?: () => void, onSuccess?: () => void,
ref?: (?React.ElementRef<'div'>) => void, ref?: (?React.ElementRef<"div">) => void,
}; };
@observer @observer
@ -25,7 +25,7 @@ class PathToDocument extends React.Component<Props> {
const { document, result, onSuccess } = this.props; const { document, result, onSuccess } = this.props;
if (!document) return; if (!document) return;
if (result.type === 'document') { if (result.type === "document") {
await document.move(result.collectionId, result.id); await document.move(result.collectionId, result.id);
} else { } else {
await document.move(result.collectionId, null); await document.move(result.collectionId, null);
@ -48,7 +48,7 @@ class PathToDocument extends React.Component<Props> {
.reduce((prev, curr) => [prev, <StyledGoToIcon />, curr])} .reduce((prev, curr) => [prev, <StyledGoToIcon />, curr])}
{document && ( {document && (
<Flex> <Flex>
{' '} {" "}
<StyledGoToIcon /> <Title>{document.title}</Title> <StyledGoToIcon /> <Title>{document.title}</Title>
</Flex> </Flex>
)} )}
@ -77,7 +77,7 @@ const ResultWrapper = styled.div`
cursor: default; cursor: default;
`; `;
const ResultWrapperLink = styled(ResultWrapper.withComponent('a'))` const ResultWrapperLink = styled(ResultWrapper.withComponent("a"))`
margin: 0 -8px; margin: 0 -8px;
padding: 8px 4px; padding: 8px 4px;
border-radius: 8px; border-radius: 8px;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import BoundlessPopover from 'boundless-popover'; import BoundlessPopover from "boundless-popover";
import styled, { keyframes } from 'styled-components'; import styled, { keyframes } from "styled-components";
const fadeIn = keyframes` const fadeIn = keyframes`
from { from {

View File

@ -1,13 +1,13 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { inject, observer } from 'mobx-react'; import { inject, observer } from "mobx-react";
import styled from 'styled-components'; import styled from "styled-components";
import Document from 'models/Document'; import Document from "models/Document";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Time from 'shared/components/Time'; import Time from "shared/components/Time";
import Breadcrumb from 'shared/components/Breadcrumb'; import Breadcrumb from "shared/components/Breadcrumb";
import CollectionsStore from 'stores/CollectionsStore'; import CollectionsStore from "stores/CollectionsStore";
import AuthStore from 'stores/AuthStore'; import AuthStore from "stores/AuthStore";
const Container = styled(Flex)` const Container = styled(Flex)`
color: ${props => props.theme.textTertiary}; color: ${props => props.theme.textTertiary};
@ -19,7 +19,7 @@ const Container = styled(Flex)`
const Modified = styled.span` const Modified = styled.span`
color: ${props => color: ${props =>
props.highlight ? props.theme.text : props.theme.textTertiary}; props.highlight ? props.theme.text : props.theme.textTertiary};
font-weight: ${props => (props.highlight ? '600' : '400')}; font-weight: ${props => (props.highlight ? "600" : "400")};
`; `;
type Props = { type Props = {
@ -102,7 +102,7 @@ function PublishingInfo({
return ( return (
<Container align="center" {...rest}> <Container align="center" {...rest}>
{updatedByMe ? 'You' : updatedBy.name}&nbsp; {updatedByMe ? "You" : updatedBy.name}&nbsp;
{content} {content}
{showCollection && {showCollection &&
collection && ( collection && (
@ -118,4 +118,4 @@ function PublishingInfo({
); );
} }
export default inject('collections', 'auth')(observer(PublishingInfo)); export default inject("collections", "auth")(observer(PublishingInfo));

View File

@ -1,8 +1,8 @@
// @flow // @flow
// based on: https://reacttraining.com/react-router/web/guides/scroll-restoration // based on: https://reacttraining.com/react-router/web/guides/scroll-restoration
import * as React from 'react'; import * as React from "react";
import { withRouter } from 'react-router-dom'; import { withRouter } from "react-router-dom";
import type { Location } from 'react-router-dom'; import type { Location } from "react-router-dom";
type Props = { type Props = {
location: Location, location: Location,

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
shadow?: boolean, shadow?: boolean,
@ -32,7 +32,7 @@ const Wrapper = styled.div`
overscroll-behavior: none; overscroll-behavior: none;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
box-shadow: ${props => box-shadow: ${props =>
props.shadow ? '0 1px inset rgba(0,0,0,.1)' : 'none'}; props.shadow ? "0 1px inset rgba(0,0,0,.1)" : "none"};
transition: all 250ms ease-in-out; transition: all 250ms ease-in-out;
`; `;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import styled from 'styled-components'; import styled from "styled-components";
import { import {
ArchiveIcon, ArchiveIcon,
HomeIcon, HomeIcon,
@ -10,25 +10,25 @@ import {
StarredIcon, StarredIcon,
TrashIcon, TrashIcon,
PlusIcon, PlusIcon,
} from 'outline-icons'; } from "outline-icons";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Modal from 'components/Modal'; import Modal from "components/Modal";
import Invite from 'scenes/Invite'; import Invite from "scenes/Invite";
import AccountMenu from 'menus/AccountMenu'; import AccountMenu from "menus/AccountMenu";
import Sidebar from './Sidebar'; import Sidebar from "./Sidebar";
import Scrollable from 'components/Scrollable'; import Scrollable from "components/Scrollable";
import Section from './components/Section'; import Section from "./components/Section";
import Collections from './components/Collections'; import Collections from "./components/Collections";
import SidebarLink from './components/SidebarLink'; import SidebarLink from "./components/SidebarLink";
import HeaderBlock from './components/HeaderBlock'; import HeaderBlock from "./components/HeaderBlock";
import Bubble from './components/Bubble'; import Bubble from "./components/Bubble";
import AuthStore from 'stores/AuthStore'; import AuthStore from "stores/AuthStore";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
import PoliciesStore from 'stores/PoliciesStore'; import PoliciesStore from "stores/PoliciesStore";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
import { observable } from 'mobx'; import { observable } from "mobx";
type Props = { type Props = {
auth: AuthStore, auth: AuthStore,
@ -47,7 +47,7 @@ class MainSidebar extends React.Component<Props> {
handleCreateCollection = (ev: SyntheticEvent<>) => { handleCreateCollection = (ev: SyntheticEvent<>) => {
ev.preventDefault(); ev.preventDefault();
this.props.ui.setActiveModal('collection-new'); this.props.ui.setActiveModal("collection-new");
}; };
handleInviteModalOpen = (ev: SyntheticEvent<>) => { handleInviteModalOpen = (ev: SyntheticEvent<>) => {
@ -90,7 +90,7 @@ class MainSidebar extends React.Component<Props> {
/> />
<SidebarLink <SidebarLink
to={{ to={{
pathname: '/search', pathname: "/search",
state: { fromMenu: true }, state: { fromMenu: true },
}} }}
icon={<SearchIcon color="currentColor" />} icon={<SearchIcon color="currentColor" />}
@ -172,4 +172,4 @@ const Drafts = styled(Flex)`
height: 24px; height: 24px;
`; `;
export default inject('documents', 'policies', 'auth', 'ui')(MainSidebar); export default inject("documents", "policies", "auth", "ui")(MainSidebar);

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import type { RouterHistory } from 'react-router-dom'; import type { RouterHistory } from "react-router-dom";
import styled from 'styled-components'; import styled from "styled-components";
import { import {
DocumentIcon, DocumentIcon,
EmailIcon, EmailIcon,
@ -15,20 +15,20 @@ import {
TeamIcon, TeamIcon,
BulletedListIcon, BulletedListIcon,
ExpandedIcon, ExpandedIcon,
} from 'outline-icons'; } from "outline-icons";
import ZapierIcon from './icons/Zapier'; import ZapierIcon from "./icons/Zapier";
import SlackIcon from './icons/Slack'; import SlackIcon from "./icons/Slack";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import Sidebar from './Sidebar'; import Sidebar from "./Sidebar";
import Scrollable from 'components/Scrollable'; import Scrollable from "components/Scrollable";
import Section from './components/Section'; import Section from "./components/Section";
import Header from './components/Header'; import Header from "./components/Header";
import SidebarLink from './components/SidebarLink'; import SidebarLink from "./components/SidebarLink";
import HeaderBlock from './components/HeaderBlock'; import HeaderBlock from "./components/HeaderBlock";
import Version from './components/Version'; import Version from "./components/Version";
import PoliciesStore from 'stores/PoliciesStore'; import PoliciesStore from "stores/PoliciesStore";
import AuthStore from 'stores/AuthStore'; import AuthStore from "stores/AuthStore";
type Props = { type Props = {
history: RouterHistory, history: RouterHistory,
@ -39,7 +39,7 @@ type Props = {
@observer @observer
class SettingsSidebar extends React.Component<Props> { class SettingsSidebar extends React.Component<Props> {
returnToDashboard = () => { returnToDashboard = () => {
this.props.history.push('/'); this.props.history.push("/");
}; };
render() { render() {
@ -146,7 +146,7 @@ class SettingsSidebar extends React.Component<Props> {
</Section> </Section>
)} )}
{can.update && {can.update &&
process.env.DEPLOYMENT !== 'hosted' && ( process.env.DEPLOYMENT !== "hosted" && (
<Section> <Section>
<Header>Installation</Header> <Header>Installation</Header>
<Version /> <Version />
@ -168,4 +168,4 @@ const ReturnToApp = styled(Flex)`
height: 16px; height: 16px;
`; `;
export default inject('auth', 'policies')(SettingsSidebar); export default inject("auth", "policies")(SettingsSidebar);

View File

@ -1,14 +1,14 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { withRouter } from 'react-router-dom'; import { withRouter } from "react-router-dom";
import type { Location } from 'react-router-dom'; import type { Location } from "react-router-dom";
import styled from 'styled-components'; import styled from "styled-components";
import breakpoint from 'styled-components-breakpoint'; import breakpoint from "styled-components-breakpoint";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import { CloseIcon, MenuIcon } from 'outline-icons'; import { CloseIcon, MenuIcon } from "outline-icons";
import Fade from 'components/Fade'; import Fade from "components/Fade";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
let firstRender = true; let firstRender = true;
@ -69,7 +69,7 @@ const Container = styled(Flex)`
width: 100%; width: 100%;
background: ${props => props.theme.sidebarBackground}; background: ${props => props.theme.sidebarBackground};
transition: left 100ms ease-out, ${props => props.theme.backgroundTransition}; transition: left 100ms ease-out, ${props => props.theme.backgroundTransition};
margin-left: ${props => (props.mobileSidebarVisible ? 0 : '-100%')}; margin-left: ${props => (props.mobileSidebarVisible ? 0 : "-100%")};
z-index: 1000; z-index: 1000;
@media print { @media print {
@ -79,7 +79,7 @@ const Container = styled(Flex)`
&:before, &:before,
&:after { &:after {
content: ''; content: "";
background: ${props => props.theme.sidebarBackground}; background: ${props => props.theme.sidebarBackground};
position: absolute; position: absolute;
top: -50vh; top: -50vh;
@ -93,7 +93,7 @@ const Container = styled(Flex)`
bottom: -50vh; bottom: -50vh;
} }
${breakpoint('tablet')` ${breakpoint("tablet")`
left: ${props => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)}; left: ${props => (props.editMode ? `-${props.theme.sidebarWidth}` : 0)};
width: ${props => props.theme.sidebarWidth}; width: ${props => props.theme.sidebarWidth};
margin: 0; margin: 0;
@ -106,14 +106,14 @@ const Toggle = styled.a`
align-items: center; align-items: center;
position: fixed; position: fixed;
top: 0; top: 0;
left: ${props => (props.mobileSidebarVisible ? 'auto' : 0)}; left: ${props => (props.mobileSidebarVisible ? "auto" : 0)};
right: ${props => (props.mobileSidebarVisible ? 0 : 'auto')}; right: ${props => (props.mobileSidebarVisible ? 0 : "auto")};
z-index: 1; z-index: 1;
margin: 12px; margin: 12px;
${breakpoint('tablet')` ${breakpoint("tablet")`
display: none; display: none;
`}; `};
`; `;
export default withRouter(inject('ui')(Sidebar)); export default withRouter(inject("ui")(Sidebar));

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { bounceIn } from 'shared/styles/animations'; import { bounceIn } from "shared/styles/animations";
type Props = { type Props = {
count: number, count: number,
@ -17,7 +17,7 @@ const Count = styled.div`
color: ${props => props.theme.white}; color: ${props => props.theme.white};
background: ${props => props.theme.slateDark}; background: ${props => props.theme.slateDark};
display: inline-block; display: inline-block;
font-feature-settings: 'tnum'; font-feature-settings: "tnum";
font-weight: 600; font-weight: 600;
font-size: 9px; font-size: 9px;
white-space: nowrap; white-space: nowrap;

View File

@ -1,17 +1,17 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { observable } from 'mobx'; import { observable } from "mobx";
import Collection from 'models/Collection'; import Collection from "models/Collection";
import Document from 'models/Document'; import Document from "models/Document";
import CollectionMenu from 'menus/CollectionMenu'; import CollectionMenu from "menus/CollectionMenu";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
import SidebarLink from './SidebarLink'; import SidebarLink from "./SidebarLink";
import DocumentLink from './DocumentLink'; import DocumentLink from "./DocumentLink";
import CollectionIcon from 'components/CollectionIcon'; import CollectionIcon from "components/CollectionIcon";
import DropToImport from 'components/DropToImport'; import DropToImport from "components/DropToImport";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
type Props = { type Props = {
collection: Collection, collection: Collection,

View File

@ -1,22 +1,22 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import { withRouter, type RouterHistory } from 'react-router-dom'; import { withRouter, type RouterHistory } from "react-router-dom";
import keydown from 'react-keydown'; import keydown from "react-keydown";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import { PlusIcon } from 'outline-icons'; import { PlusIcon } from "outline-icons";
import { newDocumentUrl } from 'utils/routeHelpers'; import { newDocumentUrl } from "utils/routeHelpers";
import Header from './Header'; import Header from "./Header";
import SidebarLink from './SidebarLink'; import SidebarLink from "./SidebarLink";
import CollectionLink from './CollectionLink'; import CollectionLink from "./CollectionLink";
import CollectionsLoading from './CollectionsLoading'; import CollectionsLoading from "./CollectionsLoading";
import Fade from 'components/Fade'; import Fade from "components/Fade";
import CollectionsStore from 'stores/CollectionsStore'; import CollectionsStore from "stores/CollectionsStore";
import PoliciesStore from 'stores/PoliciesStore'; import PoliciesStore from "stores/PoliciesStore";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
type Props = { type Props = {
history: RouterHistory, history: RouterHistory,
@ -39,7 +39,7 @@ class Collections extends React.Component<Props> {
} }
} }
@keydown('n') @keydown("n")
goToNewDocument() { goToNewDocument() {
if (this.props.ui.editMode) return; if (this.props.ui.editMode) return;
@ -94,6 +94,6 @@ class Collections extends React.Component<Props> {
} }
} }
export default inject('collections', 'ui', 'documents', 'policies')( export default inject("collections", "ui", "documents", "policies")(
withRouter(Collections) withRouter(Collections)
); );

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import Mask from 'components/Mask'; import Mask from "components/Mask";
function CollectionsLoading() { function CollectionsLoading() {
return ( return (

View File

@ -1,17 +1,17 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { observable } from 'mobx'; import { observable } from "mobx";
import styled from 'styled-components'; import styled from "styled-components";
import Document from 'models/Document'; import Document from "models/Document";
import DocumentMenu from 'menus/DocumentMenu'; import DocumentMenu from "menus/DocumentMenu";
import SidebarLink from './SidebarLink'; import SidebarLink from "./SidebarLink";
import DropToImport from 'components/DropToImport'; import DropToImport from "components/DropToImport";
import Fade from 'components/Fade'; import Fade from "components/Fade";
import Collection from 'models/Collection'; import Collection from "models/Collection";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import { type NavigationNode } from 'types'; import { type NavigationNode } from "types";
type Props = { type Props = {
node: NavigationNode, node: NavigationNode,
@ -96,7 +96,7 @@ class DocumentLink extends React.Component<Props> {
state: { title: node.title }, state: { title: node.title },
}} }}
expanded={showChildren ? true : undefined} expanded={showChildren ? true : undefined}
label={node.title || 'Untitled'} label={node.title || "Untitled"}
depth={depth} depth={depth}
exact={false} exact={false}
menuOpen={this.menuOpen} menuOpen={this.menuOpen}

View File

@ -1,6 +1,6 @@
// @flow // @flow
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import styled from 'styled-components'; import styled from "styled-components";
const Header = styled(Flex)` const Header = styled(Flex)`
font-size: 11px; font-size: 11px;

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import { ExpandedIcon } from 'outline-icons'; import { ExpandedIcon } from "outline-icons";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
import TeamLogo from 'shared/components/TeamLogo'; import TeamLogo from "shared/components/TeamLogo";
type Props = { type Props = {
teamName: string, teamName: string,
@ -26,7 +26,7 @@ function HeaderBlock({
<TeamLogo alt={`${teamName} logo`} src={logoUrl} /> <TeamLogo alt={`${teamName} logo`} src={logoUrl} />
<Flex align="flex-start" column> <Flex align="flex-start" column>
<TeamName showDisclosure> <TeamName showDisclosure>
{teamName}{' '} {teamName}{" "}
{showDisclosure && <StyledExpandedIcon color={theme.text} />} {showDisclosure && <StyledExpandedIcon color={theme.text} />}
</TeamName> </TeamName>
<Subheading>{subheading}</Subheading> <Subheading>{subheading}</Subheading>

View File

@ -1,6 +1,6 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
const Section = styled(Flex)` const Section = styled(Flex)`
position: relative; position: relative;

View File

@ -1,11 +1,11 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable, action } from 'mobx'; import { observable, action } from "mobx";
import { observer } from 'mobx-react'; import { observer } from "mobx-react";
import { withRouter, NavLink } from 'react-router-dom'; import { withRouter, NavLink } from "react-router-dom";
import { CollapsedIcon } from 'outline-icons'; import { CollapsedIcon } from "outline-icons";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import Flex from 'shared/components/Flex'; import Flex from "shared/components/Flex";
type Props = { type Props = {
to?: string | Object, to?: string | Object,
@ -82,7 +82,7 @@ class SidebarLink extends React.Component<Props> {
onClick={onClick} onClick={onClick}
exact={exact !== false} exact={exact !== false}
to={to} to={to}
as={to ? undefined : href ? 'a' : 'div'} as={to ? undefined : href ? "a" : "div"}
href={href} href={href}
> >
{icon && <IconWrapper>{icon}</IconWrapper>} {icon && <IconWrapper>{icon}</IconWrapper>}
@ -108,7 +108,7 @@ const IconWrapper = styled.span`
`; `;
const Action = styled.span` const Action = styled.span`
display: ${props => (props.menuOpen ? 'inline' : 'none')}; display: ${props => (props.menuOpen ? "inline" : "none")};
position: absolute; position: absolute;
top: 4px; top: 4px;
right: 4px; right: 4px;
@ -168,7 +168,7 @@ const Disclosure = styled(CollapsedIcon)`
position: absolute; position: absolute;
left: -24px; left: -24px;
${({ expanded }) => !expanded && 'transform: rotate(-90deg);'}; ${({ expanded }) => !expanded && "transform: rotate(-90deg);"};
`; `;
export default withRouter(withTheme(SidebarLink)); export default withRouter(withTheme(SidebarLink));

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import Badge from 'components/Badge'; import Badge from "components/Badge";
import SidebarLink from './SidebarLink'; import SidebarLink from "./SidebarLink";
import { version } from '../../../../package.json'; import { version } from "../../../../package.json";
export default function Version() { export default function Version() {
// $FlowFixMe // $FlowFixMe
@ -14,7 +14,7 @@ export default function Version() {
async function loadReleases() { async function loadReleases() {
let out = 0; let out = 0;
const res = await fetch( const res = await fetch(
'https://api.github.com/repos/outline/outline/releases' "https://api.github.com/repos/outline/outline/releases"
); );
const releases = await res.json(); const releases = await res.json();
for (const release of releases) { for (const release of releases) {
@ -37,9 +37,9 @@ export default function Version() {
<br /> <br />
<LilBadge> <LilBadge>
{releasesBehind === 0 {releasesBehind === 0
? 'Up to date' ? "Up to date"
: `${releasesBehind} version${ : `${releasesBehind} version${
releasesBehind === 1 ? '' : 's' releasesBehind === 1 ? "" : "s"
} behind`} } behind`}
</LilBadge> </LilBadge>
</React.Fragment> </React.Fragment>

View File

@ -1,11 +1,11 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
type Props = { type Props = {
color?: string, color?: string,
}; };
export default function SlackIcon({ color = '#4E5C6E' }: Props) { export default function SlackIcon({ color = "#4E5C6E" }: Props) {
return ( return (
<svg <svg
fill={color} fill={color}

View File

@ -1,11 +1,11 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
type Props = { type Props = {
color?: string, color?: string,
}; };
export default function ZapierIcon({ color = '#4E5C6E' }: Props) { export default function ZapierIcon({ color = "#4E5C6E" }: Props) {
return ( return (
<svg <svg
fill={color} fill={color}

View File

@ -1,3 +1,3 @@
// @flow // @flow
import Sidebar from './Main'; import Sidebar from "./Main";
export default Sidebar; export default Sidebar;

View File

@ -1,18 +1,18 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observable } from 'mobx'; import { observable } from "mobx";
import { inject, observer } from 'mobx-react'; import { inject, observer } from "mobx-react";
import { find } from 'lodash'; import { find } from "lodash";
import io from 'socket.io-client'; import io from "socket.io-client";
import DocumentsStore from 'stores/DocumentsStore'; import DocumentsStore from "stores/DocumentsStore";
import CollectionsStore from 'stores/CollectionsStore'; import CollectionsStore from "stores/CollectionsStore";
import GroupsStore from 'stores/GroupsStore'; import GroupsStore from "stores/GroupsStore";
import MembershipsStore from 'stores/MembershipsStore'; import MembershipsStore from "stores/MembershipsStore";
import DocumentPresenceStore from 'stores/DocumentPresenceStore'; import DocumentPresenceStore from "stores/DocumentPresenceStore";
import PoliciesStore from 'stores/PoliciesStore'; import PoliciesStore from "stores/PoliciesStore";
import ViewsStore from 'stores/ViewsStore'; import ViewsStore from "stores/ViewsStore";
import AuthStore from 'stores/AuthStore'; import AuthStore from "stores/AuthStore";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
export const SocketContext: any = React.createContext(); export const SocketContext: any = React.createContext();
@ -37,7 +37,7 @@ class SocketProvider extends React.Component<Props> {
if (!process.env.WEBSOCKETS_ENABLED) return; if (!process.env.WEBSOCKETS_ENABLED) return;
this.socket = io(window.location.origin, { this.socket = io(window.location.origin, {
path: '/realtime', path: "/realtime",
}); });
this.socket.authenticated = false; this.socket.authenticated = false;
@ -54,38 +54,38 @@ class SocketProvider extends React.Component<Props> {
} = this.props; } = this.props;
if (!auth.token) return; if (!auth.token) return;
this.socket.on('connect', () => { this.socket.on("connect", () => {
// immediately send current users token to the websocket backend where it // immediately send current users token to the websocket backend where it
// is verified, if all goes well an 'authenticated' message will be // is verified, if all goes well an 'authenticated' message will be
// received in response // received in response
this.socket.emit('authentication', { this.socket.emit("authentication", {
token: auth.token, token: auth.token,
}); });
}); });
this.socket.on('disconnect', () => { this.socket.on("disconnect", () => {
// when the socket is disconnected we need to clear all presence state as // when the socket is disconnected we need to clear all presence state as
// it's no longer reliable. // it's no longer reliable.
presence.clear(); presence.clear();
}); });
this.socket.on('authenticated', () => { this.socket.on("authenticated", () => {
this.socket.authenticated = true; this.socket.authenticated = true;
}); });
this.socket.on('unauthorized', err => { this.socket.on("unauthorized", err => {
this.socket.authenticated = false; this.socket.authenticated = false;
ui.showToast(err.message); ui.showToast(err.message);
throw err; throw err;
}); });
this.socket.on('entities', async event => { this.socket.on("entities", async event => {
if (event.documentIds) { if (event.documentIds) {
for (const documentDescriptor of event.documentIds) { for (const documentDescriptor of event.documentIds) {
const documentId = documentDescriptor.id; const documentId = documentDescriptor.id;
let document = documents.get(documentId) || {}; let document = documents.get(documentId) || {};
if (event.event === 'documents.delete') { if (event.event === "documents.delete") {
const document = documents.get(documentId); const document = documents.get(documentId);
if (document) { if (document) {
document.deletedAt = documentDescriptor.updatedAt; document.deletedAt = documentDescriptor.updatedAt;
@ -136,7 +136,7 @@ class SocketProvider extends React.Component<Props> {
const collectionId = collectionDescriptor.id; const collectionId = collectionDescriptor.id;
const collection = collections.get(collectionId) || {}; const collection = collections.get(collectionId) || {};
if (event.event === 'collections.delete') { if (event.event === "collections.delete") {
documents.removeCollectionDocuments(collectionId); documents.removeCollectionDocuments(collectionId);
continue; continue;
} }
@ -184,17 +184,17 @@ class SocketProvider extends React.Component<Props> {
} }
}); });
this.socket.on('documents.star', event => { this.socket.on("documents.star", event => {
documents.starredIds.set(event.documentId, true); documents.starredIds.set(event.documentId, true);
}); });
this.socket.on('documents.unstar', event => { this.socket.on("documents.unstar", event => {
documents.starredIds.set(event.documentId, false); documents.starredIds.set(event.documentId, false);
}); });
// received when a user is given access to a collection // received when a user is given access to a collection
// if the user is us then we go ahead and load the collection from API. // if the user is us then we go ahead and load the collection from API.
this.socket.on('collections.add_user', event => { this.socket.on("collections.add_user", event => {
if (auth.user && event.userId === auth.user.id) { if (auth.user && event.userId === auth.user.id) {
collections.fetch(event.collectionId, { force: true }); collections.fetch(event.collectionId, { force: true });
} }
@ -208,7 +208,7 @@ class SocketProvider extends React.Component<Props> {
// received when a user is removed from having access to a collection // received when a user is removed from having access to a collection
// to keep state in sync we must update our UI if the user is us, // to keep state in sync we must update our UI if the user is us,
// or otherwise just remove any membership state we have for that user. // or otherwise just remove any membership state we have for that user.
this.socket.on('collections.remove_user', event => { this.socket.on("collections.remove_user", event => {
if (auth.user && event.userId === auth.user.id) { if (auth.user && event.userId === auth.user.id) {
collections.remove(event.collectionId); collections.remove(event.collectionId);
memberships.removeCollectionMemberships(event.collectionId); memberships.removeCollectionMemberships(event.collectionId);
@ -220,32 +220,32 @@ class SocketProvider extends React.Component<Props> {
// received a message from the API server that we should request // received a message from the API server that we should request
// to join a specific room. Forward that to the ws server. // to join a specific room. Forward that to the ws server.
this.socket.on('join', event => { this.socket.on("join", event => {
this.socket.emit('join', event); this.socket.emit("join", event);
}); });
// received a message from the API server that we should request // received a message from the API server that we should request
// to leave a specific room. Forward that to the ws server. // to leave a specific room. Forward that to the ws server.
this.socket.on('leave', event => { this.socket.on("leave", event => {
this.socket.emit('leave', event); this.socket.emit("leave", event);
}); });
// received whenever we join a document room, the payload includes // received whenever we join a document room, the payload includes
// userIds that are present/viewing and those that are editing. // userIds that are present/viewing and those that are editing.
this.socket.on('document.presence', event => { this.socket.on("document.presence", event => {
presence.init(event.documentId, event.userIds, event.editingIds); presence.init(event.documentId, event.userIds, event.editingIds);
}); });
// received whenever a new user joins a document room, aka they // received whenever a new user joins a document room, aka they
// navigate to / start viewing a document // navigate to / start viewing a document
this.socket.on('user.join', event => { this.socket.on("user.join", event => {
presence.touch(event.documentId, event.userId, event.isEditing); presence.touch(event.documentId, event.userId, event.isEditing);
views.touch(event.documentId, event.userId); views.touch(event.documentId, event.userId);
}); });
// received whenever a new user leaves a document room, aka they // received whenever a new user leaves a document room, aka they
// navigate away / stop viewing a document // navigate away / stop viewing a document
this.socket.on('user.leave', event => { this.socket.on("user.leave", event => {
presence.leave(event.documentId, event.userId); presence.leave(event.documentId, event.userId);
views.touch(event.documentId, event.userId); views.touch(event.documentId, event.userId);
}); });
@ -253,7 +253,7 @@ class SocketProvider extends React.Component<Props> {
// received when another client in a document room wants to change // received when another client in a document room wants to change
// or update it's presence. Currently the only property is whether // or update it's presence. Currently the only property is whether
// the client is in editing state or not. // the client is in editing state or not.
this.socket.on('user.presence', event => { this.socket.on("user.presence", event => {
presence.touch(event.documentId, event.userId, event.isEditing); presence.touch(event.documentId, event.userId, event.isEditing);
}); });
} }
@ -275,13 +275,13 @@ class SocketProvider extends React.Component<Props> {
} }
export default inject( export default inject(
'auth', "auth",
'ui', "ui",
'documents', "documents",
'collections', "collections",
'groups', "groups",
'memberships', "memberships",
'presence', "presence",
'policies', "policies",
'views' "views"
)(SocketProvider); )(SocketProvider);

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
type Props = { type Props = {
children: React.Node, children: React.Node,
@ -13,7 +13,7 @@ const H3 = styled.h3`
line-height: 1; line-height: 1;
`; `;
const Underline = styled('span')` const Underline = styled("span")`
position: relative; position: relative;
top: 1px; top: 1px;

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { LabelText } from 'components/Input'; import { LabelText } from "components/Input";
type Props = { type Props = {
width?: number, width?: number,
@ -57,7 +57,7 @@ const Slider = styled.span`
&:before { &:before {
position: absolute; position: absolute;
content: ''; content: "";
height: ${props => props.height - 8}px; height: ${props => props.height - 8}px;
width: ${props => props.height - 8}px; width: ${props => props.height - 8}px;
left: 4px; left: 4px;

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled, { withTheme } from 'styled-components'; import styled, { withTheme } from "styled-components";
import { NavLink } from 'react-router-dom'; import { NavLink } from "react-router-dom";
import { lighten } from 'polished'; import { lighten } from "polished";
type Props = { type Props = {
theme: Object, theme: Object,
@ -35,7 +35,7 @@ const StyledNavLink = styled(NavLink)`
function Tab(props: Props) { function Tab(props: Props) {
const activeStyle = { const activeStyle = {
paddingBottom: '5px', paddingBottom: "5px",
borderBottom: `3px solid ${props.theme.textSecondary}`, borderBottom: `3px solid ${props.theme.textSecondary}`,
color: props.theme.textSecondary, color: props.theme.textSecondary,
}; };

View File

@ -1,5 +1,5 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const Tabs = styled.nav` const Tabs = styled.nav`
border-bottom: 1px solid ${props => props.theme.divider}; border-bottom: 1px solid ${props => props.theme.divider};

View File

@ -1,10 +1,10 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { inject, observer } from 'mobx-react'; import { inject, observer } from "mobx-react";
import { ThemeProvider } from 'styled-components'; import { ThemeProvider } from "styled-components";
import { dark, light } from 'shared/styles/theme'; import { dark, light } from "shared/styles/theme";
import GlobalStyles from 'shared/styles/globals'; import GlobalStyles from "shared/styles/globals";
import UiStore from 'stores/UiStore'; import UiStore from "stores/UiStore";
type Props = { type Props = {
ui: UiStore, ui: UiStore,
@ -13,7 +13,7 @@ type Props = {
function Theme({ children, ui }: Props) { function Theme({ children, ui }: Props) {
return ( return (
<ThemeProvider theme={ui.resolvedTheme === 'dark' ? dark : light}> <ThemeProvider theme={ui.resolvedTheme === "dark" ? dark : light}>
<React.Fragment> <React.Fragment>
<GlobalStyles /> <GlobalStyles />
{children} {children}
@ -22,4 +22,4 @@ function Theme({ children, ui }: Props) {
); );
} }
export default inject('ui')(observer(Theme)); export default inject("ui")(observer(Theme));

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import { observer, inject } from 'mobx-react'; import { observer, inject } from "mobx-react";
import styled from 'styled-components'; import styled from "styled-components";
import Toast from './components/Toast'; import Toast from "./components/Toast";
import UiStore from '../../stores/UiStore'; import UiStore from "../../stores/UiStore";
type Props = { type Props = {
ui: UiStore, ui: UiStore,
@ -37,4 +37,4 @@ const List = styled.ol`
z-index: 1000; z-index: 1000;
`; `;
export default inject('ui')(Toasts); export default inject("ui")(Toasts);

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import { darken } from 'polished'; import { darken } from "polished";
import { fadeAndScaleIn } from 'shared/styles/animations'; import { fadeAndScaleIn } from "shared/styles/animations";
import type { Toast as TToast } from '../../../types'; import type { Toast as TToast } from "../../../types";
type Props = { type Props = {
onRequestClose: () => void, onRequestClose: () => void,
@ -33,7 +33,7 @@ class Toast extends React.Component<Props> {
const { toast, onRequestClose } = this.props; const { toast, onRequestClose } = this.props;
const { action } = toast; const { action } = toast;
const message = const message =
typeof toast.message === 'string' typeof toast.message === "string"
? toast.message ? toast.message
: toast.message.toString(); : toast.message.toString();
@ -41,11 +41,11 @@ class Toast extends React.Component<Props> {
<li> <li>
<Container <Container
onClick={action ? undefined : onRequestClose} onClick={action ? undefined : onRequestClose}
type={toast.type || 'success'} type={toast.type || "success"}
> >
<Message>{message}</Message> <Message>{message}</Message>
{action && ( {action && (
<Action type={toast.type || 'success'} onClick={action.onClick}> <Action type={toast.type || "success"} onClick={action.onClick}>
{action.text} {action.text}
</Action> </Action>
)} )}

View File

@ -1,3 +1,3 @@
// @flow // @flow
import Toasts from './Toasts'; import Toasts from "./Toasts";
export default Toasts; export default Toasts;

View File

@ -1,12 +1,12 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import styled from 'styled-components'; import styled from "styled-components";
import Tippy from '@tippy.js/react'; import Tippy from "@tippy.js/react";
type Props = { type Props = {
tooltip: React.Node, tooltip: React.Node,
shortcut?: React.Node, shortcut?: React.Node,
placement?: 'top' | 'bottom' | 'left' | 'right', placement?: "top" | "bottom" | "left" | "right",
children: React.Node, children: React.Node,
delay?: number, delay?: number,
className?: string, className?: string,
@ -47,7 +47,7 @@ const Shortcut = styled.kbd`
display: inline-block; display: inline-block;
padding: 2px 4px; padding: 2px 4px;
font: 10px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, font: 10px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier,
monospace; monospace;
line-height: 10px; line-height: 10px;
color: ${props => props.theme.tooltipBackground}; color: ${props => props.theme.tooltipBackground};

View File

@ -1,7 +1,7 @@
// @flow // @flow
import styled from 'styled-components'; import styled from "styled-components";
const VisuallyHidden = styled('span')` const VisuallyHidden = styled("span")`
position: absolute !important; position: absolute !important;
height: 1px; height: 1px;
width: 1px; width: 1px;

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import Frame from './components/Frame'; import Frame from "./components/Frame";
type Props = {| type Props = {|
attrs: {| attrs: {|
@ -11,8 +11,8 @@ type Props = {|
export default class Abstract extends React.Component<Props> { export default class Abstract extends React.Component<Props> {
static ENABLED = [ static ENABLED = [
new RegExp('https?://share.(?:go)?abstract.com/(.*)$'), new RegExp("https?://share.(?:go)?abstract.com/(.*)$"),
new RegExp('https?://app.(?:go)?abstract.com/(?:share|embed)/(.*)$'), new RegExp("https?://app.(?:go)?abstract.com/(?:share|embed)/(.*)$"),
]; ];
render() { render() {

View File

@ -1,58 +1,58 @@
/* eslint-disable flowtype/require-valid-file-annotation */ /* eslint-disable flowtype/require-valid-file-annotation */
import Abstract from './Abstract'; import Abstract from "./Abstract";
describe('Abstract', () => { describe("Abstract", () => {
const match = Abstract.ENABLED[0]; const match = Abstract.ENABLED[0];
const match2 = Abstract.ENABLED[1]; const match2 = Abstract.ENABLED[1];
test('to be enabled on share subdomain link', () => { test("to be enabled on share subdomain link", () => {
expect( expect(
'https://share.goabstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match( "https://share.goabstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
match match
) )
).toBeTruthy(); ).toBeTruthy();
expect( expect(
'https://share.abstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match( "https://share.abstract.com/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
match match
) )
).toBeTruthy(); ).toBeTruthy();
}); });
test('to be enabled on share link', () => { test("to be enabled on share link", () => {
expect( expect(
'https://app.goabstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match( "https://app.goabstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
match2 match2
) )
).toBeTruthy(); ).toBeTruthy();
expect( expect(
'https://app.abstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match( "https://app.abstract.com/share/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
match2 match2
) )
).toBeTruthy(); ).toBeTruthy();
}); });
test('to be enabled on embed link', () => { test("to be enabled on embed link", () => {
expect( expect(
'https://app.goabstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match( "https://app.goabstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
match2 match2
) )
).toBeTruthy(); ).toBeTruthy();
expect( expect(
'https://app.abstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a'.match( "https://app.abstract.com/embed/aaec8bba-f473-4f64-96e7-bff41c70ff8a".match(
match2 match2
) )
).toBeTruthy(); ).toBeTruthy();
}); });
test('to not be enabled elsewhere', () => { test("to not be enabled elsewhere", () => {
expect('https://abstract.com'.match(match)).toBe(null); expect("https://abstract.com".match(match)).toBe(null);
expect('https://goabstract.com'.match(match)).toBe(null); expect("https://goabstract.com".match(match)).toBe(null);
expect('https://app.goabstract.com'.match(match)).toBe(null); expect("https://app.goabstract.com".match(match)).toBe(null);
expect('https://abstract.com/features'.match(match)).toBe(null); expect("https://abstract.com/features".match(match)).toBe(null);
expect('https://app.abstract.com/home'.match(match)).toBe(null); expect("https://app.abstract.com/home".match(match)).toBe(null);
expect('https://abstract.com/pricing'.match(match)).toBe(null); expect("https://abstract.com/pricing".match(match)).toBe(null);
expect('https://goabstract.com/pricing'.match(match)).toBe(null); expect("https://goabstract.com/pricing".match(match)).toBe(null);
expect('https://www.goabstract.com/pricing'.match(match)).toBe(null); expect("https://www.goabstract.com/pricing".match(match)).toBe(null);
}); });
}); });

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import Frame from './components/Frame'; import Frame from "./components/Frame";
const URL_REGEX = new RegExp('https://airtable.com/(?:embed/)?(shr.*)$'); const URL_REGEX = new RegExp("https://airtable.com/(?:embed/)?(shr.*)$");
type Props = {| type Props = {|
attrs: {| attrs: {|

View File

@ -1,21 +1,21 @@
/* eslint-disable flowtype/require-valid-file-annotation */ /* eslint-disable flowtype/require-valid-file-annotation */
import Airtable from './Airtable'; import Airtable from "./Airtable";
describe('Airtable', () => { describe("Airtable", () => {
const match = Airtable.ENABLED[0]; const match = Airtable.ENABLED[0];
test('to be enabled on share link', () => { test("to be enabled on share link", () => {
expect('https://airtable.com/shrEoQs3erLnppMie'.match(match)).toBeTruthy(); expect("https://airtable.com/shrEoQs3erLnppMie".match(match)).toBeTruthy();
}); });
test('to be enabled on embed link', () => { test("to be enabled on embed link", () => {
expect( expect(
'https://airtable.com/embed/shrEoQs3erLnppMie'.match(match) "https://airtable.com/embed/shrEoQs3erLnppMie".match(match)
).toBeTruthy(); ).toBeTruthy();
}); });
test('to not be enabled elsewhere', () => { test("to not be enabled elsewhere", () => {
expect('https://airtable.com'.match(match)).toBe(null); expect("https://airtable.com".match(match)).toBe(null);
expect('https://airtable.com/features'.match(match)).toBe(null); expect("https://airtable.com/features".match(match)).toBe(null);
expect('https://airtable.com/pricing'.match(match)).toBe(null); expect("https://airtable.com/pricing".match(match)).toBe(null);
}); });
}); });

View File

@ -1,8 +1,8 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import Frame from './components/Frame'; import Frame from "./components/Frame";
const URL_REGEX = new RegExp('^https://codepen.io/(.*?)/(pen|embed)/(.*)$'); const URL_REGEX = new RegExp("^https://codepen.io/(.*?)/(pen|embed)/(.*)$");
type Props = {| type Props = {|
attrs: {| attrs: {|
@ -15,7 +15,7 @@ export default class Codepen extends React.Component<Props> {
static ENABLED = [URL_REGEX]; static ENABLED = [URL_REGEX];
render() { render() {
const normalizedUrl = this.props.attrs.href.replace(/\/pen\//, '/embed/'); const normalizedUrl = this.props.attrs.href.replace(/\/pen\//, "/embed/");
return <Frame src={normalizedUrl} title="Codepen Embed" />; return <Frame src={normalizedUrl} title="Codepen Embed" />;
} }

View File

@ -1,22 +1,22 @@
/* eslint-disable flowtype/require-valid-file-annotation */ /* eslint-disable flowtype/require-valid-file-annotation */
import Codepen from './Codepen'; import Codepen from "./Codepen";
describe('Codepen', () => { describe("Codepen", () => {
const match = Codepen.ENABLED[0]; const match = Codepen.ENABLED[0];
test('to be enabled on pen link', () => { test("to be enabled on pen link", () => {
expect( expect(
'https://codepen.io/chriscoyier/pen/gfdDu'.match(match) "https://codepen.io/chriscoyier/pen/gfdDu".match(match)
).toBeTruthy(); ).toBeTruthy();
}); });
test('to be enabled on embed link', () => { test("to be enabled on embed link", () => {
expect( expect(
'https://codepen.io/chriscoyier/embed/gfdDu'.match(match) "https://codepen.io/chriscoyier/embed/gfdDu".match(match)
).toBeTruthy(); ).toBeTruthy();
}); });
test('to not be enabled elsewhere', () => { test("to not be enabled elsewhere", () => {
expect('https://codepen.io'.match(match)).toBe(null); expect("https://codepen.io".match(match)).toBe(null);
expect('https://codepen.io/chriscoyier'.match(match)).toBe(null); expect("https://codepen.io/chriscoyier".match(match)).toBe(null);
}); });
}); });

View File

@ -1,9 +1,9 @@
// @flow // @flow
import * as React from 'react'; import * as React from "react";
import Frame from './components/Frame'; import Frame from "./components/Frame";
const URL_REGEX = new RegExp( const URL_REGEX = new RegExp(
'https://([w.-]+.)?figma.com/(file|proto)/([0-9a-zA-Z]{22,128})(?:/.*)?$' "https://([w.-]+.)?figma.com/(file|proto)/([0-9a-zA-Z]{22,128})(?:/.*)?$"
); );
type Props = {| type Props = {|

Some files were not shown because too many files have changed in this diff Show More