mirror of
https://github.com/reactjs/react.dev.git
synced 2026-02-24 04:33:10 +00:00
Merge pull request #205 from tricinel/feature/flow-types
Add flow types to components; realted to #24
This commit is contained in:
@@ -2,12 +2,27 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import {createElement} from 'glamor/react';
|
||||
|
||||
import type {Node} from 'react';
|
||||
|
||||
type Props = {
|
||||
basis: string,
|
||||
children: Node,
|
||||
direction: string,
|
||||
grow: number,
|
||||
halign: string,
|
||||
shrink: number,
|
||||
type: string,
|
||||
valign: string,
|
||||
rest: Array<any>,
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience component for declaring a flexbox layout.
|
||||
*/
|
||||
@@ -21,7 +36,7 @@ const Flex = ({
|
||||
type = 'div',
|
||||
valign = 'flex-start',
|
||||
...rest
|
||||
}) =>
|
||||
}: Props) =>
|
||||
createElement(
|
||||
type,
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -10,7 +11,16 @@ import React from 'react';
|
||||
import {colors} from 'theme';
|
||||
import ExternalLinkSvg from 'templates/components/ExternalLinkSvg';
|
||||
|
||||
const ExternalFooterLink = ({children, href, target, rel}) => (
|
||||
import type {Node} from 'react';
|
||||
|
||||
type Props = {
|
||||
children: Node,
|
||||
href: string,
|
||||
target?: string,
|
||||
rel?: string,
|
||||
};
|
||||
|
||||
const ExternalFooterLink = ({children, href, target, rel}: Props) => (
|
||||
<a
|
||||
css={{
|
||||
lineHeight: 2,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -16,7 +17,7 @@ import {colors, media} from 'theme';
|
||||
|
||||
import ossLogoPng from 'images/oss_logo.png';
|
||||
|
||||
const Footer = ({layoutHasSidebar = false}) => (
|
||||
const Footer = ({layoutHasSidebar = false}: {layoutHasSidebar: boolean}) => (
|
||||
<footer
|
||||
css={{
|
||||
backgroundColor: colors.darker,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -10,7 +11,15 @@ import Link from 'gatsby-link';
|
||||
import React from 'react';
|
||||
import {colors} from 'theme';
|
||||
|
||||
const FooterLink = ({children, target, to}) => (
|
||||
import type {Node} from 'react';
|
||||
|
||||
type Props = {
|
||||
children: Node,
|
||||
target?: string,
|
||||
to: string,
|
||||
};
|
||||
|
||||
const FooterLink = ({children, target, to}: Props) => (
|
||||
<Link
|
||||
css={{
|
||||
lineHeight: 2,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -9,7 +10,15 @@
|
||||
import React from 'react';
|
||||
import {media} from 'theme';
|
||||
|
||||
const FooterNav = ({children, title, layoutHasSidebar = false}) => (
|
||||
import type {Node} from 'react';
|
||||
|
||||
type Props = {
|
||||
children: Node,
|
||||
title?: string,
|
||||
layoutHasSidebar: boolean,
|
||||
};
|
||||
|
||||
const FooterNav = ({children, title, layoutHasSidebar = false}: Props) => (
|
||||
<div
|
||||
css={{
|
||||
display: 'flex',
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React, {Component} from 'react';
|
||||
import {colors, media} from 'theme';
|
||||
|
||||
class DocSearch extends Component {
|
||||
type State = {
|
||||
enabled: boolean,
|
||||
};
|
||||
|
||||
class DocSearch extends Component<{}, State> {
|
||||
state = {
|
||||
enabled: true,
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -17,7 +18,7 @@ import DocSearch from './DocSearch';
|
||||
|
||||
import logoSvg from 'icons/logo.svg';
|
||||
|
||||
const Header = ({location}) => (
|
||||
const Header = ({location}: {location: Location}) => (
|
||||
<header
|
||||
css={{
|
||||
backgroundColor: colors.darker,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -10,7 +11,13 @@ import Link from 'gatsby-link';
|
||||
import React from 'react';
|
||||
import {colors, media} from 'theme';
|
||||
|
||||
const HeaderLink = ({isActive, title, to}) => (
|
||||
type Props = {
|
||||
isActive: boolean,
|
||||
title: string,
|
||||
to: string,
|
||||
};
|
||||
|
||||
const HeaderLink = ({isActive, title, to}: Props) => (
|
||||
<Link css={[style, isActive && activeStyle]} to={to}>
|
||||
{title}
|
||||
{isActive && <span css={activeAfterStyle} />}
|
||||
|
||||
@@ -2,34 +2,45 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import Container from 'components/Container';
|
||||
import {Component, React} from 'react';
|
||||
import React, {Component} from 'react';
|
||||
import Sidebar from 'templates/components/Sidebar';
|
||||
import {colors, media} from 'theme';
|
||||
import ChevronSvg from 'templates/components/ChevronSvg';
|
||||
|
||||
class StickyResponsiveSidebar extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
type State = {
|
||||
open: boolean,
|
||||
};
|
||||
|
||||
type Props = {
|
||||
enableScrollSync?: boolean,
|
||||
createLink: Function, // TODO: Add better flow type once we Flow-type createLink
|
||||
defaultActiveSection: string,
|
||||
location: Location,
|
||||
sectionList: Array<Object>, // TODO: Add better flow type once we have the Section component
|
||||
};
|
||||
|
||||
class StickyResponsiveSidebar extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
open: false,
|
||||
};
|
||||
this._openNavMenu = this._openNavMenu.bind(this);
|
||||
this._closeNavMenu = this._closeNavMenu.bind(this);
|
||||
}
|
||||
|
||||
_openNavMenu() {
|
||||
_openNavMenu = () => {
|
||||
this.setState({open: !this.state.open});
|
||||
}
|
||||
};
|
||||
|
||||
_closeNavMenu() {
|
||||
_closeNavMenu = () => {
|
||||
this.setState({open: false});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {open} = this.state;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -23,7 +24,12 @@ import 'glamor/reset';
|
||||
import 'css/reset.css';
|
||||
import 'css/algolia.css';
|
||||
|
||||
class Template extends Component {
|
||||
type Props = {
|
||||
children: Function,
|
||||
location: Location,
|
||||
};
|
||||
|
||||
class Template extends Component<Props> {
|
||||
render() {
|
||||
const {children, location} = this.props;
|
||||
|
||||
|
||||
@@ -76,18 +76,20 @@ const AllBlogPosts = ({data}: Props) => (
|
||||
</Link>
|
||||
</h2>
|
||||
<MetaTitle>{node.fields.date}</MetaTitle>
|
||||
<div
|
||||
css={{
|
||||
color: colors.subtle,
|
||||
marginTop: -5,
|
||||
}}>
|
||||
by{' '}
|
||||
{toCommaSeparatedList(node.frontmatter.author, author => (
|
||||
<span key={author.frontmatter.name}>
|
||||
{author.frontmatter.name}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
{node.frontmatter.author ? (
|
||||
<div
|
||||
css={{
|
||||
color: colors.subtle,
|
||||
marginTop: -5,
|
||||
}}>
|
||||
by{' '}
|
||||
{toCommaSeparatedList(node.frontmatter.author, author => (
|
||||
<span key={author.frontmatter.name}>
|
||||
{author.frontmatter.name}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -19,7 +20,12 @@ import {createLinkDocs} from 'utils/createLink';
|
||||
import findSectionForPath from 'utils/findSectionForPath';
|
||||
import {sectionListDocs} from 'utils/sectionList';
|
||||
|
||||
const ErrorPage = ({data, location}) => (
|
||||
type Props = {
|
||||
data: Object,
|
||||
location: Location,
|
||||
};
|
||||
|
||||
const ErrorPage = ({data, location}: Props) => (
|
||||
<Flex
|
||||
direction="column"
|
||||
grow="1"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -12,7 +13,19 @@ import ExternalLinkSvg from 'templates/components/ExternalLinkSvg';
|
||||
import slugify from 'utils/slugify';
|
||||
import {colors, media} from 'theme';
|
||||
|
||||
const createLinkBlog = ({isActive, item, section}) => {
|
||||
import type {Node} from 'react';
|
||||
|
||||
type CreateLinkBaseProps = {
|
||||
isActive: boolean,
|
||||
item: Object,
|
||||
section: Object,
|
||||
};
|
||||
|
||||
const createLinkBlog = ({
|
||||
isActive,
|
||||
item,
|
||||
section,
|
||||
}: CreateLinkBaseProps): Node => {
|
||||
return (
|
||||
<Link css={[linkCss, isActive && activeLinkCss]} to={item.id}>
|
||||
{isActive && <span css={activeLinkBefore} />}
|
||||
@@ -21,7 +34,11 @@ const createLinkBlog = ({isActive, item, section}) => {
|
||||
);
|
||||
};
|
||||
|
||||
const createLinkCommunity = ({isActive, item, section}) => {
|
||||
const createLinkCommunity = ({
|
||||
isActive,
|
||||
item,
|
||||
section,
|
||||
}: CreateLinkBaseProps): Node => {
|
||||
if (item.href) {
|
||||
return (
|
||||
<a css={[linkCss]} href={item.href} target="_blank" rel="noopener">
|
||||
@@ -44,7 +61,11 @@ const createLinkCommunity = ({isActive, item, section}) => {
|
||||
});
|
||||
};
|
||||
|
||||
const createLinkDocs = ({isActive, item, section}) => {
|
||||
const createLinkDocs = ({
|
||||
isActive,
|
||||
item,
|
||||
section,
|
||||
}: CreateLinkBaseProps): Node => {
|
||||
return (
|
||||
<Link
|
||||
css={[linkCss, isActive && activeLinkCss]}
|
||||
@@ -55,7 +76,16 @@ const createLinkDocs = ({isActive, item, section}) => {
|
||||
);
|
||||
};
|
||||
|
||||
const createLinkTutorial = ({isActive, item, onLinkClick, section}) => {
|
||||
type CreateLinkTutorialProps = {
|
||||
onLinkClick: Function,
|
||||
} & CreateLinkBaseProps;
|
||||
|
||||
const createLinkTutorial = ({
|
||||
isActive,
|
||||
item,
|
||||
onLinkClick,
|
||||
section,
|
||||
}: CreateLinkTutorialProps): Node => {
|
||||
return (
|
||||
<Link
|
||||
css={[linkCss, isActive && activeLinkCss]}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import {urlRoot} from 'site-constants';
|
||||
|
||||
export default slug =>
|
||||
export default (slug: string): string | null =>
|
||||
slug == null ? null : `${urlRoot}/${slug.replace(/^\//, '')}`;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -12,7 +13,20 @@ import slugify from './slugify';
|
||||
* Helper method to locate the section containing the current URL/path.
|
||||
* This method specifically works with the nav_*.yml format.
|
||||
*/
|
||||
const findSectionForPath = (pathname, sections) => {
|
||||
|
||||
type Item = {
|
||||
id: string,
|
||||
subitems: Array<Item>,
|
||||
};
|
||||
|
||||
type Section = {
|
||||
items: Array<Item>,
|
||||
};
|
||||
|
||||
const findSectionForPath = (
|
||||
pathname: string,
|
||||
sections: Array<Section>,
|
||||
): Section | void => {
|
||||
let activeSection;
|
||||
const slugId = pathname.split('/').slice(-1)[0];
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import slugify from 'utils/slugify';
|
||||
|
||||
const toAnchor = (href = '') => {
|
||||
const toAnchor = (href: string = ''): string => {
|
||||
const index = href.indexOf('#');
|
||||
return index >= 0 ? href.substr(index) : '';
|
||||
};
|
||||
@@ -16,7 +17,12 @@ const toAnchor = (href = '') => {
|
||||
// TODO Account for redirect_from URLs somehow; they currently won't match.
|
||||
// This comment should not be true anymore since we're using 300 redirects
|
||||
|
||||
const isItemActive = (location, item) => {
|
||||
type Item = {
|
||||
id: string,
|
||||
href: string,
|
||||
};
|
||||
|
||||
const isItemActive = (location: Location, item: Item): boolean => {
|
||||
if (location.hash) {
|
||||
if (item.href) {
|
||||
return location.hash === toAnchor(item.href);
|
||||
|
||||
@@ -2,20 +2,24 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// $FlowExpectedError
|
||||
import navCommunity from '../../content/community/nav.yml';
|
||||
// $FlowExpectedError
|
||||
import navDocs from '../../content/docs/nav.yml';
|
||||
// $FlowExpectedError
|
||||
import navTutorial from '../../content/tutorial/nav.yml';
|
||||
|
||||
const sectionListDocs = navDocs.map(item => ({
|
||||
const sectionListDocs = navDocs.map((item: Object): Object => ({
|
||||
...item,
|
||||
directory: 'docs',
|
||||
}));
|
||||
|
||||
const sectionListCommunity = navCommunity.map(item => ({
|
||||
const sectionListCommunity = navCommunity.map((item: Object): Object => ({
|
||||
...item,
|
||||
directory: 'community',
|
||||
}));
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import slugify from 'slugify';
|
||||
|
||||
export default (string, directory) => {
|
||||
export default (string: string, directory?: string): string => {
|
||||
const filename = slugify(string) + '.html';
|
||||
|
||||
return directory ? `/${directory}/${filename}` : filename;
|
||||
|
||||
@@ -2,16 +2,22 @@
|
||||
* Copyright (c) 2013-present, Facebook, Inc.
|
||||
*
|
||||
* @emails react-core
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
const addString = (list, string) =>
|
||||
import type {Node} from 'react';
|
||||
|
||||
const addString = (list: Array<Node>, string: string) =>
|
||||
list.push(<span key={`${list.length}-${string}`}>{string}</span>);
|
||||
|
||||
const toCommaSeparatedList = (array, renderCallback) => {
|
||||
const toCommaSeparatedList = (
|
||||
array: Array<any>,
|
||||
renderCallback: Function,
|
||||
): Array<any> => {
|
||||
if (array.length <= 1) {
|
||||
return array.map(renderCallback);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user