diff --git a/UNRELEASED-V4.md b/UNRELEASED-V4.md index 6831025d90a..d464d36ebbb 100644 --- a/UNRELEASED-V4.md +++ b/UNRELEASED-V4.md @@ -24,6 +24,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f ### Code quality +- Updated all our context files to export react context rather than a provider and consumer ([#1459](https://github.com/Shopify/polaris-react/pull/1459)) - Upgraded the `Autocomplete` component from legacy context API to use createContext ([#1403](https://github.com/Shopify/polaris-react/pull/1403)) - Updated `ThemeProvider` to use the new context api ([#1396](https://github.com/Shopify/polaris-react/pull/1396)) - Updated `AppProvider` to no longer use `componentWillReceiveProps`([#1255](https://github.com/Shopify/polaris-react/pull/1255)) diff --git a/src/components/AppProvider/AppProvider.tsx b/src/components/AppProvider/AppProvider.tsx index 281b43896f1..d89aa51320b 100644 --- a/src/components/AppProvider/AppProvider.tsx +++ b/src/components/AppProvider/AppProvider.tsx @@ -5,8 +5,8 @@ import { ScrollLockManager, createAppProviderContext, } from './utilities'; -import AppProviderContext from './Context'; -import {AppProviderProps, AppProviderContextType} from './types'; +import AppProviderContext, {AppProviderContextType} from './context'; +import {AppProviderProps} from './types'; interface State { context: AppProviderContextType; @@ -75,16 +75,14 @@ export default class AppProvider extends React.Component { }); } - get getContext(): AppProviderContextType { - return this.state.context; - } - render() { - const {theme = {logo: null}} = this.props; + const {theme = {logo: null}, children} = this.props; + const {context} = this.state; + return ( - + - {React.Children.only(this.props.children)} + {React.Children.only(children)} ); diff --git a/src/components/AppProvider/Context.tsx b/src/components/AppProvider/Context.tsx deleted file mode 100644 index 156a7647728..00000000000 --- a/src/components/AppProvider/Context.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import * as React from 'react'; -import {AppProviderContextType} from './types'; -import createPolarisContext from './utilities/createPolarisContext'; - -const AppProviderContext = React.createContext( - createPolarisContext(), -); - -export default AppProviderContext; diff --git a/src/components/AppProvider/context.tsx b/src/components/AppProvider/context.tsx new file mode 100644 index 00000000000..00fee4432db --- /dev/null +++ b/src/components/AppProvider/context.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import {ClientApplication} from '@shopify/app-bridge'; +import createPolarisContext from './utilities/createPolarisContext'; +import {Intl, Link, StickyManager, ScrollLockManager} from './utilities'; + +export interface AppProviderContextType { + intl: Intl; + link: Link; + stickyManager: StickyManager; + scrollLockManager: ScrollLockManager; + appBridge?: ClientApplication<{}>; +} + +const AppProviderContext = React.createContext( + createPolarisContext(), +); + +export default AppProviderContext; diff --git a/src/components/AppProvider/index.ts b/src/components/AppProvider/index.ts index 5c3540ff94a..9a895399917 100644 --- a/src/components/AppProvider/index.ts +++ b/src/components/AppProvider/index.ts @@ -13,6 +13,6 @@ export { ComplexReplacementDictionary, CreateAppProviderContext, } from './utilities'; -export {AppProviderProps as Props, AppProviderContextType} from './types'; -export {default as AppProviderContext} from './Context'; +export {AppProviderProps as Props} from './types'; +export {default as AppProviderContext, AppProviderContextType} from './context'; export {default} from './AppProvider'; diff --git a/src/components/AppProvider/tests/AppProvider.test.tsx b/src/components/AppProvider/tests/AppProvider.test.tsx index db664d4d6ca..99ce9898099 100644 --- a/src/components/AppProvider/tests/AppProvider.test.tsx +++ b/src/components/AppProvider/tests/AppProvider.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import AppProviderContext from '../Context'; +import AppProviderContext from '../context'; import AppProvider from '../AppProvider'; import {mountWithAppProvider} from '../../../test-utilities'; diff --git a/src/components/AppProvider/types.ts b/src/components/AppProvider/types.ts index 76b3a075467..fbd2025da6e 100644 --- a/src/components/AppProvider/types.ts +++ b/src/components/AppProvider/types.ts @@ -1,13 +1,6 @@ -import {ClientApplication} from '@shopify/app-bridge'; import {LinkLikeComponent} from '../UnstyledLink'; import {Theme} from '../ThemeProvider'; -import { - Intl, - Link, - StickyManager, - ScrollLockManager, - TranslationDictionary, -} from './utilities'; +import {TranslationDictionary} from './utilities'; export interface AppProviderProps { /** A locale object or array of locale objects that overrides default translations */ @@ -27,11 +20,3 @@ export interface AppProviderProps { /** Custom logos and colors provided to select components */ theme?: Theme; } - -export interface AppProviderContextType { - intl: Intl; - link: Link; - stickyManager: StickyManager; - scrollLockManager: ScrollLockManager; - appBridge?: ClientApplication<{}>; -} diff --git a/src/components/AppProvider/utilities/createAppProviderContext/createAppProviderContext.ts b/src/components/AppProvider/utilities/createAppProviderContext/createAppProviderContext.ts index 1c5ce05ab57..7e5afdb8db7 100644 --- a/src/components/AppProvider/utilities/createAppProviderContext/createAppProviderContext.ts +++ b/src/components/AppProvider/utilities/createAppProviderContext/createAppProviderContext.ts @@ -3,7 +3,8 @@ import createApp, { LifecycleHook, DispatchActionHook, } from '@shopify/app-bridge'; -import {AppProviderProps, AppProviderContextType} from '../../types'; +import {AppProviderContextType} from '../../context'; +import {AppProviderProps} from '../../types'; import StickyManager from '../StickyManager'; import ScrollLockManager from '../ScrollLockManager'; import Intl from '../Intl'; diff --git a/src/components/AppProvider/utilities/createPolarisContext/createPolarisContext.ts b/src/components/AppProvider/utilities/createPolarisContext/createPolarisContext.ts index 17a9c3c184d..214d6cf966c 100644 --- a/src/components/AppProvider/utilities/createPolarisContext/createPolarisContext.ts +++ b/src/components/AppProvider/utilities/createPolarisContext/createPolarisContext.ts @@ -1,7 +1,7 @@ import {PolarisContext} from '../../../types'; import { createThemeContext, - ThemeProviderContext as CreateThemeContext, + ThemeProviderContextType as CreateThemeContext, } from '../../../ThemeProvider'; import {AppProviderProps} from '../../types'; import StickyManager from '../StickyManager'; diff --git a/src/components/AppProvider/utilities/withAppProvider/tests/withAppProvider.test.tsx b/src/components/AppProvider/utilities/withAppProvider/tests/withAppProvider.test.tsx index 5e18f11af0f..0bb470451eb 100644 --- a/src/components/AppProvider/utilities/withAppProvider/tests/withAppProvider.test.tsx +++ b/src/components/AppProvider/utilities/withAppProvider/tests/withAppProvider.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import {mount} from 'enzyme'; -import AppProviderContext from '../../../Context'; +import AppProviderContext from '../../../context'; import withAppProvider from '../withAppProvider'; describe('withAppProvider', () => { diff --git a/src/components/AppProvider/utilities/withAppProvider/withAppProvider.tsx b/src/components/AppProvider/utilities/withAppProvider/withAppProvider.tsx index 56cc5674326..e711b34f84c 100644 --- a/src/components/AppProvider/utilities/withAppProvider/withAppProvider.tsx +++ b/src/components/AppProvider/utilities/withAppProvider/withAppProvider.tsx @@ -6,11 +6,11 @@ import Link from '../Link'; import StickyManager from '../StickyManager'; import ScrollLockManager from '../ScrollLockManager'; import { + ThemeProviderContextType, ThemeProviderContext, - Consumer as ThemeProviderConsumer, } from '../../../ThemeProvider'; import {PolarisContext} from '../../../types'; -import AppProviderContext from '../../Context'; +import AppProviderContext from '../../context'; export type ReactComponent = | React.ComponentClass

