diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 40f742563..000000000 --- a/.babelrc +++ /dev/null @@ -1,41 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "loose": true, - "modules": false, - "useBuiltIns": "usage", - "shippedProposals": true, - "targets": { - "browsers": [">0.25%", "not dead"], - } - } - ], - [ - "@babel/preset-react", - { - "useBuiltIns": true, - "pragma": "React.createElement", - } - ], - "@babel/flow" - ], - "plugins": [ - [ - "@babel/plugin-proposal-class-properties", - { - "loose": true - } - ], - "@babel/plugin-syntax-dynamic-import", - "babel-plugin-macros", - [ - "@babel/plugin-transform-runtime", - { - "helpers": true, - "regenerator": true - } - ] - ] -} \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index b0efeb7bc..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: 2 -jobs: - build: - docker: - - image: circleci/node:8 - steps: - - checkout - - restore_cache: - keys: - - dependencies-{{ checksum "yarn.lock" }} - - run: - name: Install - command: yarn install --pure-lockfile - - save_cache: - paths: - - node_modules - key: dependencies-{{ checksum "yarn.lock" }} - - run: - name: Check Prettier, ESLint, Flow - command: yarn ci-check diff --git a/.env.development b/.env.development new file mode 100644 index 000000000..a692f21c7 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +SANDPACK_BARE_COMPONENTS=true \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 000000000..445c9c4d0 --- /dev/null +++ b/.env.production @@ -0,0 +1,2 @@ +NEXT_PUBLIC_GA_TRACKING_ID = 'UA-41298772-4' +SANDPACK_BARE_COMPONENTS=true \ No newline at end of file diff --git a/.eslintignore b/.eslintignore index 942541715..4738cb697 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,10 +1,3 @@ -node_modules/* - -# Ignore markdown files and examples -content/* - -# Ignore built files -public/* - -# Ignore examples -examples/* \ No newline at end of file +scripts +plugins +next.config.js diff --git a/.eslintrc b/.eslintrc index a51454ef2..147e54607 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,18 +1,16 @@ { - "extends": [ - "fbjs" - ], - "plugins": [ - "prettier", - "react" - ], - "parser": "babel-eslint", + "root": true, + "extends": "next/core-web-vitals", + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], "rules": { - "relay/graphql-naming": 0, - "max-len": 0 + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "warn" }, "env": { "node": true, - "browser": true + "commonjs": true, + "browser": true, + "es6": true } } diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index 836f6ec1e..000000000 --- a/.flowconfig +++ /dev/null @@ -1,35 +0,0 @@ -[ignore] - -/content/.* -/node_modules/.* -/public/.* - -[include] - -[libs] -./node_modules/fbjs/flow/lib/dev.js -./flow - -[options] -module.system=haste -module.system.node.resolve_dirname=node_modules -module.system.node.resolve_dirname=src - -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 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d3c569401..7e4f6d2f2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,12 +1,10 @@ - - " + + - name: Create Comment + uses: peter-evans/create-or-update-comment@v1.4.4 + if: success() && steps.fc.outputs.comment-id == 0 + with: + issue-number: ${{ steps.get-comment-body.outputs.pr-number }} + body: ${{ steps.get-comment-body.outputs.body }} + + - name: Update Comment + uses: peter-evans/create-or-update-comment@v1.4.4 + if: success() && steps.fc.outputs.comment-id != 0 + with: + issue-number: ${{ steps.get-comment-body.outputs.pr-number }} + body: ${{ steps.get-comment-body.outputs.body }} + comment-id: ${{ steps.fc.outputs.comment-id }} + edit-mode: replace diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml new file mode 100644 index 000000000..bf446393a --- /dev/null +++ b/.github/workflows/site_lint.yml @@ -0,0 +1,27 @@ +name: Site Lint / Heading ID check + +on: + push: + branches: + - main # change this if your default branch is named differently + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-latest + + name: Lint on node 12.x and ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Use Node.js 12.x + uses: actions/setup-node@v1 + with: + node-version: 12.x + + - name: Install deps and build (with cache) + uses: bahmutov/npm-install@v1.7.10 + + - name: Lint codebase + run: yarn ci-check diff --git a/.gitignore b/.gitignore index d1bde99ce..d8bec488b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,38 @@ -.cache -.DS_STORE -.idea -node_modules -public -yarn-error.log \ No newline at end of file +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem +tsconfig.tsbuildinfo + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel + +# external fonts +public/fonts/**/Optimistic_*.woff2 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..dc0378c34 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +yarn lint-staged \ No newline at end of file diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 5debbed21..000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -lts/carbon diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..96f1f96d2 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +src/content/**/*.md diff --git a/.prettierrc b/.prettierrc index eb91e6abb..19b54ad05 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,21 @@ { "bracketSpacing": false, - "jsxBracketSameLine": true, - "parser": "flow", - "printWidth": 80, "singleQuote": true, - "trailingComma": "all" -} \ No newline at end of file + "bracketSameLine": true, + "trailingComma": "es5", + "printWidth": 80, + "overrides": [ + { + "files": "*.css", + "options": { + "parser": "css" + } + }, + { + "files": "*.md", + "options": { + "parser": "mdx" + } + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e10f4f53e..0e861af35 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,19 +18,9 @@ This is a [good summary](https://medium.com/@kvosswinkel/coding-like-a-journalis The documentation is divided into sections to cater to different learning styles and use cases. When editing an article, try to match the surrounding text in tone and style. When creating a new article, try to match the tone of the other articles in the same section. Learn about the motivation behind each section below. -**[Installation](https://reactjs.org/docs/getting-started.html)** gives an overview of the docs, and demonstrates two different ways to use it: either as a simple ` - -## CoffeeScript integration {#coffeescript-integration} - -[Vjeux](http://blog.vjeux.com/) used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript. - -> Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable. -> -> ```javascript -> {div, h3, textarea} = React.DOM -> (div {className: 'MarkdownEditor'}, [ -> (h3 {}, 'Input'), -> (textarea {onKeyUp: @handleKeyUp, ref: 'textarea'}, -> @state.value -> ) -> ]) -> ``` -> -> [Read the full post...](http://blog.vjeux.com/2013/javascript/react-coffeescript.html) - -## Tutorial in Plain JavaScript {#tutorial-in-plain-javascript} - -We've seen a lot of people comparing React with various frameworks. [Ricardo Tomasi](http://ricardo.cc/) decided to re-implement the tutorial without any framework, just plain JavaScript. - -> Facebook & Instagram launched the React framework and an accompanying tutorial. Developer Vlad Yazhbin decided to rewrite that using AngularJS. The end result is pretty neat, but if you're like me you will not actually appreciate the HTML speaking for itself and doing all the hard work. So let's see what that looks like in plain javascript. -> -> [Read the full post...](http://ricardo.cc/2013/06/07/react-tutorial-rewritten-in-plain-javascript.html) diff --git a/content/blog/2013-07-02-react-v0-4-autobind-by-default.md b/content/blog/2013-07-02-react-v0-4-autobind-by-default.md deleted file mode 100644 index 9c98fd9b2..000000000 --- a/content/blog/2013-07-02-react-v0-4-autobind-by-default.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: "New in React v0.4: Autobind by Default" -author: [zpao] ---- - -React v0.4 is very close to completion. As we finish it off, we'd like to share with you some of the major changes we've made since v0.3. This is the first of several posts we'll be making over the next week. - - -## What is React.autoBind? {#what-is-reactautobind} - -If you take a look at most of our current examples, you'll see us using `React.autoBind` for event handlers. This is used in place of `Function.prototype.bind`. Remember that in JS, [function calls are late-bound](https://bonsaiden.github.io/JavaScript-Garden/#function.this). That means that if you simply pass a function around, the `this` used inside won't necessarily be the `this` you expect. `Function.prototype.bind` creates a new, properly bound, function so that when called, `this` is exactly what you expect it to be. - -Before we launched React, we would write this: - -```js{4} -React.createClass({ - onClick: function(event) {/* do something with this */}, - render: function() { - return + + + +

That's right!

+ + +``` + + + +Manipulating the UI imperatively works well enough for isolated examples, but it gets exponentially more difficult to manage in more complex systems. Imagine updating a page full of different forms like this one. Adding a new UI element or a new interaction would require carefully checking all existing code to make sure you haven't introduced a bug (for example, forgetting to show or hide something). + +React was built to solve this problem. + +In React, you don't directly manipulate the UI--meaning you don't enable, disable, show, or hide components directly. Instead, you **declare what you want to show,** and React figures out how to update the UI. Think of getting into a taxi and telling the driver where you want to go instead of telling them exactly where to turn. It's the driver's job to get you there, and they might even know some shortcuts you haven't considered! + + + +## Thinking about UI declaratively {/*thinking-about-ui-declaratively*/} + +You've seen how to implement a form imperatively above. To better understand how to think in React, you'll walk through reimplementing this UI in React below: + +1. **Identify** your component's different visual states +2. **Determine** what triggers those state changes +3. **Represent** the state in memory using `useState` +4. **Remove** any non-essential state variables +5. **Connect** the event handlers to set the state + +### Step 1: Identify your component's different visual states {/*step-1-identify-your-components-different-visual-states*/} + +In computer science, you may hear about a ["state machine"](https://en.wikipedia.org/wiki/Finite-state_machine) being in one of several “states”. If you work with a designer, you may have seen mockups for different "visual states". React stands at the intersection of design and computer science, so both of these ideas are sources of inspiration. + +First, you need to visualize all the different "states" of the UI the user might see: + +* **Empty**: Form has a disabled "Submit" button. +* **Typing**: Form has an enabled "Submit" button. +* **Submitting**: Form is completely disabled. Spinner is shown. +* **Success**: "Thank you" message is shown instead of a form. +* **Error**: Same as Typing state, but with an extra error message. + +Just like a designer, you'll want to "mock up" or create "mocks" for the different states before you add logic. For example, here is a mock for just the visual part of the form. This mock is controlled by a prop called `status` with a default value of `'empty'`: + + + +```js +export default function Form({ + status = 'empty' +}) { + if (status === 'success') { + return

That's right!

+ } + return ( + <> +

City quiz

+

+ In which city is there a billboard that turns air into drinkable water? +

+
+ ` is not allowed. [Use `defaultValue` for initial content.](#providing-an-initial-value-for-a-text-area) +- If a text area receives a string `value` prop, it will be [treated as controlled.](#controlling-a-text-area-with-a-state-variable) +- A text area can't be both controlled and uncontrolled at the same time. +- A text area cannot switch between being controlled or uncontrolled over its lifetime. +- Every controlled text area needs an `onChange` event handler that synchronously updates its backing value. + +--- + +## Usage {/*usage*/} + +### Displaying a text area {/*displaying-a-text-area*/} + +Render `` is not supported. + + + +--- + +### Reading the text area value when submitting a form {/*reading-the-text-area-value-when-submitting-a-form*/} + +Add a [``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form) around your textarea with a [`