Migrated Gatsby website source and config
4
.babelrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": ['react', 'es2015', 'stage-1'],
|
||||
"plugins": ['add-module-exports']
|
||||
}
|
||||
7
.eslintignore
Normal file
@@ -0,0 +1,7 @@
|
||||
node_modules/*
|
||||
|
||||
# Ignore markdown files and examples
|
||||
content/*
|
||||
|
||||
# Ignore built files
|
||||
public/*
|
||||
7
.eslintrc
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
"prettier",
|
||||
"react"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
}
|
||||
33
.flowconfig
Normal file
@@ -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
|
||||
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.cache
|
||||
.DS_STORE
|
||||
node_modules
|
||||
public
|
||||
393
LICENSE.md
Normal file
@@ -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.
|
||||
54
README.md
Normal file
@@ -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
|
||||
3
flow-typed/hex2rgba.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
declare module 'hex2rgba' {
|
||||
declare module.exports: (hex : string, alpha? : number) => string;
|
||||
}
|
||||
142
gatsby-config.js
Normal file
@@ -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',
|
||||
],
|
||||
};
|
||||
244
gatsby-node.js
Normal file
@@ -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();
|
||||
});
|
||||
};
|
||||
80
package.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
22
plugins/gatsby-remark-use-jsx/index.js
Normal file
@@ -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);
|
||||
}
|
||||
});
|
||||
};
|
||||
4
plugins/gatsby-remark-use-jsx/package.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "gatsby-remark-use-jsx",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
19
plugins/gatsby-source-react-error-codes/gatsby-node.js
Normal file
@@ -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,
|
||||
},
|
||||
});
|
||||
};
|
||||
4
plugins/gatsby-source-react-error-codes/package.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "gatsby-source-react-error-codes",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
33
plugins/gatsby-transformer-authors-yaml/gatsby-node.js
Normal file
@@ -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,
|
||||
});
|
||||
});
|
||||
};
|
||||
4
plugins/gatsby-transformer-authors-yaml/package.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "gatsby-transformer-authors-yaml",
|
||||
"version": "0.0.1"
|
||||
}
|
||||
282
src/components/CodeEditor/CodeEditor.js
Normal file
@@ -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;
|
||||
14
src/components/CodeEditor/index.js
Normal file
@@ -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;
|
||||
40
src/components/Container/Container.js
Normal file
@@ -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;
|
||||
14
src/components/Container/index.js
Normal file
@@ -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;
|
||||
120
src/components/ErrorDecoder/ErrorDecoder.js
Normal file
@@ -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;
|
||||
14
src/components/ErrorDecoder/index.js
Normal file
@@ -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;
|
||||
45
src/components/Flex/Flex.js
Normal file
@@ -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;
|
||||
14
src/components/Flex/index.js
Normal file
@@ -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;
|
||||
26
src/components/Header/Header.js
Normal file
@@ -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;
|
||||
14
src/components/Header/index.js
Normal file
@@ -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;
|
||||
39
src/components/LayoutFooter/ExternalFooterLink.js
Normal file
@@ -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;
|
||||
193
src/components/LayoutFooter/Footer.js
Normal file
@@ -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;
|
||||
30
src/components/LayoutFooter/FooterLink.js
Normal file
@@ -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;
|
||||
39
src/components/LayoutFooter/FooterNav.js
Normal file
@@ -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;
|
||||
14
src/components/LayoutFooter/index.js
Normal file
@@ -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;
|
||||
251
src/components/LayoutHeader/Header.js
Normal file
@@ -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;
|
||||
74
src/components/LayoutHeader/HeaderLink.js
Normal file
@@ -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;
|
||||
33
src/components/LayoutHeader/SearchSvg.js
Normal file
@@ -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;
|
||||
14
src/components/LayoutHeader/index.js
Normal file
@@ -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;
|
||||
43
src/components/MarkdownHeader/MarkdownHeader.js
Normal file
@@ -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;
|
||||
14
src/components/MarkdownHeader/index.js
Normal file
@@ -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;
|
||||
140
src/components/MarkdownPage/MarkdownPage.js
Normal file
@@ -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;
|
||||
14
src/components/MarkdownPage/index.js
Normal file
@@ -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;
|
||||
14
src/components/StickyResponsiveSidebar/index.js
Normal file
@@ -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;
|
||||
33
src/components/TitleAndMetaTags/TitleAndMetaTags.js
Normal file
@@ -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;
|
||||
14
src/components/TitleAndMetaTags/index.js
Normal file
@@ -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;
|
||||
453
src/css/algolia.css
Normal file
42
src/css/reset.css
Normal file
@@ -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;
|
||||
}
|
||||
66
src/html.js
Normal file
@@ -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>
|
||||
);
|
||||
}
|
||||
}
|
||||
1
src/icons/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 20.46348"><title>logo</title><path d="M18.9107,6.63257h0q-.36721-.126-.74042-.2333.06187-.25141.11441-.505c.56045-2.72064.194-4.91237-1.05739-5.63386-1.1998-.692-3.1621.02952-5.14394,1.75414q-.29293.2555-.57267.52554-.18727-.17951-.3811-.352C9.05257.3439,6.97066-.43316,5.72058.29046,4.52191.98436,4.16686,3.04489,4.67144,5.62322q.0753.383.17.76179c-.29458.08367-.57908.17284-.85127.26771C1.55514,7.50165,0,8.83225,0,10.21231c0,1.42546,1.66935,2.8552,4.20575,3.722q.3085.10494.62193.19442-.10179.408-.18068.82114c-.48106,2.53354-.10535,4.54521,1.09017,5.23484,1.23481.712,3.30725-.01985,5.32533-1.78387q.23926-.20917.47994-.44238.3029.29225.62173.56727c1.95477,1.68207,3.88531,2.36132,5.07982,1.66986,1.23369-.71416,1.63454-2.87525,1.114-5.50459q-.05955-.30124-.13792-.61481.21834-.06443.42772-.13355C21.28454,13.06915,23,11.65681,23,10.21232,23,8.82726,21.39478,7.48771,18.9107,6.63257ZM12.7284,2.75581C14.42646,1.278,16.01346.69457,16.73657,1.1116h0c.77014.44421,1.06971,2.2354.5858,4.58441q-.04758.22953-.10342.45724a23.53752,23.53752,0,0,0-3.07527-.48584A23.08128,23.08128,0,0,0,12.1995,3.24094Q12.45788,2.99184,12.7284,2.75581ZM6.79111,11.39124q.312.60265.65207,1.19013.34692.59911.7221,1.18117a20.92168,20.92168,0,0,1-2.11967-.3408C6.24867,12.766,6.49887,12.08443,6.79111,11.39124ZM6.79,9.08041c-.28613-.67863-.53093-1.34586-.73085-1.99019.65624-.14688,1.356-.26689,2.08516-.358q-.36611.571-.7051,1.15877Q7.10076,8.478,6.79,9.08041Zm.52228,1.15552q.45411-.94517.9783-1.8542v.0002q.52369-.90857,1.11521-1.77542c.684-.05171,1.38536-.07879,2.09432-.07879.71212,0,1.41437.02728,2.09819.0794q.58514.86487,1.10818,1.76941.52565.90635.99153,1.84545-.46083.94817-.98828,1.86173h-.0001q-.52261.90786-1.1034,1.7803c-.6824.04876-1.3876.0739-2.10623.0739-.71568,0-1.41193-.02229-2.08241-.06575q-.59555-.86995-1.12406-1.78305Q7.76789,11.18148,7.31227,10.23593Zm8.24853,2.33862q.347-.60182.667-1.21863h0a20.86671,20.86671,0,0,1,.77238,2.02327,20.85164,20.85164,0,0,1-2.14552.36573Q15.21935,13.16682,15.5608,12.57455Zm.65767-3.49343q-.31883-.605-.66163-1.19684h0q-.33727-.58258-.6994-1.15022c.7339.09263,1.437.21579,2.09717.36654A20.95909,20.95909,0,0,1,16.21847,9.08112ZM11.511,3.94359a21.01288,21.01288,0,0,1,1.3535,1.63393q-1.35843-.06419-2.7184-.00061C10.593,4.98765,11.0507,4.44022,11.511,3.94359ZM6.21284,1.14081c.76953-.44543,2.47095.18973,4.26428,1.782.11461.10179.22974.20836.34507.3186A23.54542,23.54542,0,0,0,8.86294,5.66608a24.008,24.008,0,0,0-3.06916.477q-.088-.35228-.15808-.70866v.0001C5.20339,3.22536,5.49044,1.559,6.21284,1.14081ZM5.09132,13.18233q-.286-.08187-.56778-.17773A8.32371,8.32371,0,0,1,1.841,11.57955a2.03072,2.03072,0,0,1-.85849-1.36724c0-.83742,1.24865-1.90571,3.33117-2.63178q.39208-.1361.79162-.24908a23.56455,23.56455,0,0,0,1.121,2.90478A23.92247,23.92247,0,0,0,5.09132,13.18233ZM10.41594,17.661a8.32161,8.32161,0,0,1-2.57467,1.61184h-.0001a2.03042,2.03042,0,0,1-1.61306.06067c-.72556-.41836-1.02706-2.03376-.61573-4.20035q.07337-.38407.168-.76363a23.10444,23.10444,0,0,0,3.0995.44869,23.90954,23.90954,0,0,0,1.97431,2.43929Q10.64,17.46459,10.41594,17.661Zm1.12223-1.11053c-.46569-.50253-.93015-1.05831-1.38383-1.65612q.66051.026,1.34566.02606.70326,0,1.38841-.03084A20.89425,20.89425,0,0,1,11.53817,16.55045Zm5.96651,1.367a2.03039,2.03039,0,0,1-.753,1.4278c-.72485.41958-2.275-.12581-3.94659-1.56431q-.2875-.24735-.57837-.52727a23.08914,23.08914,0,0,0,1.9279-2.448,22.93647,22.93647,0,0,0,3.11507-.48014q.07024.284.12449.55638h0A8.32,8.32,0,0,1,17.50468,17.91749Zm.83417-4.90739h-.0001c-.12571.04163-.25478.08184-.38629.12082a23.06121,23.06121,0,0,0-1.16468-2.91373,23.05112,23.05112,0,0,0,1.11938-2.87128c.23524.0682.46365.14.68372.21579,2.12842.73258,3.42665,1.81593,3.42665,2.65061C22.01753,11.10145,20.61538,12.25574,18.33885,13.0101Z" fill="#61dafb"/><path d="M11.5,8.1585a2.05386,2.05386,0,1,1-2.05381,2.05381A2.05381,2.05381,0,0,1,11.5,8.1585" fill="#61dafb"/></svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/images/oss_logo.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
1
src/index.js
Normal file
@@ -0,0 +1 @@
|
||||
var foo = 'bar';
|
||||
85
src/layouts/index.js
Normal file
@@ -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;
|
||||
34
src/pages/404.js
Normal file
@@ -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;
|
||||
88
src/pages/acknowledgements.html.js
Normal file
@@ -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;
|
||||
117
src/pages/blog/all.html.js
Normal file
@@ -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;
|
||||
116
src/pages/docs/error-decoder.html.js
Normal file
@@ -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;
|
||||
BIN
src/pages/favicon.ico
Normal file
|
After Width: | Height: | Size: 198 B |
38
src/pages/jsx-compiler.html.js
Normal file
@@ -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;
|
||||
2
src/pages/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
||||
171
src/prism-styles.js
Normal file
@@ -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,
|
||||
});
|
||||
22
src/site-constants.js
Normal file
@@ -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',
|
||||
};
|
||||
91
src/templates/blog.js
Normal file
@@ -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;
|
||||
50
src/templates/community.js
Normal file
@@ -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;
|
||||
87
src/templates/components/ButtonLink/ButtonLink.js
Normal file
@@ -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;
|
||||
14
src/templates/components/ButtonLink/index.js
Normal file
@@ -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;
|
||||
41
src/templates/components/ChevronSvg/index.js
Normal file
@@ -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;
|
||||
39
src/templates/components/ExternalLinkSvg/index.js
Normal file
@@ -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;
|
||||
38
src/templates/components/MetaTitle/index.js
Normal file
@@ -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;
|
||||
136
src/templates/components/NavigationFooter/NavigationFooter.js
Normal file
@@ -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>
|
||||
);
|
||||
14
src/templates/components/NavigationFooter/index.js
Normal file
@@ -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;
|
||||
96
src/templates/components/Sidebar/Section.js
Normal file
@@ -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;
|
||||
70
src/templates/components/Sidebar/Sidebar.js
Normal file
@@ -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;
|
||||
14
src/templates/components/Sidebar/index.js
Normal file
@@ -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;
|
||||
50
src/templates/docs.js
Normal file
@@ -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;
|
||||
470
src/templates/home.js
Normal file
@@ -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();
|
||||
61
src/templates/tutorial.js
Normal file
@@ -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;
|
||||
407
src/theme.js
Normal file
@@ -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,
|
||||
};
|
||||
117
src/utils/createLink.js
Normal file
@@ -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,
|
||||
};
|
||||
15
src/utils/createOgUrl.js
Normal file
@@ -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(/^\//, '')}`;
|
||||
37
src/utils/findSectionForPath.js
Normal file
@@ -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;
|
||||
35
src/utils/isItemActive.js
Normal file
@@ -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;
|
||||
41
src/utils/mountCodeExample.js
Normal file
@@ -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;
|
||||
32
src/utils/sectionList.js
Normal file
@@ -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,
|
||||
};
|
||||
18
src/utils/slugify.js
Normal file
@@ -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;
|
||||
};
|
||||
39
src/utils/toCommaSeparatedList.js
Normal file
@@ -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;
|
||||
BIN
static/external.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
static/favicon.ico
Normal file
|
After Width: | Height: | Size: 24 KiB |
12
static/js/jsfiddle-integration-babel.js
Normal file
@@ -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\[/, '');
|
||||
})();
|
||||
12
static/js/jsfiddle-integration.js
Normal file
@@ -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\[/, '');
|
||||
})();
|
||||
1
static/large-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 823.85795 733"><title>large-logo</title><g opacity="0.05"><path d="M677.3796,237.5782v-.00013q-13.15347-4.51184-26.52168-8.35682,2.2162-9.00546,4.09815-18.08832c20.07545-97.45293,6.9495-175.96071-37.87563-201.8043C574.10386-15.45755,503.81433,10.386,432.82482,72.16188q-10.49272,9.15182-20.513,18.8248-6.70815-6.42994-13.651-12.60818c-74.39859-66.06005-148.97227-93.89436-193.75-67.97423-42.93648,24.85548-55.65406,98.66342-37.5803,191.01912q2.69729,13.71891,6.08893,27.28742c-10.55176,2.99712-20.74263,6.19108-30.49228,9.58925C55.70506,268.70848,0,316.37033,0,365.80411c0,51.06,59.796,102.27313,150.64951,133.32334q11.05033,3.759,22.27764,6.96393-3.64625,14.61321-6.47177,29.4132c-17.23148,90.75134-3.77376,162.80916,39.04973,187.51155,44.23076,25.50438,118.46536-.71107,190.75293-63.898q8.57022-7.49254,17.19138-15.84583,10.8498,10.46823,22.27032,20.3197c70.01968,60.25168,139.17161,84.58221,181.9586,59.81425,44.19066-25.581,58.549-102.99126,39.90285-197.17376q-2.13293-10.79053-4.94043-22.02241,7.82091-2.308,15.32089-4.78369C762.41022,468.13563,823.858,417.546,823.858,365.80425,823.858,316.19178,766.35894,268.20914,677.3796,237.5782ZM455.93017,98.71275c60.82417-52.934,117.67049-73.83348,143.5724-58.89543h.00007c27.58633,15.9116,38.31685,80.072,20.98329,164.213q-1.70415,8.22186-3.70447,16.37829A843.11184,843.11184,0,0,0,506.62552,203.0058c-22.63859-32.23516-46.09393-61.54615-69.6405-86.91573Q446.24028,107.16747,455.93017,98.71275ZM243.25691,408.03318q11.17562,21.58674,23.35692,42.63018,12.4265,21.46008,25.86547,42.30946a749.41279,749.41279,0,0,1-75.92641-12.20726C223.8269,457.27737,232.789,432.86312,243.25691,408.03318Zm-.0401-82.7737c-10.24913-24.30852-19.018-48.20874-26.17895-71.28855,23.50634-5.26129,48.57329-9.56006,74.69032-12.82331q-13.1139,20.4542-25.25653,41.50721Q254.34864,303.68289,243.21681,325.25948ZM261.9249,366.65q16.266-33.856,35.04269-66.41735v.00731q18.75838-32.54479,39.94668-63.59526c24.50177-1.85227,49.62338-2.82209,75.01843-2.82209,25.50817,0,50.66256.97714,75.15708,2.844q20.95959,30.97974,39.695,63.38007,18.82881,32.46544,35.51663,66.10381-16.50682,33.96338-35.39993,66.68714l-.00366.00007q-18.71978,32.51932-39.52367,63.77022c-24.44345,1.7466-49.70364,2.64707-75.44509,2.64707-25.63571,0-50.575-.79833-74.5919-2.35527q-21.33273-31.16146-40.26388-63.86883Q278.245,400.51974,261.9249,366.65Zm295.46159,83.76919q12.43081-21.55706,23.8929-43.65115h.00007a747.44376,747.44376,0,0,1,27.66653,72.4735,746.90393,746.90393,0,0,1-76.85248,13.10041Q545.15579,471.63431,557.38649,450.41918ZM580.944,325.28495Q569.52351,303.615,557.24445,282.4141v.00007q-12.081-20.868-25.05238-41.20092c26.2884,3.31791,51.472,7.72974,75.12057,13.1296A750.753,750.753,0,0,1,580.944,325.28495ZM412.32291,141.25908A752.67935,752.67935,0,0,1,460.805,199.78624q-48.65887-2.29927-97.37267-.02188C379.43872,178.65711,395.83523,159.04842,412.32291,141.25908ZM222.5434,40.86376C250.10793,24.9084,311.05246,47.66,375.2895,104.696c4.10546,3.64609,8.22921,7.46354,12.36021,11.41226a843.39474,843.39474,0,0,0-70.18008,86.8501A859.96423,859.96423,0,0,0,207.53247,220.044q-3.15066-12.6187-5.66241-25.38408v.00359C186.38506,115.5322,196.667,55.84191,222.5434,40.86376ZM182.3707,472.19q-10.24566-2.93259-20.33792-6.3661c-40.17271-13.73122-73.34857-31.57522-96.0893-51.04533-20.43275-17.50133-30.75117-34.875-30.75117-48.97441,0-29.99646,44.72664-68.26231,119.3222-94.26995q14.04424-4.87509,28.35573-8.922A844.0802,844.0802,0,0,0,223.02473,366.661,856.90089,856.90089,0,0,0,182.3707,472.19ZM373.09815,632.61472c-31.96537,27.94364-63.99632,47.76386-92.22443,57.736l-.00366-.00013c-25.36593,8.95844-45.56892,9.21367-57.7797,2.17319-25.98942-14.9856-36.78916-72.84909-22.05526-150.45626q2.62813-13.75741,6.01605-27.35312c33.74463,7.46354,71.0989,12.83435,111.02376,16.07206a856.43741,856.43741,0,0,0,70.71972,87.37518Q381.12547,625.58012,373.09815,632.61472Zm40.19824-39.779c-16.68093-18.00074-33.318-37.90848-49.56871-59.322q23.65952.92986,48.20142.93338,25.19087,0,49.73277-1.10475A748.43012,748.43012,0,0,1,413.2964,592.83569Zm213.71969,48.96723c-4.90764,26.44873-14.774,44.0814-26.97381,51.14381-25.96389,15.02922-81.49033-4.50652-141.36655-56.0333q-10.29837-8.85989-20.71716-18.88671c23.21474-25.3914,46.41485-54.91026,69.05717-87.68879,39.83-3.53291,77.45769-9.31215,111.58149-17.19849q2.51586,10.17258,4.45924,19.92955v-.00013C631.3003,574.71465,632.47794,612.3679,627.01609,641.80291Zm29.87976-175.78216h-.00359c-4.50293,1.49124-9.12622,2.93148-13.837,4.3279-10.42787-33.00808-24.50177-68.10909-41.71868-104.36958a825.689,825.689,0,0,0,40.09617-102.84915c8.42612,2.44291,16.60791,5.01338,24.4908,7.72974,76.24,26.241,122.74232,65.0464,122.74232,94.94445C788.6659,397.65278,738.44091,438.99953,656.89585,466.02076Z" fill="#fff"/><path d="M411.929,292.23677a73.56917,73.56917,0,1,1-73.56735,73.56735A73.56713,73.56713,0,0,1,411.929,292.23677" fill="#fff"/></g></svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
BIN
static/logo-og.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
14
static/search.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg
|
||||
alt="Search"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<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="#ffffff"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 437 B |