& C @@ -22,7 +22,7 @@ export interface WithAppProviderProps { link: Link; stickyManager: StickyManager; scrollLockManager: ScrollLockManager; - theme?: ThemeProviderContext; + theme?: ThemeProviderContextType; appBridge?: ClientApplication<{}>; }; } @@ -72,7 +72,7 @@ export default function withAppProvider({ {(polaris) => { return ( - + {(polarisTheme) => { const polarisContext: PolarisContext = { ...polaris, @@ -94,7 +94,7 @@ export default function withAppProvider({ /> ); }} - + ); }} diff --git a/src/components/Autocomplete/components/ComboBox/ComboBox.tsx b/src/components/Autocomplete/components/ComboBox/ComboBox.tsx index eb26b99bbf3..2a794c1af6b 100644 --- a/src/components/Autocomplete/components/ComboBox/ComboBox.tsx +++ b/src/components/Autocomplete/components/ComboBox/ComboBox.tsx @@ -9,9 +9,9 @@ import ActionList from '../../../ActionList'; import Popover from '../../../Popover'; import {PreferredPosition} from '../../../PositionedOverlay'; import {ActionListItemDescriptor, Key} from '../../../../types'; -import {ComboBoxContext} from '../types'; import KeypressListener from '../../../KeypressListener'; -import {TextField, Provider} from './components'; +import ComboBoxContext from './context'; +import {TextField} from './components'; import styles from './ComboBox.scss'; @@ -119,13 +119,6 @@ export default class ComboBox extends React.PureComponent { HTMLDivElement > = React.createRef(); - get getContext(): ComboBoxContext { - return { - comboBoxId: this.state.comboBoxId, - selectedOptionId: this.selectedOptionId, - }; - } - componentDidMount() { const {options, actionsBefore, actionsAfter} = this.props; const comboBoxId = this.getComboBoxId(); @@ -206,6 +199,12 @@ export default class ComboBox extends React.PureComponent { onEndReached, emptyState, } = this.props; + const { + comboBoxId, + navigableOptions, + selectedOptions, + popoverActive, + } = this.state; const actionsBeforeMarkup = actionsBefore && actionsBefore.length > 0 && ( @@ -221,9 +220,9 @@ export default class ComboBox extends React.PureComponent { @@ -240,14 +239,19 @@ export default class ComboBox extends React.PureComponent { options.length === 0 && emptyState &&

{emptyState}
; + const context = { + comboBoxId, + selectedOptionId: this.selectedOptionId, + }; + return ( - +
{ />
@@ -289,7 +293,7 @@ export default class ComboBox extends React.PureComponent {
-
+ ); } diff --git a/src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx b/src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx deleted file mode 100644 index efe1ad83653..00000000000 --- a/src/components/Autocomplete/components/ComboBox/components/Context/Context.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react'; -import {ComboBoxContext} from '../../../types'; - -const {Provider, Consumer} = React.createContext({}); - -export {Provider, Consumer}; diff --git a/src/components/Autocomplete/components/ComboBox/components/Context/index.ts b/src/components/Autocomplete/components/ComboBox/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/Autocomplete/components/ComboBox/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx b/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx index 84927238a07..31c1b9ec2c5 100644 --- a/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx +++ b/src/components/Autocomplete/components/ComboBox/components/TextField/TextField.tsx @@ -1,13 +1,12 @@ import * as React from 'react'; -import {ComboBoxContext} from '../../../types'; +import ComboBoxContext from '../../context'; import BaseTextField, {Props as TextFieldProps} from '../../../../../TextField'; -import {Consumer} from '../Context'; export default function TextField(props: TextFieldProps) { return ( - - {({selectedOptionId, comboBoxId}: ComboBoxContext) => ( + + {({selectedOptionId, comboBoxId}) => ( )} - + ); } diff --git a/src/components/Autocomplete/components/ComboBox/components/index.ts b/src/components/Autocomplete/components/ComboBox/components/index.ts index 1840ed5f493..6237903f6d0 100644 --- a/src/components/Autocomplete/components/ComboBox/components/index.ts +++ b/src/components/Autocomplete/components/ComboBox/components/index.ts @@ -1,2 +1 @@ export {default as TextField} from './TextField'; -export {Provider, Consumer} from './Context'; diff --git a/src/components/Autocomplete/components/ComboBox/context.tsx b/src/components/Autocomplete/components/ComboBox/context.tsx new file mode 100644 index 00000000000..444fa802a41 --- /dev/null +++ b/src/components/Autocomplete/components/ComboBox/context.tsx @@ -0,0 +1,10 @@ +import * as React from 'react'; + +export interface ComboBoxContextType { + comboBoxId?: string; + selectedOptionId?: string; +} + +const ComboBoxContext = React.createContext({}); + +export default ComboBoxContext; diff --git a/src/components/Autocomplete/components/types.ts b/src/components/Autocomplete/components/types.ts deleted file mode 100644 index db46d64551b..00000000000 --- a/src/components/Autocomplete/components/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ComboBoxContext { - comboBoxId?: string; - selectedOptionId?: string; -} diff --git a/src/components/Banner/Banner.tsx b/src/components/Banner/Banner.tsx index 2c7cdcd7167..81c7db4e828 100644 --- a/src/components/Banner/Banner.tsx +++ b/src/components/Banner/Banner.tsx @@ -20,7 +20,9 @@ import Heading from '../Heading'; import ButtonGroup from '../ButtonGroup'; import UnstyledLink from '../UnstyledLink'; import Icon, {Props as IconProps} from '../Icon'; -import {Consumer, WithinContentContext} from '../WithinContentContext'; +import WithinContentContext, { + WithinContentContextType, +} from '../WithinContentContext'; import withContext from '../WithContext'; import {withAppProvider, WithAppProviderProps} from '../AppProvider'; @@ -45,7 +47,7 @@ export interface Props { onDismiss?(): void; } -export type CombinedProps = Props & WithContextTypes; +export type CombinedProps = Props & WithContextTypes; export class Banner extends React.PureComponent { render() { @@ -206,6 +208,8 @@ function secondaryActionFrom(action: Action) { } export default compose( - withContext(Consumer), + withContext( + WithinContentContext.Consumer, + ), withAppProvider(), )(Banner); diff --git a/src/components/Banner/tests/Banner.test.tsx b/src/components/Banner/tests/Banner.test.tsx index 967d7fad883..c39ced5fc6e 100644 --- a/src/components/Banner/tests/Banner.test.tsx +++ b/src/components/Banner/tests/Banner.test.tsx @@ -10,7 +10,7 @@ import { import {mountWithAppProvider} from 'test-utilities'; import {Button, Icon, UnstyledLink, Heading} from 'components'; import Banner from '..'; -import {Provider} from '../../WithinContentContext'; +import WithinContentContext from '../../WithinContentContext'; describe('', () => { it('renders a title', () => { @@ -100,7 +100,7 @@ describe('', () => { }; const bannerWithContentContext = mountWithAppProvider( - + ', () => { > Some content - , + , ); it('renders a slim button with contentContext', () => { diff --git a/src/components/Card/Card.tsx b/src/components/Card/Card.tsx index 246dc7e5107..da37e9eed8a 100644 --- a/src/components/Card/Card.tsx +++ b/src/components/Card/Card.tsx @@ -4,7 +4,7 @@ import {classNames} from '@shopify/react-utilities/styles'; import {Action, DisableableAction} from '../../types'; import {buttonFrom} from '../Button'; import ButtonGroup from '../ButtonGroup'; -import {Provider, WithinContentContext} from '../WithinContentContext'; +import WithinContentContext from '../WithinContentContext'; import {Header, Section} from './components'; import styles from './Card.scss'; @@ -66,20 +66,18 @@ export default class Card extends React.PureComponent { ) : null; + const context = { + withinContentContainer: true, + }; + return ( - +
{headerMarkup} {content} {footerMarkup}
-
+ ); } - - get getContext(): WithinContentContext { - return { - withinContentContainer: true, - }; - } } diff --git a/src/components/Card/tests/Card.test.tsx b/src/components/Card/tests/Card.test.tsx index 1b33f9e0338..0189a8c102e 100644 --- a/src/components/Card/tests/Card.test.tsx +++ b/src/components/Card/tests/Card.test.tsx @@ -2,21 +2,23 @@ import * as React from 'react'; import {mountWithAppProvider} from 'test-utilities'; import {Card, Badge, Button} from 'components'; -import {Consumer, WithinContentContext} from '../../WithinContentContext'; +import WithinContentContext, { + WithinContentContextType, +} from '../../WithinContentContext'; describe('', () => { it('has a child with prop withinContentContainer set to true', () => { - function TestComponent(_: WithinContentContext) { + function TestComponent(_: WithinContentContextType) { return null; } const component = mountWithAppProvider( - + {(props) => { return ; }} - + , ); diff --git a/src/components/ContextualSaveBar/ContextualSaveBar.tsx b/src/components/ContextualSaveBar/ContextualSaveBar.tsx index 53509ffad44..cdd4ec38d24 100644 --- a/src/components/ContextualSaveBar/ContextualSaveBar.tsx +++ b/src/components/ContextualSaveBar/ContextualSaveBar.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import compose from '@shopify/react-compose'; import isEqual from 'lodash/isEqual'; -import {ContextualSaveBarProps, FrameContext, Consumer} from '../Frame'; +import {ContextualSaveBarProps, FrameContextType, FrameContext} from '../Frame'; import withContext from '../WithContext'; import {WithContextTypes} from '../../types'; import {withAppProvider, WithAppProviderProps} from '../AppProvider'; @@ -13,7 +13,7 @@ import {withAppProvider, WithAppProviderProps} from '../AppProvider'; interface Props extends ContextualSaveBarProps {} export type ComposedProps = Props & WithAppProviderProps & - WithContextTypes; + WithContextTypes; class ContextualSaveBar extends React.PureComponent { componentDidMount() { @@ -57,6 +57,8 @@ function contextualSaveBarHasChanged( } export default compose( - withContext(Consumer), + withContext( + FrameContext.Consumer, + ), withAppProvider(), )(ContextualSaveBar); diff --git a/src/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx b/src/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx index f195c5f2a01..1c73430f7d9 100644 --- a/src/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx +++ b/src/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import {mountWithAppProvider} from 'test-utilities'; import {noop} from '../../../utilities/other'; import ContextualSaveBar from '../ContextualSaveBar'; -import {Provider, createFrameContext} from '../../Frame'; +import {FrameContext, createFrameContext} from '../../Frame'; describe('', () => { const props = { @@ -18,9 +18,9 @@ describe('', () => { }); mountWithAppProvider( - + - , + , ); expect(mockFrameContext.setContextualSaveBar).toHaveBeenCalledWith({ ...props, @@ -34,9 +34,9 @@ describe('', () => { }); const frame = mountWithAppProvider( - + - , + , ); expect(mockFrameContext.removeContextualSaveBar).not.toHaveBeenCalled(); frame.unmount(); @@ -50,9 +50,9 @@ describe('', () => { }); const frame = mountWithAppProvider( - + - , + , ); const newProps = { saveAction: {content: 'Save', onAction: noop, loading: true}, @@ -75,9 +75,9 @@ describe('', () => { }); const frame = mountWithAppProvider( - + - , + , ); expect(mockFrameContext.setContextualSaveBar).toHaveBeenCalledTimes(1); diff --git a/src/components/DropZone/DropZone.tsx b/src/components/DropZone/DropZone.tsx index 7ce6552540a..22bd9c311d1 100755 --- a/src/components/DropZone/DropZone.tsx +++ b/src/components/DropZone/DropZone.tsx @@ -20,10 +20,10 @@ import VisuallyHidden from '../VisuallyHidden'; import Labelled, {Action} from '../Labelled'; import {withAppProvider, WithAppProviderProps} from '../AppProvider'; -import {FileUpload, Provider} from './components'; +import {FileUpload} from './components'; +import DropZoneContext from './context'; import {fileAccepted, getDataTransferFiles} from './utils'; -import {DropZoneContext} from './types'; import styles from './DropZone.scss'; @@ -204,19 +204,13 @@ export class DropZone extends React.Component { }; } - get getContext(): DropZoneContext { - return { - size: this.state.size, - type: this.state.type || 'file', - }; - } - render() { const { id, dragging, error, size, + type, overlayText, errorOverlayText, } = this.state; @@ -319,8 +313,15 @@ export class DropZone extends React.Component { dropZoneMarkup ); + const context = { + size, + type: type || 'file', + }; + return ( - {labelledDropzoneMarkup} + + {labelledDropzoneMarkup} + ); } diff --git a/src/components/DropZone/components/Context/Context.tsx b/src/components/DropZone/components/Context/Context.tsx deleted file mode 100644 index 2143e1b2ebb..00000000000 --- a/src/components/DropZone/components/Context/Context.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import * as React from 'react'; -import {DropZoneContext} from '../../types'; - -const {Provider, Consumer} = React.createContext({ - size: 'extraLarge', - type: 'file', -}); - -export {Provider, Consumer}; diff --git a/src/components/DropZone/components/Context/index.ts b/src/components/DropZone/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/DropZone/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/DropZone/components/FileUpload/FileUpload.tsx b/src/components/DropZone/components/FileUpload/FileUpload.tsx index 64f16bf5b03..c7a67127e48 100755 --- a/src/components/DropZone/components/FileUpload/FileUpload.tsx +++ b/src/components/DropZone/components/FileUpload/FileUpload.tsx @@ -15,11 +15,8 @@ import Caption from '../../../Caption'; import TextStyle from '../../../TextStyle'; import withContext from '../../../WithContext'; import withRef from '../../../WithRef'; - -import {DropZoneContext} from '../../types'; import {fileUpload, imageUpload} from '../../images'; - -import {Consumer} from '../Context'; +import DropZoneContext, {DropZoneContextType} from '../../context'; import styles from './FileUpload.scss'; @@ -35,7 +32,7 @@ export interface Props { export type CombinedProps = Props & WithAppProviderProps & - WithContextTypes; + WithContextTypes; export class FileUpload extends React.Component { constructor(props: CombinedProps) { super(props); @@ -146,7 +143,9 @@ export class FileUpload extends React.Component { } export default compose( - withContext(Consumer), + withContext( + DropZoneContext.Consumer, + ), withAppProvider(), withRef(), )(FileUpload); diff --git a/src/components/DropZone/components/FileUpload/tests/FileUpload.test.tsx b/src/components/DropZone/components/FileUpload/tests/FileUpload.test.tsx index a9626b26133..c113a53b967 100755 --- a/src/components/DropZone/components/FileUpload/tests/FileUpload.test.tsx +++ b/src/components/DropZone/components/FileUpload/tests/FileUpload.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import {Link, Icon, Button, Caption, TextStyle} from 'components'; import {mountWithAppProvider} from 'test-utilities'; -import {Provider} from '../../Context'; +import DropZoneContext from '../../../context'; import FileUpload from '../FileUpload'; import {fileUpload as fileUploadImage, imageUpload} from '../../../images'; @@ -9,9 +9,9 @@ describe('', () => { describe('extraLarge', () => { it('renders extra large view for type file', () => { const fileUpload = mountWithAppProvider( - + - , + , ); expect(fileUpload.find('img').prop('src')).toBe(fileUploadImage); @@ -21,9 +21,9 @@ describe('', () => { it('renders extra large view for type image', () => { const fileUpload = mountWithAppProvider( - + - , + , ); expect(fileUpload.find('img').prop('src')).toBe(imageUpload); @@ -35,9 +35,9 @@ describe('', () => { describe('large', () => { it('renders large view for type file', () => { const fileUpload = mountWithAppProvider( - + - , + , ); expect(fileUpload.find('img').prop('src')).toBe(fileUploadImage); @@ -48,9 +48,9 @@ describe('', () => { it('renders large view for type image', () => { const fileUpload = mountWithAppProvider( - + - , + , ); expect(fileUpload.find('img').prop('src')).toBe(imageUpload); @@ -62,9 +62,9 @@ describe('', () => { it('renders medium view', () => { const fileUpload = mountWithAppProvider( - + - , + , ); expect(fileUpload.find(Link)).toHaveLength(1); @@ -73,9 +73,9 @@ describe('', () => { it('renders small view', () => { const fileUpload = mountWithAppProvider( - + - , + , ); expect(fileUpload.find(Icon)).toHaveLength(1); diff --git a/src/components/DropZone/components/index.ts b/src/components/DropZone/components/index.ts index e3db4cee0aa..49f44ba4ebb 100644 --- a/src/components/DropZone/components/index.ts +++ b/src/components/DropZone/components/index.ts @@ -1,3 +1 @@ export {default as FileUpload, Props as FileUploadProps} from './FileUpload'; - -export {Provider, Consumer} from './Context'; diff --git a/src/components/DropZone/context.tsx b/src/components/DropZone/context.tsx new file mode 100644 index 00000000000..7324204b324 --- /dev/null +++ b/src/components/DropZone/context.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; + +export interface DropZoneContextType { + size: string; + type: string; +} + +const DropZoneContext = React.createContext({ + size: 'extraLarge', + type: 'file', +}); + +export default DropZoneContext; diff --git a/src/components/DropZone/index.ts b/src/components/DropZone/index.ts index c2858197cbf..32eefa55a17 100755 --- a/src/components/DropZone/index.ts +++ b/src/components/DropZone/index.ts @@ -3,5 +3,4 @@ import DropZone from './DropZone'; export * from './types'; export {Props} from './DropZone'; -export {Provider, Consumer} from './components'; export default DropZone; diff --git a/src/components/DropZone/types.ts b/src/components/DropZone/types.ts index d5f0baab7ab..68ff9b46a88 100755 --- a/src/components/DropZone/types.ts +++ b/src/components/DropZone/types.ts @@ -1,6 +1 @@ export type DropZoneEvent = DragEvent | React.ChangeEvent; - -export interface DropZoneContext { - size: string; - type: string; -} diff --git a/src/components/Frame/Frame.tsx b/src/components/Frame/Frame.tsx index af16066e4e4..4d37751b6e5 100644 --- a/src/components/Frame/Frame.tsx +++ b/src/components/Frame/Frame.tsx @@ -12,13 +12,9 @@ import TrapFocus from '../TrapFocus'; import {UserMenuProvider} from '../TopBar'; import {dataPolarisTopBar, layer, Duration} from '../shared'; import {setRootProperty} from '../../utilities/setRootProperty'; -import { - ContextualSaveBarProps, - FrameContext, - ToastID, - ToastPropsWithID, -} from './types'; -import {Provider, ToastManager, Loading, ContextualSaveBar} from './components'; +import {ContextualSaveBarProps, ToastID, ToastPropsWithID} from './types'; +import FrameContext from './context'; +import {ToastManager, Loading, ContextualSaveBar} from './components'; import styles from './Frame.scss'; @@ -225,8 +221,17 @@ export class Frame extends React.PureComponent { /> ) : null; + const context = { + showToast: this.showToast, + hideToast: this.hideToast, + startLoading: this.startLoading, + stopLoading: this.stopLoading, + setContextualSaveBar: this.setContextualSaveBar, + removeContextualSaveBar: this.removeContextualSaveBar, + }; + return ( - +
{ {globalRibbonMarkup}
-
+ ); } @@ -365,17 +370,6 @@ export class Frame extends React.PureComponent { this.handleNavigationDismiss(); } }; - - get getContext(): FrameContext { - return { - showToast: this.showToast, - hideToast: this.hideToast, - startLoading: this.startLoading, - stopLoading: this.stopLoading, - setContextualSaveBar: this.setContextualSaveBar, - removeContextualSaveBar: this.removeContextualSaveBar, - }; - } } const navTransitionClasses = { diff --git a/src/components/Frame/components/Context/Context.tsx b/src/components/Frame/components/Context/Context.tsx deleted file mode 100644 index 476623c13e8..00000000000 --- a/src/components/Frame/components/Context/Context.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import * as React from 'react'; -import {noop} from '@shopify/javascript-utilities/other'; -import {FrameContext} from '../../types'; - -const defaultContext: FrameContext = { - showToast: noop, - hideToast: noop, - setContextualSaveBar: noop, - removeContextualSaveBar: noop, - startLoading: noop, - stopLoading: noop, -}; - -const {Provider, Consumer} = React.createContext(defaultContext); - -export {Provider, Consumer}; diff --git a/src/components/Frame/components/Context/index.ts b/src/components/Frame/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/Frame/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx b/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx index 834b19753af..c5b5d170e5b 100644 --- a/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx +++ b/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import {mountWithAppProvider, trigger} from 'test-utilities'; import {Button, Image, Modal} from 'components'; import ContextualSaveBar from '../ContextualSaveBar'; -import {ThemeProviderContext} from '../../../../ThemeProvider'; +import {ThemeProviderContextType} from '../../../../ThemeProvider'; import merge from '../../../../../utilities/merge'; describe('', () => { @@ -178,7 +178,9 @@ describe('', () => { }); }); -function mergeThemeProviderContext(providedThemeContext: ThemeProviderContext) { +function mergeThemeProviderContext( + providedThemeContext: ThemeProviderContextType, +) { return { context: { themeProvider: merge({logo: null}, providedThemeContext), diff --git a/src/components/Frame/components/index.ts b/src/components/Frame/components/index.ts index 6ace59a5406..e883cd4ee92 100644 --- a/src/components/Frame/components/index.ts +++ b/src/components/Frame/components/index.ts @@ -9,4 +9,3 @@ export { } from './ToastManager'; export {default as Loading, Props as LoadingProps} from './Loading'; export {default as ContextualSaveBar} from './ContextualSaveBar'; -export {Provider, Consumer} from './Context'; diff --git a/src/components/Frame/context.tsx b/src/components/Frame/context.tsx new file mode 100644 index 00000000000..efbcf7039f4 --- /dev/null +++ b/src/components/Frame/context.tsx @@ -0,0 +1,25 @@ +import * as React from 'react'; +import {noop} from '@shopify/javascript-utilities/other'; +import {ToastPropsWithID, ToastID, ContextualSaveBarProps} from './types'; + +export interface FrameContextType { + showToast(toast: ToastPropsWithID): void; + hideToast(toast: ToastID): void; + setContextualSaveBar(props: ContextualSaveBarProps): void; + removeContextualSaveBar(): void; + startLoading(): void; + stopLoading(): void; +} + +const defaultContext: FrameContextType = { + showToast: noop, + hideToast: noop, + setContextualSaveBar: noop, + removeContextualSaveBar: noop, + startLoading: noop, + stopLoading: noop, +}; + +const FrameContext = React.createContext(defaultContext); + +export default FrameContext; diff --git a/src/components/Frame/index.ts b/src/components/Frame/index.ts index 159c9943e58..b3a88e626a9 100644 --- a/src/components/Frame/index.ts +++ b/src/components/Frame/index.ts @@ -5,12 +5,12 @@ export {Props} from './Frame'; export { DEFAULT_TOAST_DURATION, DEFAULT_TOAST_DURATION_WITH_ACTION, - Provider, - Consumer, } from './components'; -export {ContextualSaveBarProps, FrameContext, ToastProps} from './types'; +export {ContextualSaveBarProps, ToastProps} from './types'; -export {createFrameContext, CreateFrameContext} from './utilities'; +export {createFrameContext} from './utilities'; + +export {default as FrameContext, FrameContextType} from './context'; export default Frame; diff --git a/src/components/Frame/types.ts b/src/components/Frame/types.ts index 431fc8fabfb..6b2d2abb639 100644 --- a/src/components/Frame/types.ts +++ b/src/components/Frame/types.ts @@ -1,14 +1,5 @@ import {Action} from '../../types'; -export interface FrameContext { - showToast(toast: ToastPropsWithID): void; - hideToast(toast: ToastID): void; - setContextualSaveBar(props: ContextualSaveBarProps): void; - removeContextualSaveBar(): void; - startLoading(): void; - stopLoading(): void; -} - interface ContextualSaveBarAction { /** A destination to link to */ url?: string; diff --git a/src/components/Frame/utilities/createFrameContext/createFrameContext.ts b/src/components/Frame/utilities/createFrameContext/createFrameContext.ts index 9c806e50341..ea3bf249779 100644 --- a/src/components/Frame/utilities/createFrameContext/createFrameContext.ts +++ b/src/components/Frame/utilities/createFrameContext/createFrameContext.ts @@ -1,19 +1,5 @@ import {noop} from '@shopify/javascript-utilities/other'; -import { - FrameContext, - ContextualSaveBarProps, - ToastID, - ToastPropsWithID, -} from '../../types'; - -export interface CreateFrameContext { - showToast?(toast: ToastPropsWithID): void; - hideToast?(toast: ToastID): void; - setContextualSaveBar?(props: ContextualSaveBarProps): void; - removeContextualSaveBar?(): void; - startLoading?(): void; - stopLoading?(): void; -} +import {FrameContextType} from '../../context'; export default function createFrameContext({ showToast = noop, @@ -22,7 +8,7 @@ export default function createFrameContext({ removeContextualSaveBar = noop, startLoading = noop, stopLoading = noop, -}: CreateFrameContext = {}): FrameContext { +}: Partial = {}): FrameContextType { return { showToast, hideToast, diff --git a/src/components/Frame/utilities/createFrameContext/index.ts b/src/components/Frame/utilities/createFrameContext/index.ts index 2019c9079cf..59279ff9857 100644 --- a/src/components/Frame/utilities/createFrameContext/index.ts +++ b/src/components/Frame/utilities/createFrameContext/index.ts @@ -1 +1 @@ -export {default, CreateFrameContext} from './createFrameContext'; +export {default} from './createFrameContext'; diff --git a/src/components/Frame/utilities/index.ts b/src/components/Frame/utilities/index.ts index fc0419a0ad2..645a9a9d757 100644 --- a/src/components/Frame/utilities/index.ts +++ b/src/components/Frame/utilities/index.ts @@ -1,4 +1 @@ -export { - default as createFrameContext, - CreateFrameContext, -} from './createFrameContext'; +export {default as createFrameContext} from './createFrameContext'; diff --git a/src/components/Loading/Loading.tsx b/src/components/Loading/Loading.tsx index 64c2592f5a8..4226fdec4a0 100644 --- a/src/components/Loading/Loading.tsx +++ b/src/components/Loading/Loading.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import compose from '@shopify/react-compose'; import {Loading as AppBridgeLoading} from '@shopify/app-bridge/actions'; -import {FrameContext, Consumer} from '../Frame'; +import {FrameContextType, FrameContext} from '../Frame'; import withContext from '../WithContext'; import {WithContextTypes} from '../../types'; import {withAppProvider, WithAppProviderProps} from '../AppProvider'; @@ -9,7 +9,7 @@ import {withAppProvider, WithAppProviderProps} from '../AppProvider'; export interface Props {} export type ComposedProps = Props & WithAppProviderProps & - WithContextTypes; + WithContextTypes; export class Loading extends React.PureComponent { private appBridgeLoading: AppBridgeLoading.Loading | undefined; @@ -47,6 +47,8 @@ export class Loading extends React.PureComponent { } export default compose( - withContext(Consumer), + withContext( + FrameContext.Consumer, + ), withAppProvider(), )(Loading); diff --git a/src/components/Loading/tests/Loading.test.tsx b/src/components/Loading/tests/Loading.test.tsx index aa0666aac14..44ce63dc40f 100644 --- a/src/components/Loading/tests/Loading.test.tsx +++ b/src/components/Loading/tests/Loading.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import {Loading as AppBridgeLoading} from '@shopify/app-bridge/actions'; import {mountWithAppProvider} from 'test-utilities'; -import {Provider, createFrameContext} from '../../Frame'; +import {FrameContext, createFrameContext} from '../../Frame'; import Loading from '../Loading'; @@ -16,9 +16,9 @@ describe('', () => { }); mountWithAppProvider( - + - , + , ); expect(mockFrameContext.startLoading).toHaveBeenCalled(); }); @@ -28,9 +28,9 @@ describe('', () => { stopLoading: jest.fn(), }); const frame = mountWithAppProvider( - + - , + , ); expect(mockFrameContext.stopLoading).not.toHaveBeenCalled(); diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index 7e6a5c5f92c..6d52aa9acf1 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -6,7 +6,7 @@ import {focusFirstFocusableNode} from '@shopify/javascript-utilities/focus'; import {createUniqueIDFactory} from '@shopify/javascript-utilities/other'; import {wrapWithComponent} from '@shopify/react-utilities'; import {Modal as AppBridgeModal} from '@shopify/app-bridge/actions'; -import {Provider, WithinContentContext} from '../WithinContentContext'; +import WithinContentContext from '../WithinContentContext'; import {transformActions} from '../../utilities/app-bridge-transformers'; import pick from '../../utilities/pick'; @@ -296,15 +296,19 @@ export class Modal extends React.Component { const animated = !instant; + const context = { + withinContentContainer: true, + }; + return ( - + {dialog} {backdrop} - + ); } @@ -379,12 +383,6 @@ export class Modal extends React.Component { }, }; } - - get getContext(): WithinContentContext { - return { - withinContentContainer: true, - }; - } } function isIframeModal( diff --git a/src/components/Modal/tests/Modal.test.tsx b/src/components/Modal/tests/Modal.test.tsx index 3e4584de9e5..8335ae783e5 100644 --- a/src/components/Modal/tests/Modal.test.tsx +++ b/src/components/Modal/tests/Modal.test.tsx @@ -7,7 +7,9 @@ import {Badge, Spinner, Portal, Scrollable} from 'components'; import {Footer, Dialog} from '../components'; import Modal from '../Modal'; -import {Consumer, WithinContentContext} from '../../WithinContentContext'; +import WithinContentContext, { + WithinContentContextType, +} from '../../WithinContentContext'; jest.mock('../../../utilities/app-bridge-transformers', () => ({ ...require.requireActual('../../../utilities/app-bridge-transformers'), @@ -24,17 +26,17 @@ describe('', () => { }); it('has a child with contentContext', () => { - function TestComponent(_: WithinContentContext) { + function TestComponent(_: WithinContentContextType) { return null; } const component = mountWithAppProvider( - + {(props) => { return ; }} - + , ); diff --git a/src/components/Navigation/Navigation.tsx b/src/components/Navigation/Navigation.tsx index 5628757bac5..e74afd16356 100644 --- a/src/components/Navigation/Navigation.tsx +++ b/src/components/Navigation/Navigation.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import Scrollable from '../Scrollable'; -import {UserMenu, Section, Item, Provider} from './components'; +import NavigationContext from './context'; +import {UserMenu, Section, Item} from './components'; import {SectionType} from './types'; import styles from './Navigation.scss'; @@ -33,22 +34,26 @@ export default class Navigation extends React.Component { } } - get getContext() { - return { - location: this.props.location, - onNavigationDismiss: this.props.onDismiss, - }; - } - render() { - const {children, userMenu, contextControl} = this.props; + const { + children, + userMenu, + contextControl, + location, + onDismiss, + } = this.props; const contextControlMarkup = contextControl && (
{contextControl}
); + const context = { + location, + onNavigationDismiss: onDismiss, + }; + return ( - + - + ); } } diff --git a/src/components/Navigation/components/Context/Context.tsx b/src/components/Navigation/components/Context/Context.tsx deleted file mode 100644 index 235ce2462b3..00000000000 --- a/src/components/Navigation/components/Context/Context.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import {NavigationContext} from '../../types'; - -const {Provider, Consumer} = React.createContext({ - location: '', -}); - -export {Provider, Consumer}; diff --git a/src/components/Navigation/components/Context/index.ts b/src/components/Navigation/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/Navigation/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/Navigation/components/Item/Item.tsx b/src/components/Navigation/components/Item/Item.tsx index 9d111346f9c..d8b30eeb629 100644 --- a/src/components/Navigation/components/Item/Item.tsx +++ b/src/components/Navigation/components/Item/Item.tsx @@ -3,8 +3,7 @@ import * as React from 'react'; import {classNames} from '@shopify/react-utilities/styles'; import {navigationBarCollapsed} from '../../../../utilities/breakpoints'; -import {Consumer} from '../Context'; -import {NavigationContext} from '../../types'; +import NavigationContext, {NavigationContextType} from '../../context'; import {withAppProvider, WithAppProviderProps} from '../../../AppProvider'; import Badge from '../../../Badge'; import Icon, {Props as IconProps} from '../../../Icon'; @@ -57,7 +56,7 @@ export interface Props extends ItemURLDetails { export type CombinedProps = Props & WithAppProviderProps & - WithContextTypes; + WithContextTypes; interface State { expanded: boolean; @@ -389,7 +388,9 @@ function matchStateForItem( export const Item = compose( withAppProvider(), - withContext(Consumer), + withContext( + NavigationContext.Consumer, + ), )(BaseItem); export default Item; diff --git a/src/components/Navigation/components/Item/tests/Item.test.tsx b/src/components/Navigation/components/Item/tests/Item.test.tsx index 4b20b52365c..d749ab1b5e5 100644 --- a/src/components/Navigation/components/Item/tests/Item.test.tsx +++ b/src/components/Navigation/components/Item/tests/Item.test.tsx @@ -4,8 +4,7 @@ import {noop} from '@shopify/javascript-utilities/other'; import {matchMedia} from '@shopify/jest-dom-mocks'; import {Icon, UnstyledLink, Indicator, Badge} from 'components'; import {trigger, mountWithAppProvider} from 'test-utilities'; -import {NavigationContext} from '../../../types'; -import {Provider} from '../../Context'; +import NavigationContext, {NavigationContextType} from '../../../context'; import Item, {Props as ItemProps} from '../Item'; import {Secondary} from '../components'; @@ -472,7 +471,11 @@ function itemForLocation(location: string, overrides: Partial = {}) { function mountWithNavigationProvider( node: React.ReactElement, - context: NavigationContext = {location: ''}, + context: NavigationContextType = {location: ''}, ) { - return mountWithAppProvider({node}); + return mountWithAppProvider( + + {node} + , + ); } diff --git a/src/components/Navigation/components/Section/tests/Section.test.tsx b/src/components/Navigation/components/Section/tests/Section.test.tsx index c1755e2f090..0a9e7bc46e4 100644 --- a/src/components/Navigation/components/Section/tests/Section.test.tsx +++ b/src/components/Navigation/components/Section/tests/Section.test.tsx @@ -5,15 +5,14 @@ import {matchMedia, animationFrame} from '@shopify/jest-dom-mocks'; import {findByTestID, trigger, mountWithAppProvider} from 'test-utilities'; import Collapsible from '../../../../Collapsible'; -import {NavigationContext} from '../../../types'; -import {Provider} from '../../Context'; +import NavigationContext, {NavigationContextType} from '../../../context'; import Item from '../../Item'; import Section from '../Section'; import channelResults from './fixtures/AdminNavQuery/multiple-channels.json'; describe('', () => { - let context: NavigationContext; + let context: NavigationContextType; beforeEach(() => { matchMedia.mock(); @@ -207,7 +206,11 @@ describe('', () => { function mountWithNavigationProvider( node: React.ReactElement, - context: NavigationContext = {location: ''}, + context: NavigationContextType = {location: ''}, ) { - return mountWithAppProvider({node}); + return mountWithAppProvider( + + {node} + , + ); } diff --git a/src/components/Navigation/components/index.ts b/src/components/Navigation/components/index.ts index 94205982405..7664ccf1320 100644 --- a/src/components/Navigation/components/index.ts +++ b/src/components/Navigation/components/index.ts @@ -2,4 +2,3 @@ export {default as Section, Props as SectionProps} from './Section'; export {default as Item, Props as ItemProps} from './Item'; export {default as Message, Props as MessageProps} from './Message'; export {default as UserMenu, Props as UserMenuProps} from './UserMenu'; -export {Provider, Consumer} from './Context'; diff --git a/src/components/Navigation/context.tsx b/src/components/Navigation/context.tsx new file mode 100644 index 00000000000..16137d7fc6c --- /dev/null +++ b/src/components/Navigation/context.tsx @@ -0,0 +1,12 @@ +import * as React from 'react'; + +export interface NavigationContextType { + location: string; + onNavigationDismiss?(): void; +} + +const NavigationContext = React.createContext({ + location: '', +}); + +export default NavigationContext; diff --git a/src/components/Navigation/tests/Navigation.test.tsx b/src/components/Navigation/tests/Navigation.test.tsx index 986f3697932..b4b5e4c7c56 100644 --- a/src/components/Navigation/tests/Navigation.test.tsx +++ b/src/components/Navigation/tests/Navigation.test.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; import {mountWithAppProvider} from 'test-utilities'; import Navigation from '../Navigation'; -import {UserMenu, Provider, Consumer} from '../components'; +import NavigationContext from '../context'; +import {UserMenu} from '../components'; describe('', () => { it('mounts', () => { @@ -11,15 +12,19 @@ describe('', () => { it('passes context', () => { const Child: React.SFC<{}> = (_props) => { - return {({location}) => (location ?
: null)}; + return ( + + {({location}) => (location ?
: null)} + + ); }; const navigation = mountWithAppProvider( - + - , + , ); const div = navigation diff --git a/src/components/Navigation/types.ts b/src/components/Navigation/types.ts index 469c3b103a4..552fd477ba0 100644 --- a/src/components/Navigation/types.ts +++ b/src/components/Navigation/types.ts @@ -1,11 +1,6 @@ import * as PropTypes from 'prop-types'; import {Props as IconProps} from '../Icon'; -export interface NavigationContext { - location: string; - onNavigationDismiss?(): void; -} - export interface ItemType { label: string; url: string; diff --git a/src/components/ResourceList/ResourceList.tsx b/src/components/ResourceList/ResourceList.tsx index 6247f6fe18d..17ed35e8f20 100644 --- a/src/components/ResourceList/ResourceList.tsx +++ b/src/components/ResourceList/ResourceList.tsx @@ -19,10 +19,10 @@ import { CheckableButton, FilterControl, Item, - Provider, } from './components'; +import ResourceListContext from './context'; -import {ResourceListContext, SelectedItems, SELECT_ALL_ITEMS} from './types'; +import {SelectedItems, SELECT_ALL_ITEMS} from './types'; import styles from './ResourceList.scss'; @@ -291,23 +291,6 @@ export class ResourceList extends React.Component { }; } - get getContext(): ResourceListContext { - const { - selectedItems, - resourceName = this.defaultResourceName, - loading, - } = this.props; - const {selectMode} = this.state; - return { - selectable: this.selectable, - selectedItems, - selectMode, - resourceName, - loading, - onSelectionChange: this.handleSelectionChange, - }; - } - componentWillReceiveProps(nextProps: Props) { const {selectedItems} = this.props; @@ -362,6 +345,8 @@ export class ResourceList extends React.Component { sortOptions, sortValue, alternateTool, + selectedItems, + resourceName = this.defaultResourceName, onSortChange, polaris: {intl}, } = this.props; @@ -548,15 +533,24 @@ export class ResourceList extends React.Component { emptyStateMarkup ); + const context = { + selectable: this.selectable, + selectedItems, + selectMode, + resourceName, + loading, + onSelectionChange: this.handleSelectionChange, + }; + return ( - +
{filterControlMarkup} {headerMarkup} {listMarkup} {loadingWithoutItemsMarkup}
-
+ ); } diff --git a/src/components/ResourceList/components/Context/Context.tsx b/src/components/ResourceList/components/Context/Context.tsx deleted file mode 100644 index f38d8d6dc10..00000000000 --- a/src/components/ResourceList/components/Context/Context.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import {Intl} from '../../../AppProvider'; -import {ResourceListContext} from '../../types'; - -const intl = new Intl(undefined); - -const {Provider, Consumer} = React.createContext({ - selectMode: false, - resourceName: { - singular: intl.translate('Polaris.ResourceList.defaultItemSingular'), - plural: intl.translate('Polaris.ResourceList.defaultItemPlural'), - }, -}); - -export {Provider, Consumer}; diff --git a/src/components/ResourceList/components/Context/index.ts b/src/components/ResourceList/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/ResourceList/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/ResourceList/components/FilterControl/FilterControl.tsx b/src/components/ResourceList/components/FilterControl/FilterControl.tsx index 318152c96dc..d58698a3296 100644 --- a/src/components/ResourceList/components/FilterControl/FilterControl.tsx +++ b/src/components/ResourceList/components/FilterControl/FilterControl.tsx @@ -10,8 +10,7 @@ import TextField from '../../../TextField'; import Tag from '../../../Tag'; import withContext from '../../../WithContext'; -import {ResourceListContext} from '../../types'; -import {Consumer} from '../Context'; +import ResourceListContext, {ResourceListContextType} from '../../context'; import {FilterCreator} from './components'; import {AppliedFilter, Filter, FilterType, Operator} from './types'; @@ -30,7 +29,7 @@ export interface Props { export type CombinedProps = Props & WithAppProviderProps & - WithContextTypes; + WithContextTypes; export class FilterControl extends React.Component { render() { @@ -296,5 +295,7 @@ function findOperatorLabel(filter: Filter, appliedFilter: AppliedFilter) { export default compose( withAppProvider(), - withContext(Consumer), + withContext( + ResourceListContext.Consumer, + ), )(FilterControl); diff --git a/src/components/ResourceList/components/FilterControl/tests/FilterControl.test.tsx b/src/components/ResourceList/components/FilterControl/tests/FilterControl.test.tsx index c0b3b049c7b..81ea4c1c9e2 100644 --- a/src/components/ResourceList/components/FilterControl/tests/FilterControl.test.tsx +++ b/src/components/ResourceList/components/FilterControl/tests/FilterControl.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import {noop} from '@shopify/javascript-utilities/other'; import {trigger, mountWithAppProvider} from 'test-utilities'; import {TextField, Tag, Button} from 'components'; -import {Provider} from '../../Context'; +import ResourceListContext from '../../../context'; import { Filter, FilterType, @@ -68,9 +68,9 @@ describe('', () => { describe('searchValue', () => { it('renders with TextField by default', () => { const filterControl = mountWithAppProvider( - + - , + , ); const searchField = filterControl.find(TextField); @@ -80,9 +80,9 @@ describe('', () => { it('renders with searchValue as its value', () => { const searchValue = 'search value'; const filterControl = mountWithAppProvider( - + - , + , ); const searchField = filterControl.find(TextField); @@ -93,12 +93,12 @@ describe('', () => { describe('appliedFilters', () => { it('renders the same number of Tag as appliedFilters', () => { const filterControl = mountWithAppProvider( - + - , + , ); const tags = filterControl.find(Tag); @@ -108,13 +108,13 @@ describe('', () => { it('calls onFiltersChange without the applied filter when user clicks remove on the appliedFilter', () => { const onFiltersChange = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); const tags = filterControl.find(Tag); @@ -144,13 +144,13 @@ describe('', () => { value: appliedFilterLabel, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).first(); @@ -173,13 +173,13 @@ describe('', () => { value: filterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -207,13 +207,13 @@ describe('', () => { value: filterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -236,13 +236,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -264,13 +264,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -295,13 +295,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const expectedLocalizedLabel = filterControl.app.polaris.intl.translate( @@ -330,13 +330,13 @@ describe('', () => { }; const filterControl = mountWithAppProvider( - + - , + , ); const expectedLocalizedLabel = filterControl.app.polaris.intl.translate( @@ -365,13 +365,13 @@ describe('', () => { value: selectedDate, }; const filterControl = mountWithAppProvider( - + - , + , ); const expectedLocalizedLabel = filterControl.app.polaris.intl.translate( @@ -400,13 +400,13 @@ describe('', () => { value: selectedDate, }; const filterControl = mountWithAppProvider( - + - , + , ); const expectedLocalizedLabel = filterControl.app.polaris.intl.translate( @@ -447,13 +447,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -488,13 +488,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -511,13 +511,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); const firstTag = filterControl.find(Tag).at(0); @@ -531,13 +531,13 @@ describe('', () => { value: appliedFilterValue, }; const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find('ul')).toHaveLength(1); expect(filterControl.find('li')).toHaveLength(1); @@ -547,9 +547,9 @@ describe('', () => { describe('additionalAction', () => { it('renders no connectedRight prop on TextField if there is no additionalAction', () => { const filterControl = mountWithAppProvider( - + - , + , ); const searchField = filterControl.find(TextField); @@ -562,9 +562,9 @@ describe('', () => { onAction: jest.fn(), }; const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find(Button).exists()).toBe(true); @@ -577,9 +577,9 @@ describe('', () => { describe('focused', () => { it('passes its value to focus of TextField', () => { const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find(TextField).prop('focused')).toBe(true); @@ -589,9 +589,9 @@ describe('', () => { describe('filters', () => { it('renders no if there are no filters', () => { const filterControl = mountWithAppProvider( - + - , + , ); const searchField = filterControl.find(TextField); @@ -600,9 +600,9 @@ describe('', () => { it('renders if there is filters', () => { const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find(FilterCreator).exists()).toBe(true); @@ -610,9 +610,9 @@ describe('', () => { it('renders with filters', () => { const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find(FilterCreator).prop('filters')).toMatchObject( @@ -625,9 +625,9 @@ describe('', () => { it('gets passed to onBlur of TextField', () => { const onSearchBlur = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find(TextField).prop('onBlur')).toBe(onSearchBlur); @@ -636,9 +636,9 @@ describe('', () => { it('calls onSearchBlur when onBlur is triggered', () => { const onSearchBlur = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); trigger(filterControl.find(TextField), 'onBlur'); @@ -651,12 +651,12 @@ describe('', () => { it('gets passed to onChange of TextField', () => { const onSearchChange = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); expect(filterControl.find(TextField).prop('onChange')).toBe( @@ -668,12 +668,12 @@ describe('', () => { const newSearchValue = 'new search value'; const onSearchChange = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); trigger(filterControl.find(TextField), 'onChange', newSearchValue); @@ -691,14 +691,14 @@ describe('', () => { const onFiltersChange = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); trigger(filterControl.find(FilterCreator), 'onAddFilter', newFilter); @@ -713,14 +713,14 @@ describe('', () => { const newFilter = mockAppliedFilters[0]; const onFiltersChange = jest.fn(); const filterControl = mountWithAppProvider( - + - , + , ); trigger(filterControl.find(FilterCreator), 'onAddFilter', newFilter); diff --git a/src/components/ResourceList/components/Item/Item.tsx b/src/components/ResourceList/components/Item/Item.tsx index 0d7f4042c51..21ab7471e1b 100644 --- a/src/components/ResourceList/components/Item/Item.tsx +++ b/src/components/ResourceList/components/Item/Item.tsx @@ -13,9 +13,9 @@ import Checkbox from '../../../Checkbox'; import Button, {buttonsFrom} from '../../../Button'; import {withAppProvider, WithAppProviderProps} from '../../../AppProvider'; -import {ResourceListContext, SELECT_ALL_ITEMS} from '../../types'; +import {SELECT_ALL_ITEMS} from '../../types'; import withContext from '../../../WithContext'; -import {Consumer} from '../Context'; +import ResourceListContext, {ResourceListContextType} from '../../context'; import styles from './Item.scss'; export type ExceptionStatus = 'neutral' | 'warning' | 'critical'; @@ -56,10 +56,12 @@ export interface State { } export type CombinedProps = - | PropsWithUrl & WithAppProviderProps & WithContextTypes + | PropsWithUrl & + WithAppProviderProps & + WithContextTypes | PropsWithClick & WithAppProviderProps & - WithContextTypes; + WithContextTypes; const getUniqueCheckboxID = createUniqueIDFactory('ResourceListItemCheckbox'); @@ -389,6 +391,8 @@ function stopPropagation(event: React.MouseEvent) { } export default compose( - withContext(Consumer), + withContext( + ResourceListContext.Consumer, + ), withAppProvider(), )(Item); diff --git a/src/components/ResourceList/components/Item/tests/Item.test.tsx b/src/components/ResourceList/components/Item/tests/Item.test.tsx index 67755ac4a9e..9d1b99e40ed 100644 --- a/src/components/ResourceList/components/Item/tests/Item.test.tsx +++ b/src/components/ResourceList/components/Item/tests/Item.test.tsx @@ -8,7 +8,7 @@ import { Thumbnail, UnstyledLink, } from 'components'; -import {Provider} from '../../Context'; +import ResourceListContext from '../../../context'; import Item from '../Item'; describe('', () => { @@ -68,13 +68,13 @@ describe('', () => { describe('accessibilityLabel', () => { it('is used on the for the aria-label attribute', () => { const item = mountWithAppProvider( - + - , + , ); expect(item.find(UnstyledLink).prop('aria-label')).toBe( @@ -86,9 +86,9 @@ describe('', () => { describe('url', () => { it('does not render an by default', () => { const element = mountWithAppProvider( - + - , + , ); expect(element.find(UnstyledLink).exists()).toBe(false); @@ -96,9 +96,9 @@ describe('', () => { it('renders an ', () => { const element = mountWithAppProvider( - + - , + , ); expect(element.find(UnstyledLink).exists()).toBe(true); @@ -106,9 +106,9 @@ describe('', () => { it('renders an with url', () => { const element = mountWithAppProvider( - + - , + , ); expect(element.find(UnstyledLink).prop('url')).toBe(url); @@ -116,9 +116,9 @@ describe('', () => { it('renders an with an aria-label of ariaLabel', () => { const element = mountWithAppProvider( - + - , + , ); expect(element.find(UnstyledLink).prop('aria-label')).toBe(ariaLabel); @@ -126,9 +126,9 @@ describe('', () => { it('adds a data-href to the wrapper element', () => { const element = mountWithAppProvider( - + - , + , ); expect(findByTestID(element, 'Item-Wrapper').prop('data-href')).toBe(url); @@ -138,13 +138,13 @@ describe('', () => { describe('id', () => { it('is used on the content node and for the description of a link', () => { const item = mountWithAppProvider( - + - , + , ); expect(findByTestID(item, 'Item-Content').prop('id')).toBe(itemId); @@ -156,9 +156,9 @@ describe('', () => { it('calls onClick when clicking on the item when onClick exists', () => { const onClick = jest.fn(); const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'Item-Wrapper').simulate('click'); @@ -168,14 +168,14 @@ describe('', () => { it('calls onClick when clicking on the item when both onClick and url exist', () => { const onClick = jest.fn(); const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'Item-Wrapper').simulate('click'); @@ -184,9 +184,9 @@ describe('', () => { it('calls window.open on metaKey + click', () => { const wrapper = mountWithAppProvider( - + - , + , ); const item = findByTestID(wrapper, 'Item-Wrapper'); trigger(item, 'onClick', {nativeEvent: {metaKey: true}}); @@ -195,9 +195,9 @@ describe('', () => { it('calls window.open on ctrlKey + click', () => { const wrapper = mountWithAppProvider( - + - , + , ); const item = findByTestID(wrapper, 'Item-Wrapper'); trigger(item, 'onClick', {nativeEvent: {ctrlKey: true}}); @@ -209,9 +209,9 @@ describe('', () => { it('does not call the Item onClick when clicking the LargerSelectionArea', () => { const onClick = jest.fn(); const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'LargerSelectionArea').simulate('click'); @@ -220,9 +220,9 @@ describe('', () => { it('calls onSelectionChange with the id of the item when clicking the LargerSelectionArea', () => { const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'LargerSelectionArea').simulate('click'); @@ -237,9 +237,9 @@ describe('', () => { it('calls onClick when item is clicked', () => { const onClick = jest.fn(); const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'Item-Wrapper').simulate('click'); @@ -249,14 +249,14 @@ describe('', () => { it('calls onSelectionChange with the id of the item even if url or onClick is present', () => { const onClick = jest.fn(); const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'Item-Wrapper').simulate('click'); @@ -268,18 +268,18 @@ describe('', () => { it('renders a checked Checkbox if the item is in the selectedItems context', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(wrapper.find(Checkbox).props().checked).toBe(true); }); it('does not call window.open when clicking the item with metaKey', () => { const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'Item-Wrapper').simulate('click', { nativeEvent: {metaKey: true}, @@ -289,9 +289,9 @@ describe('', () => { it('does not call window.open when clicking the item with ctrlKey', () => { const wrapper = mountWithAppProvider( - + - , + , ); findByTestID(wrapper, 'Item-Wrapper').simulate('click', { nativeEvent: {ctrlKey: true}, @@ -303,27 +303,27 @@ describe('', () => { describe('media', () => { it('does not include media if not provided', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(findByTestID(wrapper, 'Media').exists()).toBe(false); }); it('renders a disabled checked Checkbox if loading context is true', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(wrapper.find(Checkbox).prop('disabled')).toBe(true); }); it('includes an if one is provided', () => { const wrapper = mountWithAppProvider( - + } /> - , + , ); expect( findByTestID(wrapper, 'Media') @@ -334,13 +334,13 @@ describe('', () => { it('includes a if one is provided', () => { const wrapper = mountWithAppProvider( - + } /> - , + , ); expect( findByTestID(wrapper, 'Media') @@ -353,46 +353,46 @@ describe('', () => { describe('shortcutActions', () => { it('does not render shortcut actions if none are provided', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(findByTestID(wrapper, 'ShortcutActions').exists()).toBe(false); }); it('renders shortcut actions when some are provided', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(findByTestID(wrapper, 'ShortcutActions').exists()).toBe(true); }); it('renders persistent shortcut actions if persistActions is true', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(wrapper.find(ButtonGroup).exists()).toBe(true); }); it('does not render while loading', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(wrapper.find(ButtonGroup)).toHaveLength(0); }); @@ -401,28 +401,28 @@ describe('', () => { describe('accessibleMarkup', () => { it('renders with a tab index of -1 when loading is true', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(wrapper.find(UnstyledLink).prop('tabIndex')).toBe(-1); }); it('renders with a tab index of 0 when loading is false', () => { const wrapper = mountWithAppProvider( - + - , + , ); expect(wrapper.find(UnstyledLink).prop('tabIndex')).toBe(0); }); diff --git a/src/components/ResourceList/components/index.ts b/src/components/ResourceList/components/index.ts index f1fbf137e89..1be8efc1a9c 100644 --- a/src/components/ResourceList/components/index.ts +++ b/src/components/ResourceList/components/index.ts @@ -11,5 +11,3 @@ export { } from './FilterControl'; export {default as Item, Props as ItemProps} from './Item'; - -export {Provider, Consumer} from './Context'; diff --git a/src/components/ResourceList/context.tsx b/src/components/ResourceList/context.tsx new file mode 100644 index 00000000000..30ca8342641 --- /dev/null +++ b/src/components/ResourceList/context.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import {Intl} from '../AppProvider'; +import {SelectedItems} from './types'; + +export interface ResourceListContextType { + selectMode: boolean; + selectable?: boolean; + selectedItems?: SelectedItems; + resourceName: { + singular: string; + plural: string; + }; + loading?: boolean; + onSelectionChange?(selected: boolean, id: string): void; +} + +const intl = new Intl(undefined); + +const ResourceListContext = React.createContext({ + selectMode: false, + resourceName: { + singular: intl.translate('Polaris.ResourceList.defaultItemSingular'), + plural: intl.translate('Polaris.ResourceList.defaultItemPlural'), + }, +}); + +export default ResourceListContext; diff --git a/src/components/ResourceList/types.ts b/src/components/ResourceList/types.ts index a184f0ad902..35319884bf0 100644 --- a/src/components/ResourceList/types.ts +++ b/src/components/ResourceList/types.ts @@ -1,15 +1,3 @@ export type SelectedItems = string[] | 'All'; export const SELECT_ALL_ITEMS = 'All'; - -export interface ResourceListContext { - selectMode: boolean; - selectable?: boolean; - selectedItems?: SelectedItems; - resourceName: { - singular: string; - plural: string; - }; - loading?: boolean; - onSelectionChange?(selected: boolean, id: string): void; -} diff --git a/src/components/Scrollable/Scrollable.tsx b/src/components/Scrollable/Scrollable.tsx index 03cf7d74145..fecd4f1620b 100644 --- a/src/components/Scrollable/Scrollable.tsx +++ b/src/components/Scrollable/Scrollable.tsx @@ -9,7 +9,8 @@ import {classNames} from '@shopify/react-utilities/styles'; import {WithAppProviderProps, withAppProvider} from '../AppProvider'; import {scrollable} from '../shared'; -import {ScrollTo, Provider} from './components'; +import {ScrollTo} from './components'; +import ScrollableContext from './context'; import styles from './Scrollable.scss'; @@ -40,10 +41,6 @@ export interface State { scrollPosition: number; } -export interface Context { - scrollToPosition(scrollY: number): void; -} - export type CombinedProps = Props & WithAppProviderProps; class Scrollable extends React.Component { static ScrollTo = ScrollTo; @@ -69,12 +66,6 @@ class Scrollable extends React.Component { {trailing: true}, ); - get getContext(): Context { - return { - scrollToPosition: this.scrollToPosition, - }; - } - componentDidMount() { const {polaris} = this.props; if (this.scrollArea == null) { @@ -132,8 +123,12 @@ class Scrollable extends React.Component { bottomShadow && styles.hasBottomShadow, ); + const context = { + scrollToPosition: this.scrollToPosition, + }; + return ( - +
{ > {children}
-
+ ); } diff --git a/src/components/Scrollable/components/Context/Context.ts b/src/components/Scrollable/components/Context/Context.ts deleted file mode 100644 index 8ad433f659a..00000000000 --- a/src/components/Scrollable/components/Context/Context.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react'; -import {ScrollableContext} from '../../types'; - -const {Provider, Consumer} = React.createContext({}); - -export {Provider, Consumer}; diff --git a/src/components/Scrollable/components/Context/index.ts b/src/components/Scrollable/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/Scrollable/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/Scrollable/components/ScrollTo/ScrollTo.tsx b/src/components/Scrollable/components/ScrollTo/ScrollTo.tsx index b1402ea36ae..86f5511cae0 100644 --- a/src/components/Scrollable/components/ScrollTo/ScrollTo.tsx +++ b/src/components/Scrollable/components/ScrollTo/ScrollTo.tsx @@ -1,11 +1,10 @@ import * as React from 'react'; import {createUniqueIDFactory} from '@shopify/javascript-utilities/other'; import withContext from '../../../WithContext'; -import {Consumer} from '../Context'; -import {ScrollableContext} from '../../types'; +import ScrollableContext, {ScrollableContextType} from '../../context'; import {WithContextTypes} from '../../../../types'; -type ComposedProps = WithContextTypes; +type ComposedProps = WithContextTypes; class ScrollTo extends React.Component { private ref: React.RefObject = React.createRef(); @@ -27,4 +26,6 @@ class ScrollTo extends React.Component { } } -export default withContext<{}, {}, ScrollableContext>(Consumer)(ScrollTo); +export default withContext<{}, {}, ScrollableContextType>( + ScrollableContext.Consumer, +)(ScrollTo); diff --git a/src/components/Scrollable/components/ScrollTo/tests/ScrollTo.test.tsx b/src/components/Scrollable/components/ScrollTo/tests/ScrollTo.test.tsx index 815782a9933..8fdc688f62f 100644 --- a/src/components/Scrollable/components/ScrollTo/tests/ScrollTo.test.tsx +++ b/src/components/Scrollable/components/ScrollTo/tests/ScrollTo.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import {mountWithAppProvider} from 'test-utilities'; import ScrollTo from '../ScrollTo'; -import {Provider} from '../../Context'; +import ScrollableContext from '../../../context'; describe('', () => { it('calls scrollToPosition on mount', () => { @@ -11,9 +11,9 @@ describe('', () => { }; mountWithAppProvider( - + - , + , ); expect(spy).toHaveBeenCalled(); diff --git a/src/components/Scrollable/components/index.ts b/src/components/Scrollable/components/index.ts index 035ae8bd81e..3ff38e22692 100644 --- a/src/components/Scrollable/components/index.ts +++ b/src/components/Scrollable/components/index.ts @@ -1,3 +1 @@ export {default as ScrollTo} from './ScrollTo'; - -export {Provider, Consumer} from './Context'; diff --git a/src/components/Scrollable/context.ts b/src/components/Scrollable/context.ts new file mode 100644 index 00000000000..a347e410c17 --- /dev/null +++ b/src/components/Scrollable/context.ts @@ -0,0 +1,9 @@ +import * as React from 'react'; + +export interface ScrollableContextType { + scrollToPosition?(scrollY: number): void; +} + +const ScrollableContext = React.createContext({}); + +export default ScrollableContext; diff --git a/src/components/Scrollable/tests/Scrollable.test.tsx b/src/components/Scrollable/tests/Scrollable.test.tsx index 100ef02096b..d74ea223e54 100644 --- a/src/components/Scrollable/tests/Scrollable.test.tsx +++ b/src/components/Scrollable/tests/Scrollable.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import {mountWithAppProvider} from 'test-utilities'; import Scrollable from '../Scrollable'; -import {Provider, Consumer} from '../components'; +import ScrollableContext from '../context'; describe('', () => { it('mounts', () => { @@ -31,17 +31,17 @@ describe('', () => { it('provides scrollToPosition callback to children', () => { const Child: React.SFC<{}> = (_) => ( - + {({scrollToPosition}) => (scrollToPosition ?
: null)} - + ); const scrollableContainer = mountWithAppProvider( - {}}}> + {}}}> - , + , ); const div = scrollableContainer diff --git a/src/components/Scrollable/types.ts b/src/components/Scrollable/types.ts deleted file mode 100644 index eef5c222ff4..00000000000 --- a/src/components/Scrollable/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface ScrollableContext { - scrollToPosition?(scrollY: number): void; -} diff --git a/src/components/ThemeProvider/ThemeProvider.tsx b/src/components/ThemeProvider/ThemeProvider.tsx index d3af0222e0e..963c01ec3d2 100644 --- a/src/components/ThemeProvider/ThemeProvider.tsx +++ b/src/components/ThemeProvider/ThemeProvider.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import isEqual from 'lodash/isEqual'; import {setColors} from './utils'; -import {Theme, ThemeProviderContext} from './types'; -import {Provider} from './components'; +import {Theme} from './types'; +import ThemeProviderContext from './context'; export interface State { theme: Theme; @@ -46,24 +46,22 @@ export default class ThemeProvider extends React.Component { }); } - get getContext(): ThemeProviderContext { + render() { const { theme: {logo = null, ...rest}, } = this.state; + const {children} = this.props; + const styles = this.createStyles() || defaultTheme; - return { + const context = { ...rest, logo, }; - } - - render() { - const styles = this.createStyles() || defaultTheme; return ( - -
{React.Children.only(this.props.children)}
-
+ +
{React.Children.only(children)}
+
); } diff --git a/src/components/ThemeProvider/components/Context/Context.tsx b/src/components/ThemeProvider/components/Context/Context.tsx deleted file mode 100644 index 29943d6c9ee..00000000000 --- a/src/components/ThemeProvider/components/Context/Context.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import * as React from 'react'; -import {ThemeProviderContext} from '../../types'; - -const {Provider, Consumer} = React.createContext({ - logo: null, -}); - -export {Provider, Consumer}; diff --git a/src/components/ThemeProvider/components/Context/index.ts b/src/components/ThemeProvider/components/Context/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/ThemeProvider/components/Context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/ThemeProvider/components/index.ts b/src/components/ThemeProvider/components/index.ts deleted file mode 100644 index e45eea34bd9..00000000000 --- a/src/components/ThemeProvider/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {Provider, Consumer} from './Context'; diff --git a/src/components/ThemeProvider/context.tsx b/src/components/ThemeProvider/context.tsx new file mode 100644 index 00000000000..d0042959e4a --- /dev/null +++ b/src/components/ThemeProvider/context.tsx @@ -0,0 +1,12 @@ +import * as React from 'react'; +import {Theme} from './types'; + +export interface ThemeProviderContextType { + logo: Theme['logo'] | null; +} + +const ThemeContext = React.createContext({ + logo: null, +}); + +export default ThemeContext; diff --git a/src/components/ThemeProvider/index.ts b/src/components/ThemeProvider/index.ts index b29b41c7419..b083320a5b3 100644 --- a/src/components/ThemeProvider/index.ts +++ b/src/components/ThemeProvider/index.ts @@ -2,13 +2,15 @@ import ThemeProvider from './ThemeProvider'; export { Theme, - ThemeProviderContext, ColorsToParse, ThemeVariant, ThemeColors, THEME_CONTEXT_TYPES, } from './types'; -export {Provider, Consumer} from './components'; +export { + default as ThemeProviderContext, + ThemeProviderContextType, +} from './context'; export { setColors, needsVariant, diff --git a/src/components/ThemeProvider/tests/ThemeProvider.test.tsx b/src/components/ThemeProvider/tests/ThemeProvider.test.tsx index 2c4d305a64a..58c0dd47eb2 100644 --- a/src/components/ThemeProvider/tests/ThemeProvider.test.tsx +++ b/src/components/ThemeProvider/tests/ThemeProvider.test.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import {mountWithAppProvider} from 'test-utilities'; import ThemeProvider from '../ThemeProvider'; -import {Consumer} from '../components'; +import ThemeProviderContext from '../context'; describe('', () => { it('mounts', () => { @@ -16,11 +16,11 @@ describe('', () => { it('passes context', () => { const Child: React.SFC<{}> = (_props) => { return ( - + {(polarisTheme) => polarisTheme && polarisTheme.logo ?
: null } - + ); }; diff --git a/src/components/ThemeProvider/types.ts b/src/components/ThemeProvider/types.ts index 4cb8ffdd358..dde38de5ea1 100644 --- a/src/components/ThemeProvider/types.ts +++ b/src/components/ThemeProvider/types.ts @@ -34,10 +34,6 @@ export interface Theme { colors?: ThemeColors; } -export interface ThemeProviderContext { - logo: Theme['logo'] | null; -} - export type ThemeVariant = 'light' | 'dark'; export const THEME_CONTEXT_TYPES = {polarisTheme: PropTypes.any}; diff --git a/src/components/ThemeProvider/utils/index.ts b/src/components/ThemeProvider/utils/index.ts index 7ca3afa8dee..9c5fd271dd4 100644 --- a/src/components/ThemeProvider/utils/index.ts +++ b/src/components/ThemeProvider/utils/index.ts @@ -11,13 +11,8 @@ import {constructColorName} from '../../../utilities/color-names'; import {createLightColor} from '../../../utilities/color-manipulation'; import {compose} from '../../../utilities/compose'; -import { - Theme, - ColorsToParse, - ThemeVariant, - ThemeColors, - ThemeProviderContext, -} from '../types'; +import {Theme, ColorsToParse, ThemeVariant, ThemeColors} from '../types'; +import {ThemeProviderContextType} from '../context'; export function setColors(theme: Theme | undefined): string[][] | undefined { let colorPairs; @@ -125,8 +120,8 @@ function parseColors([baseName, colors]: [string, ColorsToParse]): string[][] { } export function createThemeContext( - theme?: ThemeProviderContext, -): ThemeProviderContext { + theme?: ThemeProviderContextType, +): ThemeProviderContextType { if (!theme) { return {logo: null}; } diff --git a/src/components/Toast/Toast.tsx b/src/components/Toast/Toast.tsx index 8da07cfbb8a..d5e65548098 100644 --- a/src/components/Toast/Toast.tsx +++ b/src/components/Toast/Toast.tsx @@ -7,8 +7,8 @@ import {WithContextTypes} from '../../types'; import { DEFAULT_TOAST_DURATION, + FrameContextType, FrameContext, - Consumer, ToastProps, } from '../Frame'; import {withAppProvider, WithAppProviderProps} from '../AppProvider'; @@ -23,10 +23,10 @@ interface Props extends ToastProps {} export type ComposedProps = Props & WithAppProviderProps & - WithContextTypes; + WithContextTypes; export class Toast extends React.PureComponent { - context: FrameContext; + context: FrameContextType; private id = createId(); private appBridgeToast: AppBridgeToast.Toast | undefined; @@ -76,6 +76,8 @@ export class Toast extends React.PureComponent { } export default compose( - withContext(Consumer), + withContext( + FrameContext.Consumer, + ), withAppProvider(), )(Toast); diff --git a/src/components/Toast/tests/Toast.test.tsx b/src/components/Toast/tests/Toast.test.tsx index f7b290776d9..6209337117d 100644 --- a/src/components/Toast/tests/Toast.test.tsx +++ b/src/components/Toast/tests/Toast.test.tsx @@ -3,7 +3,7 @@ import {Toast as AppBridgeToast} from '@shopify/app-bridge/actions'; import {mountWithAppProvider} from 'test-utilities'; import {noop} from '../../../utilities/other'; import Toast from '../Toast'; -import {Provider, createFrameContext} from '../../Frame'; +import {FrameContext, createFrameContext} from '../../Frame'; describe('', () => { beforeEach(() => { @@ -17,9 +17,9 @@ describe('', () => { const props = {content: 'Image uploaded', onDismiss: noop}; mountWithAppProvider( - + - , + , ); expect(mockFrameContext.showToast).toHaveBeenCalledWith( @@ -33,9 +33,9 @@ describe('', () => { }); const frame = mountWithAppProvider( - + - , + , ); expect(mockFrameContext.hideToast).not.toHaveBeenCalled(); diff --git a/src/components/TopBar/tests/TopBar.test.tsx b/src/components/TopBar/tests/TopBar.test.tsx index 03b9b80ce7d..4d531bedb42 100644 --- a/src/components/TopBar/tests/TopBar.test.tsx +++ b/src/components/TopBar/tests/TopBar.test.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import {noop} from '@shopify/javascript-utilities/other'; import {mountWithAppProvider, findByTestID} from 'test-utilities'; import {Image, UnstyledLink} from 'components'; -import {ThemeProviderContext} from '../../ThemeProvider'; +import {ThemeProviderContextType} from '../../ThemeProvider'; import TopBar from '../TopBar'; import {Menu, SearchField, UserMenu, Search} from '../components'; import merge from '../../../utilities/merge'; @@ -230,7 +230,9 @@ describe('', () => { }); }); -function mergeThemeProviderContext(providedThemeContext: ThemeProviderContext) { +function mergeThemeProviderContext( + providedThemeContext: ThemeProviderContextType, +) { return { context: { themeProvider: merge({logo: null}, providedThemeContext), diff --git a/src/components/WithinContentContext/WithinContentContext.tsx b/src/components/WithinContentContext/WithinContentContext.tsx deleted file mode 100644 index cb04b3a414f..00000000000 --- a/src/components/WithinContentContext/WithinContentContext.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; - -export interface WithinContentContext { - withinContentContainer: boolean; -} - -const {Provider, Consumer} = React.createContext({ - withinContentContainer: false, -}); - -export {Provider, Consumer}; diff --git a/src/components/WithinContentContext/context.tsx b/src/components/WithinContentContext/context.tsx new file mode 100644 index 00000000000..0ed46b22085 --- /dev/null +++ b/src/components/WithinContentContext/context.tsx @@ -0,0 +1,11 @@ +import * as React from 'react'; + +export interface WithinContentContextType { + withinContentContainer: boolean; +} + +const WithinContentContext = React.createContext({ + withinContentContainer: false, +}); + +export default WithinContentContext; diff --git a/src/components/WithinContentContext/index.ts b/src/components/WithinContentContext/index.ts index ab8ed75bb31..e6605ee442c 100644 --- a/src/components/WithinContentContext/index.ts +++ b/src/components/WithinContentContext/index.ts @@ -1 +1,4 @@ -export {Provider, Consumer, WithinContentContext} from './WithinContentContext'; +import WithinContentContext from './context'; + +export {WithinContentContextType} from './context'; +export default WithinContentContext; diff --git a/src/components/index.ts b/src/components/index.ts index 64388a592a0..e6b2475be00 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -8,7 +8,6 @@ export {default as ActionList, Props as ActionListProps} from './ActionList'; export { default as AppProvider, Props as AppProviderProps, - AppProviderContextType, createAppProviderContext, createPolarisContext, withAppProvider, @@ -257,7 +256,7 @@ export {default as Thumbnail, Props as ThumbnailProps} from './Thumbnail'; export { default as ThemeProvider, Props as ThemeProviderProps, - ThemeProviderContext, + ThemeProviderContextType, createThemeContext, } from './ThemeProvider'; diff --git a/src/components/types.ts b/src/components/types.ts index cfc240fbf92..0606d0c7216 100644 --- a/src/components/types.ts +++ b/src/components/types.ts @@ -1,8 +1,8 @@ import {AppProviderContextType} from './AppProvider'; -import {ThemeProviderContext} from './ThemeProvider'; +import {ThemeProviderContextType} from './ThemeProvider'; export interface PolarisContext extends AppProviderContextType { - theme: ThemeProviderContext; + theme: ThemeProviderContextType; } export type TransitionStatus = 'entering' | 'entered' | 'exiting' | 'exited'; diff --git a/src/test-utilities/enzyme.tsx b/src/test-utilities/enzyme.tsx index 58e7d2b1140..eb5935be479 100644 --- a/src/test-utilities/enzyme.tsx +++ b/src/test-utilities/enzyme.tsx @@ -12,12 +12,12 @@ import { AppProviderContext, } from '../components/AppProvider'; // eslint-disable-next-line shopify/strict-component-boundaries -import {Provider as FrameProvider, FrameContext} from '../components/Frame'; +import {FrameContext, FrameContextType} from '../components/Frame'; // eslint-disable-next-line shopify/strict-component-boundaries import { createThemeContext, + ThemeProviderContextType, ThemeProviderContext, - Provider as ThemeProviderProvider, } from '../components/ThemeProvider'; export type AnyWrapper = ReactWrapper | CommonWrapper; @@ -82,8 +82,8 @@ function updateRoot(wrapper: AnyWrapper) { type AppContext = { polaris: PolarisContext; - themeProvider: ThemeProviderContext; - frame: FrameContext; + themeProvider: ThemeProviderContextType; + frame: FrameContextType; }; interface AppContextOptions { @@ -93,8 +93,8 @@ interface AppContextOptions { interface MountWithAppProviderOptions { context?: { polaris?: DeepPartial; - themeProvider?: DeepPartial; - frame?: DeepPartial; + themeProvider?: DeepPartial; + frame?: DeepPartial; }; } @@ -151,9 +151,11 @@ export function polarisContextReactWrapper( return ( - - {content} - + + + {content} + + ); }