diff --git a/package.json b/package.json index d6a22d33b56..03cdedf9ff6 100644 --- a/package.json +++ b/package.json @@ -159,6 +159,7 @@ "react-axe": "^3.0.2", "react-dom": "^18.0.0", "react-test-renderer": "^16.9.0", + "recast": "^0.20", "recursive-readdir": "^2.2.2", "regenerator-runtime": "0.13.3", "rimraf": "^2.6.3", diff --git a/packages/dev/docs/pages/react-aria/getting-started.mdx b/packages/dev/docs/pages/react-aria/getting-started.mdx index a445aad537c..34c0f736744 100644 --- a/packages/dev/docs/pages/react-aria/getting-started.mdx +++ b/packages/dev/docs/pages/react-aria/getting-started.mdx @@ -28,18 +28,32 @@ screen readers. ## Installation -React Aria is **incrementally adoptable**. Each component is published as a separate package, so you can try it -out in a single component and gradually add more over time. All of these packages are published under the -[@react-aria](https://www.npmjs.com/org/react-aria) scope on npm. - -You can install any React Aria package using a package manager like [npm](https://docs.npmjs.com/cli/npm) or +React Aria can be installed using a package manager like [npm](https://docs.npmjs.com/cli/npm) or [yarn](https://classic.yarnpkg.com/lang/en/). +``` +yarn add react-aria +``` + +If you prefer, you can also use our hooks from individually versioned packages. This allows you to only +install the hooks you use, or more granularly manage their versions. The individual packages are published +under the [@react-aria](https://www.npmjs.com/org/react-aria) scope on npm. For example: + ``` yarn add @react-aria/button ``` -We also offer a single package containing all React Aria hooks. See [below](#mono-package) for details. +Once installed, hooks can be used from the monopackage or individual packages the same way. + +```tsx +// Monopackage +import {useButton} from 'react-aria'; +``` + +```tsx keepIndividualImports +// Individual packages +import {useButton} from '@react-aria/button'; +``` ## Building a component @@ -123,31 +137,6 @@ function Checkbox(props) { See the [useCheckbox](useCheckbox.html) docs for a full example of a custom styled checkbox. -## Mono-package - -In addition to individual packages, we also offer a mono-package containing all of the React Aria hooks in a single -package. This ensures that all packages use compatible versions and are upgraded together. If you release all components -in your component library in a single package, or just want to get started easily without installing a lot of packages, -the mono-package may be the way to go. It is available as the [react-aria](https://npmjs.com/package/react-aria) package -on npm. - -``` -yarn add react-aria -``` - -Once installed, all hooks work the same way as the individual packages, but are imported from the `react-aria` package -instead of individual packages. - -```tsx -// Individual packages -import {useButton} from '@react-aria/button'; -``` - -```tsx -// Monopackage -import {useButton} from 'react-aria'; -``` - ## Next steps Now that you understand how to use the hooks in React Aria to build your own components, you can read the documentation diff --git a/packages/dev/docs/pages/react-stately/getting-started.mdx b/packages/dev/docs/pages/react-stately/getting-started.mdx index e109a28d1b6..664cbbaf8da 100644 --- a/packages/dev/docs/pages/react-stately/getting-started.mdx +++ b/packages/dev/docs/pages/react-stately/getting-started.mdx @@ -31,18 +31,32 @@ and user interactions for many components, while React Stately provides state ma ## Installation -React Stately is **incrementally adoptable**. Each component is published as a separate package, so you can try it -out in a single component and gradually add more over time. All of these packages are published under the -[@react-stately](https://www.npmjs.com/org/react-stately) scope on npm. - -You can install any React Stately package using a package manager like [npm](https://docs.npmjs.com/cli/npm) or +React Stately can be installed using a package manager like [npm](https://docs.npmjs.com/cli/npm) or [yarn](https://classic.yarnpkg.com/lang/en/). +``` +yarn add react-stately +``` + +If you prefer, you can also use our hooks from individually versioned packages. This allows you to only +install the hooks you use, or more granularly manage their versions. The individual packages are published +under the [@react-stately](https://www.npmjs.com/org/react-stately) scope on npm. For example: + ``` yarn add @react-stately/radio ``` -We also offer a single package containing all React Stately hooks. See [below](#mono-package) for details. +Once installed, hooks can be used from the monopackage or individual packages the same way. + +```tsx +// Monopackage +import {useRadioGroupState} from 'react-stately'; +``` + +```tsx keepIndividualImports +// Individual packages +import {useRadioGroupState} from '@react-stately/radio'; +``` ## Building a component @@ -88,31 +102,6 @@ If you're using React Stately on the web, see [useRadioGroup](../react-aria/useR handle more of this behavior and accessibility for you. To see an example of how React Stately manages more complex state, see [useSelectState](useSelectState.html). -## Mono-package - -In addition to individual packages, we also offer a mono-package containing all of the React Stately hooks in a single -package. This ensures that all packages use compatible versions and are upgraded together. If you release all components -in your component library in a single package, or just want to get started easily without installing a lot of packages, -the mono-package may be the way to go. It is available as the [react-stately](https://npmjs.com/package/react-stately) package -on npm. - -``` -yarn add react-stately -``` - -Once installed, all hooks work the same way as the individual packages, but are imported from the `react-stately` package -instead of individual packages. - -```tsx -// Individual packages -import {useRadioGroupState} from '@react-stately/radio'; -``` - -```tsx -// Monopackage -import {useRadioGroupState} from 'react-stately'; -``` - ## Next steps Now that you understand how to use the hooks in React Stately to build your own components, you can read the documentation diff --git a/packages/dev/docs/src/HeaderInfo.js b/packages/dev/docs/src/HeaderInfo.js index 2ced37fdaec..a7643d777af 100644 --- a/packages/dev/docs/src/HeaderInfo.js +++ b/packages/dev/docs/src/HeaderInfo.js @@ -10,16 +10,34 @@ * governing permissions and limitations under the License. */ +import ariaMonopackage from 'react-aria/package.json'; import {Flex} from '@react-spectrum/layout'; import js from 'highlight.js/lib/languages/javascript'; import Lowlight from 'react-lowlight'; import React from 'react'; import {ResourceCard} from './ResourceCard'; +import rspMonopackage from '@adobe/react-spectrum/package.json'; +import statelyMonopackage from 'react-stately/package.json'; import styles from './headerInfo.css'; import typographyStyles from '@adobe/spectrum-css-temp/components/typography/vars.css'; Lowlight.registerLanguage('js', js); +const monopackages = { + '@react-spectrum': { + importName: '@adobe/react-spectrum', + version: rspMonopackage.version + }, + '@react-aria': { + importName: 'react-aria', + version: ariaMonopackage.version + }, + '@react-stately': { + importName: 'react-stately', + version: statelyMonopackage.version + } +}; + export function HeaderInfo(props) { let { packageData, @@ -29,8 +47,12 @@ export function HeaderInfo(props) { let preRelease = packageData.version.match(/(alpha)|(beta)|(rc)/); let importName = packageData.name; - if (importName.startsWith('@react-spectrum') && process.env.DOCS_ENV === 'production' && !preRelease) { - importName = '@adobe/react-spectrum'; + let version = packageData.version; + if (!preRelease) { + let scope = importName.split('/')[0]; + if (monopackages[scope]) { + ({importName, version} = monopackages[scope]); + } } return ( @@ -43,7 +65,7 @@ export function HeaderInfo(props) { version - {packageData.version} + {version} {componentNames && diff --git a/packages/dev/parcel-transformer-mdx-docs/MDXTransformer.js b/packages/dev/parcel-transformer-mdx-docs/MDXTransformer.js index 1c4b25c0c42..59e4c21cc0b 100644 --- a/packages/dev/parcel-transformer-mdx-docs/MDXTransformer.js +++ b/packages/dev/parcel-transformer-mdx-docs/MDXTransformer.js @@ -407,32 +407,42 @@ function transformExample(node, preRelease) { /* Replace individual package imports in the code * with monorepo imports if building for production and not a pre-release */ - if (process.env.DOCS_ENV === 'production' && !preRelease && node.value.includes('@react-spectrum')) { - let specifiers = []; - let last; + if (!preRelease && /@react-spectrum|@react-aria|@react-stately/.test(node.value)) { + let specifiers = {}; + const recast = require('recast'); const traverse = require('@babel/traverse').default; const {parse} = require('@babel/parser'); - const generate = require('@babel/generator').default; - let ast = parse(node.value, { - sourceType: 'module', - plugins: ['jsx', 'typescript'] + let ast = recast.parse(node.value, { + parser: { + parse() { + return parse(node.value, { + sourceType: 'module', + plugins: ['jsx', 'typescript'], + tokens: true + }); + } + } }); traverse(ast, { ImportDeclaration(path) { - if (path.node.source.value.startsWith('@react-spectrum') && !(node.meta && node.meta.split(' ').includes('keepIndividualImports'))) { + if (/^(@react-spectrum|@react-aria|@react-stately)/.test(path.node.source.value) && !(node.meta && node.meta.split(' ').includes('keepIndividualImports'))) { + let lib = path.node.source.value.split('/')[0]; + if (!specifiers[lib]) { + specifiers[lib] = []; + } + let mapping = IMPORT_MAPPINGS[path.node.source.value]; for (let specifier of path.node.specifiers) { let mapped = mapping && mapping[specifier.imported.name]; if (mapped && specifier.local.name === specifier.imported.name) { path.scope.rename(specifier.local.name, mapped); - specifiers.push(mapped); + specifiers[lib].push(mapped); } else { - specifiers.push(specifier.imported.name); + specifiers[lib].push(specifier.imported.name); } } - last = path.node; path.remove(); } }, @@ -441,26 +451,25 @@ function transformExample(node, preRelease) { }, Program: { exit(path) { - if (specifiers.length > 0) { - let literal = t.stringLiteral('@adobe/react-spectrum'); - literal.raw = "'@adobe/react-spectrum'"; - - let decl = t.importDeclaration( - specifiers.map(s => t.importSpecifier(t.identifier(s), t.identifier(s))), - literal - ); - - decl.loc = last.loc; - decl.start = last.start; - decl.end = last.end; - - path.unshiftContainer('body', [decl]); + for (let lib in specifiers) { + let names = specifiers[lib]; + if (names.length > 0) { + let monopackage = lib === '@react-spectrum' ? '@adobe/react-spectrum' : lib.slice(1); + let literal = t.stringLiteral(monopackage); + + let decl = t.importDeclaration( + names.map(s => t.importSpecifier(t.identifier(s), t.identifier(s))), + literal + ); + + path.unshiftContainer('body', [decl]); + } } } } }); - node.value = generate(ast).code.replace(/((?:.|\n)*<\/WRAPPER>)/g, '\n($1)'); + node.value = recast.print(ast, {objectCurlySpacing: false, quote: 'single'}).code.replace(/((?:.|\n)*<\/WRAPPER>)/g, '\n($1)'); force = true; } diff --git a/yarn.lock b/yarn.lock index 68e4e39c14c..a3909210d34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6272,18 +6272,18 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" - integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== - -ast-types@^0.14.2: +ast-types@0.14.2, ast-types@^0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== dependencies: tslib "^2.0.1" +ast-types@^0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" + integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== + astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -10234,7 +10234,7 @@ espree@^7.3.0: acorn-jsx "^5.2.0" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -19651,6 +19651,16 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +recast@^0.20: + version "0.20.5" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.20.5.tgz#8e2c6c96827a1b339c634dd232957d230553ceae" + integrity sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ== + dependencies: + ast-types "0.14.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"