@ -0,0 +1,4 @@ |
|||
{ |
|||
"presets": ['react', 'es2015', 'stage-1'], |
|||
"plugins": ['add-module-exports'] |
|||
} |
@ -0,0 +1,7 @@ |
|||
node_modules/* |
|||
|
|||
# Ignore markdown files and examples |
|||
content/* |
|||
|
|||
# Ignore built files |
|||
public/* |
@ -0,0 +1,7 @@ |
|||
{ |
|||
"plugins": [ |
|||
"prettier", |
|||
"react" |
|||
], |
|||
"parser": "babel-eslint", |
|||
} |
@ -0,0 +1,33 @@ |
|||
[ignore] |
|||
|
|||
<PROJECT_ROOT>/content/.* |
|||
<PROJECT_ROOT>/node_modules/.* |
|||
<PROJECT_ROOT>/public/.* |
|||
|
|||
[include] |
|||
|
|||
[libs] |
|||
./node_modules/fbjs/flow/lib/dev.js |
|||
./flow |
|||
|
|||
[options] |
|||
module.system=haste |
|||
|
|||
esproposal.class_static_fields=enable |
|||
esproposal.class_instance_fields=enable |
|||
unsafe.enable_getters_and_setters=true |
|||
|
|||
munge_underscores=false |
|||
|
|||
suppress_type=$FlowIssue |
|||
suppress_type=$FlowFixMe |
|||
suppress_type=$FixMe |
|||
suppress_type=$FlowExpectedError |
|||
|
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\) |
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*www[a-z,_]*\\)?)\\)?:? #[0-9]+ |
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy |
|||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError |
|||
|
|||
[version] |
|||
^0.56.0 |
@ -0,0 +1,4 @@ |
|||
.cache |
|||
.DS_STORE |
|||
node_modules |
|||
public |
@ -0,0 +1 @@ |
|||
8.4 |
@ -0,0 +1,393 @@ |
|||
Attribution 4.0 International |
|||
|
|||
======================================================================= |
|||
|
|||
Creative Commons Corporation ("Creative Commons") is not a law firm and |
|||
does not provide legal services or legal advice. Distribution of |
|||
Creative Commons public licenses does not create a lawyer-client or |
|||
other relationship. Creative Commons makes its licenses and related |
|||
information available on an "as-is" basis. Creative Commons gives no |
|||
warranties regarding its licenses, any material licensed under their |
|||
terms and conditions, or any related information. Creative Commons |
|||
disclaims all liability for damages resulting from their use to the |
|||
fullest extent possible. |
|||
|
|||
Using Creative Commons Public Licenses |
|||
|
|||
Creative Commons public licenses provide a standard set of terms and |
|||
conditions that creators and other rights holders may use to share |
|||
original works of authorship and other material subject to copyright |
|||
and certain other rights specified in the public license below. The |
|||
following considerations are for informational purposes only, are not |
|||
exhaustive, and do not form part of our licenses. |
|||
|
|||
Considerations for licensors: Our public licenses are |
|||
intended for use by those authorized to give the public |
|||
permission to use material in ways otherwise restricted by |
|||
copyright and certain other rights. Our licenses are |
|||
irrevocable. Licensors should read and understand the terms |
|||
and conditions of the license they choose before applying it. |
|||
Licensors should also secure all rights necessary before |
|||
applying our licenses so that the public can reuse the |
|||
material as expected. Licensors should clearly mark any |
|||
material not subject to the license. This includes other CC- |
|||
licensed material, or material used under an exception or |
|||
limitation to copyright. More considerations for licensors: |
|||
wiki.creativecommons.org/Considerations_for_licensors |
|||
|
|||
Considerations for the public: By using one of our public |
|||
licenses, a licensor grants the public permission to use the |
|||
licensed material under specified terms and conditions. If |
|||
the licensor's permission is not necessary for any reason--for |
|||
example, because of any applicable exception or limitation to |
|||
copyright--then that use is not regulated by the license. Our |
|||
licenses grant only permissions under copyright and certain |
|||
other rights that a licensor has authority to grant. Use of |
|||
the licensed material may still be restricted for other |
|||
reasons, including because others have copyright or other |
|||
rights in the material. A licensor may make special requests, |
|||
such as asking that all changes be marked or described. |
|||
Although not required by our licenses, you are encouraged to |
|||
respect those requests where reasonable. More_considerations |
|||
for the public: |
|||
wiki.creativecommons.org/Considerations_for_licensees |
|||
|
|||
======================================================================= |
|||
|
|||
Creative Commons Attribution 4.0 International Public License |
|||
|
|||
By exercising the Licensed Rights (defined below), You accept and agree |
|||
to be bound by the terms and conditions of this Creative Commons |
|||
Attribution 4.0 International Public License ("Public License"). To the |
|||
extent this Public License may be interpreted as a contract, You are |
|||
granted the Licensed Rights in consideration of Your acceptance of |
|||
these terms and conditions, and the Licensor grants You such rights in |
|||
consideration of benefits the Licensor receives from making the |
|||
Licensed Material available under these terms and conditions. |
|||
|
|||
|
|||
Section 1 -- Definitions. |
|||
|
|||
a. Adapted Material means material subject to Copyright and Similar |
|||
Rights that is derived from or based upon the Licensed Material |
|||
and in which the Licensed Material is translated, altered, |
|||
arranged, transformed, or otherwise modified in a manner requiring |
|||
permission under the Copyright and Similar Rights held by the |
|||
Licensor. For purposes of this Public License, where the Licensed |
|||
Material is a musical work, performance, or sound recording, |
|||
Adapted Material is always produced where the Licensed Material is |
|||
synched in timed relation with a moving image. |
|||
|
|||
b. Adapter's License means the license You apply to Your Copyright |
|||
and Similar Rights in Your contributions to Adapted Material in |
|||
accordance with the terms and conditions of this Public License. |
|||
|
|||
c. Copyright and Similar Rights means copyright and/or similar rights |
|||
closely related to copyright including, without limitation, |
|||
performance, broadcast, sound recording, and Sui Generis Database |
|||
Rights, without regard to how the rights are labeled or |
|||
categorized. For purposes of this Public License, the rights |
|||
specified in Section 2(b)(1)-(2) are not Copyright and Similar |
|||
Rights. |
|||
|
|||
d. Effective Technological Measures means those measures that, in the |
|||
absence of proper authority, may not be circumvented under laws |
|||
fulfilling obligations under Article 11 of the WIPO Copyright |
|||
Treaty adopted on December 20, 1996, and/or similar international |
|||
agreements. |
|||
|
|||
e. Exceptions and Limitations means fair use, fair dealing, and/or |
|||
any other exception or limitation to Copyright and Similar Rights |
|||
that applies to Your use of the Licensed Material. |
|||
|
|||
f. Licensed Material means the artistic or literary work, database, |
|||
or other material to which the Licensor applied this Public |
|||
License. |
|||
|
|||
g. Licensed Rights means the rights granted to You subject to the |
|||
terms and conditions of this Public License, which are limited to |
|||
all Copyright and Similar Rights that apply to Your use of the |
|||
Licensed Material and that the Licensor has authority to license. |
|||
|
|||
h. Licensor means the individual(s) or entity(ies) granting rights |
|||
under this Public License. |
|||
|
|||
i. Share means to provide material to the public by any means or |
|||
process that requires permission under the Licensed Rights, such |
|||
as reproduction, public display, public performance, distribution, |
|||
dissemination, communication, or importation, and to make material |
|||
available to the public including in ways that members of the |
|||
public may access the material from a place and at a time |
|||
individually chosen by them. |
|||
|
|||
j. Sui Generis Database Rights means rights other than copyright |
|||
resulting from Directive 96/9/EC of the European Parliament and of |
|||
the Council of 11 March 1996 on the legal protection of databases, |
|||
as amended and/or succeeded, as well as other essentially |
|||
equivalent rights anywhere in the world. |
|||
|
|||
k. You means the individual or entity exercising the Licensed Rights |
|||
under this Public License. Your has a corresponding meaning. |
|||
|
|||
|
|||
Section 2 -- Scope. |
|||
|
|||
a. License grant. |
|||
|
|||
1. Subject to the terms and conditions of this Public License, |
|||
the Licensor hereby grants You a worldwide, royalty-free, |
|||
non-sublicensable, non-exclusive, irrevocable license to |
|||
exercise the Licensed Rights in the Licensed Material to: |
|||
|
|||
a. reproduce and Share the Licensed Material, in whole or |
|||
in part; and |
|||
|
|||
b. produce, reproduce, and Share Adapted Material. |
|||
|
|||
2. Exceptions and Limitations. For the avoidance of doubt, where |
|||
Exceptions and Limitations apply to Your use, this Public |
|||
License does not apply, and You do not need to comply with |
|||
its terms and conditions. |
|||
|
|||
3. Term. The term of this Public License is specified in Section |
|||
6(a). |
|||
|
|||
4. Media and formats; technical modifications allowed. The |
|||
Licensor authorizes You to exercise the Licensed Rights in |
|||
all media and formats whether now known or hereafter created, |
|||
and to make technical modifications necessary to do so. The |
|||
Licensor waives and/or agrees not to assert any right or |
|||
authority to forbid You from making technical modifications |
|||
necessary to exercise the Licensed Rights, including |
|||
technical modifications necessary to circumvent Effective |
|||
Technological Measures. For purposes of this Public License, |
|||
simply making modifications authorized by this Section 2(a) |
|||
(4) never produces Adapted Material. |
|||
|
|||
5. Downstream recipients. |
|||
|
|||
a. Offer from the Licensor -- Licensed Material. Every |
|||
recipient of the Licensed Material automatically |
|||
receives an offer from the Licensor to exercise the |
|||
Licensed Rights under the terms and conditions of this |
|||
Public License. |
|||
|
|||
b. No downstream restrictions. You may not offer or impose |
|||
any additional or different terms or conditions on, or |
|||
apply any Effective Technological Measures to, the |
|||
Licensed Material if doing so restricts exercise of the |
|||
Licensed Rights by any recipient of the Licensed |
|||
Material. |
|||
|
|||
6. No endorsement. Nothing in this Public License constitutes or |
|||
may be construed as permission to assert or imply that You |
|||
are, or that Your use of the Licensed Material is, connected |
|||
with, or sponsored, endorsed, or granted official status by, |
|||
the Licensor or others designated to receive attribution as |
|||
provided in Section 3(a)(1)(A)(i). |
|||
|
|||
b. Other rights. |
|||
|
|||
1. Moral rights, such as the right of integrity, are not |
|||
licensed under this Public License, nor are publicity, |
|||
privacy, and/or other similar personality rights; however, to |
|||
the extent possible, the Licensor waives and/or agrees not to |
|||
assert any such rights held by the Licensor to the limited |
|||
extent necessary to allow You to exercise the Licensed |
|||
Rights, but not otherwise. |
|||
|
|||
2. Patent and trademark rights are not licensed under this |
|||
Public License. |
|||
|
|||
3. To the extent possible, the Licensor waives any right to |
|||
collect royalties from You for the exercise of the Licensed |
|||
Rights, whether directly or through a collecting society |
|||
under any voluntary or waivable statutory or compulsory |
|||
licensing scheme. In all other cases the Licensor expressly |
|||
reserves any right to collect such royalties. |
|||
|
|||
|
|||
Section 3 -- License Conditions. |
|||
|
|||
Your exercise of the Licensed Rights is expressly made subject to the |
|||
following conditions. |
|||
|
|||
a. Attribution. |
|||
|
|||
1. If You Share the Licensed Material (including in modified |
|||
form), You must: |
|||
|
|||
a. retain the following if it is supplied by the Licensor |
|||
with the Licensed Material: |
|||
|
|||
i. identification of the creator(s) of the Licensed |
|||
Material and any others designated to receive |
|||
attribution, in any reasonable manner requested by |
|||
the Licensor (including by pseudonym if |
|||
designated); |
|||
|
|||
ii. a copyright notice; |
|||
|
|||
iii. a notice that refers to this Public License; |
|||
|
|||
iv. a notice that refers to the disclaimer of |
|||
warranties; |
|||
|
|||
v. a URI or hyperlink to the Licensed Material to the |
|||
extent reasonably practicable; |
|||
|
|||
b. indicate if You modified the Licensed Material and |
|||
retain an indication of any previous modifications; and |
|||
|
|||
c. indicate the Licensed Material is licensed under this |
|||
Public License, and include the text of, or the URI or |
|||
hyperlink to, this Public License. |
|||
|
|||
2. You may satisfy the conditions in Section 3(a)(1) in any |
|||
reasonable manner based on the medium, means, and context in |
|||
which You Share the Licensed Material. For example, it may be |
|||
reasonable to satisfy the conditions by providing a URI or |
|||
hyperlink to a resource that includes the required |
|||
information. |
|||
|
|||
3. If requested by the Licensor, You must remove any of the |
|||
information required by Section 3(a)(1)(A) to the extent |
|||
reasonably practicable. |
|||
|
|||
4. If You Share Adapted Material You produce, the Adapter's |
|||
License You apply must not prevent recipients of the Adapted |
|||
Material from complying with this Public License. |
|||
|
|||
|
|||
Section 4 -- Sui Generis Database Rights. |
|||
|
|||
Where the Licensed Rights include Sui Generis Database Rights that |
|||
apply to Your use of the Licensed Material: |
|||
|
|||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right |
|||
to extract, reuse, reproduce, and Share all or a substantial |
|||
portion of the contents of the database; |
|||
|
|||
b. if You include all or a substantial portion of the database |
|||
contents in a database in which You have Sui Generis Database |
|||
Rights, then the database in which You have Sui Generis Database |
|||
Rights (but not its individual contents) is Adapted Material; and |
|||
|
|||
c. You must comply with the conditions in Section 3(a) if You Share |
|||
all or a substantial portion of the contents of the database. |
|||
|
|||
For the avoidance of doubt, this Section 4 supplements and does not |
|||
replace Your obligations under this Public License where the Licensed |
|||
Rights include other Copyright and Similar Rights. |
|||
|
|||
|
|||
Section 5 -- Disclaimer of Warranties and Limitation of Liability. |
|||
|
|||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE |
|||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS |
|||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF |
|||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, |
|||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, |
|||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, |
|||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT |
|||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT |
|||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. |
|||
|
|||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE |
|||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, |
|||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, |
|||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, |
|||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR |
|||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN |
|||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR |
|||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR |
|||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. |
|||
|
|||
c. The disclaimer of warranties and limitation of liability provided |
|||
above shall be interpreted in a manner that, to the extent |
|||
possible, most closely approximates an absolute disclaimer and |
|||
waiver of all liability. |
|||
|
|||
|
|||
Section 6 -- Term and Termination. |
|||
|
|||
a. This Public License applies for the term of the Copyright and |
|||
Similar Rights licensed here. However, if You fail to comply with |
|||
this Public License, then Your rights under this Public License |
|||
terminate automatically. |
|||
|
|||
b. Where Your right to use the Licensed Material has terminated under |
|||
Section 6(a), it reinstates: |
|||
|
|||
1. automatically as of the date the violation is cured, provided |
|||
it is cured within 30 days of Your discovery of the |
|||
violation; or |
|||
|
|||
2. upon express reinstatement by the Licensor. |
|||
|
|||
For the avoidance of doubt, this Section 6(b) does not affect any |
|||
right the Licensor may have to seek remedies for Your violations |
|||
of this Public License. |
|||
|
|||
c. For the avoidance of doubt, the Licensor may also offer the |
|||
Licensed Material under separate terms or conditions or stop |
|||
distributing the Licensed Material at any time; however, doing so |
|||
will not terminate this Public License. |
|||
|
|||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public |
|||
License. |
|||
|
|||
|
|||
Section 7 -- Other Terms and Conditions. |
|||
|
|||
a. The Licensor shall not be bound by any additional or different |
|||
terms or conditions communicated by You unless expressly agreed. |
|||
|
|||
b. Any arrangements, understandings, or agreements regarding the |
|||
Licensed Material not stated herein are separate from and |
|||
independent of the terms and conditions of this Public License. |
|||
|
|||
|
|||
Section 8 -- Interpretation. |
|||
|
|||
a. For the avoidance of doubt, this Public License does not, and |
|||
shall not be interpreted to, reduce, limit, restrict, or impose |
|||
conditions on any use of the Licensed Material that could lawfully |
|||
be made without permission under this Public License. |
|||
|
|||
b. To the extent possible, if any provision of this Public License is |
|||
deemed unenforceable, it shall be automatically reformed to the |
|||
minimum extent necessary to make it enforceable. If the provision |
|||
cannot be reformed, it shall be severed from this Public License |
|||
without affecting the enforceability of the remaining terms and |
|||
conditions. |
|||
|
|||
c. No term or condition of this Public License will be waived and no |
|||
failure to comply consented to unless expressly agreed to by the |
|||
Licensor. |
|||
|
|||
d. Nothing in this Public License constitutes or may be interpreted |
|||
as a limitation upon, or waiver of, any privileges and immunities |
|||
that apply to the Licensor or You, including from the legal |
|||
processes of any jurisdiction or authority. |
|||
|
|||
|
|||
======================================================================= |
|||
|
|||
Creative Commons is not a party to its public licenses. |
|||
Notwithstanding, Creative Commons may elect to apply one of its public |
|||
licenses to material it publishes and in those instances will be |
|||
considered the "Licensor." Except for the limited purpose of indicating |
|||
that material is shared under a Creative Commons public license or as |
|||
otherwise permitted by the Creative Commons policies published at |
|||
creativecommons.org/policies, Creative Commons does not authorize the |
|||
use of the trademark "Creative Commons" or any other trademark or logo |
|||
of Creative Commons without its prior written consent including, |
|||
without limitation, in connection with any unauthorized modifications |
|||
to any of its public licenses or any other arrangements, |
|||
understandings, or agreements concerning use of licensed material. For |
|||
the avoidance of doubt, this paragraph does not form part of the public |
|||
licenses. |
|||
|
|||
Creative Commons may be contacted at creativecommons.org. |
@ -0,0 +1,54 @@ |
|||
# reactjs.org |
|||
|
|||
## Getting started |
|||
|
|||
### Prerequisites |
|||
|
|||
1. Git |
|||
1. Node: install version 8.4 or greater |
|||
1. Yarn: `npm i -g yarn` to install it globally via NPM |
|||
1. A clone of the [reactjs.org repo](https://github.com/facebook/reactjs.org) on your local machine |
|||
1. A fork of the repo (for any contributions) |
|||
|
|||
### Installation |
|||
|
|||
1. `cd reactjs.org` to go into the project root |
|||
1. `yarn` to install the website's NPM dependencies |
|||
|
|||
### Running locally |
|||
|
|||
1. `yarn dev` to start the hot-reloading development server (powered by [Gatsby](https://www.gatsbyjs.org)) |
|||
1. `open http://localhost:8000` to open the site in your favorite browser |
|||
|
|||
## Contributing |
|||
|
|||
### Create a branch |
|||
|
|||
1. `git checkout master` from any folder in your local react repository |
|||
1. `git pull origin master` to ensure you have the latest main code |
|||
1. `git checkout -b the-name-of-my-branch` (replacing `the-name-of-my-branch` with a suitable name) to create a branch |
|||
|
|||
### Make the change |
|||
|
|||
1. Follow the "Running locally" instructions |
|||
1. Save the files and check in the browser |
|||
1. Changes to React components in `src` will hot-reload |
|||
1. Changes to markdown files in `content` will hot-reload |
|||
1. If working with plugins, you may need to remove the `.cache` directory and restart the server |
|||
|
|||
### Test the change |
|||
|
|||
1. If possible, test any visual changes in all latest versions of common browsers, on both desktop and mobile. |
|||
1. Run `yarn check-all` from the project root. (This will run Prettier, ESlint, and Flow.) |
|||
|
|||
### Push it |
|||
|
|||
1. `git add -A && git commit -m "My message"` (replacing `My message` with a commit message, such as `Fixed header logo on Android`) to stage and commit your changes |
|||
1. `git push my-fork-name the-name-of-my-branch` |
|||
1. Go to the [reactjs.org repo](https://github.com/facebook/reactjs.org) and you should see recently pushed branches. |
|||
1. Follow GitHub's instructions. |
|||
1. If possible include screenshots of visual changes. A Netlify build will also be automatically created once you make your PR so other people can see your change. |
|||
|
|||
## Troubleshooting |
|||
|
|||
- `yarn reset` to clear the local cache |
@ -0,0 +1,3 @@ |
|||
declare module 'hex2rgba' { |
|||
declare module.exports: (hex : string, alpha? : number) => string; |
|||
} |
@ -0,0 +1,142 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
module.exports = { |
|||
siteMetadata: { |
|||
title: 'React: A JavaScript library for building user interfaces', |
|||
siteUrl: 'https://reactjs.org', |
|||
rssFeedTitle: 'React', |
|||
rssFeedDescription: 'A JavaScript library for building user interfaces', |
|||
}, |
|||
mapping: { |
|||
'MarkdownRemark.frontmatter.author': 'AuthorYaml', |
|||
}, |
|||
plugins: [ |
|||
'gatsby-source-react-error-codes', |
|||
'gatsby-transformer-authors-yaml', |
|||
'gatsby-plugin-netlify', |
|||
'gatsby-plugin-glamor', |
|||
'gatsby-plugin-react-next', |
|||
'gatsby-plugin-twitter', |
|||
{ |
|||
resolve: 'gatsby-plugin-nprogress', |
|||
options: { |
|||
color: '#61dafb', |
|||
}, |
|||
}, |
|||
{ |
|||
resolve: 'gatsby-source-filesystem', |
|||
options: { |
|||
path: `${__dirname}/src/pages`, |
|||
name: 'pages', |
|||
}, |
|||
}, |
|||
{ |
|||
resolve: 'gatsby-source-filesystem', |
|||
options: { |
|||
name: 'packages', |
|||
path: `${__dirname}/content/`, |
|||
}, |
|||
}, |
|||
{ |
|||
resolve: 'gatsby-transformer-remark', |
|||
options: { |
|||
plugins: [ |
|||
'gatsby-remark-responsive-iframe', |
|||
{ |
|||
resolve: 'gatsby-remark-images', |
|||
options: { |
|||
maxWidth: 840, |
|||
}, |
|||
}, |
|||
'gatsby-remark-autolink-headers', |
|||
'gatsby-remark-use-jsx', |
|||
{ |
|||
resolve: 'gatsby-remark-prismjs', |
|||
options: { |
|||
classPrefix: 'gatsby-code-', |
|||
}, |
|||
}, |
|||
'gatsby-remark-copy-linked-files', |
|||
'gatsby-remark-smartypants', |
|||
], |
|||
}, |
|||
}, |
|||
'gatsby-transformer-sharp', |
|||
'gatsby-plugin-sharp', |
|||
{ |
|||
resolve: 'gatsby-plugin-google-analytics', |
|||
options: { |
|||
trackingId: 'UA-41298772-1', |
|||
}, |
|||
}, |
|||
{ |
|||
resolve: 'gatsby-plugin-feed', |
|||
options: { |
|||
query: ` |
|||
{ |
|||
site { |
|||
siteMetadata { |
|||
title: rssFeedTitle |
|||
description: rssFeedDescription |
|||
siteUrl |
|||
site_url: siteUrl |
|||
} |
|||
} |
|||
}`,
|
|||
feeds: [ |
|||
{ |
|||
serialize: ({query: {site, allMarkdownRemark}}) => { |
|||
return allMarkdownRemark.edges.map(edge => { |
|||
return Object.assign( |
|||
{}, |
|||
{ |
|||
title: edge.node.frontmatter.title, |
|||
description: edge.node.html, |
|||
date: require('moment')(edge.node.fields.date).format( |
|||
'MMMM DD, YYYY, h:mm A', |
|||
), |
|||
url: site.siteMetadata.siteUrl + edge.node.fields.slug, |
|||
guid: site.siteMetadata.siteUrl + edge.node.fields.slug, |
|||
}, |
|||
); |
|||
}); |
|||
}, |
|||
query: ` |
|||
{ |
|||
allMarkdownRemark |
|||
(limit: 10, |
|||
filter: {id: {regex: "/blog/"}}, |
|||
sort: {fields: [fields___date], |
|||
order: DESC}) { |
|||
edges { |
|||
node { |
|||
fields { |
|||
date |
|||
slug |
|||
} |
|||
frontmatter { |
|||
title |
|||
} |
|||
html |
|||
} |
|||
} |
|||
} |
|||
} |
|||
`,
|
|||
output: '/feed.xml', |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
'gatsby-plugin-react-helmet', |
|||
], |
|||
}; |
@ -0,0 +1,244 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
const {resolve} = require('path'); |
|||
const webpack = require('webpack'); |
|||
|
|||
exports.modifyWebpackConfig = ({config, stage}) => { |
|||
// See https://github.com/FormidableLabs/react-live/issues/5
|
|||
config.plugin('ignore', () => new webpack.IgnorePlugin(/^(xor|props)$/)); |
|||
|
|||
config.merge({ |
|||
resolve: { |
|||
root: resolve(__dirname, './src'), |
|||
extensions: ['', '.js', '.jsx', '.json'], |
|||
}, |
|||
}); |
|||
return config; |
|||
}; |
|||
|
|||
exports.createPages = async ({graphql, boundActionCreators}) => { |
|||
const {createPage, createRedirect} = boundActionCreators; |
|||
|
|||
const blogTemplate = resolve('./src/templates/blog.js'); |
|||
const communityTemplate = resolve('./src/templates/community.js'); |
|||
const docsTemplate = resolve('./src/templates/docs.js'); |
|||
const tutorialTemplate = resolve('./src/templates/tutorial.js'); |
|||
const homeTemplate = resolve('./src/templates/home.js'); |
|||
|
|||
const allMarkdown = await graphql( |
|||
` |
|||
{ |
|||
allMarkdownRemark(limit: 1000) { |
|||
edges { |
|||
node { |
|||
fields { |
|||
redirect |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
`,
|
|||
); |
|||
|
|||
if (allMarkdown.errors) { |
|||
console.error(allMarkdown.errors); |
|||
|
|||
throw Error(allMarkdown.errors); |
|||
} |
|||
|
|||
allMarkdown.data.allMarkdownRemark.edges.forEach(edge => { |
|||
const slug = edge.node.fields.slug; |
|||
|
|||
if (slug === '/index.html') { |
|||
createPage({ |
|||
path: '/', |
|||
component: homeTemplate, |
|||
context: { |
|||
slug, |
|||
}, |
|||
}); |
|||
} else if (slug === 'docs/error-decoder.html') { |
|||
// No-op so far as markdown templates go.
|
|||
// Error codes are managed by a page in src/pages
|
|||
// (which gets created by Gatsby during a separate phase).
|
|||
} else if ( |
|||
slug.includes('blog/') || |
|||
slug.includes('community/') || |
|||
slug.includes('contributing/') || |
|||
slug.includes('docs/') || |
|||
slug.includes('tutorial/') || |
|||
slug.includes('warnings/') |
|||
) { |
|||
let template; |
|||
if (slug.includes('blog/')) { |
|||
template = blogTemplate; |
|||
} else if (slug.includes('community/')) { |
|||
template = communityTemplate; |
|||
} else if ( |
|||
slug.includes('contributing/') || |
|||
slug.includes('docs/') || |
|||
slug.includes('warnings/') |
|||
) { |
|||
template = docsTemplate; |
|||
} else if (slug.includes('tutorial/')) { |
|||
template = tutorialTemplate; |
|||
} |
|||
|
|||
const createArticlePage = path => |
|||
createPage({ |
|||
path: path, |
|||
component: template, |
|||
context: { |
|||
slug, |
|||
}, |
|||
}); |
|||
|
|||
// Register primary URL.
|
|||
createArticlePage(slug); |
|||
|
|||
// Register redirects as well if the markdown specifies them.
|
|||
if (edge.node.fields.redirect) { |
|||
let redirect = JSON.parse(edge.node.fields.redirect); |
|||
if (!Array.isArray(redirect)) { |
|||
redirect = [redirect]; |
|||
} |
|||
|
|||
redirect.forEach(fromPath => |
|||
createRedirect({ |
|||
fromPath: `/${fromPath}`, |
|||
redirectInBrowser: true, |
|||
toPath: `/${slug}`, |
|||
}), |
|||
); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
const newestBlogEntry = await graphql( |
|||
` |
|||
{ |
|||
allMarkdownRemark( |
|||
limit: 1, |
|||
filter: { id: { regex: "/blog/" } } |
|||
sort: { fields: [fields___date], order: DESC } |
|||
) { |
|||
edges { |
|||
node { |
|||
fields { |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
`,
|
|||
); |
|||
const newestBlogNode = newestBlogEntry.data.allMarkdownRemark.edges[0].node; |
|||
|
|||
// Blog landing page should always show the most recent blog entry.
|
|||
createRedirect({ |
|||
fromPath: '/blog/', |
|||
redirectInBrowser: true, |
|||
toPath: newestBlogNode.fields.slug, |
|||
}); |
|||
}; |
|||
|
|||
// Parse date information out of blog post filename.
|
|||
const BLOG_POST_FILENAME_REGEX = /([0-9]+)\-([0-9]+)\-([0-9]+)\-(.+)\.md$/; |
|||
|
|||
// Add custom fields to MarkdownRemark nodes.
|
|||
exports.onCreateNode = ({node, boundActionCreators, getNode}) => { |
|||
const {createNodeField} = boundActionCreators; |
|||
|
|||
switch (node.internal.type) { |
|||
case 'MarkdownRemark': |
|||
const {permalink, redirect_from} = node.frontmatter; |
|||
const {relativePath} = getNode(node.parent); |
|||
|
|||
let slug = permalink; |
|||
|
|||
if (!slug) { |
|||
if (relativePath.includes('blog')) { |
|||
// Blog posts don't have embedded permalinks.
|
|||
// Their slugs follow a pattern: /blog/<year>/<month>/<day>/<slug>.html
|
|||
// The date portion comes from the file name: <date>-<title>.md
|
|||
const match = BLOG_POST_FILENAME_REGEX.exec(relativePath); |
|||
const year = match[1]; |
|||
const month = match[2]; |
|||
const day = match[3]; |
|||
const filename = match[4]; |
|||
|
|||
slug = `/blog/${year}/${month}/${day}/${filename}.html`; |
|||
|
|||
const date = new Date(year, month - 1, day); |
|||
|
|||
// Blog posts are sorted by date and display the date in their header.
|
|||
createNodeField({ |
|||
node, |
|||
name: 'date', |
|||
value: date.toJSON(), |
|||
}); |
|||
} |
|||
} |
|||
|
|||
if (!slug) { |
|||
slug = `/${relativePath.replace('.md', '.html')}`; |
|||
|
|||
// This should (probably) only happen for the index.md,
|
|||
// But let's log it in case it happens for other files also.
|
|||
console.warn( |
|||
`Warning: No slug found for "${relativePath}". Falling back to default "${slug}".`, |
|||
); |
|||
} |
|||
|
|||
// Used to generate URL to view this content.
|
|||
createNodeField({ |
|||
node, |
|||
name: 'slug', |
|||
value: slug, |
|||
}); |
|||
|
|||
// Used to generate a GitHub edit link.
|
|||
createNodeField({ |
|||
node, |
|||
name: 'path', |
|||
value: relativePath, |
|||
}); |
|||
|
|||
// Used by createPages() above to register redirects.
|
|||
createNodeField({ |
|||
node, |
|||
name: 'redirect', |
|||
value: redirect_from ? JSON.stringify(redirect_from) : '', |
|||
}); |
|||
return; |
|||
} |
|||
}; |
|||
|
|||
exports.onCreatePage = async ({page, boundActionCreators}) => { |
|||
const {createPage} = boundActionCreators; |
|||
|
|||
return new Promise(resolvePromise => { |
|||
// page.matchPath is a special key that's used for matching pages only on the client.
|
|||
// Explicitly wire up all error code wildcard matches to redirect to the error code page.
|
|||
if (page.path.includes('docs/error-decoder.html')) { |
|||
page.matchPath = 'docs/error-decoder:path?'; |
|||
page.context.slug = 'docs/error-decoder.html'; |
|||
|
|||
createPage(page); |
|||
} |
|||
|
|||
resolvePromise(); |
|||
}); |
|||
}; |
@ -0,0 +1,80 @@ |
|||
{ |
|||
"name": "react-website", |
|||
"description": "React website", |
|||
"version": "0.0.1", |
|||
"bugs": { |
|||
"url": "https://github.com/facebook/react" |
|||
}, |
|||
"resolutions": { |
|||
"gatsby/graphql": "0.10.5", |
|||
"gatsby/react": "16.0.0", |
|||
"gatsby/react-dom": "16.0.0" |
|||
}, |
|||
"dependencies": { |
|||
"@gaearon/react-live": "1.7.1-with-safari-fix", |
|||
"array-from": "^2.1.1", |
|||
"babel-eslint": "^8.0.1", |
|||
"eslint": "^4.8.0", |
|||
"eslint-config-react": "^1.1.7", |
|||
"eslint-plugin-flowtype": "^2.37.0", |
|||
"eslint-plugin-prettier": "^2.3.1", |
|||
"eslint-plugin-react": "^7.4.0", |
|||
"flow-bin": "^0.56.0", |
|||
"gatsby": "^1.9.9", |
|||
"gatsby-link": "^1.6.9", |
|||
"gatsby-plugin-feed": "^1.3.9", |
|||
"gatsby-plugin-glamor": "^1.6.4", |
|||
"gatsby-plugin-google-analytics": "^1.0.4", |
|||
"gatsby-plugin-manifest": "^1.0.4", |
|||
"gatsby-plugin-netlify": "^1.0.4", |
|||
"gatsby-plugin-nprogress": "^1.0.7", |
|||
"gatsby-plugin-react-helmet": "^1.0.3", |
|||
"gatsby-plugin-react-next": "^1.0.3", |
|||
"gatsby-plugin-sharp": "^1.6.2", |
|||
"gatsby-plugin-twitter": "^1.0.10", |
|||
"gatsby-remark-autolink-headers": "^1.4.4", |
|||
"gatsby-remark-copy-linked-files": "^1.5.2", |
|||
"gatsby-remark-images": "^1.5.11", |
|||
"gatsby-remark-prismjs": "^1.2.1", |
|||
"gatsby-remark-responsive-iframe": "^1.4.3", |
|||
"gatsby-remark-smartypants": "^1.4.3", |
|||
"gatsby-source-filesystem": "^1.4.4", |
|||
"gatsby-transformer-remark": "^1.7.2", |
|||
"gatsby-transformer-sharp": "^1.6.1", |
|||
"glamor": "^2.20.40", |
|||
"hex2rgba": "^0.0.1", |
|||
"prettier": "^1.7.4", |
|||
"remarkable": "^1.7.1", |
|||
"request-promise": "^4.2.2", |
|||
"rimraf": "^2.6.1", |
|||
"slugify": "^1.2.1", |
|||
"string.prototype.includes": "^1.0.0", |
|||
"string.prototype.repeat": "^0.2.0", |
|||
"unist-util-visit": "^1.1.3" |
|||
}, |
|||
"engines": { |
|||
"node": ">=8.4.0" |
|||
}, |
|||
"homepage": "https://reactjs.org/", |
|||
"keywords": [ |
|||
"gatsby" |
|||
], |
|||
"license": "MIT", |
|||
"main": "n/a", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/facebook/react.git" |
|||
}, |
|||
"scripts": { |
|||
"build": "gatsby build", |
|||
"check-all": "yarn prettier && yarn lint && yarn flow", |
|||
"dev": "gatsby develop -H 0.0.0.0", |
|||
"lint": "eslint .", |
|||
"netlify": "yarn install && yarn build", |
|||
"prettier": "prettier --no-bracket-spacing --single-quote --jsx-bracket-same-line --trailing-comma all --print-width 80 --parser flow --write 'src/**/*.js'", |
|||
"reset": "rimraf ./.cache" |
|||
}, |
|||
"devDependencies": { |
|||
"eslint-config-prettier": "^2.6.0" |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
const visit = require('unist-util-visit'); |
|||
|
|||
// Always treat JS blocks as JSX.
|
|||
// TODO: maybe we can just change it in Markdown in the future?
|
|||
module.exports = ({markdownAST}) => { |
|||
visit(markdownAST, `code`, node => { |
|||
if (typeof node.lang !== 'string') { |
|||
return; |
|||
} |
|||
if (node.lang.indexOf('jsx') === 0) { |
|||
// Already JSX (with optional line range).
|
|||
return; |
|||
} |
|||
// Turn JS into JSX, preserving the optional line range.
|
|||
if (node.lang.indexOf('js') === 0) { |
|||
node.lang = 'jsx' + node.lang.substring('js'.length); |
|||
} |
|||
if (node.lang.indexOf('javascript') === 0) { |
|||
node.lang = 'jsx' + node.lang.substring('javascript'.length); |
|||
} |
|||
}); |
|||
}; |
@ -0,0 +1,4 @@ |
|||
{ |
|||
"name": "gatsby-remark-use-jsx", |
|||
"version": "0.0.1" |
|||
} |
@ -0,0 +1,19 @@ |
|||
const request = require('request-promise'); |
|||
|
|||
const errorCodesUrl = 'http://raw.githubusercontent.com/facebook/react/master/scripts/error-codes/codes.json'; |
|||
|
|||
exports.sourceNodes = async ({ boundActionCreators }) => { |
|||
const { createNode } = boundActionCreators; |
|||
|
|||
const jsonString = await request(errorCodesUrl); |
|||
|
|||
createNode({ |
|||
id: 'error-codes', |
|||
children: [], |
|||
parent: 'ERRORS', |
|||
internal: { |
|||
type: 'ErrorCodesJson', |
|||
contentDigest: jsonString, |
|||
}, |
|||
}); |
|||
}; |
@ -0,0 +1,4 @@ |
|||
{ |
|||
"name": "gatsby-source-react-error-codes", |
|||
"version": "0.0.1" |
|||
} |
@ -0,0 +1,33 @@ |
|||
const readFileSync = require('fs').readFileSync; |
|||
const resolve = require('path').resolve; |
|||
const safeLoad = require('js-yaml').safeLoad; |
|||
|
|||
// TODO It would be nice to replace this plugin with gatsby-transformer-yaml
|
|||
// That plugin errors on some of the YML files in the docs folder though,
|
|||
// And doesn't currently support any options to whitelist/blacklist files.
|
|||
|
|||
// Reads authors.yml data into GraphQL.
|
|||
// This is auto-linked by gatsby-config.js to blog posts.
|
|||
exports.sourceNodes = ({graphql, boundActionCreators}) => { |
|||
const {createNode} = boundActionCreators; |
|||
|
|||
const path = resolve(__dirname, '../../content/authors.yml'); |
|||
const file = readFileSync(path, 'utf8'); |
|||
const authors = safeLoad(file); |
|||
|
|||
// authors.yml structure is {[username: string]: {name: string, url: string}}
|
|||
Object.keys(authors).forEach(username => { |
|||
const author = authors[username]; |
|||
|
|||
createNode({ |
|||
id: username, |
|||
children: [], |
|||
parent: 'AUTHORS', |
|||
internal: { |
|||
type: 'AuthorYaml', |
|||
contentDigest: JSON.stringify(author), |
|||
}, |
|||
frontmatter: author, |
|||
}); |
|||
}); |
|||
}; |
@ -0,0 +1,4 @@ |
|||
{ |
|||
"name": "gatsby-transformer-authors-yaml", |
|||
"version": "0.0.1" |
|||
} |
@ -0,0 +1,282 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React, {Component} from 'react'; |
|||
import ReactDOM from 'react-dom'; |
|||
import Remarkable from 'remarkable'; |
|||
// TODO: switch back to the upstream version of react-live
|
|||
// once https://github.com/FormidableLabs/react-live/issues/37 is fixed.
|
|||
import {LiveProvider, LiveEditor} from '@gaearon/react-live'; |
|||
import {colors, media} from 'theme'; |
|||
import MetaTitle from 'templates/components/MetaTitle'; |
|||
|
|||
const compile = code => |
|||
Babel.transform(code, {presets: ['es2015', 'react']}).code; // eslint-disable-line no-undef
|
|||
|
|||
class CodeEditor extends Component { |
|||
constructor(props, context) { |
|||
super(props, context); |
|||
|
|||
this.state = this._updateState(props.code); |
|||
} |
|||
|
|||
componentDidMount() { |
|||
// Initial render() will always be a no-op,
|
|||
// Because the mountNode ref won't exist yet.
|
|||
this._render(); |
|||
} |
|||
|
|||
componentDidUpdate(prevProps, prevState) { |
|||
if (prevState.compiled !== this.state.compiled) { |
|||
this._render(); |
|||
} |
|||
} |
|||
|
|||
render() { |
|||
const {children, code} = this.props; |
|||
const {error} = this.state; |
|||
|
|||
return ( |
|||
<LiveProvider code={code} mountStylesheet={false}> |
|||
<div |
|||
css={{ |
|||
[media.greaterThan('xlarge')]: { |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
}, |
|||
|
|||
[media.lessThan('large')]: { |
|||
display: 'block', |
|||
}, |
|||
}}> |
|||
{children && ( |
|||
<div |
|||
css={{ |
|||
flex: '0 0 33%', |
|||
|
|||
[media.lessThan('xlarge')]: { |
|||
marginBottom: 20, |
|||
}, |
|||
|
|||
'& h3': { |
|||
color: colors.dark, |
|||
maxWidth: '11em', |
|||
paddingTop: 0, |
|||
}, |
|||
|
|||
'& p': { |
|||
marginTop: 15, |
|||
marginRight: 40, |
|||
lineHeight: 1.7, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
marginTop: 25, |
|||
}, |
|||
}, |
|||
}}> |
|||
{children} |
|||
</div> |
|||
)} |
|||
|
|||
<div |
|||
css={{ |
|||
[media.greaterThan('medium')]: { |
|||
flex: '0 0 67%', |
|||
display: 'flex', |
|||
alignItems: 'stretch', |
|||
flexDirection: 'row', |
|||
}, |
|||
|
|||
[media.lessThan('small')]: { |
|||
display: 'block', |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
flex: '0 0 70%', |
|||
overflow: 'hidden', |
|||
borderRadius: '10px 0 0 10px', |
|||
|
|||
[media.lessThan('small')]: { |
|||
borderRadius: '10px 10px 0 0', |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
padding: '0px 10px', |
|||
background: colors.darker, |
|||
color: colors.white, |
|||
}}> |
|||
<MetaTitle onDark={true}>Live JSX Editor</MetaTitle> |
|||
</div> |
|||
<div |
|||
css={{ |
|||
height: '100%', |
|||
width: '100%', |
|||
borderRadius: '0', |
|||
marginTop: '0 !important', |
|||
marginLeft: '0 !important', |
|||
paddingLeft: '0 !important', |
|||
marginRight: '0 !important', |
|||
paddingRight: '0 !important', |
|||
|
|||
'& pre.prism-code[contenteditable]': { |
|||
maxHeight: '280px !important', |
|||
outline: 0, |
|||
}, |
|||
}} |
|||
className="gatsby-highlight"> |
|||
<LiveEditor onChange={this._onChange} /> |
|||
</div> |
|||
</div> |
|||
{error && ( |
|||
<div |
|||
css={{ |
|||
flex: '0 0 30%', |
|||
overflow: 'hidden', |
|||
border: `1px solid ${colors.error}`, |
|||
borderRadius: '0 10px 10px 0', |
|||
fontSize: 12, |
|||
lineHeight: 1.5, |
|||
|
|||
[media.lessThan('small')]: { |
|||
borderRadius: '0 0 10px 10px', |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
padding: '0px 10px', |
|||
background: colors.error, |
|||
color: colors.white, |
|||
}}> |
|||
<MetaTitle |
|||
cssProps={{ |
|||
color: colors.white, |
|||
}}> |
|||
Error |
|||
</MetaTitle> |
|||
</div> |
|||
<pre |
|||
css={{ |
|||
whiteSpace: 'pre-wrap', |
|||
wordBreak: 'break-word', |
|||
color: colors.error, |
|||
padding: 10, |
|||
}}> |
|||
{error.message} |
|||
</pre> |
|||
</div> |
|||
)} |
|||
{!error && ( |
|||
<div |
|||
css={{ |
|||
flex: '0 0 30%', |
|||
overflow: 'hidden', |
|||
border: `1px solid ${colors.divider}`, |
|||
borderRadius: '0 10px 10px 0', |
|||
|
|||
[media.lessThan('small')]: { |
|||
borderRadius: '0 0 10px 10px', |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
padding: '0 10px', |
|||
backgroundColor: colors.divider, |
|||
}}> |
|||
<MetaTitle>Result</MetaTitle> |
|||
</div> |
|||
<div |
|||
css={{ |
|||
padding: 10, |
|||
|
|||
'& input': { |
|||
width: '100%', |
|||
display: 'block', |
|||
border: '1px solid #ccc', // TODO
|
|||
padding: 5, |
|||
}, |
|||
|
|||
'& button': { |
|||
marginTop: 10, |
|||
padding: '5px 10px', |
|||
}, |
|||
|
|||
'& textarea': { |
|||
width: '100%', |
|||
marginTop: 10, |
|||
height: 60, |
|||
padding: 5, |
|||
}, |
|||
}} |
|||
ref={this._setMountRef} |
|||
/> |
|||
</div> |
|||
)} |
|||
</div> |
|||
</div> |
|||
</LiveProvider> |
|||
); |
|||
} |
|||
|
|||
_render() { |
|||
if (!this._mountNode) { |
|||
return; |
|||
} |
|||
|
|||
const {compiled} = this.state; |
|||
|
|||
try { |
|||
// Example code requires React, ReactDOM, and Remarkable to be within scope.
|
|||
// It also requires a "mountNode" variable for ReactDOM.render()
|
|||
// eslint-disable-next-line no-new-func
|
|||
new Function('React', 'ReactDOM', 'Remarkable', 'mountNode', compiled)( |
|||
React, |
|||
ReactDOM, |
|||
Remarkable, |
|||
this._mountNode, |
|||
); |
|||
} catch (error) { |
|||
console.error(error); |
|||
|
|||
this.setState({ |
|||
compiled: null, |
|||
error, |
|||
}); |
|||
} |
|||
} |
|||
|
|||
_setMountRef = ref => { |
|||
this._mountNode = ref; |
|||
}; |
|||
|
|||
_updateState(code) { |
|||
try { |
|||
return { |
|||
compiled: compile(code), |
|||
error: null, |
|||
}; |
|||
} catch (error) { |
|||
console.error(error); |
|||
|
|||
return { |
|||
compiled: null, |
|||
error, |
|||
}; |
|||
} |
|||
} |
|||
|
|||
_onChange = code => { |
|||
this.setState(this._updateState(code)); |
|||
}; |
|||
} |
|||
|
|||
export default CodeEditor; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import CodeEditor from './CodeEditor'; |
|||
|
|||
export default CodeEditor; |
@ -0,0 +1,40 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
|
|||
import {media} from 'theme'; |
|||
|
|||
/** |
|||
* This component wraps page content sections (eg header, footer, main). |
|||
* It provides consistent margin and max width behavior. |
|||
*/ |
|||
const Container = ({children}) => ( |
|||
<div |
|||
css={{ |
|||
paddingLeft: 20, |
|||
paddingRight: 20, |
|||
marginLeft: 'auto', |
|||
marginRight: 'auto', |
|||
|
|||
[media.greaterThan('medium')]: { |
|||
width: '90%', |
|||
}, |
|||
|
|||
[media.size('xxlarge')]: { |
|||
maxWidth: 1260, |
|||
}, |
|||
}}> |
|||
{children} |
|||
</div> |
|||
); |
|||
|
|||
export default Container; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from './Container'; |
|||
|
|||
export default Container; |
@ -0,0 +1,120 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React, {Component} from 'react'; |
|||
import PropTypes from 'prop-types'; |
|||
|
|||
function replaceArgs(msg, argList) { |
|||
let argIdx = 0; |
|||
return msg.replace(/%s/g, function() { |
|||
const arg = argList[argIdx++]; |
|||
return arg === undefined ? '[missing argument]' : arg; |
|||
}); |
|||
} |
|||
|
|||
function urlify(str) { |
|||
const urlRegex = /(https:\/\/fb\.me\/[a-z\-]+)/g; |
|||
|
|||
const segments = str.split(urlRegex); |
|||
|
|||
for (let i = 0; i < segments.length; i++) { |
|||
if (i % 2 === 1) { |
|||
segments[i] = ( |
|||
<a key={i} target="_blank" rel="noopener" href={segments[i]}> |
|||
{segments[i]} |
|||
</a> |
|||
); |
|||
} |
|||
} |
|||
|
|||
return segments; |
|||
} |
|||
|
|||
// ?invariant=123&args[]=foo&args[]=bar
|
|||
function parseQueryString(location) { |
|||
const rawQueryString = location.search.substring(1); |
|||
if (!rawQueryString) { |
|||
return null; |
|||
} |
|||
|
|||
let code = ''; |
|||
let args = []; |
|||
|
|||
const queries = rawQueryString.split('&'); |
|||
for (let i = 0; i < queries.length; i++) { |
|||
const query = decodeURIComponent(queries[i]); |
|||
if (query.indexOf('invariant=') === 0) { |
|||
code = query.slice(10); |
|||
} else if (query.indexOf('args[]=') === 0) { |
|||
args.push(query.slice(7)); |
|||
} |
|||
} |
|||
|
|||
return [code, args]; |
|||
} |
|||
|
|||
function ErrorResult(props) { |
|||
const code = props.code; |
|||
const errorMsg = props.msg; |
|||
|
|||
if (!code) { |
|||
return ( |
|||
<p> |
|||
When you encounter an error, you'll receive a link to this page for that |
|||
specific error and we'll show you the full error text. |
|||
</p> |
|||
); |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<p>The full text of the error you just encountered is:</p> |
|||
<code>{urlify(errorMsg)}</code> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
class ErrorDecoder extends Component { |
|||
constructor(...args) { |
|||
super(...args); |
|||
|
|||
this.state = { |
|||
code: null, |
|||
errorMsg: '', |
|||
}; |
|||
} |
|||
|
|||
componentWillMount() { |
|||
const {errorCodesString} = this.props; |
|||
const errorCodes = JSON.parse(errorCodesString); |
|||
const parseResult = parseQueryString(this.props.location); |
|||
if (parseResult != null) { |
|||
const [code, args] = parseResult; |
|||
if (errorCodes[code]) { |
|||
this.setState({ |
|||
code: code, |
|||
errorMsg: replaceArgs(errorCodes[code], args), |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
|
|||
render() { |
|||
return <ErrorResult code={this.state.code} msg={this.state.errorMsg} />; |
|||
} |
|||
} |
|||
|
|||
ErrorDecoder.propTypes = { |
|||
errorCodesString: PropTypes.string.isRequired, |
|||
location: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
export default ErrorDecoder; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import ErrorDecoder from './ErrorDecoder'; |
|||
|
|||
export default ErrorDecoder; |
@ -0,0 +1,45 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import {createElement} from 'glamor/react'; |
|||
|
|||
/** |
|||
* Convenience component for declaring a flexbox layout. |
|||
*/ |
|||
const Flex = ({ |
|||
basis = 'auto', |
|||
children, |
|||
direction = 'row', |
|||
grow = 0, |
|||
halign = 'flex-start', |
|||
shrink = 1, |
|||
type = 'div', |
|||
valign = 'flex-start', |
|||
...rest |
|||
}) => |
|||
createElement( |
|||
type, |
|||
{ |
|||
css: { |
|||
display: 'flex', |
|||
flexDirection: direction, |
|||
flexGrow: grow, |
|||
flexShrink: shrink, |
|||
flexBasis: basis, |
|||
justifyContent: direction === 'row' ? halign : valign, |
|||
alignItems: direction === 'row' ? valign : halign, |
|||
}, |
|||
...rest, |
|||
}, |
|||
children, |
|||
); |
|||
|
|||
export default Flex; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Flex from './Flex'; |
|||
|
|||
export default Flex; |
@ -0,0 +1,26 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
import {colors, fonts} from 'theme'; |
|||
|
|||
const Header = ({children}) => ( |
|||
<h1 |
|||
css={{ |
|||
color: colors.dark, |
|||
marginRight: '5%', |
|||
...fonts.header, |
|||
}}> |
|||
{children} |
|||
</h1> |
|||
); |
|||
|
|||
export default Header; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Header from './Header'; |
|||
|
|||
export default Header; |
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
import {colors} from 'theme'; |
|||
import ExternalLinkSvg from 'templates/components/ExternalLinkSvg'; |
|||
|
|||
const ExternalFooterLink = ({children, href, target, rel}) => ( |
|||
<a |
|||
css={{ |
|||
lineHeight: 2, |
|||
':hover': { |
|||
color: colors.brand, |
|||
}, |
|||
}} |
|||
href={href} |
|||
target={target} |
|||
rel={rel}> |
|||
{children} |
|||
<ExternalLinkSvg |
|||
cssProps={{ |
|||
verticalAlign: -2, |
|||
display: 'inline-block', |
|||
marginLeft: 5, |
|||
color: colors.subtle, |
|||
}} |
|||
/> |
|||
</a> |
|||
); |
|||
|
|||
export default ExternalFooterLink; |
@ -0,0 +1,193 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import ExternalFooterLink from './ExternalFooterLink'; |
|||
import FooterLink from './FooterLink'; |
|||
import FooterNav from './FooterNav'; |
|||
import MetaTitle from 'templates/components/MetaTitle'; |
|||
import React from 'react'; |
|||
import {colors, media} from 'theme'; |
|||
|
|||
import ossLogoPng from 'images/oss_logo.png'; |
|||
|
|||
const Footer = ({layoutHasSidebar = false}) => ( |
|||
<footer |
|||
css={{ |
|||
backgroundColor: colors.darker, |
|||
color: colors.white, |
|||
paddingTop: 10, |
|||
paddingBottom: 50, |
|||
|
|||
[media.size('sidebarFixed')]: { |
|||
paddingTop: 40, |
|||
}, |
|||
}}> |
|||
<Container> |
|||
<div |
|||
css={{ |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
flexWrap: 'wrap', |
|||
|
|||
[media.between('small', 'medium')]: { |
|||
paddingRight: layoutHasSidebar ? 240 : null, |
|||
}, |
|||
|
|||
[media.between('large', 'largerSidebar')]: { |
|||
paddingRight: layoutHasSidebar ? 280 : null, |
|||
}, |
|||
[media.between('largerSidebar', 'sidebarFixed', true)]: { |
|||
paddingRight: layoutHasSidebar ? 380 : null, |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
flexWrap: 'wrap', |
|||
display: 'flex', |
|||
|
|||
[media.lessThan('large')]: { |
|||
width: '100%', |
|||
}, |
|||
[media.greaterThan('xlarge')]: { |
|||
width: 'calc(100% / 3 * 2)', |
|||
paddingLeft: 40, |
|||
}, |
|||
}}> |
|||
<FooterNav layoutHasSidebar={layoutHasSidebar}> |
|||
<MetaTitle onDark={true}>Docs</MetaTitle> |
|||
<FooterLink to="/docs/hello-world.html">Quick Start</FooterLink> |
|||
<FooterLink to="/docs/thinking-in-react.html"> |
|||
Thinking in React |
|||
</FooterLink> |
|||
<FooterLink to="/tutorial/tutorial.html">Tutorial</FooterLink> |
|||
<FooterLink to="/docs/jsx-in-depth.html"> |
|||
Advanced Guides |
|||
</FooterLink> |
|||
</FooterNav> |
|||
<FooterNav layoutHasSidebar={layoutHasSidebar}> |
|||
<MetaTitle onDark={true}>Community</MetaTitle> |
|||
<ExternalFooterLink |
|||
href="http://stackoverflow.com/questions/tagged/reactjs" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Stack Overflow |
|||
</ExternalFooterLink> |
|||
<ExternalFooterLink |
|||
href="https://discuss.reactjs.org" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Discussion Forum |
|||
</ExternalFooterLink> |
|||
<ExternalFooterLink |
|||
href="https://discord.gg/0ZcbPKXt5bZjGY5n" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Reactiflux Chat |
|||
</ExternalFooterLink> |
|||
<ExternalFooterLink |
|||
href="https://www.facebook.com/react" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Facebook |
|||
</ExternalFooterLink> |
|||
<ExternalFooterLink |
|||
href="https://twitter.com/reactjs" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Twitter |
|||
</ExternalFooterLink> |
|||
</FooterNav> |
|||
<FooterNav layoutHasSidebar={layoutHasSidebar}> |
|||
<MetaTitle onDark={true}>Resources</MetaTitle> |
|||
<FooterLink to="/community/conferences.html"> |
|||
Conferences |
|||
</FooterLink> |
|||
<FooterLink to="/community/videos.html">Videos</FooterLink> |
|||
<ExternalFooterLink |
|||
href="https://github.com/facebook/react/wiki/Examples" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Examples |
|||
</ExternalFooterLink> |
|||
<ExternalFooterLink |
|||
href="https://github.com/facebook/react/wiki/Complementary-Tools" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
Complementary Tools |
|||
</ExternalFooterLink> |
|||
</FooterNav> |
|||
<FooterNav layoutHasSidebar={layoutHasSidebar}> |
|||
<MetaTitle onDark={true}>More</MetaTitle> |
|||
<FooterLink to="/blog/">Blog</FooterLink> |
|||
<ExternalFooterLink |
|||
href="https://github.com/facebook/react" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
GitHub |
|||
</ExternalFooterLink> |
|||
<ExternalFooterLink |
|||
href="http://facebook.github.io/react-native/" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
React Native |
|||
</ExternalFooterLink> |
|||
<FooterLink to="/acknowledgements.html"> |
|||
Acknowledgements |
|||
</FooterLink> |
|||
</FooterNav> |
|||
</div> |
|||
<section |
|||
css={{ |
|||
paddingTop: 40, |
|||
display: 'block !important', // Override 'Installation' <style> specifics
|
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
width: 'calc(100% / 3)', |
|||
order: -1, |
|||
}, |
|||
[media.greaterThan('large')]: { |
|||
order: -1, |
|||
width: layoutHasSidebar ? null : 'calc(100% / 3)', |
|||
}, |
|||
[media.lessThan('large')]: { |
|||
textAlign: 'center', |
|||
width: '100%', |
|||
paddingTop: 40, |
|||
}, |
|||
}}> |
|||
<a |
|||
href="https://code.facebook.com/projects/" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
<img |
|||
alt="Facebook Open Source" |
|||
css={{ |
|||
maxWidth: 160, |
|||
height: 'auto', |
|||
}} |
|||
src={ossLogoPng} |
|||
/> |
|||
</a> |
|||
<p |
|||
css={{ |
|||
color: colors.subtleOnDark, |
|||
paddingTop: 15, |
|||
}}> |
|||
Copyright © 2017 Facebook Inc. |
|||
</p> |
|||
</section> |
|||
</div> |
|||
</Container> |
|||
</footer> |
|||
); |
|||
|
|||
export default Footer; |
@ -0,0 +1,30 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Link from 'gatsby-link'; |
|||
import React from 'react'; |
|||
import {colors} from 'theme'; |
|||
|
|||
const FooterLink = ({children, target, to}) => ( |
|||
<Link |
|||
css={{ |
|||
lineHeight: 2, |
|||
':hover': { |
|||
color: colors.brand, |
|||
}, |
|||
}} |
|||
to={to} |
|||
target={target}> |
|||
{children} |
|||
</Link> |
|||
); |
|||
|
|||
export default FooterLink; |
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
import {media} from 'theme'; |
|||
|
|||
const FooterNav = ({children, title, layoutHasSidebar = false}) => ( |
|||
<div |
|||
css={{ |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
alignItems: 'flex-start', |
|||
width: '50%', |
|||
paddingTop: 40, |
|||
|
|||
[media.size('sidebarFixed')]: { |
|||
paddingTop: 0, |
|||
width: '25%', |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
display: 'inline-flex', |
|||
flexDirection: 'column', |
|||
}}> |
|||
{children} |
|||
</div> |
|||
</div> |
|||
); |
|||
|
|||
export default FooterNav; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Footer from './Footer'; |
|||
|
|||
export default Footer; |
@ -0,0 +1,251 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import HeaderLink from './HeaderLink'; |
|||
import Link from 'gatsby-link'; |
|||
import React from 'react'; |
|||
import {colors, fonts, media} from 'theme'; |
|||
import {version} from 'site-constants'; |
|||
import ExternalLinkSvg from 'templates/components/ExternalLinkSvg'; |
|||
|
|||
import logoSvg from 'icons/logo.svg'; |
|||
|
|||
const Header = ({location}) => ( |
|||
<header |
|||
css={{ |
|||
backgroundColor: colors.darker, |
|||
color: colors.white, |
|||
position: 'fixed', |
|||
zIndex: 1, |
|||
width: '100%', |
|||
top: 0, |
|||
left: 0, |
|||
}}> |
|||
<Container> |
|||
<div |
|||
css={{ |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
alignItems: 'center', |
|||
height: 60, |
|||
[media.between('small', 'large')]: { |
|||
height: 50, |
|||
}, |
|||
[media.lessThan('small')]: { |
|||
height: 40, |
|||
}, |
|||
}}> |
|||
<Link |
|||
css={{ |
|||
display: 'flex', |
|||
marginRight: 10, |
|||
height: '100%', |
|||
alignItems: 'center', |
|||
|
|||
[media.greaterThan('small')]: { |
|||
width: 'calc(100% / 6)', |
|||
}, |
|||
[media.lessThan('small')]: { |
|||
flex: '0 0 auto', |
|||
}, |
|||
}} |
|||
to="/"> |
|||
<img src={logoSvg} alt="" height="20" /> |
|||
<span |
|||
css={{ |
|||
color: colors.brand, |
|||
marginLeft: 10, |
|||
fontWeight: 700, |
|||
fontSize: 20, |
|||
lineHeight: '20px', |
|||
[media.lessThan('large')]: { |
|||
fontSize: 16, |
|||
marginTop: 1, |
|||
}, |
|||
[media.lessThan('small')]: { |
|||
// Visually hidden
|
|||
position: 'absolute', |
|||
overflow: 'hidden', |
|||
clip: 'rect(0 0 0 0)', |
|||
height: 1, |
|||
width: 1, |
|||
margin: -1, |
|||
padding: 0, |
|||
border: 0, |
|||
}, |
|||
}}> |
|||
React |
|||
</span> |
|||
</Link> |
|||
|
|||
<nav |
|||
css={{ |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
alignItems: 'stretch', |
|||
overflowX: 'auto', |
|||
overflowY: 'hidden', |
|||
WebkitOverflowScrolling: 'touch', |
|||
height: '100%', |
|||
width: '60%', |
|||
[media.size('xsmall')]: { |
|||
flexGrow: '1', |
|||
width: 'auto', |
|||
}, |
|||
[media.greaterThan('xlarge')]: { |
|||
width: null, |
|||
}, |
|||
[media.lessThan('small')]: { |
|||
maskImage: |
|||
'linear-gradient(to right, transparent, black 20px, black 90%, transparent)', |
|||
}, |
|||
}}> |
|||
<HeaderLink |
|||
isActive={location.pathname.includes('/docs/')} |
|||
title="Docs" |
|||
to="/docs/hello-world.html" |
|||
/> |
|||
<HeaderLink |
|||
isActive={location.pathname.includes('/tutorial/')} |
|||
title="Tutorial" |
|||
to="/tutorial/tutorial.html" |
|||
/> |
|||
<HeaderLink |
|||
isActive={location.pathname.includes('/community/')} |
|||
title="Community" |
|||
to="/community/support.html" |
|||
/> |
|||
<HeaderLink |
|||
isActive={location.pathname.includes('/blog')} |
|||
title="Blog" |
|||
to="/blog/" |
|||
/> |
|||
</nav> |
|||
|
|||
<form |
|||
css={{ |
|||
display: 'flex', |
|||
flex: '0 0 auto', |
|||
flexDirection: 'row', |
|||
alignItems: 'center', |
|||
paddingLeft: '0.5rem', |
|||
paddingRight: '0.5rem', |
|||
|
|||
[media.lessThan('small')]: { |
|||
justifyContent: 'flex-end', |
|||
}, |
|||
[media.lessThan('large')]: { |
|||
marginRight: 10, |
|||
}, |
|||
[media.between('small', 'medium')]: { |
|||
width: 'calc(100% / 3)', |
|||
}, |
|||
[media.between('medium', 'xlarge')]: { |
|||
width: 'calc(100% / 6)', |
|||
}, |
|||
[media.greaterThan('small')]: { |
|||
minWidth: 120, |
|||
}, |
|||
}}> |
|||
<input |
|||
css={{ |
|||
appearance: 'none', |
|||
background: 'transparent', |
|||
border: 0, |
|||
color: colors.white, |
|||
fontSize: 18, |
|||
fontWeight: 300, |
|||
fontFamily: 'inherit', |
|||
position: 'relative', |
|||
paddingLeft: '24px', |
|||
backgroundImage: 'url(/search.svg)', |
|||
backgroundSize: '16px 16px', |
|||
backgroundRepeat: 'no-repeat', |
|||
backgroundPositionY: 'center', |
|||
backgroundPositionX: 'left', |
|||
|
|||
[media.lessThan('large')]: { |
|||
fontSize: 16, |
|||
}, |
|||
[media.greaterThan('small')]: { |
|||
width: '100%', |
|||
}, |
|||
[media.lessThan('small')]: { |
|||
width: '16px', |
|||
transition: 'width 0.2s ease, padding 0.2s ease', |
|||
paddingLeft: '16px', |
|||
|
|||
':focus': { |
|||
paddingLeft: '24px', |
|||
width: '8rem', |
|||
outline: 'none', |
|||
}, |
|||
}, |
|||
}} |
|||
id="algolia-doc-search" |
|||
type="search" |
|||
placeholder="Search docs" |
|||
aria-label="Search docs" |
|||
/> |
|||
</form> |
|||
|
|||
<div |
|||
css={{ |
|||
[media.lessThan('medium')]: { |
|||
display: 'none', |
|||
}, |
|||
[media.greaterThan('large')]: { |
|||
width: 'calc(100% / 6)', |
|||
}, |
|||
}}> |
|||
<a |
|||
css={{ |
|||
padding: '5px 10px', |
|||
backgroundColor: colors.lighter, |
|||
borderRadius: 15, |
|||
whiteSpace: 'nowrap', |
|||
...fonts.small, |
|||
}} |
|||
href="https://github.com/facebook/react/releases" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
v{version} |
|||
</a> |
|||
<a |
|||
css={{ |
|||
padding: '5px 10px', |
|||
marginLeft: 10, |
|||
whiteSpace: 'nowrap', |
|||
...fonts.small, |
|||
':hover': { |
|||
color: colors.brand, |
|||
}, |
|||
}} |
|||
href="https://github.com/facebook/react/" |
|||
target="_blank" |
|||
rel="noopener"> |
|||
GitHub |
|||
<ExternalLinkSvg |
|||
cssProps={{ |
|||
marginLeft: 5, |
|||
verticalAlign: -2, |
|||
color: colors.subtle, |
|||
}} |
|||
/> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
</header> |
|||
); |
|||
|
|||
export default Header; |
@ -0,0 +1,74 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Link from 'gatsby-link'; |
|||
import React from 'react'; |
|||
import {colors, media} from 'theme'; |
|||
|
|||
const HeaderLink = ({isActive, title, to}) => ( |
|||
<Link css={[style, isActive && activeStyle]} to={to}> |
|||
{title} |
|||
{isActive && <span css={activeAfterStyle} />} |
|||
</Link> |
|||
); |
|||
|
|||
const style = { |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
alignItems: 'center', |
|||
color: colors.white, |
|||
transition: 'color 0.2s ease-out', |
|||
paddingLeft: 15, |
|||
paddingRight: 15, |
|||
fontWeight: 300, |
|||
|
|||
[media.size('xsmall')]: { |
|||
paddingLeft: 8, |
|||
paddingRight: 8, |
|||
}, |
|||
|
|||
[media.between('small', 'medium')]: { |
|||
paddingLeft: 10, |
|||
paddingRight: 10, |
|||
}, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
paddingLeft: 20, |
|||
paddingRight: 20, |
|||
fontSize: 18, |
|||
|
|||
':hover': { |
|||
color: colors.brand, |
|||
}, |
|||
}, |
|||
}; |
|||
|
|||
const activeStyle = { |
|||
color: colors.brand, |
|||
|
|||
[media.greaterThan('small')]: { |
|||
position: 'relative', |
|||
}, |
|||
}; |
|||
|
|||
const activeAfterStyle = { |
|||
[media.greaterThan('small')]: { |
|||
position: 'absolute', |
|||
bottom: -1, |
|||
height: 4, |
|||
background: colors.brand, |
|||
left: 0, |
|||
right: 0, |
|||
zIndex: 1, |
|||
}, |
|||
}; |
|||
|
|||
export default HeaderLink; |
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
|
|||
const SearchSvg = () => ( |
|||
<svg |
|||
alt="Search" |
|||
height="16" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
viewBox="0 0 16 16"> |
|||
<title>Search</title> |
|||
<path |
|||
d={` |
|||
M6.02945,10.20327a4.17382,4.17382,0,1,1,4.17382-4.17382A4.15609,4.15609, |
|||
0,0,1,6.02945,10.20327Zm9.69195,4.2199L10.8989,9.59979A5.88021,5.88021, |
|||
0,0,0,12.058,6.02856,6.00467,6.00467,0,1,0,9.59979,10.8989l4.82338, |
|||
4.82338a.89729.89729,0,0,0,1.29912,0,.89749.89749,0,0,0-.00087-1.29909Z |
|||
`}
|
|||
fill="currentColor" |
|||
/> |
|||
</svg> |
|||
); |
|||
|
|||
export default SearchSvg; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Header from './Header'; |
|||
|
|||
export default Header; |
@ -0,0 +1,43 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Flex from 'components/Flex'; |
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import {colors, fonts, media} from 'theme'; |
|||
|
|||
const MarkdownHeader = ({title}) => ( |
|||
<Flex type="header" halign="space-between" valign="baseline"> |
|||
<h1 |
|||
css={{ |
|||
color: colors.dark, |
|||
marginBottom: 0, |
|||
marginTop: 40, |
|||
...fonts.header, |
|||
|
|||
[media.size('medium')]: { |
|||
marginTop: 60, |
|||
}, |
|||
|
|||
[media.greaterThan('large')]: { |
|||
marginTop: 80, |
|||
}, |
|||
}}> |
|||
{title} |
|||
</h1> |
|||
</Flex> |
|||
); |
|||
|
|||
MarkdownHeader.propTypes = { |
|||
title: PropTypes.string.isRequired, |
|||
}; |
|||
|
|||
export default MarkdownHeader; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import MarkdownHeader from './MarkdownHeader'; |
|||
|
|||
export default MarkdownHeader; |
@ -0,0 +1,140 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import Flex from 'components/Flex'; |
|||
import MarkdownHeader from 'components/MarkdownHeader'; |
|||
import NavigationFooter from 'templates/components/NavigationFooter'; |
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import StickyResponsiveSidebar from 'components/StickyResponsiveSidebar'; |
|||
import TitleAndMetaTags from 'components/TitleAndMetaTags'; |
|||
import findSectionForPath from 'utils/findSectionForPath'; |
|||
import toCommaSeparatedList from 'utils/toCommaSeparatedList'; |
|||
import {sharedStyles} from 'theme'; |
|||
import createOgUrl from 'utils/createOgUrl'; |
|||
|
|||
const MarkdownPage = ({ |
|||
authors, |
|||
createLink, |
|||
date, |
|||
ogDescription, |
|||
location, |
|||
markdownRemark, |
|||
sectionList, |
|||
titlePostfix = '', |
|||
}) => { |
|||
const hasAuthors = authors.length > 0; |
|||
const titlePrefix = markdownRemark.frontmatter.title || ''; |
|||
|
|||
return ( |
|||
<Flex |
|||
direction="column" |
|||
grow="1" |
|||
shrink="0" |
|||
halign="stretch" |
|||
css={{ |
|||
width: '100%', |
|||
flex: '1 0 auto', |
|||
position: 'relative', |
|||
zIndex: 0, |
|||
}}> |
|||
<TitleAndMetaTags |
|||
ogDescription={ogDescription} |
|||
ogUrl={createOgUrl(markdownRemark.fields.slug)} |
|||
title={`${titlePrefix}${titlePostfix}`} |
|||
/> |
|||
<div css={{flex: '1 0 auto'}}> |
|||
<Container> |
|||
<div css={sharedStyles.articleLayout.container}> |
|||
<Flex type="article" direction="column" grow="1" halign="stretch"> |
|||
<MarkdownHeader title={titlePrefix} /> |
|||
|
|||
{(date || hasAuthors) && ( |
|||
<div css={{marginTop: 15}}> |
|||
{date}{' '} |
|||
{hasAuthors && ( |
|||
<span> |
|||
by{' '} |
|||
{toCommaSeparatedList(authors, author => ( |
|||
<a |
|||
css={sharedStyles.link} |
|||
href={author.frontmatter.url} |
|||
key={author.frontmatter.name}> |
|||
{author.frontmatter.name} |
|||
</a> |
|||
))} |
|||
</span> |
|||
)} |
|||
</div> |
|||
)} |
|||
|
|||
<div css={sharedStyles.articleLayout.content}> |
|||
<div |
|||
css={[sharedStyles.markdown]} |
|||
dangerouslySetInnerHTML={{__html: markdownRemark.html}} |
|||
/> |
|||
|
|||
{markdownRemark.fields.path && ( |
|||
<div css={{marginTop: 80}}> |
|||
<a |
|||
css={sharedStyles.articleLayout.editLink} |
|||
href={`https://github.com/facebook/react/tree/master/docs/${markdownRemark |
|||
.fields.path}`}>
|
|||
Edit this page |
|||
</a> |
|||
</div> |
|||
)} |
|||
</div> |
|||
</Flex> |
|||
|
|||
<div css={sharedStyles.articleLayout.sidebar}> |
|||
<StickyResponsiveSidebar |
|||
createLink={createLink} |
|||
defaultActiveSection={findSectionForPath( |
|||
location.pathname, |
|||
sectionList, |
|||
)} |
|||
location={location} |
|||
sectionList={sectionList} |
|||
/> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
</div> |
|||
|
|||
{/* TODO Read prev/next from index map, not this way */} |
|||
{(markdownRemark.frontmatter.next || markdownRemark.frontmatter.prev) && ( |
|||
<NavigationFooter |
|||
location={location} |
|||
next={markdownRemark.frontmatter.next} |
|||
prev={markdownRemark.frontmatter.prev} |
|||
/> |
|||
)} |
|||
</Flex> |
|||
); |
|||
}; |
|||
|
|||
MarkdownPage.defaultProps = { |
|||
authors: [], |
|||
}; |
|||
|
|||
// TODO Better types
|
|||
MarkdownPage.propTypes = { |
|||
authors: PropTypes.array.isRequired, |
|||
createLink: PropTypes.func.isRequired, |
|||
date: PropTypes.string, |
|||
location: PropTypes.object.isRequired, |
|||
markdownRemark: PropTypes.object.isRequired, |
|||
sectionList: PropTypes.array.isRequired, |
|||
}; |
|||
|
|||
export default MarkdownPage; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import MarkdownPage from './MarkdownPage'; |
|||
|
|||
export default MarkdownPage; |
@ -0,0 +1,199 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import {Component, React} 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); |
|||
|
|||
this.state = { |
|||
open: false, |
|||
}; |
|||
this._openNavMenu = this._openNavMenu.bind(this); |
|||
this._closeNavMenu = this._closeNavMenu.bind(this); |
|||
} |
|||
|
|||
_openNavMenu() { |
|||
this.setState({open: !this.state.open}); |
|||
} |
|||
|
|||
_closeNavMenu() { |
|||
this.setState({open: false}); |
|||
} |
|||
|
|||
render() { |
|||
const {open} = this.state; |
|||
const smallScreenSidebarStyles = { |
|||
top: 0, |
|||
left: 0, |
|||
bottom: 0, |
|||
right: 0, |
|||
position: 'fixed', |
|||
backgroundColor: colors.white, |
|||
zIndex: 2, |
|||
height: '100vh', |
|||
overflowY: 'auto', |
|||
WebkitOverflowScrolling: 'touch', |
|||
pointerEvents: open ? 'auto' : 'none', |
|||
}; |
|||
|
|||
const smallScreenBottomBarStyles = { |
|||
display: 'inline-block', |
|||
}; |
|||
|
|||
const iconOffset = open ? 8 : -4; |
|||
const menuOpacity = open ? 1 : 0; |
|||
const menuOffset = open ? 0 : 40; |
|||
|
|||
// TODO: role and aria props for 'close' button?
|
|||
return ( |
|||
<div> |
|||
<div |
|||
style={{ |
|||
opacity: menuOpacity, |
|||
transition: 'opacity 0.5s ease', |
|||
}} |
|||
css={{ |
|||
[media.lessThan('small')]: smallScreenSidebarStyles, |
|||
|
|||
[media.greaterThan('medium')]: { |
|||
marginRight: -999, |
|||
paddingRight: 999, |
|||
backgroundColor: '#f7f7f7', |
|||
}, |
|||
|
|||
[media.between('medium', 'sidebarFixed', true)]: { |
|||
position: 'fixed', |
|||
zIndex: 2, |
|||
height: '100%', |
|||
}, |
|||
|
|||
[media.greaterThan('small')]: { |
|||
position: 'fixed', |
|||
zIndex: 2, |
|||
height: 'calc(100vh - 60px)', |
|||
overflowY: 'auto', |
|||
WebkitOverflowScrolling: 'touch', |
|||
marginRight: -999, |
|||
paddingRight: 999, |
|||
backgroundColor: '#f7f7f7', |
|||
opacity: '1 !important', |
|||
}, |
|||
|
|||
[media.size('small')]: { |
|||
height: 'calc(100vh - 40px)', |
|||
}, |
|||
|
|||
[media.between('medium', 'large')]: { |
|||
height: 'calc(100vh - 50px)', |
|||
}, |
|||
|
|||
[media.greaterThan('sidebarFixed')]: { |
|||
borderLeft: '1px solid #ececec', |
|||
}, |
|||
}}> |
|||
<div |
|||
style={{ |
|||
transform: `translate(0px, ${menuOffset}px)`, |
|||
transition: 'transform 0.5s ease', |
|||
}} |
|||
css={{ |
|||
marginTop: 60, |
|||
|
|||
[media.size('xsmall')]: { |
|||
marginTop: 40, |
|||
}, |
|||
|
|||
[media.between('small', 'medium')]: { |
|||
marginTop: 0, |
|||
}, |
|||
|
|||
[media.between('medium', 'large')]: { |
|||
marginTop: 50, |
|||
}, |
|||
|
|||
[media.greaterThan('small')]: { |
|||
tranform: 'none !important', |
|||
}, |
|||
}}> |
|||
<Sidebar closeParentMenu={this._closeNavMenu} {...this.props} /> |
|||
</div> |
|||
</div> |
|||
<div |
|||
css={{ |
|||
backgroundColor: colors.darker, |
|||
bottom: 44, // iOS Safari's inert "bottom 44px"
|
|||
color: colors.brand, |
|||
display: 'none', // gets overriden at small screen sizes
|
|||
cursor: 'pointer', |
|||
position: 'fixed', |
|||
right: 20, |
|||
zIndex: 3, |
|||
borderRadius: '50%', |
|||
border: '1px solid rgba(255, 255, 255, 0.1)', |
|||
boxShadow: '0 0 20px rgba(0, 0, 0, 0.3)', |
|||
[media.lessThan('small')]: smallScreenBottomBarStyles, |
|||
}} |
|||
onClick={this._openNavMenu}> |
|||
<Container> |
|||
<div |
|||
css={{ |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
alignItems: 'center', |
|||
height: 60, |
|||
[media.between('medium', 'large')]: { |
|||
height: 50, |
|||
}, |
|||
[media.lessThan('small')]: { |
|||
height: 60, |
|||
overflow: 'hidden', |
|||
alignItems: 'flex-start', |
|||
}, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
width: 20, |
|||
height: 20, |
|||
alignSelf: 'center', |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
color: colors.brand, |
|||
}}> |
|||
<ChevronSvg |
|||
size={15} |
|||
cssProps={{ |
|||
transform: `translate(2px, ${iconOffset}px) rotate(180deg)`, |
|||
transition: 'transform 0.2s ease', |
|||
}} |
|||
/> |
|||
<ChevronSvg |
|||
size={15} |
|||
cssProps={{ |
|||
transform: `translate(2px, ${0 - iconOffset}px)`, |
|||
transition: 'transform 0.2s ease', |
|||
}} |
|||
/> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
</div> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default StickyResponsiveSidebar; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import StickyResponsiveSidebar from './StickyResponsiveSidebar'; |
|||
|
|||
export default StickyResponsiveSidebar; |
@ -0,0 +1,33 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Helmet from 'react-helmet'; |
|||
import React from 'react'; |
|||
|
|||
const defaultDescription = 'A JavaScript library for building user interfaces'; |
|||
|
|||
const TitleAndMetaTags = ({title, ogDescription, ogUrl}) => { |
|||
return ( |
|||
<Helmet title={title}> |
|||
<meta property="og:title" content={title} /> |
|||
<meta property="og:type" content="website" /> |
|||
{ogUrl && <meta property="og:url" content={ogUrl} />} |
|||
<meta property="og:image" content="/logo-og.png" /> |
|||
<meta |
|||
property="og:description" |
|||
content={ogDescription || defaultDescription} |
|||
/> |
|||
<meta property="fb:app_id" content="623268441017527" /> |
|||
</Helmet> |
|||
); |
|||
}; |
|||
|
|||
export default TitleAndMetaTags; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import TitleAndMetaTags from './TitleAndMetaTags'; |
|||
|
|||
export default TitleAndMetaTags; |
@ -0,0 +1,42 @@ |
|||
html { |
|||
box-sizing: border-box; |
|||
font-family: -apple-system, BlinkMacSystemFont, |
|||
"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", |
|||
"Fira Sans", "Droid Sans", "Helvetica Neue", |
|||
sans-serif; |
|||
font-weight: 400; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
} |
|||
|
|||
body { |
|||
overflow-x: hidden; |
|||
position: relative; |
|||
} |
|||
|
|||
* { |
|||
margin: 0; |
|||
padding: 0; |
|||
} |
|||
|
|||
*, *::before, *::after { |
|||
box-sizing: inherit; |
|||
} |
|||
|
|||
a { |
|||
color: inherit; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
ul, ol { |
|||
list-style: none; |
|||
} |
|||
|
|||
img { |
|||
display: inline-block; |
|||
vertical-align: top; |
|||
} |
|||
|
|||
pre, code { |
|||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; |
|||
} |
@ -0,0 +1,66 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React, {Component} from 'react'; |
|||
|
|||
let stylesStr; |
|||
if (process.env.NODE_ENV === `production`) { |
|||
try { |
|||
stylesStr = require(`!raw-loader!../public/styles.css`); |
|||
} catch (e) { |
|||
console.log(e); |
|||
} |
|||
} |
|||
|
|||
const JS_NPM_URLS = [ |
|||
'//unpkg.com/docsearch.js@2.4.1/dist/cdn/docsearch.min.js', |
|||
'//unpkg.com/babel-standalone@6.26.0/babel.min.js', |
|||
]; |
|||
|
|||
export default class HTML extends Component { |
|||
render() { |
|||
let css; |
|||
if (process.env.NODE_ENV === 'production') { |
|||
css = ( |
|||
<style |
|||
id="gatsby-inlined-css" |
|||
dangerouslySetInnerHTML={{__html: stylesStr}} |
|||
/> |
|||
); |
|||
} |
|||
|
|||
const js = JS_NPM_URLS.map(url => <script key={url} src={url} />); |
|||
|
|||
return ( |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charSet="utf-8" /> |
|||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" /> |
|||
<meta |
|||
name="viewport" |
|||
content="width=device-width, initial-scale=1.0" |
|||
/> |
|||
<link rel="icon" href="/favicon.ico" /> |
|||
{this.props.headComponents} |
|||
{js} |
|||
{css} |
|||
</head> |
|||
<body> |
|||
<div |
|||
id="___gatsby" |
|||
dangerouslySetInnerHTML={{__html: this.props.body}} |
|||
/> |
|||
{this.props.postBodyComponents} |
|||
</body> |
|||
</html> |
|||
); |
|||
} |
|||
} |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.3 KiB |
@ -0,0 +1 @@ |
|||
var foo = 'bar'; |
@ -0,0 +1,85 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
// Polyfills for IE
|
|||
import 'array-from'; |
|||
import 'string.prototype.includes'; |
|||
import 'string.prototype.repeat'; |
|||
|
|||
import React, {Component} from 'react'; |
|||
import Flex from 'components/Flex'; |
|||
import Footer from 'components/LayoutFooter'; |
|||
import Header from 'components/LayoutHeader'; |
|||
import {media} from 'theme'; |
|||
|
|||
// Import global styles
|
|||
import '../prism-styles'; |
|||
import 'glamor/reset'; |
|||
import 'css/reset.css'; |
|||
import 'css/algolia.css'; |
|||
|
|||
class Template extends Component { |
|||
componentDidMount() { |
|||
// Initialize Algolia search.
|
|||
// TODO Is this expensive? Should it be deferred until a user is about to search?
|
|||
// eslint-disable-next-line no-undef
|
|||
docsearch({ |
|||
apiKey: '36221914cce388c46d0420343e0bb32e', |
|||
indexName: 'react', |
|||
inputSelector: '#algolia-doc-search', |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
const {children, location} = this.props; |
|||
|
|||
// TODO - is there a better way to check if we need we have a sidebar?
|
|||
let layoutHasSidebar = false; |
|||
if ( |
|||
location.pathname.match( |
|||
/^\/(docs|tutorial|community|blog|contributing|warnings)/, |
|||
) |
|||
) { |
|||
layoutHasSidebar = true; |
|||
} |
|||
|
|||
return ( |
|||
<div |
|||
css={{ |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
minHeight: 'calc(100vh - 40px)', |
|||
}}> |
|||
<Header location={location} /> |
|||
<Flex |
|||
direction="column" |
|||
shrink="0" |
|||
grow="1" |
|||
valign="stretch" |
|||
css={{ |
|||
flex: '1 0 auto', |
|||
marginTop: 60, |
|||
[media.between('medium', 'large')]: { |
|||
marginTop: 50, |
|||
}, |
|||
[media.lessThan('medium')]: { |
|||
marginTop: 40, |
|||
}, |
|||
}}> |
|||
{children()} |
|||
</Flex> |
|||
<Footer layoutHasSidebar={layoutHasSidebar} /> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default Template; |
@ -0,0 +1,34 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import Header from 'components/Header'; |
|||
import React from 'react'; |
|||
import {sharedStyles} from 'theme'; |
|||
|
|||
const PageNotFound = () => ( |
|||
<Container> |
|||
<div css={sharedStyles.articleLayout.container}> |
|||
<div css={sharedStyles.articleLayout.content}> |
|||
<Header>Page Not Found</Header> |
|||
<div css={sharedStyles.markdown}> |
|||
<p>We couldn't find what you were looking for.</p> |
|||
<p> |
|||
Please contact the owner of the site that linked you to the original |
|||
URL and let them know their link is broken. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
); |
|||
|
|||
export default PageNotFound; |
@ -0,0 +1,88 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import Header from 'components/Header'; |
|||
import React from 'react'; |
|||
import {sharedStyles} from 'theme'; |
|||
|
|||
import names from '../../content/acknowledgements.yml'; |
|||
|
|||
const Acknowlegements = ({data, location}) => ( |
|||
<Container> |
|||
<div css={sharedStyles.articleLayout.container}> |
|||
<div css={sharedStyles.articleLayout.content}> |
|||
<Header>Acknowledgements</Header> |
|||
|
|||
<div css={sharedStyles.markdown}> |
|||
<p>We'd like to thank all of our contributors:</p> |
|||
|
|||
<ul |
|||
css={{ |
|||
display: 'flex', |
|||
flexWrap: 'wrap', |
|||
}}> |
|||
{names.map((name, index) => ( |
|||
<li |
|||
css={{ |
|||
flex: '1 0 200px', |
|||
}} |
|||
key={index}> |
|||
{name} |
|||
</li> |
|||
))} |
|||
</ul> |
|||
|
|||
<p>In addition, we're grateful to</p> |
|||
<ul> |
|||
<li> |
|||
<a href="https://github.com/jeffbski">Jeff Barczewski</a> for |
|||
allowing us to use the{' '} |
|||
<a href="https://www.npmjs.com/package/react">react</a> package |
|||
name on npm. |
|||
</li> |
|||
<li> |
|||
<a href="http://christopheraue.net/">Christopher Aue</a> for |
|||
letting us use the <a href="http://reactjs.com/"> |
|||
reactjs.com |
|||
</a>{' '} |
|||
domain name and the{' '} |
|||
<a href="https://twitter.com/reactjs">@reactjs</a> username on |
|||
Twitter. |
|||
</li> |
|||
<li> |
|||
<a href="https://github.com/ProjectMoon">ProjectMoon</a> for |
|||
letting us use the{' '} |
|||
<a href="https://www.npmjs.com/package/flux">flux</a> package name |
|||
on npm. |
|||
</li> |
|||
<li> |
|||
Shane Anderson for allowing us to use the{' '} |
|||
<a href="https://github.com/react">react</a> org on GitHub. |
|||
</li> |
|||
<li> |
|||
<a href="https://github.com/voronianski"> |
|||
Dmitri Voronianski |
|||
</a>{' '} |
|||
for letting us use the{' '} |
|||
<a href="https://labs.voronianski.com/oceanic-next-color-scheme/"> |
|||
Oceanic Next |
|||
</a>{' '} |
|||
color scheme on this website. |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
); |
|||
|
|||
export default Acknowlegements; |
@ -0,0 +1,117 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Link from 'gatsby-link'; |
|||
import Container from 'components/Container'; |
|||
import Header from 'components/Header'; |
|||
import React from 'react'; |
|||
import {colors, media, sharedStyles} from 'theme'; |
|||
import toCommaSeparatedList from 'utils/toCommaSeparatedList'; |
|||
import MetaTitle from 'templates/components/MetaTitle'; |
|||
|
|||
const AllBlogPosts = ({data}) => ( |
|||
<Container> |
|||
<div css={sharedStyles.articleLayout.container}> |
|||
<div css={sharedStyles.articleLayout.content}> |
|||
<Header>All Posts</Header> |
|||
<ul |
|||
css={{ |
|||
display: 'flex', |
|||
flexWrap: 'wrap', |
|||
marginLeft: -40, |
|||
}}> |
|||
{data.allMarkdownRemark.edges.map(({node}) => ( |
|||
<li |
|||
css={{ |
|||
paddingLeft: 40, |
|||
paddingTop: 40, |
|||
borderTop: '1px dotted #ececec', |
|||
paddingBottom: 40, |
|||
width: '100%', |
|||
|
|||
[media.size('medium')]: { |
|||
width: '50%', |
|||
}, |
|||
|
|||
[media.greaterThan('large')]: { |
|||
width: '33.33%', |
|||
}, |
|||
}} |
|||
key={node.fields.slug}> |
|||
<h2 |
|||
css={{ |
|||
fontSize: 24, |
|||
color: colors.dark, |
|||
lineHeight: 1.3, |
|||
fontWeight: 700, |
|||
}}> |
|||
<Link |
|||
css={{ |
|||
borderBottom: '1px solid #ececec', |
|||
':hover': { |
|||
borderBottomColor: colors.black, |
|||
}, |
|||
}} |
|||
key={node.fields.slug} |
|||
to={node.fields.slug}> |
|||
{node.frontmatter.title} |
|||
</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> |
|||
</li> |
|||
))} |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
); |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query AllBlogPostsPageQuery { |
|||
allMarkdownRemark( |
|||
filter: {id: {regex: "/blog/"}} |
|||
sort: {fields: [fields___date], order: DESC} |
|||
) { |
|||
edges { |
|||
node { |
|||
frontmatter { |
|||
title |
|||
author { |
|||
frontmatter { |
|||
name |
|||
url |
|||
} |
|||
} |
|||
} |
|||
fields { |
|||
date(formatString: "MMMM DD, YYYY") |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default AllBlogPosts; |
@ -0,0 +1,116 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import ErrorDecoder from 'components/ErrorDecoder'; |
|||
import Flex from 'components/Flex'; |
|||
import hex2rgba from 'hex2rgba'; |
|||
import MarkdownHeader from 'components/MarkdownHeader'; |
|||
import React from 'react'; |
|||
import StickyResponsiveSidebar from 'components/StickyResponsiveSidebar'; |
|||
import {colors, sharedStyles} from 'theme'; |
|||
import {createLinkDocs} from 'utils/createLink'; |
|||
import findSectionForPath from 'utils/findSectionForPath'; |
|||
import {sectionListDocs} from 'utils/sectionList'; |
|||
|
|||
const ErrorPage = ({data, location}) => ( |
|||
<Flex |
|||
direction="column" |
|||
grow="1" |
|||
shrink="0" |
|||
halign="stretch" |
|||
css={{ |
|||
width: '100%', |
|||
flex: '1 0 auto', |
|||
position: 'relative', |
|||
zIndex: 0, |
|||
}}> |
|||
<Container> |
|||
<div css={sharedStyles.articleLayout.container}> |
|||
<Flex |
|||
type="article" |
|||
direction="column" |
|||
grow="1" |
|||
halign="stretch" |
|||
css={{ |
|||
minHeight: 'calc(100vh - 40px)', |
|||
}}> |
|||
<MarkdownHeader |
|||
path={data.markdownRemark.fields.path} |
|||
title={data.markdownRemark.frontmatter.title} |
|||
/> |
|||
|
|||
<div css={sharedStyles.articleLayout.content}> |
|||
<div |
|||
css={sharedStyles.markdown} |
|||
dangerouslySetInnerHTML={{__html: data.markdownRemark.html}} |
|||
/> |
|||
<div |
|||
css={[ |
|||
sharedStyles.markdown, |
|||
{ |
|||
marginTop: 30, |
|||
'& code': { |
|||
display: 'block', |
|||
marginTop: 30, |
|||
padding: '1rem', |
|||
borderRadius: '0.5rem', |
|||
backgroundColor: hex2rgba(colors.error, 0.1), |
|||
color: colors.error, |
|||
}, |
|||
}, |
|||
]}> |
|||
<ErrorDecoder |
|||
errorCodesString={data.errorCodesJson.internal.contentDigest} |
|||
location={location} |
|||
/> |
|||
</div> |
|||
</div> |
|||
</Flex> |
|||
|
|||
<div css={sharedStyles.articleLayout.sidebar}> |
|||
<StickyResponsiveSidebar |
|||
createLink={createLinkDocs} |
|||
defaultActiveSection={findSectionForPath( |
|||
location.pathname, |
|||
sectionListDocs, |
|||
)} |
|||
location={location} |
|||
sectionList={sectionListDocs} |
|||
title={data.markdownRemark.frontmatter.title} |
|||
/> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
</Flex> |
|||
); |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query ErrorPageMarkdown($slug: String!) { |
|||
markdownRemark(fields: {slug: {eq: $slug}}) { |
|||
html |
|||
fields { |
|||
path |
|||
} |
|||
frontmatter { |
|||
title |
|||
} |
|||
} |
|||
errorCodesJson { |
|||
internal { |
|||
contentDigest |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default ErrorPage; |
After Width: | Height: | Size: 198 B |
@ -0,0 +1,38 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import Header from 'components/Header'; |
|||
import React from 'react'; |
|||
import {sharedStyles} from 'theme'; |
|||
|
|||
const JsxCompiler = () => ( |
|||
<Container> |
|||
<div css={sharedStyles.articleLayout.container}> |
|||
<div css={sharedStyles.articleLayout.content}> |
|||
<Header>JSX Compiler Service</Header> |
|||
<div css={sharedStyles.markdown}> |
|||
<p> |
|||
<strong> |
|||
This tool has been removed as JSXTransformer has been deprecated. |
|||
</strong> |
|||
</p> |
|||
<p> |
|||
We recommend using another tool such as{' '} |
|||
<a href="https://babeljs.io/repl/">the Babel REPL</a>. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</Container> |
|||
); |
|||
|
|||
export default JsxCompiler; |
@ -0,0 +1,2 @@ |
|||
User-agent: * |
|||
Disallow: |
@ -0,0 +1,171 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import {css} from 'glamor'; |
|||
import {colors} from 'theme'; |
|||
|
|||
const prismColors = { |
|||
char: '#D8DEE9', |
|||
comment: '#999999', |
|||
keyword: '#c5a5c5', |
|||
lineHighlight: '#14161a', |
|||
primitive: '#5a9bcf', |
|||
string: '#8dc891', |
|||
variable: '#d7deea', |
|||
boolean: '#ff8b50', |
|||
punctuation: '#5FB3B3', |
|||
tag: '#fc929e', |
|||
function: '#79b6f2', |
|||
className: '#FAC863', |
|||
method: '#6699CC', |
|||
operator: '#fc929e', |
|||
}; |
|||
|
|||
css.global('.gatsby-highlight', { |
|||
background: colors.dark, |
|||
color: colors.white, |
|||
borderRadius: 10, |
|||
overflow: 'auto', |
|||
tabSize: '1.5em', |
|||
}); |
|||
|
|||
css.global( |
|||
` |
|||
.gatsby-highlight code[class*="gatsby-code-"], |
|||
.gatsby-highlight pre[class*="gatsby-code-"], |
|||
.gatsby-highlight pre.prism-code`,
|
|||
{ |
|||
height: 'auto !important', |
|||
margin: '1rem', |
|||
fontSize: 14, |
|||
lineHeight: '20px', |
|||
whiteSpace: 'pre-wrap', |
|||
wordBreak: 'break-word', |
|||
}, |
|||
); |
|||
|
|||
css.global('.gatsby-highlight + .gatsby-highlight', { |
|||
marginTop: 20, |
|||
}); |
|||
|
|||
css.global('.gatsby-highlight-code-line', { |
|||
backgroundColor: prismColors.lineHighlight, |
|||
display: 'block', |
|||
margin: '-0.125rem calc(-1rem - 15px)', |
|||
padding: '0.125rem calc(1rem + 15px)', |
|||
}); |
|||
|
|||
css.global('.token.attr-name', { |
|||
color: prismColors.keyword, |
|||
}); |
|||
|
|||
css.global( |
|||
` |
|||
.token.comment, |
|||
.token.block-comment, |
|||
.token.prolog, |
|||
.token.doctype, |
|||
.token.cdata`,
|
|||
{ |
|||
color: prismColors.comment, |
|||
}, |
|||
); |
|||
|
|||
css.global( |
|||
` |
|||
.token.property, |
|||
.token.number, |
|||
.token.function-name, |
|||
.token.constant, |
|||
.token.symbol, |
|||
.token.deleted`,
|
|||
{ |
|||
color: prismColors.primitive, |
|||
}, |
|||
); |
|||
|
|||
css.global(`.token.boolean`, { |
|||
color: prismColors.boolean, |
|||
}); |
|||
|
|||
css.global(`.token.tag`, { |
|||
color: prismColors.tag, |
|||
}); |
|||
|
|||
css.global(`.token.string`, { |
|||
color: prismColors.string, |
|||
}); |
|||
|
|||
css.global(`.token.punctuation`, { |
|||
color: prismColors.punctuation, |
|||
}); |
|||
|
|||
css.global( |
|||
` |
|||
.token.selector, |
|||
.token.char, |
|||
.token.builtin, |
|||
.token.inserted`,
|
|||
{ |
|||
color: prismColors.char, |
|||
}, |
|||
); |
|||
|
|||
css.global(`.token.function`, { |
|||
color: prismColors.function, |
|||
}); |
|||
|
|||
css.global( |
|||
` |
|||
.token.operator, |
|||
.token.entity, |
|||
.token.url, |
|||
.token.variable`,
|
|||
{ |
|||
color: prismColors.variable, |
|||
}, |
|||
); |
|||
|
|||
css.global('.token.attr-value', { |
|||
color: prismColors.string, |
|||
}); |
|||
|
|||
css.global('.token.keyword', { |
|||
color: prismColors.keyword, |
|||
}); |
|||
|
|||
css.global( |
|||
` |
|||
.token.atrule, |
|||
.token.class-name`,
|
|||
{ |
|||
color: prismColors.className, |
|||
}, |
|||
); |
|||
|
|||
css.global('.token.important', { |
|||
fontWeight: 400, |
|||
}); |
|||
|
|||
css.global('.token.bold', { |
|||
fontWeight: 700, |
|||
}); |
|||
css.global('.token.italic', { |
|||
fontStyle: 'italic', |
|||
}); |
|||
|
|||
css.global('.token.entity', { |
|||
cursor: 'help', |
|||
}); |
|||
|
|||
css.global('.namespace', { |
|||
opacity: 0.7, |
|||
}); |
@ -0,0 +1,22 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
* @flow |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
/** |
|||
* Variables shared by multiple components. |
|||
*/ |
|||
|
|||
export default { |
|||
// NOTE: We can't just use `location.toString()` because when we are rendering
|
|||
// the SSR part in node.js we won't have a proper location.
|
|||
urlRoot: 'https://reactjs.org', |
|||
version: '16.0.0', |
|||
}; |
@ -0,0 +1,91 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import MarkdownPage from 'components/MarkdownPage'; |
|||
import {createLinkBlog} from 'utils/createLink'; |
|||
|
|||
const toSectionList = allMarkdownRemark => [ |
|||
{ |
|||
title: 'Recent Posts', |
|||
items: allMarkdownRemark.edges |
|||
.map(({node}) => ({ |
|||
id: node.fields.slug, |
|||
title: node.frontmatter.title, |
|||
})) |
|||
.concat({ |
|||
id: '/blog/all.html', |
|||
title: 'All posts ...', |
|||
}), |
|||
}, |
|||
]; |
|||
|
|||
const Blog = ({data, location}) => ( |
|||
<MarkdownPage |
|||
authors={data.markdownRemark.frontmatter.author} |
|||
createLink={createLinkBlog} |
|||
date={data.markdownRemark.fields.date} |
|||
location={location} |
|||
ogDescription={data.markdownRemark.excerpt} |
|||
markdownRemark={data.markdownRemark} |
|||
sectionList={toSectionList(data.allMarkdownRemark)} |
|||
titlePostfix=" - React Blog" |
|||
/> |
|||
); |
|||
|
|||
Blog.propTypes = { |
|||
data: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query TemplateBlogMarkdown($slug: String!) { |
|||
markdownRemark(fields: {slug: {eq: $slug}}) { |
|||
html |
|||
excerpt(pruneLength: 500) |
|||
frontmatter { |
|||
title |
|||
next |
|||
prev |
|||
author { |
|||
frontmatter { |
|||
name |
|||
url |
|||
} |
|||
} |
|||
} |
|||
fields { |
|||
date(formatString: "MMMM DD, YYYY") |
|||
path |
|||
slug |
|||
} |
|||
} |
|||
allMarkdownRemark( |
|||
limit: 10 |
|||
filter: {id: {regex: "/blog/"}} |
|||
sort: {fields: [fields___date], order: DESC} |
|||
) { |
|||
edges { |
|||
node { |
|||
frontmatter { |
|||
title |
|||
} |
|||
fields { |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default Blog; |
@ -0,0 +1,50 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import MarkdownPage from 'components/MarkdownPage'; |
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import {createLinkCommunity} from 'utils/createLink'; |
|||
import {sectionListCommunity} from 'utils/sectionList'; |
|||
|
|||
const Community = ({data, location}) => ( |
|||
<MarkdownPage |
|||
createLink={createLinkCommunity} |
|||
location={location} |
|||
markdownRemark={data.markdownRemark} |
|||
sectionList={sectionListCommunity} |
|||
titlePostfix=" - React" |
|||
/> |
|||
); |
|||
|
|||
Community.propTypes = { |
|||
data: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query TemplateCommunityMarkdown($slug: String!) { |
|||
markdownRemark(fields: {slug: {eq: $slug}}) { |
|||
html |
|||
frontmatter { |
|||
title |
|||
next |
|||
prev |
|||
} |
|||
fields { |
|||
path |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default Community; |
@ -0,0 +1,87 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Link from 'gatsby-link'; |
|||
import React from 'react'; |
|||
import {colors, media} from 'theme'; |
|||
|
|||
const ArrowSvg = ({cssProps = {}}) => ( |
|||
<svg |
|||
css={cssProps} |
|||
height="12" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
viewBox="0 0 4.53657 8.69699"> |
|||
<path |
|||
d={` |
|||
M.18254,8.697a.18149.18149,0,0,1-.12886-.31034L4.09723,4.34126.05369.29954a.18149.18149, |
|||
0,0,1,.2559-.2559L4.4838,4.21785a.18149.18149,0,0,1,0,.2559L.30958,8.648A.18149.18149, |
|||
0,0,1,.18254,8.697Z |
|||
`}
|
|||
fill="currentColor" |
|||
/> |
|||
</svg> |
|||
); |
|||
|
|||
const ButtonLink = ({children, type, ...rest}) => { |
|||
let typeStyle; |
|||
switch (type) { |
|||
case 'primary': |
|||
typeStyle = primaryStyle; |
|||
break; |
|||
case 'secondary': |
|||
typeStyle = secondaryStyle; |
|||
break; |
|||
} |
|||
|
|||
return ( |
|||
<Link {...rest} css={[style, typeStyle]}> |
|||
{children} |
|||
{type === 'secondary' && <ArrowSvg cssProps={{marginLeft: 10}} />} |
|||
</Link> |
|||
); |
|||
}; |
|||
|
|||
const style = { |
|||
display: 'inline-block', |
|||
fontSize: 16, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 20, |
|||
}, |
|||
}; |
|||
|
|||
const primaryStyle = { |
|||
backgroundColor: colors.brand, |
|||
color: colors.black, |
|||
padding: '10px 25px', |
|||
whiteSpace: 'nowrap', |
|||
transition: 'background-color 0.2s ease-out', |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
paddingTop: 15, |
|||
paddingBottom: 15, |
|||
}, |
|||
|
|||
':hover': { |
|||
backgroundColor: colors.white, |
|||
}, |
|||
}; |
|||
|
|||
const secondaryStyle = { |
|||
color: colors.brand, |
|||
transition: 'color 0.2s ease-out', |
|||
|
|||
':hover': { |
|||
color: colors.white, |
|||
}, |
|||
}; |
|||
|
|||
export default ButtonLink; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import ButtonLink from './ButtonLink'; |
|||
|
|||
export default ButtonLink; |
@ -0,0 +1,41 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
|
|||
const ChevronSvg = ({size = 10, cssProps = {}}) => ( |
|||
<svg |
|||
css={cssProps} |
|||
viewBox="0 0 926.23699 573.74994" |
|||
version="1.1" |
|||
x="0px" |
|||
y="0px" |
|||
width={size} |
|||
height={size}> |
|||
<g transform="translate(904.92214,-879.1482)"> |
|||
<path |
|||
d={` |
|||
m -673.67664,1221.6502 -231.2455,-231.24803 55.6165, |
|||
-55.627 c 30.5891,-30.59485 56.1806,-55.627 56.8701,-55.627 0.6894, |
|||
0 79.8637,78.60862 175.9427,174.68583 l 174.6892,174.6858 174.6892, |
|||
-174.6858 c 96.079,-96.07721 175.253196,-174.68583 175.942696, |
|||
-174.68583 0.6895,0 26.281,25.03215 56.8701, |
|||
55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864 |
|||
-231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688, |
|||
-104.0616 -231.873,-231.248 z |
|||
`}
|
|||
fill="currentColor" |
|||
/> |
|||
</g> |
|||
</svg> |
|||
); |
|||
|
|||
export default ChevronSvg; |
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
|
|||
const ExternalLinkSvg = ({cssProps = {}}) => ( |
|||
<svg |
|||
x="0px" |
|||
y="0px" |
|||
viewBox="0 0 100 100" |
|||
width={15} |
|||
height={15} |
|||
css={cssProps}> |
|||
<path |
|||
fill="currentColor" |
|||
d={` |
|||
M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0, |
|||
0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z |
|||
`}
|
|||
/> |
|||
<polygon |
|||
fill="currentColor" |
|||
points={` |
|||
45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8, |
|||
14.9 62.8,22.9 71.5,22.9 |
|||
`}
|
|||
/> |
|||
</svg> |
|||
); |
|||
|
|||
export default ExternalLinkSvg; |
@ -0,0 +1,38 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
import {colors} from 'theme'; |
|||
|
|||
const MetaTitle = ({ |
|||
children, |
|||
title, |
|||
cssProps = {}, |
|||
onClick, |
|||
onDark = false, |
|||
}) => ( |
|||
<div |
|||
onClick={onClick} |
|||
css={{ |
|||
color: onDark ? colors.subtleOnDark : colors.subtle, |
|||
cursor: onClick ? 'pointer' : null, |
|||
fontSize: 14, |
|||
fontWeight: 700, |
|||
lineHeight: 3, |
|||
textTransform: 'uppercase', |
|||
letterSpacing: '0.08em', |
|||
...cssProps, |
|||
}}> |
|||
{children} |
|||
</div> |
|||
); |
|||
|
|||
export default MetaTitle; |
@ -0,0 +1,136 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Container from 'components/Container'; |
|||
import Flex from 'components/Flex'; |
|||
import Link from 'gatsby-link'; |
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import {colors, fonts, media} from 'theme'; |
|||
|
|||
const NavigationFooter = ({next, prev, location}) => { |
|||
return ( |
|||
<div |
|||
css={{ |
|||
background: colors.dark, |
|||
color: colors.white, |
|||
paddingTop: 50, |
|||
paddingBottom: 50, |
|||
}}> |
|||
<Container> |
|||
<Flex |
|||
type="ul" |
|||
halign="space-between" |
|||
css={{ |
|||
[media.between('small', 'medium')]: { |
|||
paddingRight: 240, |
|||
}, |
|||
|
|||
[media.between('large', 'largerSidebar')]: { |
|||
paddingRight: 280, |
|||
}, |
|||
|
|||
[media.between('largerSidebar', 'sidebarFixed', true)]: { |
|||
paddingRight: 380, |
|||
}, |
|||
}}> |
|||
<Flex basis="50%" type="li"> |
|||
{prev && ( |
|||
<div> |
|||
<SecondaryLabel>Previous article</SecondaryLabel> |
|||
<div |
|||
css={{ |
|||
paddingTop: 10, |
|||
}}> |
|||
<PrimaryLink location={location} to={prev}> |
|||
{linkToTitle(prev)} |
|||
</PrimaryLink> |
|||
</div> |
|||
</div> |
|||
)} |
|||
</Flex> |
|||
{next && ( |
|||
<Flex |
|||
halign="flex-end" |
|||
basis="50%" |
|||
type="li" |
|||
css={{ |
|||
textAlign: 'right', |
|||
}}> |
|||
<div> |
|||
<SecondaryLabel>Next article</SecondaryLabel> |
|||
<div |
|||
css={{ |
|||
paddingTop: 10, |
|||
}}> |
|||
<PrimaryLink location={location} to={next}> |
|||
{linkToTitle(next)} |
|||
</PrimaryLink> |
|||
</div> |
|||
</div> |
|||
</Flex> |
|||
)} |
|||
</Flex> |
|||
</Container> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
NavigationFooter.propTypes = { |
|||
next: PropTypes.string, |
|||
prev: PropTypes.string, |
|||
}; |
|||
|
|||
export default NavigationFooter; |
|||
|
|||
const linkToTitle = link => link.replace(/-/g, ' ').replace('.html', ''); |
|||
|
|||
const PrimaryLink = ({children, to, location}) => { |
|||
// quick fix
|
|||
// TODO: replace this with better method of getting correct full url
|
|||
const updatedUrl = |
|||
(location && location.pathname.replace(/\/[^/]+\.html/, '/' + to)) || to; |
|||
return ( |
|||
<Link |
|||
css={{ |
|||
display: 'inline', |
|||
textTransform: 'capitalize', |
|||
borderColor: colors.subtle, |
|||
transition: 'border-color 0.2s ease', |
|||
fontSize: 30, |
|||
borderBottomWidth: 1, |
|||
borderBottomStyle: 'solid', |
|||
|
|||
[media.lessThan('large')]: { |
|||
fontSize: 24, |
|||
}, |
|||
[media.size('xsmall')]: { |
|||
fontSize: 16, |
|||
}, |
|||
':hover': { |
|||
borderColor: colors.white, |
|||
}, |
|||
}} |
|||
to={updatedUrl}> |
|||
{children} |
|||
</Link> |
|||
); |
|||
}; |
|||
|
|||
const SecondaryLabel = ({children}) => ( |
|||
<div |
|||
css={{ |
|||
color: colors.brand, |
|||
...fonts.small, |
|||
}}> |
|||
{children} |
|||
</div> |
|||
); |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import NavigationFooter from './NavigationFooter'; |
|||
|
|||
export default NavigationFooter; |
@ -0,0 +1,96 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
import {colors, media} from 'theme'; |
|||
import MetaTitle from '../MetaTitle'; |
|||
import ChevronSvg from '../ChevronSvg'; |
|||
|
|||
// TODO Update isActive link as document scrolls past anchor tags
|
|||
// Maybe used 'hashchange' along with 'scroll' to set/update active links
|
|||
|
|||
const Section = ({ |
|||
createLink, |
|||
isActive, |
|||
location, |
|||
onLinkClick, |
|||
onSectionTitleClick, |
|||
section, |
|||
}) => ( |
|||
<div> |
|||
<MetaTitle |
|||
onClick={onSectionTitleClick} |
|||
cssProps={{ |
|||
marginTop: 10, |
|||
|
|||
[media.greaterThan('small')]: { |
|||
color: isActive ? colors.text : colors.subtle, |
|||
|
|||
':hover': { |
|||
color: colors.text, |
|||
}, |
|||
}, |
|||
}}> |
|||
{section.title} |
|||
<ChevronSvg |
|||
cssProps={{ |
|||
marginLeft: 7, |
|||
transform: isActive ? 'rotateX(180deg)' : 'rotateX(0deg)', |
|||
transition: 'transform 0.2s ease', |
|||
|
|||
[media.lessThan('small')]: { |
|||
display: 'none', |
|||
}, |
|||
}} |
|||
/> |
|||
</MetaTitle> |
|||
<ul |
|||
css={{ |
|||
marginBottom: 10, |
|||
|
|||
[media.greaterThan('small')]: { |
|||
display: isActive ? 'block' : 'none', |
|||
}, |
|||
}}> |
|||
{section.items.map(item => ( |
|||
<li |
|||
key={item.id} |
|||
css={{ |
|||
marginTop: 5, |
|||
}}> |
|||
{createLink({ |
|||
item, |
|||
location, |
|||
onLinkClick, |
|||
section, |
|||
})} |
|||
|
|||
{item.subitems && ( |
|||
<ul css={{marginLeft: 20}}> |
|||
{item.subitems.map(subitem => ( |
|||
<li key={subitem.id}> |
|||
{createLink({ |
|||
item: subitem, |
|||
location, |
|||
onLinkClick, |
|||
section, |
|||
})} |
|||
</li> |
|||
))} |
|||
</ul> |
|||
)} |
|||
</li> |
|||
))} |
|||
</ul> |
|||
</div> |
|||
); |
|||
|
|||
export default Section; |
@ -0,0 +1,70 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React, {Component} from 'react'; |
|||
import Flex from 'components/Flex'; |
|||
import Section from './Section'; |
|||
import {media} from 'theme'; |
|||
|
|||
class Sidebar extends Component { |
|||
constructor(props, context) { |
|||
super(props, context); |
|||
|
|||
this.state = { |
|||
activeSection: props.defaultActiveSection, |
|||
}; |
|||
} |
|||
|
|||
render() { |
|||
const {closeParentMenu, createLink, location, sectionList} = this.props; |
|||
const {activeSection} = this.state; |
|||
|
|||
return ( |
|||
<Flex |
|||
type="nav" |
|||
direction="column" |
|||
halign="stretch" |
|||
css={{ |
|||
width: '100%', |
|||
paddingLeft: 20, |
|||
position: 'relative', |
|||
|
|||
[media.greaterThan('largerSidebar')]: { |
|||
paddingLeft: 40, |
|||
}, |
|||
|
|||
[media.lessThan('small')]: { |
|||
paddingBottom: 100, |
|||
}, |
|||
}}> |
|||
{sectionList.map((section, index) => ( |
|||
<Section |
|||
createLink={createLink} |
|||
isActive={activeSection === section || sectionList.length === 1} |
|||
key={index} |
|||
location={location} |
|||
onLinkClick={closeParentMenu} |
|||
onSectionTitleClick={() => this._toggleSection(section)} |
|||
section={section} |
|||
/> |
|||
))} |
|||
</Flex> |
|||
); |
|||
} |
|||
|
|||
_toggleSection(section) { |
|||
this.setState(state => ({ |
|||
activeSection: state.activeSection === section ? null : section, |
|||
})); |
|||
} |
|||
} |
|||
|
|||
export default Sidebar; |
@ -0,0 +1,14 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Sidebar from './Sidebar'; |
|||
|
|||
export default Sidebar; |
@ -0,0 +1,50 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import MarkdownPage from 'components/MarkdownPage'; |
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import {createLinkDocs} from 'utils/createLink'; |
|||
import {sectionListDocs} from 'utils/sectionList'; |
|||
|
|||
const Docs = ({data, location}) => ( |
|||
<MarkdownPage |
|||
createLink={createLinkDocs} |
|||
location={location} |
|||
markdownRemark={data.markdownRemark} |
|||
sectionList={sectionListDocs} |
|||
titlePostfix=" - React" |
|||
/> |
|||
); |
|||
|
|||
Docs.propTypes = { |
|||
data: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query TemplateDocsMarkdown($slug: String!) { |
|||
markdownRemark(fields: {slug: {eq: $slug}}) { |
|||
html |
|||
frontmatter { |
|||
title |
|||
next |
|||
prev |
|||
} |
|||
fields { |
|||
path |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default Docs; |
@ -0,0 +1,470 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import ButtonLink from './components/ButtonLink'; |
|||
import Container from 'components/Container'; |
|||
import Flex from 'components/Flex'; |
|||
import mountCodeExample from 'utils/mountCodeExample'; |
|||
import PropTypes from 'prop-types'; |
|||
import React, {Component} from 'react'; |
|||
import TitleAndMetaTags from 'components/TitleAndMetaTags'; |
|||
import {colors, media, sharedStyles} from 'theme'; |
|||
import createOgUrl from 'utils/createOgUrl'; |
|||
|
|||
class Home extends Component { |
|||
componentDidMount() { |
|||
mountCodeExample('helloExample', HELLO_COMPONENT); |
|||
mountCodeExample('timerExample', TIMER_COMPONENT); |
|||
mountCodeExample('todoExample', TODO_COMPONENT); |
|||
mountCodeExample('markdownExample', MARKDOWN_COMPONENT); |
|||
} |
|||
|
|||
render() { |
|||
const {data} = this.props; |
|||
const title = 'React - A JavaScript library for building user interfaces'; |
|||
|
|||
return ( |
|||
<div css={{width: '100%'}}> |
|||
<TitleAndMetaTags |
|||
title={title} |
|||
ogUrl={createOgUrl(data.markdownRemark.fields.slug)} |
|||
/> |
|||
<header |
|||
css={{ |
|||
backgroundColor: colors.dark, |
|||
color: colors.white, |
|||
}}> |
|||
<div |
|||
css={{ |
|||
paddingTop: 45, |
|||
paddingBottom: 20, |
|||
|
|||
[media.greaterThan('small')]: { |
|||
paddingTop: 60, |
|||
paddingBottom: 70, |
|||
}, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
paddingTop: 95, |
|||
paddingBottom: 85, |
|||
maxWidth: 1500, // Positioning of background logo
|
|||
marginLeft: 'auto', |
|||
marginRight: 'auto', |
|||
backgroundImage: 'url(/large-logo.svg)', |
|||
backgroundRepeat: 'no-repeat', |
|||
backgroundPosition: '100% 100px', |
|||
backgroundSize: '50% auto', |
|||
}, |
|||
}}> |
|||
<Container> |
|||
<h1 |
|||
css={{ |
|||
color: colors.brand, |
|||
textAlign: 'center', |
|||
margin: 0, |
|||
fontSize: 45, |
|||
letterSpacing: '0.01em', |
|||
[media.size('xsmall')]: { |
|||
fontSize: 30, |
|||
}, |
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 60, |
|||
}, |
|||
}}> |
|||
React |
|||
</h1> |
|||
<p |
|||
css={{ |
|||
paddingTop: 15, |
|||
textAlign: 'center', |
|||
fontSize: 24, |
|||
letterSpacing: '0.01em', |
|||
fontWeight: 200, |
|||
|
|||
[media.size('xsmall')]: { |
|||
fontSize: 16, |
|||
maxWidth: '12em', |
|||
marginLeft: 'auto', |
|||
marginRight: 'auto', |
|||
}, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
paddingTop: 20, |
|||
fontSize: 30, |
|||
}, |
|||
}}> |
|||
A JavaScript library for building user interfaces |
|||
</p> |
|||
<Flex |
|||
valign="center" |
|||
css={{ |
|||
paddingTop: 40, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
paddingTop: 65, |
|||
}, |
|||
}}> |
|||
<CtaItem> |
|||
<ButtonLink to="/docs/hello-world.html" type="primary"> |
|||
Get Started |
|||
</ButtonLink> |
|||
</CtaItem> |
|||
<CtaItem> |
|||
<ButtonLink to="/tutorial/tutorial.html" type="secondary"> |
|||
Take the Tutorial |
|||
</ButtonLink> |
|||
</CtaItem> |
|||
</Flex> |
|||
</Container> |
|||
</div> |
|||
</header> |
|||
|
|||
<Container> |
|||
<div |
|||
css={[sharedStyles.markdown, markdownStyles]} |
|||
dangerouslySetInnerHTML={{__html: data.markdownRemark.html}} |
|||
/> |
|||
</Container> |
|||
|
|||
<section |
|||
css={{ |
|||
background: colors.dark, |
|||
color: colors.white, |
|||
paddingTop: 45, |
|||
paddingBottom: 45, |
|||
}}> |
|||
<Container> |
|||
<Flex valign="center"> |
|||
<CtaItem> |
|||
<ButtonLink to="/docs/hello-world.html" type="primary"> |
|||
Get Started |
|||
</ButtonLink> |
|||
</CtaItem> |
|||
<CtaItem> |
|||
<ButtonLink to="/tutorial/tutorial.html" type="secondary"> |
|||
Take the Tutorial |
|||
</ButtonLink> |
|||
</CtaItem> |
|||
</Flex> |
|||
</Container> |
|||
</section> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
Home.propTypes = { |
|||
data: PropTypes.object.isRequired, |
|||
location: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
const CtaItem = ({children, primary = false}) => ( |
|||
<div |
|||
css={{ |
|||
width: '50%', |
|||
|
|||
[media.between('small', 'large')]: { |
|||
paddingLeft: 20, |
|||
}, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
paddingLeft: 40, |
|||
}, |
|||
|
|||
'&:first-child': { |
|||
textAlign: 'right', |
|||
paddingRight: 15, |
|||
}, |
|||
|
|||
'&:nth-child(2)': { |
|||
[media.greaterThan('small')]: { |
|||
paddingLeft: 15, |
|||
}, |
|||
}, |
|||
}}> |
|||
{children} |
|||
</div> |
|||
); |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query HomeMarkdown($slug: String!) { |
|||
markdownRemark(fields: {slug: {eq: $slug}}) { |
|||
html |
|||
frontmatter { |
|||
title |
|||
} |
|||
fields { |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default Home; |
|||
|
|||
// TODO This nasty CSS is required because 'docs/index.md' defines hard-coded class names.
|
|||
const markdownStyles = { |
|||
'& .home-section': { |
|||
marginTop: 20, |
|||
marginBottom: 15, |
|||
|
|||
[media.greaterThan('medium')]: { |
|||
marginTop: 60, |
|||
marginBottom: 65, |
|||
}, |
|||
}, |
|||
|
|||
'& .home-section:first-child': { |
|||
[media.lessThan('medium')]: { |
|||
marginTop: 0, |
|||
marginBottom: 0, |
|||
overflowX: 'auto', |
|||
paddingTop: 30, |
|||
WebkitOverflowScrolling: 'touch', |
|||
position: 'relative', |
|||
maskImage: |
|||
'linear-gradient(to right, transparent, white 10px, white 90%, transparent)', |
|||
}, |
|||
}, |
|||
|
|||
'& .homeDivider': { |
|||
height: 1, |
|||
marginBottom: -1, |
|||
border: 'none', |
|||
borderBottom: `1 solid ${colors.divider}`, |
|||
}, |
|||
|
|||
'& .marketing-row': { |
|||
display: 'flex', |
|||
flexDirection: 'row', |
|||
|
|||
[media.lessThan('medium')]: { |
|||
display: 'block', |
|||
whiteSpace: 'nowrap', |
|||
}, |
|||
}, |
|||
|
|||
'& .marketing-col': { |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
flex: '0 1 33%', |
|||
marginLeft: 40, |
|||
|
|||
'&:first-of-type': { |
|||
marginLeft: 0, |
|||
|
|||
[media.lessThan('medium')]: { |
|||
marginLeft: 10, |
|||
}, |
|||
}, |
|||
|
|||
[media.lessThan('medium')]: { |
|||
display: 'inline-block', |
|||
verticalAlign: 'top', |
|||
marginLeft: 0, |
|||
whiteSpace: 'normal', |
|||
width: '75%', |
|||
marginRight: 20, |
|||
paddingBottom: 40, |
|||
|
|||
'&:first-of-type': { |
|||
marginTop: 0, |
|||
}, |
|||
}, |
|||
|
|||
'& h3': { |
|||
color: colors.subtle, |
|||
paddingTop: 0, |
|||
fontWeight: 300, |
|||
fontSize: 20, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 24, |
|||
fontWeight: 200, |
|||
}, |
|||
}, |
|||
|
|||
'& p': { |
|||
lineHeight: 1.7, |
|||
}, |
|||
|
|||
'& h3 + p': { |
|||
marginTop: 20, |
|||
}, |
|||
}, |
|||
|
|||
'& .example': { |
|||
marginTop: 40, |
|||
|
|||
'&:first-child': { |
|||
marginTop: 0, |
|||
}, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
marginTop: 80, |
|||
}, |
|||
}, |
|||
}; |
|||
|
|||
// TODO Move these hard-coded examples into example files and out of the template?
|
|||
// Alternately, move them into the markdown and transform them during build?
|
|||
// This could be done via a new Gatsby transform plug-in that auto-converts to runnable REPLs?
|
|||
const name = Math.random() > 0.5 ? 'John' : 'Jane'; |
|||
const HELLO_COMPONENT = ` |
|||
class HelloMessage extends React.Component { |
|||
render() { |
|||
return ( |
|||
<div> |
|||
Hello {this.props.name} |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
ReactDOM.render( |
|||
<HelloMessage name="${name}" />, |
|||
mountNode |
|||
); |
|||
`.trim();
|
|||
|
|||
const TIMER_COMPONENT = ` |
|||
class Timer extends React.Component { |
|||
constructor(props) { |
|||
super(props); |
|||
this.state = { seconds: 0 }; |
|||
} |
|||
|
|||
tick() { |
|||
this.setState((prevState) => ({ |
|||
seconds: prevState.seconds + 1 |
|||
})); |
|||
} |
|||
|
|||
componentDidMount() { |
|||
this.interval = setInterval(() => this.tick(), 1000); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
clearInterval(this.interval); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div> |
|||
Seconds: {this.state.seconds} |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
ReactDOM.render(<Timer />, mountNode); |
|||
`.trim();
|
|||
|
|||
var TODO_COMPONENT = ` |
|||
class TodoApp extends React.Component { |
|||
constructor(props) { |
|||
super(props); |
|||
this.state = { items: [], text: '' }; |
|||
this.handleChange = this.handleChange.bind(this); |
|||
this.handleSubmit = this.handleSubmit.bind(this); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div> |
|||
<h3>TODO</h3> |
|||
<TodoList items={this.state.items} /> |
|||
<form onSubmit={this.handleSubmit}> |
|||
<input |
|||
onChange={this.handleChange} |
|||
value={this.state.text} |
|||
/> |
|||
<button> |
|||
Add #{this.state.items.length + 1} |
|||
</button> |
|||
</form> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
handleChange(e) { |
|||
this.setState({ text: e.target.value }); |
|||
} |
|||
|
|||
handleSubmit(e) { |
|||
e.preventDefault(); |
|||
if (!this.state.text.length) { |
|||
return; |
|||
} |
|||
const newItem = { |
|||
text: this.state.text, |
|||
id: Date.now() |
|||
}; |
|||
this.setState((prevState) => ({ |
|||
items: prevState.items.concat(newItem), |
|||
text: '' |
|||
})); |
|||
} |
|||
} |
|||
|
|||
class TodoList extends React.Component { |
|||
render() { |
|||
return ( |
|||
<ul> |
|||
{this.props.items.map(item => ( |
|||
<li key={item.id}>{item.text}</li> |
|||
))} |
|||
</ul> |
|||
); |
|||
} |
|||
} |
|||
|
|||
ReactDOM.render(<TodoApp />, mountNode); |
|||
`.trim();
|
|||
|
|||
var MARKDOWN_COMPONENT = ` |
|||
class MarkdownEditor extends React.Component { |
|||
constructor(props) { |
|||
super(props); |
|||
this.handleChange = this.handleChange.bind(this); |
|||
this.state = { value: 'Type some *markdown* here!' }; |
|||
} |
|||
|
|||
handleChange(e) { |
|||
this.setState({ value: e.target.value }); |
|||
} |
|||
|
|||
getRawMarkup() { |
|||
const md = new Remarkable(); |
|||
return { __html: md.render(this.state.value) }; |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="MarkdownEditor"> |
|||
<h3>Input</h3> |
|||
<textarea |
|||
onChange={this.handleChange} |
|||
defaultValue={this.state.value} |
|||
/> |
|||
<h3>Output</h3> |
|||
<div |
|||
className="content" |
|||
dangerouslySetInnerHTML={this.getRawMarkup()} |
|||
/> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
ReactDOM.render(<MarkdownEditor />, mountNode); |
|||
`.trim();
|
@ -0,0 +1,61 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import MarkdownPage from 'components/MarkdownPage'; |
|||
import PropTypes from 'prop-types'; |
|||
import React from 'react'; |
|||
import {createLinkTutorial} from 'utils/createLink'; |
|||
import {sectionListTutorial} from 'utils/sectionList'; |
|||
|
|||
const Tutorial = ({data, location}) => { |
|||
// HACK The injected location prop doesn't update when hash changes
|
|||
// This might be a gatsby issue, or a react-router/history issue,
|
|||
// Or we might be using either library incorrectly.
|
|||
// For now this patch keeps the hash in sync by JIT copying it from window.
|
|||
// The undefined check prevents us from breaking on production build.
|
|||
if (typeof window !== 'undefined' && typeof window.location !== 'undefined') { |
|||
location.hash = window.location.hash; |
|||
} |
|||
|
|||
return ( |
|||
<MarkdownPage |
|||
createLink={createLinkTutorial} |
|||
location={location} |
|||
markdownRemark={data.markdownRemark} |
|||
sectionList={sectionListTutorial} |
|||
titlePostfix=" - React" |
|||
/> |
|||
); |
|||
}; |
|||
|
|||
Tutorial.propTypes = { |
|||
data: PropTypes.object.isRequired, |
|||
}; |
|||
|
|||
// eslint-disable-next-line no-undef
|
|||
export const pageQuery = graphql` |
|||
query TemplateTutorialMarkdown($slug: String!) { |
|||
markdownRemark(fields: {slug: {eq: $slug}}) { |
|||
html |
|||
frontmatter { |
|||
title |
|||
next |
|||
prev |
|||
} |
|||
fields { |
|||
path |
|||
slug |
|||
} |
|||
} |
|||
} |
|||
`;
|
|||
|
|||
export default Tutorial; |
@ -0,0 +1,407 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
* @flow |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
/** |
|||
* Theme contains variables shared by styles of multiple components. |
|||
*/ |
|||
|
|||
import hex2rgba from 'hex2rgba'; |
|||
|
|||
const colors = { |
|||
lighter: '#373940', // light blue
|
|||
dark: '#282c34', // dark blue
|
|||
darker: '#20232a', // really dark blue
|
|||
brand: '#61dafb', // electric blue
|
|||
brandLight: '#bbeffd', |
|||
text: '#1a1a1a', // very dark grey / black substitute
|
|||
subtle: '#6d6d6d', // light grey for text
|
|||
subtleOnDark: '#999', |
|||
divider: '#ececec', // very light grey
|
|||
note: '#ffe564', // yellow
|
|||
error: '#ff6464', // yellow
|
|||
white: '#ffffff', |
|||
black: '#000000', |
|||
}; |
|||
|
|||
const SIZES = { |
|||
xsmall: {min: 0, max: 599}, |
|||
small: {min: 600, max: 779}, |
|||
medium: {min: 780, max: 979}, |
|||
large: {min: 980, max: 1279}, |
|||
xlarge: {min: 1280, max: 1339}, |
|||
xxlarge: {min: 1340, max: Infinity}, |
|||
|
|||
// Sidebar/nav related tweakpoints
|
|||
largerSidebar: {min: 1100, max: 1339}, |
|||
sidebarFixed: {min: 2000, max: Infinity}, |
|||
}; |
|||
|
|||
type Size = $Keys<typeof SIZES>; |
|||
|
|||
const media = { |
|||
between(smallKey: Size, largeKey: Size, excludeLarge: boolean = false) { |
|||
if (excludeLarge) { |
|||
return `@media (min-width: ${SIZES[smallKey] |
|||
.min}px) and (max-width: ${SIZES[largeKey].min - 1}px)`;
|
|||
} else { |
|||
if (SIZES[largeKey].max === Infinity) { |
|||
return `@media (min-width: ${SIZES[smallKey].min}px)`; |
|||
} else { |
|||
return `@media (min-width: ${SIZES[smallKey] |
|||
.min}px) and (max-width: ${SIZES[largeKey].max}px)`;
|
|||
} |
|||
} |
|||
}, |
|||
|
|||
greaterThan(key: Size) { |
|||
return `@media (min-width: ${SIZES[key].min}px)`; |
|||
}, |
|||
|
|||
lessThan(key: Size) { |
|||
return `@media (max-width: ${SIZES[key].min - 1}px)`; |
|||
}, |
|||
|
|||
size(key: Size) { |
|||
const size = SIZES[key]; |
|||
|
|||
if (size.min == null) { |
|||
return media.lessThan(key); |
|||
} else if (size.max == null) { |
|||
return media.greaterThan(key); |
|||
} else { |
|||
return media.between(key, key); |
|||
} |
|||
}, |
|||
}; |
|||
|
|||
const fonts = { |
|||
header: { |
|||
fontSize: 60, |
|||
lineHeight: '65px', |
|||
fontWeight: 700, |
|||
|
|||
[media.lessThan('medium')]: { |
|||
fontSize: 40, |
|||
lineHeight: '45px', |
|||
}, |
|||
}, |
|||
small: { |
|||
fontSize: 14, |
|||
}, |
|||
}; |
|||
|
|||
// Shared styles are generally better as components,
|
|||
// Except when they must be used within nested CSS selectors.
|
|||
// This is the case for eg markdown content.
|
|||
const linkStyle = { |
|||
backgroundColor: hex2rgba(colors.brandLight, 0.5), |
|||
borderBottom: `1px solid ${hex2rgba(colors.black, 0.2)}`, |
|||
color: colors.text, |
|||
|
|||
':hover': { |
|||
backgroundColor: colors.brandLight, |
|||
borderBottomColor: colors.text, |
|||
}, |
|||
}; |
|||
const sharedStyles = { |
|||
link: linkStyle, |
|||
|
|||
articleLayout: { |
|||
container: { |
|||
display: 'flex', |
|||
minHeight: 'calc(100vh - 60px)', |
|||
[media.greaterThan('sidebarFixed')]: { |
|||
maxWidth: 840, |
|||
marginLeft: 'auto', |
|||
marginRight: 'auto', |
|||
}, |
|||
}, |
|||
content: { |
|||
marginTop: 40, |
|||
marginBottom: 120, |
|||
|
|||
[media.greaterThan('medium')]: { |
|||
marginTop: 50, |
|||
}, |
|||
}, |
|||
sidebar: { |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
|
|||
[media.between('small', 'sidebarFixed')]: { |
|||
borderLeft: '1px solid #ececec', |
|||
marginLeft: 80, |
|||
}, |
|||
|
|||
[media.between('small', 'largerSidebar')]: { |
|||
flex: '0 0 200px', |
|||
marginLeft: 80, |
|||
}, |
|||
|
|||
[media.between('small', 'medium')]: { |
|||
marginLeft: 40, |
|||
}, |
|||
|
|||
[media.greaterThan('largerSidebar')]: { |
|||
flex: '0 0 300px', |
|||
}, |
|||
|
|||
[media.greaterThan('sidebarFixed')]: { |
|||
position: 'fixed', |
|||
right: 0, |
|||
width: 300, |
|||
zIndex: 2, |
|||
}, |
|||
}, |
|||
|
|||
editLink: { |
|||
color: colors.subtle, |
|||
borderColor: colors.divider, |
|||
transition: 'all 0.2s ease', |
|||
transitionPropery: 'color, border-color', |
|||
whiteSpace: 'nowrap', |
|||
borderBottomWidth: 1, |
|||
borderBottomStyle: 'solid', |
|||
|
|||
':hover': { |
|||
color: colors.text, |
|||
borderColor: colors.text, |
|||
}, |
|||
}, |
|||
}, |
|||
|
|||
markdown: { |
|||
lineHeight: '25px', |
|||
|
|||
'& .gatsby-highlight': { |
|||
marginTop: 25, |
|||
marginLeft: -30, |
|||
marginRight: -30, |
|||
marginBottom: 25, |
|||
paddingLeft: 15, |
|||
paddingRight: 15, |
|||
|
|||
[media.lessThan('small')]: { |
|||
marginLeft: -20, |
|||
marginRight: -20, |
|||
borderRadius: 0, |
|||
}, |
|||
}, |
|||
|
|||
'& a:not(.anchor):not(.gatsby-resp-image-link)': linkStyle, |
|||
|
|||
'& > p:first-child': { |
|||
fontSize: 18, |
|||
fontWeight: 300, |
|||
color: colors.subtle, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 24, |
|||
}, |
|||
|
|||
'& a, & strong': { |
|||
fontWeight: 400, |
|||
}, |
|||
}, |
|||
|
|||
'& p': { |
|||
marginTop: 30, |
|||
fontSize: 17, |
|||
lineHeight: 1.7, |
|||
maxWidth: '42em', |
|||
|
|||
'&:first-of-type': { |
|||
marginTop: 15, |
|||
}, |
|||
|
|||
'&:first-child': { |
|||
marginTop: 0, |
|||
}, |
|||
|
|||
[media.lessThan('large')]: { |
|||
fontSize: 16, |
|||
marginTop: 25, |
|||
}, |
|||
}, |
|||
|
|||
'& h3 + p, & h3 + p:first-of-type': { |
|||
marginTop: 20, |
|||
}, |
|||
|
|||
'& p > code, & li > code': { |
|||
background: hex2rgba(colors.note, 0.3), |
|||
padding: '0 3px', |
|||
fontSize: 'inherit', |
|||
color: colors.text, |
|||
wordBreak: 'break-word', |
|||
}, |
|||
|
|||
'& hr': { |
|||
height: 1, |
|||
marginBottom: -1, |
|||
border: 'none', |
|||
borderBottom: `1px solid ${colors.divider}`, |
|||
marginTop: 40, |
|||
|
|||
':first-child': { |
|||
marginTop: 0, |
|||
}, |
|||
}, |
|||
|
|||
'& h1': { |
|||
lineHeight: 1.2, |
|||
|
|||
[media.size('xsmall')]: { |
|||
fontSize: 30, |
|||
}, |
|||
|
|||
[media.between('small', 'large')]: { |
|||
fontSize: 45, |
|||
}, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 60, |
|||
}, |
|||
}, |
|||
|
|||
'& h2': { |
|||
borderTop: `1px solid ${colors.divider}`, |
|||
marginTop: 44, |
|||
paddingTop: 40, |
|||
lineHeight: 1.2, |
|||
|
|||
':first-child': { |
|||
borderTop: 0, |
|||
marginTop: 0, |
|||
paddingTop: 0, |
|||
}, |
|||
|
|||
[media.lessThan('large')]: { |
|||
fontSize: 20, |
|||
}, |
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 35, |
|||
}, |
|||
}, |
|||
|
|||
'& hr + h2': { |
|||
borderTop: 0, |
|||
marginTop: 0, |
|||
}, |
|||
|
|||
'& h3': { |
|||
paddingTop: 45, |
|||
|
|||
[media.greaterThan('xlarge')]: { |
|||
fontSize: 25, |
|||
lineHeight: 1.3, |
|||
}, |
|||
}, |
|||
|
|||
'& h2 + h3, & h2 + h3:first-of-type': { |
|||
paddingTop: 30, |
|||
}, |
|||
|
|||
'& h4': { |
|||
fontSize: 20, |
|||
color: colors.subtle, |
|||
lineHeight: 1.3, |
|||
marginTop: 50, |
|||
fontWeight: 400, |
|||
}, |
|||
|
|||
'& h4 + p': { |
|||
marginTop: 20, |
|||
}, |
|||
|
|||
'& ol, & ul': { |
|||
marginTop: 20, |
|||
fontSize: 16, |
|||
color: colors.text, |
|||
|
|||
[media.lessThan('small')]: { |
|||
paddingLeft: 20, |
|||
}, |
|||
|
|||
'& p, & p:first-of-type': { |
|||
fontSize: 16, |
|||
marginTop: 0, |
|||
lineHeight: 1.2, |
|||
}, |
|||
|
|||
'& li': { |
|||
marginTop: 20, |
|||
}, |
|||
|
|||
'& li.button-newapp': { |
|||
marginTop: 0, |
|||
}, |
|||
|
|||
'& ol, & ul': { |
|||
marginLeft: 20, |
|||
}, |
|||
}, |
|||
|
|||
'& img': { |
|||
maxWidth: '100%', |
|||
}, |
|||
|
|||
'& ol': { |
|||
listStyle: 'decimal', |
|||
}, |
|||
|
|||
'& ul': { |
|||
listStyle: 'disc', |
|||
}, |
|||
|
|||
'& blockquote': { |
|||
backgroundColor: hex2rgba('#ffe564', 0.3), |
|||
borderLeftColor: colors.note, |
|||
borderLeftWidth: 9, |
|||
borderLeftStyle: 'solid', |
|||
padding: '20px 45px 20px 26px', |
|||
marginBottom: 30, |
|||
marginTop: 20, |
|||
marginLeft: -30, |
|||
marginRight: -30, |
|||
|
|||
[media.lessThan('small')]: { |
|||
marginLeft: -20, |
|||
marginRight: -20, |
|||
}, |
|||
|
|||
'& p': { |
|||
marginTop: 15, |
|||
|
|||
'&:first-of-type': { |
|||
fontWeight: 700, |
|||
marginTop: 0, |
|||
}, |
|||
|
|||
'&:nth-of-type(2)': { |
|||
marginTop: 0, |
|||
}, |
|||
}, |
|||
}, |
|||
|
|||
'& .gatsby-highlight + blockquote': { |
|||
marginTop: 40, |
|||
}, |
|||
}, |
|||
}; |
|||
|
|||
export default { |
|||
colors, |
|||
fonts, |
|||
media, |
|||
sharedStyles, |
|||
}; |
@ -0,0 +1,117 @@ |
|||
/** |
|||
* Copyright 2015-present, Facebook, Inc. |
|||
* All rights reserved. |
|||
* |
|||
* This source code is licensed under the BSD-style license found in the |
|||
* LICENSE file in the root directory of this source tree. An additional grant |
|||
* of patent rights can be found in the PATENTS file in the same directory. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import Link from 'gatsby-link'; |
|||
import React from 'react'; |
|||
import ExternalLinkSvg from 'templates/components/ExternalLinkSvg'; |
|||
import isItemActive from 'utils/isItemActive'; |
|||
import slugify from 'utils/slugify'; |
|||
import {colors, media} from 'theme'; |
|||
|
|||
const createLinkBlog = ({item, location, section}) => { |
|||
const isActive = isItemActive(location, item); |
|||
|
|||
return ( |
|||
<Link css={[linkCss, isActive && activeLinkCss]} to={item.id}> |
|||
{isActive && <span css={activeLinkBefore} />} |
|||
{item.title} |
|||
</Link> |
|||
); |
|||
}; |
|||
|
|||
const createLinkCommunity = ({item, location, section}) => { |
|||
if (item.href) { |
|||
return ( |
|||
<a css={[linkCss]} href={item.href} target="_blank" rel="noopener"> |
|||
{item.title} |
|||
<ExternalLinkSvg |
|||
cssProps={{ |
|||
verticalAlign: -2, |
|||
display: 'inline-block', |
|||
marginLeft: 5, |
|||
color: colors.subtle, |
|||
}} |
|||
/> |
|||
</a> |
|||
); |
|||
} |
|||
return createLinkDocs({ |
|||
item, |
|||
location, |
|||
section, |
|||
}); |
|||
}; |
|||
|
|||
const createLinkDocs = ({item, location, section}) => { |
|||
const isActive = isItemActive(location, item); |
|||
|
|||
return ( |
|||
<Link |
|||
css={[linkCss, isActive && activeLinkCss]} |
|||
to={slugify(item.id, section.directory)}> |
|||
{isActive && <span css={activeLinkBefore} />} |
|||
{item.title} |
|||
</Link> |
|||
); |
|||
}; |
|||
|
|||
const createLinkTutorial = ({item, location, onLinkClick, section}) => { |
|||
const isActive = isItemActive(location, item); |
|||
|
|||
return ( |
|||
<Link |
|||
css={[linkCss, isActive && activeLinkCss]} |
|||
onClick={onLinkClick} |
|||
to={item.href}> |
|||
{isActive && <span css={activeLinkBefore} />} |
|||
{item.title} |
|||
</Link> |
|||
); |
|||
}; |
|||
|
|||
const activeLinkCss = { |
|||
fontWeight: 700, |
|||
}; |
|||
|
|||
const activeLinkBefore = { |
|||
width: 4, |
|||
height: 25, |
|||
borderLeft: `4px solid ${colors.brand}`, |
|||
paddingLeft: 16, |
|||
position: 'absolute', |
|||
left: 0, |
|||
marginTop: -3, |
|||
|
|||
[media.greaterThan('largerSidebar')]: { |
|||
left: 15, |
|||
}, |
|||
}; |
|||
|
|||
const linkCss = { |
|||
color: colors.text, |
|||
display: 'inline-block', |
|||
borderBottom: '1px solid transparent', |
|||
transition: 'border 0.2s ease', |
|||
marginTop: 5, |
|||
|
|||
'&:hover': { |
|||
color: colors.subtle, |
|||
}, |
|||
}; |
|||
|
|||
export default { |
|||
createLinkBlog, |
|||
createLinkCommunity, |
|||
createLinkDocs, |
|||
createLinkTutorial, |
|||
}; |
@ -0,0 +1,15 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import {urlRoot} from 'site-constants'; |
|||
|
|||
export default slug => |
|||
slug == null ? null : `${urlRoot}/${slug.replace(/^\//, '')}`; |
@ -0,0 +1,37 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
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) => { |
|||
let activeSection; |
|||
const slugId = pathname.split('/').slice(-1)[0]; |
|||
|
|||
sections.forEach(section => { |
|||
const match = section.items.some( |
|||
item => |
|||
slugId === slugify(item.id) || |
|||
(item.subitems && |
|||
item.subitems.some(subitem => slugId === slugify(subitem.id))), |
|||
); |
|||
if (match) { |
|||
activeSection = section; |
|||
} |
|||
}); |
|||
|
|||
return activeSection; |
|||
}; |
|||
|
|||
export default findSectionForPath; |
@ -0,0 +1,35 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import slugify from 'utils/slugify'; |
|||
|
|||
const toAnchor = (href = '') => { |
|||
const index = href.indexOf('#'); |
|||
return index >= 0 ? href.substr(index) : ''; |
|||
}; |
|||
|
|||
// 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) => { |
|||
if (location.hash) { |
|||
if (item.href) { |
|||
return location.hash === toAnchor(item.href); |
|||
} |
|||
} else if (item.id.includes('html')) { |
|||
return location.pathname.includes(item.id); |
|||
} else { |
|||
const slugId = location.pathname.split('/').slice(-1)[0]; |
|||
return slugId === slugify(item.id); |
|||
} |
|||
}; |
|||
|
|||
export default isItemActive; |
@ -0,0 +1,41 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import CodeEditor from '../components/CodeEditor'; |
|||
import React from 'react'; |
|||
import ReactDOM from 'react-dom'; |
|||
|
|||
// TODO This is a huge hack.
|
|||
// Remark transform this template to split code examples and their targets apart.
|
|||
const mountCodeExample = (containerId, code) => { |
|||
const container = document.getElementById(containerId); |
|||
const parent = container.parentElement; |
|||
|
|||
const children = Array.prototype.filter.call( |
|||
parent.children, |
|||
child => child !== container, |
|||
); |
|||
children.forEach(child => parent.removeChild(child)); |
|||
|
|||
const description = children |
|||
.map(child => child.outerHTML) |
|||
.join('') |
|||
.replace(/`([^`]+)`/g, '<code>$1</code>'); |
|||
|
|||
ReactDOM.render( |
|||
<CodeEditor code={code}> |
|||
{<div dangerouslySetInnerHTML={{__html: description}} />} |
|||
</CodeEditor>, |
|||
container, |
|||
); |
|||
}; |
|||
|
|||
export default mountCodeExample; |
@ -0,0 +1,32 @@ |
|||
/** |
|||
* Copyright 2015-present, Facebook, Inc. |
|||
* All rights reserved. |
|||
* |
|||
* This source code is licensed under the BSD-style license found in the |
|||
* LICENSE file in the root directory of this source tree. An additional grant |
|||
* of patent rights can be found in the PATENTS file in the same directory. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import navCommunity from '../../content/community/nav.yml'; |
|||
import navDocs from '../../content/docs/nav.yml'; |
|||
import navTutorial from '../../content/tutorial/nav.yml'; |
|||
|
|||
const sectionListDocs = navDocs.map(item => ({ |
|||
...item, |
|||
directory: 'docs', |
|||
})); |
|||
|
|||
const sectionListCommunity = navCommunity.map(item => ({ |
|||
...item, |
|||
directory: 'community', |
|||
})); |
|||
|
|||
export { |
|||
sectionListCommunity, |
|||
sectionListDocs, |
|||
navTutorial as sectionListTutorial, |
|||
}; |
@ -0,0 +1,18 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import slugify from 'slugify'; |
|||
|
|||
export default (string, directory) => { |
|||
const filename = slugify(string) + '.html'; |
|||
|
|||
return directory ? `/${directory}/${filename}` : filename; |
|||
}; |
@ -0,0 +1,39 @@ |
|||
/** |
|||
* Copyright (c) 2013-present, Facebook, Inc. |
|||
* |
|||
* This source code is licensed under the MIT license found in the |
|||
* LICENSE file in the root directory of this source tree. |
|||
* |
|||
* @emails react-core |
|||
*/ |
|||
|
|||
'use strict'; |
|||
|
|||
import React from 'react'; |
|||
|
|||
const addString = (list, string) => |
|||
list.push(<span key={`${list.length}-${string}`}>{string}</span>); |
|||
|
|||
const toCommaSeparatedList = (array, renderCallback) => { |
|||
if (array.length <= 1) { |
|||
return array.map(renderCallback); |
|||
} |
|||
|
|||
const list = []; |
|||
|
|||
array.forEach((item, index) => { |
|||
if (index === array.length - 1) { |
|||
addString(list, array.length === 2 ? ' and ' : ', and '); |
|||
list.push(renderCallback(item, index)); |
|||
} else if (index > 0) { |
|||
addString(list, ', '); |
|||
list.push(renderCallback(item, index)); |
|||
} else { |
|||
list.push(renderCallback(item, index)); |
|||
} |
|||
}); |
|||
|
|||
return list; |
|||
}; |
|||
|
|||
export default toCommaSeparatedList; |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,12 @@ |
|||
// Do not delete or move this file.
|
|||
// Many fiddles reference it so we have to keep it here.
|
|||
(function() { |
|||
var tag = document.querySelector( |
|||
'script[type="application/javascript;version=1.7"]' |
|||
); |
|||
if (!tag || tag.textContent.indexOf('window.onload=function(){') !== -1) { |
|||
alert('Bad JSFiddle configuration, please fork the original React JSFiddle'); |
|||
} |
|||
tag.setAttribute('type', 'text/babel'); |
|||
tag.textContent = tag.textContent.replace(/^\/\/<!\[CDATA\[/, ''); |
|||
})(); |
@ -0,0 +1,12 @@ |
|||
// Do not delete or move this file.
|
|||
// Many fiddles reference it so we have to keep it here.
|
|||
(function() { |
|||
var tag = document.querySelector( |
|||
'script[type="application/javascript;version=1.7"]' |
|||
); |
|||
if (!tag || tag.textContent.indexOf('window.onload=function(){') !== -1) { |
|||
alert('Bad JSFiddle configuration, please fork the original React JSFiddle'); |
|||
} |
|||
tag.setAttribute('type', 'text/jsx;harmony=true'); |
|||
tag.textContent = tag.textContent.replace(/^\/\/<!\[CDATA\[/, ''); |
|||
})(); |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 437 B |