diff --git a/.eslintignore b/.eslintignore index a9bfa7b1ede..ee0245f39b0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,4 +7,4 @@ node_modules packages/*/*/dist packages/react-aria/dist packages/react-stately/dist -packages/dev/storybook-builder-preview/preview.js +packages/dev/storybook-builder-parcel/preview.js diff --git a/.storybook/custom-addons/strictmode/index.js b/.storybook/custom-addons/strictmode/index.js new file mode 100644 index 00000000000..49415f62acf --- /dev/null +++ b/.storybook/custom-addons/strictmode/index.js @@ -0,0 +1,37 @@ +import {addons, makeDecorator} from '@storybook/addons'; +import {getQueryParams} from '@storybook/client-api'; +import React, {StrictMode, useEffect, useState} from 'react'; + +function StrictModeDecorator(props) { + let {children} = props; + let [isStrict, setStrict] = useState(getQueryParams()?.strict === 'true' || false); + + useEffect(() => { + let channel = addons.getChannel(); + let updateStrict = (val) => { + setStrict(val); + }; + channel.on('strict/updated', updateStrict); + return () => { + channel.removeListener('strict/updated', updateStrict); + }; + }, []); + + return isStrict ? ( + + {children} + + ) : children; +} + +export const withStrictModeSwitcher = makeDecorator({ + name: 'withStrictModeSwitcher', + parameterName: 'strictModeSwitcher', + wrapper: (getStory, context) => { + return ( + + {getStory(context)} + + ); + } +}); diff --git a/.storybook/custom-addons/strictmode/register.js b/.storybook/custom-addons/strictmode/register.js new file mode 100644 index 00000000000..b226fe1e0b3 --- /dev/null +++ b/.storybook/custom-addons/strictmode/register.js @@ -0,0 +1,40 @@ +import {addons, types} from '@storybook/addons'; +import {getQueryParams} from '@storybook/client-api'; +import React, {useEffect, useState} from 'react'; + +const StrictModeToolBar = ({api}) => { + let channel = addons.getChannel(); + let [isStrict, setStrict] = useState(getQueryParams()?.strict === 'true' || false); + let onChange = () => { + setStrict((old) => { + channel.emit('strict/updated', !old); + return !old; + }) + }; + + useEffect(() => { + api.setQueryParams({ + 'strict': isStrict + }); + }); + + return ( +
+
+ +
+
+ ); +}; + +addons.register('StrictModeSwitcher', (api) => { + addons.add('StrictModeSwitcher', { + title: 'Strict mode switcher', + type: types.TOOL, + //👇 Shows the Toolbar UI element if either the Canvas or Docs tab is active + match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)), + render: () => + }); +}); diff --git a/.storybook/main.js b/.storybook/main.js index 24a0f04b09d..5d73778c058 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -11,13 +11,11 @@ module.exports = { 'storybook-dark-mode', './custom-addons/provider/register', './custom-addons/descriptions/register', - './custom-addons/theme/register' + './custom-addons/theme/register', + './custom-addons/strictmode/register' ], typescript: { check: false, reactDocgen: false - }, - reactOptions: { - strictMode: process.env.STRICT_MODE - }, + } }; diff --git a/.storybook/preview.js b/.storybook/preview.js index 0b268d77a1b..bc696a5a6b5 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -2,6 +2,7 @@ import {configureActions} from '@storybook/addon-actions'; import React from 'react'; import {VerticalCenter} from './layout'; import {withProviderSwitcher} from './custom-addons/provider'; +import {withStrictModeSwitcher} from './custom-addons/strictmode'; // decorator order matters, the last one will be the outer most @@ -29,5 +30,6 @@ export const decorators = [ ), + withStrictModeSwitcher, withProviderSwitcher ]; diff --git a/package.json b/package.json index 049bc351fb4..5679a401113 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "install-16": "yarn add -W react@^16.8.0 react-dom@^16.8.0 @testing-library/react@^12 @testing-library/react-hooks@^8", "install-17": "yarn add -W react@^17 react-dom@^17 @testing-library/react@^12 @testing-library/react-hooks@^8", "start": "cross-env NODE_ENV=storybook start-storybook -p 9003 --ci -c '.storybook'", - "start-strict": "cross-env NODE_ENV=storybook STRICT_MODE=1 start-storybook -p 9003 --ci -c '.storybook'", "build:storybook": "build-storybook -c .storybook -o dist/$(git rev-parse HEAD)/storybook", "build:storybook-16": "build-storybook -c .storybook -o dist/$(git rev-parse HEAD)/storybook-16", "build:storybook-17": "build-storybook -c .storybook -o dist/$(git rev-parse HEAD)/storybook-17", diff --git a/packages/@react-spectrum/provider/src/Provider.tsx b/packages/@react-spectrum/provider/src/Provider.tsx index ac1a29401a0..7243ae74f5c 100644 --- a/packages/@react-spectrum/provider/src/Provider.tsx +++ b/packages/@react-spectrum/provider/src/Provider.tsx @@ -18,6 +18,7 @@ import { useStyleProps } from '@react-spectrum/utils'; import clsx from 'clsx'; +import {Context} from './context'; import {DOMRef} from '@react-types/shared'; import {filterDOMProps} from '@react-aria/utils'; import {I18nProvider, useLocale} from '@react-aria/i18n'; @@ -30,9 +31,6 @@ import {useColorScheme, useScale} from './mediaQueries'; // @ts-ignore import {version} from '../package.json'; -const Context = React.createContext(null); -Context.displayName = 'ProviderContext'; - const DEFAULT_BREAKPOINTS = {S: 640, M: 768, L: 1024, XL: 1280, XXL: 1536}; function Provider(props: ProviderProps, ref: DOMRef) { diff --git a/packages/@react-spectrum/provider/src/context.ts b/packages/@react-spectrum/provider/src/context.ts new file mode 100644 index 00000000000..2c104719b04 --- /dev/null +++ b/packages/@react-spectrum/provider/src/context.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2020 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import {ProviderContext} from '@react-types/provider'; +import React from 'react'; + +// Context is placed in a separate file to avoid fast refresh issue where the old provider context values +// are immediately replaced with the null default. Stopgap solution until we fix this in parcel. +export const Context = React.createContext(null); +Context.displayName = 'ProviderContext'; diff --git a/yarn.lock b/yarn.lock index 4dfcd8d0f4d..4f05e65c303 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1132,6 +1132,13 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.6.2": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd" + integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.16.7", "@babel/template@^7.3.3": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"