diff --git a/packages/react-core/package.json b/packages/react-core/package.json index c856a0a76c7..3a8f4147143 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -43,9 +43,7 @@ "@patternfly/react-icons": "^3.15.13", "@patternfly/react-styles": "^3.7.10", "@patternfly/react-tokens": "^2.8.10", - "emotion": "^9.2.9", - "exenv": "^1.2.2", - "focus-trap-react": "^4.0.1", + "focus-trap": "4.0.2", "react-dropzone": "9.0.0", "tippy.js": "5.1.2" }, @@ -59,7 +57,6 @@ "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "@patternfly/patternfly": "2.70.1", - "@types/exenv": "^1.2.0", "@types/jest": "^24.0.11", "@types/react": "^16.4.0", "@types/react-dom": "^16.4.0", diff --git a/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx b/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx index bf0d32ee619..3d78816e850 100644 --- a/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx +++ b/packages/react-core/src/components/AboutModal/AboutModalContainer.tsx @@ -1,10 +1,7 @@ import * as React from 'react'; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const FocusTrap: any = require('focus-trap-react'); - -import styles from '@patternfly/react-styles/css/layouts/Bullseye/bullseye'; import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/layouts/Bullseye/bullseye'; +import { FocusTrap } from '../../helpers'; import { AboutModalBoxContent } from './AboutModalBoxContent'; import { AboutModalBoxHeader } from './AboutModalBoxHeader'; diff --git a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx index 504118b62e3..674b0a9dc98 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx +++ b/packages/react-core/src/components/AboutModal/__tests__/AboutModalBoxCloseButton.test.tsx @@ -14,7 +14,7 @@ test('AboutModalBoxCloseButton Test onclose', () => { }); test('AboutModalBoxCloseButton Test close button aria label', () => { - const closeButtonAriaLabel = 'Klose Daylok' + const closeButtonAriaLabel = 'Klose Daylok'; const view = shallow(); expect(view).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap index c050d70c6b6..7c7adf129a1 100644 --- a/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap +++ b/packages/react-core/src/components/AboutModal/__tests__/__snapshots__/AboutModalContainer.test.tsx.snap @@ -3,7 +3,6 @@ exports[`About Modal Container Test isOpen 1`] = ` { test('Action Close Button', () => { const onClose = jest.fn(); const view = mount( - } title={`Sample ${variant} alert`}> + } + title={`Sample ${variant} alert`} + > Some alert ); diff --git a/packages/react-core/src/components/ContextSelector/ContextSelector.tsx b/packages/react-core/src/components/ContextSelector/ContextSelector.tsx index 4282c86c952..b961b3b7895 100644 --- a/packages/react-core/src/components/ContextSelector/ContextSelector.tsx +++ b/packages/react-core/src/components/ContextSelector/ContextSelector.tsx @@ -9,11 +9,7 @@ import { Button, ButtonVariant } from '../Button'; import { TextInput } from '../TextInput'; import { InputGroup } from '../InputGroup'; import { KEY_CODES } from '../../helpers/constants'; - -// Can't use ES6 imports :( -// The types for it are also wrong, we should probably ditch this dependency. -/* eslint-disable-next-line @typescript-eslint/no-var-requires */ -const FocusTrap: any = require('focus-trap-react'); +import { FocusTrap } from '../../helpers'; // seed for the aria-labelledby ID let currentId = 0; diff --git a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap index 127abc6f145..db99a9d1ffd 100644 --- a/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap +++ b/packages/react-core/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap @@ -41,7 +41,6 @@ exports[`Renders ContextSelector open 1`] = ` className="pf-c-context-selector__menu" >
{ const panelContent = ( - + drawer-panel - + - drawer-panel - ); - const drawerContent = + drawer-panel + + ); + const drawerContent = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut. Morbi viverra, eros vel porttitor facilisis, eros purus aliquet erat,nec lobortis felis elit pulvinar sem. Vivamus vulputate, risus eget commodo eleifend, eros nibh porta quam, vitae lacinia leo libero at magna. Maecenas aliquam sagittis orci, et posuere nisi ultrices sit amet. Aliquam ex odio, malesuada sed posuere quis, pellentesque at mauris. Phasellus venenatis massa ex, eget pulvinar libero auctor pretium. Aliquam erat volutpat. Duis euismod justo in quam ullamcorper, in commodo massa vulputate.'; test(`Drawer isExpanded = ${isExpanded} and isInline = ${isInline} and isStatic = ${isStatic}`, () => { const view = mount( - - {drawerContent} - - ); + + {drawerContent} + + + ); expect(view).toMatchSnapshot(); }); }); diff --git a/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx b/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx index dfbb4eceb24..0decd02e1a7 100644 --- a/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx +++ b/packages/react-core/src/components/Dropdown/__tests__/Dropdown.test.tsx @@ -185,18 +185,20 @@ describe('API', () => { }); test('dropdownItems and children console error ', () => { - const myMock = jest.fn(); - global.console = { error: myMock } as any; - mount( - Dropdown} - > -
Children items
-
- ) - expect(myMock).toBeCalledWith('Children and dropdownItems props have been provided. Only the dropdownItems prop items will be rendered'); + const myMock = jest.fn(); + global.console = { error: myMock } as any; + mount( + Dropdown} + > +
Children items
+
+ ); + expect(myMock).toBeCalledWith( + 'Children and dropdownItems props have been provided. Only the dropdownItems prop items will be rendered' + ); }); test('dropdownItems only, no console error ', () => { diff --git a/packages/react-core/src/components/FileUpload/__tests__/FileUpload.test.tsx b/packages/react-core/src/components/FileUpload/__tests__/FileUpload.test.tsx index a192bd1fb40..e8d4945a5a8 100644 --- a/packages/react-core/src/components/FileUpload/__tests__/FileUpload.test.tsx +++ b/packages/react-core/src/components/FileUpload/__tests__/FileUpload.test.tsx @@ -7,16 +7,17 @@ test('simple fileupload', () => { const readStartedHandler = jest.fn(); const readFinishedHandler = jest.fn(); - const view = shallow(); + const view = shallow( + + ); expect(view).toMatchSnapshot(); }); - diff --git a/packages/react-core/src/components/FileUpload/__tests__/FileUploadField.test.tsx b/packages/react-core/src/components/FileUpload/__tests__/FileUploadField.test.tsx index 8247d26a019..cc50e8011de 100644 --- a/packages/react-core/src/components/FileUpload/__tests__/FileUploadField.test.tsx +++ b/packages/react-core/src/components/FileUpload/__tests__/FileUploadField.test.tsx @@ -7,21 +7,23 @@ test('simple fileuploadfield', () => { const browserBtnClickHandler = jest.fn(); const clearBtnClickHandler = jest.fn(); - const view = shallow( - {

A custom preview of the uploaded file can be passed as children

} -
); + const view = shallow( + + {

A custom preview of the uploaded file can be passed as children

} +
+ ); expect(view).toMatchSnapshot(); }); diff --git a/packages/react-core/src/components/Modal/ModalContent.tsx b/packages/react-core/src/components/Modal/ModalContent.tsx index 321c5fa82d6..3a264b39e53 100644 --- a/packages/react-core/src/components/Modal/ModalContent.tsx +++ b/packages/react-core/src/components/Modal/ModalContent.tsx @@ -1,12 +1,7 @@ import * as React from 'react'; - -// Can't use ES6 imports :( -// The types for it are also wrong, we should probably ditch this dependency. -// eslint-disable-next-line @typescript-eslint/no-var-requires -const FocusTrap: any = require('focus-trap-react'); - -import styles from '@patternfly/react-styles/css/layouts/Bullseye/bullseye'; +import { FocusTrap } from '../../helpers'; import titleStyles from '@patternfly/react-styles/css/components/Title/title'; +import styles from '@patternfly/react-styles/css/layouts/Bullseye/bullseye'; import { css } from '@patternfly/react-styles'; import { Backdrop } from '../Backdrop/Backdrop'; diff --git a/packages/react-core/src/components/Modal/__tests__/__snapshots__/ModalContent.test.tsx.snap b/packages/react-core/src/components/Modal/__tests__/__snapshots__/ModalContent.test.tsx.snap index 53bd2c2ae25..9d14ed11a0c 100644 --- a/packages/react-core/src/components/Modal/__tests__/__snapshots__/ModalContent.test.tsx.snap +++ b/packages/react-core/src/components/Modal/__tests__/__snapshots__/ModalContent.test.tsx.snap @@ -3,7 +3,6 @@ exports[`Modal Content Test description 1`] = ` , 'checked' | 'selected' | 'ref'> { /** Content rendered inside the SelectMenu */ diff --git a/packages/react-core/src/components/Select/__tests__/__snapshots__/Select.test.tsx.snap b/packages/react-core/src/components/Select/__tests__/__snapshots__/Select.test.tsx.snap index 01e65e24294..fd86cfbaeb2 100644 --- a/packages/react-core/src/components/Select/__tests__/__snapshots__/Select.test.tsx.snap +++ b/packages/react-core/src/components/Select/__tests__/__snapshots__/Select.test.tsx.snap @@ -432,7 +432,6 @@ exports[`checkbox select renders checkbox select groups successfully - old class sendRef={[Function]} >
diff --git a/packages/react-core/src/helpers/FocusTrap/FocusTrap.tsx b/packages/react-core/src/helpers/FocusTrap/FocusTrap.tsx new file mode 100644 index 00000000000..34aeed04222 --- /dev/null +++ b/packages/react-core/src/helpers/FocusTrap/FocusTrap.tsx @@ -0,0 +1,85 @@ +import * as React from 'react'; +import createFocusTrap from 'focus-trap'; +import { Options as FocusTrapOptions, FocusTrap as IFocusTrap } from 'focus-trap'; + +interface FocusTrapProps { + children: React.ReactNode; + className?: string; + active?: boolean; + paused?: boolean; + focusTrapOptions?: FocusTrapOptions; +} + +export class FocusTrap extends React.Component { + previouslyFocusedElement: HTMLElement; + focusTrap: IFocusTrap; + divRef = React.createRef(); + + static defaultProps = { + active: true, + paused: false, + focusTrapOptions: {} + }; + + constructor(props: FocusTrapProps) { + super(props); + + if (typeof document !== 'undefined') { + this.previouslyFocusedElement = document.activeElement as HTMLElement; + } + } + + componentDidMount() { + // We need to hijack the returnFocusOnDeactivate option, + // because React can move focus into the element before we arrived at + // this lifecycle hook (e.g. with autoFocus inputs). So the component + // captures the previouslyFocusedElement in componentWillMount, + // then (optionally) returns focus to it in componentWillUnmount. + this.focusTrap = createFocusTrap(this.divRef.current, { + ...this.props.focusTrapOptions, + returnFocusOnDeactivate: false + }); + if (this.props.active) { + this.focusTrap.activate(); + } + if (this.props.paused) { + this.focusTrap.pause(); + } + } + + componentDidUpdate(prevProps: FocusTrapProps) { + if (prevProps.active && !this.props.active) { + const { returnFocusOnDeactivate } = this.props.focusTrapOptions; + const returnFocus = returnFocusOnDeactivate || false; + const config = { returnFocus }; + this.focusTrap.deactivate(config); + } else if (!prevProps.active && this.props.active) { + this.focusTrap.activate(); + } + + if (prevProps.paused && !this.props.paused) { + this.focusTrap.unpause(); + } else if (!prevProps.paused && this.props.paused) { + this.focusTrap.pause(); + } + } + + componentWillUnmount() { + this.focusTrap.deactivate(); + if ( + this.props.focusTrapOptions.returnFocusOnDeactivate !== false && + this.previouslyFocusedElement && + this.previouslyFocusedElement.focus + ) { + this.previouslyFocusedElement.focus(); + } + } + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} diff --git a/packages/react-core/src/helpers/index.ts b/packages/react-core/src/helpers/index.ts index 93812a9259c..ff565e7e511 100644 --- a/packages/react-core/src/helpers/index.ts +++ b/packages/react-core/src/helpers/index.ts @@ -1,5 +1,6 @@ -export { default as GenerateId } from './GenerateId/GenerateId'; -export * from './util'; export * from './constants'; +export * from './FocusTrap/FocusTrap'; +export { default as GenerateId } from './GenerateId/GenerateId'; export * from './htmlConstants'; export * from './typeUtils'; +export * from './util'; diff --git a/packages/react-inline-edit-extension/package.json b/packages/react-inline-edit-extension/package.json index 40e3eb54a73..ace46e80c6e 100644 --- a/packages/react-inline-edit-extension/package.json +++ b/packages/react-inline-edit-extension/package.json @@ -33,7 +33,6 @@ "@patternfly/react-styles": "^3.7.10", "@patternfly/react-table": "^2.28.21", "classnames": "^2.2.5", - "exenv": "^1.2.2", "reactabular-table": "^8.14.0" }, "peerDependencies": { @@ -47,6 +46,7 @@ "build:babel:cjs": "babel --source-maps --extensions \".js,.ts,.tsx\" src --out-dir dist/js --presets=@babel/env", "build:babel:esm": "babel --source-maps --extensions \".js,.ts,.tsx\" src --out-dir dist/esm", "build:babel:umd": "babel --source-maps --extensions \".js\" dist/esm --out-dir dist/umd --plugins=transform-es2015-modules-umd", + "clean": "rimraf dist", "develop": "yarn build:babel:esm --skip-initial-build --watch --verbose", "postbuild": "node ./build/copyStyles.js" }, @@ -67,6 +67,7 @@ "css": "^2.2.3", "fs-extra": "^6.0.1", "glob": "^7.1.2", - "npmlog": "^4.1.2" + "npmlog": "^4.1.2", + "rimraf": "^2.6.2" } } diff --git a/packages/react-table/package.json b/packages/react-table/package.json index 67c75589c0c..1a17a193ad2 100644 --- a/packages/react-table/package.json +++ b/packages/react-table/package.json @@ -33,7 +33,6 @@ "@patternfly/react-styles": "^3.7.10", "@patternfly/react-tokens": "^2.8.10", "classnames": "^2.2.5", - "exenv": "^1.2.2", "lodash": "^4.17.15" }, "peerDependencies": { diff --git a/packages/react-virtualized-extension/package.json b/packages/react-virtualized-extension/package.json index baba4c361f0..6b703e4c6ec 100644 --- a/packages/react-virtualized-extension/package.json +++ b/packages/react-virtualized-extension/package.json @@ -34,7 +34,6 @@ "@types/react-virtualized": "^9.21.5", "clsx": "^1.0.1", "dom-helpers": "^2.4.0 || ^3.0.0", - "exenv": "^1.2.2", "linear-layout-vector": "0.0.1", "react-lifecycles-compat": "^3.0.4", "react-virtualized": "^9.21.1" diff --git a/scripts/verifyPatternflyVersions.js b/scripts/verifyPatternflyVersions.js index 867dcd952bb..bf322294756 100644 --- a/scripts/verifyPatternflyVersions.js +++ b/scripts/verifyPatternflyVersions.js @@ -25,7 +25,7 @@ function setDependency(dependencies, package, version) { } async function verifyPatternflyVersions() { - const packages = (await new Project(__dirname).getPackages()); + const packages = await new Project(__dirname).getPackages(); packages.forEach(package => { accumulateDependencies(package.name, { [package.name]: `^${package.version}` }); @@ -34,18 +34,21 @@ async function verifyPatternflyVersions() { }); let failed = false; - const mismatchedVersions = Object.entries(patternflyDeps) - .filter(([_dep, versions]) => Object.keys(versions).length > 1); - + const mismatchedVersions = Object.entries(patternflyDeps).filter( + ([_dep, versions]) => Object.keys(versions).length > 1 + ); + mismatchedVersions.forEach(([dep, versions]) => { - failed = true; - console.error(`Mismatching versions for ${dep}:`); - Object.entries(versions).forEach(([version, packages]) => console.error(`${version}: ${packages.join(' ')}`)); - }); - + failed = true; + console.error(`Mismatching versions for ${dep}:`); + Object.entries(versions).forEach(([version, packages]) => console.error(`${version}: ${packages.join(' ')}`)); + }); + if (process.argv[2] === '--fix') { mismatchedVersions.forEach(([dep, versions]) => { - const highestVersion = Object.keys(versions).sort().reverse()[0]; + const highestVersion = Object.keys(versions) + .sort() + .reverse()[0]; Object.keys(versions) .filter(version => version !== highestVersion) .map(version => versions[version]) diff --git a/yarn.lock b/yarn.lock index 4236148da3b..511e14d49c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3691,10 +3691,6 @@ version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" -"@types/exenv@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/exenv/-/exenv-1.2.0.tgz#84ff936feeafc917c3c66f80b43e917f56eed00b" - "@types/geojson@*": version "7946.0.7" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad" @@ -9612,10 +9608,6 @@ executable@4.1.1: dependencies: pify "^2.2.0" -exenv@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" - exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -10222,17 +10214,12 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -focus-trap-react@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-4.0.1.tgz#3cffd39341df3b2f546a4a2fe94cfdea66154683" - dependencies: - focus-trap "^3.0.0" - -focus-trap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-3.0.0.tgz#4d2ee044ae66bf7eb6ebc6c93bd7a1039481d7dc" +focus-trap@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-4.0.2.tgz#4ee2b96547c9ea0e4252a2d4b2cca68944194663" + integrity sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw== dependencies: - tabbable "^3.1.0" + tabbable "^3.1.2" xtend "^4.0.1" follow-redirects@1.5.10: @@ -20843,9 +20830,10 @@ symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" -tabbable@^3.1.0: +tabbable@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2" + integrity sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ== table-layout@^0.4.3, table-layout@~0.4.0: version "0.4.5"