@ -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 |