diff --git a/.eslintrc.js b/.eslintrc.js index 8b3f743..5231550 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,6 +17,7 @@ module.exports = { 'react-hooks', 'import', 'jest', + 'es5', ], env: { es6: true, @@ -62,7 +63,7 @@ module.exports = { 'no-plusplus': 'off', // Always enforcing the use of curly braces for if statements - 'curly': ['error', 'all'], + curly: ['error', 'all'], 'no-restricted-syntax': [ // Nicer booleans #1 @@ -102,14 +103,16 @@ module.exports = { // No usage of `tiny-invariant`. Must use our own invariant for error flow { selector: 'ImportDeclaration[source.value="tiny-invariant"]', - message: 'Please use our own invariant function (src/invariant.js) to ensure correct error flow' + message: + 'Please use our own invariant function (src/invariant.js) to ensure correct error flow', }, // Must use invariant to throw { selector: 'ThrowStatement', - message: 'Please use invariant (src/invariant.js) for throwing. This is to ensure correct error flows' - } + message: + 'Please use invariant (src/invariant.js) for throwing. This is to ensure correct error flows', + }, ], // Allowing Math.pow rather than forcing `**` @@ -206,4 +209,14 @@ module.exports = { // don't need to initialize state in a constructor 'react/state-in-constructor': 'off', }, + overrides: [ + // Forbid using not es5 methods + { + files: 'src/**/*.js', + rules: { + 'es5/no-es6-methods': 'error', + 'es5/no-es6-static-methods': 'error', + }, + }, + ], }; diff --git a/.size-snapshot.json b/.size-snapshot.json index 83ee934..eab2ab4 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -1,25 +1,25 @@ { "dist/react-beautiful-dnd.js": { - "bundled": 379875, - "minified": 139571, - "gzipped": 41966 + "bundled": 365555, + "minified": 134065, + "gzipped": 39834 }, "dist/react-beautiful-dnd.min.js": { - "bundled": 321489, - "minified": 115006, - "gzipped": 34084 + "bundled": 307334, + "minified": 109550, + "gzipped": 31958 }, "dist/react-beautiful-dnd.esm.js": { - "bundled": 241086, - "minified": 125714, - "gzipped": 32875, + "bundled": 241599, + "minified": 125790, + "gzipped": 32910, "treeshaked": { "rollup": { - "code": 21306, - "import_statements": 788 + "code": 21158, + "import_statements": 503 }, "webpack": { - "code": 24963 + "code": 24653 } } } diff --git a/package.json b/package.json index 9b21d3b..8926ea5 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "prepublishOnly": "yarn build" }, "dependencies": { - "@babel/runtime-corejs2": "^7.6.3", + "@babel/runtime": "^7.6.3", "css-box-model": "^1.2.0", "memoize-one": "^5.1.1", "raf-schd": "^4.0.2", @@ -96,6 +96,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-cypress": "^2.7.0", "eslint-plugin-emotion": "^10.0.14", + "eslint-plugin-es5": "^1.4.1", "eslint-plugin-flowtype": "^4.3.0", "eslint-plugin-import": "^2.18.2", "eslint-plugin-jest": "^22.20.0", diff --git a/rollup.config.js b/rollup.config.js index 943290e..943a85c 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,7 +20,7 @@ const excludeAllExternals = id => !id.startsWith('.') && !id.startsWith('/'); const getBabelOptions = ({ useESModules }) => ({ exclude: 'node_modules/**', runtimeHelpers: true, - plugins: [['@babel/transform-runtime', { corejs: 2, useESModules }]], + plugins: [['@babel/transform-runtime', { useESModules }]], }); const snapshotArgs = diff --git a/src/native-with-fallback.js b/src/native-with-fallback.js index 8cc7291..9775ea9 100644 --- a/src/native-with-fallback.js +++ b/src/native-with-fallback.js @@ -1,14 +1,30 @@ // @flow +/* eslint-disable es5/no-es6-methods */ + type Map = { [key: string]: T, }; -// @babel/runtime-corejs2 will replace Object.values +// Number.isInteger is not forbidden yet +// https://github.com/nkt/eslint-plugin-es5/pull/37 +export function isInteger(value: mixed): boolean { + if (Number.isInteger) { + return Number.isInteger(value); + } + return ( + typeof value === 'number' && isFinite(value) && Math.floor(value) === value + ); +} + // Using this helper to ensure there are correct flow types // https://github.com/facebook/flow/issues/2221 export function values(map: Map): T[] { - // $FlowFixMe - Object.values currently does not have good flow support - return Object.values(map); + if (Object.values) { + // $FlowFixMe - Object.values currently does not have good flow support + return Object.values(map); + } + + return Object.keys(map).map(key => map[key]); } // Could also extend to pass index and list diff --git a/src/view/assign-visually-hidden-style.js b/src/view/assign-visually-hidden-style.js new file mode 100644 index 0000000..827a407 --- /dev/null +++ b/src/view/assign-visually-hidden-style.js @@ -0,0 +1,16 @@ +// @flow +// https://allyjs.io/tutorials/hiding-elements.html +// Element is visually hidden but is readable by screen readers +const assignVisuallyHidden = (style: Object) => { + style.position = 'absolute'; + style.width = '1px'; + style.height = '1px'; + style.margin = '-1px'; + style.border = '0'; + style.padding = '0'; + style.overflow = 'hidden'; + style.clip = 'rect(0 0 0 0)'; + style['clip-path'] = 'inset(100%)'; +}; + +export default assignVisuallyHidden; diff --git a/src/view/draggable/use-validation.js b/src/view/draggable/use-validation.js index 175d09f..81db93a 100644 --- a/src/view/draggable/use-validation.js +++ b/src/view/draggable/use-validation.js @@ -1,6 +1,7 @@ // @flow import { useRef } from 'react'; import { invariant } from '../../invariant'; +import { isInteger } from '../../native-with-fallback.js'; import type { DraggableId, ContextId } from '../../types'; import type { Props } from './draggable-types'; import checkIsValidInnerRef from '../check-is-valid-inner-ref'; @@ -21,7 +22,6 @@ export function useValidation( // wrapping entire block for better minification const id: ?DraggableId = props.draggableId; - // Number.isInteger will be provided by @babel/runtime-corejs2 invariant(id, 'Draggable requires a draggableId'); invariant( typeof id === 'string', @@ -30,7 +30,7 @@ export function useValidation( ); invariant( - Number.isInteger(props.index), + isInteger(props.index), `${prefix(id)} requires an integer index prop`, ); diff --git a/src/view/use-announcer/use-announcer.js b/src/view/use-announcer/use-announcer.js index ed571c8..e341d6c 100644 --- a/src/view/use-announcer/use-announcer.js +++ b/src/view/use-announcer/use-announcer.js @@ -4,7 +4,7 @@ import { useMemo, useCallback } from 'use-memo-one'; import type { Announce, ContextId } from '../../types'; import { warning } from '../../dev-warning'; import getBodyElement from '../get-body-element'; -import visuallyHidden from '../visually-hidden-style'; +import assignVisuallyHidden from '../assign-visually-hidden-style'; export const getId = (contextId: ContextId): string => `rbd-announcement-${contextId}`; @@ -31,7 +31,7 @@ export default function useAnnouncer(contextId: ContextId): Announce { el.setAttribute('aria-atomic', 'true'); // hide the element visually - Object.assign(el.style, visuallyHidden); + assignVisuallyHidden(el.style); // Add to body getBodyElement().appendChild(el); diff --git a/src/view/use-lift-instruction/use-lift-instruction.js b/src/view/use-lift-instruction/use-lift-instruction.js index 302cffc..0c974ea 100644 --- a/src/view/use-lift-instruction/use-lift-instruction.js +++ b/src/view/use-lift-instruction/use-lift-instruction.js @@ -25,7 +25,7 @@ export default function useLiftInstruction( // Using `display: none` prevent screen readers from reading this element in the document flow // This element is used as a `aria-labelledby` reference for *other elements* and will be read out for those - Object.assign(el.style, { display: 'none' }); + el.style.display = 'none'; // Add to body getBodyElement().appendChild(el); diff --git a/src/view/visually-hidden-style.js b/src/view/visually-hidden-style.js deleted file mode 100644 index 856279b..0000000 --- a/src/view/visually-hidden-style.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow -// https://allyjs.io/tutorials/hiding-elements.html -// Element is visually hidden but is readable by screen readers -const visuallyHidden: Object = { - position: 'absolute', - width: '1px', - height: '1px', - margin: '-1px', - border: '0', - padding: '0', - overflow: 'hidden', - clip: 'rect(0 0 0 0)', - 'clip-path': 'inset(100%)', -}; - -export default visuallyHidden; diff --git a/yarn.lock b/yarn.lock index 152f168..7995530 100644 --- a/yarn.lock +++ b/yarn.lock @@ -992,14 +992,6 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-typescript" "^7.6.0" -"@babel/runtime-corejs2@^7.6.3": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.6.3.tgz#de3f446b3fb688b98cbd220474d1a7cad909bcb8" - integrity sha512-nuA2o+rgX2+PrNTZ063ehncVcg7sn+tU71BB81SaWRVUbGwCOlb0+yQA1e0QqmzOfRSYOxfvf8cosYqFbJEiwQ== - dependencies: - core-js "^2.6.5" - regenerator-runtime "^0.13.2" - "@babel/runtime@7.3.4": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83" @@ -1021,6 +1013,13 @@ dependencies: regenerator-runtime "^0.13.2" +"@babel/runtime@^7.6.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.3.tgz#0811944f73a6c926bb2ad35e918dcc1bfab279f1" + integrity sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/template@^7.1.0", "@babel/template@^7.4.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0": version "7.6.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" @@ -4048,7 +4047,7 @@ core-js@^1.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.4.0, core-js@^2.4.1, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.4.1: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== @@ -5063,6 +5062,11 @@ eslint-plugin-emotion@^10.0.14: resolved "https://registry.yarnpkg.com/eslint-plugin-emotion/-/eslint-plugin-emotion-10.0.14.tgz#c643ff2f34f85ae77a65b2056915e939cf7e8129" integrity sha512-kI0hTPA5oo7MAc2YcdF1JcT36TZ1Ci0S5sbA9aojZ3leEPyCH34YBB76/8NQ3/9gybqrekIEuEhr8MP6JZf95Q== +eslint-plugin-es5@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es5/-/eslint-plugin-es5-1.4.1.tgz#258fe89bc5f72fbd9f5f7936c840151766821f1e" + integrity sha512-kktkmkF2O7pnSZYgrMiYMbt3wCKRIiXePwILv8USDG95YgP0PzhIxSIROLLKmiQQ/Z6LuhDGWTHK04gnbXBvkg== + eslint-plugin-flowtype@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.3.0.tgz#06d0837ac341caf369e7e6dbb112dd7fd21acf17"