diff --git a/.circleci/config.yml b/.circleci/config.yml index 48a782c848..f42305cae6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -133,6 +133,31 @@ jobs: path: cypress/videos - store_artifacts: path: cypress/screenshots + test-a11y: + docker: + - image: circleci/node:10.15.3-browsers + working_directory: ~/repo + steps: + - checkout + + - restore_cache: + keys: + - v7-dependencies-{{ checksum "yarn.lock" }} + + # PR's from forks cannot use the dependency cache for performance reasons + - run: + name: 'Forked PR dependency install' + command: yarn + + - run: + name: Accessibility Audit + command: node browser-test-harness.js yarn test:accessibility + + - store_artifacts: + path: test-reports/lighthouse + + - store_test_results: + path: test-reports/lighthouse workflows: version: 2 build: @@ -150,3 +175,6 @@ workflows: - test-browser: requires: - install + - test-a11y: + requires: + - install diff --git a/.eslintrc.js b/.eslintrc.js index 92632eb9d0..b5eadaf5ba 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -82,6 +82,13 @@ module.exports = { message: 'Must use `useLayoutEffect` as the name of the import from `*use-isomorphic-layout-effect` to leverage `eslint-plugin-react-hooks`', }, + + // No Array.from as it pulls in a large amount of babel helpers + { + selector: 'MemberExpression[object.name="Array"][property.name="from"]', + message: + 'Not allowing using of Array.from to save kbs. Please use native-with-fallback/from', + }, ], // Allowing Math.pow rather than forcing `**` @@ -162,6 +169,6 @@ module.exports = { // Enforce rules of hooks 'react-hooks/rules-of-hooks': 'error', // Second argument to hook functions - 'react-hooks/exhaustive-deps': 'warn', + 'react-hooks/exhaustive-deps': 'error', }, }; diff --git a/.flowconfig b/.flowconfig index 43eb1b40c9..403588d582 100644 --- a/.flowconfig +++ b/.flowconfig @@ -15,4 +15,4 @@ suppress_comment= \\(.\\|\n\\)*\\$ExpectError include_warnings=true # Fixing issue with CircleCI where flow would hang # I suspect this is caused by incorrect advertisement of virtual cores -server.max_workers=1 +# server.max_workers=1 diff --git a/.size-snapshot.json b/.size-snapshot.json index b7cac82f6e..f684a04a8b 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -1,25 +1,25 @@ { "dist/react-beautiful-dnd.js": { - "bundled": 392081, - "minified": 147079, - "gzipped": 41340 + "bundled": 367592, + "minified": 138436, + "gzipped": 41559 }, "dist/react-beautiful-dnd.min.js": { - "bundled": 323864, - "minified": 116189, - "gzipped": 33372 + "bundled": 316103, + "minified": 114634, + "gzipped": 34002 }, "dist/react-beautiful-dnd.esm.js": { - "bundled": 238384, - "minified": 123773, - "gzipped": 31477, + "bundled": 239478, + "minified": 124359, + "gzipped": 32332, "treeshaked": { "rollup": { - "code": 29975, - "import_statements": 793 + "code": 20714, + "import_statements": 818 }, "webpack": { - "code": 33907 + "code": 23865 } } } diff --git a/.storybook/.babelrc b/.storybook/.babelrc index 309c47e728..c019ede44a 100644 --- a/.storybook/.babelrc +++ b/.storybook/.babelrc @@ -2,9 +2,11 @@ "presets": [ "@babel/react", "@babel/flow", - ["@babel/env", { "modules": false, "loose": true }] + ["@babel/env", { "modules": false, "loose": true }], + "@emotion/babel-preset-css-prop" ], "plugins": [ + "emotion", ["@babel/proposal-class-properties", { "loose": true }], ["@babel/proposal-object-rest-spread", { "loose": true }] ], diff --git a/.storybook/decorator/global-styles.jsx b/.storybook/decorator/global-styles.jsx index 2f3a661320..401d05b98f 100644 --- a/.storybook/decorator/global-styles.jsx +++ b/.storybook/decorator/global-styles.jsx @@ -5,7 +5,6 @@ import { colors } from '@atlaskit/theme'; import { grid } from '../../stories/src/constants'; const GlobalStyles = styled.div` - background-color: ${colors.N0}; min-height: 100vh; color: ${colors.N900}; `; diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html new file mode 100644 index 0000000000..33e32d5582 --- /dev/null +++ b/.storybook/preview-head.html @@ -0,0 +1,9 @@ + + diff --git a/README.md b/README.md index c711ad0f61..c3ddcf3e6b 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,8 @@ We have created [a free course on `egghead.io` ๐Ÿฅš](https://egghead.io/courses/ - Compatible with semantic `` reordering - [table pattern](/docs/patterns/tables.md) - [Auto scrolling](/docs/guides/auto-scrolling.md) - automatically scroll containers and the window as required during a drag (even with keyboard ๐Ÿ”ฅ) - Custom drag handles - you can drag a whole item by just a part of it -- Compatible with [`ReactDOM.createPortal`](https://reactjs.org/docs/portals.html) - [portal pattern](/docs/patterns/using-a-portal.md) +- Able to drag a [clone](TODO) or use a [portal](/docs/patterns/using-a-portal.md) +- Full [programmatic api ๐ŸŽฎ](/docs/api/programmatic.md) - ๐ŸŒฒ Tree support through the [`@atlaskit/tree`](https://atlaskit.atlassian.com/packages/core/tree) package - A `` list can be a scroll container (without a scrollable parent) or be the child of a scroll container (that also does not have a scrollable parent) - Independent nested lists - a list can be a child of another list, but you cannot drag items from the parent list into a child list @@ -85,6 +86,7 @@ There are a lot of libraries out there that allow for drag and drop interactions - [Mouse dragging ๐Ÿญ](/docs/sensors/mouse.md) - [Touch dragging ๐Ÿ‘‰๐Ÿ“ฑ](/docs/sensors/touch.md) - [Keyboard dragging ๐ŸŽนโ™ฟ๏ธ](/docs/sensors/keyboard.md) +- [Programmatic dragging ๐ŸŽฎ](/docs/sensors/programmatic.md) ### API ๐Ÿ‹๏ธโ€ diff --git a/a11y-audit-parse.js b/a11y-audit-parse.js new file mode 100644 index 0000000000..346cb2a71c --- /dev/null +++ b/a11y-audit-parse.js @@ -0,0 +1,23 @@ +try { + const a11yReport = require('./test-reports/lighthouse/a11y.report.json'); + const a11yScore = a11yReport.categories.accessibility.score; + const a11yScoreFormatted = `${a11yScore ? a11yScore * 100 : 0}%`; + + console.log('*************************'); + console.log('a11y score: ', a11yScoreFormatted); + console.log('*************************'); + + if (a11yScore === 1) { + // success! + process.exit(0); + } else { + // fail build + console.log( + '\nNOTE: Lighthouse accessibility audit score must be 100% to pass this build step.\n\n', + ); + process.exit(1); + } +} catch (e) { + console.error(e); + process.exit(1); +} diff --git a/babel.config.js b/babel.config.js index 8e9193cdcd..050fc64e40 100644 --- a/babel.config.js +++ b/babel.config.js @@ -2,7 +2,6 @@ module.exports = { presets: ['@babel/react', '@babel/flow', ['@babel/env', { loose: true }]], plugins: [ ['@babel/proposal-class-properties', { loose: true }], - 'emotion', // used for stripping out the `invariant` messages in production builds 'dev-expression', ], diff --git a/cypress/integration/focus.spec.js b/cypress/integration/focus.spec.js new file mode 100644 index 0000000000..cf3bd25dc4 --- /dev/null +++ b/cypress/integration/focus.spec.js @@ -0,0 +1,148 @@ +// @flow +import * as keyCodes from '../../src/view/key-codes'; +import { getHandleSelector, getDraggableSelector } from './util'; + +beforeEach(() => { + cy.visit('/iframe.html?id=board--dragging-a-clone'); +}); + +it('should not steal focus if not already focused when lifting', () => { + // focusing on another handle + cy.get(getHandleSelector('1')).focus(); + cy.focused().should('contain', 'id:1'); + + cy.get(getHandleSelector('2')) + .as('id:2') + .trigger('mousedown', { button: 0 }) + .trigger('mousemove', { + button: 0, + clientX: 200, + clientY: 300, + force: true, + }); + + // asserting id:2 is now dragging + cy.get(getHandleSelector('2')).should( + 'have.attr', + 'data-is-dragging', + 'true', + ); + + // focus not stolen + cy.focused().should('contain', 'id:1'); + + cy.get(getHandleSelector('2')) + .trigger('mouseup', { force: true }) + // clone will be unmounting during drop + .should('not.exist'); + + // getting post clone handle + cy.get(getHandleSelector('2')).should( + 'have.attr', + 'data-is-dragging', + 'false', + ); + + // focus not stolen + cy.focused().should('contain', 'id:1'); +}); + +it('should maintain focus if dragging a clone', () => { + // focusing on another handle + cy.get(getHandleSelector('2')).focus(); + cy.focused().should('contain', 'id:2'); + + cy.get(getHandleSelector('2')).trigger('keydown', { + keyCode: keyCodes.space, + }); + + // asserting id:2 is now dragging + cy.get(getHandleSelector('2')).should( + 'have.attr', + 'data-is-dragging', + 'true', + ); + + // focus maintained + cy.focused().should('contain', 'id:2'); + + cy.get(getHandleSelector('2')) + .trigger('keydown', { keyCode: keyCodes.arrowRight, force: true }) + .trigger('keydown', { keyCode: keyCodes.space, force: true }) + // clone will be unmounting during drop + .should('not.exist'); + + // getting post clone handle + cy.get(getHandleSelector('2')) + // no longer dragging + .should('have.attr', 'data-is-dragging', 'false') + // is in the second column (normally would loose focus moving between lists) + .closest(getDraggableSelector('BMO')); + + // focus maintained + cy.focused().should('contain', 'id:2'); +}); + +it('should give focus to a combine target', () => { + cy.visit('/iframe.html?id=board--with-combining-and-cloning'); + cy.get(getHandleSelector('2')).focus(); + cy.focused().should('contain', 'id:2'); + + cy.get(getHandleSelector('2')).trigger('keydown', { + keyCode: keyCodes.space, + }); + + // asserting id:2 is now dragging + cy.get(getHandleSelector('2')).should( + 'have.attr', + 'data-is-dragging', + 'true', + ); + + // focus maintained + cy.focused().should('contain', 'id:2'); + + cy.get(getHandleSelector('2')) + .trigger('keydown', { keyCode: keyCodes.arrowRight, force: true }) + // combining with item:1 + .trigger('keydown', { keyCode: keyCodes.arrowUp, force: true }) + // dropping + .trigger('keydown', { keyCode: keyCodes.space, force: true }) + // clone will be unmounting during drop + .should('not.exist'); + + // focus giving to item:1 the combine target + cy.focused().should('contain', 'id:1'); +}); + +it('should not give focus to a combine target if source did not have focus at start of drag', () => { + cy.visit('/iframe.html?id=board--with-combining-and-cloning'); + // focusing on something unrelated to the drag + cy.get(getHandleSelector('3')).focus(); + + cy.get(getHandleSelector('2')).trigger('keydown', { + keyCode: keyCodes.space, + }); + + // asserting id:2 is now dragging + cy.get(getHandleSelector('2')).should( + 'have.attr', + 'data-is-dragging', + 'true', + ); + + // focus not stolen + cy.focused().should('contain', 'id:3'); + + cy.get(getHandleSelector('2')) + .trigger('keydown', { keyCode: keyCodes.arrowRight, force: true }) + // combining with item:1 + .trigger('keydown', { keyCode: keyCodes.arrowUp, force: true }) + // dropping + .trigger('keydown', { keyCode: keyCodes.space, force: true }) + // clone will be unmounting during drop + .should('not.exist'); + + // focus not given to the combine target + cy.focused().should('contain', 'id:3'); +}); diff --git a/cypress/integration/move-between-lists.spec.js b/cypress/integration/move-between-lists.spec.js index 9571355359..d3e37b5029 100644 --- a/cypress/integration/move-between-lists.spec.js +++ b/cypress/integration/move-between-lists.spec.js @@ -1,6 +1,7 @@ // @flow import * as keyCodes from '../../src/view/key-codes'; import { timings } from '../../src/animation'; +import { getDroppableSelector, getHandleSelector } from './util'; beforeEach(() => { cy.visit('/iframe.html?id=board--simple'); @@ -8,19 +9,19 @@ beforeEach(() => { it('should move between lists', () => { // first list has item with id:2 - cy.get('[data-react-beautiful-dnd-droppable]') + cy.get(getDroppableSelector()) .eq(1) .as('first-list') .should('contain', 'id:2'); // second list does not have item with id:2 - cy.get('[data-react-beautiful-dnd-droppable]') + cy.get(getDroppableSelector()) .eq(2) .as('second-list') .should('not.contain', 'id:2'); cy.get('@first-list') - .find('[data-react-beautiful-dnd-drag-handle]') + .find(getHandleSelector()) .first() .should('contain', 'id:2') .focus() diff --git a/cypress/integration/reorder-lists.spec.js b/cypress/integration/reorder-lists.spec.js index bfe2017fd0..722b82f7e1 100644 --- a/cypress/integration/reorder-lists.spec.js +++ b/cypress/integration/reorder-lists.spec.js @@ -1,6 +1,7 @@ // @flow import * as keyCodes from '../../src/view/key-codes'; import { timings } from '../../src/animation'; +import { getHandleSelector } from './util'; beforeEach(() => { cy.visit('/iframe.html?id=board--simple'); @@ -11,15 +12,15 @@ it('should reorder lists', () => { cy.get('h4') .eq(0) .as('first') - .should('have.text', 'Jake'); + .should('contain', 'Jake'); cy.get('h4') .eq(1) - .should('have.text', 'BMO'); + .should('contain', 'BMO'); // reorder operation cy.get('@first') - .closest('[data-react-beautiful-dnd-drag-handle]') + .closest(getHandleSelector()) .focus() .trigger('keydown', { keyCode: keyCodes.space }) .trigger('keydown', { keyCode: keyCodes.arrowRight, force: true }) @@ -31,10 +32,10 @@ it('should reorder lists', () => { // note: not using get aliases as they where returning incorrect results cy.get('h4') .eq(0) - .should('have.text', 'BMO'); + .should('contain', 'BMO'); // index of the drag handle has changed cy.get('h4') .eq(1) - .should('have.text', 'Jake'); + .should('contain', 'Jake'); }); diff --git a/cypress/integration/reorder.spec.js b/cypress/integration/reorder.spec.js index 6e3f7dba4d..f18cc7fb9a 100644 --- a/cypress/integration/reorder.spec.js +++ b/cypress/integration/reorder.spec.js @@ -1,18 +1,19 @@ // @flow import * as keyCodes from '../../src/view/key-codes'; import { timings } from '../../src/animation'; +import { getHandleSelector } from './util'; beforeEach(() => { cy.visit('/iframe.html?id=single-vertical-list--basic'); }); -it('should reorder a list', () => { +it('should reorder within a list', () => { // order: 1, 2 - cy.get('[data-react-beautiful-dnd-drag-handle]') + cy.get(getHandleSelector()) .eq(0) .as('first') .should('contain', 'id:1'); - cy.get('[data-react-beautiful-dnd-drag-handle]') + cy.get(getHandleSelector()) .eq(1) .should('contain', 'id:2'); @@ -20,6 +21,8 @@ it('should reorder a list', () => { cy.get('@first') .focus() .trigger('keydown', { keyCode: keyCodes.space }) + // need to re-query for a clone + .get('@first') .trigger('keydown', { keyCode: keyCodes.arrowDown, force: true }) // finishing before the movement time is fine - but this looks nice .wait(timings.outOfTheWay * 1000) @@ -27,11 +30,14 @@ it('should reorder a list', () => { // order now 2, 1 // note: not using get aliases as they where returning incorrect results - cy.get('[data-react-beautiful-dnd-drag-handle]') + cy.get(getHandleSelector()) .eq(0) .should('contain', 'id:2'); - cy.get('[data-react-beautiful-dnd-drag-handle]') + cy.get(getHandleSelector()) .eq(1) .should('contain', 'id:1'); + + // element should maintain focus post drag + cy.focused().should('contain', 'id:1'); }); diff --git a/cypress/integration/util.js b/cypress/integration/util.js new file mode 100644 index 0000000000..3f4e9e8d54 --- /dev/null +++ b/cypress/integration/util.js @@ -0,0 +1,23 @@ +// @flow +import * as dataAttr from '../../src/view/data-attributes'; + +export function getDroppableSelector(droppableId?: string) { + if (droppableId) { + return `[${dataAttr.droppable.id}="${droppableId}"]`; + } + return `[${dataAttr.droppable.id}]`; +} + +export function getHandleSelector(draggableId?: string) { + if (draggableId) { + return `[${dataAttr.dragHandle.draggableId}="${draggableId}"]`; + } + return `[${dataAttr.dragHandle.draggableId}]`; +} + +export function getDraggableSelector(draggableId?: string) { + if (draggableId) { + return `[${dataAttr.draggable.id}="${draggableId}"]`; + } + return `[${dataAttr.draggable.id}]`; +} diff --git a/docs/about/accessibility.md b/docs/about/accessibility.md index 52c08499cc..0f2199ce7a 100644 --- a/docs/about/accessibility.md +++ b/docs/about/accessibility.md @@ -9,9 +9,7 @@ Traditionally drag and drop interactions have been exclusively a mouse or touch - Keyboard [auto scrolling](/docs/guides/auto-scrolling.md) - Fantastic [screen reader support](/docs/guides/screen-reader.md) - _We ship with english messaging out of the box ๐Ÿ“ฆ_ - Correct use of `aria-*` attributes for [lift announcements](/docs/guides/screen-reader.md) -- Ensure a dragging item maintains focus if started dragging with focus - [more info](/docs/api/draggable.md) -- Ensure a dragging item maintains focus when dropping into a new list to allow drags to be chained together - [more info](/docs/api/draggable.md) -- Ensure a dragging item maintains focus moving into a [portal](/docs/patterns/using-a-portal.md) +- Smart management of focus - [more info](/docs/guides/focus.md) ![screen-reader-text](https://user-images.githubusercontent.com/2182637/36571009-d326d82a-1888-11e8-9a1d-e44f8b969c2f.gif) diff --git a/docs/api/draggable.md b/docs/api/draggable.md index b75de9b42d..7d30d880a6 100644 --- a/docs/api/draggable.md +++ b/docs/api/draggable.md @@ -217,14 +217,9 @@ If the user force presses on the element before they have moved the element (eve Any force press action will cancel an existing or pending drag -#### Focus retention when moving between lists +#### Focus retention -When moving a `` from one list to another the default browser behaviour is for the _drag handle_ element to lose focus. This is because the old element is being destroyed and a new one is being created. The loss of focus is not good when dragging with a keyboard as the user is then unable to continue to interact with the element. To improve this user experience we automatically give a _drag handle_ focus when: - -- It was unmounted at the end of a drag -- It had focus -- It is enabled when mounted -- No other elements have gained browser focus before the drag handle has mounted +See [/docs/guides/focus.md] #### Extending `DraggableProps.style` @@ -311,14 +306,19 @@ It is an assumption that ``s are _visible siblings_ of one another. ```js type DragHandleProps = {| - onFocus: () => void, - onBlur: () => void, - onMouseDown: (event: MouseEvent) => void, - onKeyDown: (event: KeyboardEvent) => void, - onTouchStart: (event: TouchEvent) => void, - 'data-react-beautiful-dnd-drag-handle': string, - 'aria-roledescription': string, + // what draggable the handle belongs to + 'data-rbd-drag-handle-draggable-id': DraggableId, + + // What DragDropContext the drag handle is in + 'data-rbd-drag-handle-context-id': ContextId, + + // Id of hidden element that contains the lift instruction (nicer screen reader text) + 'aria-labelledby': ElementId, + + // Allow tabbing to this element tabIndex: number, + + // Stop html5 drag and drop draggable: boolean, onDragStart: (event: DragEvent) => void, |}; @@ -355,42 +355,6 @@ Controlling a whole draggable by just a part of it ``` -#### `dragHandleProps` monkey patching - -You can override some of the `dragHandleProps` props with your own behavior if you need to. - -```js -const myOnMouseDown = event => console.log('mouse down on', event.target); - - - {(provided, snapshot) => { - const onMouseDown = (() => { - // dragHandleProps might be null - if (!provided.dragHandleProps) { - return onMouseDown; - } - - // creating a new onMouseDown function that calls myOnMouseDown as well as the drag handle one. - return event => { - provided.dragHandleProps.onMouseDown(event); - myOnMouseDown(event); - }; - })(); - - return ( -
- Drag me! -
- ); - }} -
; -``` - ### 2. Snapshot: (DraggableStateSnapshot) ```js diff --git a/docs/guides/dragging-svgs.md b/docs/guides/dragging-svgs.md index 955dbb17bd..8943dcae7f 100644 --- a/docs/guides/dragging-svgs.md +++ b/docs/guides/dragging-svgs.md @@ -8,11 +8,9 @@ We require that a `` and its drag handle be a `HTMLElement`. Almost ![HTMLElement](https://user-images.githubusercontent.com/2182637/42302315-9150d4e0-805d-11e8-8345-71bc32135203.png) -## Using focus +## Focus management -We use and manipulate focus on a drag handle during a drag if it is needed. This is especially true for keyboard dragging that relies on focus management. - -An element loses focus when it moves into a [`React Portal`](https://reactjs.org/docs/portals.html). We can detect when a `` is moving into a portal and we give the new element in the portal focus with `.focus()`. Additionally, we also will maintain focus when you move a `` from one list to another using `.focus()` if it had focus when dragging. An element will always have focus when keyboard dragging. +We use and manipulate focus on a drag handle during a drag if it is needed. This is especially true for keyboard dragging that relies on focus management. See our [focus guide](/docs/guides/focus.md). ## Enter [`SVGElement`](https://developer.mozilla.org/en-US/docs/Web/API/SVGElement) ๐Ÿ–ผ diff --git a/docs/guides/focus.md b/docs/guides/focus.md new file mode 100644 index 0000000000..dd911950df --- /dev/null +++ b/docs/guides/focus.md @@ -0,0 +1,23 @@ +# Focus + +> "You got to focus on what's real, man" - [Jake from Adventure time](https://www.youtube.com/watch?v=TFGz6Qvg1CE) + +`react-beautiful-dnd` includes logic to maintain browser focus for _drag handles_. This especially important for [keyboard dragging](/docs/sensors/keyboard.md) which requires the dragging item to be focused. + +## Terminology reminder ๐Ÿ“– + +A `` has a _drag handle_. A _drag handle_ is the part of the `` that controls the dragging of the whole ``. A _drag handle_ can be the same element as the `` + +## Drag handle not focused at drag start + +If the _drag handle_ is not focused when a drag starts then **focus is not given** to the dragging item. This is a mirror of the native HTML5 drag and drop behaviour which does not give focus to an item just because it is dragging. You are welcome to call `HTMLElement.focus()` when a drag starts to give it focus, but that is up to you. + +## Drag handle is focused at drag start + +If a _drag handle_ has browser focus when a drag starts then `rbd` will try to give focus to the _drag handle_ during a drag and just after a drag ends. + +Here is what is done: + +- Give focus to a _drag handle_ with a matching `DraggableId` after the drag starts. This might be a different element to the original _drag handle_ if you are using a [portal](TODO) or a [clone](TODO). +- Give focus to a _drag handle_ with a matching `DraggableId` after the drag ends. Sometimes the original _drag handle_ element is lost during a drag, such as when using a [portal](TODO) or a [clone](TODO), or when moving a `Draggable` from one list to another as `React` will recreate the element. +- If [combining](TODO) then focus is given to the combine target after a drag ends. This allows keyboard users to continue to engage with the application without needing to get the focus back to where they where the last interaction was diff --git a/docs/guides/how-we-use-dom-events.md b/docs/guides/how-we-use-dom-events.md index 808aff6a5a..d908bea09c 100644 --- a/docs/guides/how-we-use-dom-events.md +++ b/docs/guides/how-we-use-dom-events.md @@ -17,11 +17,7 @@ Without needing going into all the details below, here are the safest event hand > These can be added on the _drag handle_, anywhere else higher on the tree or to the window directly. - `onClick`: the `event.defaultPrevented` property will be set to `true` if occurred as a part of the drag interaction. This is true even if the drag was not finished with a pre-click action such as `mouseup` or `touchend`. See [sloppy clicks and click prevention](/docs/sensors/mouse.md#sloppy-clicks-and-click-prevention-). -- `onKeyDown`: the `event.defaultPrevented` property will be set to `true` if it was used as a part of a drag. If you add `onKeyDown` to the _drag handle_ you will need to monkey patch the [`DragHandleProps`](/docs/api/draggable.md) `onKeyDown` event handler. - -You may need to enchance the logic of your event handlers with information from [`onDragStart`](/docs/guides/responders.md) and [`onDragEnd`](/docs/guides/responders.md) to know about whether a drag is occuring while those events fire. - -You are welcome to add other event handlers but you may be more reliant on `onDragStart` and `onDragEnd` information. +- `onKeyDown`: the `event.defaultPrevented` property will be set to `true` if it was used as a part of a drag. ## General rules @@ -32,7 +28,7 @@ When we use an input event as part of a drag and drop interaction we generally c - we use: `event.preventDefault()` - we do not use: `event.stopPropagation()` -Some event handlers we add on the _drag handle_ itself (see [`DragHandleProps`](https://github.com/atlassian/react-beautiful-dnd#draghandleprops-type-information)) and others we add to the `window` in the [capture phase](https://javascript.info/bubbling-and-capturing#capturing). What this means is as long as you are applying your events handlers in the [bubbling phase](https://javascript.info/bubbling-and-capturing#bubbling) (which is the default for event handlers) then behaviour of events will be as described on this page. +We add all event handlers to the `window` in the [capture phase](https://javascript.info/bubbling-and-capturing#capturing). What this means is as long as you are applying your events handlers in the [bubbling phase](https://javascript.info/bubbling-and-capturing#bubbling) (which is the default for event handlers) then behaviour of events will be as described on this page. In order to know if we have already used the event for the purpose of drag and drop you need to check the [`event.defaultPrevented`](https://developer.mozilla.org/en-US/docs/Web/API/Event/defaultPrevented) property. @@ -51,7 +47,7 @@ window.addEventListener('click', (event: MouseEvent) => { ### Direct and indirect actions -Some user events have a direct impact on a drag: such as a `mousemove` when dragging with a mouse or the **up arrow** โ†‘ `keydown` event while dragging with a keyboard. These direct events will have `event.preventDefault()` called on them to prevent their default browser behaviours. Some events indirectly impact a drag such as a `resize` event which cancels a drag. For events that indirectly impact a drag we do not call `event.preventDefault()` on them. Generally indirect events that impact drag are events that cancel a drag such as `resize` or `orientationchange` events. +Some user events have a direct impact on a drag: such as a `mousemove` when dragging with a mouse or the **up arrow** โ†‘ `keydown` event while dragging with a keyboard. These direct events will have `event.preventDefault()` called on them to prevent their default browser behaviours. Some events indirectly impact a drag such as a `resize` event which cancels a drag. For events that indirectly impact a drag we do not call `event.preventDefault()` on them. Generally indirect events that impact drag are events that cancel a drag such as `resize` and `orientationchange` events. ## Mouse dragging ๐Ÿญ diff --git a/docs/guides/screen-reader.md b/docs/guides/screen-reader.md index 918f8af7f2..19fc6ba536 100644 --- a/docs/guides/screen-reader.md +++ b/docs/guides/screen-reader.md @@ -43,19 +43,24 @@ All of our built in screen reader messages use `id`'s to identify ` ### Step 1: Introduce draggable item -When a user `tabs` to a ``, we need to tell them how to start a drag. We do this by using the `aria-roledescription` property on a _drag handle_. +When a user `tabs` to a _drag handle_, we need to tell them how to start a drag. We do this by using the `liftInstruction` property on a ``. All _drag handles_ share the same lift announcement message. -**Default message**: "Draggable item. Press space bar to lift" +**Default message**: "Draggable item. Ensure your screen reader is not in browse mode and then press spacebar to lift." We tell the user the following: - The item is draggable +- To disable _browse mode_ - How to start a drag You don't need to give all the drag movement instructions at this point, let's wait until the user decides to start a drag. Think about substituting the word "item" for a noun that matches your problem domain, for example, "task" or "issue". You might also want to drop the word "item" altogether. +#### Disabling browse mode + +Screen readers can run in [various modes](https://www.accessibility-developer-guide.com/knowledge/desktop-screen-readers/browse-focus-modes/). In order for the keyboard shortcuts to work correctly the user needs to leave the _browse mode_ as it remaps a lot of keyboard shortcuts. Alternatively you could use `aria-role="application"` on the `` element, but this can wreck the standard screen reader usage of your page. + ### Step 2: Start drag When a user lifts a `` by using the `spacebar` we want to tell them a number of things. diff --git a/docs/patterns/multi-drag.md b/docs/patterns/multi-drag.md index c5c16b9f2d..08ab5c82e3 100644 --- a/docs/patterns/multi-drag.md +++ b/docs/patterns/multi-drag.md @@ -16,9 +16,9 @@ We have decided on a simple, but very flexible and scalable multi drag pattern t We can break the user experience down in three phases. -1. [**Selection**](#selection): The user selects one or more items. -2. [**Dragging**](#dragging): The user drags one item as a representation of the whole group. -3. [**Dropping**](#dropping): The user drops an item into a new location. We move all of the selected items into the new location +1. [**Selection**](#selection): The user selects one or more items. +2. [**Dragging**](#dragging): The user drags one item as a representation of the whole group. +3. [**Dropping**](#dropping): The user drops an item into a new location. We move all of the selected items into the new location ## Announcements @@ -47,9 +47,9 @@ If a user clicks on an item the selected state of the item should be toggled. Ad #### Keyboard event handler - When the user presses **enter** โŽ toggle the selection of the item -- **Option 1**: Attach an `onKeyDown` handler to your _drag handle_ or ``. You will need to monkey patch the `DragHandleProvided > onKeyDown` keyboard handler. -- **Option 2**: Attach an `onKeyUp` handler to your _drag handle_. Then you will not need to monkey patch the `onKeyDown` handler. However, `keyup` events will not have their default action prevented so you will not be able to check `event.defaultPrevented` to see if the keypress was used for a drag. If you are only using the **enter** โŽ key in your event handler then you should be fine as that is not used as a part of dragging. -- Prevent the default action on the `keydown` / `keyup` event if you are toggling selection as you are using it for selection as you want to opt out of the standard browser behaviour and also provide a clue that this event has been used. +- **Option 1**: Attach an `onKeyDown` handler to your _drag handle_ or `` +- **Option 2**: Attach an `onKeyUp` handler to your _drag handle_. `keyup` events will not have their default action prevented so you will not be able to check `event.defaultPrevented` to see if the keypress was used for a drag. If you are only using the **enter** โŽ key in your event handler then you should be fine as that is not used as a part of dragging. +- Prevent the default action on the `keydown` / `keyup` event if you are toggling selection as you are using it for selection and you want to opt out of the standard browser behaviour - and also provide a clue that this event has been used. #### Toggle selection behaviour @@ -110,16 +110,8 @@ Here is an example of composing the above event handling logic in a component ```js class Task extends Component { - onKeyDown = ( - event: KeyboardEvent, - // we will be monkey patching this - provided: DraggableProvided, - snapshot: DraggableStateSnapshot, - ) => { - if (provided.dragHandleProps) { - provided.dragHandleProps.onKeyDown(event); - } - + onKeyDown = (event: KeyboardEvent, snapshot: DraggableStateSnapshot) => { + // already used if (event.defaultPrevented) { return; } @@ -195,7 +187,7 @@ class Task extends Component { {...provided.dragHandleProps} onClick={this.onClick} onKeyDown={(event: KeyboardEvent) => - this.onKeyDown(event, provided, snapshot) + this.onKeyDown(event, snapshot) } > {task.content} diff --git a/docs/sensors/programmatic.md b/docs/sensors/programmatic.md new file mode 100644 index 0000000000..a944668b8e --- /dev/null +++ b/docs/sensors/programmatic.md @@ -0,0 +1,279 @@ +# Programmatic dragging ๐ŸŽฎ + +![programmatic api logo](https://user-images.githubusercontent.com/2182637/60233733-ec8ade00-98e4-11e9-88b2-6fe407cf6bcb.jpg) + +It is possible to drive an entire drag and drop experience programmatically ๐Ÿ˜ฑ + +You can use the programmatic API to: + +- Create drag and drop interactions from **any input** type you can think of +- Create beautiful scripted **experiences** + +The programmatic API is the same API that our [mouse](/docs/sensors/mouse.md), [keyboard](/docs/sensors/keyboard.md), and [touch](/docs/sensors/touch.md) sensors use. So it is powerful enough to drive any experience we ship out of the box. + +## Overview + +You create a `sensor` that has the ability to attempt to claim a **lock**. A **lock** allows _exclusive_ control of dragging within a ``. When you are finished with your interaction, you can then release the **lock**. + +```js +function mySimpleSensor(api: SensorAPI) { + const preDrag: ?PreDragActions = api.tryGetLock('item-1'); + // Could not get lock + if (!preDrag) { + return; + } + + const drag: SnapDragActions = preDrag.snapLift(); + + drag.moveDown(); + drag.moveDown(); + drag.moveDown(); + + drag.drop(); +} + +function App() { + return ( + {/*...*/} + ); +} +``` + +## Lifecycle + +![programmatic state flow](https://user-images.githubusercontent.com/2182637/58779115-35b67d80-8618-11e9-8934-6dfa2b14ce23.jpg) + +1. Try to get a **lock** when a `sensor` wants to drag and item. A sensor might not be able to claim a lock for a variety of reasons, such as when another `sensor` already has a **lock**. +2. If a **lock** is obtained then there are a number of _pre drag_ actions available to you (`PreDragActions`). This allows a `sensor` to claim a lock before starting a drag. This is important for things like [sloppy click detection](TODO) where a drag is only started after a sufficiently large movement. +3. A _pre drag_ lock can be upgraded to a _drag lock_, which contains a different set of APIs (`FluidDragActions` or `SnapDragActions`). Once a `` has been lifted, it can be moved around. + +## Rules + +- Only one `` can be dragging at a time for a `` +- You cannot use outdated or aborted **locks** (see below) +- That's it! + +## API + +### Creating a `sensor` + +A `sensor` is a [React hook](https://reactjs.org/docs/hooks-intro.html). It is fine if you do not want to use any of the React hook goodness, you can treat the `sensor` just as a function. React hooks are just functions that let you use the built in React hooks if you want to ๐Ÿคซ. You pass your `sensor` into the `sensors` array on a ``. + +```js +function useMyCoolSensor(api: SensorAPI) { + const start = useCallback(function start(event: MouseEvent) { + const preDrag: ?PreDragActions = api.tryGetLock('item-2'); + if (!preDrag) { + return; + } + preDrag.snapLift(); + preDrag.moveDown(); + preDrag.drop(); + }, []); + + useEffect(() => { + window.addEventListener('click', start); + + return () => { + window.removeEventListener('click', start); + }; + }, []); +} + +function App() { + return ( + + + + ); +} +``` + +You can also disable all of the prebuilt sensors ([mouse](/docs/sensors/mouse.md), [keyboard](/docs/sensors/keyboard.md), and [touch](/docs/sensors/touch.md)) by setting `enableDefaultSensors={false}` on a ``. This is useful if you _only_ want a `` to be controlled programmatically. + +### Controlling a drag: try to get a lock + +A `sensor` is provided with a an object (`SensorAPI`) which is used to try to get a **lock** + +```js +export type SensorAPI = {| + tryGetLock: TryGetLock, + canGetLock: (id: DraggableId) => boolean, + isLockClaimed: () => boolean, + tryReleaseLock: () => void, + findClosestDraggableId: (event: Event) => ?DraggableId, + findOptionsForDraggable: (id: DraggableId) => ?DraggableOptions, +|}; + +export type DraggableOptions = {| + canDragInteractiveElements: boolean, + shouldRespectForcePress: boolean, + isEnabled: boolean, +|}; +``` + +- `tryGetLock` (`TryGetLock`): a function that is used to **try** and get a **lock** for a `` +- `canGetLock(id)`: returns whether a lock _could_ be claimed for a given `DraggableId` +- `isLockClaimed()`: returns `true` if any sensor currently has a lock +- `tryReleaseLock()`: will release any active lock. This can be useful for programmatically cancelling a drag. +- `findClosestDraggableId(event)`: a function that will try to find the closest `draggableId` based on an event. It will look upwards from the `event.target` to try and find a _drag handle_ +- `findOptionsForDraggable(id)`: tries to lookup `DraggableOptions` associated with a `` + +```js +export type TryGetLock = ( + draggableId: DraggableId, + forceStop?: () => void, + options?: TryGetLockOptions, +) => ?PreDragActions; +``` + +- `draggableId`: The `DraggableId` of the `` that you want to drag. +- `forceStop` (optional): a function that is called when the lock needs to be abandoned by the application. See **force abandoning locks**. + +```js +type TryGetLockOptions = { + sourceEvent?: Event, +}; +``` + +- `sourceEvent` (optional): Used to do further validation when starting the drag from a user input event. We will do some [interactive element checking](TODO) + +### Controlling a drag: pre drag (`PreDragAction`) + +The `PreDragAction` object contains a number of functions: + +```js +type PreDragActions = {| + // discover if the lock is still active + isActive: () => boolean, + // whether it has been indicated if force press should be respected + shouldRespectForcePress: () => boolean, + // Lift the current item + fluidLift: (clientSelection: Position) => FluidDragActions, + snapLift: () => SnapDragActions, + // Cancel the pre drag without starting a drag. Releases the lock + abort: () => void, +|}; +``` + +This phase allows you to conditionally start or abort a drag after obtaining an exclusive **lock**. This is useful if you are not sure if a drag should start such as when using [long press](/docs/sensors/touch.md) or [sloppy click detection](/docs/sensors/mouse.md). If you want to abort the pre drag without lifting you can call `.abort()`. + +### Controlling a drag: dragging + +You can lift a dragging item by calling either `.fluidLift(clientSelection)` or `snapLift()`. This will start a visual drag and will also trigger the `onDragStart` responder. There are two different _lift_ functions, as there are two different dragging modes: **snap dragging** (`SnapDragActions`) and **fluid dragging** (`FluidDragActions`). + +#### Shared + +```js +type DragActions = {| + drop: (args?: StopDragOptions) => void, + cancel: (args?: StopDragOptions) => void, + isActive: () => boolean, + shouldRespectForcePress: () => boolean, +|}; + +type StopDragOptions = {| + shouldBlockNextClick: boolean, +|}; +``` + +#### Fluid dragging + +``s move around naturally in response a moving point. The _impact_ of the drag is controlled by a _collision engine_. (This is what our [mouse sensor](/docs/sensors/mouse.md) and [touch sensor](/docs/sensors/touch.md) use) + +```js +type FluidDragActions = {| + ...DragActions, + move: (clientSelection: Position) => void, +|}; +``` + +Calls to `.move()` are throttled using [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame). So if you make multipole `.move()` calls in the same animation frame, it will only result in a single update + +```js +const drag: SnapDragActions = preDrag.fluidLift({ x: 0, y: 0 }); + +// will all be batched into a single update +drag.move({ x: 0, y: 1 }); +drag.move({ x: 0, y: 2 }); +drag.move({ x: 0, y: 3 }); + +// after animation frame +// update(x: 0, y: 3) +``` + +#### Snap dragging + +``s are forced to move to a new position using a single command. For example, "move down". (This is what our [keyboard sensor](/docs/sensors/keyboard.md) uses) + +```js +export type SnapDragActions = {| + ...DragActions, + moveUp: () => void, + moveDown: () => void, + moveRight: () => void, + moveLeft: () => void, +|}; +``` + +## Force abandoning locks + +A **lock** can be aborted at any time by the application, such as when an error occurs. If you try to perform actions on an aborted **lock** then it will not do anything. The second argument to `SensorAPI.tryGetLock()` is a `forceStop` function. The `forceStop` function will be called when the **lock** needs to be abandoned by the application. If you try to use any functions on the **lock** after it has been abandoned they will have no effect and will log a warning to the console. + +```js +function useMySensor(api: SensorAPI) { + let unbindClick; + + function forceStop() { + if (unbindClick) { + unbindClick(); + } + } + + const preDrag: ?PreDragActions = api.tryGetLock('item-1', forceStop); + // Could not get lock + if (!preDrag) { + return; + } + + const drag: SnapDragActions = preDrag.snapLift(); + const move = () => drag.moveDown(); + window.addEventListener('click', move); + unbindClick = window.removeEventListener('click', move); +} +``` + +The `PreDragActions`, `FluidDragActions` and `SnapDragActions` all have a `isActive()` function which can be called to discover if a lock is still active. So if you do not want to provide a `forceStop()` function, it is best to defensively call api's with a `isActiveCheck`. + +```js +function useMySensor(api: SensorAPI) { + const preDrag: ?PreDragActions = api.tryGetLock(); + // Could not get lock + if (!preDrag) { + return; + } + + const drag: SnapDragActions = preDrag.snapLift(); + const move = () => { + if (drag.isActive()) { + drag.moveDown(); + return; + } + // unbinding if no longer active + window.removeEventListener('click', move); + }; + window.addEventListener('click', move); +} +``` + +## Invalid behaviours + +These are all caused by not respecting the lifecycle (see above) + +> โš ๏ธ = warning logged +> โŒ = error thrown + +- โš ๏ธ Using any `PreDragAction`, `FluidDragAction` or `SnapDragAction` after `forceStop()` is called +- โš ๏ธ Using any `PreDragAction` after `.abort()` has been called +- โš ๏ธ Using any `FluidDragAction` or `SnapDragAction` after `.cancel()` or `.drop()` has been called. +- โŒ Trying to call two `lift` functions on a `PreDragAction` will result in an error being thrown. diff --git a/docs/support/media.md b/docs/support/media.md index ad482f8a70..aa973c3988 100644 --- a/docs/support/media.md +++ b/docs/support/media.md @@ -19,8 +19,9 @@ This page contains a list of articles, blogs and newsletters that `react-beautif - [Dragging React performance forward](https://medium.com/@alexandereardon/dragging-react-performance-forward-688b30d40a33) - [Grabbing the flame ๐Ÿ”ฅ](https://medium.com/@alexandereardon/grabbing-the-flame-290c794fe852) -## React ecosystem +## Other +- [What does react-beautiful-dnd cost to maintain?](https://dev.to/alexandereardon/what-does-react-beautiful-dnd-cost-to-maintain-52e8) - [Deep Sea Fishing with React Hooks](https://www.youtube.com/watch?v=MVi17tk3VsI) ## Podcasts @@ -48,7 +49,9 @@ This page contains a list of articles, blogs and newsletters that `react-beautif - React Status [issue 114](https://react.statuscode.com/issues/114) - React Status [issue 129](https://react.statuscode.com/issues/129) - React Status [issue 134](https://react.statuscode.com/issues/134) +- React Status [issue 139](https://react.statuscode.com/issues/139) - Fullstack React [issue 72](http://newsletter.fullstackreact.com/issues/72) +- React Digest [issue 201](https://www.reactdigest.net/digests/201) - HashBang Weekly [issue 52](http://hashbangweekly.okgrow.com/2018/01/22/issue-52) - CSS Animation Weekly [issue 60](http://weekly.cssanimation.rocks/issues/css-animation-weekly-60-working-with-animations-skeleton-screens-and-rethinking-drag-and-drop-73446) - Codrops [collective 340](https://tympanus.net/codrops/collective/collective-340/) @@ -57,9 +60,14 @@ This page contains a list of articles, blogs and newsletters that `react-beautif - sidebar.io - [28/8/16](https://sidebar.io/?after=2017-08-21&before=2017-08-21) - Best of JS [issue 25](https://weekly.bestofjs.org/issues/25/) - BxJS Weekly [episode 59](https://dev.to/yamalight/bxjs-weekly-episode-59-javascript-news-podcast-b28) +- FASination Daily [May 21st](http://opensource.faseidl.com/#/) +- The Week of React [issue 57](http://www.theweekofreact.com/issues/fold-up-images-in-react-using-webassembly-w-react-react-europe-livestream-more-179542) +- React Digest [issue 201](https://reactdigest.net/digests/201) ## Articles, tutorials and blogs +- CSS-Tricks [tweet](https://twitter.com/css/status/1138866065965010945) +- dev.to 7 most popular DEV posts [May 27th, 2019](https://dev.to/devteam/the-7-most-popular-dev-posts-from-the-past-week-2ice) - [React Drag and Drop - Multiple Horizontal Lists](https://www.youtube.com/watch?v=RI9kA09Egas) - [Building a Drag-and-Drop Game with react-beautiful-dnd](https://able.bio/drenther/building-a-drag-and-drop-game-with-react-beautiful-dnd--094r3g8) - [Let's Create a Trello Clone with React + Redux](https://www.youtube.com/watch?v=RDQGPs7StNA) diff --git a/flow-typed/custom/cypress.js b/flow-typed/custom/cypress.js index 3af9a7ab8d..a408710844 100644 --- a/flow-typed/custom/cypress.js +++ b/flow-typed/custom/cypress.js @@ -2,4 +2,4 @@ // Currently just opting out of flow for the cy global // https://github.com/cypress-io/cypress/issues/2732 // https://github.com/flow-typed/flow-typed/pull/3028 -declare function cy(...any[]): any; +declare var cy: any; diff --git a/flow-typed/custom/raf.js b/flow-typed/custom/raf.js new file mode 100644 index 0000000000..3351c930a5 --- /dev/null +++ b/flow-typed/custom/raf.js @@ -0,0 +1,11 @@ +declare function raf(callback: (timestamp: number) => void): AnimationFrameID; + +// TODO: would like to use `import type {Stub} from 'raf-stub' +// This is not supported right now: https://github.com/flow-typed/flow-typed/issues/2023 +declare var requestAnimationFrame: { + add: (cb: Function) => number, + remove: (id: number) => void, + flush: (duration?: number) => void, + reset: () => void, + step: (steps?: number, duration?: number) => void, +} & typeof raf; diff --git a/flow-typed/npm/@atlaskit/css-reset_vx.x.x.js b/flow-typed/npm/@atlaskit/css-reset_vx.x.x.js index e677de90ee..7d7586e6c8 100644 --- a/flow-typed/npm/@atlaskit/css-reset_vx.x.x.js +++ b/flow-typed/npm/@atlaskit/css-reset_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 1e37cf34aa5bb445498a3c315113251b -// flow-typed version: <>/@atlaskit/css-reset_v^3.0.6/flow_v0.95.1 +// flow-typed signature: f32a462214bd2e8b7fb2be1d187e8f99 +// flow-typed version: <>/@atlaskit/css-reset_v^5.0.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -16,3 +16,58 @@ declare module '@atlaskit/css-reset' { declare module.exports: any; } + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module '@atlaskit/css-reset/base' { + declare module.exports: any; +} + +declare module '@atlaskit/css-reset/browser-fixes' { + declare module.exports: any; +} + +declare module '@atlaskit/css-reset/reset' { + declare module.exports: any; +} + +declare module '@atlaskit/css-reset/tables' { + declare module.exports: any; +} + +declare module '@atlaskit/css-reset/utils' { + declare module.exports: any; +} + +declare module '@atlaskit/css-reset/utils/evaluate-inner' { + declare module.exports: any; +} + +// Filename aliases +declare module '@atlaskit/css-reset/base.js' { + declare module.exports: $Exports<'@atlaskit/css-reset/base'>; +} +declare module '@atlaskit/css-reset/browser-fixes.js' { + declare module.exports: $Exports<'@atlaskit/css-reset/browser-fixes'>; +} +declare module '@atlaskit/css-reset/index' { + declare module.exports: $Exports<'@atlaskit/css-reset'>; +} +declare module '@atlaskit/css-reset/index.js' { + declare module.exports: $Exports<'@atlaskit/css-reset'>; +} +declare module '@atlaskit/css-reset/reset.js' { + declare module.exports: $Exports<'@atlaskit/css-reset/reset'>; +} +declare module '@atlaskit/css-reset/tables.js' { + declare module.exports: $Exports<'@atlaskit/css-reset/tables'>; +} +declare module '@atlaskit/css-reset/utils.js' { + declare module.exports: $Exports<'@atlaskit/css-reset/utils'>; +} +declare module '@atlaskit/css-reset/utils/evaluate-inner.js' { + declare module.exports: $Exports<'@atlaskit/css-reset/utils/evaluate-inner'>; +} diff --git a/flow-typed/npm/@babel/core_vx.x.x.js b/flow-typed/npm/@babel/core_vx.x.x.js index c2a6911dbd..7ef0b072cc 100644 --- a/flow-typed/npm/@babel/core_vx.x.x.js +++ b/flow-typed/npm/@babel/core_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: f9ce5b944d6802a562649660e3c46b76 -// flow-typed version: <>/@babel/core_v^7.4.3/flow_v0.96.0 +// flow-typed signature: f230f03f0142201c725eed8b861bda1a +// flow-typed version: <>/@babel/core_v^7.4.5/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/plugin-proposal-class-properties_vx.x.x.js b/flow-typed/npm/@babel/plugin-proposal-class-properties_vx.x.x.js index 37a9f61d51..9d55edca68 100644 --- a/flow-typed/npm/@babel/plugin-proposal-class-properties_vx.x.x.js +++ b/flow-typed/npm/@babel/plugin-proposal-class-properties_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 6e2bcba2dbfc7e3c856b4a63b7cb236f -// flow-typed version: <>/@babel/plugin-proposal-class-properties_v^7.4.0/flow_v0.96.0 +// flow-typed signature: f51c0c05384ec8448fd883737a9204ab +// flow-typed version: <>/@babel/plugin-proposal-class-properties_v^7.4.4/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/plugin-transform-modules-commonjs_vx.x.x.js b/flow-typed/npm/@babel/plugin-transform-modules-commonjs_vx.x.x.js index 996d1a2b62..5f33006640 100644 --- a/flow-typed/npm/@babel/plugin-transform-modules-commonjs_vx.x.x.js +++ b/flow-typed/npm/@babel/plugin-transform-modules-commonjs_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: bdfb1d4183f375144e4118b87ba93bee -// flow-typed version: <>/@babel/plugin-transform-modules-commonjs_v^7.4.3/flow_v0.96.0 +// flow-typed signature: ddf10cd93ac0e25c84ee6b62ef25cbfe +// flow-typed version: <>/@babel/plugin-transform-modules-commonjs_v^7.4.4/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/plugin-transform-runtime_vx.x.x.js b/flow-typed/npm/@babel/plugin-transform-runtime_vx.x.x.js index 0171552239..1af24a64e3 100644 --- a/flow-typed/npm/@babel/plugin-transform-runtime_vx.x.x.js +++ b/flow-typed/npm/@babel/plugin-transform-runtime_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 489e57e1e66d02415a2265fc0ee1b2ad -// flow-typed version: <>/@babel/plugin-transform-runtime_v^7.4.3/flow_v0.96.0 +// flow-typed signature: c1904f48f37d45b6a4f4553c7a85dd95 +// flow-typed version: <>/@babel/plugin-transform-runtime_v^7.4.4/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/preset-env_vx.x.x.js b/flow-typed/npm/@babel/preset-env_vx.x.x.js index ac0eac3f67..0efa675048 100644 --- a/flow-typed/npm/@babel/preset-env_vx.x.x.js +++ b/flow-typed/npm/@babel/preset-env_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: c48f89dc24c96871cbe461a64bded15f -// flow-typed version: <>/@babel/preset-env_v^7.4.3/flow_v0.96.0 +// flow-typed signature: 5c8b591a7eebb849e4477a03c08f42ca +// flow-typed version: <>/@babel/preset-env_v^7.4.5/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/preset-flow_vx.x.x.js b/flow-typed/npm/@babel/preset-flow_vx.x.x.js index 0450af4b71..152622da64 100644 --- a/flow-typed/npm/@babel/preset-flow_vx.x.x.js +++ b/flow-typed/npm/@babel/preset-flow_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 8f65f5a975bcf1cebc7acc6a0da81c6e -// flow-typed version: <>/@babel/preset-flow_v^7.0.0/flow_v0.96.0 +// flow-typed signature: e34943f565ada7e8ee0d7ae12c81aff8 +// flow-typed version: <>/@babel/preset-flow_v^7.0.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/preset-react_vx.x.x.js b/flow-typed/npm/@babel/preset-react_vx.x.x.js index 4097246987..eb0faaacb0 100644 --- a/flow-typed/npm/@babel/preset-react_vx.x.x.js +++ b/flow-typed/npm/@babel/preset-react_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: bc4e2309ea659005cdd86bc4ec5fdafb -// flow-typed version: <>/@babel/preset-react_v^7.0.0/flow_v0.96.0 +// flow-typed signature: 3c1269506085210cf5a030ae21fad6a2 +// flow-typed version: <>/@babel/preset-react_v^7.0.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@babel/runtime-corejs2_vx.x.x.js b/flow-typed/npm/@babel/runtime-corejs2_vx.x.x.js index 1a3072ddfa..90d7276459 100644 --- a/flow-typed/npm/@babel/runtime-corejs2_vx.x.x.js +++ b/flow-typed/npm/@babel/runtime-corejs2_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: babd97d6ed49545ee3060a9b52ed1332 -// flow-typed version: <>/@babel/runtime-corejs2_v^7.4.3/flow_v0.96.0 +// flow-typed signature: f5841cc7e27a9aca4e89b8c70da58f7a +// flow-typed version: <>/@babel/runtime-corejs2_v^7.4.5/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/@emotion/babel-preset-css-prop_vx.x.x.js b/flow-typed/npm/@emotion/babel-preset-css-prop_vx.x.x.js new file mode 100644 index 0000000000..68fefa2631 --- /dev/null +++ b/flow-typed/npm/@emotion/babel-preset-css-prop_vx.x.x.js @@ -0,0 +1,60 @@ +// flow-typed signature: 0c3d4221a655e3abad4eb6cddbedbeb0 +// flow-typed version: <>/@emotion/babel-preset-css-prop_v^10.0.14/flow_v0.102.0 + +/** + * This is an autogenerated libdef stub for: + * + * '@emotion/babel-preset-css-prop' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module '@emotion/babel-preset-css-prop' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.dev' { + declare module.exports: any; +} + +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs' { + declare module.exports: any; +} + +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.prod' { + declare module.exports: any; +} + +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.esm' { + declare module.exports: any; +} + +declare module '@emotion/babel-preset-css-prop/src/index' { + declare module.exports: any; +} + +// Filename aliases +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.dev.js' { + declare module.exports: $Exports<'@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.dev'>; +} +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.js' { + declare module.exports: $Exports<'@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs'>; +} +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.prod.js' { + declare module.exports: $Exports<'@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.cjs.prod'>; +} +declare module '@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.esm.js' { + declare module.exports: $Exports<'@emotion/babel-preset-css-prop/dist/babel-preset-css-prop.esm'>; +} +declare module '@emotion/babel-preset-css-prop/src/index.js' { + declare module.exports: $Exports<'@emotion/babel-preset-css-prop/src/index'>; +} diff --git a/flow-typed/npm/@storybook/addon-options_v4.x.x.js b/flow-typed/npm/@storybook/addon-options_v4.x.x.js deleted file mode 100644 index 25335c2e06..0000000000 --- a/flow-typed/npm/@storybook/addon-options_v4.x.x.js +++ /dev/null @@ -1,165 +0,0 @@ -// flow-typed signature: d87955256c0438e8d919bd2cfe5423e9 -// flow-typed version: 028ef45280/@storybook/addon-options_v4.x.x/flow_>=v0.25.x - -declare module '@storybook/addon-options' { - declare type Theme = { - /** - * applied to root `background` - * @default: 'linear-gradient(to bottom right, black, gray' - */ - mainBackground?: string, - /** - * applied to panels `border` - * @default: '1px solid rgba(0,0,0,0.1)' - */ - mainBorder?: string, - /** - * applied for most borders - * @default: 'rgba(0,0,0,0.1)' - */ - mainBorderColor?: string, - /** - * applied to panels, buttons, inputs - * @default: 4 - */ - mainBorderRadius?: string, - /** - * applied to panels `background` - * @default: 'rgba(255,255,255,0.89)' - */ - mainFill?: string, - /** - * applied to TabsBar `background` - * @default: 'rgba(255,255,255,1)' - */ - barFill?: string, - /** - * applied to Input `background` - * @default: 'rgba(0,0,0,0.05)' - */ - inputFill?: string, - /** - * applied to root `font-family` - */ - mainTextFace?: string, - /** - * applied to root & buttons & input `color` - * @default: black - */ - mainTextColor?: string, - /** - * applied to root - * @default: 13 - */ - mainTextSize?: string, - /** - * applied in less important text - * @default: 'rgba(0,0,0,0.4)' - */ - dimmedTextColor?: string, - /** - * applied to indicate selection - * @default: '#9fdaff' - */ - highlightColor?: string, - /** - * applied to indicate positive - * @default: '#0edf62' - */ - successColor?: string, - /** - * applied to indicate negative - * @default: '#ff3f3f' - */ - failColor?: string, - /** - * applied to indicate ow-ow - * @default: 'orange' - */ - warnColor?: string, - /** - * applied to pre, - */ - monoTextFace?: string, - /** - * applied to space panels - * @default: 10 - */ - layoutMargin?: string, - /** - * applied to overlay `background` - * @default: 'linear-gradient(to bottom right, rgba(233, 233, 233, 0.6), rgba(255, 255, 255, 0.8))' - */ - overlayBackground?: string, - }; - - declare type Options = { - theme?: Theme, - /** - * name to display in the top left corner - */ - name?: string, - /** - * URL for name in top left corner to link to - */ - url?: string, - /** - * show story component as full screen - */ - goFullScreen?: boolean, - /** - * display panel that shows a list of stories - */ - showStoriesPanel?: boolean, - /** - * display panel that shows addon configurations - */ - showAddonPanel?: boolean, - /** - * display floating search box to search through stories - */ - showSearchBox?: boolean, - /** - * show addon panel as a vertical panel on the right - */ - addonPanelInRight?: boolean, - /** - * sorts stories - */ - sortStoriesByKind?: boolean, - /** - * regex for finding the hierarchy separator - * @example: - * null - turn off hierarchy - * /\// - split by `/` - * /\./ - split by `.` - * /\/|\./ - split by `/` or `.` - */ - hierarchySeparator?: RegExp | string, - /** - * regex for finding the hierarchy root separator - * @example: - * null - turn off multiple hierarchy roots - * /\|/ - split by `|` - */ - hierarchyRootSeparator?: RegExp | string, - /** - * sidebar tree animations - */ - sidebarAnimations?: boolean, - /** - * id to select an addon panel - * The order of addons in the "Addon panel" is the same as you import them in 'addons.js'. - * The first panel will be opened by default as you run Storybook - */ - selectedAddonPanel?: string, - /** - * enable/disable shortcuts - * @default true - */ - enableShortcuts?: boolean, - }; - - declare function setOptions(options: $Exact): void; // deprecated: use `withOptions` - declare function withOptions(options: $Exact): void; -} diff --git a/flow-typed/npm/@storybook/addons_vx.x.x.js b/flow-typed/npm/@storybook/addons_vx.x.x.js deleted file mode 100644 index d04d932553..0000000000 --- a/flow-typed/npm/@storybook/addons_vx.x.x.js +++ /dev/null @@ -1,81 +0,0 @@ -// flow-typed signature: 81dc9300b3a07ebac0bbe937e70b3aa1 -// flow-typed version: <>/@storybook/addons_v^4.1.13/flow_v0.93.0 - -/** - * This is an autogenerated libdef stub for: - * - * '@storybook/addons' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module '@storybook/addons' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module '@storybook/addons/dist/index' { - declare module.exports: any; -} - -declare module '@storybook/addons/dist/make-decorator' { - declare module.exports: any; -} - -declare module '@storybook/addons/dist/make-decorator.test' { - declare module.exports: any; -} - -declare module '@storybook/addons/dist/storybook-channel-mock' { - declare module.exports: any; -} - -declare module '@storybook/addons/src/index' { - declare module.exports: any; -} - -declare module '@storybook/addons/src/make-decorator' { - declare module.exports: any; -} - -declare module '@storybook/addons/src/make-decorator.test' { - declare module.exports: any; -} - -declare module '@storybook/addons/src/storybook-channel-mock' { - declare module.exports: any; -} - -// Filename aliases -declare module '@storybook/addons/dist/index.js' { - declare module.exports: $Exports<'@storybook/addons/dist/index'>; -} -declare module '@storybook/addons/dist/make-decorator.js' { - declare module.exports: $Exports<'@storybook/addons/dist/make-decorator'>; -} -declare module '@storybook/addons/dist/make-decorator.test.js' { - declare module.exports: $Exports<'@storybook/addons/dist/make-decorator.test'>; -} -declare module '@storybook/addons/dist/storybook-channel-mock.js' { - declare module.exports: $Exports<'@storybook/addons/dist/storybook-channel-mock'>; -} -declare module '@storybook/addons/src/index.js' { - declare module.exports: $Exports<'@storybook/addons/src/index'>; -} -declare module '@storybook/addons/src/make-decorator.js' { - declare module.exports: $Exports<'@storybook/addons/src/make-decorator'>; -} -declare module '@storybook/addons/src/make-decorator.test.js' { - declare module.exports: $Exports<'@storybook/addons/src/make-decorator.test'>; -} -declare module '@storybook/addons/src/storybook-channel-mock.js' { - declare module.exports: $Exports<'@storybook/addons/src/storybook-channel-mock'>; -} diff --git a/flow-typed/npm/@storybook/react_v4.x.x.js b/flow-typed/npm/@storybook/react_v4.x.x.js deleted file mode 100644 index 029443f86a..0000000000 --- a/flow-typed/npm/@storybook/react_v4.x.x.js +++ /dev/null @@ -1,55 +0,0 @@ -// flow-typed signature: 04c5870b5fe5aee349b372d22630ffcc -// flow-typed version: 43bc56fd02/@storybook/react_v4.x.x/flow_>=v0.72.x - -type NodeModule = typeof module; - -declare module '@storybook/react' { - declare type Context = { kind: string, story: string }; - declare type Renderable = React$Element<*>; - declare type RenderCallback = ( - context: Context - ) => Renderable | Array; - declare type RenderFunction = () => Renderable | Array; - - declare type StoryDecorator = ( - story: RenderFunction, - context: Context - ) => Renderable | null; - - declare type DecoratorParameters = { - [key: string]: any, - }; - - declare interface Story { - +kind: string; - add( - storyName: string, - callback: RenderCallback, - parameters?: DecoratorParameters - ): Story; - addDecorator(decorator: StoryDecorator): Story; - addParameters(parameters: DecoratorParameters): Story; - } - - declare interface StoryObject { - name: string; - render: RenderFunction; - } - - declare interface StoryBucket { - kind: string; - filename: string; - stories: Array; - } - - declare function addDecorator(decorator: StoryDecorator): void; - declare function addParameters(parameters: DecoratorParameters): void; - declare function clearDecorators(): void; - declare function configure(fn: () => void, module: NodeModule): void; - declare function setAddon(addon: Object): void; - declare function storiesOf(name: string, module: NodeModule): Story; - declare function storiesOf(name: string, module: NodeModule): Story & T; - declare function forceReRender(): void; - - declare function getStorybook(): Array; -} diff --git a/flow-typed/npm/@storybook/react_v5.x.x.js b/flow-typed/npm/@storybook/react_v5.x.x.js index df2e75d576..682c493102 100644 --- a/flow-typed/npm/@storybook/react_v5.x.x.js +++ b/flow-typed/npm/@storybook/react_v5.x.x.js @@ -1,20 +1,24 @@ -// flow-typed signature: 9a5dabc68709bcf07f1b2c7f56a60413 -// flow-typed version: 56bf22e6ef/@storybook/react_v5.x.x/flow_>=v0.72.x +// flow-typed signature: 68ee88c520cb9bb70866d8812664bc7b +// flow-typed version: 00c3a083ad/@storybook/react_v5.x.x/flow_>=v0.72.x type NodeModule = typeof module; declare module '@storybook/react' { declare type Context = { kind: string, story: string }; - declare type Renderable = React$Element<*>; + declare type Renderable = + | string + | number + | React$Element + | Iterable; declare type RenderCallback = ( context: Context - ) => Renderable | Array; - declare type RenderFunction = () => Renderable | Array; + ) => Renderable; + declare type RenderFunction = () => Renderable; declare type StoryDecorator = ( story: RenderFunction, context: Context - ) => Renderable | null; + ) => Renderable; declare type DecoratorParameters = { [key: string]: any, diff --git a/flow-typed/npm/@storybook/react_vx.x.x.js b/flow-typed/npm/@storybook/react_vx.x.x.js deleted file mode 100644 index fe39d3a47b..0000000000 --- a/flow-typed/npm/@storybook/react_vx.x.x.js +++ /dev/null @@ -1,361 +0,0 @@ -// flow-typed signature: 451ec325629cf7b9ff2a8a35a24092cf -// flow-typed version: <>/@storybook/react_v^5.0.1/flow_v0.94.0 - -/** - * This is an autogenerated libdef stub for: - * - * '@storybook/react' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module '@storybook/react' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module '@storybook/react/bin/build' { - declare module.exports: any; -} - -declare module '@storybook/react/bin/index' { - declare module.exports: any; -} - -declare module '@storybook/react/demo' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/index' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/preview/element_check' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/preview/element_check.test' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/preview/globals' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/preview/index' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/preview/index.test' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/client/preview/render' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/demo/Button' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/demo/Welcome' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/__mocks__/mockConfig' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/__mocks__/mockRules' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/__mocks__/react-scripts-2-0-0/config/webpack.config.dev' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/__mocks__/react-scripts-2-1-0/config/webpack.config.dev' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/build' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/cra-config' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/cra-config.test' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/framework-preset-cra' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/framework-preset-react-docgen' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/framework-preset-react-docgen.test' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/framework-preset-react' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/index' { - declare module.exports: any; -} - -declare module '@storybook/react/dist/server/options' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/index' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/preview/element_check' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/preview/element_check.test' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/preview/globals' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/preview/index' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/preview/index.test' { - declare module.exports: any; -} - -declare module '@storybook/react/src/client/preview/render' { - declare module.exports: any; -} - -declare module '@storybook/react/src/demo/Button' { - declare module.exports: any; -} - -declare module '@storybook/react/src/demo/Welcome' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/__mocks__/mockConfig' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/__mocks__/mockRules' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/__mocks__/react-scripts-2-0-0/config/webpack.config.dev' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/__mocks__/react-scripts-2-1-0/config/webpack.config.dev' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/build' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/cra-config' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/cra-config.test' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/framework-preset-cra' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/framework-preset-react-docgen' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/framework-preset-react-docgen.test' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/framework-preset-react' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/index' { - declare module.exports: any; -} - -declare module '@storybook/react/src/server/options' { - declare module.exports: any; -} - -declare module '@storybook/react/standalone' { - declare module.exports: any; -} - -// Filename aliases -declare module '@storybook/react/bin/build.js' { - declare module.exports: $Exports<'@storybook/react/bin/build'>; -} -declare module '@storybook/react/bin/index.js' { - declare module.exports: $Exports<'@storybook/react/bin/index'>; -} -declare module '@storybook/react/demo.js' { - declare module.exports: $Exports<'@storybook/react/demo'>; -} -declare module '@storybook/react/dist/client/index.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/index'>; -} -declare module '@storybook/react/dist/client/preview/element_check.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/preview/element_check'>; -} -declare module '@storybook/react/dist/client/preview/element_check.test.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/preview/element_check.test'>; -} -declare module '@storybook/react/dist/client/preview/globals.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/preview/globals'>; -} -declare module '@storybook/react/dist/client/preview/index.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/preview/index'>; -} -declare module '@storybook/react/dist/client/preview/index.test.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/preview/index.test'>; -} -declare module '@storybook/react/dist/client/preview/render.js' { - declare module.exports: $Exports<'@storybook/react/dist/client/preview/render'>; -} -declare module '@storybook/react/dist/demo/Button.js' { - declare module.exports: $Exports<'@storybook/react/dist/demo/Button'>; -} -declare module '@storybook/react/dist/demo/Welcome.js' { - declare module.exports: $Exports<'@storybook/react/dist/demo/Welcome'>; -} -declare module '@storybook/react/dist/server/__mocks__/mockConfig.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/__mocks__/mockConfig'>; -} -declare module '@storybook/react/dist/server/__mocks__/mockRules.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/__mocks__/mockRules'>; -} -declare module '@storybook/react/dist/server/__mocks__/react-scripts-2-0-0/config/webpack.config.dev.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/__mocks__/react-scripts-2-0-0/config/webpack.config.dev'>; -} -declare module '@storybook/react/dist/server/__mocks__/react-scripts-2-1-0/config/webpack.config.dev.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/__mocks__/react-scripts-2-1-0/config/webpack.config.dev'>; -} -declare module '@storybook/react/dist/server/build.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/build'>; -} -declare module '@storybook/react/dist/server/cra-config.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/cra-config'>; -} -declare module '@storybook/react/dist/server/cra-config.test.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/cra-config.test'>; -} -declare module '@storybook/react/dist/server/framework-preset-cra.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/framework-preset-cra'>; -} -declare module '@storybook/react/dist/server/framework-preset-react-docgen.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/framework-preset-react-docgen'>; -} -declare module '@storybook/react/dist/server/framework-preset-react-docgen.test.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/framework-preset-react-docgen.test'>; -} -declare module '@storybook/react/dist/server/framework-preset-react.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/framework-preset-react'>; -} -declare module '@storybook/react/dist/server/index.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/index'>; -} -declare module '@storybook/react/dist/server/options.js' { - declare module.exports: $Exports<'@storybook/react/dist/server/options'>; -} -declare module '@storybook/react/src/client/index.js' { - declare module.exports: $Exports<'@storybook/react/src/client/index'>; -} -declare module '@storybook/react/src/client/preview/element_check.js' { - declare module.exports: $Exports<'@storybook/react/src/client/preview/element_check'>; -} -declare module '@storybook/react/src/client/preview/element_check.test.js' { - declare module.exports: $Exports<'@storybook/react/src/client/preview/element_check.test'>; -} -declare module '@storybook/react/src/client/preview/globals.js' { - declare module.exports: $Exports<'@storybook/react/src/client/preview/globals'>; -} -declare module '@storybook/react/src/client/preview/index.js' { - declare module.exports: $Exports<'@storybook/react/src/client/preview/index'>; -} -declare module '@storybook/react/src/client/preview/index.test.js' { - declare module.exports: $Exports<'@storybook/react/src/client/preview/index.test'>; -} -declare module '@storybook/react/src/client/preview/render.js' { - declare module.exports: $Exports<'@storybook/react/src/client/preview/render'>; -} -declare module '@storybook/react/src/demo/Button.js' { - declare module.exports: $Exports<'@storybook/react/src/demo/Button'>; -} -declare module '@storybook/react/src/demo/Welcome.js' { - declare module.exports: $Exports<'@storybook/react/src/demo/Welcome'>; -} -declare module '@storybook/react/src/server/__mocks__/mockConfig.js' { - declare module.exports: $Exports<'@storybook/react/src/server/__mocks__/mockConfig'>; -} -declare module '@storybook/react/src/server/__mocks__/mockRules.js' { - declare module.exports: $Exports<'@storybook/react/src/server/__mocks__/mockRules'>; -} -declare module '@storybook/react/src/server/__mocks__/react-scripts-2-0-0/config/webpack.config.dev.js' { - declare module.exports: $Exports<'@storybook/react/src/server/__mocks__/react-scripts-2-0-0/config/webpack.config.dev'>; -} -declare module '@storybook/react/src/server/__mocks__/react-scripts-2-1-0/config/webpack.config.dev.js' { - declare module.exports: $Exports<'@storybook/react/src/server/__mocks__/react-scripts-2-1-0/config/webpack.config.dev'>; -} -declare module '@storybook/react/src/server/build.js' { - declare module.exports: $Exports<'@storybook/react/src/server/build'>; -} -declare module '@storybook/react/src/server/cra-config.js' { - declare module.exports: $Exports<'@storybook/react/src/server/cra-config'>; -} -declare module '@storybook/react/src/server/cra-config.test.js' { - declare module.exports: $Exports<'@storybook/react/src/server/cra-config.test'>; -} -declare module '@storybook/react/src/server/framework-preset-cra.js' { - declare module.exports: $Exports<'@storybook/react/src/server/framework-preset-cra'>; -} -declare module '@storybook/react/src/server/framework-preset-react-docgen.js' { - declare module.exports: $Exports<'@storybook/react/src/server/framework-preset-react-docgen'>; -} -declare module '@storybook/react/src/server/framework-preset-react-docgen.test.js' { - declare module.exports: $Exports<'@storybook/react/src/server/framework-preset-react-docgen.test'>; -} -declare module '@storybook/react/src/server/framework-preset-react.js' { - declare module.exports: $Exports<'@storybook/react/src/server/framework-preset-react'>; -} -declare module '@storybook/react/src/server/index.js' { - declare module.exports: $Exports<'@storybook/react/src/server/index'>; -} -declare module '@storybook/react/src/server/options.js' { - declare module.exports: $Exports<'@storybook/react/src/server/options'>; -} -declare module '@storybook/react/standalone.js' { - declare module.exports: $Exports<'@storybook/react/standalone'>; -} diff --git a/flow-typed/npm/@storybook/theming_vx.x.x.js b/flow-typed/npm/@storybook/theming_vx.x.x.js index 346015da01..ccb5cb38c5 100644 --- a/flow-typed/npm/@storybook/theming_vx.x.x.js +++ b/flow-typed/npm/@storybook/theming_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: b82e4146df874d06c07be8c6c7c33510 -// flow-typed version: <>/@storybook/theming_v^5.0.6/flow_v0.96.0 +// flow-typed signature: e6880483ec0f9e9821793e3333e96524 +// flow-typed version: <>/@storybook/theming_v^5.1.9/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -22,6 +22,10 @@ declare module '@storybook/theming' { * require those files directly. Feel free to delete any files that aren't * needed. */ +declare module '@storybook/theming/create' { + declare module.exports: any; +} + declare module '@storybook/theming/dist/animation' { declare module.exports: any; } @@ -30,6 +34,10 @@ declare module '@storybook/theming/dist/base' { declare module.exports: any; } +declare module '@storybook/theming/dist/convert' { + declare module.exports: any; +} + declare module '@storybook/theming/dist/create' { declare module.exports: any; } @@ -50,6 +58,10 @@ declare module '@storybook/theming/dist/modules/syntax' { declare module.exports: any; } +declare module '@storybook/theming/dist/tests/convert.test' { + declare module.exports: any; +} + declare module '@storybook/theming/dist/tests/create.test' { declare module.exports: any; } @@ -62,21 +74,39 @@ declare module '@storybook/theming/dist/themes/light' { declare module.exports: any; } +declare module '@storybook/theming/dist/types' { + declare module.exports: any; +} + declare module '@storybook/theming/dist/utils' { declare module.exports: any; } +declare module '@storybook/theming/paths' { + declare module.exports: any; +} + +declare module '@storybook/theming/src/tests/convert.test' { + declare module.exports: any; +} + declare module '@storybook/theming/src/tests/create.test' { declare module.exports: any; } // Filename aliases +declare module '@storybook/theming/create.js' { + declare module.exports: $Exports<'@storybook/theming/create'>; +} declare module '@storybook/theming/dist/animation.js' { declare module.exports: $Exports<'@storybook/theming/dist/animation'>; } declare module '@storybook/theming/dist/base.js' { declare module.exports: $Exports<'@storybook/theming/dist/base'>; } +declare module '@storybook/theming/dist/convert.js' { + declare module.exports: $Exports<'@storybook/theming/dist/convert'>; +} declare module '@storybook/theming/dist/create.js' { declare module.exports: $Exports<'@storybook/theming/dist/create'>; } @@ -92,6 +122,9 @@ declare module '@storybook/theming/dist/index.js' { declare module '@storybook/theming/dist/modules/syntax.js' { declare module.exports: $Exports<'@storybook/theming/dist/modules/syntax'>; } +declare module '@storybook/theming/dist/tests/convert.test.js' { + declare module.exports: $Exports<'@storybook/theming/dist/tests/convert.test'>; +} declare module '@storybook/theming/dist/tests/create.test.js' { declare module.exports: $Exports<'@storybook/theming/dist/tests/create.test'>; } @@ -101,9 +134,18 @@ declare module '@storybook/theming/dist/themes/dark.js' { declare module '@storybook/theming/dist/themes/light.js' { declare module.exports: $Exports<'@storybook/theming/dist/themes/light'>; } +declare module '@storybook/theming/dist/types.js' { + declare module.exports: $Exports<'@storybook/theming/dist/types'>; +} declare module '@storybook/theming/dist/utils.js' { declare module.exports: $Exports<'@storybook/theming/dist/utils'>; } +declare module '@storybook/theming/paths.js' { + declare module.exports: $Exports<'@storybook/theming/paths'>; +} +declare module '@storybook/theming/src/tests/convert.test.js' { + declare module.exports: $Exports<'@storybook/theming/src/tests/convert.test'>; +} declare module '@storybook/theming/src/tests/create.test.js' { declare module.exports: $Exports<'@storybook/theming/src/tests/create.test'>; } diff --git a/flow-typed/npm/babel-core_vx.x.x.js b/flow-typed/npm/babel-core_vx.x.x.js index 85c4c4f1f3..b5b0542b8a 100644 --- a/flow-typed/npm/babel-core_vx.x.x.js +++ b/flow-typed/npm/babel-core_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 15b12cc054beb5785cab1813df487f4a -// flow-typed version: <>/babel-core_v^7.0.0-bridge.0/flow_v0.96.0 +// flow-typed signature: db2f9ad162e004b977606ad2fcf3d045 +// flow-typed version: <>/babel-core_v^7.0.0-bridge.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-eslint_vx.x.x.js b/flow-typed/npm/babel-eslint_vx.x.x.js index 53c5b5a999..d6a4312ddc 100644 --- a/flow-typed/npm/babel-eslint_vx.x.x.js +++ b/flow-typed/npm/babel-eslint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 03bb20be27e0b5d1aa1965337e650c6b -// flow-typed version: <>/babel-eslint_v^10.0.1/flow_v0.96.0 +// flow-typed signature: 6531f11721fe8f17828f74486dac94f7 +// flow-typed version: <>/babel-eslint_v^10.0.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-jest_vx.x.x.js b/flow-typed/npm/babel-jest_vx.x.x.js index 36c4a731d0..76666a9252 100644 --- a/flow-typed/npm/babel-jest_vx.x.x.js +++ b/flow-typed/npm/babel-jest_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 2178a5dce9b57afc8bcfdec6ecb29843 -// flow-typed version: <>/babel-jest_v^24.7.1/flow_v0.96.0 +// flow-typed signature: 544b2a0d21f766db7d5beddc0503eab9 +// flow-typed version: <>/babel-jest_v^24.8.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-loader_vx.x.x.js b/flow-typed/npm/babel-loader_vx.x.x.js index 5508d7a712..4531a476cc 100644 --- a/flow-typed/npm/babel-loader_vx.x.x.js +++ b/flow-typed/npm/babel-loader_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: bda1d2297c12e38eb2525d30b0d866c0 -// flow-typed version: <>/babel-loader_v^8.0.5/flow_v0.96.0 +// flow-typed signature: 4b3aa457e328c9a0fe32f97cfe92db2a +// flow-typed version: <>/babel-loader_v^8.0.6/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-plugin-dev-expression_vx.x.x.js b/flow-typed/npm/babel-plugin-dev-expression_vx.x.x.js index bcda629b14..80076406a7 100644 --- a/flow-typed/npm/babel-plugin-dev-expression_vx.x.x.js +++ b/flow-typed/npm/babel-plugin-dev-expression_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 67a9a546e9859c391c5f659cb1ba250b -// flow-typed version: <>/babel-plugin-dev-expression_v^0.2.1/flow_v0.96.0 +// flow-typed signature: d1643e137930a8fb6f9df6c1420b682f +// flow-typed version: <>/babel-plugin-dev-expression_v^0.2.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/babel-plugin-styled-components_vx.x.x.js b/flow-typed/npm/babel-plugin-styled-components_vx.x.x.js deleted file mode 100644 index 5608238ce9..0000000000 --- a/flow-typed/npm/babel-plugin-styled-components_vx.x.x.js +++ /dev/null @@ -1,130 +0,0 @@ -// flow-typed signature: db56562bad1d5fd4ac128ca23353cb7c -// flow-typed version: <>/babel-plugin-styled-components_v^1.10.0/flow_v0.93.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-plugin-styled-components' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-plugin-styled-components' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-plugin-styled-components/lib/css/placeholderUtils' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/index' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/minify/index' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/utils/detectors' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/utils/getName' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/utils/hash' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/utils/options' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/utils/prefixDigit' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/assignStyledRequired' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/displayNameAndId' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/minify' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/pure' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/templateLiterals/index' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/templateLiterals/transpile' { - declare module.exports: any; -} - -declare module 'babel-plugin-styled-components/lib/visitors/transpileCssProp' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-plugin-styled-components/lib/css/placeholderUtils.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/css/placeholderUtils'>; -} -declare module 'babel-plugin-styled-components/lib/index.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/index'>; -} -declare module 'babel-plugin-styled-components/lib/minify/index.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/minify/index'>; -} -declare module 'babel-plugin-styled-components/lib/utils/detectors.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/utils/detectors'>; -} -declare module 'babel-plugin-styled-components/lib/utils/getName.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/utils/getName'>; -} -declare module 'babel-plugin-styled-components/lib/utils/hash.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/utils/hash'>; -} -declare module 'babel-plugin-styled-components/lib/utils/options.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/utils/options'>; -} -declare module 'babel-plugin-styled-components/lib/utils/prefixDigit.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/utils/prefixDigit'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/assignStyledRequired.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/assignStyledRequired'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/displayNameAndId.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/displayNameAndId'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/minify.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/minify'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/pure.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/pure'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/templateLiterals/index.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/templateLiterals/index'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/templateLiterals/transpile.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/templateLiterals/transpile'>; -} -declare module 'babel-plugin-styled-components/lib/visitors/transpileCssProp.js' { - declare module.exports: $Exports<'babel-plugin-styled-components/lib/visitors/transpileCssProp'>; -} diff --git a/flow-typed/npm/cross-env_vx.x.x.js b/flow-typed/npm/cross-env_vx.x.x.js index 57bdedcc9d..c245bacd77 100644 --- a/flow-typed/npm/cross-env_vx.x.x.js +++ b/flow-typed/npm/cross-env_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 7289d445d9db2b040518db47bc65009e -// flow-typed version: <>/cross-env_v^5.2.0/flow_v0.96.0 +// flow-typed signature: eebbf40b06ba0b752477df3797fd00df +// flow-typed version: <>/cross-env_v^5.2.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/cypress_vx.x.x.js b/flow-typed/npm/cypress_vx.x.x.js deleted file mode 100644 index fd55c1c8b5..0000000000 --- a/flow-typed/npm/cypress_vx.x.x.js +++ /dev/null @@ -1,150 +0,0 @@ -// flow-typed signature: 6d3c00c360d75290a220292953dbee05 -// flow-typed version: <>/cypress_v^3.2.0/flow_v0.96.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'cypress' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'cypress' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'cypress/lib/cli' { - declare module.exports: any; -} - -declare module 'cypress/lib/cypress' { - declare module.exports: any; -} - -declare module 'cypress/lib/errors' { - declare module.exports: any; -} - -declare module 'cypress/lib/exec/open' { - declare module.exports: any; -} - -declare module 'cypress/lib/exec/run' { - declare module.exports: any; -} - -declare module 'cypress/lib/exec/spawn' { - declare module.exports: any; -} - -declare module 'cypress/lib/exec/versions' { - declare module.exports: any; -} - -declare module 'cypress/lib/exec/xvfb' { - declare module.exports: any; -} - -declare module 'cypress/lib/fs' { - declare module.exports: any; -} - -declare module 'cypress/lib/logger' { - declare module.exports: any; -} - -declare module 'cypress/lib/tasks/cache' { - declare module.exports: any; -} - -declare module 'cypress/lib/tasks/download' { - declare module.exports: any; -} - -declare module 'cypress/lib/tasks/install' { - declare module.exports: any; -} - -declare module 'cypress/lib/tasks/state' { - declare module.exports: any; -} - -declare module 'cypress/lib/tasks/unzip' { - declare module.exports: any; -} - -declare module 'cypress/lib/tasks/verify' { - declare module.exports: any; -} - -declare module 'cypress/lib/util' { - declare module.exports: any; -} - -// Filename aliases -declare module 'cypress/index' { - declare module.exports: $Exports<'cypress'>; -} -declare module 'cypress/index.js' { - declare module.exports: $Exports<'cypress'>; -} -declare module 'cypress/lib/cli.js' { - declare module.exports: $Exports<'cypress/lib/cli'>; -} -declare module 'cypress/lib/cypress.js' { - declare module.exports: $Exports<'cypress/lib/cypress'>; -} -declare module 'cypress/lib/errors.js' { - declare module.exports: $Exports<'cypress/lib/errors'>; -} -declare module 'cypress/lib/exec/open.js' { - declare module.exports: $Exports<'cypress/lib/exec/open'>; -} -declare module 'cypress/lib/exec/run.js' { - declare module.exports: $Exports<'cypress/lib/exec/run'>; -} -declare module 'cypress/lib/exec/spawn.js' { - declare module.exports: $Exports<'cypress/lib/exec/spawn'>; -} -declare module 'cypress/lib/exec/versions.js' { - declare module.exports: $Exports<'cypress/lib/exec/versions'>; -} -declare module 'cypress/lib/exec/xvfb.js' { - declare module.exports: $Exports<'cypress/lib/exec/xvfb'>; -} -declare module 'cypress/lib/fs.js' { - declare module.exports: $Exports<'cypress/lib/fs'>; -} -declare module 'cypress/lib/logger.js' { - declare module.exports: $Exports<'cypress/lib/logger'>; -} -declare module 'cypress/lib/tasks/cache.js' { - declare module.exports: $Exports<'cypress/lib/tasks/cache'>; -} -declare module 'cypress/lib/tasks/download.js' { - declare module.exports: $Exports<'cypress/lib/tasks/download'>; -} -declare module 'cypress/lib/tasks/install.js' { - declare module.exports: $Exports<'cypress/lib/tasks/install'>; -} -declare module 'cypress/lib/tasks/state.js' { - declare module.exports: $Exports<'cypress/lib/tasks/state'>; -} -declare module 'cypress/lib/tasks/unzip.js' { - declare module.exports: $Exports<'cypress/lib/tasks/unzip'>; -} -declare module 'cypress/lib/tasks/verify.js' { - declare module.exports: $Exports<'cypress/lib/tasks/verify'>; -} -declare module 'cypress/lib/util.js' { - declare module.exports: $Exports<'cypress/lib/util'>; -} diff --git a/flow-typed/npm/enzyme-adapter-react-16_vx.x.x.js b/flow-typed/npm/enzyme-adapter-react-16_vx.x.x.js index 103fa8594d..d86cdc99da 100644 --- a/flow-typed/npm/enzyme-adapter-react-16_vx.x.x.js +++ b/flow-typed/npm/enzyme-adapter-react-16_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 7a4ce8257d745ddee5ef466f19a4d40e -// flow-typed version: <>/enzyme-adapter-react-16_v^1.11.2/flow_v0.96.0 +// flow-typed signature: 70b8d9bd48f92f611fb6648d18e93f26 +// flow-typed version: <>/enzyme-adapter-react-16_v^1.14.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-config-airbnb_vx.x.x.js b/flow-typed/npm/eslint-config-airbnb_vx.x.x.js index 5e00ba5eed..d1cc0d40a7 100644 --- a/flow-typed/npm/eslint-config-airbnb_vx.x.x.js +++ b/flow-typed/npm/eslint-config-airbnb_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 468ec577dfca71c397f167491e507e62 -// flow-typed version: <>/eslint-config-airbnb_v^17.1.0/flow_v0.96.0 +// flow-typed signature: 8372ef3fd51bad59ca6c528ca24faf99 +// flow-typed version: <>/eslint-config-airbnb_v^17.1.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-config-prettier_vx.x.x.js b/flow-typed/npm/eslint-config-prettier_vx.x.x.js index 924d896365..5475422614 100644 --- a/flow-typed/npm/eslint-config-prettier_vx.x.x.js +++ b/flow-typed/npm/eslint-config-prettier_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: c3e1fa7095346bbf390c6cff66bca2ca -// flow-typed version: <>/eslint-config-prettier_v^4.1.0/flow_v0.96.0 +// flow-typed signature: 4bf0e5d69e0057ce27b15b595ceaebe6 +// flow-typed version: <>/eslint-config-prettier_v^6.0.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-plugin-cypress_vx.x.x.js b/flow-typed/npm/eslint-plugin-cypress_vx.x.x.js index a129f1298b..0cef0a1358 100644 --- a/flow-typed/npm/eslint-plugin-cypress_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-cypress_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 963cdfdedb67feb7729202c25b546207 -// flow-typed version: <>/eslint-plugin-cypress_v^2.2.1/flow_v0.96.0 +// flow-typed signature: 34d2abd0a3e2b3be9f147abd35665b81 +// flow-typed version: <>/eslint-plugin-cypress_v^2.2.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js b/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js index 6fb1930d19..542266e984 100644 --- a/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 0d24d9a0784ba628b84fb6f86404d2a5 -// flow-typed version: <>/eslint-plugin-flowtype_v^3.5.1/flow_v0.96.0 +// flow-typed signature: 9eb2b7d4d509e25f55c868822809e7e6 +// flow-typed version: <>/eslint-plugin-flowtype_v^3.11.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -130,10 +130,18 @@ declare module 'eslint-plugin-flowtype/dist/rules/requireExactType' { declare module.exports: any; } +declare module 'eslint-plugin-flowtype/dist/rules/requireInexactType' { + declare module.exports: any; +} + declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType' { declare module.exports: any; } +declare module 'eslint-plugin-flowtype/dist/rules/requireReadonlyReactProps' { + declare module.exports: any; +} + declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType' { declare module.exports: any; } @@ -170,6 +178,10 @@ declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon' { declare module.exports: any; } +declare module 'eslint-plugin-flowtype/dist/rules/spreadExactType' { + declare module.exports: any; +} + declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions' { declare module.exports: any; } @@ -352,9 +364,15 @@ declare module 'eslint-plugin-flowtype/dist/rules/requireCompoundTypeAlias.js' { declare module 'eslint-plugin-flowtype/dist/rules/requireExactType.js' { declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireExactType'>; } +declare module 'eslint-plugin-flowtype/dist/rules/requireInexactType.js' { + declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireInexactType'>; +} declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType.js' { declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireParameterType'>; } +declare module 'eslint-plugin-flowtype/dist/rules/requireReadonlyReactProps.js' { + declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireReadonlyReactProps'>; +} declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType.js' { declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireReturnType'>; } @@ -382,6 +400,9 @@ declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket.js' declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon.js' { declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon'>; } +declare module 'eslint-plugin-flowtype/dist/rules/spreadExactType.js' { + declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spreadExactType'>; +} declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions.js' { declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions'>; } diff --git a/flow-typed/npm/eslint-plugin-import_vx.x.x.js b/flow-typed/npm/eslint-plugin-import_vx.x.x.js index ff15e23b89..604a6c9ba1 100644 --- a/flow-typed/npm/eslint-plugin-import_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-import_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: f0633391ebd85a6b99725c25888b5263 -// flow-typed version: <>/eslint-plugin-import_v^2.16.0/flow_v0.96.0 +// flow-typed signature: 4f87de8db0927b2ca7be02fe60c86d68 +// flow-typed version: <>/eslint-plugin-import_v^2.18.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -218,6 +218,10 @@ declare module 'eslint-plugin-import/lib/rules/no-unresolved' { declare module.exports: any; } +declare module 'eslint-plugin-import/lib/rules/no-unused-modules' { + declare module.exports: any; +} + declare module 'eslint-plugin-import/lib/rules/no-useless-path-segments' { declare module.exports: any; } @@ -390,6 +394,9 @@ declare module 'eslint-plugin-import/lib/rules/no-unassigned-import.js' { declare module 'eslint-plugin-import/lib/rules/no-unresolved.js' { declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-unresolved'>; } +declare module 'eslint-plugin-import/lib/rules/no-unused-modules.js' { + declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-unused-modules'>; +} declare module 'eslint-plugin-import/lib/rules/no-useless-path-segments.js' { declare module.exports: $Exports<'eslint-plugin-import/lib/rules/no-useless-path-segments'>; } diff --git a/flow-typed/npm/eslint-plugin-jest_vx.x.x.js b/flow-typed/npm/eslint-plugin-jest_vx.x.x.js index 08043d4562..bdbee356e4 100644 --- a/flow-typed/npm/eslint-plugin-jest_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-jest_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 6cce5ef9eaebbc1d67e69d7f9bdb533e -// flow-typed version: <>/eslint-plugin-jest_v^22.4.1/flow_v0.96.0 +// flow-typed signature: 1d4ba71a60a746b531c6c90eb9823226 +// flow-typed version: <>/eslint-plugin-jest_v^22.7.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -22,451 +22,970 @@ declare module 'eslint-plugin-jest' { * require those files directly. Feel free to delete any files that aren't * needed. */ -declare module 'eslint-plugin-jest/processors/__tests__/snapshot-processor.test' { +declare module 'eslint-plugin-jest/lib/__tests__/rules.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/processors/snapshot-processor' { +declare module 'eslint-plugin-jest/lib/index' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/consistent-test-it.test' { +declare module 'eslint-plugin-jest/lib/processors/__tests__/snapshot-processor.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/expect-expect.test' { +declare module 'eslint-plugin-jest/lib/processors/snapshot-processor' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/lowercase-name.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/consistent-test-it.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-alias-methods.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/expect-expect.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-disabled-tests.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/lowercase-name.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-empty-title' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-alias-methods.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-focused-tests.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-commented-out-tests.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-hooks.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-disabled-tests.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-identical-title.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-empty-title' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-jasmine-globals.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-focused-tests.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-jest-import.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-hooks.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-large-snapshots.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-identical-title.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-test-callback.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-jasmine-globals.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-test-prefixes.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-jest-import.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-test-return-statement.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-large-snapshots.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/no-truthy-falsy.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-mocks-import.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-called-with' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-test-callback.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-expect-assertions.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-test-prefixes.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-inline-snapshots.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-test-return-statement.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-spy-on.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-truthy-falsy.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-strict-equal.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-called-with' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-be-null.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-expect-assertions.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-be-undefined.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-inline-snapshots.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-contain.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-spy-on.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-have-length.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-strict-equal.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-todo.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-be-null.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/require-tothrow-message.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-be-undefined.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/valid-describe.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-contain.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/valid-expect-in-promise.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-have-length.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/__tests__/valid-expect.test' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-todo.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/consistent-test-it' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/require-tothrow-message.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/expect-expect' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/valid-describe.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/lowercase-name' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/valid-expect-in-promise.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-alias-methods' { +declare module 'eslint-plugin-jest/lib/rules/__tests__/valid-expect.test' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-disabled-tests' { +declare module 'eslint-plugin-jest/lib/rules/consistent-test-it' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-empty-title' { +declare module 'eslint-plugin-jest/lib/rules/expect-expect' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-focused-tests' { +declare module 'eslint-plugin-jest/lib/rules/lowercase-name' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-hooks' { +declare module 'eslint-plugin-jest/lib/rules/no-alias-methods' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-identical-title' { +declare module 'eslint-plugin-jest/lib/rules/no-commented-out-tests' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-jasmine-globals' { +declare module 'eslint-plugin-jest/lib/rules/no-disabled-tests' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-jest-import' { +declare module 'eslint-plugin-jest/lib/rules/no-empty-title' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-large-snapshots' { +declare module 'eslint-plugin-jest/lib/rules/no-focused-tests' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-test-callback' { +declare module 'eslint-plugin-jest/lib/rules/no-hooks' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-test-prefixes' { +declare module 'eslint-plugin-jest/lib/rules/no-identical-title' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-test-return-statement' { +declare module 'eslint-plugin-jest/lib/rules/no-jasmine-globals' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/no-truthy-falsy' { +declare module 'eslint-plugin-jest/lib/rules/no-jest-import' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-called-with' { +declare module 'eslint-plugin-jest/lib/rules/no-large-snapshots' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-expect-assertions' { +declare module 'eslint-plugin-jest/lib/rules/no-mocks-import' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-inline-snapshots' { +declare module 'eslint-plugin-jest/lib/rules/no-test-callback' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-spy-on' { +declare module 'eslint-plugin-jest/lib/rules/no-test-prefixes' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-strict-equal' { +declare module 'eslint-plugin-jest/lib/rules/no-test-return-statement' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-to-be-null' { +declare module 'eslint-plugin-jest/lib/rules/no-truthy-falsy' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-to-be-undefined' { +declare module 'eslint-plugin-jest/lib/rules/prefer-called-with' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-to-contain' { +declare module 'eslint-plugin-jest/lib/rules/prefer-expect-assertions' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-to-have-length' { +declare module 'eslint-plugin-jest/lib/rules/prefer-inline-snapshots' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/prefer-todo' { +declare module 'eslint-plugin-jest/lib/rules/prefer-spy-on' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/require-tothrow-message' { +declare module 'eslint-plugin-jest/lib/rules/prefer-strict-equal' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/util' { +declare module 'eslint-plugin-jest/lib/rules/prefer-to-be-null' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/valid-describe' { +declare module 'eslint-plugin-jest/lib/rules/prefer-to-be-undefined' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/valid-expect-in-promise' { +declare module 'eslint-plugin-jest/lib/rules/prefer-to-contain' { declare module.exports: any; } -declare module 'eslint-plugin-jest/rules/valid-expect' { +declare module 'eslint-plugin-jest/lib/rules/prefer-to-have-length' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/lib/rules/prefer-todo' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/lib/rules/require-tothrow-message' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/lib/rules/util' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/lib/rules/valid-describe' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/lib/rules/valid-expect-in-promise' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/lib/rules/valid-expect' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/__tests__/rules.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/index' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/processors/__tests__/snapshot-processor.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/processors/snapshot-processor' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/consistent-test-it.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/expect-expect.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/lowercase-name.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-alias-methods.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-commented-out-tests.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-disabled-tests.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-empty-title' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-focused-tests.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-hooks.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-identical-title.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-jasmine-globals.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-jest-import.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-large-snapshots.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-mocks-import.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-test-callback.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-test-prefixes.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-test-return-statement.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/no-truthy-falsy.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-called-with' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-expect-assertions.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-inline-snapshots.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-spy-on.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-strict-equal.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-be-null.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-be-undefined.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-contain.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-have-length.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-todo.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/require-tothrow-message.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/valid-describe.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/valid-expect-in-promise.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/__tests__/valid-expect.test' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/consistent-test-it' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/expect-expect' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/lowercase-name' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-alias-methods' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-commented-out-tests' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-disabled-tests' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-empty-title' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-focused-tests' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-hooks' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-identical-title' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-jasmine-globals' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-jest-import' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-large-snapshots' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-mocks-import' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-test-callback' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-test-prefixes' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-test-return-statement' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/no-truthy-falsy' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-called-with' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-expect-assertions' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-inline-snapshots' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-spy-on' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-strict-equal' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-to-be-null' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-to-be-undefined' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-to-contain' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-to-have-length' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/prefer-todo' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/require-tothrow-message' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/util' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/valid-describe' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/valid-expect-in-promise' { + declare module.exports: any; +} + +declare module 'eslint-plugin-jest/src/rules/valid-expect' { declare module.exports: any; } // Filename aliases -declare module 'eslint-plugin-jest/index' { - declare module.exports: $Exports<'eslint-plugin-jest'>; +declare module 'eslint-plugin-jest/lib/__tests__/rules.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/__tests__/rules.test'>; +} +declare module 'eslint-plugin-jest/lib/index.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/index'>; +} +declare module 'eslint-plugin-jest/lib/processors/__tests__/snapshot-processor.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/processors/__tests__/snapshot-processor.test'>; +} +declare module 'eslint-plugin-jest/lib/processors/snapshot-processor.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/processors/snapshot-processor'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/consistent-test-it.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/consistent-test-it.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/expect-expect.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/expect-expect.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/lowercase-name.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/lowercase-name.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-alias-methods.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-alias-methods.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-commented-out-tests.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-commented-out-tests.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-disabled-tests.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-disabled-tests.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-empty-title.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-empty-title'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-focused-tests.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-focused-tests.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-hooks.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-hooks.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-identical-title.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-identical-title.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-jasmine-globals.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-jasmine-globals.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-jest-import.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-jest-import.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-large-snapshots.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-large-snapshots.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-mocks-import.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-mocks-import.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-test-callback.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-test-callback.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-test-prefixes.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-test-prefixes.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-test-return-statement.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-test-return-statement.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/no-truthy-falsy.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/no-truthy-falsy.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-called-with.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-called-with'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-expect-assertions.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-expect-assertions.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-inline-snapshots.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-inline-snapshots.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-spy-on.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-spy-on.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-strict-equal.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-strict-equal.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-be-null.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-to-be-null.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-be-undefined.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-to-be-undefined.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-contain.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-to-contain.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-to-have-length.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-to-have-length.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/prefer-todo.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/prefer-todo.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/require-tothrow-message.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/require-tothrow-message.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/valid-describe.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/valid-describe.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/valid-expect-in-promise.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/valid-expect-in-promise.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/__tests__/valid-expect.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/__tests__/valid-expect.test'>; +} +declare module 'eslint-plugin-jest/lib/rules/consistent-test-it.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/consistent-test-it'>; +} +declare module 'eslint-plugin-jest/lib/rules/expect-expect.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/expect-expect'>; +} +declare module 'eslint-plugin-jest/lib/rules/lowercase-name.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/lowercase-name'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-alias-methods.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-alias-methods'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-commented-out-tests.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-commented-out-tests'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-disabled-tests.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-disabled-tests'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-empty-title.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-empty-title'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-focused-tests.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-focused-tests'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-hooks.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-hooks'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-identical-title.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-identical-title'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-jasmine-globals.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-jasmine-globals'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-jest-import.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-jest-import'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-large-snapshots.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-large-snapshots'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-mocks-import.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-mocks-import'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-test-callback.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-test-callback'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-test-prefixes.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-test-prefixes'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-test-return-statement.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-test-return-statement'>; +} +declare module 'eslint-plugin-jest/lib/rules/no-truthy-falsy.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/no-truthy-falsy'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-called-with.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-called-with'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-expect-assertions.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-expect-assertions'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-inline-snapshots.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-inline-snapshots'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-spy-on.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-spy-on'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-strict-equal.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-strict-equal'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-to-be-null.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-to-be-null'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-to-be-undefined.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-to-be-undefined'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-to-contain.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-to-contain'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-to-have-length.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-to-have-length'>; +} +declare module 'eslint-plugin-jest/lib/rules/prefer-todo.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/prefer-todo'>; +} +declare module 'eslint-plugin-jest/lib/rules/require-tothrow-message.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/require-tothrow-message'>; +} +declare module 'eslint-plugin-jest/lib/rules/util.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/util'>; +} +declare module 'eslint-plugin-jest/lib/rules/valid-describe.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/valid-describe'>; +} +declare module 'eslint-plugin-jest/lib/rules/valid-expect-in-promise.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/valid-expect-in-promise'>; +} +declare module 'eslint-plugin-jest/lib/rules/valid-expect.js' { + declare module.exports: $Exports<'eslint-plugin-jest/lib/rules/valid-expect'>; +} +declare module 'eslint-plugin-jest/src/__tests__/rules.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/__tests__/rules.test'>; +} +declare module 'eslint-plugin-jest/src/index.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/index'>; +} +declare module 'eslint-plugin-jest/src/processors/__tests__/snapshot-processor.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/processors/__tests__/snapshot-processor.test'>; +} +declare module 'eslint-plugin-jest/src/processors/snapshot-processor.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/processors/snapshot-processor'>; +} +declare module 'eslint-plugin-jest/src/rules/__tests__/consistent-test-it.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/consistent-test-it.test'>; } -declare module 'eslint-plugin-jest/index.js' { - declare module.exports: $Exports<'eslint-plugin-jest'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/expect-expect.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/expect-expect.test'>; } -declare module 'eslint-plugin-jest/processors/__tests__/snapshot-processor.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/processors/__tests__/snapshot-processor.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/lowercase-name.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/lowercase-name.test'>; } -declare module 'eslint-plugin-jest/processors/snapshot-processor.js' { - declare module.exports: $Exports<'eslint-plugin-jest/processors/snapshot-processor'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-alias-methods.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-alias-methods.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/consistent-test-it.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/consistent-test-it.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-commented-out-tests.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-commented-out-tests.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/expect-expect.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/expect-expect.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-disabled-tests.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-disabled-tests.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/lowercase-name.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/lowercase-name.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-empty-title.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-empty-title'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-alias-methods.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-alias-methods.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-focused-tests.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-focused-tests.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-disabled-tests.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-disabled-tests.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-hooks.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-hooks.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-empty-title.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-empty-title'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-identical-title.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-identical-title.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-focused-tests.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-focused-tests.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-jasmine-globals.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-jasmine-globals.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-hooks.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-hooks.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-jest-import.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-jest-import.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-identical-title.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-identical-title.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-large-snapshots.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-large-snapshots.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-jasmine-globals.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-jasmine-globals.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-mocks-import.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-mocks-import.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-jest-import.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-jest-import.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-test-callback.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-test-callback.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-large-snapshots.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-large-snapshots.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-test-prefixes.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-test-prefixes.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-test-callback.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-test-callback.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-test-return-statement.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-test-return-statement.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-test-prefixes.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-test-prefixes.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/no-truthy-falsy.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/no-truthy-falsy.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-test-return-statement.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-test-return-statement.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-called-with.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-called-with'>; } -declare module 'eslint-plugin-jest/rules/__tests__/no-truthy-falsy.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/no-truthy-falsy.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-expect-assertions.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-expect-assertions.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-called-with.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-called-with'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-inline-snapshots.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-inline-snapshots.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-expect-assertions.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-expect-assertions.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-spy-on.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-spy-on.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-inline-snapshots.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-inline-snapshots.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-strict-equal.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-strict-equal.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-spy-on.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-spy-on.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-be-null.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-to-be-null.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-strict-equal.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-strict-equal.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-be-undefined.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-to-be-undefined.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-be-null.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-to-be-null.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-contain.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-to-contain.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-be-undefined.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-to-be-undefined.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-to-have-length.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-to-have-length.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-contain.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-to-contain.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/prefer-todo.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/prefer-todo.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-to-have-length.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-to-have-length.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/require-tothrow-message.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/require-tothrow-message.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/prefer-todo.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/prefer-todo.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/valid-describe.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/valid-describe.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/require-tothrow-message.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/require-tothrow-message.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/valid-expect-in-promise.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/valid-expect-in-promise.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/valid-describe.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/valid-describe.test'>; +declare module 'eslint-plugin-jest/src/rules/__tests__/valid-expect.test.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/__tests__/valid-expect.test'>; } -declare module 'eslint-plugin-jest/rules/__tests__/valid-expect-in-promise.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/valid-expect-in-promise.test'>; +declare module 'eslint-plugin-jest/src/rules/consistent-test-it.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/consistent-test-it'>; } -declare module 'eslint-plugin-jest/rules/__tests__/valid-expect.test.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/__tests__/valid-expect.test'>; +declare module 'eslint-plugin-jest/src/rules/expect-expect.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/expect-expect'>; } -declare module 'eslint-plugin-jest/rules/consistent-test-it.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/consistent-test-it'>; +declare module 'eslint-plugin-jest/src/rules/lowercase-name.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/lowercase-name'>; } -declare module 'eslint-plugin-jest/rules/expect-expect.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/expect-expect'>; +declare module 'eslint-plugin-jest/src/rules/no-alias-methods.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-alias-methods'>; } -declare module 'eslint-plugin-jest/rules/lowercase-name.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/lowercase-name'>; +declare module 'eslint-plugin-jest/src/rules/no-commented-out-tests.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-commented-out-tests'>; } -declare module 'eslint-plugin-jest/rules/no-alias-methods.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-alias-methods'>; +declare module 'eslint-plugin-jest/src/rules/no-disabled-tests.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-disabled-tests'>; } -declare module 'eslint-plugin-jest/rules/no-disabled-tests.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-disabled-tests'>; +declare module 'eslint-plugin-jest/src/rules/no-empty-title.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-empty-title'>; } -declare module 'eslint-plugin-jest/rules/no-empty-title.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-empty-title'>; +declare module 'eslint-plugin-jest/src/rules/no-focused-tests.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-focused-tests'>; } -declare module 'eslint-plugin-jest/rules/no-focused-tests.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-focused-tests'>; +declare module 'eslint-plugin-jest/src/rules/no-hooks.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-hooks'>; } -declare module 'eslint-plugin-jest/rules/no-hooks.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-hooks'>; +declare module 'eslint-plugin-jest/src/rules/no-identical-title.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-identical-title'>; } -declare module 'eslint-plugin-jest/rules/no-identical-title.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-identical-title'>; +declare module 'eslint-plugin-jest/src/rules/no-jasmine-globals.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-jasmine-globals'>; } -declare module 'eslint-plugin-jest/rules/no-jasmine-globals.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-jasmine-globals'>; +declare module 'eslint-plugin-jest/src/rules/no-jest-import.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-jest-import'>; } -declare module 'eslint-plugin-jest/rules/no-jest-import.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-jest-import'>; +declare module 'eslint-plugin-jest/src/rules/no-large-snapshots.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-large-snapshots'>; } -declare module 'eslint-plugin-jest/rules/no-large-snapshots.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-large-snapshots'>; +declare module 'eslint-plugin-jest/src/rules/no-mocks-import.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-mocks-import'>; } -declare module 'eslint-plugin-jest/rules/no-test-callback.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-test-callback'>; +declare module 'eslint-plugin-jest/src/rules/no-test-callback.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-test-callback'>; } -declare module 'eslint-plugin-jest/rules/no-test-prefixes.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-test-prefixes'>; +declare module 'eslint-plugin-jest/src/rules/no-test-prefixes.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-test-prefixes'>; } -declare module 'eslint-plugin-jest/rules/no-test-return-statement.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-test-return-statement'>; +declare module 'eslint-plugin-jest/src/rules/no-test-return-statement.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-test-return-statement'>; } -declare module 'eslint-plugin-jest/rules/no-truthy-falsy.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/no-truthy-falsy'>; +declare module 'eslint-plugin-jest/src/rules/no-truthy-falsy.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/no-truthy-falsy'>; } -declare module 'eslint-plugin-jest/rules/prefer-called-with.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-called-with'>; +declare module 'eslint-plugin-jest/src/rules/prefer-called-with.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-called-with'>; } -declare module 'eslint-plugin-jest/rules/prefer-expect-assertions.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-expect-assertions'>; +declare module 'eslint-plugin-jest/src/rules/prefer-expect-assertions.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-expect-assertions'>; } -declare module 'eslint-plugin-jest/rules/prefer-inline-snapshots.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-inline-snapshots'>; +declare module 'eslint-plugin-jest/src/rules/prefer-inline-snapshots.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-inline-snapshots'>; } -declare module 'eslint-plugin-jest/rules/prefer-spy-on.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-spy-on'>; +declare module 'eslint-plugin-jest/src/rules/prefer-spy-on.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-spy-on'>; } -declare module 'eslint-plugin-jest/rules/prefer-strict-equal.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-strict-equal'>; +declare module 'eslint-plugin-jest/src/rules/prefer-strict-equal.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-strict-equal'>; } -declare module 'eslint-plugin-jest/rules/prefer-to-be-null.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-to-be-null'>; +declare module 'eslint-plugin-jest/src/rules/prefer-to-be-null.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-to-be-null'>; } -declare module 'eslint-plugin-jest/rules/prefer-to-be-undefined.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-to-be-undefined'>; +declare module 'eslint-plugin-jest/src/rules/prefer-to-be-undefined.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-to-be-undefined'>; } -declare module 'eslint-plugin-jest/rules/prefer-to-contain.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-to-contain'>; +declare module 'eslint-plugin-jest/src/rules/prefer-to-contain.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-to-contain'>; } -declare module 'eslint-plugin-jest/rules/prefer-to-have-length.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-to-have-length'>; +declare module 'eslint-plugin-jest/src/rules/prefer-to-have-length.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-to-have-length'>; } -declare module 'eslint-plugin-jest/rules/prefer-todo.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/prefer-todo'>; +declare module 'eslint-plugin-jest/src/rules/prefer-todo.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/prefer-todo'>; } -declare module 'eslint-plugin-jest/rules/require-tothrow-message.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/require-tothrow-message'>; +declare module 'eslint-plugin-jest/src/rules/require-tothrow-message.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/require-tothrow-message'>; } -declare module 'eslint-plugin-jest/rules/util.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/util'>; +declare module 'eslint-plugin-jest/src/rules/util.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/util'>; } -declare module 'eslint-plugin-jest/rules/valid-describe.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/valid-describe'>; +declare module 'eslint-plugin-jest/src/rules/valid-describe.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/valid-describe'>; } -declare module 'eslint-plugin-jest/rules/valid-expect-in-promise.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/valid-expect-in-promise'>; +declare module 'eslint-plugin-jest/src/rules/valid-expect-in-promise.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/valid-expect-in-promise'>; } -declare module 'eslint-plugin-jest/rules/valid-expect.js' { - declare module.exports: $Exports<'eslint-plugin-jest/rules/valid-expect'>; +declare module 'eslint-plugin-jest/src/rules/valid-expect.js' { + declare module.exports: $Exports<'eslint-plugin-jest/src/rules/valid-expect'>; } diff --git a/flow-typed/npm/eslint-plugin-jsx-a11y_vx.x.x.js b/flow-typed/npm/eslint-plugin-jsx-a11y_vx.x.x.js index 1974db4360..63c6bfa413 100644 --- a/flow-typed/npm/eslint-plugin-jsx-a11y_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-jsx-a11y_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 4b6e6cd5ee716eac220207bba62444ef -// flow-typed version: <>/eslint-plugin-jsx-a11y_v^6.2.1/flow_v0.96.0 +// flow-typed signature: 94bc4169988020d57b444a1593337981 +// flow-typed version: <>/eslint-plugin-jsx-a11y_v^6.2.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-plugin-prettier_vx.x.x.js b/flow-typed/npm/eslint-plugin-prettier_vx.x.x.js index 3a47a95018..914b8ac991 100644 --- a/flow-typed/npm/eslint-plugin-prettier_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-prettier_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 9ef4994d0fcef5cadd5cfc403ab1194a -// flow-typed version: <>/eslint-plugin-prettier_v^3.0.1/flow_v0.96.0 +// flow-typed signature: a5a0fc160efb7a281909f6bdf369156e +// flow-typed version: <>/eslint-plugin-prettier_v^3.1.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-plugin-react-hooks_vx.x.x.js b/flow-typed/npm/eslint-plugin-react-hooks_vx.x.x.js index ec4ea5789d..c04bf580fc 100644 --- a/flow-typed/npm/eslint-plugin-react-hooks_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-react-hooks_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 8e71a0b20a9cf88422f4b4195552059f -// flow-typed version: <>/eslint-plugin-react-hooks_v^1.6.0/flow_v0.96.0 +// flow-typed signature: 20e4422b5524a17f9b69a02dd64e2633 +// flow-typed version: <>/eslint-plugin-react-hooks_v^1.6.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/eslint-plugin-react_vx.x.x.js b/flow-typed/npm/eslint-plugin-react_vx.x.x.js index 14ca7a94d1..3a29ee5e03 100644 --- a/flow-typed/npm/eslint-plugin-react_vx.x.x.js +++ b/flow-typed/npm/eslint-plugin-react_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 9ae7426f151e87815c8d11a830649719 -// flow-typed version: <>/eslint-plugin-react_v^7.12.4/flow_v0.96.0 +// flow-typed signature: a80f2454bae3af142ac45eda9d11673f +// flow-typed version: <>/eslint-plugin-react_v^7.14.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -82,6 +82,10 @@ declare module 'eslint-plugin-react/lib/rules/jsx-curly-brace-presence' { declare module.exports: any; } +declare module 'eslint-plugin-react/lib/rules/jsx-curly-newline' { + declare module.exports: any; +} + declare module 'eslint-plugin-react/lib/rules/jsx-curly-spacing' { declare module.exports: any; } @@ -162,6 +166,10 @@ declare module 'eslint-plugin-react/lib/rules/jsx-props-no-multi-spaces' { declare module.exports: any; } +declare module 'eslint-plugin-react/lib/rules/jsx-props-no-spreading' { + declare module.exports: any; +} + declare module 'eslint-plugin-react/lib/rules/jsx-sort-default-props' { declare module.exports: any; } @@ -290,6 +298,10 @@ declare module 'eslint-plugin-react/lib/rules/prefer-es6-class' { declare module.exports: any; } +declare module 'eslint-plugin-react/lib/rules/prefer-read-only-props' { + declare module.exports: any; +} + declare module 'eslint-plugin-react/lib/rules/prefer-stateless-function' { declare module.exports: any; } @@ -326,6 +338,14 @@ declare module 'eslint-plugin-react/lib/rules/sort-prop-types' { declare module.exports: any; } +declare module 'eslint-plugin-react/lib/rules/state-in-constructor' { + declare module.exports: any; +} + +declare module 'eslint-plugin-react/lib/rules/static-property-placement' { + declare module.exports: any; +} + declare module 'eslint-plugin-react/lib/rules/style-prop-object' { declare module.exports: any; } @@ -366,6 +386,10 @@ declare module 'eslint-plugin-react/lib/util/jsx' { declare module.exports: any; } +declare module 'eslint-plugin-react/lib/util/linkComponents' { + declare module.exports: any; +} + declare module 'eslint-plugin-react/lib/util/log' { declare module.exports: any; } @@ -454,6 +478,9 @@ declare module 'eslint-plugin-react/lib/rules/jsx-closing-tag-location.js' { declare module 'eslint-plugin-react/lib/rules/jsx-curly-brace-presence.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-curly-brace-presence'>; } +declare module 'eslint-plugin-react/lib/rules/jsx-curly-newline.js' { + declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-curly-newline'>; +} declare module 'eslint-plugin-react/lib/rules/jsx-curly-spacing.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-curly-spacing'>; } @@ -514,6 +541,9 @@ declare module 'eslint-plugin-react/lib/rules/jsx-pascal-case.js' { declare module 'eslint-plugin-react/lib/rules/jsx-props-no-multi-spaces.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-props-no-multi-spaces'>; } +declare module 'eslint-plugin-react/lib/rules/jsx-props-no-spreading.js' { + declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-props-no-spreading'>; +} declare module 'eslint-plugin-react/lib/rules/jsx-sort-default-props.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/jsx-sort-default-props'>; } @@ -610,6 +640,9 @@ declare module 'eslint-plugin-react/lib/rules/no-will-update-set-state.js' { declare module 'eslint-plugin-react/lib/rules/prefer-es6-class.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/prefer-es6-class'>; } +declare module 'eslint-plugin-react/lib/rules/prefer-read-only-props.js' { + declare module.exports: $Exports<'eslint-plugin-react/lib/rules/prefer-read-only-props'>; +} declare module 'eslint-plugin-react/lib/rules/prefer-stateless-function.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/prefer-stateless-function'>; } @@ -637,6 +670,12 @@ declare module 'eslint-plugin-react/lib/rules/sort-comp.js' { declare module 'eslint-plugin-react/lib/rules/sort-prop-types.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/sort-prop-types'>; } +declare module 'eslint-plugin-react/lib/rules/state-in-constructor.js' { + declare module.exports: $Exports<'eslint-plugin-react/lib/rules/state-in-constructor'>; +} +declare module 'eslint-plugin-react/lib/rules/static-property-placement.js' { + declare module.exports: $Exports<'eslint-plugin-react/lib/rules/static-property-placement'>; +} declare module 'eslint-plugin-react/lib/rules/style-prop-object.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/rules/style-prop-object'>; } @@ -667,6 +706,9 @@ declare module 'eslint-plugin-react/lib/util/getTokenBeforeClosingBracket.js' { declare module 'eslint-plugin-react/lib/util/jsx.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/util/jsx'>; } +declare module 'eslint-plugin-react/lib/util/linkComponents.js' { + declare module.exports: $Exports<'eslint-plugin-react/lib/util/linkComponents'>; +} declare module 'eslint-plugin-react/lib/util/log.js' { declare module.exports: $Exports<'eslint-plugin-react/lib/util/log'>; } diff --git a/flow-typed/npm/eslint_vx.x.x.js b/flow-typed/npm/eslint_vx.x.x.js index c013f7d476..41d56401b9 100644 --- a/flow-typed/npm/eslint_vx.x.x.js +++ b/flow-typed/npm/eslint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: a6cbad9ec0f33677631899a6daf10c26 -// flow-typed version: <>/eslint_v^5.16.0/flow_v0.96.0 +// flow-typed signature: ee6c186ff9a21e8b4ebc24b311eaa75a +// flow-typed version: <>/eslint_v^6.0.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -50,143 +50,223 @@ declare module 'eslint/lib/api' { declare module.exports: any; } -declare module 'eslint/lib/built-in-rules-index' { +declare module 'eslint/lib/cli-engine/cascading-config-array-factory' { declare module.exports: any; } -declare module 'eslint/lib/cli-engine' { +declare module 'eslint/lib/cli-engine/cli-engine' { declare module.exports: any; } -declare module 'eslint/lib/cli' { +declare module 'eslint/lib/cli-engine/config-array-factory' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/config-array/config-array' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/config-array/config-dependency' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/config-array/extracted-config' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/config-array/index' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/config-array/override-tester' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/file-enumerator' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/checkstyle' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/codeframe' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/compact' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/html' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/jslint-xml' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/json-with-metadata' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/json' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/junit' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/stylish' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/table' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/tap' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/unix' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/formatters/visualstudio' { + declare module.exports: any; +} + +declare module 'eslint/lib/cli-engine/hash' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/code-path-analyzer' { +declare module 'eslint/lib/cli-engine/ignored-paths' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/code-path-segment' { +declare module 'eslint/lib/cli-engine/index' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/code-path-state' { +declare module 'eslint/lib/cli-engine/lint-result-cache' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/code-path' { +declare module 'eslint/lib/cli-engine/load-rules' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/debug-helpers' { +declare module 'eslint/lib/cli-engine/naming' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/fork-context' { +declare module 'eslint/lib/cli-engine/xml-escape' { declare module.exports: any; } -declare module 'eslint/lib/code-path-analysis/id-generator' { +declare module 'eslint/lib/cli' { declare module.exports: any; } -declare module 'eslint/lib/config' { +declare module 'eslint/lib/init/autoconfig' { declare module.exports: any; } -declare module 'eslint/lib/config/autoconfig' { +declare module 'eslint/lib/init/config-file' { declare module.exports: any; } -declare module 'eslint/lib/config/config-cache' { +declare module 'eslint/lib/init/config-initializer' { declare module.exports: any; } -declare module 'eslint/lib/config/config-file' { +declare module 'eslint/lib/init/config-rule' { declare module.exports: any; } -declare module 'eslint/lib/config/config-initializer' { +declare module 'eslint/lib/init/npm-utils' { declare module.exports: any; } -declare module 'eslint/lib/config/config-ops' { +declare module 'eslint/lib/init/source-code-utils' { declare module.exports: any; } -declare module 'eslint/lib/config/config-rule' { +declare module 'eslint/lib/linter/apply-disable-directives' { declare module.exports: any; } -declare module 'eslint/lib/config/config-validator' { +declare module 'eslint/lib/linter/code-path-analysis/code-path-analyzer' { declare module.exports: any; } -declare module 'eslint/lib/config/environments' { +declare module 'eslint/lib/linter/code-path-analysis/code-path-segment' { declare module.exports: any; } -declare module 'eslint/lib/config/plugins' { +declare module 'eslint/lib/linter/code-path-analysis/code-path-state' { declare module.exports: any; } -declare module 'eslint/lib/formatters/checkstyle' { +declare module 'eslint/lib/linter/code-path-analysis/code-path' { declare module.exports: any; } -declare module 'eslint/lib/formatters/codeframe' { +declare module 'eslint/lib/linter/code-path-analysis/debug-helpers' { declare module.exports: any; } -declare module 'eslint/lib/formatters/compact' { +declare module 'eslint/lib/linter/code-path-analysis/fork-context' { declare module.exports: any; } -declare module 'eslint/lib/formatters/html' { +declare module 'eslint/lib/linter/code-path-analysis/id-generator' { declare module.exports: any; } -declare module 'eslint/lib/formatters/jslint-xml' { +declare module 'eslint/lib/linter/config-comment-parser' { declare module.exports: any; } -declare module 'eslint/lib/formatters/json-with-metadata' { +declare module 'eslint/lib/linter/index' { declare module.exports: any; } -declare module 'eslint/lib/formatters/json' { +declare module 'eslint/lib/linter/interpolate' { declare module.exports: any; } -declare module 'eslint/lib/formatters/junit' { +declare module 'eslint/lib/linter/linter' { declare module.exports: any; } -declare module 'eslint/lib/formatters/stylish' { +declare module 'eslint/lib/linter/node-event-generator' { declare module.exports: any; } -declare module 'eslint/lib/formatters/table' { +declare module 'eslint/lib/linter/report-translator' { declare module.exports: any; } -declare module 'eslint/lib/formatters/tap' { +declare module 'eslint/lib/linter/rule-fixer' { declare module.exports: any; } -declare module 'eslint/lib/formatters/unix' { +declare module 'eslint/lib/linter/rules' { declare module.exports: any; } -declare module 'eslint/lib/formatters/visualstudio' { +declare module 'eslint/lib/linter/safe-emitter' { declare module.exports: any; } -declare module 'eslint/lib/linter' { +declare module 'eslint/lib/linter/source-code-fixer' { declare module.exports: any; } -declare module 'eslint/lib/load-rules' { +declare module 'eslint/lib/linter/timing' { declare module.exports: any; } @@ -194,7 +274,11 @@ declare module 'eslint/lib/options' { declare module.exports: any; } -declare module 'eslint/lib/rules' { +declare module 'eslint/lib/rule-tester/index' { + declare module.exports: any; +} + +declare module 'eslint/lib/rule-tester/rule-tester' { declare module.exports: any; } @@ -382,6 +466,10 @@ declare module 'eslint/lib/rules/indent' { declare module.exports: any; } +declare module 'eslint/lib/rules/index' { + declare module.exports: any; +} + declare module 'eslint/lib/rules/init-declarations' { declare module.exports: any; } @@ -1234,223 +1322,163 @@ declare module 'eslint/lib/rules/use-isnan' { declare module.exports: any; } -declare module 'eslint/lib/rules/valid-jsdoc' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/valid-typeof' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/vars-on-top' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/wrap-iife' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/wrap-regex' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/yield-star-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/yoda' { - declare module.exports: any; -} - -declare module 'eslint/lib/testers/rule-tester' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/backward-token-comment-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/backward-token-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/cursors' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/decorative-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/filter-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/forward-token-comment-cursor' { +declare module 'eslint/lib/rules/utils/ast-utils' { declare module.exports: any; } -declare module 'eslint/lib/token-store/forward-token-cursor' { +declare module 'eslint/lib/rules/utils/fix-tracker' { declare module.exports: any; } -declare module 'eslint/lib/token-store/index' { +declare module 'eslint/lib/rules/utils/keywords' { declare module.exports: any; } -declare module 'eslint/lib/token-store/limit-cursor' { +declare module 'eslint/lib/rules/utils/lazy-loading-rule-map' { declare module.exports: any; } -declare module 'eslint/lib/token-store/padded-token-cursor' { +declare module 'eslint/lib/rules/utils/patterns/letters' { declare module.exports: any; } -declare module 'eslint/lib/token-store/skip-cursor' { +declare module 'eslint/lib/rules/utils/unicode/index' { declare module.exports: any; } -declare module 'eslint/lib/token-store/utils' { +declare module 'eslint/lib/rules/utils/unicode/is-combining-character' { declare module.exports: any; } -declare module 'eslint/lib/util/ajv' { +declare module 'eslint/lib/rules/utils/unicode/is-emoji-modifier' { declare module.exports: any; } -declare module 'eslint/lib/util/apply-disable-directives' { +declare module 'eslint/lib/rules/utils/unicode/is-regional-indicator-symbol' { declare module.exports: any; } -declare module 'eslint/lib/util/ast-utils' { +declare module 'eslint/lib/rules/utils/unicode/is-surrogate-pair' { declare module.exports: any; } -declare module 'eslint/lib/util/config-comment-parser' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/file-finder' { +declare module 'eslint/lib/rules/valid-jsdoc' { declare module.exports: any; } -declare module 'eslint/lib/util/fix-tracker' { +declare module 'eslint/lib/rules/valid-typeof' { declare module.exports: any; } -declare module 'eslint/lib/util/glob-utils' { +declare module 'eslint/lib/rules/vars-on-top' { declare module.exports: any; } -declare module 'eslint/lib/util/glob' { +declare module 'eslint/lib/rules/wrap-iife' { declare module.exports: any; } -declare module 'eslint/lib/util/hash' { +declare module 'eslint/lib/rules/wrap-regex' { declare module.exports: any; } -declare module 'eslint/lib/util/ignored-paths' { +declare module 'eslint/lib/rules/yield-star-spacing' { declare module.exports: any; } -declare module 'eslint/lib/util/interpolate' { +declare module 'eslint/lib/rules/yoda' { declare module.exports: any; } -declare module 'eslint/lib/util/keywords' { +declare module 'eslint/lib/shared/ajv' { declare module.exports: any; } -declare module 'eslint/lib/util/lint-result-cache' { +declare module 'eslint/lib/shared/ast-utils' { declare module.exports: any; } -declare module 'eslint/lib/util/logging' { +declare module 'eslint/lib/shared/config-ops' { declare module.exports: any; } -declare module 'eslint/lib/util/module-resolver' { +declare module 'eslint/lib/shared/config-validator' { declare module.exports: any; } -declare module 'eslint/lib/util/naming' { +declare module 'eslint/lib/shared/logging' { declare module.exports: any; } -declare module 'eslint/lib/util/node-event-generator' { +declare module 'eslint/lib/shared/relative-module-resolver' { declare module.exports: any; } -declare module 'eslint/lib/util/npm-utils' { +declare module 'eslint/lib/shared/traverser' { declare module.exports: any; } -declare module 'eslint/lib/util/path-utils' { +declare module 'eslint/lib/shared/types' { declare module.exports: any; } -declare module 'eslint/lib/util/patterns/letters' { +declare module 'eslint/lib/source-code/index' { declare module.exports: any; } -declare module 'eslint/lib/util/report-translator' { +declare module 'eslint/lib/source-code/source-code' { declare module.exports: any; } -declare module 'eslint/lib/util/rule-fixer' { +declare module 'eslint/lib/source-code/token-store/backward-token-comment-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/safe-emitter' { +declare module 'eslint/lib/source-code/token-store/backward-token-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/source-code-fixer' { +declare module 'eslint/lib/source-code/token-store/cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/source-code-utils' { +declare module 'eslint/lib/source-code/token-store/cursors' { declare module.exports: any; } -declare module 'eslint/lib/util/source-code' { +declare module 'eslint/lib/source-code/token-store/decorative-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/timing' { +declare module 'eslint/lib/source-code/token-store/filter-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/traverser' { +declare module 'eslint/lib/source-code/token-store/forward-token-comment-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/unicode/index' { +declare module 'eslint/lib/source-code/token-store/forward-token-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/unicode/is-combining-character' { +declare module 'eslint/lib/source-code/token-store/index' { declare module.exports: any; } -declare module 'eslint/lib/util/unicode/is-emoji-modifier' { +declare module 'eslint/lib/source-code/token-store/limit-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/unicode/is-regional-indicator-symbol' { +declare module 'eslint/lib/source-code/token-store/padded-token-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/unicode/is-surrogate-pair' { +declare module 'eslint/lib/source-code/token-store/skip-cursor' { declare module.exports: any; } -declare module 'eslint/lib/util/xml-escape' { +declare module 'eslint/lib/source-code/token-store/utils' { declare module.exports: any; } @@ -1476,116 +1504,179 @@ declare module 'eslint/conf/eslint-recommended.js' { declare module 'eslint/lib/api.js' { declare module.exports: $Exports<'eslint/lib/api'>; } -declare module 'eslint/lib/built-in-rules-index.js' { - declare module.exports: $Exports<'eslint/lib/built-in-rules-index'>; +declare module 'eslint/lib/cli-engine/cascading-config-array-factory.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/cascading-config-array-factory'>; } -declare module 'eslint/lib/cli-engine.js' { - declare module.exports: $Exports<'eslint/lib/cli-engine'>; +declare module 'eslint/lib/cli-engine/cli-engine.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/cli-engine'>; } -declare module 'eslint/lib/cli.js' { - declare module.exports: $Exports<'eslint/lib/cli'>; +declare module 'eslint/lib/cli-engine/config-array-factory.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/config-array-factory'>; +} +declare module 'eslint/lib/cli-engine/config-array/config-array.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/config-array/config-array'>; +} +declare module 'eslint/lib/cli-engine/config-array/config-dependency.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/config-array/config-dependency'>; +} +declare module 'eslint/lib/cli-engine/config-array/extracted-config.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/config-array/extracted-config'>; +} +declare module 'eslint/lib/cli-engine/config-array/index.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/config-array/index'>; +} +declare module 'eslint/lib/cli-engine/config-array/override-tester.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/config-array/override-tester'>; +} +declare module 'eslint/lib/cli-engine/file-enumerator.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/file-enumerator'>; +} +declare module 'eslint/lib/cli-engine/formatters/checkstyle.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/checkstyle'>; +} +declare module 'eslint/lib/cli-engine/formatters/codeframe.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/codeframe'>; +} +declare module 'eslint/lib/cli-engine/formatters/compact.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/compact'>; +} +declare module 'eslint/lib/cli-engine/formatters/html.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/html'>; +} +declare module 'eslint/lib/cli-engine/formatters/jslint-xml.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/jslint-xml'>; +} +declare module 'eslint/lib/cli-engine/formatters/json-with-metadata.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/json-with-metadata'>; } -declare module 'eslint/lib/code-path-analysis/code-path-analyzer.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path-analyzer'>; +declare module 'eslint/lib/cli-engine/formatters/json.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/json'>; } -declare module 'eslint/lib/code-path-analysis/code-path-segment.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path-segment'>; +declare module 'eslint/lib/cli-engine/formatters/junit.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/junit'>; } -declare module 'eslint/lib/code-path-analysis/code-path-state.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path-state'>; +declare module 'eslint/lib/cli-engine/formatters/stylish.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/stylish'>; } -declare module 'eslint/lib/code-path-analysis/code-path.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path'>; +declare module 'eslint/lib/cli-engine/formatters/table.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/table'>; } -declare module 'eslint/lib/code-path-analysis/debug-helpers.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/debug-helpers'>; +declare module 'eslint/lib/cli-engine/formatters/tap.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/tap'>; } -declare module 'eslint/lib/code-path-analysis/fork-context.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/fork-context'>; +declare module 'eslint/lib/cli-engine/formatters/unix.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/unix'>; } -declare module 'eslint/lib/code-path-analysis/id-generator.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/id-generator'>; +declare module 'eslint/lib/cli-engine/formatters/visualstudio.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/formatters/visualstudio'>; } -declare module 'eslint/lib/config.js' { - declare module.exports: $Exports<'eslint/lib/config'>; +declare module 'eslint/lib/cli-engine/hash.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/hash'>; } -declare module 'eslint/lib/config/autoconfig.js' { - declare module.exports: $Exports<'eslint/lib/config/autoconfig'>; +declare module 'eslint/lib/cli-engine/ignored-paths.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/ignored-paths'>; } -declare module 'eslint/lib/config/config-cache.js' { - declare module.exports: $Exports<'eslint/lib/config/config-cache'>; +declare module 'eslint/lib/cli-engine/index.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/index'>; } -declare module 'eslint/lib/config/config-file.js' { - declare module.exports: $Exports<'eslint/lib/config/config-file'>; +declare module 'eslint/lib/cli-engine/lint-result-cache.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/lint-result-cache'>; } -declare module 'eslint/lib/config/config-initializer.js' { - declare module.exports: $Exports<'eslint/lib/config/config-initializer'>; +declare module 'eslint/lib/cli-engine/load-rules.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/load-rules'>; } -declare module 'eslint/lib/config/config-ops.js' { - declare module.exports: $Exports<'eslint/lib/config/config-ops'>; +declare module 'eslint/lib/cli-engine/naming.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/naming'>; } -declare module 'eslint/lib/config/config-rule.js' { - declare module.exports: $Exports<'eslint/lib/config/config-rule'>; +declare module 'eslint/lib/cli-engine/xml-escape.js' { + declare module.exports: $Exports<'eslint/lib/cli-engine/xml-escape'>; } -declare module 'eslint/lib/config/config-validator.js' { - declare module.exports: $Exports<'eslint/lib/config/config-validator'>; +declare module 'eslint/lib/cli.js' { + declare module.exports: $Exports<'eslint/lib/cli'>; +} +declare module 'eslint/lib/init/autoconfig.js' { + declare module.exports: $Exports<'eslint/lib/init/autoconfig'>; +} +declare module 'eslint/lib/init/config-file.js' { + declare module.exports: $Exports<'eslint/lib/init/config-file'>; +} +declare module 'eslint/lib/init/config-initializer.js' { + declare module.exports: $Exports<'eslint/lib/init/config-initializer'>; +} +declare module 'eslint/lib/init/config-rule.js' { + declare module.exports: $Exports<'eslint/lib/init/config-rule'>; } -declare module 'eslint/lib/config/environments.js' { - declare module.exports: $Exports<'eslint/lib/config/environments'>; +declare module 'eslint/lib/init/npm-utils.js' { + declare module.exports: $Exports<'eslint/lib/init/npm-utils'>; } -declare module 'eslint/lib/config/plugins.js' { - declare module.exports: $Exports<'eslint/lib/config/plugins'>; +declare module 'eslint/lib/init/source-code-utils.js' { + declare module.exports: $Exports<'eslint/lib/init/source-code-utils'>; } -declare module 'eslint/lib/formatters/checkstyle.js' { - declare module.exports: $Exports<'eslint/lib/formatters/checkstyle'>; +declare module 'eslint/lib/linter/apply-disable-directives.js' { + declare module.exports: $Exports<'eslint/lib/linter/apply-disable-directives'>; } -declare module 'eslint/lib/formatters/codeframe.js' { - declare module.exports: $Exports<'eslint/lib/formatters/codeframe'>; +declare module 'eslint/lib/linter/code-path-analysis/code-path-analyzer.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/code-path-analyzer'>; } -declare module 'eslint/lib/formatters/compact.js' { - declare module.exports: $Exports<'eslint/lib/formatters/compact'>; +declare module 'eslint/lib/linter/code-path-analysis/code-path-segment.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/code-path-segment'>; } -declare module 'eslint/lib/formatters/html.js' { - declare module.exports: $Exports<'eslint/lib/formatters/html'>; +declare module 'eslint/lib/linter/code-path-analysis/code-path-state.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/code-path-state'>; } -declare module 'eslint/lib/formatters/jslint-xml.js' { - declare module.exports: $Exports<'eslint/lib/formatters/jslint-xml'>; +declare module 'eslint/lib/linter/code-path-analysis/code-path.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/code-path'>; } -declare module 'eslint/lib/formatters/json-with-metadata.js' { - declare module.exports: $Exports<'eslint/lib/formatters/json-with-metadata'>; +declare module 'eslint/lib/linter/code-path-analysis/debug-helpers.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/debug-helpers'>; } -declare module 'eslint/lib/formatters/json.js' { - declare module.exports: $Exports<'eslint/lib/formatters/json'>; +declare module 'eslint/lib/linter/code-path-analysis/fork-context.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/fork-context'>; } -declare module 'eslint/lib/formatters/junit.js' { - declare module.exports: $Exports<'eslint/lib/formatters/junit'>; +declare module 'eslint/lib/linter/code-path-analysis/id-generator.js' { + declare module.exports: $Exports<'eslint/lib/linter/code-path-analysis/id-generator'>; } -declare module 'eslint/lib/formatters/stylish.js' { - declare module.exports: $Exports<'eslint/lib/formatters/stylish'>; +declare module 'eslint/lib/linter/config-comment-parser.js' { + declare module.exports: $Exports<'eslint/lib/linter/config-comment-parser'>; } -declare module 'eslint/lib/formatters/table.js' { - declare module.exports: $Exports<'eslint/lib/formatters/table'>; +declare module 'eslint/lib/linter/index.js' { + declare module.exports: $Exports<'eslint/lib/linter/index'>; } -declare module 'eslint/lib/formatters/tap.js' { - declare module.exports: $Exports<'eslint/lib/formatters/tap'>; +declare module 'eslint/lib/linter/interpolate.js' { + declare module.exports: $Exports<'eslint/lib/linter/interpolate'>; } -declare module 'eslint/lib/formatters/unix.js' { - declare module.exports: $Exports<'eslint/lib/formatters/unix'>; +declare module 'eslint/lib/linter/linter.js' { + declare module.exports: $Exports<'eslint/lib/linter/linter'>; } -declare module 'eslint/lib/formatters/visualstudio.js' { - declare module.exports: $Exports<'eslint/lib/formatters/visualstudio'>; +declare module 'eslint/lib/linter/node-event-generator.js' { + declare module.exports: $Exports<'eslint/lib/linter/node-event-generator'>; } -declare module 'eslint/lib/linter.js' { - declare module.exports: $Exports<'eslint/lib/linter'>; +declare module 'eslint/lib/linter/report-translator.js' { + declare module.exports: $Exports<'eslint/lib/linter/report-translator'>; } -declare module 'eslint/lib/load-rules.js' { - declare module.exports: $Exports<'eslint/lib/load-rules'>; +declare module 'eslint/lib/linter/rule-fixer.js' { + declare module.exports: $Exports<'eslint/lib/linter/rule-fixer'>; +} +declare module 'eslint/lib/linter/rules.js' { + declare module.exports: $Exports<'eslint/lib/linter/rules'>; +} +declare module 'eslint/lib/linter/safe-emitter.js' { + declare module.exports: $Exports<'eslint/lib/linter/safe-emitter'>; +} +declare module 'eslint/lib/linter/source-code-fixer.js' { + declare module.exports: $Exports<'eslint/lib/linter/source-code-fixer'>; +} +declare module 'eslint/lib/linter/timing.js' { + declare module.exports: $Exports<'eslint/lib/linter/timing'>; } declare module 'eslint/lib/options.js' { declare module.exports: $Exports<'eslint/lib/options'>; } -declare module 'eslint/lib/rules.js' { - declare module.exports: $Exports<'eslint/lib/rules'>; +declare module 'eslint/lib/rule-tester/index.js' { + declare module.exports: $Exports<'eslint/lib/rule-tester/index'>; +} +declare module 'eslint/lib/rule-tester/rule-tester.js' { + declare module.exports: $Exports<'eslint/lib/rule-tester/rule-tester'>; } declare module 'eslint/lib/rules/accessor-pairs.js' { declare module.exports: $Exports<'eslint/lib/rules/accessor-pairs'>; @@ -1725,6 +1816,9 @@ declare module 'eslint/lib/rules/indent-legacy.js' { declare module 'eslint/lib/rules/indent.js' { declare module.exports: $Exports<'eslint/lib/rules/indent'>; } +declare module 'eslint/lib/rules/index.js' { + declare module.exports: $Exports<'eslint/lib/rules/index'>; +} declare module 'eslint/lib/rules/init-declarations.js' { declare module.exports: $Exports<'eslint/lib/rules/init-declarations'>; } @@ -2364,6 +2458,36 @@ declare module 'eslint/lib/rules/unicode-bom.js' { declare module 'eslint/lib/rules/use-isnan.js' { declare module.exports: $Exports<'eslint/lib/rules/use-isnan'>; } +declare module 'eslint/lib/rules/utils/ast-utils.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/ast-utils'>; +} +declare module 'eslint/lib/rules/utils/fix-tracker.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/fix-tracker'>; +} +declare module 'eslint/lib/rules/utils/keywords.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/keywords'>; +} +declare module 'eslint/lib/rules/utils/lazy-loading-rule-map.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/lazy-loading-rule-map'>; +} +declare module 'eslint/lib/rules/utils/patterns/letters.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/patterns/letters'>; +} +declare module 'eslint/lib/rules/utils/unicode/index.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/unicode/index'>; +} +declare module 'eslint/lib/rules/utils/unicode/is-combining-character.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/unicode/is-combining-character'>; +} +declare module 'eslint/lib/rules/utils/unicode/is-emoji-modifier.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/unicode/is-emoji-modifier'>; +} +declare module 'eslint/lib/rules/utils/unicode/is-regional-indicator-symbol.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/unicode/is-regional-indicator-symbol'>; +} +declare module 'eslint/lib/rules/utils/unicode/is-surrogate-pair.js' { + declare module.exports: $Exports<'eslint/lib/rules/utils/unicode/is-surrogate-pair'>; +} declare module 'eslint/lib/rules/valid-jsdoc.js' { declare module.exports: $Exports<'eslint/lib/rules/valid-jsdoc'>; } @@ -2385,147 +2509,72 @@ declare module 'eslint/lib/rules/yield-star-spacing.js' { declare module 'eslint/lib/rules/yoda.js' { declare module.exports: $Exports<'eslint/lib/rules/yoda'>; } -declare module 'eslint/lib/testers/rule-tester.js' { - declare module.exports: $Exports<'eslint/lib/testers/rule-tester'>; -} -declare module 'eslint/lib/token-store/backward-token-comment-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/backward-token-comment-cursor'>; -} -declare module 'eslint/lib/token-store/backward-token-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/backward-token-cursor'>; -} -declare module 'eslint/lib/token-store/cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/cursor'>; -} -declare module 'eslint/lib/token-store/cursors.js' { - declare module.exports: $Exports<'eslint/lib/token-store/cursors'>; -} -declare module 'eslint/lib/token-store/decorative-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/decorative-cursor'>; -} -declare module 'eslint/lib/token-store/filter-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/filter-cursor'>; -} -declare module 'eslint/lib/token-store/forward-token-comment-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/forward-token-comment-cursor'>; -} -declare module 'eslint/lib/token-store/forward-token-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/forward-token-cursor'>; -} -declare module 'eslint/lib/token-store/index.js' { - declare module.exports: $Exports<'eslint/lib/token-store/index'>; -} -declare module 'eslint/lib/token-store/limit-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/limit-cursor'>; -} -declare module 'eslint/lib/token-store/padded-token-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/padded-token-cursor'>; -} -declare module 'eslint/lib/token-store/skip-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/skip-cursor'>; -} -declare module 'eslint/lib/token-store/utils.js' { - declare module.exports: $Exports<'eslint/lib/token-store/utils'>; -} -declare module 'eslint/lib/util/ajv.js' { - declare module.exports: $Exports<'eslint/lib/util/ajv'>; -} -declare module 'eslint/lib/util/apply-disable-directives.js' { - declare module.exports: $Exports<'eslint/lib/util/apply-disable-directives'>; -} -declare module 'eslint/lib/util/ast-utils.js' { - declare module.exports: $Exports<'eslint/lib/util/ast-utils'>; -} -declare module 'eslint/lib/util/config-comment-parser.js' { - declare module.exports: $Exports<'eslint/lib/util/config-comment-parser'>; -} -declare module 'eslint/lib/util/file-finder.js' { - declare module.exports: $Exports<'eslint/lib/util/file-finder'>; -} -declare module 'eslint/lib/util/fix-tracker.js' { - declare module.exports: $Exports<'eslint/lib/util/fix-tracker'>; -} -declare module 'eslint/lib/util/glob-utils.js' { - declare module.exports: $Exports<'eslint/lib/util/glob-utils'>; -} -declare module 'eslint/lib/util/glob.js' { - declare module.exports: $Exports<'eslint/lib/util/glob'>; -} -declare module 'eslint/lib/util/hash.js' { - declare module.exports: $Exports<'eslint/lib/util/hash'>; -} -declare module 'eslint/lib/util/ignored-paths.js' { - declare module.exports: $Exports<'eslint/lib/util/ignored-paths'>; -} -declare module 'eslint/lib/util/interpolate.js' { - declare module.exports: $Exports<'eslint/lib/util/interpolate'>; -} -declare module 'eslint/lib/util/keywords.js' { - declare module.exports: $Exports<'eslint/lib/util/keywords'>; +declare module 'eslint/lib/shared/ajv.js' { + declare module.exports: $Exports<'eslint/lib/shared/ajv'>; } -declare module 'eslint/lib/util/lint-result-cache.js' { - declare module.exports: $Exports<'eslint/lib/util/lint-result-cache'>; +declare module 'eslint/lib/shared/ast-utils.js' { + declare module.exports: $Exports<'eslint/lib/shared/ast-utils'>; } -declare module 'eslint/lib/util/logging.js' { - declare module.exports: $Exports<'eslint/lib/util/logging'>; +declare module 'eslint/lib/shared/config-ops.js' { + declare module.exports: $Exports<'eslint/lib/shared/config-ops'>; } -declare module 'eslint/lib/util/module-resolver.js' { - declare module.exports: $Exports<'eslint/lib/util/module-resolver'>; +declare module 'eslint/lib/shared/config-validator.js' { + declare module.exports: $Exports<'eslint/lib/shared/config-validator'>; } -declare module 'eslint/lib/util/naming.js' { - declare module.exports: $Exports<'eslint/lib/util/naming'>; +declare module 'eslint/lib/shared/logging.js' { + declare module.exports: $Exports<'eslint/lib/shared/logging'>; } -declare module 'eslint/lib/util/node-event-generator.js' { - declare module.exports: $Exports<'eslint/lib/util/node-event-generator'>; +declare module 'eslint/lib/shared/relative-module-resolver.js' { + declare module.exports: $Exports<'eslint/lib/shared/relative-module-resolver'>; } -declare module 'eslint/lib/util/npm-utils.js' { - declare module.exports: $Exports<'eslint/lib/util/npm-utils'>; +declare module 'eslint/lib/shared/traverser.js' { + declare module.exports: $Exports<'eslint/lib/shared/traverser'>; } -declare module 'eslint/lib/util/path-utils.js' { - declare module.exports: $Exports<'eslint/lib/util/path-utils'>; +declare module 'eslint/lib/shared/types.js' { + declare module.exports: $Exports<'eslint/lib/shared/types'>; } -declare module 'eslint/lib/util/patterns/letters.js' { - declare module.exports: $Exports<'eslint/lib/util/patterns/letters'>; +declare module 'eslint/lib/source-code/index.js' { + declare module.exports: $Exports<'eslint/lib/source-code/index'>; } -declare module 'eslint/lib/util/report-translator.js' { - declare module.exports: $Exports<'eslint/lib/util/report-translator'>; +declare module 'eslint/lib/source-code/source-code.js' { + declare module.exports: $Exports<'eslint/lib/source-code/source-code'>; } -declare module 'eslint/lib/util/rule-fixer.js' { - declare module.exports: $Exports<'eslint/lib/util/rule-fixer'>; +declare module 'eslint/lib/source-code/token-store/backward-token-comment-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/backward-token-comment-cursor'>; } -declare module 'eslint/lib/util/safe-emitter.js' { - declare module.exports: $Exports<'eslint/lib/util/safe-emitter'>; +declare module 'eslint/lib/source-code/token-store/backward-token-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/backward-token-cursor'>; } -declare module 'eslint/lib/util/source-code-fixer.js' { - declare module.exports: $Exports<'eslint/lib/util/source-code-fixer'>; +declare module 'eslint/lib/source-code/token-store/cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/cursor'>; } -declare module 'eslint/lib/util/source-code-utils.js' { - declare module.exports: $Exports<'eslint/lib/util/source-code-utils'>; +declare module 'eslint/lib/source-code/token-store/cursors.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/cursors'>; } -declare module 'eslint/lib/util/source-code.js' { - declare module.exports: $Exports<'eslint/lib/util/source-code'>; +declare module 'eslint/lib/source-code/token-store/decorative-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/decorative-cursor'>; } -declare module 'eslint/lib/util/timing.js' { - declare module.exports: $Exports<'eslint/lib/util/timing'>; +declare module 'eslint/lib/source-code/token-store/filter-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/filter-cursor'>; } -declare module 'eslint/lib/util/traverser.js' { - declare module.exports: $Exports<'eslint/lib/util/traverser'>; +declare module 'eslint/lib/source-code/token-store/forward-token-comment-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/forward-token-comment-cursor'>; } -declare module 'eslint/lib/util/unicode/index.js' { - declare module.exports: $Exports<'eslint/lib/util/unicode/index'>; +declare module 'eslint/lib/source-code/token-store/forward-token-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/forward-token-cursor'>; } -declare module 'eslint/lib/util/unicode/is-combining-character.js' { - declare module.exports: $Exports<'eslint/lib/util/unicode/is-combining-character'>; +declare module 'eslint/lib/source-code/token-store/index.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/index'>; } -declare module 'eslint/lib/util/unicode/is-emoji-modifier.js' { - declare module.exports: $Exports<'eslint/lib/util/unicode/is-emoji-modifier'>; +declare module 'eslint/lib/source-code/token-store/limit-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/limit-cursor'>; } -declare module 'eslint/lib/util/unicode/is-regional-indicator-symbol.js' { - declare module.exports: $Exports<'eslint/lib/util/unicode/is-regional-indicator-symbol'>; +declare module 'eslint/lib/source-code/token-store/padded-token-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/padded-token-cursor'>; } -declare module 'eslint/lib/util/unicode/is-surrogate-pair.js' { - declare module.exports: $Exports<'eslint/lib/util/unicode/is-surrogate-pair'>; +declare module 'eslint/lib/source-code/token-store/skip-cursor.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/skip-cursor'>; } -declare module 'eslint/lib/util/xml-escape.js' { - declare module.exports: $Exports<'eslint/lib/util/xml-escape'>; +declare module 'eslint/lib/source-code/token-store/utils.js' { + declare module.exports: $Exports<'eslint/lib/source-code/token-store/utils'>; } diff --git a/flow-typed/npm/fs-extra_v7.x.x.js b/flow-typed/npm/fs-extra_v7.x.x.js deleted file mode 100644 index 151fa81f2f..0000000000 --- a/flow-typed/npm/fs-extra_v7.x.x.js +++ /dev/null @@ -1,755 +0,0 @@ -// flow-typed signature: 736900083d1f92195f5af04fec4c5eb7 -// flow-typed version: 564b2e9f7a/fs-extra_v7.x.x/flow_vx.x.x - -declare module "fs-extra" { - import type { Stats, ReadStream, WriteStream } from "fs"; - - declare export type SymlinkType = "dir" | "file"; - declare export type FsSymlinkType = "dir" | "file" | "junction"; - - declare export type CopyFilterSync = (src: string, dest: string) => boolean; - declare export type CopyFilterAsync = ( - src: string, - dest: string - ) => Promise; - - declare export type CopyOptions = { - dereference?: boolean, - overwrite?: boolean, - preserveTimestamps?: boolean, - errorOnExist?: boolean, - recursive?: boolean - }; - - declare export type CopyOptionsAync = CopyOptions & { - filter?: CopyFilterSync | CopyFilterAsync - }; - - declare export type CopyOptionsSync = CopyOptions & { - filter?: CopyFilterSync - }; - - declare export type MoveOptions = { - overwrite?: boolean, - limit?: number - }; - - declare export type ReadOptions = { - throws?: boolean, - fs?: Object, - reviver?: any, - encoding?: string, - flag?: string - }; - - declare export type WriteFileOptions = { - encoding?: string, - flag?: string, - mode?: number - }; - - declare export type WriteOptions = WriteFileOptions & { - fs?: Object, - replacer?: any, - spaces?: number | string, - EOL?: string - }; - - declare export type ReadResult = { - bytesRead: number, - buffer: Buffer - }; - - declare export type WriteResult = { - bytesWritten: number, - buffer: Buffer - }; - - declare export function copy( - src: string, - dest: string, - options?: CopyOptionsAync - ): Promise; - declare export function copy( - src: string, - dest: string, - callback: (err: Error) => void - ): void; - declare export function copy( - src: string, - dest: string, - options: CopyOptionsAync, - callback: (err: Error) => void - ): void; - declare export function copySync( - src: string, - dest: string, - options?: CopyOptionsSync - ): void; - - declare export function move( - src: string, - dest: string, - options?: MoveOptions - ): Promise; - declare export function move( - src: string, - dest: string, - callback: (err: Error) => void - ): void; - declare export function move( - src: string, - dest: string, - options: MoveOptions, - callback: (err: Error) => void - ): void; - declare export function moveSync( - src: string, - dest: string, - options?: MoveOptions - ): void; - - declare export function createFile(file: string): Promise; - declare export function createFile( - file: string, - callback: (err: Error) => void - ): void; - declare export function createFileSync(file: string): void; - declare export function createReadStream(path: string, options?: Object): ReadStream; - declare export function createWriteStream(path: string, options?: Object): WriteStream; - - declare export function ensureDir(path: string): Promise; - declare export function ensureDir( - path: string, - callback: (err: Error) => void - ): void; - declare export function ensureDirSync(path: string): void; - - declare export function exists(path: string): Promise; - declare export function exists(path: string, callback?: (exists: boolean) => void): void; - - declare export function mkdirs(dir: string): Promise; - declare export function mkdirs( - dir: string, - callback: (err: Error) => void - ): void; - declare export function mkdirsSync(dir: string): void; - - declare export function mkdirp(dir: string): Promise; - declare export function mkdirp( - dir: string, - callback: (err: Error) => void - ): void; - declare export function mkdirpSync(dir: string): void; - - declare export function outputFile( - file: string, - data: any, - options?: WriteFileOptions | string - ): Promise; - declare export function outputFile( - file: string, - data: any, - callback: (err: Error) => void - ): void; - declare export function outputFile( - file: string, - data: any, - options: WriteFileOptions | string, - callback: (err: Error) => void - ): void; - declare export function outputFileSync( - file: string, - data: any, - options?: WriteFileOptions | string - ): void; - - declare export function readJson( - file: string, - options?: ReadOptions - ): Promise; - declare export function readJson( - file: string, - callback: (err: Error, jsonObject: any) => void - ): void; - declare export function readJson( - file: string, - options: ReadOptions, - callback: (err: Error, jsonObject: any) => void - ): void; - declare export function readJSON( - file: string, - options?: ReadOptions - ): Promise; - declare export function readJSON( - file: string, - callback: (err: Error, jsonObject: any) => void - ): void; - declare export function readJSON( - file: string, - options: ReadOptions, - callback: (err: Error, jsonObject: any) => void - ): void; - - declare export function readJsonSync( - file: string, - options?: ReadOptions - ): any; - declare export function readJSONSync( - file: string, - options?: ReadOptions - ): any; - - declare export function remove(dir: string): Promise; - declare export function remove( - dir: string, - callback: (err: Error) => void - ): void; - declare export function removeSync(dir: string): void; - - declare export function outputJson( - file: string, - data: any, - options?: WriteOptions - ): Promise; - declare export function outputJSON( - file: string, - data: any, - options?: WriteOptions - ): Promise; - declare export function outputJson( - file: string, - data: any, - options: WriteOptions, - callback: (err: Error) => void - ): void; - declare export function outputJSON( - file: string, - data: any, - options: WriteOptions, - callback: (err: Error) => void - ): void; - declare export function outputJson( - file: string, - data: any, - callback: (err: Error) => void - ): void; - declare export function outputJSON( - file: string, - data: any, - callback: (err: Error) => void - ): void; - declare export function outputJsonSync( - file: string, - data: any, - options?: WriteOptions - ): void; - declare export function outputJSONSync( - file: string, - data: any, - options?: WriteOptions - ): void; - - declare export function writeJSON( - file: string, - object: any, - options?: WriteOptions - ): Promise; - declare export function writeJSON( - file: string, - object: any, - callback: (err: Error) => void - ): void; - declare export function writeJSON( - file: string, - object: any, - options: WriteOptions, - callback: (err: Error) => void - ): void; - declare export function writeJson( - file: string, - object: any, - options?: WriteOptions - ): Promise; - declare export function writeJson( - file: string, - object: any, - callback: (err: Error) => void - ): void; - declare export function writeJson( - file: string, - object: any, - options: WriteOptions, - callback: (err: Error) => void - ): void; - - declare export function writeJsonSync( - file: string, - object: any, - options?: WriteOptions - ): void; - declare export function writeJSONSync( - file: string, - object: any, - options?: WriteOptions - ): void; - - declare export function ensureFile(path: string): Promise; - declare export function ensureFile( - path: string, - callback: (err: Error) => void - ): void; - declare export function ensureFileSync(path: string): void; - - declare export function ensureLink(src: string, dest: string): Promise; - declare export function ensureLink( - src: string, - dest: string, - callback: (err: Error) => void - ): void; - declare export function ensureLinkSync(src: string, dest: string): void; - - declare export function ensureSymlink( - src: string, - dest: string, - type?: SymlinkType - ): Promise; - declare export function ensureSymlink( - src: string, - dest: string, - type: SymlinkType, - callback: (err: Error) => void - ): void; - declare export function ensureSymlink( - src: string, - dest: string, - callback: (err: Error) => void - ): void; - declare export function ensureSymlinkSync( - src: string, - dest: string, - type?: SymlinkType - ): void; - - declare export function emptyDir(path: string): Promise; - declare export function emptyDir( - path: string, - callback: (err: Error) => void - ): void; - declare export function emptyDirSync(path: string): void; - - declare export function pathExists(path: string): Promise; - declare export function pathExists( - path: string, - callback: (err: Error, exists: boolean) => void - ): void; - declare export function pathExistsSync(path: string): boolean; - - declare export function access( - path: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function access( - path: string | Buffer, - mode: number, - callback: (err: ErrnoError) => void - ): void; - declare export function access( - path: string | Buffer, - mode?: number - ): Promise; - - declare export function appendFile( - file: string | Buffer | number, - data: any, - options: { encoding?: string, mode?: number | string, flag?: string }, - callback: (err: ErrnoError) => void - ): void; - declare export function appendFile( - file: string | Buffer | number, - data: any, - callback: (err: ErrnoError) => void - ): void; - declare export function appendFile( - file: string | Buffer | number, - data: any, - options?: { encoding?: string, mode?: number | string, flag?: string } - ): Promise; - - declare export function chmod( - path: string | Buffer, - mode: string | number, - callback: (err: ErrnoError) => void - ): void; - declare export function chmod( - path: string | Buffer, - mode: string | number - ): Promise; - - declare export function chown( - path: string | Buffer, - uid: number, - gid: number - ): Promise; - declare export function chown( - path: string | Buffer, - uid: number, - gid: number, - callback: (err: ErrnoError) => void - ): void; - - declare export function close( - fd: number, - callback: (err: ErrnoError) => void - ): void; - declare export function close(fd: number): Promise; - - declare export function fchmod( - fd: number, - mode: string | number, - callback: (err: ErrnoError) => void - ): void; - declare export function fchmod( - fd: number, - mode: string | number - ): Promise; - - declare export function fchown( - fd: number, - uid: number, - gid: number, - callback: (err: ErrnoError) => void - ): void; - declare export function fchown( - fd: number, - uid: number, - gid: number - ): Promise; - - declare export function fdatasync(fd: number, callback: () => void): void; - declare export function fdatasync(fd: number): Promise; - - declare export function fstat( - fd: number, - callback: (err: ErrnoError, stats: Stats) => any - ): void; - declare export function fstat(fd: number): Promise; - - declare export function fsync( - fd: number, - callback: (err: ErrnoError) => void - ): void; - declare export function fsync(fd: number): Promise; - - declare export function ftruncate( - fd: number, - callback: (err: ErrnoError) => void - ): void; - declare export function ftruncate( - fd: number, - len: number, - callback: (err: ErrnoError) => void - ): void; - declare export function ftruncate(fd: number, len?: number): Promise; - - declare export function futimes( - fd: number, - atime: number, - mtime: number, - callback: (err: ErrnoError) => void - ): void; - declare export function futimes( - fd: number, - atime: Date, - mtime: Date, - callback: (err: ErrnoError) => void - ): void; - declare export function futimes( - fd: number, - atime: number, - mtime: number - ): Promise; - declare export function futimes( - fd: number, - atime: Date, - mtime: Date - ): Promise; - - declare export function lchown( - path: string | Buffer, - uid: number, - gid: number, - callback: (err: ErrnoError) => void - ): void; - declare export function lchown( - path: string | Buffer, - uid: number, - gid: number - ): Promise; - - declare export function link( - srcpath: string | Buffer, - dstpath: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function link( - srcpath: string | Buffer, - dstpath: string | Buffer - ): Promise; - - declare export function lstat( - path: string | Buffer, - callback: (err: ErrnoError, stats: Stats) => any - ): void; - declare export function lstat(path: string | Buffer): Promise; - - declare export function mkdir( - path: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function mkdir( - path: string | Buffer, - mode: number | string, - callback: (err: ErrnoError) => void - ): void; - declare export function mkdir(path: string | Buffer): Promise; - - declare export function open( - path: string | Buffer, - flags: string | number, - callback: (err: ErrnoError, fd: number) => void - ): void; - declare export function open( - path: string | Buffer, - flags: string | number, - mode: number, - callback: (err: ErrnoError, fd: number) => void - ): void; - declare export function open( - path: string | Buffer, - flags: string | number, - mode?: number - ): Promise; - - declare export function read( - fd: number, - buffer: Buffer, - offset: number, - length: number, - position: number | null, - callback: (err: ErrnoError, bytesRead: number, buffer: Buffer) => void - ): void; - declare export function read( - fd: number, - buffer: Buffer, - offset: number, - length: number, - position: number | null - ): Promise; - - declare export function readFile( - file: string | Buffer | number, - callback: (err: ErrnoError, data: Buffer) => void - ): void; - declare export function readFile( - file: string | Buffer | number, - encoding: string, - callback: (err: ErrnoError, data: string) => void - ): void; - declare export function readFile( - file: string | Buffer | number, - options: { flag?: string } | { encoding: string, flag?: string }, - callback: (err: ErrnoError, data: Buffer) => void - ): void; - declare export function readFile( - file: string | Buffer | number, - options: { flag?: string } | { encoding: string, flag?: string } - ): Promise; - declare export function readFile( - file: string | Buffer | number, - encoding: string - ): Promise; - declare export function readFile( - file: string | Buffer | number - ): Promise; - - declare export function readdir( - path: string | Buffer, - callback: (err: ErrnoError, files: string[]) => void - ): void; - declare export function readdir(path: string | Buffer): Promise; - - declare export function readlink( - path: string | Buffer, - callback: (err: ErrnoError, linkString: string) => any - ): void; - declare export function readlink(path: string | Buffer): Promise; - - declare export function realpath( - path: string | Buffer, - callback: (err: ErrnoError, resolvedPath: string) => any - ): void; - declare export function realpath( - path: string | Buffer, - cache: { [path: string]: string }, - callback: (err: ErrnoError, resolvedPath: string) => any - ): void; - declare export function realpath( - path: string | Buffer, - cache?: { [path: string]: string } - ): Promise; - - declare export function rename( - oldPath: string, - newPath: string, - callback: (err: ErrnoError) => void - ): void; - declare export function rename( - oldPath: string, - newPath: string - ): Promise; - - declare export function rmdir( - path: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function rmdir(path: string | Buffer): Promise; - - declare export function stat( - path: string | Buffer, - callback: (err: ErrnoError, stats: Stats) => any - ): void; - declare export function stat(path: string | Buffer): Promise; - - declare export function statSync(path: string): Stats; - - declare export function symlink( - srcpath: string | Buffer, - dstpath: string | Buffer, - type: FsSymlinkType | void, - callback: (err: ErrnoError) => void - ): void; - declare export function symlink( - srcpath: string | Buffer, - dstpath: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function symlink( - srcpath: string | Buffer, - dstpath: string | Buffer, - type?: FsSymlinkType - ): Promise; - - declare export function truncate( - path: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function truncate( - path: string | Buffer, - len: number, - callback: (err: ErrnoError) => void - ): void; - declare export function truncate( - path: string | Buffer, - len?: number - ): Promise; - - declare export function unlink( - path: string | Buffer, - callback: (err: ErrnoError) => void - ): void; - declare export function unlink(path: string | Buffer): Promise; - - declare export function utimes( - path: string | Buffer, - atime: number, - mtime: number, - callback: (err: ErrnoError) => void - ): void; - declare export function utimes( - path: string | Buffer, - atime: Date, - mtime: Date, - callback: (err: ErrnoError) => void - ): void; - declare export function utimes( - path: string | Buffer, - atime: number, - mtime: number - ): Promise; - declare export function utimes( - path: string | Buffer, - atime: Date, - mtime: Date - ): Promise; - - declare export function write( - fd: number, - buffer: Buffer, - offset: number, - length: number, - position: number | null, - callback: (err: ErrnoError, written: number, buffer: Buffer) => void - ): void; - declare export function write( - fd: number, - buffer: Buffer, - offset: number, - length: number, - callback: (err: ErrnoError, written: number, buffer: Buffer) => void - ): void; - declare export function write( - fd: number, - data: any, - callback: (err: ErrnoError, written: number, str: string) => void - ): void; - declare export function write( - fd: number, - data: any, - offset: number, - callback: (err: ErrnoError, written: number, str: string) => void - ): void; - declare export function write( - fd: number, - data: any, - offset: number, - encoding: string, - callback: (err: ErrnoError, written: number, str: string) => void - ): void; - declare export function write( - fd: number, - buffer: Buffer, - offset: number, - length: number, - position?: number | null - ): Promise; - declare export function write( - fd: number, - data: any, - offset: number, - encoding?: string - ): Promise; - - declare export function writeFile( - file: string | Buffer | number, - data: any, - callback: (err: ErrnoError) => void - ): void; - declare export function writeFile( - file: string | Buffer | number, - data: any, - options?: WriteFileOptions | string - ): Promise; - declare export function writeFile( - file: string | Buffer | number, - data: any, - options: WriteFileOptions | string, - callback: (err: ErrnoError) => void - ): void; - - declare export function mkdtemp(prefix: string): Promise; - declare export function mkdtemp( - prefix: string, - callback: (err: ErrnoError, folder: string) => void - ): void; -} diff --git a/flow-typed/npm/fs-extra_vx.x.x.js b/flow-typed/npm/fs-extra_vx.x.x.js new file mode 100644 index 0000000000..475d5680a0 --- /dev/null +++ b/flow-typed/npm/fs-extra_vx.x.x.js @@ -0,0 +1,249 @@ +// flow-typed signature: 9d15e58be939ea1c9a63893d4bf16fef +// flow-typed version: <>/fs-extra_v^8.0.1/flow_v0.102.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'fs-extra' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'fs-extra' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'fs-extra/lib/copy-sync/copy-sync' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/copy-sync/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/copy/copy' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/copy/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/empty/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/ensure/file' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/ensure/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/ensure/link' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/ensure/symlink-paths' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/ensure/symlink-type' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/ensure/symlink' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/fs/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/json/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/json/jsonfile' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/json/output-json-sync' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/json/output-json' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/mkdirs/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/mkdirs/mkdirs-sync' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/mkdirs/mkdirs' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/mkdirs/win32' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/move-sync/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/move-sync/move-sync' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/move/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/move/move' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/output/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/path-exists/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/remove/index' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/remove/rimraf' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/util/buffer' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/util/stat' { + declare module.exports: any; +} + +declare module 'fs-extra/lib/util/utimes' { + declare module.exports: any; +} + +// Filename aliases +declare module 'fs-extra/lib/copy-sync/copy-sync.js' { + declare module.exports: $Exports<'fs-extra/lib/copy-sync/copy-sync'>; +} +declare module 'fs-extra/lib/copy-sync/index.js' { + declare module.exports: $Exports<'fs-extra/lib/copy-sync/index'>; +} +declare module 'fs-extra/lib/copy/copy.js' { + declare module.exports: $Exports<'fs-extra/lib/copy/copy'>; +} +declare module 'fs-extra/lib/copy/index.js' { + declare module.exports: $Exports<'fs-extra/lib/copy/index'>; +} +declare module 'fs-extra/lib/empty/index.js' { + declare module.exports: $Exports<'fs-extra/lib/empty/index'>; +} +declare module 'fs-extra/lib/ensure/file.js' { + declare module.exports: $Exports<'fs-extra/lib/ensure/file'>; +} +declare module 'fs-extra/lib/ensure/index.js' { + declare module.exports: $Exports<'fs-extra/lib/ensure/index'>; +} +declare module 'fs-extra/lib/ensure/link.js' { + declare module.exports: $Exports<'fs-extra/lib/ensure/link'>; +} +declare module 'fs-extra/lib/ensure/symlink-paths.js' { + declare module.exports: $Exports<'fs-extra/lib/ensure/symlink-paths'>; +} +declare module 'fs-extra/lib/ensure/symlink-type.js' { + declare module.exports: $Exports<'fs-extra/lib/ensure/symlink-type'>; +} +declare module 'fs-extra/lib/ensure/symlink.js' { + declare module.exports: $Exports<'fs-extra/lib/ensure/symlink'>; +} +declare module 'fs-extra/lib/fs/index.js' { + declare module.exports: $Exports<'fs-extra/lib/fs/index'>; +} +declare module 'fs-extra/lib/index.js' { + declare module.exports: $Exports<'fs-extra/lib/index'>; +} +declare module 'fs-extra/lib/json/index.js' { + declare module.exports: $Exports<'fs-extra/lib/json/index'>; +} +declare module 'fs-extra/lib/json/jsonfile.js' { + declare module.exports: $Exports<'fs-extra/lib/json/jsonfile'>; +} +declare module 'fs-extra/lib/json/output-json-sync.js' { + declare module.exports: $Exports<'fs-extra/lib/json/output-json-sync'>; +} +declare module 'fs-extra/lib/json/output-json.js' { + declare module.exports: $Exports<'fs-extra/lib/json/output-json'>; +} +declare module 'fs-extra/lib/mkdirs/index.js' { + declare module.exports: $Exports<'fs-extra/lib/mkdirs/index'>; +} +declare module 'fs-extra/lib/mkdirs/mkdirs-sync.js' { + declare module.exports: $Exports<'fs-extra/lib/mkdirs/mkdirs-sync'>; +} +declare module 'fs-extra/lib/mkdirs/mkdirs.js' { + declare module.exports: $Exports<'fs-extra/lib/mkdirs/mkdirs'>; +} +declare module 'fs-extra/lib/mkdirs/win32.js' { + declare module.exports: $Exports<'fs-extra/lib/mkdirs/win32'>; +} +declare module 'fs-extra/lib/move-sync/index.js' { + declare module.exports: $Exports<'fs-extra/lib/move-sync/index'>; +} +declare module 'fs-extra/lib/move-sync/move-sync.js' { + declare module.exports: $Exports<'fs-extra/lib/move-sync/move-sync'>; +} +declare module 'fs-extra/lib/move/index.js' { + declare module.exports: $Exports<'fs-extra/lib/move/index'>; +} +declare module 'fs-extra/lib/move/move.js' { + declare module.exports: $Exports<'fs-extra/lib/move/move'>; +} +declare module 'fs-extra/lib/output/index.js' { + declare module.exports: $Exports<'fs-extra/lib/output/index'>; +} +declare module 'fs-extra/lib/path-exists/index.js' { + declare module.exports: $Exports<'fs-extra/lib/path-exists/index'>; +} +declare module 'fs-extra/lib/remove/index.js' { + declare module.exports: $Exports<'fs-extra/lib/remove/index'>; +} +declare module 'fs-extra/lib/remove/rimraf.js' { + declare module.exports: $Exports<'fs-extra/lib/remove/rimraf'>; +} +declare module 'fs-extra/lib/util/buffer.js' { + declare module.exports: $Exports<'fs-extra/lib/util/buffer'>; +} +declare module 'fs-extra/lib/util/stat.js' { + declare module.exports: $Exports<'fs-extra/lib/util/stat'>; +} +declare module 'fs-extra/lib/util/utimes.js' { + declare module.exports: $Exports<'fs-extra/lib/util/utimes'>; +} diff --git a/flow-typed/npm/globby_vx.x.x.js b/flow-typed/npm/globby_vx.x.x.js index 80dfe8453b..844d9cda6e 100644 --- a/flow-typed/npm/globby_vx.x.x.js +++ b/flow-typed/npm/globby_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 172a6e9588ecba1bf092b9a51a2b922b -// flow-typed version: <>/globby_v^9.2.0/flow_v0.96.0 +// flow-typed signature: 56110e0b9c8ef6e52894c332fc812341 +// flow-typed version: <>/globby_v^9.2.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/jest-junit_vx.x.x.js b/flow-typed/npm/jest-junit_vx.x.x.js index de1e4177a1..3a79eb3b96 100644 --- a/flow-typed/npm/jest-junit_vx.x.x.js +++ b/flow-typed/npm/jest-junit_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: bf0e4f4ef56a59ef43cc4e8730175a0b -// flow-typed version: <>/jest-junit_v^6.3.0/flow_v0.96.0 +// flow-typed signature: 7d6730c9e61c06dfd7ce783527ca02ea +// flow-typed version: <>/jest-junit_v^6.4.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/jest-watch-typeahead_vx.x.x.js b/flow-typed/npm/jest-watch-typeahead_vx.x.x.js index 018a7021aa..d7e4f83fd1 100644 --- a/flow-typed/npm/jest-watch-typeahead_vx.x.x.js +++ b/flow-typed/npm/jest-watch-typeahead_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 04cd97764cab76369586f93865c47f3b -// flow-typed version: <>/jest-watch-typeahead_v^0.3.0/flow_v0.96.0 +// flow-typed signature: 4d088ad7ea08ca413f7d729ad94d8555 +// flow-typed version: <>/jest-watch-typeahead_v^0.3.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -22,6 +22,14 @@ declare module 'jest-watch-typeahead' { * require those files directly. Feel free to delete any files that aren't * needed. */ +declare module 'jest-watch-typeahead/build/file_name_pattern_prompt' { + declare module.exports: any; +} + +declare module 'jest-watch-typeahead/build/file_name_plugin' { + declare module.exports: any; +} + declare module 'jest-watch-typeahead/build/file_name_plugin/plugin' { declare module.exports: any; } @@ -30,6 +38,10 @@ declare module 'jest-watch-typeahead/build/file_name_plugin/prompt' { declare module.exports: any; } +declare module 'jest-watch-typeahead/build/index' { + declare module.exports: any; +} + declare module 'jest-watch-typeahead/build/lib/pattern_mode_helpers' { declare module.exports: any; } @@ -42,6 +54,22 @@ declare module 'jest-watch-typeahead/build/lib/utils' { declare module.exports: any; } +declare module 'jest-watch-typeahead/build/shared/pattern_mode_helpers' { + declare module.exports: any; +} + +declare module 'jest-watch-typeahead/build/shared/scroll' { + declare module.exports: any; +} + +declare module 'jest-watch-typeahead/build/test_name_pattern_prompt' { + declare module.exports: any; +} + +declare module 'jest-watch-typeahead/build/test_name_plugin' { + declare module.exports: any; +} + declare module 'jest-watch-typeahead/build/test_name_plugin/plugin' { declare module.exports: any; } @@ -67,12 +95,21 @@ declare module 'jest-watch-typeahead/testname' { } // Filename aliases +declare module 'jest-watch-typeahead/build/file_name_pattern_prompt.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/file_name_pattern_prompt'>; +} +declare module 'jest-watch-typeahead/build/file_name_plugin.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/file_name_plugin'>; +} declare module 'jest-watch-typeahead/build/file_name_plugin/plugin.js' { declare module.exports: $Exports<'jest-watch-typeahead/build/file_name_plugin/plugin'>; } declare module 'jest-watch-typeahead/build/file_name_plugin/prompt.js' { declare module.exports: $Exports<'jest-watch-typeahead/build/file_name_plugin/prompt'>; } +declare module 'jest-watch-typeahead/build/index.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/index'>; +} declare module 'jest-watch-typeahead/build/lib/pattern_mode_helpers.js' { declare module.exports: $Exports<'jest-watch-typeahead/build/lib/pattern_mode_helpers'>; } @@ -82,6 +119,18 @@ declare module 'jest-watch-typeahead/build/lib/scroll.js' { declare module 'jest-watch-typeahead/build/lib/utils.js' { declare module.exports: $Exports<'jest-watch-typeahead/build/lib/utils'>; } +declare module 'jest-watch-typeahead/build/shared/pattern_mode_helpers.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/shared/pattern_mode_helpers'>; +} +declare module 'jest-watch-typeahead/build/shared/scroll.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/shared/scroll'>; +} +declare module 'jest-watch-typeahead/build/test_name_pattern_prompt.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/test_name_pattern_prompt'>; +} +declare module 'jest-watch-typeahead/build/test_name_plugin.js' { + declare module.exports: $Exports<'jest-watch-typeahead/build/test_name_plugin'>; +} declare module 'jest-watch-typeahead/build/test_name_plugin/plugin.js' { declare module.exports: $Exports<'jest-watch-typeahead/build/test_name_plugin/plugin'>; } diff --git a/flow-typed/npm/jest_v24.x.x.js b/flow-typed/npm/jest_v24.x.x.js index 1c1d6d9a28..3eaae99c6f 100644 --- a/flow-typed/npm/jest_v24.x.x.js +++ b/flow-typed/npm/jest_v24.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 833075a5cefc49eb523160a5fca9d8b6 -// flow-typed version: 325925f1b7/jest_v24.x.x/flow_>=v0.39.x +// flow-typed signature: 62afff77b0be14fade0f13aee8bda9db +// flow-typed version: 9823121349/jest_v24.x.x/flow_>=v0.39.x type JestMockFn, TReturn> = { (...args: TArguments): TReturn, @@ -127,8 +127,8 @@ type JestMatcherResult = { }; type JestMatcher = ( - actual: any, - expected: any + received: any, + ...actual: Array ) => JestMatcherResult | Promise; type JestPromiseType = { @@ -215,6 +215,7 @@ type EnzymeMatchersType = { // DOM testing library extensions https://github.com/kentcdodds/dom-testing-library#custom-jest-matchers type DomTestingLibraryType = { toBeDisabled(): void, + toBeEnabled(): void, toBeEmpty(): void, toBeInTheDocument(): void, toBeVisible(): void, @@ -707,7 +708,7 @@ interface JestExpectType { /** * */ - toHaveProperty(propPath: string, value?: any): void; + toHaveProperty(propPath: string | $ReadOnlyArray, value?: any): void; /** * Use .toMatch to check that a string matches a regular expression or string. */ diff --git a/flow-typed/npm/markdown-it_vx.x.x.js b/flow-typed/npm/markdown-it_vx.x.x.js index f356d00198..c9dcdc021a 100644 --- a/flow-typed/npm/markdown-it_vx.x.x.js +++ b/flow-typed/npm/markdown-it_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 82287c9885fa6b8b7feafed5c6b3af38 -// flow-typed version: <>/markdown-it_v^8.4.2/flow_v0.96.0 +// flow-typed signature: c477286f0fa9c78283fc7045b981a677 +// flow-typed version: <>/markdown-it_v^8.4.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/prop-types_v15.x.x.js b/flow-typed/npm/prop-types_v15.x.x.js deleted file mode 100644 index ba9478bfe0..0000000000 --- a/flow-typed/npm/prop-types_v15.x.x.js +++ /dev/null @@ -1,35 +0,0 @@ -// flow-typed signature: d9a983bb1ac458a256c31c139047bdbb -// flow-typed version: 927687984d/prop-types_v15.x.x/flow_>=v0.41.x - -type $npm$propTypes$ReactPropsCheckType = ( - props: any, - propName: string, - componentName: string, - href?: string) => ?Error; - -declare module 'prop-types' { - declare var array: React$PropType$Primitive>; - declare var bool: React$PropType$Primitive; - declare var func: React$PropType$Primitive; - declare var number: React$PropType$Primitive; - declare var object: React$PropType$Primitive; - declare var string: React$PropType$Primitive; - declare var symbol: React$PropType$Primitive; - declare var any: React$PropType$Primitive; - declare var arrayOf: React$PropType$ArrayOf; - declare var element: React$PropType$Primitive; /* TODO */ - declare var instanceOf: React$PropType$InstanceOf; - declare var node: React$PropType$Primitive; /* TODO */ - declare var objectOf: React$PropType$ObjectOf; - declare var oneOf: React$PropType$OneOf; - declare var oneOfType: React$PropType$OneOfType; - declare var shape: React$PropType$Shape; - - declare function checkPropTypes( - propTypes: $Subtype<{[_: $Keys]: $npm$propTypes$ReactPropsCheckType}>, - values: V, - location: string, - componentName: string, - getStack: ?(() => ?string) - ) : void; -} diff --git a/flow-typed/npm/react-redux_v5.x.x.js b/flow-typed/npm/react-redux_v5.x.x.js deleted file mode 100644 index eeeab17df9..0000000000 --- a/flow-typed/npm/react-redux_v5.x.x.js +++ /dev/null @@ -1,276 +0,0 @@ -// flow-typed signature: f06f00c3ad0cfedb90c0c6de04b219f3 -// flow-typed version: 3a6d556e4b/react-redux_v5.x.x/flow_>=v0.89.x - -/** -The order of type arguments for connect() is as follows: - -connect(โ€ฆ) - -In Flow v0.89 only the first two are mandatory to specify. Other 4 can be repaced with the new awesome type placeholder: - -connect(โ€ฆ) - -But beware, in case of weird type errors somewhere in random places -just type everything and get to a green field and only then try to -remove the definitions you see bogus. - -Decrypting the abbreviations: - WC = Component being wrapped - S = State - D = Dispatch - OP = OwnProps - SP = StateProps - DP = DispatchProps - MP = Merge props - RSP = Returned state props - RDP = Returned dispatch props - RMP = Returned merge props - CP = Props for returned component - Com = React Component - ST = Static properties of Com - EFO = Extra factory options (used only in connectAdvanced) -*/ - -declare module "react-redux" { - // ------------------------------------------------------------ - // Typings for connect() - // ------------------------------------------------------------ - - declare export type Options = {| - pure?: boolean, - withRef?: boolean, - areStatesEqual?: (next: S, prev: S) => boolean, - areOwnPropsEqual?: (next: OP, prev: OP) => boolean, - areStatePropsEqual?: (next: SP, prev: SP) => boolean, - areMergedPropsEqual?: (next: MP, prev: MP) => boolean, - storeKey?: string, - |}; - - declare type MapStateToProps<-S, -OP, +SP> = - | ((state: S, ownProps: OP) => SP) - // If you want to use the factory function but get a strange error - // like "function is not an object" then just type the factory function - // like this: - // const factory: (State, OwnProps) => (State, OwnProps) => StateProps - // and provide the StateProps type to the SP type parameter. - | ((state: S, ownProps: OP) => (state: S, ownProps: OP) => SP); - - declare type Bind = ((...A) => R) => (...A) => $Call; - - declare type MapDispatchToPropsFn = - | ((dispatch: D, ownProps: OP) => DP) - // If you want to use the factory function but get a strange error - // like "function is not an object" then just type the factory function - // like this: - // const factory: (Dispatch, OwnProps) => (Dispatch, OwnProps) => DispatchProps - // and provide the DispatchProps type to the DP type parameter. - | ((dispatch: D, ownProps: OP) => (dispatch: D, ownProps: OP) => DP); - - declare class ConnectedComponent extends React$Component { - static +WrappedComponent: WC; - getWrappedInstance(): React$ElementRef; - } - // The connection of the Wrapped Component and the Connected Component - // happens here in `MP: P`. It means that type wise MP belongs to P, - // so to say MP >= P. - declare type Connector = >( - WC, - ) => Class> & WC; - - // No `mergeProps` argument - - // Got error like inexact OwnProps is incompatible with exact object type? - // Just make the OP parameter for `connect()` an exact object. - declare type MergeOP = {| ...$Exact, dispatch: D |}; - declare type MergeOPSP = {| ...$Exact, ...SP, dispatch: D |}; - declare type MergeOPDP = {| ...$Exact, ...DP |}; - declare type MergeOPSPDP = {| ...$Exact, ...SP, ...DP |}; - - declare export function connect<-P, -OP, -SP, -DP, -S, -D>( - mapStateToProps?: null | void, - mapDispatchToProps?: null | void, - mergeProps?: null | void, - options?: ?Options>, - ): Connector>; - - declare export function connect<-P, -OP, -SP, -DP, -S, -D>( - // If you get error here try adding return type to your mapStateToProps function - mapStateToProps: MapStateToProps, - mapDispatchToProps?: null | void, - mergeProps?: null | void, - options?: ?Options>, - ): Connector>; - - // In this case DP is an object of functions which has been bound to dispatch - // by the given mapDispatchToProps function. - declare export function connect<-P, -OP, -SP, -DP, S, D>( - mapStateToProps: null | void, - mapDispatchToProps: MapDispatchToPropsFn, - mergeProps?: null | void, - options?: ?Options>, - ): Connector>; - - // In this case DP is an object of action creators not yet bound to dispatch, - // this difference is not important in the vanila redux, - // but in case of usage with redux-thunk, the return type may differ. - declare export function connect<-P, -OP, -SP, -DP, S, D>( - mapStateToProps: null | void, - mapDispatchToProps: DP, - mergeProps?: null | void, - options?: ?Options>, - ): Connector>>>; - - declare export function connect<-P, -OP, -SP, -DP, S, D>( - // If you get error here try adding return type to your mapStateToProps function - mapStateToProps: MapStateToProps, - mapDispatchToProps: MapDispatchToPropsFn, - mergeProps?: null | void, - options?: ?Options, - ): Connector; - - declare export function connect<-P, -OP, -SP, -DP, S, D>( - // If you get error here try adding return type to your mapStateToProps function - mapStateToProps: MapStateToProps, - mapDispatchToProps: DP, - mergeProps?: null | void, - options?: ?Options>, - ): Connector>>>; - - // With `mergeProps` argument - - declare type MergeProps<+P, -OP, -SP, -DP> = ( - stateProps: SP, - dispatchProps: DP, - ownProps: OP, - ) => P; - - declare export function connect<-P, -OP, -SP: {||}, -DP: {||}, S, D>( - mapStateToProps: null | void, - mapDispatchToProps: null | void, - // If you get error here try adding return type to you mapStateToProps function - mergeProps: MergeProps, - options?: ?Options, - ): Connector; - - declare export function connect<-P, -OP, -SP, -DP: {||}, S, D>( - mapStateToProps: MapStateToProps, - mapDispatchToProps: null | void, - // If you get error here try adding return type to you mapStateToProps function - mergeProps: MergeProps, - options?: ?Options, - ): Connector; - - // In this case DP is an object of functions which has been bound to dispatch - // by the given mapDispatchToProps function. - declare export function connect<-P, -OP, -SP: {||}, -DP, S, D>( - mapStateToProps: null | void, - mapDispatchToProps: MapDispatchToPropsFn, - mergeProps: MergeProps, - options?: ?Options, - ): Connector; - - // In this case DP is an object of action creators not yet bound to dispatch, - // this difference is not important in the vanila redux, - // but in case of usage with redux-thunk, the return type may differ. - declare export function connect<-P, -OP, -SP: {||}, -DP, S, D>( - mapStateToProps: null | void, - mapDispatchToProps: DP, - mergeProps: MergeProps>>, - options?: ?Options, - ): Connector; - - // In this case DP is an object of functions which has been bound to dispatch - // by the given mapDispatchToProps function. - declare export function connect<-P, -OP, -SP, -DP, S, D>( - mapStateToProps: MapStateToProps, - mapDispatchToProps: MapDispatchToPropsFn, - mergeProps: MergeProps, - options?: ?Options, - ): Connector; - - // In this case DP is an object of action creators not yet bound to dispatch, - // this difference is not important in the vanila redux, - // but in case of usage with redux-thunk, the return type may differ. - declare export function connect<-P, -OP, -SP, -DP, S, D>( - mapStateToProps: MapStateToProps, - mapDispatchToProps: DP, - mergeProps: MergeProps>>, - options?: ?Options, - ): Connector; - - // ------------------------------------------------------------ - // Typings for Provider - // ------------------------------------------------------------ - - declare export class Provider extends React$Component<{ - store: Store, - children?: React$Node, - }> {} - - declare export function createProvider( - storeKey?: string, - subKey?: string, - ): Class>; - - // ------------------------------------------------------------ - // Typings for connectAdvanced() - // ------------------------------------------------------------ - - declare type ConnectAdvancedOptions = { - getDisplayName?: (name: string) => string, - methodName?: string, - renderCountProp?: string, - shouldHandleStateChanges?: boolean, - storeKey?: string, - withRef?: boolean, - }; - - declare type SelectorFactoryOptions = { - getDisplayName: (name: string) => string, - methodName: string, - renderCountProp: ?string, - shouldHandleStateChanges: boolean, - storeKey: string, - withRef: boolean, - displayName: string, - wrappedComponentName: string, - WrappedComponent: Com, - }; - - declare type MapStateToPropsEx = ( - state: S, - props: SP, - ) => RSP; - - declare type SelectorFactory< - Com: React$ComponentType<*>, - Dispatch, - S: Object, - OP: Object, - EFO: Object, - CP: Object, - > = ( - dispatch: Dispatch, - factoryOptions: SelectorFactoryOptions & EFO, - ) => MapStateToPropsEx; - - declare export function connectAdvanced< - Com: React$ComponentType<*>, - D, - S: Object, - OP: Object, - CP: Object, - EFO: Object, - ST: { [_: $Keys]: any }, - >( - selectorFactory: SelectorFactory, - connectAdvancedOptions: ?(ConnectAdvancedOptions & EFO), - ): (component: Com) => React$ComponentType & $Shape; - - declare export default { - Provider: typeof Provider, - createProvider: typeof createProvider, - connect: typeof connect, - connectAdvanced: typeof connectAdvanced, - }; -} diff --git a/flow-typed/npm/react-redux_vx.x.x.js b/flow-typed/npm/react-redux_vx.x.x.js index e3ba302c80..11587457cf 100644 --- a/flow-typed/npm/react-redux_vx.x.x.js +++ b/flow-typed/npm/react-redux_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: d5e5aaf2c5938444fa7739e86d89de0a -// flow-typed version: <>/react-redux_v7.0.0-beta.1/flow_v0.96.0 +// flow-typed signature: 02a15053230b0e8d0b67b8c644515023 +// flow-typed version: <>/react-redux_v^7.1.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -74,6 +74,22 @@ declare module 'react-redux/es/connect/wrapMapToProps' { declare module.exports: any; } +declare module 'react-redux/es/hooks/useDispatch' { + declare module.exports: any; +} + +declare module 'react-redux/es/hooks/useReduxContext' { + declare module.exports: any; +} + +declare module 'react-redux/es/hooks/useSelector' { + declare module.exports: any; +} + +declare module 'react-redux/es/hooks/useStore' { + declare module.exports: any; +} + declare module 'react-redux/es/index' { declare module.exports: any; } @@ -158,6 +174,22 @@ declare module 'react-redux/lib/connect/wrapMapToProps' { declare module.exports: any; } +declare module 'react-redux/lib/hooks/useDispatch' { + declare module.exports: any; +} + +declare module 'react-redux/lib/hooks/useReduxContext' { + declare module.exports: any; +} + +declare module 'react-redux/lib/hooks/useSelector' { + declare module.exports: any; +} + +declare module 'react-redux/lib/hooks/useStore' { + declare module.exports: any; +} + declare module 'react-redux/lib/index' { declare module.exports: any; } @@ -242,6 +274,22 @@ declare module 'react-redux/src/connect/wrapMapToProps' { declare module.exports: any; } +declare module 'react-redux/src/hooks/useDispatch' { + declare module.exports: any; +} + +declare module 'react-redux/src/hooks/useReduxContext' { + declare module.exports: any; +} + +declare module 'react-redux/src/hooks/useSelector' { + declare module.exports: any; +} + +declare module 'react-redux/src/hooks/useStore' { + declare module.exports: any; +} + declare module 'react-redux/src/index' { declare module.exports: any; } @@ -322,6 +370,18 @@ declare module 'react-redux/es/connect/verifySubselectors.js' { declare module 'react-redux/es/connect/wrapMapToProps.js' { declare module.exports: $Exports<'react-redux/es/connect/wrapMapToProps'>; } +declare module 'react-redux/es/hooks/useDispatch.js' { + declare module.exports: $Exports<'react-redux/es/hooks/useDispatch'>; +} +declare module 'react-redux/es/hooks/useReduxContext.js' { + declare module.exports: $Exports<'react-redux/es/hooks/useReduxContext'>; +} +declare module 'react-redux/es/hooks/useSelector.js' { + declare module.exports: $Exports<'react-redux/es/hooks/useSelector'>; +} +declare module 'react-redux/es/hooks/useStore.js' { + declare module.exports: $Exports<'react-redux/es/hooks/useStore'>; +} declare module 'react-redux/es/index.js' { declare module.exports: $Exports<'react-redux/es/index'>; } @@ -385,6 +445,18 @@ declare module 'react-redux/lib/connect/verifySubselectors.js' { declare module 'react-redux/lib/connect/wrapMapToProps.js' { declare module.exports: $Exports<'react-redux/lib/connect/wrapMapToProps'>; } +declare module 'react-redux/lib/hooks/useDispatch.js' { + declare module.exports: $Exports<'react-redux/lib/hooks/useDispatch'>; +} +declare module 'react-redux/lib/hooks/useReduxContext.js' { + declare module.exports: $Exports<'react-redux/lib/hooks/useReduxContext'>; +} +declare module 'react-redux/lib/hooks/useSelector.js' { + declare module.exports: $Exports<'react-redux/lib/hooks/useSelector'>; +} +declare module 'react-redux/lib/hooks/useStore.js' { + declare module.exports: $Exports<'react-redux/lib/hooks/useStore'>; +} declare module 'react-redux/lib/index.js' { declare module.exports: $Exports<'react-redux/lib/index'>; } @@ -448,6 +520,18 @@ declare module 'react-redux/src/connect/verifySubselectors.js' { declare module 'react-redux/src/connect/wrapMapToProps.js' { declare module.exports: $Exports<'react-redux/src/connect/wrapMapToProps'>; } +declare module 'react-redux/src/hooks/useDispatch.js' { + declare module.exports: $Exports<'react-redux/src/hooks/useDispatch'>; +} +declare module 'react-redux/src/hooks/useReduxContext.js' { + declare module.exports: $Exports<'react-redux/src/hooks/useReduxContext'>; +} +declare module 'react-redux/src/hooks/useSelector.js' { + declare module.exports: $Exports<'react-redux/src/hooks/useSelector'>; +} +declare module 'react-redux/src/hooks/useStore.js' { + declare module.exports: $Exports<'react-redux/src/hooks/useStore'>; +} declare module 'react-redux/src/index.js' { declare module.exports: $Exports<'react-redux/src/index'>; } diff --git a/flow-typed/npm/react-testing-library_vx.x.x.js b/flow-typed/npm/react-testing-library_vx.x.x.js new file mode 100644 index 0000000000..3fc24bac90 --- /dev/null +++ b/flow-typed/npm/react-testing-library_vx.x.x.js @@ -0,0 +1,33 @@ +// flow-typed signature: bba7dfd35bcc1c91cba32b61fb5cced9 +// flow-typed version: <>/react-testing-library_v^8.0.1/flow_v0.102.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'react-testing-library' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'react-testing-library' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ + + +// Filename aliases +declare module 'react-testing-library/index' { + declare module.exports: $Exports<'react-testing-library'>; +} +declare module 'react-testing-library/index.js' { + declare module.exports: $Exports<'react-testing-library'>; +} diff --git a/flow-typed/npm/redux_v4.x.x.js b/flow-typed/npm/redux_v4.x.x.js index 861c6c8292..2ba2c8b265 100644 --- a/flow-typed/npm/redux_v4.x.x.js +++ b/flow-typed/npm/redux_v4.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 55b84d40e54f80cef7b74a34aa052ad5 -// flow-typed version: 2c899a110b/redux_v4.x.x/flow_>=v0.89.x +// flow-typed signature: a49a6c96fe8a8bb3330cce2028588f4c +// flow-typed version: de5b3a01c6/redux_v4.x.x/flow_>=v0.89.x declare module 'redux' { /* @@ -10,6 +10,10 @@ declare module 'redux' { */ + declare export type Action = { + type: T + } + declare export type DispatchAPI = (action: A) => A; declare export type Dispatch = DispatchAPI; diff --git a/flow-typed/npm/rollup-plugin-babel_vx.x.x.js b/flow-typed/npm/rollup-plugin-babel_vx.x.x.js index 2ae64511be..acc42f3ad0 100644 --- a/flow-typed/npm/rollup-plugin-babel_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-babel_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: e74997f07524ef3d6de410eee3dc035c -// flow-typed version: <>/rollup-plugin-babel_v^4.3.2/flow_v0.96.0 +// flow-typed signature: 13a8f22ecd253680e6e3c26a409b41f6 +// flow-typed version: <>/rollup-plugin-babel_v^4.3.3/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-commonjs_vx.x.x.js b/flow-typed/npm/rollup-plugin-commonjs_vx.x.x.js index 65db766ccf..2254429f1b 100644 --- a/flow-typed/npm/rollup-plugin-commonjs_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-commonjs_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: f1a0ff74fdcf45f93509ae3d8cfd1924 -// flow-typed version: <>/rollup-plugin-commonjs_v^9.3.4/flow_v0.96.0 +// flow-typed signature: deec162c270c50e3c4f4ca3d434b2b84 +// flow-typed version: <>/rollup-plugin-commonjs_v^10.0.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -34,10 +34,6 @@ declare module 'rollup-plugin-commonjs/src/ast-utils' { declare module.exports: any; } -declare module 'rollup-plugin-commonjs/src/default-resolver' { - declare module.exports: any; -} - declare module 'rollup-plugin-commonjs/src/helpers' { declare module.exports: any; } @@ -72,9 +68,6 @@ declare module 'rollup-plugin-commonjs/dist/rollup-plugin-commonjs.es.js' { declare module 'rollup-plugin-commonjs/src/ast-utils.js' { declare module.exports: $Exports<'rollup-plugin-commonjs/src/ast-utils'>; } -declare module 'rollup-plugin-commonjs/src/default-resolver.js' { - declare module.exports: $Exports<'rollup-plugin-commonjs/src/default-resolver'>; -} declare module 'rollup-plugin-commonjs/src/helpers.js' { declare module.exports: $Exports<'rollup-plugin-commonjs/src/helpers'>; } diff --git a/flow-typed/npm/rollup-plugin-json_vx.x.x.js b/flow-typed/npm/rollup-plugin-json_vx.x.x.js index 1832b107a2..116707048e 100644 --- a/flow-typed/npm/rollup-plugin-json_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-json_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 84a03641f89c01917c07bd63a57293bd -// flow-typed version: <>/rollup-plugin-json_v^4.0.0/flow_v0.96.0 +// flow-typed signature: 0c17a36edefddd418b5e3a8df6f95a39 +// flow-typed version: <>/rollup-plugin-json_v^4.0.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js b/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js index b449c6961d..c570fc4248 100644 --- a/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-node-resolve_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 530227e8bc61221b829b193989c9becc -// flow-typed version: <>/rollup-plugin-node-resolve_v^4.0.1/flow_v0.96.0 +// flow-typed signature: fe5469d6caabe0f4ec249530dc20179a +// flow-typed version: <>/rollup-plugin-node-resolve_v^5.1.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -30,10 +30,6 @@ declare module 'rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.es' { declare module.exports: any; } -declare module 'rollup-plugin-node-resolve/src/empty' { - declare module.exports: any; -} - declare module 'rollup-plugin-node-resolve/src/index' { declare module.exports: any; } @@ -45,9 +41,6 @@ declare module 'rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.cjs.j declare module 'rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.es.js' { declare module.exports: $Exports<'rollup-plugin-node-resolve/dist/rollup-plugin-node-resolve.es'>; } -declare module 'rollup-plugin-node-resolve/src/empty.js' { - declare module.exports: $Exports<'rollup-plugin-node-resolve/src/empty'>; -} declare module 'rollup-plugin-node-resolve/src/index.js' { declare module.exports: $Exports<'rollup-plugin-node-resolve/src/index'>; } diff --git a/flow-typed/npm/rollup-plugin-replace_vx.x.x.js b/flow-typed/npm/rollup-plugin-replace_vx.x.x.js index 2fdf951413..f619e201fd 100644 --- a/flow-typed/npm/rollup-plugin-replace_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-replace_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 62f7ca0bdda049a7feb1aa0414a1b5e8 -// flow-typed version: <>/rollup-plugin-replace_v^2.1.1/flow_v0.96.0 +// flow-typed signature: 59dc00f255f68390553e52a8fb048e2e +// flow-typed version: <>/rollup-plugin-replace_v^2.2.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-size-snapshot_vx.x.x.js b/flow-typed/npm/rollup-plugin-size-snapshot_vx.x.x.js index ecf88debd5..791f5d2df9 100644 --- a/flow-typed/npm/rollup-plugin-size-snapshot_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-size-snapshot_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: a3289ca6f8af4d2a62702f5e01d0a6f2 -// flow-typed version: <>/rollup-plugin-size-snapshot_v^0.8.0/flow_v0.96.0 +// flow-typed signature: bc2dec9657a4089b483037a298455867 +// flow-typed version: <>/rollup-plugin-size-snapshot_v^0.9.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-strip_vx.x.x.js b/flow-typed/npm/rollup-plugin-strip_vx.x.x.js index 00444c91d3..e72048918f 100644 --- a/flow-typed/npm/rollup-plugin-strip_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-strip_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: c1869aa6943385bfeb1abbcef6af552c -// flow-typed version: <>/rollup-plugin-strip_v^1.2.1/flow_v0.96.0 +// flow-typed signature: c6be4891a5bbd01e6ff01c7a1c6f61e1 +// flow-typed version: <>/rollup-plugin-strip_v^1.2.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup-plugin-uglify_vx.x.x.js b/flow-typed/npm/rollup-plugin-uglify_vx.x.x.js index 917f823db1..a1f6fcbfa1 100644 --- a/flow-typed/npm/rollup-plugin-uglify_vx.x.x.js +++ b/flow-typed/npm/rollup-plugin-uglify_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 93830a2d7698c6f9faf96c71111d7f84 -// flow-typed version: <>/rollup-plugin-uglify_v^6.0.2/flow_v0.96.0 +// flow-typed signature: 296927435e02c281ff2d11b83ea6432a +// flow-typed version: <>/rollup-plugin-uglify_v^6.0.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/rollup_vx.x.x.js b/flow-typed/npm/rollup_vx.x.x.js index 5d7d388b96..99d27fe8b3 100644 --- a/flow-typed/npm/rollup_vx.x.x.js +++ b/flow-typed/npm/rollup_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: d9b61cb670757f1344c03d05d1f1ec55 -// flow-typed version: <>/rollup_v^1.8.0/flow_v0.96.0 +// flow-typed signature: d1c41f42d27185701fba19ab7df22687 +// flow-typed version: <>/rollup_v^1.16.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/styled-components_v3.x.x.js b/flow-typed/npm/styled-components_v3.x.x.js deleted file mode 100644 index e0291771a9..0000000000 --- a/flow-typed/npm/styled-components_v3.x.x.js +++ /dev/null @@ -1,395 +0,0 @@ -// flow-typed signature: f523b1ef4ab2de4542946d8ff8f9d2be -// flow-typed version: a92e9b07d7/styled-components_v3.x.x/flow_>=v0.75.x - -// @flow - -type $npm$styledComponents$Interpolation = ((executionContext: C) => string) | string | number; -type $npm$styledComponents$NameGenerator = (hash: number) => string; - -type $npm$styledComponents$TaggedTemplateLiteral = {| (Array, $npm$styledComponents$Interpolation): R |}; - -// ---- FUNCTIONAL COMPONENT DEFINITIONS ---- -type $npm$styledComponents$ReactComponentFunctional = - & { defaultProps: DefaultProps } - & $npm$styledComponents$ReactComponentFunctionalUndefinedDefaultProps - -type $npm$styledComponents$ReactComponentFunctionalUndefinedDefaultProps = - React$StatelessFunctionalComponent - -// ---- CLASS COMPONENT DEFINITIONS ---- -class $npm$styledComponents$ReactComponent extends React$Component { - static defaultProps: DefaultProps -} -type $npm$styledComponents$ReactComponentClass = Class<$npm$styledComponents$ReactComponent> -type $npm$styledComponents$ReactComponentClassUndefinedDefaultProps = Class> - -// ---- COMPONENT FUNCTIONS INPUT (UNION) & OUTPUT (INTERSECTION) ---- -type $npm$styledComponents$ReactComponentUnion = - $npm$styledComponents$ReactComponentUnionWithDefaultProps - -type $npm$styledComponents$ReactComponentUnionWithDefaultProps = - | $npm$styledComponents$ReactComponentFunctional - | $npm$styledComponents$ReactComponentFunctionalUndefinedDefaultProps - | $npm$styledComponents$ReactComponentClass - | $npm$styledComponents$ReactComponentClassUndefinedDefaultProps - -type $npm$styledComponents$ReactComponentIntersection = - & $npm$styledComponents$ReactComponentFunctional - & $npm$styledComponents$ReactComponentClass; - -// ---- WITHCOMPONENT ---- -type $npm$styledComponents$ReactComponentStyledWithComponent = < - Props, DefaultProps, - Input: - | ComponentList - | $npm$styledComponents$ReactComponentStyled - | $npm$styledComponents$ReactComponentUnionWithDefaultProps ->(Input) => $npm$styledComponents$ReactComponentStyled - -// ---- STATIC PROPERTIES ---- -type $npm$styledComponents$ReactComponentStyledStaticProps = {| - attrs: (AdditionalProps) => $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteral, - extend: $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteral, -|} - -type $npm$styledComponents$ReactComponentStyledStaticPropsWithComponent = {| - withComponent: $npm$styledComponents$ReactComponentStyledWithComponent, - attrs: (AdditionalProps) => $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent, - extend: $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent, -|} - -// ---- STYLED FUNCTION ---- -// Error: styled(CustomComponent).withComponent('a') -// Ok: styled('div').withComponent('a') -type $npm$styledComponents$Call = - & (ComponentListKeys => $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent<{}, ComponentListKeys>) - & (($npm$styledComponents$ReactComponentUnion) => $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteral) - -// ---- STYLED COMPONENT ---- -type $npm$styledComponents$ReactComponentStyled = - & $npm$styledComponents$ReactComponentStyledStaticPropsWithComponent - & $npm$styledComponents$ReactComponentIntersection - -// ---- TAGGED TEMPLATE LITERAL ---- -type $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteral = - & $npm$styledComponents$ReactComponentStyledStaticProps - & $npm$styledComponents$TaggedTemplateLiteral<$npm$styledComponents$ReactComponentStyled> - -type $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent = - & $npm$styledComponents$ReactComponentStyledStaticPropsWithComponent - & $npm$styledComponents$TaggedTemplateLiteral<$npm$styledComponents$ReactComponentStyled> - -// ---- WITHTHEME ---- -type $npm$styledComponents$WithThemeReactComponentClass = < - InputProps: { theme: $npm$styledComponents$Theme }, - InputDefaultProps: {}, - OutputProps: $Diff, - OutputDefaultProps: InputDefaultProps & { theme: $npm$styledComponents$Theme }, ->($npm$styledComponents$ReactComponentClass) => $npm$styledComponents$ReactComponentClass - -type $npm$styledComponents$WithThemeReactComponentClassUndefinedDefaultProps = < - InputProps: { theme: $npm$styledComponents$Theme }, - OutputProps: $Diff, ->($npm$styledComponents$ReactComponentClassUndefinedDefaultProps) => $npm$styledComponents$ReactComponentClass - -type $npm$styledComponents$WithThemeReactComponentFunctional = < - InputProps: { theme: $npm$styledComponents$Theme }, - InputDefaultProps: {}, - OutputProps: $Diff, - OutputDefaultProps: InputDefaultProps & { theme: $npm$styledComponents$Theme }, ->($npm$styledComponents$ReactComponentFunctional) => $npm$styledComponents$ReactComponentFunctional - -type $npm$styledComponents$WithThemeReactComponentFunctionalUndefinedDefaultProps = < - InputProps: { theme: $npm$styledComponents$Theme }, - OutputProps: $Diff ->($npm$styledComponents$ReactComponentFunctionalUndefinedDefaultProps) => $npm$styledComponents$ReactComponentFunctional - -type $npm$styledComponents$WithTheme = - & $npm$styledComponents$WithThemeReactComponentClass - & $npm$styledComponents$WithThemeReactComponentClassUndefinedDefaultProps - & $npm$styledComponents$WithThemeReactComponentFunctional - & $npm$styledComponents$WithThemeReactComponentFunctionalUndefinedDefaultProps - -// ---- MISC ---- -type $npm$styledComponents$Theme = $ReadOnly<{[key: string]: mixed}>; -type $npm$styledComponents$ThemeProviderProps = { - theme: $npm$styledComponents$Theme | ((outerTheme: $npm$styledComponents$Theme) => void) -}; - -class Npm$StyledComponents$ThemeProvider extends React$Component<$npm$styledComponents$ThemeProviderProps> {} - -class Npm$StyledComponents$StyleSheetManager extends React$Component<{ sheet: mixed }> {} - -class Npm$StyledComponents$ServerStyleSheet { - instance: StyleSheet - collectStyles: (children: any) => React$Node - getStyleTags: () => string - getStyleElement: () => React$Node - interleaveWithNodeStream: (readableStream: stream$Readable) => stream$Readable -} - -type $npm$styledComponents$StyledComponentsComponentListKeys = - $Subtype<$Keys<$npm$styledComponents$StyledComponentsComponentList>> - -type $npm$styledComponents$StyledComponentsComponentListValue = - $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent<{}, $npm$styledComponents$StyledComponentsComponentListKeys> - -// ---- COMPONENT LIST ---- -type $npm$styledComponents$StyledComponentsComponentList = {| - a: $npm$styledComponents$StyledComponentsComponentListValue, - abbr: $npm$styledComponents$StyledComponentsComponentListValue, - address: $npm$styledComponents$StyledComponentsComponentListValue, - area: $npm$styledComponents$StyledComponentsComponentListValue, - article: $npm$styledComponents$StyledComponentsComponentListValue, - aside: $npm$styledComponents$StyledComponentsComponentListValue, - audio: $npm$styledComponents$StyledComponentsComponentListValue, - b: $npm$styledComponents$StyledComponentsComponentListValue, - base: $npm$styledComponents$StyledComponentsComponentListValue, - bdi: $npm$styledComponents$StyledComponentsComponentListValue, - bdo: $npm$styledComponents$StyledComponentsComponentListValue, - big: $npm$styledComponents$StyledComponentsComponentListValue, - blockquote: $npm$styledComponents$StyledComponentsComponentListValue, - body: $npm$styledComponents$StyledComponentsComponentListValue, - br: $npm$styledComponents$StyledComponentsComponentListValue, - button: $npm$styledComponents$StyledComponentsComponentListValue, - canvas: $npm$styledComponents$StyledComponentsComponentListValue, - caption: $npm$styledComponents$StyledComponentsComponentListValue, - cite: $npm$styledComponents$StyledComponentsComponentListValue, - code: $npm$styledComponents$StyledComponentsComponentListValue, - col: $npm$styledComponents$StyledComponentsComponentListValue, - colgroup: $npm$styledComponents$StyledComponentsComponentListValue, - data: $npm$styledComponents$StyledComponentsComponentListValue, - datalist: $npm$styledComponents$StyledComponentsComponentListValue, - dd: $npm$styledComponents$StyledComponentsComponentListValue, - del: $npm$styledComponents$StyledComponentsComponentListValue, - details: $npm$styledComponents$StyledComponentsComponentListValue, - dfn: $npm$styledComponents$StyledComponentsComponentListValue, - dialog: $npm$styledComponents$StyledComponentsComponentListValue, - div: $npm$styledComponents$StyledComponentsComponentListValue, - dl: $npm$styledComponents$StyledComponentsComponentListValue, - dt: $npm$styledComponents$StyledComponentsComponentListValue, - em: $npm$styledComponents$StyledComponentsComponentListValue, - embed: $npm$styledComponents$StyledComponentsComponentListValue, - fieldset: $npm$styledComponents$StyledComponentsComponentListValue, - figcaption: $npm$styledComponents$StyledComponentsComponentListValue, - figure: $npm$styledComponents$StyledComponentsComponentListValue, - footer: $npm$styledComponents$StyledComponentsComponentListValue, - form: $npm$styledComponents$StyledComponentsComponentListValue, - h1: $npm$styledComponents$StyledComponentsComponentListValue, - h2: $npm$styledComponents$StyledComponentsComponentListValue, - h3: $npm$styledComponents$StyledComponentsComponentListValue, - h4: $npm$styledComponents$StyledComponentsComponentListValue, - h5: $npm$styledComponents$StyledComponentsComponentListValue, - h6: $npm$styledComponents$StyledComponentsComponentListValue, - head: $npm$styledComponents$StyledComponentsComponentListValue, - header: $npm$styledComponents$StyledComponentsComponentListValue, - hgroup: $npm$styledComponents$StyledComponentsComponentListValue, - hr: $npm$styledComponents$StyledComponentsComponentListValue, - html: $npm$styledComponents$StyledComponentsComponentListValue, - i: $npm$styledComponents$StyledComponentsComponentListValue, - iframe: $npm$styledComponents$StyledComponentsComponentListValue, - img: $npm$styledComponents$StyledComponentsComponentListValue, - input: $npm$styledComponents$StyledComponentsComponentListValue, - ins: $npm$styledComponents$StyledComponentsComponentListValue, - kbd: $npm$styledComponents$StyledComponentsComponentListValue, - keygen: $npm$styledComponents$StyledComponentsComponentListValue, - label: $npm$styledComponents$StyledComponentsComponentListValue, - legend: $npm$styledComponents$StyledComponentsComponentListValue, - li: $npm$styledComponents$StyledComponentsComponentListValue, - link: $npm$styledComponents$StyledComponentsComponentListValue, - main: $npm$styledComponents$StyledComponentsComponentListValue, - map: $npm$styledComponents$StyledComponentsComponentListValue, - mark: $npm$styledComponents$StyledComponentsComponentListValue, - menu: $npm$styledComponents$StyledComponentsComponentListValue, - menuitem: $npm$styledComponents$StyledComponentsComponentListValue, - meta: $npm$styledComponents$StyledComponentsComponentListValue, - meter: $npm$styledComponents$StyledComponentsComponentListValue, - nav: $npm$styledComponents$StyledComponentsComponentListValue, - noscript: $npm$styledComponents$StyledComponentsComponentListValue, - object: $npm$styledComponents$StyledComponentsComponentListValue, - ol: $npm$styledComponents$StyledComponentsComponentListValue, - optgroup: $npm$styledComponents$StyledComponentsComponentListValue, - option: $npm$styledComponents$StyledComponentsComponentListValue, - output: $npm$styledComponents$StyledComponentsComponentListValue, - p: $npm$styledComponents$StyledComponentsComponentListValue, - param: $npm$styledComponents$StyledComponentsComponentListValue, - picture: $npm$styledComponents$StyledComponentsComponentListValue, - pre: $npm$styledComponents$StyledComponentsComponentListValue, - progress: $npm$styledComponents$StyledComponentsComponentListValue, - q: $npm$styledComponents$StyledComponentsComponentListValue, - rp: $npm$styledComponents$StyledComponentsComponentListValue, - rt: $npm$styledComponents$StyledComponentsComponentListValue, - ruby: $npm$styledComponents$StyledComponentsComponentListValue, - s: $npm$styledComponents$StyledComponentsComponentListValue, - samp: $npm$styledComponents$StyledComponentsComponentListValue, - script: $npm$styledComponents$StyledComponentsComponentListValue, - section: $npm$styledComponents$StyledComponentsComponentListValue, - select: $npm$styledComponents$StyledComponentsComponentListValue, - small: $npm$styledComponents$StyledComponentsComponentListValue, - source: $npm$styledComponents$StyledComponentsComponentListValue, - span: $npm$styledComponents$StyledComponentsComponentListValue, - strong: $npm$styledComponents$StyledComponentsComponentListValue, - style: $npm$styledComponents$StyledComponentsComponentListValue, - sub: $npm$styledComponents$StyledComponentsComponentListValue, - summary: $npm$styledComponents$StyledComponentsComponentListValue, - sup: $npm$styledComponents$StyledComponentsComponentListValue, - table: $npm$styledComponents$StyledComponentsComponentListValue, - tbody: $npm$styledComponents$StyledComponentsComponentListValue, - td: $npm$styledComponents$StyledComponentsComponentListValue, - textarea: $npm$styledComponents$StyledComponentsComponentListValue, - tfoot: $npm$styledComponents$StyledComponentsComponentListValue, - th: $npm$styledComponents$StyledComponentsComponentListValue, - thead: $npm$styledComponents$StyledComponentsComponentListValue, - time: $npm$styledComponents$StyledComponentsComponentListValue, - title: $npm$styledComponents$StyledComponentsComponentListValue, - tr: $npm$styledComponents$StyledComponentsComponentListValue, - track: $npm$styledComponents$StyledComponentsComponentListValue, - u: $npm$styledComponents$StyledComponentsComponentListValue, - ul: $npm$styledComponents$StyledComponentsComponentListValue, - var: $npm$styledComponents$StyledComponentsComponentListValue, - video: $npm$styledComponents$StyledComponentsComponentListValue, - wbr: $npm$styledComponents$StyledComponentsComponentListValue, - - // SVG - circle: $npm$styledComponents$StyledComponentsComponentListValue, - clipPath: $npm$styledComponents$StyledComponentsComponentListValue, - defs: $npm$styledComponents$StyledComponentsComponentListValue, - ellipse: $npm$styledComponents$StyledComponentsComponentListValue, - g: $npm$styledComponents$StyledComponentsComponentListValue, - image: $npm$styledComponents$StyledComponentsComponentListValue, - line: $npm$styledComponents$StyledComponentsComponentListValue, - linearGradient: $npm$styledComponents$StyledComponentsComponentListValue, - mask: $npm$styledComponents$StyledComponentsComponentListValue, - path: $npm$styledComponents$StyledComponentsComponentListValue, - pattern: $npm$styledComponents$StyledComponentsComponentListValue, - polygon: $npm$styledComponents$StyledComponentsComponentListValue, - polyline: $npm$styledComponents$StyledComponentsComponentListValue, - radialGradient: $npm$styledComponents$StyledComponentsComponentListValue, - rect: $npm$styledComponents$StyledComponentsComponentListValue, - stop: $npm$styledComponents$StyledComponentsComponentListValue, - svg: $npm$styledComponents$StyledComponentsComponentListValue, - text: $npm$styledComponents$StyledComponentsComponentListValue, - tspan: $npm$styledComponents$StyledComponentsComponentListValue, -|} - -type $npm$styledComponents$StyledComponentsNativeComponentListKeys = - $Subtype<$Keys<$npm$styledComponents$StyledComponentsNativeComponentList>> - -type $npm$styledComponents$StyledComponentsNativeComponentListValue = - $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent<{}, $npm$styledComponents$StyledComponentsNativeComponentListKeys> - -type $npm$styledComponents$StyledComponentsNativeComponentList = {| - ActivityIndicator: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ActivityIndicatorIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ART: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Button: $npm$styledComponents$StyledComponentsNativeComponentListValue, - DatePickerIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - DrawerLayoutAndroid: $npm$styledComponents$StyledComponentsNativeComponentListValue, - FlatList: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Image: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ImageBackground: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ImageEditor: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ImageStore: $npm$styledComponents$StyledComponentsNativeComponentListValue, - KeyboardAvoidingView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ListView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - MapView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Modal: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Navigator: $npm$styledComponents$StyledComponentsNativeComponentListValue, - NavigatorIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Picker: $npm$styledComponents$StyledComponentsNativeComponentListValue, - PickerIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ProgressBarAndroid: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ProgressViewIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - RecyclerViewBackedScrollView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - RefreshControl: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SafeAreaView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ScrollView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SectionList: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SegmentedControlIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Slider: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SliderIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SnapshotViewIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - StatusBar: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SwipeableListView: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Switch: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SwitchAndroid: $npm$styledComponents$StyledComponentsNativeComponentListValue, - SwitchIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - TabBarIOS: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Text: $npm$styledComponents$StyledComponentsNativeComponentListValue, - TextInput: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ToastAndroid: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ToolbarAndroid: $npm$styledComponents$StyledComponentsNativeComponentListValue, - Touchable: $npm$styledComponents$StyledComponentsNativeComponentListValue, - TouchableHighlight: $npm$styledComponents$StyledComponentsNativeComponentListValue, - TouchableNativeFeedback: $npm$styledComponents$StyledComponentsNativeComponentListValue, - TouchableOpacity: $npm$styledComponents$StyledComponentsNativeComponentListValue, - TouchableWithoutFeedback: $npm$styledComponents$StyledComponentsNativeComponentListValue, - View: $npm$styledComponents$StyledComponentsNativeComponentListValue, - ViewPagerAndroid: $npm$styledComponents$StyledComponentsNativeComponentListValue, - VirtualizedList: $npm$styledComponents$StyledComponentsNativeComponentListValue, - WebView: $npm$styledComponents$StyledComponentsNativeComponentListValue, -|} - -declare module 'styled-components' { - declare export type Interpolation = $npm$styledComponents$Interpolation; - declare export type NameGenerator = $npm$styledComponents$NameGenerator; - declare export type Theme = $npm$styledComponents$Theme; - declare export type ThemeProviderProps = $npm$styledComponents$ThemeProviderProps; - declare export type TaggedTemplateLiteral = $npm$styledComponents$TaggedTemplateLiteral; - declare export type ComponentListKeys = $npm$styledComponents$StyledComponentsComponentListKeys; - - declare export type ReactComponentFunctional = $npm$styledComponents$ReactComponentFunctional; - declare export type ReactComponentFunctionalUndefinedDefaultProps = $npm$styledComponents$ReactComponentFunctionalUndefinedDefaultProps; - declare export type ReactComponentClass = $npm$styledComponents$ReactComponentClass; - declare export type ReactComponentClassUndefinedDefaultProps = $npm$styledComponents$ReactComponentClassUndefinedDefaultProps; - declare export type ReactComponentUnion = $npm$styledComponents$ReactComponentUnion; - declare export type ReactComponentIntersection = $npm$styledComponents$ReactComponentIntersection; - declare export type ReactComponentStyledStaticProps = $npm$styledComponents$ReactComponentStyledStaticPropsWithComponent; - declare export type ReactComponentStyled = $npm$styledComponents$ReactComponentStyled; - declare export type ReactComponentStyledTaggedTemplateLiteral = $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent; - - declare export var css: TaggedTemplateLiteral>; - declare export var injectGlobal: TaggedTemplateLiteral; - declare export var keyframes: TaggedTemplateLiteral; - declare export var withTheme: $npm$styledComponents$WithTheme; - declare export var ServerStyleSheet: typeof Npm$StyledComponents$ServerStyleSheet; - declare export var StyleSheetManager: typeof Npm$StyledComponents$StyleSheetManager; - declare export var ThemeProvider: typeof Npm$StyledComponents$ThemeProvider; - - declare export default { - css: TaggedTemplateLiteral>, - ...$npm$styledComponents$StyledComponentsComponentList, - ...$npm$styledComponents$StyledComponentsNativeComponentList, - } & { - [[call]]: $npm$styledComponents$Call - } -} - -declare module 'styled-components/native' { - declare export type Interpolation = $npm$styledComponents$Interpolation; - declare export type NameGenerator = $npm$styledComponents$NameGenerator; - declare export type Theme = $npm$styledComponents$Theme; - declare export type ThemeProviderProps = $npm$styledComponents$ThemeProviderProps; - declare export type TaggedTemplateLiteral = $npm$styledComponents$TaggedTemplateLiteral; - declare export type NativeComponentListKeys = $npm$styledComponents$StyledComponentsNativeComponentListKeys; - - declare export type ReactComponentFunctional = $npm$styledComponents$ReactComponentFunctional; - declare export type ReactComponentFunctionalUndefinedDefaultProps = $npm$styledComponents$ReactComponentFunctionalUndefinedDefaultProps; - declare export type ReactComponentClass = $npm$styledComponents$ReactComponentClass; - declare export type ReactComponentClassUndefinedDefaultProps = $npm$styledComponents$ReactComponentClassUndefinedDefaultProps; - declare export type ReactComponentUnion = $npm$styledComponents$ReactComponentUnion; - declare export type ReactComponentIntersection = $npm$styledComponents$ReactComponentIntersection; - declare export type ReactComponentStyledStaticProps = $npm$styledComponents$ReactComponentStyledStaticPropsWithComponent; - declare export type ReactComponentStyled = $npm$styledComponents$ReactComponentStyled; - declare export type ReactComponentStyledTaggedTemplateLiteral = $npm$styledComponents$ReactComponentStyledTaggedTemplateLiteralWithComponent; - - declare export var keyframes: TaggedTemplateLiteral; - declare export var withTheme: $npm$styledComponents$WithTheme; - declare export var ThemeProvider: typeof Npm$StyledComponents$ThemeProvider; - declare export default { - css: TaggedTemplateLiteral>, - ...$npm$styledComponents$StyledComponentsNativeComponentList, - } & { - [[call]]: $npm$styledComponents$Call - } -} diff --git a/flow-typed/npm/styled-components_vx.x.x.js b/flow-typed/npm/styled-components_vx.x.x.js deleted file mode 100644 index 779de37abe..0000000000 --- a/flow-typed/npm/styled-components_vx.x.x.js +++ /dev/null @@ -1,130 +0,0 @@ -// flow-typed signature: 02072b946e1e6c80e6ba8ec7275b8b1f -// flow-typed version: <>/styled-components_v^4.1.3/flow_v0.91.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'styled-components' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'styled-components' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'styled-components/dist/styled-components-macro.cjs' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components-macro.esm' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components.browser.cjs' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components.browser.esm' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components.cjs' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components.esm' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components' { - declare module.exports: any; -} - -declare module 'styled-components/dist/styled-components.min' { - declare module.exports: any; -} - -declare module 'styled-components/native/dist/styled-components.native.cjs' { - declare module.exports: any; -} - -declare module 'styled-components/native/dist/styled-components.native.esm' { - declare module.exports: any; -} - -declare module 'styled-components/primitives/dist/styled-components-primitives.cjs' { - declare module.exports: any; -} - -declare module 'styled-components/primitives/dist/styled-components-primitives.esm' { - declare module.exports: any; -} - -declare module 'styled-components/scripts/postinstall' { - declare module.exports: any; -} - -declare module 'styled-components/test-utils/index' { - declare module.exports: any; -} - -declare module 'styled-components/test-utils/setupTestFramework' { - declare module.exports: any; -} - -// Filename aliases -declare module 'styled-components/dist/styled-components-macro.cjs.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components-macro.cjs'>; -} -declare module 'styled-components/dist/styled-components-macro.esm.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components-macro.esm'>; -} -declare module 'styled-components/dist/styled-components.browser.cjs.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components.browser.cjs'>; -} -declare module 'styled-components/dist/styled-components.browser.esm.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components.browser.esm'>; -} -declare module 'styled-components/dist/styled-components.cjs.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components.cjs'>; -} -declare module 'styled-components/dist/styled-components.esm.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components.esm'>; -} -declare module 'styled-components/dist/styled-components.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components'>; -} -declare module 'styled-components/dist/styled-components.min.js' { - declare module.exports: $Exports<'styled-components/dist/styled-components.min'>; -} -declare module 'styled-components/native/dist/styled-components.native.cjs.js' { - declare module.exports: $Exports<'styled-components/native/dist/styled-components.native.cjs'>; -} -declare module 'styled-components/native/dist/styled-components.native.esm.js' { - declare module.exports: $Exports<'styled-components/native/dist/styled-components.native.esm'>; -} -declare module 'styled-components/primitives/dist/styled-components-primitives.cjs.js' { - declare module.exports: $Exports<'styled-components/primitives/dist/styled-components-primitives.cjs'>; -} -declare module 'styled-components/primitives/dist/styled-components-primitives.esm.js' { - declare module.exports: $Exports<'styled-components/primitives/dist/styled-components-primitives.esm'>; -} -declare module 'styled-components/scripts/postinstall.js' { - declare module.exports: $Exports<'styled-components/scripts/postinstall'>; -} -declare module 'styled-components/test-utils/index.js' { - declare module.exports: $Exports<'styled-components/test-utils/index'>; -} -declare module 'styled-components/test-utils/setupTestFramework.js' { - declare module.exports: $Exports<'styled-components/test-utils/setupTestFramework'>; -} diff --git a/flow-typed/npm/stylelint-config-prettier_vx.x.x.js b/flow-typed/npm/stylelint-config-prettier_vx.x.x.js index e9c430f830..f812987685 100644 --- a/flow-typed/npm/stylelint-config-prettier_vx.x.x.js +++ b/flow-typed/npm/stylelint-config-prettier_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: e2e0cee1afa7f626969cc84035053daf -// flow-typed version: <>/stylelint-config-prettier_v^5.0.0/flow_v0.96.0 +// flow-typed signature: d62894e1e78da9558a0efd67d0724a08 +// flow-typed version: <>/stylelint-config-prettier_v^5.2.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/stylelint-config-recommended_vx.x.x.js b/flow-typed/npm/stylelint-config-recommended_vx.x.x.js index 9278d52d3c..463157d2bc 100644 --- a/flow-typed/npm/stylelint-config-recommended_vx.x.x.js +++ b/flow-typed/npm/stylelint-config-recommended_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 4d751d844f8a1af496115535059ddda5 -// flow-typed version: <>/stylelint-config-recommended_v^2.1.0/flow_v0.96.0 +// flow-typed signature: 6aa0b949e364f11f152458c99b105f3f +// flow-typed version: <>/stylelint-config-recommended_v^2.2.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/stylelint-config-standard_vx.x.x.js b/flow-typed/npm/stylelint-config-standard_vx.x.x.js index 4a29fe6012..dc755936f6 100644 --- a/flow-typed/npm/stylelint-config-standard_vx.x.x.js +++ b/flow-typed/npm/stylelint-config-standard_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: ecd8e3a73e933c364b5d7e3ddafc72f2 -// flow-typed version: <>/stylelint-config-standard_v^18.2.0/flow_v0.96.0 +// flow-typed signature: 69a7f384725a057e90d113cd7a946a4f +// flow-typed version: <>/stylelint-config-standard_v^18.3.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/stylelint-config-styled-components_vx.x.x.js b/flow-typed/npm/stylelint-config-styled-components_vx.x.x.js index cc4e899a8a..04aab851a0 100644 --- a/flow-typed/npm/stylelint-config-styled-components_vx.x.x.js +++ b/flow-typed/npm/stylelint-config-styled-components_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 12d5c366ed1a01ef891ead808989f7d8 -// flow-typed version: <>/stylelint-config-styled-components_v^0.1.1/flow_v0.96.0 +// flow-typed signature: ae41bd2c966b1b444db939a131caa45d +// flow-typed version: <>/stylelint-config-styled-components_v^0.1.1/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/stylelint-processor-styled-components_vx.x.x.js b/flow-typed/npm/stylelint-processor-styled-components_vx.x.x.js index e4897f281e..fe8c5768d8 100644 --- a/flow-typed/npm/stylelint-processor-styled-components_vx.x.x.js +++ b/flow-typed/npm/stylelint-processor-styled-components_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 32fd23102fa81c7e729c9b7ed645b2bb -// flow-typed version: <>/stylelint-processor-styled-components_v^1.6.0/flow_v0.96.0 +// flow-typed signature: 719f0a401b11eda0f6cfe307ddcba591 +// flow-typed version: <>/stylelint-processor-styled-components_v^1.8.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -22,38 +22,6 @@ declare module 'stylelint-processor-styled-components' { * require those files directly. Feel free to delete any files that aren't * needed. */ -declare module 'stylelint-processor-styled-components/lib/index' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/parsers/babylon-parser' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/parsers/index' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/utils/general' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/utils/parse' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/utils/result' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/utils/styled' { - declare module.exports: any; -} - -declare module 'stylelint-processor-styled-components/lib/utils/tagged-template-literal' { - declare module.exports: any; -} - declare module 'stylelint-processor-styled-components/src/index' { declare module.exports: any; } @@ -283,30 +251,6 @@ declare module 'stylelint-processor-styled-components/test/utils.test' { } // Filename aliases -declare module 'stylelint-processor-styled-components/lib/index.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/index'>; -} -declare module 'stylelint-processor-styled-components/lib/parsers/babylon-parser.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/parsers/babylon-parser'>; -} -declare module 'stylelint-processor-styled-components/lib/parsers/index.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/parsers/index'>; -} -declare module 'stylelint-processor-styled-components/lib/utils/general.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/utils/general'>; -} -declare module 'stylelint-processor-styled-components/lib/utils/parse.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/utils/parse'>; -} -declare module 'stylelint-processor-styled-components/lib/utils/result.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/utils/result'>; -} -declare module 'stylelint-processor-styled-components/lib/utils/styled.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/utils/styled'>; -} -declare module 'stylelint-processor-styled-components/lib/utils/tagged-template-literal.js' { - declare module.exports: $Exports<'stylelint-processor-styled-components/lib/utils/tagged-template-literal'>; -} declare module 'stylelint-processor-styled-components/src/index.js' { declare module.exports: $Exports<'stylelint-processor-styled-components/src/index'>; } diff --git a/flow-typed/npm/stylelint_vx.x.x.js b/flow-typed/npm/stylelint_vx.x.x.js index 5710ed642d..38f76d550b 100644 --- a/flow-typed/npm/stylelint_vx.x.x.js +++ b/flow-typed/npm/stylelint_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: ca493817c78918df93fa14498da586b5 -// flow-typed version: <>/stylelint_v^9.10.1/flow_v0.96.0 +// flow-typed signature: 73ce070eb7b8980832357c991cbfcfe6 +// flow-typed version: <>/stylelint_v^10.1.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: @@ -178,6 +178,10 @@ declare module 'stylelint/lib/rules/at-rule-no-vendor-prefix/index' { declare module.exports: any; } +declare module 'stylelint/lib/rules/at-rule-property-requirelist/index' { + declare module.exports: any; +} + declare module 'stylelint/lib/rules/at-rule-semicolon-newline-after/index' { declare module.exports: any; } @@ -1066,6 +1070,10 @@ declare module 'stylelint/lib/utils/hasTplInterpolation' { declare module.exports: any; } +declare module 'stylelint/lib/utils/hasUnresolvedNestedSelector' { + declare module.exports: any; +} + declare module 'stylelint/lib/utils/isAfterComment' { declare module.exports: any; } @@ -1230,6 +1238,10 @@ declare module 'stylelint/lib/utils/nodeContextLookup' { declare module.exports: any; } +declare module 'stylelint/lib/utils/noFilesFoundError' { + declare module.exports: any; +} + declare module 'stylelint/lib/utils/optionsMatches' { declare module.exports: any; } @@ -1290,6 +1302,10 @@ declare module 'stylelint/lib/vendor/writeFileAtomic' { declare module.exports: any; } +declare module 'stylelint/lib/writeOutputFile' { + declare module.exports: any; +} + // Filename aliases declare module 'stylelint/bin/stylelint.js' { declare module.exports: $Exports<'stylelint/bin/stylelint'>; @@ -1408,6 +1424,9 @@ declare module 'stylelint/lib/rules/at-rule-no-unknown/index.js' { declare module 'stylelint/lib/rules/at-rule-no-vendor-prefix/index.js' { declare module.exports: $Exports<'stylelint/lib/rules/at-rule-no-vendor-prefix/index'>; } +declare module 'stylelint/lib/rules/at-rule-property-requirelist/index.js' { + declare module.exports: $Exports<'stylelint/lib/rules/at-rule-property-requirelist/index'>; +} declare module 'stylelint/lib/rules/at-rule-semicolon-newline-after/index.js' { declare module.exports: $Exports<'stylelint/lib/rules/at-rule-semicolon-newline-after/index'>; } @@ -2074,6 +2093,9 @@ declare module 'stylelint/lib/utils/hasScssInterpolation.js' { declare module 'stylelint/lib/utils/hasTplInterpolation.js' { declare module.exports: $Exports<'stylelint/lib/utils/hasTplInterpolation'>; } +declare module 'stylelint/lib/utils/hasUnresolvedNestedSelector.js' { + declare module.exports: $Exports<'stylelint/lib/utils/hasUnresolvedNestedSelector'>; +} declare module 'stylelint/lib/utils/isAfterComment.js' { declare module.exports: $Exports<'stylelint/lib/utils/isAfterComment'>; } @@ -2197,6 +2219,9 @@ declare module 'stylelint/lib/utils/nextNonCommentNode.js' { declare module 'stylelint/lib/utils/nodeContextLookup.js' { declare module.exports: $Exports<'stylelint/lib/utils/nodeContextLookup'>; } +declare module 'stylelint/lib/utils/noFilesFoundError.js' { + declare module.exports: $Exports<'stylelint/lib/utils/noFilesFoundError'>; +} declare module 'stylelint/lib/utils/optionsMatches.js' { declare module.exports: $Exports<'stylelint/lib/utils/optionsMatches'>; } @@ -2242,3 +2267,6 @@ declare module 'stylelint/lib/utils/whitespaceChecker.js' { declare module 'stylelint/lib/vendor/writeFileAtomic.js' { declare module.exports: $Exports<'stylelint/lib/vendor/writeFileAtomic'>; } +declare module 'stylelint/lib/writeOutputFile.js' { + declare module.exports: $Exports<'stylelint/lib/writeOutputFile'>; +} diff --git a/flow-typed/npm/testcafe-reporter-xunit_vx.x.x.js b/flow-typed/npm/testcafe-reporter-xunit_vx.x.x.js index 50fc039940..a4115d68a7 100644 --- a/flow-typed/npm/testcafe-reporter-xunit_vx.x.x.js +++ b/flow-typed/npm/testcafe-reporter-xunit_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 9c7c3224b59d0c207dcd74e3aa1f32d7 -// flow-typed version: <>/testcafe-reporter-xunit_v^2.1.0/flow_v0.96.0 +// flow-typed signature: 2e89a36cbe1275ac1a18150722b00ddb +// flow-typed version: <>/testcafe-reporter-xunit_v^2.1.0/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/testcafe_v0.x.x.js b/flow-typed/npm/testcafe_v0.x.x.js deleted file mode 100644 index 52983e0a70..0000000000 --- a/flow-typed/npm/testcafe_v0.x.x.js +++ /dev/null @@ -1,857 +0,0 @@ -// flow-typed signature: 47a32e7bccec89c55d746b93b3a95417 -// flow-typed version: 2ba87494a7/testcafe_v0.x.x/flow_>=v0.63.x - -/** - * Flowtype definitions for TestCafe - * Based on definitions generated by Flowgen - * Flowgen v1.2.0 - * Author: [Joar Wilk](http://twitter.com/joarwilk) - * Repo: http://github.com/joarwilk/flowgen - */ - -declare type TestCafe$CustomPropsSnapshotTypeTransform = ( - (node: HTMLElement) => V | Promise, -) => V; -declare type TestCafe$CustomPropsSelectorTypeTransform = ( - (node: HTMLElement) => V | Promise, -) => Promise; -declare type TestCafe$CustomMethodsSelectorTypeTransform = ( - (node: HTMLElement, ...args: any) => V | Promise, -) => (...args: any) => Promise; - -declare type TestCafe$ClientFunctionOptions = { - dependencies?: { [string]: any }, - - boundTestRun?: TestCafe$TestController, -}; - -declare interface TestCafe$TextRectangle { - bottom: number; - left: number; - right: number; - top: number; - width: number; - height: number; -} - -declare interface TestCafe$NodeSnapshot { - childElementCount: number; - childNodeCount: number; - hasChildElements: boolean; - hasChildNodes: boolean; - nodeType: number; - textContent: string; - attributes?: { [name: string]: string }; - boundingClientRect?: TestCafe$TextRectangle; - checked?: boolean | void; - classNames?: string[]; - clientHeight?: number; - clientLeft?: number; - clientTop?: number; - clientWidth?: number; - focused?: boolean; - id?: string; - innerText?: string; - namespaceURI?: string | null; - offsetHeight?: number; - offsetLeft?: number; - offsetTop?: number; - offsetWidth?: number; - selected?: boolean | void; - selectedIndex?: number | void; - scrollHeight?: number; - scrollLeft?: number; - scrollTop?: number; - scrollWidth?: number; - style?: { [prop: string]: string }; - tagName?: string; - value?: string | void; - visible?: boolean; - hasClass(className: string): boolean; - getStyleProperty(propertyName: string): string; - getAttribute(attributeName: string): string; - getBoundingClientRectProperty(propertyName: string): number; - hasAttribute(attributeName: string): boolean; -} - -declare interface TestCafe$SelectorOptions { - boundTestRun?: TestCafe$TestController; - timeout?: number; - visibilityCheck?: boolean; -} - -declare interface TestCafe$SelectorAPI { - childElementCount: Promise; - childNodeCount: Promise; - hasChildElements: Promise; - hasChildNodes: Promise; - nodeType: Promise; - textContent: Promise; - attributes: Promise<{ [name: string]: string }>; - boundingClientRect: Promise; - checked: Promise; - classNames: Promise; - clientHeight: Promise; - clientLeft: Promise; - clientTop: Promise; - clientWidth: Promise; - focused: Promise; - id: Promise; - innerText: Promise; - namespaceURI: Promise; - offsetHeight: Promise; - offsetLeft: Promise; - offsetTop: Promise; - offsetWidth: Promise; - selected: Promise; - selectedIndex: Promise; - scrollHeight: Promise; - scrollLeft: Promise; - scrollTop: Promise; - scrollWidth: Promise; - style: Promise<{ [prop: string]: string }>; - tagName: Promise; - value: Promise; - visible: Promise; - - hasClass(className: string): Promise; - getStyleProperty(propertyName: string): Promise; - getAttribute(attributeName: string): Promise; - getBoundingClientRectProperty(propertyName: string): Promise; - hasAttribute(attributeName: string): Promise; - nth(index: number): TestCafe$SelectorFn; - withText(text: string): TestCafe$SelectorFn; - withText(re: RegExp): TestCafe$SelectorFn; - withExactText(text: string): TestCafe$SelectorFn; - withAttribute( - attrName: string | RegExp, - attrValue?: string | RegExp, - ): TestCafe$SelectorPromise; - filterVisible(): TestCafe$SelectorFn; - filterHidden(): TestCafe$SelectorFn; - filter(cssSelector: string): TestCafe$SelectorFn; - filter( - filterFn: (node: Element, idx: number) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - find(cssSelector: string): TestCafe$SelectorFn; - find( - filterFn: (node: Element, idx: number, originNode: Element) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - parent(): TestCafe$SelectorFn; - parent(index: number): TestCafe$SelectorFn; - parent(cssSelector: string): TestCafe$SelectorFn; - parent( - filterFn: (node: Element, idx: number, originNode: Element) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - child(): TestCafe$SelectorFn; - child(index: number): TestCafe$SelectorFn; - child(cssSelector: string): TestCafe$SelectorFn; - child( - filterFn: (node: Element, idx: number, originNode: Element) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - sibling(): TestCafe$SelectorFn; - - sibling(index: number): TestCafe$SelectorFn; - - sibling(cssSelector: string): TestCafe$SelectorFn; - - sibling( - filterFn: (node: Element, idx: number, originNode: Element) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - nextSibling(): TestCafe$SelectorFn; - - nextSibling(index: number): TestCafe$SelectorFn; - - nextSibling(cssSelector: string): TestCafe$SelectorFn; - - nextSibling( - filterFn: (node: Element, idx: number, originNode: Element) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - prevSibling(): TestCafe$SelectorFn; - - prevSibling(index: number): TestCafe$SelectorFn; - - prevSibling(cssSelector: string): TestCafe$SelectorFn; - - prevSibling( - filterFn: (node: Element, idx: number, originNode: Element) => boolean, - dependencies?: { [string]: any }, - ): TestCafe$SelectorFn; - - exists: Promise; - - count: Promise; - - addCustomDOMProperties(props: T): TestCafe$CustomPropsSelectorFn; - - addCustomMethods(methods: T): TestCafe$CustomMethodsSelectorFn; - - with(options?: TestCafe$SelectorOptions): TestCafe$SelectorFn; -} - -declare interface TestCafe$SelectorPromise - extends TestCafe$SelectorAPI, - Promise {} - -declare interface TestCafe$CustomMethodsSelectorPromiseI - extends TestCafe$SelectorAPI, - Promise< - TestCafe$NodeSnapshot & - $ObjMap, - > {} - -declare type TestCafe$CustomMethodsSelectorPromise< - T, -> = TestCafe$CustomMethodsSelectorPromiseI & - $ObjMap; - -declare interface TestCafe$CustomPropsSelectorPromiseI - extends TestCafe$SelectorAPI, - Promise< - TestCafe$NodeSnapshot & - $ObjMap, - > {} - -declare type TestCafe$CustomPropsSelectorPromise< - T, -> = TestCafe$CustomPropsSelectorPromiseI & - $ObjMap; - -declare interface TestCafe$RoleOptions { - preseveUrl?: boolean; -} - -declare interface TestCafe$KeyModifiers { - ctrl?: boolean; - alt?: boolean; - shift?: boolean; - meta?: boolean; -} - -declare interface TestCafe$CropOptions { - left?: number; - right?: number; - top?: number; - bottom?: number; -} - -declare interface TestCafe$ActionOptions { - speed?: number; -} - -declare interface TestCafe$TakeElementScreenshotOptions - extends TestCafe$ActionOptions { - crop?: TestCafe$CropOptions; - includeMargins?: boolean; - includeBorders?: boolean; - includePaddings?: boolean; - scrollTargetX?: number; - scrollTargetY?: number; -} - -declare interface TestCafe$MouseActionOptions extends TestCafe$ActionOptions { - offsetX?: number; - offsetY?: number; - modifiers?: TestCafe$KeyModifiers; -} - -declare interface TestCafe$ClickActionOptions - extends TestCafe$MouseActionOptions { - caretPos?: number; -} - -declare interface TestCafe$DragToElementOptions - extends TestCafe$MouseActionOptions { - destinationOffsetX?: number; - destinationOffsetY?: number; -} - -declare interface TestCafe$TypeActionOptions - extends TestCafe$ClickActionOptions { - replace?: boolean; - paste?: boolean; -} - -declare interface TestCafe$ResizeToFitDeviceOptions { - portraitOrientation?: boolean; -} - -declare interface TestCafe$NativeDialogHistoryItem { - type: 'alert' | 'confirm' | 'beforeunload' | 'prompt'; - text: string; - url: string; -} - -declare interface TestCafe$RequestLogger { - contains(predicate: Function): Promise; - count(predicate: Function): Promise; - clear(): void; - - requests: TestCafe$Request[]; -} - -declare interface TestCafe$RequestLoggerOptions { - logRequestHeaders?: boolean; - logRequestBody?: boolean; - stringifyRequestBody?: boolean; - logResponseHeaders?: boolean; - logResponseBody?: boolean; - stringifyResponseBody?: boolean; -} - -interface TestCafe$RequestMock { - onRequestTo( - filter: - | string - | RegExp - | Object - | ((req: TestCafe$RequestData, res: TestCafe$ResponseData) => boolean), - ): TestCafe$RequestMock; - - respond( - body?: - | Object - | string - | ((req: TestCafe$RequestData, res: TestCafe$ResponseData) => any), - statusCode?: number, - headers?: Object, - ): TestCafe$RequestMock; -} - -interface TestCafe$Request { - userAgent: string; - request: TestCafe$RequestData; - response: TestCafe$ResponseData; -} - -interface TestCafe$RequestData { - url: string; - method: string; - headers: Object; - body: string | any; -} - -interface TestCafe$ResponseData { - statusCode: string; - headers: Object; - body: string | any; -} - -declare type TestCafe$SelectorParameter = - | string - | TestCafe$SelectorFn - | TestCafe$NodeSnapshot - | TestCafe$SelectorPromise - | (( - ...args: any[] - ) => null | Node | Node[] | NodeList<*> | HTMLCollection<*>); - -declare interface TestCafe$TestController { - ctx: { [key: string]: any }; - fixtureCtx: { [key: string]: any }; - - click( - selector: TestCafe$SelectorParameter, - options?: TestCafe$ClickActionOptions, - ): TestCafe$TestControllerPromise; - - rightClick( - selector: TestCafe$SelectorParameter, - options?: TestCafe$ClickActionOptions, - ): TestCafe$TestControllerPromise; - - doubleClick( - selector: TestCafe$SelectorParameter, - options?: TestCafe$ClickActionOptions, - ): TestCafe$TestControllerPromise; - - hover( - selector: TestCafe$SelectorParameter, - options?: TestCafe$MouseActionOptions, - ): TestCafe$TestControllerPromise; - - drag( - selector: TestCafe$SelectorParameter, - dragOffsetX: number, - dragOffsetY: number, - options?: TestCafe$DragToElementOptions, - ): TestCafe$TestControllerPromise; - - dragToElement( - selector: TestCafe$SelectorParameter, - destinationSelector: TestCafe$SelectorParameter, - options?: TestCafe$MouseActionOptions, - ): TestCafe$TestControllerPromise; - - typeText( - selector: TestCafe$SelectorParameter, - text: string, - options?: TestCafe$TypeActionOptions, - ): TestCafe$TestControllerPromise; - - selectText( - selector: TestCafe$SelectorParameter, - startPos?: number, - endPos?: number, - options?: TestCafe$ActionOptions, - ): TestCafe$TestControllerPromise; - - selectTextAreaContent( - selector: TestCafe$SelectorParameter, - startLine?: number, - startPos?: number, - endLine?: number, - endPos?: number, - options?: TestCafe$ActionOptions, - ): TestCafe$TestControllerPromise; - - selectEditableContent( - startSelector: TestCafe$SelectorParameter, - endSelector: TestCafe$SelectorParameter, - options?: TestCafe$ActionOptions, - ): TestCafe$TestControllerPromise; - - pressKey( - keys: string, - options?: TestCafe$ActionOptions, - ): TestCafe$TestControllerPromise; - - wait(timeout: number): TestCafe$TestControllerPromise; - - navigateTo(url: string): TestCafe$TestControllerPromise; - - setFilesToUpload( - selector: TestCafe$SelectorParameter, - filePath: string | string[], - ): TestCafe$TestControllerPromise; - - clearUpload( - selector: TestCafe$SelectorParameter, - ): TestCafe$TestControllerPromise; - - takeScreenshot(path?: string): TestCafe$TestControllerPromise; - - takeElementScreenshot( - selector: TestCafe$SelectorParameter, - path?: string, - options?: TestCafe$TakeElementScreenshotOptions, - ): TestCafe$TestControllerPromise; - - resizeWindow(width: number, height: number): TestCafe$TestControllerPromise; - - resizeWindowToFitDevice( - deviceName: string, - options?: TestCafe$ResizeToFitDeviceOptions, - ): TestCafe$TestControllerPromise; - - maximizeWindow(): TestCafe$TestControllerPromise; - - switchToIframe( - selector: TestCafe$SelectorParameter, - ): TestCafe$TestControllerPromise; - - switchToMainWindow(): TestCafe$TestControllerPromise; - - eval(fn: Function, options?: TestCafe$ClientFunctionOptions): Promise; - - setNativeDialogHandler( - fn: - | (( - type: 'alert' | 'confirm' | 'beforeunload' | 'prompt', - text: string, - url: string, - ) => any) - | null, - options?: TestCafe$ClientFunctionOptions, - ): TestCafe$TestControllerPromise; - - getNativeDialogHistory(): Promise; - - expect(actual: any): TestCafe$Assertion; - - debug(): TestCafe$TestControllerPromise; - - setTestSpeed(speed: number): TestCafe$TestControllerPromise; - - setPageLoadTimeout(duration: number): TestCafe$TestControllerPromise; - - useRole(role: TestCafe$RoleFn): TestCafe$TestControllerPromise; - - addRequestHooks(...hooks: Object[]): TestCafe$TestControllerPromise; - - removeRequestHooks(...hooks: Object[]): TestCafe$TestControllerPromise; -} - -declare interface TestCafe$TestControllerPromise - extends TestCafe$TestController, - Promise {} - -declare interface TestCafe$AssertionOptions { - timeout?: number; - allowUnawaitedPromise?: boolean; -} - -declare interface TestCafe$Assertion { - eql( - expected: any, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - eql( - expected: any, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notEql( - unexpected: any, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notEql( - unexpected: any, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - ok( - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - ok(options?: TestCafe$AssertionOptions): TestCafe$TestControllerPromise; - - notOk( - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notOk(options?: TestCafe$AssertionOptions): TestCafe$TestControllerPromise; - - contains( - expected: any, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - contains( - expected: any, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notContains( - unexpected: any, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notContains( - unexpected: any, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - typeOf( - typeName: string, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - typeOf( - typeName: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notTypeOf( - typeName: string, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notTypeOf( - typeName: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - gt( - expected: number, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - gt( - expected: number, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - gte( - expected: number, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - gte( - expected: number, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - lt( - expected: number, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - lt( - expected: number, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - lte( - expected: number, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - lte( - expected: number, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - within( - start: number, - finish: number, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - within( - start: number, - finish: number, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notWithin( - start: number, - finish: number, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notWithin( - start: number, - finish: number, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - match( - re: RegExp, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - match( - re: RegExp, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notMatch( - re: RegExp, - message?: string, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; - - notMatch( - re: RegExp, - options?: TestCafe$AssertionOptions, - ): TestCafe$TestControllerPromise; -} - -declare interface TestCafe$HTTPAuthCredentials { - username: string; - password: string; - domain?: string; - workstation?: string; -} - -declare interface TestCafe$FixtureFn { - (name: string | string[]): TestCafe$FixtureFn; - page(url: string | string[]): TestCafe$FixtureFn; - httpAuth(credentials: TestCafe$HTTPAuthCredentials): TestCafe$FixtureFn; - before(fn: (ctx: { [key: string]: any }) => Promise): any; - after(fn: (ctx: { [key: string]: any }) => Promise): any; - beforeEach( - fn: (t: TestCafe$TestController) => Promise, - ): TestCafe$FixtureFn; - afterEach( - fn: (t: TestCafe$TestController) => Promise, - ): TestCafe$FixtureFn; - skip: TestCafe$FixtureFn; - only: TestCafe$FixtureFn; - meta(key: string, value: string): TestCafe$FixtureFn; - meta(data: Object): TestCafe$FixtureFn; - requestHooks(...hooks: Object[]): TestCafe$TestFn; -} - -declare interface TestCafe$TestFn { - ( - name: string | string[], - fn: (t: TestCafe$TestController) => Promise, - ): TestCafe$TestFn; - page(url: string | string[]): TestCafe$TestFn; - httpAuth(credentials: TestCafe$HTTPAuthCredentials): TestCafe$TestFn; - before(fn: (t: TestCafe$TestController) => Promise): TestCafe$TestFn; - after(fn: (t: TestCafe$TestController) => Promise): TestCafe$TestFn; - skip: TestCafe$TestFn; - only: TestCafe$TestFn; - meta(key: string, value: string): TestCafe$TestFn; - meta(data: Object): TestCafe$TestFn; - requestHooks(...hooks: Object[]): TestCafe$TestFn; -} - -declare interface TestCafe$SelectorCallable { - (...args: any[]): TestCafe$SelectorPromise; -} - -declare interface TestCafe$CustomSelectorCallable { - (...args: any[]): T; -} - -declare type TestCafe$SelectorFn = TestCafe$SelectorAPI & - TestCafe$SelectorCallable; - -declare type TestCafe$CustomSelectorFnI = TestCafe$SelectorAPI & - TestCafe$CustomSelectorCallable; - -declare type TestCafe$CustomPropsSelectorFn = TestCafe$CustomSelectorFnI< - TestCafe$CustomPropsSelectorPromise, -> & - $ObjMap; - -declare type TestCafe$CustomMethodsSelectorFn = TestCafe$CustomSelectorFnI< - TestCafe$CustomMethodsSelectorPromise, -> & - $ObjMap; - -declare interface TestCafe$ClientFunctionFn { - (...args: any[]): Promise; - with(options: TestCafe$ClientFunctionOptions): TestCafe$ClientFunctionFn; -} - -declare interface TestCafe$RoleFn { - ( - url: string, - fn: (t: TestCafe$TestController) => Promise, - options?: TestCafe$RoleOptions, - ): TestCafe$RoleFn; - anonymous(): TestCafe$RoleFn; -} - -declare function TestCafe$RequestMockFn(): TestCafe$RequestMock; - -declare function TestCafe$RequestLoggerFn( - filter?: - | string - | RegExp - | Object - | ((req: TestCafe$RequestData, res: TestCafe$ResponseData) => boolean), - options?: TestCafe$RequestLoggerOptions, -): TestCafe$RequestLogger; - -declare class TestCafe$RequestHookClass { - constructor( - requestFilterRules?: any[], - responseEventConfigureOpts?: Object, - ): TestCafe$RequestHookClass; - onRequest(requestEvent: Object): void; - onResponse(responseEvent: Object): void; -} - -declare var fixture: TestCafe$FixtureFn; -declare var test: TestCafe$TestFn; - -declare module 'testcafe' { - declare interface BrowserConnection { - url: string; - on(event: 'ready', handler: Function): BrowserConnection; - } - - declare type BrowserType = - | string - | { path: string, cmd: string } - | BrowserConnection; - - declare interface Stream { - write(chunk: string): any; - } - - declare interface CancelablePromise extends Promise { - cancel(): Promise; - } - - declare class Runner { - src(...source: (string | string[])[]): Runner; - filter( - callback: ( - testName: string, - fixtureName: string, - fixturePath: string, - ) => boolean, - ): Runner; - browsers(...browser: (BrowserType | BrowserType[])[]): Runner; - screenshots(path: string, takeOnFails?: boolean): Runner; - reporter(name: string, outStream?: Stream): Runner; - startApp(command: string, initDelay?: number): Runner; - useProxy(host: string, bypassRules?: string | string[]): Runner; - - run(options?: { - skipJsErrors: boolean, - quarantineMode: boolean, - selectorTimeout: number, - assertionTimeout: number, - pageLoadTimeout: number, - speed: number, - debugMode: boolean, - debugOnFail: boolean, - }): CancelablePromise; - - stop(): Promise; - } - - declare interface TestCafe { - createBrowserConnection(): Promise; - createRunner(): Runner; - close(): Promise; - } - - declare module.exports: { - (hostname: string, port1: number, port2: number): Promise, - - Selector( - init: TestCafe$SelectorParameter, - options?: TestCafe$SelectorOptions, - ): TestCafe$SelectorFn, - ClientFunction( - fn: Function, - options?: TestCafe$ClientFunctionOptions, - ): TestCafe$ClientFunctionFn, - - Role: TestCafe$RoleFn, - - RequestMock: any, //TestCafe$RequestMockFn, - RequestLogger: any, //TestCafe$RequestLoggerFn, - RequestHook: Class, - - t: TestCafe$TestController, - }; -} diff --git a/flow-typed/npm/testcafe_vx.x.x.js b/flow-typed/npm/testcafe_vx.x.x.js deleted file mode 100644 index 4037d5fd8a..0000000000 --- a/flow-typed/npm/testcafe_vx.x.x.js +++ /dev/null @@ -1,1495 +0,0 @@ -// flow-typed signature: 389274d5e2bff4548c8d20c36cb70ccf -// flow-typed version: <>/testcafe_v^1.0.1/flow_v0.93.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'testcafe' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'testcafe' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'testcafe/bin/testcafe-with-v8-flag-filter' { - declare module.exports: any; -} - -declare module 'testcafe/bin/testcafe' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/exportable-lib/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/request-hooks/assert-type' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/request-hooks/hook' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/request-hooks/request-logger' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/request-hooks/request-mock' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/structure/fixture' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/structure/test-file' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/structure/test' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/structure/testing-unit' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/test-controller/assertion' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/test-controller/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/test-controller/proxy' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/test-page-url' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/test-run-tracker' { - declare module.exports: any; -} - -declare module 'testcafe/lib/api/wrap-test-function' { - declare module.exports: any; -} - -declare module 'testcafe/lib/assertions/executor' { - declare module.exports: any; -} - -declare module 'testcafe/lib/assertions/get-fn' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/connection/command' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/connection/gateway' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/connection/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/connection/remotes-queue' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/connection/status' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/connection/unstable-network-mode' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/chrome/cdp' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/chrome/config' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/chrome/create-temp-profile' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/chrome/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/chrome/local-chrome' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/chrome/runtime-info' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/config' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/create-temp-profile' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/local-firefox' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/marionette-client/commands' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/marionette-client/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/firefox/runtime-info' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/locally-installed' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/path' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/built-in/remote' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/parse-provider-name' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/plugin-host' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/pool' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/utils/argument-parsing' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/utils/browser-starter' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/utils/client-functions' { - declare module.exports: any; -} - -declare module 'testcafe/lib/browser/provider/utils/get-maximized-headless-window-size' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/argument-parser' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/cli' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/correct-browsers-and-sources' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/log' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/remotes-wizard' { - declare module.exports: any; -} - -declare module 'testcafe/lib/cli/termination-handler' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/builder-symbol' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/client-function-builder' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/replicator' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/selectors/add-api' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/selectors/create-snapshot-methods' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/selectors/selector-attribute-filter' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/selectors/selector-builder' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/selectors/selector-text-filter' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client-functions/selectors/snapshot-properties' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/automation/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/automation/index.min' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/browser/idle-page/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/core/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/core/index.min' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/driver/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/driver/index.min' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/ui/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/client/ui/index.min' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/compile-client-function' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/load-babel-libs' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/api-based' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/base' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/coffeescript/compiler' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/coffeescript/get-test-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/es-next/compiler' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/es-next/get-test-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/raw' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/typescript/compiler' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/formats/typescript/get-test-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/compiler/test-file/test-file-parser-base' { - declare module.exports: any; -} - -declare module 'testcafe/lib/configuration/default-values' { - declare module.exports: any; -} - -declare module 'testcafe/lib/configuration/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/configuration/option-conversion' { - declare module.exports: any; -} - -declare module 'testcafe/lib/configuration/option-names' { - declare module.exports: any; -} - -declare module 'testcafe/lib/configuration/option-source' { - declare module.exports: any; -} - -declare module 'testcafe/lib/configuration/option' { - declare module.exports: any; -} - -declare module 'testcafe/lib/embedding-utils' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/create-stack-filter' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/error-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/get-callsite' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/process-test-fn-error' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/render-forbidden-chars-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/runtime/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/runtime/message' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/runtime/type-assertions' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/stack-cleaning-hook' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/test-run/formattable-adapter' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/test-run/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/test-run/templates' { - declare module.exports: any; -} - -declare module 'testcafe/lib/errors/test-run/type' { - declare module.exports: any; -} - -declare module 'testcafe/lib/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/bootstrapper' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/controller' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/file-watcher/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/file-watcher/modules-graph' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/logger/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/test-run-controller' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/test-run-state' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/test-run' { - declare module.exports: any; -} - -declare module 'testcafe/lib/live/test-runner' { - declare module.exports: any; -} - -declare module 'testcafe/lib/load-assets' { - declare module.exports: any; -} - -declare module 'testcafe/lib/notifications/debug-logger' { - declare module.exports: any; -} - -declare module 'testcafe/lib/notifications/deprecation-message' { - declare module.exports: any; -} - -declare module 'testcafe/lib/notifications/warning-log' { - declare module.exports: any; -} - -declare module 'testcafe/lib/notifications/warning-message' { - declare module.exports: any; -} - -declare module 'testcafe/lib/reporter/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/reporter/plugin-host' { - declare module.exports: any; -} - -declare module 'testcafe/lib/role/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/role/marker-symbol' { - declare module.exports: any; -} - -declare module 'testcafe/lib/role/phase' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/bootstrapper' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/browser-job-result' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/browser-job' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/browser-set' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/fixture-hook-controller' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/task' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/test-run-controller' { - declare module.exports: any; -} - -declare module 'testcafe/lib/runner/tested-app' { - declare module.exports: any; -} - -declare module 'testcafe/lib/screenshots/capturer' { - declare module.exports: any; -} - -declare module 'testcafe/lib/screenshots/constants' { - declare module.exports: any; -} - -declare module 'testcafe/lib/screenshots/crop' { - declare module.exports: any; -} - -declare module 'testcafe/lib/screenshots/generate-mark' { - declare module.exports: any; -} - -declare module 'testcafe/lib/screenshots/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/bookmark' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/browser-console-messages' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/browser-manipulation-queue' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/client-messages' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/actions' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/assertion' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/base' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/browser-manipulation' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/from-object' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/observation' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/options' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/service' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/type' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/utils' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/validations/argument' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/validations/factories' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/commands/validations/initializers' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/debug-log' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/execute-js-expression' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/marker-symbol' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/phase' { - declare module.exports: any; -} - -declare module 'testcafe/lib/test-run/session-controller' { - declare module.exports: any; -} - -declare module 'testcafe/lib/testcafe' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/assignable' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/async-event-emitter' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/async-queue' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/check-file-path' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/check-url' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/convert-to-best-fit-type' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/correct-file-path' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/define-lazy-property' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/delay' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/delegated-api' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/detect-ffmpeg' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/escape-user-agent' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/flag-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-common-path' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-filter-fn' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-options/base' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-options/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-options/ssl' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-options/video' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/get-viewport-width' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/handle-errors' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/handle-tag-args' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/http' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/limit-number' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/make-reg-exp' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/moment-loader' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/parse-file-list' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/path-pattern' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/prepare-reporters' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/process' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/promisified-functions' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/promisify' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/re-executable-promise' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/render-template' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/resolve-path-relatively-cwd' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/string' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/temp-directory/cleanup-process/commands' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/temp-directory/cleanup-process/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/temp-directory/cleanup-process/worker' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/temp-directory/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/temp-directory/lockfile' { - declare module.exports: any; -} - -declare module 'testcafe/lib/utils/thennable' { - declare module.exports: any; -} - -declare module 'testcafe/lib/video-recorder/index' { - declare module.exports: any; -} - -declare module 'testcafe/lib/video-recorder/process' { - declare module.exports: any; -} - -// Filename aliases -declare module 'testcafe/bin/testcafe-with-v8-flag-filter.js' { - declare module.exports: $Exports<'testcafe/bin/testcafe-with-v8-flag-filter'>; -} -declare module 'testcafe/bin/testcafe.js' { - declare module.exports: $Exports<'testcafe/bin/testcafe'>; -} -declare module 'testcafe/lib/api/exportable-lib/index.js' { - declare module.exports: $Exports<'testcafe/lib/api/exportable-lib/index'>; -} -declare module 'testcafe/lib/api/request-hooks/assert-type.js' { - declare module.exports: $Exports<'testcafe/lib/api/request-hooks/assert-type'>; -} -declare module 'testcafe/lib/api/request-hooks/hook.js' { - declare module.exports: $Exports<'testcafe/lib/api/request-hooks/hook'>; -} -declare module 'testcafe/lib/api/request-hooks/request-logger.js' { - declare module.exports: $Exports<'testcafe/lib/api/request-hooks/request-logger'>; -} -declare module 'testcafe/lib/api/request-hooks/request-mock.js' { - declare module.exports: $Exports<'testcafe/lib/api/request-hooks/request-mock'>; -} -declare module 'testcafe/lib/api/structure/fixture.js' { - declare module.exports: $Exports<'testcafe/lib/api/structure/fixture'>; -} -declare module 'testcafe/lib/api/structure/test-file.js' { - declare module.exports: $Exports<'testcafe/lib/api/structure/test-file'>; -} -declare module 'testcafe/lib/api/structure/test.js' { - declare module.exports: $Exports<'testcafe/lib/api/structure/test'>; -} -declare module 'testcafe/lib/api/structure/testing-unit.js' { - declare module.exports: $Exports<'testcafe/lib/api/structure/testing-unit'>; -} -declare module 'testcafe/lib/api/test-controller/assertion.js' { - declare module.exports: $Exports<'testcafe/lib/api/test-controller/assertion'>; -} -declare module 'testcafe/lib/api/test-controller/index.js' { - declare module.exports: $Exports<'testcafe/lib/api/test-controller/index'>; -} -declare module 'testcafe/lib/api/test-controller/proxy.js' { - declare module.exports: $Exports<'testcafe/lib/api/test-controller/proxy'>; -} -declare module 'testcafe/lib/api/test-page-url.js' { - declare module.exports: $Exports<'testcafe/lib/api/test-page-url'>; -} -declare module 'testcafe/lib/api/test-run-tracker.js' { - declare module.exports: $Exports<'testcafe/lib/api/test-run-tracker'>; -} -declare module 'testcafe/lib/api/wrap-test-function.js' { - declare module.exports: $Exports<'testcafe/lib/api/wrap-test-function'>; -} -declare module 'testcafe/lib/assertions/executor.js' { - declare module.exports: $Exports<'testcafe/lib/assertions/executor'>; -} -declare module 'testcafe/lib/assertions/get-fn.js' { - declare module.exports: $Exports<'testcafe/lib/assertions/get-fn'>; -} -declare module 'testcafe/lib/browser/connection/command.js' { - declare module.exports: $Exports<'testcafe/lib/browser/connection/command'>; -} -declare module 'testcafe/lib/browser/connection/gateway.js' { - declare module.exports: $Exports<'testcafe/lib/browser/connection/gateway'>; -} -declare module 'testcafe/lib/browser/connection/index.js' { - declare module.exports: $Exports<'testcafe/lib/browser/connection/index'>; -} -declare module 'testcafe/lib/browser/connection/remotes-queue.js' { - declare module.exports: $Exports<'testcafe/lib/browser/connection/remotes-queue'>; -} -declare module 'testcafe/lib/browser/connection/status.js' { - declare module.exports: $Exports<'testcafe/lib/browser/connection/status'>; -} -declare module 'testcafe/lib/browser/connection/unstable-network-mode.js' { - declare module.exports: $Exports<'testcafe/lib/browser/connection/unstable-network-mode'>; -} -declare module 'testcafe/lib/browser/provider/built-in/chrome/cdp.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/chrome/cdp'>; -} -declare module 'testcafe/lib/browser/provider/built-in/chrome/config.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/chrome/config'>; -} -declare module 'testcafe/lib/browser/provider/built-in/chrome/create-temp-profile.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/chrome/create-temp-profile'>; -} -declare module 'testcafe/lib/browser/provider/built-in/chrome/index.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/chrome/index'>; -} -declare module 'testcafe/lib/browser/provider/built-in/chrome/local-chrome.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/chrome/local-chrome'>; -} -declare module 'testcafe/lib/browser/provider/built-in/chrome/runtime-info.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/chrome/runtime-info'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/config.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/config'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/create-temp-profile.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/create-temp-profile'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/index.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/index'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/local-firefox.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/local-firefox'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/marionette-client/commands.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/marionette-client/commands'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/marionette-client/index.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/marionette-client/index'>; -} -declare module 'testcafe/lib/browser/provider/built-in/firefox/runtime-info.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/firefox/runtime-info'>; -} -declare module 'testcafe/lib/browser/provider/built-in/index.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/index'>; -} -declare module 'testcafe/lib/browser/provider/built-in/locally-installed.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/locally-installed'>; -} -declare module 'testcafe/lib/browser/provider/built-in/path.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/path'>; -} -declare module 'testcafe/lib/browser/provider/built-in/remote.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/built-in/remote'>; -} -declare module 'testcafe/lib/browser/provider/index.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/index'>; -} -declare module 'testcafe/lib/browser/provider/parse-provider-name.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/parse-provider-name'>; -} -declare module 'testcafe/lib/browser/provider/plugin-host.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/plugin-host'>; -} -declare module 'testcafe/lib/browser/provider/pool.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/pool'>; -} -declare module 'testcafe/lib/browser/provider/utils/argument-parsing.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/utils/argument-parsing'>; -} -declare module 'testcafe/lib/browser/provider/utils/browser-starter.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/utils/browser-starter'>; -} -declare module 'testcafe/lib/browser/provider/utils/client-functions.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/utils/client-functions'>; -} -declare module 'testcafe/lib/browser/provider/utils/get-maximized-headless-window-size.js' { - declare module.exports: $Exports<'testcafe/lib/browser/provider/utils/get-maximized-headless-window-size'>; -} -declare module 'testcafe/lib/cli/argument-parser.js' { - declare module.exports: $Exports<'testcafe/lib/cli/argument-parser'>; -} -declare module 'testcafe/lib/cli/cli.js' { - declare module.exports: $Exports<'testcafe/lib/cli/cli'>; -} -declare module 'testcafe/lib/cli/correct-browsers-and-sources.js' { - declare module.exports: $Exports<'testcafe/lib/cli/correct-browsers-and-sources'>; -} -declare module 'testcafe/lib/cli/index.js' { - declare module.exports: $Exports<'testcafe/lib/cli/index'>; -} -declare module 'testcafe/lib/cli/log.js' { - declare module.exports: $Exports<'testcafe/lib/cli/log'>; -} -declare module 'testcafe/lib/cli/remotes-wizard.js' { - declare module.exports: $Exports<'testcafe/lib/cli/remotes-wizard'>; -} -declare module 'testcafe/lib/cli/termination-handler.js' { - declare module.exports: $Exports<'testcafe/lib/cli/termination-handler'>; -} -declare module 'testcafe/lib/client-functions/builder-symbol.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/builder-symbol'>; -} -declare module 'testcafe/lib/client-functions/client-function-builder.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/client-function-builder'>; -} -declare module 'testcafe/lib/client-functions/replicator.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/replicator'>; -} -declare module 'testcafe/lib/client-functions/selectors/add-api.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/selectors/add-api'>; -} -declare module 'testcafe/lib/client-functions/selectors/create-snapshot-methods.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/selectors/create-snapshot-methods'>; -} -declare module 'testcafe/lib/client-functions/selectors/selector-attribute-filter.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/selectors/selector-attribute-filter'>; -} -declare module 'testcafe/lib/client-functions/selectors/selector-builder.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/selectors/selector-builder'>; -} -declare module 'testcafe/lib/client-functions/selectors/selector-text-filter.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/selectors/selector-text-filter'>; -} -declare module 'testcafe/lib/client-functions/selectors/snapshot-properties.js' { - declare module.exports: $Exports<'testcafe/lib/client-functions/selectors/snapshot-properties'>; -} -declare module 'testcafe/lib/client/automation/index.js' { - declare module.exports: $Exports<'testcafe/lib/client/automation/index'>; -} -declare module 'testcafe/lib/client/automation/index.min.js' { - declare module.exports: $Exports<'testcafe/lib/client/automation/index.min'>; -} -declare module 'testcafe/lib/client/browser/idle-page/index.js' { - declare module.exports: $Exports<'testcafe/lib/client/browser/idle-page/index'>; -} -declare module 'testcafe/lib/client/core/index.js' { - declare module.exports: $Exports<'testcafe/lib/client/core/index'>; -} -declare module 'testcafe/lib/client/core/index.min.js' { - declare module.exports: $Exports<'testcafe/lib/client/core/index.min'>; -} -declare module 'testcafe/lib/client/driver/index.js' { - declare module.exports: $Exports<'testcafe/lib/client/driver/index'>; -} -declare module 'testcafe/lib/client/driver/index.min.js' { - declare module.exports: $Exports<'testcafe/lib/client/driver/index.min'>; -} -declare module 'testcafe/lib/client/ui/index.js' { - declare module.exports: $Exports<'testcafe/lib/client/ui/index'>; -} -declare module 'testcafe/lib/client/ui/index.min.js' { - declare module.exports: $Exports<'testcafe/lib/client/ui/index.min'>; -} -declare module 'testcafe/lib/compiler/compile-client-function.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/compile-client-function'>; -} -declare module 'testcafe/lib/compiler/index.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/index'>; -} -declare module 'testcafe/lib/compiler/load-babel-libs.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/load-babel-libs'>; -} -declare module 'testcafe/lib/compiler/test-file/api-based.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/api-based'>; -} -declare module 'testcafe/lib/compiler/test-file/base.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/base'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/coffeescript/compiler.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/coffeescript/compiler'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/coffeescript/get-test-list.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/coffeescript/get-test-list'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/es-next/compiler.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/es-next/compiler'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/es-next/get-test-list.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/es-next/get-test-list'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/raw.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/raw'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/typescript/compiler.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/typescript/compiler'>; -} -declare module 'testcafe/lib/compiler/test-file/formats/typescript/get-test-list.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/formats/typescript/get-test-list'>; -} -declare module 'testcafe/lib/compiler/test-file/test-file-parser-base.js' { - declare module.exports: $Exports<'testcafe/lib/compiler/test-file/test-file-parser-base'>; -} -declare module 'testcafe/lib/configuration/default-values.js' { - declare module.exports: $Exports<'testcafe/lib/configuration/default-values'>; -} -declare module 'testcafe/lib/configuration/index.js' { - declare module.exports: $Exports<'testcafe/lib/configuration/index'>; -} -declare module 'testcafe/lib/configuration/option-conversion.js' { - declare module.exports: $Exports<'testcafe/lib/configuration/option-conversion'>; -} -declare module 'testcafe/lib/configuration/option-names.js' { - declare module.exports: $Exports<'testcafe/lib/configuration/option-names'>; -} -declare module 'testcafe/lib/configuration/option-source.js' { - declare module.exports: $Exports<'testcafe/lib/configuration/option-source'>; -} -declare module 'testcafe/lib/configuration/option.js' { - declare module.exports: $Exports<'testcafe/lib/configuration/option'>; -} -declare module 'testcafe/lib/embedding-utils.js' { - declare module.exports: $Exports<'testcafe/lib/embedding-utils'>; -} -declare module 'testcafe/lib/errors/create-stack-filter.js' { - declare module.exports: $Exports<'testcafe/lib/errors/create-stack-filter'>; -} -declare module 'testcafe/lib/errors/error-list.js' { - declare module.exports: $Exports<'testcafe/lib/errors/error-list'>; -} -declare module 'testcafe/lib/errors/get-callsite.js' { - declare module.exports: $Exports<'testcafe/lib/errors/get-callsite'>; -} -declare module 'testcafe/lib/errors/process-test-fn-error.js' { - declare module.exports: $Exports<'testcafe/lib/errors/process-test-fn-error'>; -} -declare module 'testcafe/lib/errors/render-forbidden-chars-list.js' { - declare module.exports: $Exports<'testcafe/lib/errors/render-forbidden-chars-list'>; -} -declare module 'testcafe/lib/errors/runtime/index.js' { - declare module.exports: $Exports<'testcafe/lib/errors/runtime/index'>; -} -declare module 'testcafe/lib/errors/runtime/message.js' { - declare module.exports: $Exports<'testcafe/lib/errors/runtime/message'>; -} -declare module 'testcafe/lib/errors/runtime/type-assertions.js' { - declare module.exports: $Exports<'testcafe/lib/errors/runtime/type-assertions'>; -} -declare module 'testcafe/lib/errors/stack-cleaning-hook.js' { - declare module.exports: $Exports<'testcafe/lib/errors/stack-cleaning-hook'>; -} -declare module 'testcafe/lib/errors/test-run/formattable-adapter.js' { - declare module.exports: $Exports<'testcafe/lib/errors/test-run/formattable-adapter'>; -} -declare module 'testcafe/lib/errors/test-run/index.js' { - declare module.exports: $Exports<'testcafe/lib/errors/test-run/index'>; -} -declare module 'testcafe/lib/errors/test-run/templates.js' { - declare module.exports: $Exports<'testcafe/lib/errors/test-run/templates'>; -} -declare module 'testcafe/lib/errors/test-run/type.js' { - declare module.exports: $Exports<'testcafe/lib/errors/test-run/type'>; -} -declare module 'testcafe/lib/index.js' { - declare module.exports: $Exports<'testcafe/lib/index'>; -} -declare module 'testcafe/lib/live/bootstrapper.js' { - declare module.exports: $Exports<'testcafe/lib/live/bootstrapper'>; -} -declare module 'testcafe/lib/live/controller.js' { - declare module.exports: $Exports<'testcafe/lib/live/controller'>; -} -declare module 'testcafe/lib/live/file-watcher/index.js' { - declare module.exports: $Exports<'testcafe/lib/live/file-watcher/index'>; -} -declare module 'testcafe/lib/live/file-watcher/modules-graph.js' { - declare module.exports: $Exports<'testcafe/lib/live/file-watcher/modules-graph'>; -} -declare module 'testcafe/lib/live/logger/index.js' { - declare module.exports: $Exports<'testcafe/lib/live/logger/index'>; -} -declare module 'testcafe/lib/live/test-run-controller.js' { - declare module.exports: $Exports<'testcafe/lib/live/test-run-controller'>; -} -declare module 'testcafe/lib/live/test-run-state.js' { - declare module.exports: $Exports<'testcafe/lib/live/test-run-state'>; -} -declare module 'testcafe/lib/live/test-run.js' { - declare module.exports: $Exports<'testcafe/lib/live/test-run'>; -} -declare module 'testcafe/lib/live/test-runner.js' { - declare module.exports: $Exports<'testcafe/lib/live/test-runner'>; -} -declare module 'testcafe/lib/load-assets.js' { - declare module.exports: $Exports<'testcafe/lib/load-assets'>; -} -declare module 'testcafe/lib/notifications/debug-logger.js' { - declare module.exports: $Exports<'testcafe/lib/notifications/debug-logger'>; -} -declare module 'testcafe/lib/notifications/deprecation-message.js' { - declare module.exports: $Exports<'testcafe/lib/notifications/deprecation-message'>; -} -declare module 'testcafe/lib/notifications/warning-log.js' { - declare module.exports: $Exports<'testcafe/lib/notifications/warning-log'>; -} -declare module 'testcafe/lib/notifications/warning-message.js' { - declare module.exports: $Exports<'testcafe/lib/notifications/warning-message'>; -} -declare module 'testcafe/lib/reporter/index.js' { - declare module.exports: $Exports<'testcafe/lib/reporter/index'>; -} -declare module 'testcafe/lib/reporter/plugin-host.js' { - declare module.exports: $Exports<'testcafe/lib/reporter/plugin-host'>; -} -declare module 'testcafe/lib/role/index.js' { - declare module.exports: $Exports<'testcafe/lib/role/index'>; -} -declare module 'testcafe/lib/role/marker-symbol.js' { - declare module.exports: $Exports<'testcafe/lib/role/marker-symbol'>; -} -declare module 'testcafe/lib/role/phase.js' { - declare module.exports: $Exports<'testcafe/lib/role/phase'>; -} -declare module 'testcafe/lib/runner/bootstrapper.js' { - declare module.exports: $Exports<'testcafe/lib/runner/bootstrapper'>; -} -declare module 'testcafe/lib/runner/browser-job-result.js' { - declare module.exports: $Exports<'testcafe/lib/runner/browser-job-result'>; -} -declare module 'testcafe/lib/runner/browser-job.js' { - declare module.exports: $Exports<'testcafe/lib/runner/browser-job'>; -} -declare module 'testcafe/lib/runner/browser-set.js' { - declare module.exports: $Exports<'testcafe/lib/runner/browser-set'>; -} -declare module 'testcafe/lib/runner/fixture-hook-controller.js' { - declare module.exports: $Exports<'testcafe/lib/runner/fixture-hook-controller'>; -} -declare module 'testcafe/lib/runner/index.js' { - declare module.exports: $Exports<'testcafe/lib/runner/index'>; -} -declare module 'testcafe/lib/runner/task.js' { - declare module.exports: $Exports<'testcafe/lib/runner/task'>; -} -declare module 'testcafe/lib/runner/test-run-controller.js' { - declare module.exports: $Exports<'testcafe/lib/runner/test-run-controller'>; -} -declare module 'testcafe/lib/runner/tested-app.js' { - declare module.exports: $Exports<'testcafe/lib/runner/tested-app'>; -} -declare module 'testcafe/lib/screenshots/capturer.js' { - declare module.exports: $Exports<'testcafe/lib/screenshots/capturer'>; -} -declare module 'testcafe/lib/screenshots/constants.js' { - declare module.exports: $Exports<'testcafe/lib/screenshots/constants'>; -} -declare module 'testcafe/lib/screenshots/crop.js' { - declare module.exports: $Exports<'testcafe/lib/screenshots/crop'>; -} -declare module 'testcafe/lib/screenshots/generate-mark.js' { - declare module.exports: $Exports<'testcafe/lib/screenshots/generate-mark'>; -} -declare module 'testcafe/lib/screenshots/index.js' { - declare module.exports: $Exports<'testcafe/lib/screenshots/index'>; -} -declare module 'testcafe/lib/test-run/bookmark.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/bookmark'>; -} -declare module 'testcafe/lib/test-run/browser-console-messages.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/browser-console-messages'>; -} -declare module 'testcafe/lib/test-run/browser-manipulation-queue.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/browser-manipulation-queue'>; -} -declare module 'testcafe/lib/test-run/client-messages.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/client-messages'>; -} -declare module 'testcafe/lib/test-run/commands/actions.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/actions'>; -} -declare module 'testcafe/lib/test-run/commands/assertion.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/assertion'>; -} -declare module 'testcafe/lib/test-run/commands/base.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/base'>; -} -declare module 'testcafe/lib/test-run/commands/browser-manipulation.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/browser-manipulation'>; -} -declare module 'testcafe/lib/test-run/commands/from-object.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/from-object'>; -} -declare module 'testcafe/lib/test-run/commands/observation.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/observation'>; -} -declare module 'testcafe/lib/test-run/commands/options.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/options'>; -} -declare module 'testcafe/lib/test-run/commands/service.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/service'>; -} -declare module 'testcafe/lib/test-run/commands/type.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/type'>; -} -declare module 'testcafe/lib/test-run/commands/utils.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/utils'>; -} -declare module 'testcafe/lib/test-run/commands/validations/argument.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/validations/argument'>; -} -declare module 'testcafe/lib/test-run/commands/validations/factories.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/validations/factories'>; -} -declare module 'testcafe/lib/test-run/commands/validations/initializers.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/commands/validations/initializers'>; -} -declare module 'testcafe/lib/test-run/debug-log.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/debug-log'>; -} -declare module 'testcafe/lib/test-run/execute-js-expression.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/execute-js-expression'>; -} -declare module 'testcafe/lib/test-run/index.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/index'>; -} -declare module 'testcafe/lib/test-run/marker-symbol.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/marker-symbol'>; -} -declare module 'testcafe/lib/test-run/phase.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/phase'>; -} -declare module 'testcafe/lib/test-run/session-controller.js' { - declare module.exports: $Exports<'testcafe/lib/test-run/session-controller'>; -} -declare module 'testcafe/lib/testcafe.js' { - declare module.exports: $Exports<'testcafe/lib/testcafe'>; -} -declare module 'testcafe/lib/utils/assignable.js' { - declare module.exports: $Exports<'testcafe/lib/utils/assignable'>; -} -declare module 'testcafe/lib/utils/async-event-emitter.js' { - declare module.exports: $Exports<'testcafe/lib/utils/async-event-emitter'>; -} -declare module 'testcafe/lib/utils/async-queue.js' { - declare module.exports: $Exports<'testcafe/lib/utils/async-queue'>; -} -declare module 'testcafe/lib/utils/check-file-path.js' { - declare module.exports: $Exports<'testcafe/lib/utils/check-file-path'>; -} -declare module 'testcafe/lib/utils/check-url.js' { - declare module.exports: $Exports<'testcafe/lib/utils/check-url'>; -} -declare module 'testcafe/lib/utils/convert-to-best-fit-type.js' { - declare module.exports: $Exports<'testcafe/lib/utils/convert-to-best-fit-type'>; -} -declare module 'testcafe/lib/utils/correct-file-path.js' { - declare module.exports: $Exports<'testcafe/lib/utils/correct-file-path'>; -} -declare module 'testcafe/lib/utils/define-lazy-property.js' { - declare module.exports: $Exports<'testcafe/lib/utils/define-lazy-property'>; -} -declare module 'testcafe/lib/utils/delay.js' { - declare module.exports: $Exports<'testcafe/lib/utils/delay'>; -} -declare module 'testcafe/lib/utils/delegated-api.js' { - declare module.exports: $Exports<'testcafe/lib/utils/delegated-api'>; -} -declare module 'testcafe/lib/utils/detect-ffmpeg.js' { - declare module.exports: $Exports<'testcafe/lib/utils/detect-ffmpeg'>; -} -declare module 'testcafe/lib/utils/escape-user-agent.js' { - declare module.exports: $Exports<'testcafe/lib/utils/escape-user-agent'>; -} -declare module 'testcafe/lib/utils/flag-list.js' { - declare module.exports: $Exports<'testcafe/lib/utils/flag-list'>; -} -declare module 'testcafe/lib/utils/get-common-path.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-common-path'>; -} -declare module 'testcafe/lib/utils/get-filter-fn.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-filter-fn'>; -} -declare module 'testcafe/lib/utils/get-options/base.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-options/base'>; -} -declare module 'testcafe/lib/utils/get-options/index.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-options/index'>; -} -declare module 'testcafe/lib/utils/get-options/ssl.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-options/ssl'>; -} -declare module 'testcafe/lib/utils/get-options/video.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-options/video'>; -} -declare module 'testcafe/lib/utils/get-viewport-width.js' { - declare module.exports: $Exports<'testcafe/lib/utils/get-viewport-width'>; -} -declare module 'testcafe/lib/utils/handle-errors.js' { - declare module.exports: $Exports<'testcafe/lib/utils/handle-errors'>; -} -declare module 'testcafe/lib/utils/handle-tag-args.js' { - declare module.exports: $Exports<'testcafe/lib/utils/handle-tag-args'>; -} -declare module 'testcafe/lib/utils/http.js' { - declare module.exports: $Exports<'testcafe/lib/utils/http'>; -} -declare module 'testcafe/lib/utils/limit-number.js' { - declare module.exports: $Exports<'testcafe/lib/utils/limit-number'>; -} -declare module 'testcafe/lib/utils/make-reg-exp.js' { - declare module.exports: $Exports<'testcafe/lib/utils/make-reg-exp'>; -} -declare module 'testcafe/lib/utils/moment-loader.js' { - declare module.exports: $Exports<'testcafe/lib/utils/moment-loader'>; -} -declare module 'testcafe/lib/utils/parse-file-list.js' { - declare module.exports: $Exports<'testcafe/lib/utils/parse-file-list'>; -} -declare module 'testcafe/lib/utils/path-pattern.js' { - declare module.exports: $Exports<'testcafe/lib/utils/path-pattern'>; -} -declare module 'testcafe/lib/utils/prepare-reporters.js' { - declare module.exports: $Exports<'testcafe/lib/utils/prepare-reporters'>; -} -declare module 'testcafe/lib/utils/process.js' { - declare module.exports: $Exports<'testcafe/lib/utils/process'>; -} -declare module 'testcafe/lib/utils/promisified-functions.js' { - declare module.exports: $Exports<'testcafe/lib/utils/promisified-functions'>; -} -declare module 'testcafe/lib/utils/promisify.js' { - declare module.exports: $Exports<'testcafe/lib/utils/promisify'>; -} -declare module 'testcafe/lib/utils/re-executable-promise.js' { - declare module.exports: $Exports<'testcafe/lib/utils/re-executable-promise'>; -} -declare module 'testcafe/lib/utils/render-template.js' { - declare module.exports: $Exports<'testcafe/lib/utils/render-template'>; -} -declare module 'testcafe/lib/utils/resolve-path-relatively-cwd.js' { - declare module.exports: $Exports<'testcafe/lib/utils/resolve-path-relatively-cwd'>; -} -declare module 'testcafe/lib/utils/string.js' { - declare module.exports: $Exports<'testcafe/lib/utils/string'>; -} -declare module 'testcafe/lib/utils/temp-directory/cleanup-process/commands.js' { - declare module.exports: $Exports<'testcafe/lib/utils/temp-directory/cleanup-process/commands'>; -} -declare module 'testcafe/lib/utils/temp-directory/cleanup-process/index.js' { - declare module.exports: $Exports<'testcafe/lib/utils/temp-directory/cleanup-process/index'>; -} -declare module 'testcafe/lib/utils/temp-directory/cleanup-process/worker.js' { - declare module.exports: $Exports<'testcafe/lib/utils/temp-directory/cleanup-process/worker'>; -} -declare module 'testcafe/lib/utils/temp-directory/index.js' { - declare module.exports: $Exports<'testcafe/lib/utils/temp-directory/index'>; -} -declare module 'testcafe/lib/utils/temp-directory/lockfile.js' { - declare module.exports: $Exports<'testcafe/lib/utils/temp-directory/lockfile'>; -} -declare module 'testcafe/lib/utils/thennable.js' { - declare module.exports: $Exports<'testcafe/lib/utils/thennable'>; -} -declare module 'testcafe/lib/video-recorder/index.js' { - declare module.exports: $Exports<'testcafe/lib/video-recorder/index'>; -} -declare module 'testcafe/lib/video-recorder/process.js' { - declare module.exports: $Exports<'testcafe/lib/video-recorder/process'>; -} diff --git a/flow-typed/npm/url-loader_vx.x.x.js b/flow-typed/npm/url-loader_vx.x.x.js new file mode 100644 index 0000000000..642ff76595 --- /dev/null +++ b/flow-typed/npm/url-loader_vx.x.x.js @@ -0,0 +1,46 @@ +// flow-typed signature: e232778c3abca72a5b5705b8df980d76 +// flow-typed version: <>/url-loader_v^2.0.1/flow_v0.102.0 + +/** + * This is an autogenerated libdef stub for: + * + * 'url-loader' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'url-loader' { + declare module.exports: any; +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ +declare module 'url-loader/dist/cjs' { + declare module.exports: any; +} + +declare module 'url-loader/dist/index' { + declare module.exports: any; +} + +declare module 'url-loader/dist/utils/normalizeFallback' { + declare module.exports: any; +} + +// Filename aliases +declare module 'url-loader/dist/cjs.js' { + declare module.exports: $Exports<'url-loader/dist/cjs'>; +} +declare module 'url-loader/dist/index.js' { + declare module.exports: $Exports<'url-loader/dist/index'>; +} +declare module 'url-loader/dist/utils/normalizeFallback.js' { + declare module.exports: $Exports<'url-loader/dist/utils/normalizeFallback'>; +} diff --git a/flow-typed/npm/wait-port_vx.x.x.js b/flow-typed/npm/wait-port_vx.x.x.js index e5ead76ec0..5ee2ae9c5c 100644 --- a/flow-typed/npm/wait-port_vx.x.x.js +++ b/flow-typed/npm/wait-port_vx.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: ece86cce336bd1860c445c190d58cb0e -// flow-typed version: <>/wait-port_v^0.2.2/flow_v0.96.0 +// flow-typed signature: 3f24a12633b467e4fc1135a502b35ccf +// flow-typed version: <>/wait-port_v^0.2.2/flow_v0.102.0 /** * This is an autogenerated libdef stub for: diff --git a/flow-typed/npm/webpack_v4.x.x.js b/flow-typed/npm/webpack_v4.x.x.js index a1df5f6e4d..6960283bb1 100644 --- a/flow-typed/npm/webpack_v4.x.x.js +++ b/flow-typed/npm/webpack_v4.x.x.js @@ -1,5 +1,5 @@ -// flow-typed signature: 72cb54db24df27a7bac24b0b302df296 -// flow-typed version: 6cb74e5628/webpack_v4.x.x/flow_>=v0.71.x +// flow-typed signature: ddbbc20af6521fcadfe6b222df027838 +// flow-typed version: 9818728193/webpack_v4.x.x/flow_>=v0.71.x import * as http from 'http'; import fs from 'fs'; @@ -581,6 +581,13 @@ declare module 'webpack' { watchOptions?: WatchOptions, }; + declare class EnvironmentPlugin { + constructor(env: { [string]: mixed } | string[]): $ElementType< + $NonMaybeType<$PropertyType>, + number + >; + } + declare function builder( options: WebpackOptions, callback?: Callback @@ -590,5 +597,7 @@ declare module 'webpack' { callback?: Callback ): WebpackMultiCompiler; - declare module.exports: typeof builder; + declare module.exports: typeof builder & { + EnvironmentPlugin: typeof EnvironmentPlugin, + }; } diff --git a/jest.config.js b/jest.config.js index 33eeb2a32a..c0a37e7b90 100644 --- a/jest.config.js +++ b/jest.config.js @@ -10,6 +10,7 @@ module.exports = { setupFilesAfterEnv: ['./test/test-setup.js'], // node_modules is default. testPathIgnorePatterns: ['/node_modules/', '/cypress/'], + modulePathIgnorePatterns: ['/dist/'], watchPlugins: [ 'jest-watch-typeahead/filename', 'jest-watch-typeahead/testname', diff --git a/package.json b/package.json index 66ab00ad22..84d027f7bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-beautiful-dnd", - "version": "11.0.5", + "version": "12.0.0-alpha.7", "description": "Beautiful and accessible drag and drop for lists with React", "author": "Alex Reardon ", "keywords": [ @@ -12,7 +12,8 @@ "react", "react.js", "natural", - "beautiful" + "beautiful", + "accessible" ], "repository": { "type": "git", @@ -32,6 +33,7 @@ "prettier_target": "*.{js,jsx,md,json} src/**/*.{js,jsx,md,json} test/**/*.{js,jsx,md,json} docs/**/*.{js,jsx,md,json} stories/**/*.{js,jsx,md,json} cypress/**/*.{js,jsx,md,json}" }, "scripts": { + "test:accessibility": "lighthouse http://localhost:9002/iframe.html?id=single-vertical-list--basic --chrome-flags='--headless' --output=json --output=html --output-path=./test-reports/lighthouse/a11y.json && node a11y-audit-parse.js", "test": "jest --config ./jest.config.js", "test:ci": "jest test --maxWorkers=2", "test:browser": "cypress open", @@ -54,70 +56,74 @@ "prepublishOnly": "yarn build" }, "dependencies": { - "@babel/runtime-corejs2": "^7.4.5", - "css-box-model": "^1.1.2", - "memoize-one": "^5.0.4", - "raf-schd": "^4.0.0", - "react-redux": "^7.0.3", - "redux": "^4.0.1", - "tiny-invariant": "^1.0.4", - "use-memo-one": "^1.1.0" + "@babel/runtime-corejs2": "^7.5.2", + "css-box-model": "^1.1.3", + "memoize-one": "^5.0.5", + "raf-schd": "^4.0.2", + "react-redux": "^7.1.0", + "redux": "^4.0.2", + "tiny-invariant": "^1.0.5", + "use-memo-one": "^1.1.1" }, "devDependencies": { - "@atlaskit/css-reset": "^4.0.0", - "@atlaskit/theme": "^9.1.0", - "@babel/core": "^7.4.5", - "@babel/plugin-proposal-class-properties": "^7.4.4", - "@babel/plugin-transform-modules-commonjs": "^7.4.4", - "@babel/plugin-transform-runtime": "^7.4.4", - "@babel/preset-env": "^7.4.5", + "@atlaskit/css-reset": "^5.0.2", + "@atlaskit/theme": "^9.1.1", + "@babel/core": "^7.5.0", + "@babel/plugin-proposal-class-properties": "^7.5.0", + "@babel/plugin-transform-modules-commonjs": "^7.5.0", + "@babel/plugin-transform-runtime": "^7.5.0", + "@babel/preset-env": "^7.5.2", "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", - "@emotion/core": "^10.0.10", - "@emotion/styled": "^10.0.12", - "@storybook/react": "^5.1.3", - "@storybook/theming": "^5.1.3", + "@emotion/babel-preset-css-prop": "^10.0.14", + "@emotion/core": "^10.0.14", + "@emotion/styled": "^10.0.14", + "@storybook/react": "^5.1.9", + "@storybook/theming": "^5.1.9", + "@testing-library/react": "^8.0.4", "babel-core": "^7.0.0-bridge.0", - "babel-eslint": "^10.0.1", + "babel-eslint": "^10.0.2", "babel-jest": "^24.8.0", "babel-loader": "^8.0.6", - "babel-plugin-dev-expression": "^0.2.1", - "babel-plugin-emotion": "^10.0.13", + "babel-plugin-dev-expression": "^0.2.2", + "babel-plugin-emotion": "^10.0.14", "cross-env": "^5.2.0", "cypress": "^3.3.1", - "emotion-theming": "^10.0.10", + "emotion-theming": "^10.0.14", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.14.0", - "eslint": "^5.16.0", + "eslint": "^6.0.1", "eslint-config-airbnb": "^17.1.0", - "eslint-config-prettier": "^5.1.0", + "eslint-config-prettier": "^6.0.0", "eslint-plugin-cypress": "^2.2.1", - "eslint-plugin-emotion": "^10.0.7", - "eslint-plugin-flowtype": "^3.10.1", - "eslint-plugin-import": "^2.17.3", - "eslint-plugin-jest": "^22.6.4", + "eslint-plugin-emotion": "^10.0.14", + "eslint-plugin-flowtype": "^3.11.1", + "eslint-plugin-import": "^2.18.0", + "eslint-plugin-jest": "^22.7.1", "eslint-plugin-jsx-a11y": "^6.2.1", "eslint-plugin-prettier": "^3.1.0", - "eslint-plugin-react": "^7.13.0", - "eslint-plugin-react-hooks": "^1.6.0", - "flow-bin": "0.96.0", + "eslint-plugin-react": "^7.14.2", + "eslint-plugin-react-hooks": "^1.6.1", + "flow-bin": "0.102.0", "fs-extra": "^8.0.1", - "globby": "^9.2.0", + "globby": "^10.0.1", "jest": "^24.8.0", "jest-junit": "^6.4.0", "jest-watch-typeahead": "^0.3.1", + "lighthouse": "^4.3.1", "markdown-it": "^8.4.2", "prettier": "^1.18.2", - "raf-stub": "^2.0.2", + "raf-stub": "^3.0.0", "react": "^16.8.6", "react-dom": "^16.8.6", "react-test-renderer": "^16.8.6", + "react-window": "^1.8.5", "rimraf": "^2.6.3", - "rollup": "^1.14.6", - "rollup-plugin-babel": "^4.3.2", + "rollup": "^1.16.6", + "rollup-plugin-babel": "^4.3.3", "rollup-plugin-commonjs": "^10.0.0", "rollup-plugin-json": "^4.0.0", - "rollup-plugin-node-resolve": "^5.0.1", + "rollup-plugin-node-resolve": "^5.1.0", "rollup-plugin-replace": "^2.2.0", "rollup-plugin-size-snapshot": "^0.9.0", "rollup-plugin-strip": "^1.2.1", @@ -130,8 +136,9 @@ "stylelint-config-styled-components": "^0.1.1", "stylelint-processor-styled-components": "^1.8.0", "testcafe-reporter-xunit": "^2.1.0", + "url-loader": "^2.0.1", "wait-port": "^0.2.2", - "webpack": "^4.33.0" + "webpack": "^4.35.3" }, "peerDependencies": { "react": "^16.8.5" diff --git a/rollup.config.js b/rollup.config.js index 56e215e822..5234534ecc 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -36,7 +36,7 @@ const commonjsArgs = { // needed for react-is via react-redux // https://stackoverflow.com/questions/50080893/rollup-error-isvalidelementtype-is-not-exported-by-node-modules-react-is-inde/50098540 namedExports: { - 'node_modules/react-redux/node_modules/react-is/index.js': [ + 'node_modules/react-is/index.js': [ 'isValidElementType', 'isContextConsumer', ], diff --git a/src/debug/middleware/log.js b/src/debug/middleware/log.js index b187df0fbf..1b91c321ba 100644 --- a/src/debug/middleware/log.js +++ b/src/debug/middleware/log.js @@ -2,11 +2,19 @@ /* eslint-disable no-console */ import type { Action, Store } from '../../state/store-types'; -export default (store: Store) => (next: Action => mixed) => ( - action: Action, -): any => { +type Mode = 'verbose' | 'light'; + +export default (mode?: Mode = 'verbose') => (store: Store) => ( + next: Action => mixed, +) => (action: Action): any => { + if (mode === 'light') { + console.log('๐Ÿƒโ€ Action:', action.type); + return next(action); + } + console.group(`action: ${action.type}`); console.log('action payload', action.payload); + console.log('state before', store.getState()); const result: mixed = next(action); diff --git a/src/dev-warning.js b/src/dev-warning.js index 5f3a33a336..638e7e7aea 100644 --- a/src/dev-warning.js +++ b/src/dev-warning.js @@ -7,13 +7,13 @@ const spacesAndTabs: RegExp = /[ \t]{2,}/g; const lineStartWithSpaces: RegExp = /^[ \t]*/gm; // using .trim() to clear the any newlines before the first text and after last text -const clean = (value: string) => +const clean = (value: string): string => value .replace(spacesAndTabs, ' ') .replace(lineStartWithSpaces, '') .trim(); -const getDevMessage = (message: string) => +const getDevMessage = (message: string): string => clean(` %creact-beautiful-dnd diff --git a/src/empty.js b/src/empty.js new file mode 100644 index 0000000000..7c6e177f0a --- /dev/null +++ b/src/empty.js @@ -0,0 +1,6 @@ +// @flow +export function noop(): void {} + +export function identity(value: T): T { + return value; +} diff --git a/src/index.js b/src/index.js index 30d1f6a912..e746aca13c 100644 --- a/src/index.js +++ b/src/index.js @@ -21,6 +21,7 @@ export type { DragStart, DragUpdate, DropResult, + Direction, ResponderProvided, Announce, DraggableLocation, @@ -28,6 +29,8 @@ export type { OnDragStartResponder, OnDragUpdateResponder, OnDragEndResponder, + SensorAPI, + Sensor, } from './types'; // Droppable types @@ -41,12 +44,10 @@ export type { export type { Provided as DraggableProvided, StateSnapshot as DraggableStateSnapshot, + DragHandleProps, DropAnimation, DraggableProps, DraggableStyle, DraggingStyle, NotDraggingStyle, } from './view/draggable/draggable-types'; - -// DragHandle types -export type { DragHandleProps } from './view/use-drag-handle/drag-handle-types'; diff --git a/src/native-with-fallback.js b/src/native-with-fallback.js index 0b1daced11..8cc7291699 100644 --- a/src/native-with-fallback.js +++ b/src/native-with-fallback.js @@ -14,6 +14,7 @@ export function values(map: Map): T[] { // Could also extend to pass index and list type PredicateFn = (value: T) => boolean; +// TODO: swap order export function findIndex( list: Array, predicate: PredicateFn, @@ -43,3 +44,10 @@ export function find(list: Array, predicate: PredicateFn): ?T { // Array.prototype.find returns undefined when nothing is found return undefined; } + +// Using this rather than Array.from as Array.from adds 2kb to the gzip +// document.querySelector actually returns Element[], but flow thinks it is HTMLElement[] +// So we downcast the result to Element[] +export function toArray(list: NodeList): Element[] { + return Array.prototype.slice.call(list); +} diff --git a/src/state/middleware/util/screen-reader-message-preset.js b/src/screen-reader-message-preset.js similarity index 93% rename from src/state/middleware/util/screen-reader-message-preset.js rename to src/screen-reader-message-preset.js index ed26a5c2ba..0dd4874d7a 100644 --- a/src/state/middleware/util/screen-reader-message-preset.js +++ b/src/screen-reader-message-preset.js @@ -6,14 +6,17 @@ import type { DropResult, DraggableLocation, Combine, -} from '../../../types'; +} from './types'; export type MessagePreset = {| + liftInstruction: string, onDragStart: (start: DragStart) => string, onDragUpdate: (update: DragUpdate) => string, onDragEnd: (result: DropResult) => string, |}; +const liftInstruction: string = `Draggable item. Ensure your screen reader is not in browse mode and then press spacebar to lift.`; + const position = (index: number): number => index + 1; // We cannot list what index the Droppable is in automatically as we are not sure how @@ -119,6 +122,7 @@ const onDragEnd = (result: DropResult): string => { }; const preset: MessagePreset = { + liftInstruction, onDragStart, onDragUpdate, onDragEnd, diff --git a/src/state/auto-scroller/fluid-scroller/scroll.js b/src/state/auto-scroller/fluid-scroller/scroll.js index 1608753626..52768286ae 100644 --- a/src/state/auto-scroller/fluid-scroller/scroll.js +++ b/src/state/auto-scroller/fluid-scroller/scroll.js @@ -31,7 +31,6 @@ export default ({ const draggable: DraggableDimension = state.dimensions.draggables[state.critical.draggable.id]; const subject: Rect = draggable.page.marginBox; - // 1. Can we scroll the viewport? if (state.isWindowScrollAllowed) { const viewport: Viewport = state.viewport; diff --git a/src/state/calculate-drag-impact/calculate-combine-impact.js b/src/state/calculate-drag-impact/calculate-combine-impact.js new file mode 100644 index 0000000000..6670bd2d30 --- /dev/null +++ b/src/state/calculate-drag-impact/calculate-combine-impact.js @@ -0,0 +1,64 @@ +// @flow +import type { + DraggableId, + DroppableId, + DragImpact, + UserDirection, + CombineImpact, +} from '../../types'; + +type Args = {| + combineWithId: DraggableId, + destinationId: DroppableId, + previousImpact: DragImpact, + userDirection: UserDirection, +|}; + +function getWhenEntered( + id: DraggableId, + current: UserDirection, + lastCombineImpact: ?CombineImpact, +): UserDirection { + if (!lastCombineImpact) { + return current; + } + if (id !== lastCombineImpact.combine.draggableId) { + return current; + } + return lastCombineImpact.whenEntered; +} + +function tryGetCombineImpact(impact: DragImpact): ?CombineImpact { + if (impact.at && impact.at.type === 'COMBINE') { + return impact.at; + } + return null; +} + +export default function calculateCombineImpact({ + combineWithId, + destinationId, + userDirection, + previousImpact, +}: Args): DragImpact { + const lastCombineImpact: ?CombineImpact = tryGetCombineImpact(previousImpact); + const whenEntered: UserDirection = getWhenEntered( + combineWithId, + userDirection, + lastCombineImpact, + ); + const impact: DragImpact = { + // no change to displacement when combining + displacedBy: previousImpact.displacedBy, + displaced: previousImpact.displaced, + at: { + type: 'COMBINE', + whenEntered, + combine: { + draggableId: combineWithId, + droppableId: destinationId, + }, + }, + }; + return impact; +} diff --git a/src/state/calculate-drag-impact/calculate-reorder-impact.js b/src/state/calculate-drag-impact/calculate-reorder-impact.js new file mode 100644 index 0000000000..7d726e841d --- /dev/null +++ b/src/state/calculate-drag-impact/calculate-reorder-impact.js @@ -0,0 +1,136 @@ +// @flow +import type { + DraggableDimension, + DroppableDimension, + DragImpact, + DisplacementGroups, + Viewport, + DisplacedBy, +} from '../../types'; +import removeDraggableFromList from '../remove-draggable-from-list'; +import isHomeOf from '../droppable/is-home-of'; +import { emptyGroups } from '../no-impact'; +import { find } from '../../native-with-fallback'; +import getDisplacementGroups from '../get-displacement-groups'; + +type Args = {| + draggable: DraggableDimension, + insideDestination: DraggableDimension[], + destination: DroppableDimension, + viewport: Viewport, + displacedBy: DisplacedBy, + last: DisplacementGroups, + index: ?number, + forceShouldAnimate?: boolean, +|}; + +function getIndexOfLastItem( + draggables: DraggableDimension[], + options: {| inHomeList: boolean |}, +): number { + if (!draggables.length) { + return 0; + } + + const indexOfLastItem: number = + draggables[draggables.length - 1].descriptor.index; + + // When in a foreign list there will be an additional one item in the list + return options.inHomeList ? indexOfLastItem : indexOfLastItem + 1; +} + +type GoAtEndArgs = {| + insideDestination: DraggableDimension[], + inHomeList: boolean, + displacedBy: DisplacedBy, + destination: DroppableDimension, +|}; + +function goAtEnd({ + insideDestination, + inHomeList, + displacedBy, + destination, +}: GoAtEndArgs): DragImpact { + const newIndex: number = getIndexOfLastItem(insideDestination, { + inHomeList, + }); + + return { + displaced: emptyGroups, + displacedBy, + at: { + type: 'REORDER', + destination: { + droppableId: destination.descriptor.id, + index: newIndex, + }, + }, + }; +} + +export default function calculateReorderImpact({ + draggable, + insideDestination, + destination, + viewport, + displacedBy, + last, + index, + forceShouldAnimate, +}: Args): DragImpact { + const inHomeList: boolean = isHomeOf(draggable, destination); + + // Go into last spot of list + if (index == null) { + return goAtEnd({ + insideDestination, + inHomeList, + displacedBy, + destination, + }); + } + + // this might be the dragging item + const match: ?DraggableDimension = find( + insideDestination, + (item: DraggableDimension) => item.descriptor.index === index, + ); + + if (!match) { + return goAtEnd({ + insideDestination, + inHomeList, + displacedBy, + destination, + }); + } + const withoutDragging: DraggableDimension[] = removeDraggableFromList( + draggable, + insideDestination, + ); + + const sliceFrom: number = insideDestination.indexOf(match); + const impacted: DraggableDimension[] = withoutDragging.slice(sliceFrom); + + const displaced: DisplacementGroups = getDisplacementGroups({ + afterDragging: impacted, + destination, + displacedBy, + last, + viewport: viewport.frame, + forceShouldAnimate, + }); + + return { + displaced, + displacedBy, + at: { + type: 'REORDER', + destination: { + droppableId: destination.descriptor.id, + index, + }, + }, + }; +} diff --git a/src/state/create-store.js b/src/state/create-store.js index 231c831db8..77086e116e 100644 --- a/src/state/create-store.js +++ b/src/state/create-store.js @@ -5,12 +5,16 @@ import reducer from './reducer'; import lift from './middleware/lift'; import style from './middleware/style'; import drop from './middleware/drop/drop-middleware'; +import scrollListener from './middleware/scroll-listener'; import responders from './middleware/responders/responders-middleware'; -import dropAnimationFinish from './middleware/drop-animation-finish'; +import dropAnimationFinish from './middleware/drop/drop-animation-finish-middleware'; +import dropAnimationFlushOnScroll from './middleware/drop/drop-animation-flush-on-scroll-middleware'; import dimensionMarshalStopper from './middleware/dimension-marshal-stopper'; +import focus from './middleware/focus'; import autoScroll from './middleware/auto-scroll'; import pendingDrop from './middleware/pending-drop'; import type { DimensionMarshal } from './dimension-marshal/dimension-marshal-types'; +import type { FocusMarshal } from '../view/use-focus-marshal/focus-marshal-types'; import type { StyleMarshal } from '../view/use-style-marshal/style-marshal-types'; import type { AutoScroller } from './auto-scroller/auto-scroller-types'; import type { Responders, Announce } from '../types'; @@ -28,6 +32,7 @@ const composeEnhancers = type Args = {| dimensionMarshal: DimensionMarshal, + focusMarshal: FocusMarshal, styleMarshal: StyleMarshal, getResponders: () => Responders, announce: Announce, @@ -36,6 +41,7 @@ type Args = {| export default ({ dimensionMarshal, + focusMarshal, styleMarshal, getResponders, announce, @@ -49,7 +55,7 @@ export default ({ // > uncomment to use // debugging logger - // require('../debug/middleware/log').default, + // require('../debug/middleware/log').default('light'), // // user timing api // require('../debug/middleware/user-timing').default, // debugging timer @@ -77,8 +83,11 @@ export default ({ drop, // When a drop animation finishes - fire a drop complete dropAnimationFinish, + dropAnimationFlushOnScroll, pendingDrop, autoScroll(autoScroller), + scrollListener, + focus(focusMarshal), // Fire responders for consumers (after update to store) responders(getResponders, announce), ), diff --git a/src/state/did-start-after-critical.js b/src/state/did-start-after-critical.js new file mode 100644 index 0000000000..f8557a3ba0 --- /dev/null +++ b/src/state/did-start-after-critical.js @@ -0,0 +1,9 @@ +// @flow +import type { DraggableId, LiftEffect } from '../types'; + +export default function didStartAfterCritical( + draggableId: DraggableId, + afterCritical: LiftEffect, +): boolean { + return Boolean(afterCritical.effected[draggableId]); +} diff --git a/src/state/dimension-marshal/dimension-marshal-types.js b/src/state/dimension-marshal/dimension-marshal-types.js index 2df5ce7471..4aa2072cfd 100644 --- a/src/state/dimension-marshal/dimension-marshal-types.js +++ b/src/state/dimension-marshal/dimension-marshal-types.js @@ -6,13 +6,7 @@ import type { UpdateDroppableIsCombineEnabledArgs, } from '../action-creators'; import type { - DraggableDescriptor, - DroppableDescriptor, - DraggableDimension, - DroppableDimension, - DraggableId, DroppableId, - ScrollOptions, Critical, DimensionMap, LiftRequest, @@ -20,53 +14,10 @@ import type { Viewport, } from '../../types'; -export type GetDraggableDimensionFn = ( - windowScroll: Position, -) => DraggableDimension; - -export type GetDroppableDimensionFn = ( - windowScroll: Position, - options: ScrollOptions, -) => DroppableDimension; - export type RecollectDroppableOptions = {| withoutPlaceholder: boolean, |}; -export type DroppableCallbacks = {| - // a drag is starting - getDimensionAndWatchScroll: GetDroppableDimensionFn, - recollect: (options: RecollectDroppableOptions) => DroppableDimension, - // scroll a droppable - scroll: (change: Position) => void, - // If the Droppable is listening for scroll events - it needs to stop! - // Can be called on droppables that have not been asked to watch scroll - dragStopped: () => void, -|}; - -export type DroppableEntry = {| - descriptor: DroppableDescriptor, - callbacks: DroppableCallbacks, -|}; - -export type DraggableEntry = {| - descriptor: DraggableDescriptor, - getDimension: GetDraggableDimensionFn, -|}; - -export type DraggableEntryMap = { - [key: DraggableId]: DraggableEntry, -}; - -export type DroppableEntryMap = { - [key: DroppableId]: DroppableEntry, -}; - -export type Entries = {| - droppables: DroppableEntryMap, - draggables: DraggableEntryMap, -|}; - export type StartPublishingResult = {| critical: Critical, dimensions: DimensionMap, @@ -74,22 +25,6 @@ export type StartPublishingResult = {| |}; export type DimensionMarshal = {| - // Draggable - registerDraggable: ( - descriptor: DraggableDescriptor, - getDimension: GetDraggableDimensionFn, - ) => void, - updateDraggable: ( - previous: DraggableDescriptor, - descriptor: DraggableDescriptor, - getDimension: GetDraggableDimensionFn, - ) => void, - unregisterDraggable: (descriptor: DraggableDescriptor) => void, - // Droppable - registerDroppable: ( - descriptor: DroppableDescriptor, - callbacks: DroppableCallbacks, - ) => void, // it is possible for a droppable to change whether it is enabled during a drag updateDroppableIsEnabled: (id: DroppableId, isEnabled: boolean) => void, // it is also possible to update whether combining is enabled @@ -99,7 +34,6 @@ export type DimensionMarshal = {| ) => void, updateDroppableScroll: (id: DroppableId, newScroll: Position) => void, scrollDroppable: (id: DroppableId, change: Position) => void, - unregisterDroppable: (descriptor: DroppableDescriptor) => void, // Entry startPublishing: (request: LiftRequest) => StartPublishingResult, stopPublishing: () => void, diff --git a/src/state/dimension-marshal/dimension-marshal.js b/src/state/dimension-marshal/dimension-marshal.js index 63723b3228..4a0442df5c 100644 --- a/src/state/dimension-marshal/dimension-marshal.js +++ b/src/state/dimension-marshal/dimension-marshal.js @@ -4,53 +4,34 @@ import invariant from 'tiny-invariant'; import type { DimensionMarshal, Callbacks, - GetDraggableDimensionFn, - DroppableCallbacks, - Entries, - DroppableEntry, - DraggableEntry, StartPublishingResult, } from './dimension-marshal-types'; import createPublisher, { type WhileDraggingPublisher, } from './while-dragging-publisher'; import getInitialPublish from './get-initial-publish'; +import type { + Registry, + DroppableEntry, + DraggableEntry, + Subscriber, + Unsubscribe, + RegistryEvent, +} from '../registry/registry-types'; import type { DroppableId, DroppableDescriptor, - DraggableDescriptor, LiftRequest, Critical, + DraggableId, } from '../../types'; -import { values } from '../../native-with-fallback'; -import { warning } from '../../dev-warning'; type Collection = {| critical: Critical, + unsubscribe: Unsubscribe, |}; -const throwIfAddOrRemoveOfWrongType = ( - collection: Collection, - descriptor: DraggableDescriptor, -) => { - invariant( - collection.critical.draggable.type === descriptor.type, - `We have detected that you have added a Draggable during a drag. - This is not of the same type as the dragging item - - Dragging type: ${collection.critical.draggable.type}. - Added type: ${descriptor.type} - - We are not allowing this as you can run into problems if your change - has shifted the positioning of other Droppables, or has changed the size of the page`, - ); -}; - -export default (callbacks: Callbacks) => { - const entries: Entries = { - droppables: {}, - draggables: {}, - }; +export default (registry: Registry, callbacks: Callbacks) => { let collection: ?Collection = null; const publisher: WhileDraggingPublisher = createPublisher({ @@ -65,151 +46,12 @@ export default (callbacks: Callbacks) => { return collection.critical; }, }, - getEntries: (): Entries => entries, + registry, }); - const registerDraggable = ( - descriptor: DraggableDescriptor, - getDimension: GetDraggableDimensionFn, - ) => { - // Not checking if the draggable already exists. - // - This allows for overwriting in particular circumstances. - // Not checking if a parent droppable exists. - // - In React 16 children are mounted before their parents - - const entry: DraggableEntry = { - descriptor, - getDimension, - }; - entries.draggables[descriptor.id] = entry; - - if (!collection) { - return; - } - - throwIfAddOrRemoveOfWrongType(collection, descriptor); - - // A Draggable has been added during a collection - need to act! - publisher.add(descriptor); - }; - - const updateDraggable = ( - published: DraggableDescriptor, - descriptor: DraggableDescriptor, - getDimension: GetDraggableDimensionFn, - ) => { - const existing: ?DraggableEntry = entries.draggables[published.id]; - - invariant( - existing, - 'Cannot update draggable registration as no published registration was found', - ); - - // If consumers are not using keys correctly then there can be timing issues - // Note: there will still be a crash if starting a drag during the drop animation - if (existing.descriptor === published) { - // id might have changed so we are removing the old entry - delete entries.draggables[published.id]; - } else { - warning(` - Detected incorrect usage of 'key' on ' - - Your 'key' should be: - - Unique for each Draggable in a list - - Not be based on the index of the Draggable - - Usually you want your 'key' to just be the 'draggableId' - - More information: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/draggable.md#keys-for-a-list-of-draggable- - `); - } - - // adding new entry - const entry: DraggableEntry = { - descriptor, - getDimension, - }; - entries.draggables[descriptor.id] = entry; - - // it is fine if these are updated during a drag - // this can happen as the index changes - }; - - const unregisterDraggable = (descriptor: DraggableDescriptor) => { - const entry: ?DraggableEntry = entries.draggables[descriptor.id]; - invariant( - entry, - `Cannot unregister Draggable with id: - ${descriptor.id} as it is not registered`, - ); - - // Entry has already been overwritten. - // This can happen when a new Draggable with the same draggableId - // is mounted before the old Draggable has been removed. - if (entry.descriptor !== descriptor) { - return; - } - - delete entries.draggables[descriptor.id]; - - if (!collection) { - return; - } - - invariant( - collection.critical.draggable.id !== descriptor.id, - 'Cannot remove the dragging item during a drag', - ); - - throwIfAddOrRemoveOfWrongType(collection, descriptor); - - publisher.remove(descriptor); - }; - - const registerDroppable = ( - descriptor: DroppableDescriptor, - droppableCallbacks: DroppableCallbacks, - ) => { - const id: DroppableId = descriptor.id; - - // Not checking if there is already a droppable published with the same id - // In some situations a Droppable might be published with the same id as - // a Droppable that is about to be unmounted - but has not unpublished yet - - entries.droppables[id] = { - descriptor, - callbacks: droppableCallbacks, - }; - - invariant(!collection, 'Cannot add a Droppable during a drag'); - }; - - const unregisterDroppable = (descriptor: DroppableDescriptor) => { - const entry: ?DroppableEntry = entries.droppables[descriptor.id]; - - invariant( - entry, - `Cannot unregister Droppable with id ${descriptor.id} as as it is not registered`, - ); - - // entry has already been overwritten - // in which can we will not remove it - if (entry.descriptor !== descriptor) { - return; - } - - // Not checking if this will leave orphan draggables as react - // unmounts parents before it unmounts children: - // https://twitter.com/alexandereardon/status/941514612624703488 - - delete entries.droppables[descriptor.id]; - - invariant(!collection, 'Cannot add a Droppable during a drag'); - }; - const updateDroppableIsEnabled = (id: DroppableId, isEnabled: boolean) => { invariant( - entries.droppables[id], + registry.droppable.exists(id), `Cannot update is enabled flag of Droppable ${id} as it is not registered`, ); @@ -228,43 +70,38 @@ export default (callbacks: Callbacks) => { id: DroppableId, isCombineEnabled: boolean, ) => { - invariant( - entries.droppables[id], - `Cannot update isCombineEnabled flag of Droppable ${id} as it is not registered`, - ); - // no need to update if (!collection) { return; } + invariant( + registry.droppable.exists(id), + `Cannot update isCombineEnabled flag of Droppable ${id} as it is not registered`, + ); + callbacks.updateDroppableIsCombineEnabled({ id, isCombineEnabled }); }; const updateDroppableScroll = (id: DroppableId, newScroll: Position) => { - invariant( - entries.droppables[id], - `Cannot update the scroll on Droppable ${id} as it is not registered`, - ); - // no need to update the application state if a collection is not occurring if (!collection) { return; } + invariant( + registry.droppable.exists(id), + `Cannot update the scroll on Droppable ${id} as it is not registered`, + ); + callbacks.updateDroppableScroll({ id, offset: newScroll }); }; const scrollDroppable = (id: DroppableId, change: Position) => { - const entry: ?DroppableEntry = entries.droppables[id]; - - invariant(entry, `Cannot scroll Droppable ${id} as it is not registered`); - if (!collection) { return; } - - entry.callbacks.scroll(change); + registry.droppable.getById(id).callbacks.scroll(change); }; const stopPublishing = () => { @@ -278,52 +115,70 @@ export default (callbacks: Callbacks) => { // Tell all droppables to stop watching scroll // all good if they where not already listening const home: DroppableDescriptor = collection.critical.droppable; - values(entries.droppables) - .filter( - (entry: DroppableEntry): boolean => entry.descriptor.type === home.type, - ) + registry.droppable + .getAllByType(home.type) .forEach((entry: DroppableEntry) => entry.callbacks.dragStopped()); + // Unsubscribe from registry updates + collection.unsubscribe(); // Finally - clear our collection collection = null; }; + const subscriber: Subscriber = (event: RegistryEvent) => { + invariant( + collection, + 'Should only be subscribed when a collection is occurring', + ); + // The dragging item can be add and removed when using a clone + // We do not publish updates for the critical item + const criticalId: DraggableId = collection.critical.draggable.id; + + if (event.type === 'ADDITION') { + if (event.value.descriptor.id !== criticalId) { + publisher.add(event.value); + } + } + if (event.type === 'REMOVAL') { + if (event.value.id !== criticalId) { + publisher.remove(event.value); + } + } + }; + const startPublishing = (request: LiftRequest): StartPublishingResult => { invariant( !collection, 'Cannot start capturing critical dimensions as there is already a collection', ); - const entry: ?DraggableEntry = entries.draggables[request.draggableId]; - invariant(entry, 'Cannot find critical draggable entry'); - const home: ?DroppableEntry = - entries.droppables[entry.descriptor.droppableId]; - invariant(home, 'Cannot find critical droppable entry'); + const entry: DraggableEntry = registry.draggable.getById( + request.draggableId, + ); + const home: DroppableEntry = registry.droppable.getById( + entry.descriptor.droppableId, + ); const critical: Critical = { draggable: entry.descriptor, droppable: home.descriptor, }; + const unsubscribe = registry.subscribe(subscriber); + collection = { critical, + unsubscribe, }; return getInitialPublish({ critical, - entries, + registry, scrollOptions: request.scrollOptions, }); }; const marshal: DimensionMarshal = { - // dimension registration - registerDraggable, - updateDraggable, - unregisterDraggable, - registerDroppable, - unregisterDroppable, - - // droppable changes + // Droppable changes updateDroppableIsEnabled, updateDroppableIsCombineEnabled, scrollDroppable, diff --git a/src/state/dimension-marshal/get-initial-publish.js b/src/state/dimension-marshal/get-initial-publish.js index ca6d95bcde..f149d3d7a0 100644 --- a/src/state/dimension-marshal/get-initial-publish.js +++ b/src/state/dimension-marshal/get-initial-publish.js @@ -1,14 +1,13 @@ // @flow import type { Position } from 'css-box-model'; import * as timings from '../../debug/timings'; +import type { StartPublishingResult } from './dimension-marshal-types'; import type { - Entries, - DroppableEntry, + Registry, DraggableEntry, - StartPublishingResult, -} from './dimension-marshal-types'; + DroppableEntry, +} from '../registry/registry-types'; import { toDraggableMap, toDroppableMap } from '../dimension-structures'; -import { values } from '../../native-with-fallback'; import type { DroppableDescriptor, DroppableDimension, @@ -23,13 +22,13 @@ import getViewport from '../../view/window/get-viewport'; type Args = {| critical: Critical, scrollOptions: ScrollOptions, - entries: Entries, + registry: Registry, |}; export default ({ critical, scrollOptions, - entries, + registry, }: Args): StartPublishingResult => { const timingKey: string = 'Initial collection from DOM'; timings.start(timingKey); @@ -38,20 +37,14 @@ export default ({ const home: DroppableDescriptor = critical.droppable; - const droppables: DroppableDimension[] = values(entries.droppables) - // Exclude things of the wrong type - .filter( - (entry: DroppableEntry): boolean => entry.descriptor.type === home.type, - ) + const droppables: DroppableDimension[] = registry.droppable + .getAllByType(home.type) .map((entry: DroppableEntry): DroppableDimension => entry.callbacks.getDimensionAndWatchScroll(windowScroll, scrollOptions), ); - const draggables: DraggableDimension[] = values(entries.draggables) - .filter( - (entry: DraggableEntry): boolean => - entry.descriptor.type === critical.draggable.type, - ) + const draggables: DraggableDimension[] = registry.draggable + .getAllByType(critical.draggable.type) .map((entry: DraggableEntry): DraggableDimension => entry.getDimension(windowScroll), ); diff --git a/src/state/dimension-marshal/while-dragging-publisher.js b/src/state/dimension-marshal/while-dragging-publisher.js index 59607a33af..70ebf42323 100644 --- a/src/state/dimension-marshal/while-dragging-publisher.js +++ b/src/state/dimension-marshal/while-dragging-publisher.js @@ -1,41 +1,36 @@ // @flow -import invariant from 'tiny-invariant'; import type { DraggableId, DroppableId, + DraggableDescriptor, Published, DraggableDimension, DroppableDimension, - DraggableDescriptor, + DroppableIdMap, Critical, + DraggableIdMap, } from '../../types'; +import type { RecollectDroppableOptions } from './dimension-marshal-types'; import type { - Entries, DroppableEntry, - RecollectDroppableOptions, -} from './dimension-marshal-types'; + Registry, + DraggableEntry, + DraggableEntryMap, +} from '../registry/registry-types'; import * as timings from '../../debug/timings'; import { origin } from '../position'; import { warning } from '../../dev-warning'; export type WhileDraggingPublisher = {| - add: (descriptor: DraggableDescriptor) => void, + add: (entry: DraggableEntry) => void, remove: (descriptor: DraggableDescriptor) => void, stop: () => void, |}; -type DraggableMap = { - [id: DraggableId]: DraggableDescriptor, -}; - -type DroppableMap = { - [id: DroppableId]: true, -}; - type Staging = {| - additions: DraggableMap, - removals: DraggableMap, - modified: DroppableMap, + additions: DraggableEntryMap, + removals: DraggableIdMap, + modified: DroppableIdMap, |}; type Callbacks = {| @@ -45,7 +40,7 @@ type Callbacks = {| |}; type Args = {| - getEntries: () => Entries, + registry: Registry, callbacks: Callbacks, |}; @@ -57,7 +52,10 @@ const clean = (): Staging => ({ const timingKey: string = 'Publish collection from DOM'; -export default ({ getEntries, callbacks }: Args): WhileDraggingPublisher => { +export default function createPublisher({ + registry, + callbacks, +}: Args): WhileDraggingPublisher { const advancedUsageWarning = (() => { // noop for production if (process.env.NODE_ENV === 'production') { @@ -98,14 +96,13 @@ export default ({ getEntries, callbacks }: Args): WhileDraggingPublisher => { const critical: Critical = callbacks.getCritical(); timings.start(timingKey); - const entries: Entries = getEntries(); const { additions, removals, modified } = staging; const added: DraggableDimension[] = Object.keys(additions) .map( // Using the origin as the window scroll. This will be adjusted when processing the published values (id: DraggableId): DraggableDimension => - entries.draggables[id].getDimension(origin), + registry.draggable.getById(id).getDimension(origin), ) // Dimensions are not guarenteed to be ordered in the same order as keys // So we need to sort them so they are in the correct order @@ -116,8 +113,7 @@ export default ({ getEntries, callbacks }: Args): WhileDraggingPublisher => { const updated: DroppableDimension[] = Object.keys(modified).map( (id: DroppableId) => { - const entry: ?DroppableEntry = entries.droppables[id]; - invariant(entry, 'Cannot find dynamically added droppable in cache'); + const entry: DroppableEntry = registry.droppable.getById(id); const isHome: boolean = entry.descriptor.id === critical.droppable.id; // need to keep the placeholder when in home list @@ -141,18 +137,19 @@ export default ({ getEntries, callbacks }: Args): WhileDraggingPublisher => { }); }; - const add = (descriptor: DraggableDescriptor) => { - staging.additions[descriptor.id] = descriptor; - staging.modified[descriptor.droppableId] = true; + const add = (entry: DraggableEntry) => { + const id: DraggableId = entry.descriptor.id; + staging.additions[id] = entry; + staging.modified[entry.descriptor.droppableId] = true; - if (staging.removals[descriptor.id]) { - delete staging.removals[descriptor.id]; + if (staging.removals[id]) { + delete staging.removals[id]; } collect(); }; const remove = (descriptor: DraggableDescriptor) => { - staging.removals[descriptor.id] = descriptor; + staging.removals[descriptor.id] = true; staging.modified[descriptor.droppableId] = true; if (staging.additions[descriptor.id]) { @@ -176,4 +173,4 @@ export default ({ getEntries, callbacks }: Args): WhileDraggingPublisher => { remove, stop, }; -}; +} diff --git a/src/state/droppable/what-is-dragged-over.js b/src/state/droppable/what-is-dragged-over.js index e709646910..ca858fa4aa 100644 --- a/src/state/droppable/what-is-dragged-over.js +++ b/src/state/droppable/what-is-dragged-over.js @@ -1,16 +1,16 @@ // @flow -import type { DroppableId, DragImpact } from '../../types'; +import type { ImpactLocation, DroppableId, DragImpact } from '../../types'; export default (impact: DragImpact): ?DroppableId => { - const { merge, destination } = impact; + const at: ?ImpactLocation = impact.at; - if (destination) { - return destination.droppableId; + if (!at) { + return null; } - if (merge) { - return merge.combine.droppableId; + if (at.type === 'REORDER') { + return at.destination.droppableId; } - return null; + return at.combine.droppableId; }; diff --git a/src/state/get-center-from-impact/get-client-border-box-center/index.js b/src/state/get-center-from-impact/get-client-border-box-center/index.js index e32c4adde3..ccb2190e07 100644 --- a/src/state/get-center-from-impact/get-client-border-box-center/index.js +++ b/src/state/get-center-from-impact/get-client-border-box-center/index.js @@ -6,7 +6,7 @@ import type { DragImpact, DraggableDimension, DraggableDimensionMap, - OnLift, + LiftEffect, } from '../../../types'; import getPageBorderBoxCenterFromImpact from '../get-page-border-box-center'; import getClientFromPageBorderBoxCenter from './get-client-from-page-border-box-center'; @@ -17,7 +17,7 @@ type Args = {| droppable: DroppableDimension, draggables: DraggableDimensionMap, viewport: Viewport, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -26,14 +26,14 @@ export default ({ droppable, draggables, viewport, - onLift, + afterCritical, }: Args): Position => { const pageBorderBoxCenter: Position = getPageBorderBoxCenterFromImpact({ impact, draggable, draggables, droppable, - onLift, + afterCritical, }); return getClientFromPageBorderBoxCenter({ diff --git a/src/state/get-center-from-impact/get-page-border-box-center/index.js b/src/state/get-center-from-impact/get-page-border-box-center/index.js index 5194268b56..260afb01b4 100644 --- a/src/state/get-center-from-impact/get-page-border-box-center/index.js +++ b/src/state/get-center-from-impact/get-page-border-box-center/index.js @@ -5,9 +5,8 @@ import type { DraggableDimension, DroppableDimension, DraggableDimensionMap, - CombineImpact, - DraggableLocation, - OnLift, + ImpactLocation, + LiftEffect, } from '../../../types'; import whenCombining from './when-combining'; import whenReordering from './when-reordering'; @@ -15,7 +14,7 @@ import withDroppableDisplacement from '../../with-scroll-change/with-droppable-d type Args = {| impact: DragImpact, - onLift: OnLift, + afterCritical: LiftEffect, draggable: DraggableDimension, droppable: ?DroppableDimension, draggables: DraggableDimensionMap, @@ -26,37 +25,34 @@ const getResultWithoutDroppableDisplacement = ({ draggable, droppable, draggables, - onLift, + afterCritical, }: Args): Position => { - const merge: ?CombineImpact = impact.merge; - const destination: ?DraggableLocation = impact.destination; - const original: Position = draggable.page.borderBox.center; + const at: ?ImpactLocation = impact.at; if (!droppable) { return original; } - if (destination) { + if (!at) { + return original; + } + + if (at.type === 'REORDER') { return whenReordering({ - movement: impact.movement, + impact, draggable, draggables, droppable, - onLift, - }); - } - - if (merge) { - return whenCombining({ - movement: impact.movement, - combine: merge.combine, - draggables, - onLift, + afterCritical, }); } - return original; + return whenCombining({ + impact, + draggables, + afterCritical, + }); }; export default (args: Args): Position => { diff --git a/src/state/get-center-from-impact/get-page-border-box-center/when-combining.js b/src/state/get-center-from-impact/get-page-border-box-center/when-combining.js index 9585c4c282..7d5b558a36 100644 --- a/src/state/get-center-from-impact/get-page-border-box-center/when-combining.js +++ b/src/state/get-center-from-impact/get-page-border-box-center/when-combining.js @@ -1,34 +1,38 @@ // @flow +import invariant from 'tiny-invariant'; import { type Position } from 'css-box-model'; import type { DraggableDimensionMap, DraggableId, Combine, - DragMovement, - OnLift, + LiftEffect, + DragImpact, } from '../../../types'; import { add } from '../../position'; import getCombinedItemDisplacement from '../../get-combined-item-displacement'; +import { tryGetCombine } from '../../get-impact-location'; type Args = {| - movement: DragMovement, - combine: Combine, + impact: DragImpact, // all draggables in the system draggables: DraggableDimensionMap, - onLift: OnLift, + afterCritical: LiftEffect, |}; // Returns the client offset required to move an item from its // original client position to its final resting position -export default ({ combine, onLift, movement, draggables }: Args): Position => { +export default ({ afterCritical, impact, draggables }: Args): Position => { + const combine: ?Combine = tryGetCombine(impact); + invariant(combine); + const combineWith: DraggableId = combine.draggableId; const center: Position = draggables[combineWith].page.borderBox.center; const displaceBy: Position = getCombinedItemDisplacement({ - displaced: movement.map, - onLift, + displaced: impact.displaced, + afterCritical, combineWith, - displacedBy: movement.displacedBy, + displacedBy: impact.displacedBy, }); return add(center, displaceBy); diff --git a/src/state/get-center-from-impact/get-page-border-box-center/when-reordering.js b/src/state/get-center-from-impact/get-page-border-box-center/when-reordering.js index cf8414d9d7..3370e35d6e 100644 --- a/src/state/get-center-from-impact/get-page-border-box-center/when-reordering.js +++ b/src/state/get-center-from-impact/get-page-border-box-center/when-reordering.js @@ -2,33 +2,34 @@ import { offset, type Position, type BoxModel } from 'css-box-model'; import type { Axis, + DragImpact, + DraggableId, DraggableDimension, DraggableDimensionMap, - DragMovement, DroppableDimension, - OnLift, + LiftEffect, } from '../../../types'; import { goBefore, goAfter, goIntoStart } from '../move-relative-to'; import getDraggablesInsideDroppable from '../../get-draggables-inside-droppable'; import { negate } from '../../position'; -import didStartDisplaced from '../../starting-displaced/did-start-displaced'; +import didStartAfterCritical from '../../did-start-after-critical'; type NewHomeArgs = {| - movement: DragMovement, + impact: DragImpact, draggable: DraggableDimension, draggables: DraggableDimensionMap, droppable: DroppableDimension, - onLift: OnLift, + afterCritical: LiftEffect, |}; // Returns the client offset required to move an item from its // original client position to its final resting position export default ({ - movement, + impact, draggable, draggables, droppable, - onLift, + afterCritical, }: NewHomeArgs): Position => { const insideDestination: DraggableDimension[] = getDraggablesInsideDroppable( droppable.descriptor.id, @@ -47,30 +48,27 @@ export default ({ }); } - const { displaced, displacedBy } = movement; + const { displaced, displacedBy } = impact; + const closestAfter: ?DraggableId = displaced.all[0]; // go before the first displaced item // items can only be displaced forwards - if (displaced.length) { - const closestAfter: DraggableDimension = - draggables[displaced[0].draggableId]; + if (closestAfter) { + const closest: DraggableDimension = draggables[closestAfter]; // want to go before where it would be with the displacement // target is displaced and is already in it's starting position - if (didStartDisplaced(closestAfter.descriptor.id, onLift)) { + if (didStartAfterCritical(closestAfter, afterCritical)) { return goBefore({ axis, - moveRelativeTo: closestAfter.page, + moveRelativeTo: closest.page, isMoving: draggablePage, }); } // target has been displaced during the drag and it is not in its starting position // we need to account for the displacement - const withDisplacement: BoxModel = offset( - closestAfter.page, - displacedBy.point, - ); + const withDisplacement: BoxModel = offset(closest.page, displacedBy.point); return goBefore({ axis, @@ -90,11 +88,14 @@ export default ({ return draggablePage.borderBox.center; } - if (didStartDisplaced(last.descriptor.id, onLift)) { + if (didStartAfterCritical(last.descriptor.id, afterCritical)) { // if the item started displaced and it is no longer displaced then // we need to go after it it's non-displaced position - const page: BoxModel = offset(last.page, negate(onLift.displacedBy.point)); + const page: BoxModel = offset( + last.page, + negate(afterCritical.displacedBy.point), + ); return goAfter({ axis, moveRelativeTo: page, diff --git a/src/state/get-combined-item-displacement.js b/src/state/get-combined-item-displacement.js index c7824cd209..3b84e69fe9 100644 --- a/src/state/get-combined-item-displacement.js +++ b/src/state/get-combined-item-displacement.js @@ -1,30 +1,32 @@ // @flow import type { Position } from 'css-box-model'; import type { - DisplacementMap, - OnLift, + DisplacementGroups, + LiftEffect, DraggableId, DisplacedBy, } from '../types'; import { origin, negate } from './position'; -import didStartDisplaced from './starting-displaced/did-start-displaced'; +import didStartAfterCritical from './did-start-after-critical'; type Args = {| - displaced: DisplacementMap, - onLift: OnLift, + displaced: DisplacementGroups, + afterCritical: LiftEffect, combineWith: DraggableId, displacedBy: DisplacedBy, |}; export default ({ displaced, - onLift, + afterCritical, combineWith, displacedBy, }: Args): Position => { - const isDisplaced: boolean = Boolean(displaced[combineWith]); + const isDisplaced: boolean = Boolean( + displaced.visible[combineWith] || displaced.invisible[combineWith], + ); - if (didStartDisplaced(combineWith, onLift)) { + if (didStartAfterCritical(combineWith, afterCritical)) { return isDisplaced ? origin : negate(displacedBy.point); } diff --git a/src/state/get-displaced-by.js b/src/state/get-displaced-by.js index faba20ee49..d83b7571ac 100644 --- a/src/state/get-displaced-by.js +++ b/src/state/get-displaced-by.js @@ -5,7 +5,10 @@ import type { Axis, DisplacedBy } from '../types'; import { patch } from './position'; // TODO: memoization needed? -export default memoizeOne((axis: Axis, displaceBy: Position): DisplacedBy => { +export default memoizeOne(function getDisplacedBy( + axis: Axis, + displaceBy: Position, +): DisplacedBy { const displacement: number = displaceBy[axis.line]; return { value: displacement, diff --git a/src/state/get-displacement-groups.js b/src/state/get-displacement-groups.js new file mode 100644 index 0000000000..b977f16b96 --- /dev/null +++ b/src/state/get-displacement-groups.js @@ -0,0 +1,130 @@ +// @flow +import { type Rect, type Spacing, expand, getRect } from 'css-box-model'; +import type { + DraggableId, + Displacement, + DraggableDimension, + DroppableDimension, + DisplacementGroups, + DisplacedBy, +} from '../types'; +import { isPartiallyVisible } from './visibility/is-visible'; + +type Args = {| + afterDragging: DraggableDimension[], + destination: DroppableDimension, + displacedBy: DisplacedBy, + last: ?DisplacementGroups, + viewport: Rect, + forceShouldAnimate?: boolean, +|}; + +const getShouldAnimate = ( + id, + last: ?DisplacementGroups, + forceShouldAnimate: ?boolean, +) => { + // Use a forced value if provided + if (typeof forceShouldAnimate === 'boolean') { + return forceShouldAnimate; + } + + // nothing to gauge animation from + if (!last) { + return true; + } + + const { invisible, visible } = last; + + // it was previously invisible - no animation + if (invisible[id]) { + return false; + } + + const previous: ?Displacement = visible[id]; + + return previous ? previous.shouldAnimate : true; +}; + +// Note: it is also an optimisation to not render the displacement on +// items when they are not longer visible. +// This prevents a lot of .render() calls when leaving / entering a list + +function getTarget( + draggable: DraggableDimension, + displacedBy: DisplacedBy, +): Rect { + const marginBox: Rect = draggable.page.marginBox; + + // ## Visibility overscanning + // We are expanding rather than offsetting the marginBox. + // In some cases we want + // - the target based on the starting position (such as when dropping outside of any list) + // - the target based on the items position without starting displacement (such as when moving inside a list) + // To keep things simple we just expand the whole area for this check + // The worst case is some minor redundant offscreen movements + const expandBy: Spacing = { + // pull backwards into viewport + top: displacedBy.point.y, + right: 0, + bottom: 0, + // pull backwards into viewport + left: displacedBy.point.x, + }; + + return getRect(expand(marginBox, expandBy)); +} + +export default function getDisplacementGroups({ + afterDragging, + destination, + displacedBy, + viewport, + forceShouldAnimate, + last, +}: Args): DisplacementGroups { + return afterDragging.reduce( + function process( + groups: DisplacementGroups, + draggable: DraggableDimension, + ): DisplacementGroups { + const target: Rect = getTarget(draggable, displacedBy); + const id: DraggableId = draggable.descriptor.id; + + groups.all.push(id); + + const isVisible: boolean = isPartiallyVisible({ + target, + destination, + viewport, + withDroppableDisplacement: true, + }); + + if (!isVisible) { + groups.invisible[draggable.descriptor.id] = true; + return groups; + } + + // item is visible + + const shouldAnimate: boolean = getShouldAnimate( + id, + last, + forceShouldAnimate, + ); + + const displacement: Displacement = { + draggableId: id, + shouldAnimate, + }; + + groups.visible[id] = displacement; + return groups; + }, + { + all: [], + visible: {}, + invisible: {}, + }, + ); +} diff --git a/src/state/get-displacement-map.js b/src/state/get-displacement-map.js deleted file mode 100644 index cb4f9811eb..0000000000 --- a/src/state/get-displacement-map.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow -import memoizeOne from 'memoize-one'; -import type { Displacement, DisplacementMap } from '../types'; - -export default memoizeOne((displaced: Displacement[]): DisplacementMap => - displaced.reduce((map: DisplacementMap, displacement: Displacement) => { - map[displacement.draggableId] = displacement; - return map; - }, {}), -); diff --git a/src/state/get-displacement.js b/src/state/get-displacement.js deleted file mode 100644 index 5c18921f01..0000000000 --- a/src/state/get-displacement.js +++ /dev/null @@ -1,117 +0,0 @@ -// @flow -import { type Rect, type Spacing, expand, getRect } from 'css-box-model'; -import type { - DraggableId, - Displacement, - DraggableDimension, - DroppableDimension, - DragImpact, - DisplacementMap, - OnLift, -} from '../types'; -import { isPartiallyVisible } from './visibility/is-visible'; -import didStartDisplaced from './starting-displaced/did-start-displaced'; - -type Args = {| - draggable: DraggableDimension, - destination: DroppableDimension, - previousImpact: DragImpact, - viewport: Rect, - onLift: OnLift, - forceShouldAnimate?: boolean, -|}; - -const getShouldAnimate = ( - forceShouldAnimate: ?boolean, - isVisible: boolean, - previous: ?Displacement, -) => { - // Use a forced value if provided - if (typeof forceShouldAnimate === 'boolean') { - return forceShouldAnimate; - } - - // if should be displaced and not visible - if (!isVisible) { - return false; - } - - // if visible and no previous entries: animate! - if (!previous) { - return true; - } - - // return our previous value - // for items that where originally not visible this will be false - // otherwise it will be true - return previous.shouldAnimate; -}; - -// Note: it is also an optimisation to not render the displacement on -// items when they are not longer visible. -// This prevents a lot of .render() calls when leaving / entering a list - -const getTarget = (draggable: DraggableDimension, onLift: OnLift): Rect => { - const marginBox: Rect = draggable.page.marginBox; - - if (!didStartDisplaced(draggable.descriptor.id, onLift)) { - return marginBox; - } - - // ## Visibility overscanning - // We are expanding rather than offsetting the marginBox. - // In some cases we want - // - the target based on the starting position (such as when dropping outside of any list) - // - the target based on the items position without starting displacement (such as when moving inside a list) - // To keep things simple we just expand the whole area for this check - // The worst case is some minor redundant offscreen movements - const expandBy: Spacing = { - // pull backwards into viewport - top: onLift.displacedBy.point.y, - right: 0, - bottom: 0, - // pull backwards into viewport - left: onLift.displacedBy.point.x, - }; - - return getRect(expand(marginBox, expandBy)); -}; - -export default ({ - draggable, - destination, - previousImpact, - viewport, - onLift, - forceShouldAnimate, -}: Args): Displacement => { - const id: DraggableId = draggable.descriptor.id; - const map: DisplacementMap = previousImpact.movement.map; - const target: Rect = getTarget(draggable, onLift); - - // We need to account for items that are not in their resting - // position without original displacement - - // only displacing items that are visible in the droppable and the viewport - const isVisible: boolean = isPartiallyVisible({ - // TODO: borderBox? - target, - destination, - viewport, - withDroppableDisplacement: true, - }); - - const shouldAnimate: boolean = getShouldAnimate( - forceShouldAnimate, - isVisible, - map[id], - ); - - const displacement: Displacement = { - draggableId: id, - isVisible, - shouldAnimate, - }; - - return displacement; -}; diff --git a/src/state/get-drag-impact/get-combine-impact.js b/src/state/get-drag-impact/get-combine-impact.js index b7a7e48e63..aea6fc7e38 100644 --- a/src/state/get-drag-impact/get-combine-impact.js +++ b/src/state/get-drag-impact/get-combine-impact.js @@ -8,28 +8,30 @@ import type { DroppableDimension, CombineImpact, DragImpact, - DisplacementMap, - OnLift, + DisplacementGroups, + LiftEffect, DisplacedBy, } from '../../types'; import isWithin from '../is-within'; import { find } from '../../native-with-fallback'; import isUserMovingForward from '../user-direction/is-user-moving-forward'; import getCombinedItemDisplacement from '../get-combined-item-displacement'; +import removeDraggableFromList from '../remove-draggable-from-list'; +import calculateCombineImpact from '../calculate-drag-impact/calculate-combine-impact'; -const getWhenEntered = ( +function getWhenEntered( id: DraggableId, current: UserDirection, - oldMerge: ?CombineImpact, -): UserDirection => { - if (!oldMerge) { + lastCombineImpact: ?CombineImpact, +): UserDirection { + if (!lastCombineImpact) { return current; } - if (id !== oldMerge.combine.draggableId) { + if (id !== lastCombineImpact.combine.draggableId) { return current; } - return oldMerge.whenEntered; -}; + return lastCombineImpact.whenEntered; +} type IsCombiningWithArgs = {| id: DraggableId, @@ -38,7 +40,7 @@ type IsCombiningWithArgs = {| borderBox: Rect, displaceBy: Position, currentUserDirection: UserDirection, - oldMerge: ?CombineImpact, + lastCombineImpact: ?CombineImpact, |}; const isCombiningWith = ({ @@ -48,7 +50,7 @@ const isCombiningWith = ({ borderBox, displaceBy, currentUserDirection, - oldMerge, + lastCombineImpact, }: IsCombiningWithArgs): boolean => { const start: number = borderBox[axis.start] + displaceBy[axis.line]; const end: number = borderBox[axis.end] + displaceBy[axis.line]; @@ -58,7 +60,7 @@ const isCombiningWith = ({ const whenEntered: UserDirection = getWhenEntered( id, currentUserDirection, - oldMerge, + lastCombineImpact, ); const isMovingForward: boolean = isUserMovingForward(axis, whenEntered); const targetCenter: number = currentCenter[axis.line]; @@ -71,39 +73,48 @@ const isCombiningWith = ({ return isWithin(end - twoThirdsOfSize, end)(targetCenter); }; +function tryGetCombineImpact(impact: DragImpact): ?CombineImpact { + if (impact.at && impact.at.type === 'COMBINE') { + return impact.at; + } + return null; +} + type Args = {| + draggable: DraggableDimension, pageBorderBoxCenterWithDroppableScrollChange: Position, previousImpact: DragImpact, destination: DroppableDimension, - insideDestinationWithoutDraggable: DraggableDimension[], + insideDestination: DraggableDimension[], userDirection: UserDirection, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ + draggable, pageBorderBoxCenterWithDroppableScrollChange: currentCenter, previousImpact, destination, - insideDestinationWithoutDraggable, + insideDestination, userDirection, - onLift, + afterCritical, }: Args): ?DragImpact => { if (!destination.isCombineEnabled) { return null; } const axis: Axis = destination.axis; - const map: DisplacementMap = previousImpact.movement.map; - const canBeDisplacedBy: DisplacedBy = previousImpact.movement.displacedBy; - const oldMerge: ?CombineImpact = previousImpact.merge; + const displaced: DisplacementGroups = previousImpact.displaced; + const canBeDisplacedBy: DisplacedBy = previousImpact.displacedBy; + const lastCombineImpact: ?CombineImpact = tryGetCombineImpact(previousImpact); - const target: ?DraggableDimension = find( - insideDestinationWithoutDraggable, + const combineWith: ?DraggableDimension = find( + removeDraggableFromList(draggable, insideDestination), (child: DraggableDimension): boolean => { const id: DraggableId = child.descriptor.id; const displaceBy: Position = getCombinedItemDisplacement({ - displaced: map, - onLift, + displaced, + afterCritical, combineWith: id, displacedBy: canBeDisplacedBy, }); @@ -115,29 +126,19 @@ export default ({ borderBox: child.page.borderBox, displaceBy, currentUserDirection: userDirection, - oldMerge, + lastCombineImpact, }); }, ); - if (!target) { + if (!combineWith) { return null; } - const merge: CombineImpact = { - whenEntered: getWhenEntered(target.descriptor.id, userDirection, oldMerge), - combine: { - draggableId: target.descriptor.id, - droppableId: destination.descriptor.id, - }, - }; - - // no change of displacement - // clearing any destination - const withMerge: DragImpact = { - ...previousImpact, - destination: null, - merge, - }; - return withMerge; + return calculateCombineImpact({ + combineWithId: combineWith.descriptor.id, + destinationId: destination.descriptor.id, + previousImpact, + userDirection, + }); }; diff --git a/src/state/get-drag-impact/get-reorder-impact.js b/src/state/get-drag-impact/get-reorder-impact.js index c52f62babb..3f5db2abb1 100644 --- a/src/state/get-drag-impact/get-reorder-impact.js +++ b/src/state/get-drag-impact/get-reorder-impact.js @@ -1,43 +1,67 @@ // @flow import { type Position, type Rect } from 'css-box-model'; import type { - DragMovement, + DraggableId, DraggableDimension, DroppableDimension, DragImpact, Axis, - Displacement, + DisplacementGroups, Viewport, UserDirection, DisplacedBy, - OnLift, + LiftEffect, } from '../../types'; -import getDisplacement from '../get-displacement'; -import getDisplacementMap from '../get-displacement-map'; import isUserMovingForward from '../user-direction/is-user-moving-forward'; import getDisplacedBy from '../get-displaced-by'; -import getDidStartDisplaced from '../starting-displaced/did-start-displaced'; +import removeDraggableFromList from '../remove-draggable-from-list'; +import isHomeOf from '../droppable/is-home-of'; +import { find } from '../../native-with-fallback'; +import getDidStartAfterCritical from '../did-start-after-critical'; +import calculateReorderImpact from '../calculate-drag-impact/calculate-reorder-impact'; type Args = {| pageBorderBoxCenterWithDroppableScrollChange: Position, draggable: DraggableDimension, destination: DroppableDimension, - insideDestinationWithoutDraggable: DraggableDimension[], - previousImpact: DragImpact, + insideDestination: DraggableDimension[], + last: DisplacementGroups, viewport: Viewport, userDirection: UserDirection, - onLift: OnLift, + afterCritical: LiftEffect, |}; +type AtIndexArgs = {| + draggable: DraggableDimension, + closest: ?DraggableDimension, + inHomeList: boolean, +|}; + +function atIndex({ draggable, closest, inHomeList }: AtIndexArgs): ?number { + if (!closest) { + return null; + } + + if (!inHomeList) { + return closest.descriptor.index; + } + + if (closest.descriptor.index > draggable.descriptor.index) { + return closest.descriptor.index - 1; + } + + return closest.descriptor.index; +} + export default ({ pageBorderBoxCenterWithDroppableScrollChange: currentCenter, draggable, destination, - insideDestinationWithoutDraggable, - previousImpact, + insideDestination, + last, viewport, userDirection, - onLift, + afterCritical, }: Args): DragImpact => { const axis: Axis = destination.axis; const isMovingForward: boolean = isUserMovingForward( @@ -48,23 +72,30 @@ export default ({ destination.axis, draggable.displaceBy, ); + const targetCenter: number = currentCenter[axis.line]; const displacement: number = displacedBy.value; + const withoutDragging: DraggableDimension[] = removeDraggableFromList( + draggable, + insideDestination, + ); - const displaced: Displacement[] = insideDestinationWithoutDraggable - .filter((child: DraggableDimension): boolean => { + const closest: ?DraggableDimension = find( + withoutDragging, + (child: DraggableDimension): boolean => { + const id: DraggableId = child.descriptor.id; const borderBox: Rect = child.page.borderBox; const start: number = borderBox[axis.start]; const end: number = borderBox[axis.end]; - const didStartDisplaced: boolean = getDidStartDisplaced( - child.descriptor.id, - onLift, + const didStartAfterCritical: boolean = getDidStartAfterCritical( + id, + afterCritical, ); // Moving forward will decrease the amount of things needed to be displaced if (isMovingForward) { - if (didStartDisplaced) { + if (didStartAfterCritical) { // if started displaced then its displaced position is its resting position // continue to keep the item at rest until we go onto the start of the item return targetCenter < start; @@ -78,40 +109,32 @@ export default ({ // The logic for this works by looking at assuming everything has been displaced // backwards and then looking at how you would undo that - if (didStartDisplaced) { + if (didStartAfterCritical) { // we continue to displace the item until we move back over the end of the item without displacement return targetCenter <= end - displacement; } // a non-displaced item is at rest. when we hit the item from the bottom we move it out of the way return targetCenter <= end; - }) - .map((dimension: DraggableDimension): Displacement => - getDisplacement({ - draggable: dimension, - destination, - previousImpact, - viewport: viewport.frame, - onLift, - }), - ); - - const newIndex: number = - insideDestinationWithoutDraggable.length - displaced.length; - - const movement: DragMovement = { - displacedBy, - displaced, - map: getDisplacementMap(displaced), - }; - const impact: DragImpact = { - movement, - destination: { - droppableId: destination.descriptor.id, - index: newIndex, }, - merge: null, - }; + ); + + const newIndex: ?number = atIndex({ + draggable, + closest, + inHomeList: isHomeOf(draggable, destination), + }); - return impact; + // TODO: index cannot be null? + // otherwise return null from there and return empty impact + // that was calculate reorder impact does not need to account for a null index + return calculateReorderImpact({ + draggable, + insideDestination, + destination, + viewport, + last, + displacedBy, + index: newIndex, + }); }; diff --git a/src/state/get-drag-impact/index.js b/src/state/get-drag-impact/index.js index 2da6679db9..7ee8a5f93d 100644 --- a/src/state/get-drag-impact/index.js +++ b/src/state/get-drag-impact/index.js @@ -9,15 +9,14 @@ import type { UserDirection, DragImpact, Viewport, - OnLift, + LiftEffect, } from '../../types'; import getDroppableOver from '../get-droppable-over'; import getDraggablesInsideDroppable from '../get-draggables-inside-droppable'; import withDroppableScroll from '../with-scroll-change/with-droppable-scroll'; -import getCombineImpact from './get-combine-impact'; import getReorderImpact from './get-reorder-impact'; +import getCombineImpact from './get-combine-impact'; import noImpact from '../no-impact'; -import removeDraggableFromList from '../remove-draggable-from-list'; type Args = {| pageBorderBoxCenter: Position, @@ -28,7 +27,7 @@ type Args = {| previousImpact: DragImpact, viewport: Viewport, userDirection: UserDirection, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -39,7 +38,7 @@ export default ({ previousImpact, viewport, userDirection, - onLift, + afterCritical, }: Args): DragImpact => { const destinationId: ?DroppableId = getDroppableOver({ target: pageBorderBoxCenter, @@ -59,10 +58,7 @@ export default ({ destination.descriptor.id, draggables, ); - const insideDestinationWithoutDraggable: DraggableDimension[] = removeDraggableFromList( - draggable, - insideDestination, - ); + // Where the element actually is now. // Need to take into account the change of scroll in the droppable const pageBorderBoxCenterWithDroppableScrollChange: Position = withDroppableScroll( @@ -71,27 +67,25 @@ export default ({ ); // checking combine first so we combine before any reordering - const withMerge: ?DragImpact = getCombineImpact({ - pageBorderBoxCenterWithDroppableScrollChange, - previousImpact, - destination, - insideDestinationWithoutDraggable, - userDirection, - onLift, - }); - - if (withMerge) { - return withMerge; - } - - return getReorderImpact({ - pageBorderBoxCenterWithDroppableScrollChange, - destination, - draggable, - insideDestinationWithoutDraggable, - previousImpact, - viewport, - userDirection, - onLift, - }); + return ( + getCombineImpact({ + pageBorderBoxCenterWithDroppableScrollChange, + draggable, + previousImpact, + destination, + insideDestination, + userDirection, + afterCritical, + }) || + getReorderImpact({ + pageBorderBoxCenterWithDroppableScrollChange, + draggable, + destination, + insideDestination, + last: previousImpact.displaced, + viewport, + userDirection, + afterCritical, + }) + ); }; diff --git a/src/state/get-home-on-lift.js b/src/state/get-home-on-lift.js deleted file mode 100644 index e7626578b3..0000000000 --- a/src/state/get-home-on-lift.js +++ /dev/null @@ -1,87 +0,0 @@ -// @flow -import getHomeLocation from './get-home-location'; -import type { - DraggableDimension, - DroppableDimension, - DraggableDimensionMap, - DragImpact, - Displacement, - DisplacedBy, - Viewport, - DragMovement, - DraggableIdMap, - OnLift, -} from '../types'; -import noImpact from './no-impact'; -import getDraggablesInsideDroppable from './get-draggables-inside-droppable'; -import getDisplacedBy from './get-displaced-by'; -import getDisplacementMap from './get-displacement-map'; -import getDisplacement from './get-displacement'; - -type Args = {| - draggable: DraggableDimension, - home: DroppableDimension, - draggables: DraggableDimensionMap, - viewport: Viewport, -|}; - -type Result = {| - onLift: OnLift, - impact: DragImpact, -|}; - -export default ({ draggable, home, draggables, viewport }: Args): Result => { - const displacedBy: DisplacedBy = getDisplacedBy( - home.axis, - draggable.displaceBy, - ); - - const insideHome: DraggableDimension[] = getDraggablesInsideDroppable( - home.descriptor.id, - draggables, - ); - - const originallyDisplaced: DraggableDimension[] = insideHome.slice( - draggable.descriptor.index + 1, - ); - const wasDisplaced: DraggableIdMap = originallyDisplaced.reduce( - (previous: DraggableIdMap, item: DraggableDimension): DraggableIdMap => { - previous[item.descriptor.id] = true; - return previous; - }, - {}, - ); - const onLift: OnLift = { - displacedBy, - wasDisplaced, - }; - - const displaced: Displacement[] = originallyDisplaced.map( - (dimension: DraggableDimension): Displacement => - getDisplacement({ - draggable: dimension, - destination: home, - previousImpact: noImpact, - viewport: viewport.frame, - // originally we do not want any animation as we want - // everything to be fixed in the same position that - // it started in - forceShouldAnimate: false, - onLift, - }), - ); - - const movement: DragMovement = { - displaced, - map: getDisplacementMap(displaced), - displacedBy, - }; - - const impact: DragImpact = { - movement, - destination: getHomeLocation(draggable.descriptor), - merge: null, - }; - - return { impact, onLift }; -}; diff --git a/src/state/get-impact-location.js b/src/state/get-impact-location.js new file mode 100644 index 0000000000..c1c338aa8c --- /dev/null +++ b/src/state/get-impact-location.js @@ -0,0 +1,16 @@ +// @flow +import type { DragImpact, DraggableLocation, Combine } from '../types'; + +export function tryGetDestination(impact: DragImpact): ?DraggableLocation { + if (impact.at && impact.at.type === 'REORDER') { + return impact.at.destination; + } + return null; +} + +export function tryGetCombine(impact: DragImpact): ?Combine { + if (impact.at && impact.at.type === 'COMBINE') { + return impact.at.combine; + } + return null; +} diff --git a/src/state/get-lift-effect.js b/src/state/get-lift-effect.js new file mode 100644 index 0000000000..26e9164346 --- /dev/null +++ b/src/state/get-lift-effect.js @@ -0,0 +1,82 @@ +// @flow +import invariant from 'tiny-invariant'; +import getHomeLocation from './get-home-location'; +import type { + DraggableDimension, + DroppableDimension, + DraggableDimensionMap, + DragImpact, + DisplacedBy, + Viewport, + DraggableIdMap, + DisplacementGroups, + LiftEffect, +} from '../types'; +import getDraggablesInsideDroppable from './get-draggables-inside-droppable'; +import getDisplacedBy from './get-displaced-by'; +import getDisplacementGroups from './get-displacement-groups'; + +type Args = {| + draggable: DraggableDimension, + home: DroppableDimension, + draggables: DraggableDimensionMap, + viewport: Viewport, +|}; + +type Result = {| + afterCritical: LiftEffect, + impact: DragImpact, +|}; + +export default ({ draggable, home, draggables, viewport }: Args): Result => { + const displacedBy: DisplacedBy = getDisplacedBy( + home.axis, + draggable.displaceBy, + ); + + const insideHome: DraggableDimension[] = getDraggablesInsideDroppable( + home.descriptor.id, + draggables, + ); + + // in a list that does not start at 0 the descriptor.index might be different from the index in the list + // eg a list could be: [2,3,4]. A descriptor.index of '2' would actually be in index '0' of the list + const rawIndex: number = insideHome.indexOf(draggable); + invariant(rawIndex !== -1, 'Expected draggable to be inside home list'); + + const afterDragging: DraggableDimension[] = insideHome.slice(rawIndex + 1); + const effected: DraggableIdMap = afterDragging.reduce( + (previous: DraggableIdMap, item: DraggableDimension): DraggableIdMap => { + previous[item.descriptor.id] = true; + return previous; + }, + {}, + ); + const afterCritical: LiftEffect = { + inVirtualList: home.descriptor.mode === 'VIRTUAL', + displacedBy, + effected, + }; + + const displaced: DisplacementGroups = getDisplacementGroups({ + afterDragging, + destination: home, + displacedBy, + last: null, + viewport: viewport.frame, + // originally we do not want any animation as we want + // everything to be fixed in the same position that + // it started in + forceShouldAnimate: false, + }); + + const impact: DragImpact = { + displaced, + displacedBy, + at: { + type: 'REORDER', + destination: getHomeLocation(draggable.descriptor), + }, + }; + return { impact, afterCritical }; +}; diff --git a/src/state/middleware/auto-scroll.js b/src/state/middleware/auto-scroll.js index 57123c1cc4..f9cf6b6f81 100644 --- a/src/state/middleware/auto-scroll.js +++ b/src/state/middleware/auto-scroll.js @@ -4,7 +4,7 @@ import type { AutoScroller } from '../auto-scroller/auto-scroller-types'; import type { Action, Dispatch, MiddlewareStore } from '../store-types'; import type { State } from '../../types'; -const shouldEnd = (action: Action): boolean => +const shouldStop = (action: Action): boolean => action.type === 'DROP_COMPLETE' || action.type === 'DROP_ANIMATE' || action.type === 'CLEAN'; @@ -15,7 +15,7 @@ const shouldCancelPending = (action: Action): boolean => export default (autoScroller: AutoScroller) => (store: MiddlewareStore) => ( next: Dispatch, ) => (action: Action): any => { - if (shouldEnd(action)) { + if (shouldStop(action)) { autoScroller.stop(); next(action); return; diff --git a/src/state/middleware/drop-animation-finish.js b/src/state/middleware/drop/drop-animation-finish-middleware.js similarity index 73% rename from src/state/middleware/drop-animation-finish.js rename to src/state/middleware/drop/drop-animation-finish-middleware.js index c0e23b8dd8..2a53a1ddd5 100644 --- a/src/state/middleware/drop-animation-finish.js +++ b/src/state/middleware/drop/drop-animation-finish-middleware.js @@ -1,8 +1,8 @@ // @flow import invariant from 'tiny-invariant'; -import { completeDrop } from '../action-creators'; -import type { State } from '../../types'; -import type { MiddlewareStore, Action, Dispatch } from '../store-types'; +import { completeDrop } from '../../action-creators'; +import type { State } from '../../../types'; +import type { MiddlewareStore, Action, Dispatch } from '../../store-types'; export default (store: MiddlewareStore) => (next: Dispatch) => ( action: Action, diff --git a/src/state/middleware/drop/drop-animation-flush-on-scroll-middleware.js b/src/state/middleware/drop/drop-animation-flush-on-scroll-middleware.js new file mode 100644 index 0000000000..8471b044e2 --- /dev/null +++ b/src/state/middleware/drop/drop-animation-flush-on-scroll-middleware.js @@ -0,0 +1,62 @@ +// @flow +import { dropAnimationFinished } from '../../action-creators'; +import type { State } from '../../../types'; +import type { MiddlewareStore, Action, Dispatch } from '../../store-types'; +import type { EventBinding } from '../../../view/event-bindings/event-types'; +import bindEvents from '../../../view/event-bindings/bind-events'; + +export default (store: MiddlewareStore) => { + let unbind: ?() => void = null; + let frameId: ?AnimationFrameID = null; + + function clear() { + if (frameId) { + cancelAnimationFrame(frameId); + frameId = null; + } + + if (unbind) { + unbind(); + unbind = null; + } + } + + return (next: Dispatch) => (action: Action): any => { + if ( + action.type === 'CLEAN' || + action.type === 'DROP_COMPLETE' || + action.type === 'DROP_ANIMATION_FINISHED' + ) { + clear(); + } + + next(action); + + if (action.type !== 'DROP_ANIMATE') { + return; + } + + const binding: EventBinding = { + eventName: 'scroll', + // capture: true will catch all scroll events, event from scroll containers + // once: just in case, we only want to ever fire one + options: { capture: true, passive: false }, + fn: function flushDropAnimation() { + const state: State = store.getState(); + if (state.phase === 'DROP_ANIMATING') { + store.dispatch(dropAnimationFinished()); + } + }, + }; + + // The browser can batch a few scroll events in a single frame + // including the one that ended the drag. + // Binding after a requestAnimationFrame ensures that any scrolls caused + // by the auto scroller are finished + // TODO: why is a second window scroll being fired? + // It leads to funny drop positions :( + frameId = requestAnimationFrame(() => { + unbind = bindEvents(window, [binding]); + }); + }; +}; diff --git a/src/state/middleware/drop/drop-middleware.js b/src/state/middleware/drop/drop-middleware.js index d0079e3945..e7ea15c82f 100644 --- a/src/state/middleware/drop/drop-middleware.js +++ b/src/state/middleware/drop/drop-middleware.js @@ -23,6 +23,7 @@ import { isEqual } from '../../position'; import getDropDuration from './get-drop-duration'; import getNewHomeClientOffset from './get-new-home-client-offset'; import getDropImpact, { type Result } from './get-drop-impact'; +import { tryGetCombine, tryGetDestination } from '../../get-impact-location'; export default ({ getState, dispatch }: MiddlewareStore) => ( next: Dispatch, @@ -64,27 +65,27 @@ export default ({ getState, dispatch }: MiddlewareStore) => ( const critical: Critical = state.critical; const dimensions: DimensionMap = state.dimensions; + const draggable: DraggableDimension = + dimensions.draggables[state.critical.draggable.id]; // Only keeping impact when doing a user drop - otherwise we are cancelling const { impact, didDropInsideDroppable }: Result = getDropImpact({ reason, lastImpact: state.impact, - onLift: state.onLift, + afterCritical: state.afterCritical, onLiftImpact: state.onLiftImpact, home: state.dimensions.droppables[state.critical.droppable.id], viewport: state.viewport, draggables: state.dimensions.draggables, }); - const draggable: DraggableDimension = - dimensions.draggables[state.critical.draggable.id]; - // only populating destination / combine if 'didDropInsideDroppable' is true const destination: ?DraggableLocation = didDropInsideDroppable - ? impact.destination + ? tryGetDestination(impact) + : null; + const combine: ?Combine = didDropInsideDroppable + ? tryGetCombine(impact) : null; - const combine: ?Combine = - didDropInsideDroppable && impact.merge ? impact.merge.combine : null; const source: DraggableLocation = { index: critical.draggable.index, @@ -107,11 +108,12 @@ export default ({ getState, dispatch }: MiddlewareStore) => ( draggable, dimensions, viewport: state.viewport, - onLift: state.onLift, + afterCritical: state.afterCritical, }); const completed: CompletedDrag = { critical: state.critical, + afterCritical: state.afterCritical, result, impact, }; diff --git a/src/state/middleware/drop/get-drop-impact.js b/src/state/middleware/drop/get-drop-impact.js index caed464cbf..30d2b81260 100644 --- a/src/state/middleware/drop/get-drop-impact.js +++ b/src/state/middleware/drop/get-drop-impact.js @@ -5,20 +5,19 @@ import type { Viewport, DroppableDimension, DraggableDimensionMap, - OnLift, + LiftEffect, } from '../../../types'; -import whatIsDraggedOver from '../../droppable/what-is-dragged-over'; import recompute from '../../update-displacement-visibility/recompute'; -import { noMovement } from '../../no-impact'; +import { emptyGroups } from '../../no-impact'; type Args = {| + draggables: DraggableDimensionMap, + home: DroppableDimension, reason: DropReason, lastImpact: DragImpact, onLiftImpact: DragImpact, viewport: Viewport, - home: DroppableDimension, - draggables: DraggableDimensionMap, - onLift: OnLift, + afterCritical: LiftEffect, |}; export type Result = {| @@ -27,45 +26,40 @@ export type Result = {| |}; export default ({ + draggables, reason, lastImpact, home, viewport, - draggables, onLiftImpact, - onLift, }: Args): Result => { - const didDropInsideDroppable: boolean = - reason === 'DROP' && Boolean(whatIsDraggedOver(lastImpact)); - - if (!didDropInsideDroppable) { + if (!lastImpact.at || reason !== 'DROP') { // Dropping outside of a list or the drag was cancelled // Going to use the on lift impact // Need to recompute the visibility of the original impact // What is visible can be different to when the drag started - const impact: DragImpact = recompute({ + const recomputedHomeImpact: DragImpact = recompute({ + draggables, impact: onLiftImpact, destination: home, viewport, - draggables, - onLift, // We need the draggables to animate back to their positions forceShouldAnimate: true, }); return { - impact, - didDropInsideDroppable, + impact: recomputedHomeImpact, + didDropInsideDroppable: false, }; } // use the existing impact - if (lastImpact.destination) { + if (lastImpact.at.type === 'REORDER') { return { impact: lastImpact, - didDropInsideDroppable, + didDropInsideDroppable: true, }; } @@ -73,11 +67,11 @@ export default ({ // will animate closed const withoutMovement: DragImpact = { ...lastImpact, - movement: noMovement, + displaced: emptyGroups, }; return { impact: withoutMovement, - didDropInsideDroppable, + didDropInsideDroppable: true, }; }; diff --git a/src/state/middleware/drop/get-new-home-client-offset.js b/src/state/middleware/drop/get-new-home-client-offset.js index 9b36d0fe36..40a9eedfd9 100644 --- a/src/state/middleware/drop/get-new-home-client-offset.js +++ b/src/state/middleware/drop/get-new-home-client-offset.js @@ -7,20 +7,19 @@ import type { DimensionMap, DraggableDimension, DroppableId, - OnLift, - CombineImpact, + LiftEffect, + Combine, } from '../../../types'; import whatIsDraggedOver from '../../droppable/what-is-dragged-over'; import { subtract } from '../../position'; import getClientBorderBoxCenter from '../../get-center-from-impact/get-client-border-box-center'; -import didStartDisplaced from '../../starting-displaced/did-start-displaced'; type Args = {| impact: DragImpact, draggable: DraggableDimension, dimensions: DimensionMap, viewport: Viewport, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -28,7 +27,7 @@ export default ({ draggable, dimensions, viewport, - onLift, + afterCritical, }: Args): Position => { const { draggables, droppables } = dimensions; const droppableId: ?DroppableId = whatIsDraggedOver(impact); @@ -42,7 +41,7 @@ export default ({ draggable, draggables, // if there is no destination, then we will be dropping back into the home - onLift, + afterCritical, droppable: destination || home, viewport, }); @@ -52,14 +51,5 @@ export default ({ draggable.client.borderBox.center, ); - const merge: ?CombineImpact = impact.merge; - - // When dropping with a merge we want to drop the dragging item - // into the new home location of the target. - // The target will move as a result of a drop if it started displaced - if (merge && didStartDisplaced(merge.combine.draggableId, onLift)) { - return subtract(offset, onLift.displacedBy.point); - } - return offset; }; diff --git a/src/state/middleware/focus.js b/src/state/middleware/focus.js new file mode 100644 index 0000000000..ecb760c631 --- /dev/null +++ b/src/state/middleware/focus.js @@ -0,0 +1,42 @@ +// @flow +import type { DropResult } from '../../types'; +import type { Action, Dispatch } from '../store-types'; +import type { FocusMarshal } from '../../view/use-focus-marshal/focus-marshal-types'; + +export default (marshal: FocusMarshal) => { + let isWatching: boolean = false; + + return () => (next: Dispatch) => (action: Action): any => { + if (action.type === 'INITIAL_PUBLISH') { + isWatching = true; + + marshal.tryRecordFocus(action.payload.critical.draggable.id); + next(action); + marshal.tryRestoreFocusRecorded(); + return; + } + + next(action); + + if (!isWatching) { + return; + } + + if (action.type === 'CLEAN') { + isWatching = false; + marshal.tryRestoreFocusRecorded(); + return; + } + + if (action.type === 'DROP_COMPLETE') { + isWatching = false; + const result: DropResult = action.payload.completed.result; + + // give focus to the combine target when combining + if (result.combine) { + marshal.tryShiftRecord(result.draggableId, result.combine.draggableId); + } + marshal.tryRestoreFocusRecorded(); + } + }; +}; diff --git a/src/state/middleware/lift.js b/src/state/middleware/lift.js index d9f3909036..3e50966cc0 100644 --- a/src/state/middleware/lift.js +++ b/src/state/middleware/lift.js @@ -1,9 +1,10 @@ // @flow import invariant from 'tiny-invariant'; -import { completeDrop, initialPublish } from '../action-creators'; import type { DimensionMarshal } from '../dimension-marshal/dimension-marshal-types'; import type { State, ScrollOptions, LiftRequest } from '../../types'; import type { MiddlewareStore, Action, Dispatch } from '../store-types'; +import { completeDrop, initialPublish } from '../action-creators'; +import validateDimensions from './util/validate-dimensions'; export default (marshal: DimensionMarshal) => ({ getState, @@ -36,6 +37,8 @@ export default (marshal: DimensionMarshal) => ({ // Let's get the marshal started! const { critical, dimensions, viewport } = marshal.startPublishing(request); + validateDimensions(critical, dimensions); + // Okay, we are good to start dragging now dispatch( initialPublish({ diff --git a/src/state/middleware/responders/expiring-announce.js b/src/state/middleware/responders/expiring-announce.js index 92ba9ddf7f..3259dd74e2 100644 --- a/src/state/middleware/responders/expiring-announce.js +++ b/src/state/middleware/responders/expiring-announce.js @@ -2,7 +2,11 @@ import type { Announce } from '../../../types'; import { warning } from '../../../dev-warning'; -export default (announce: Announce) => { +export type ExpiringAnnounce = Announce & { + wasCalled: () => boolean, +}; + +export default (announce: Announce): ExpiringAnnounce => { let wasCalled: boolean = false; let isExpired: boolean = false; diff --git a/src/state/middleware/responders/publisher.js b/src/state/middleware/responders/publisher.js index 44d6574de2..c8b84455d1 100644 --- a/src/state/middleware/responders/publisher.js +++ b/src/state/middleware/responders/publisher.js @@ -1,8 +1,10 @@ // @flow import invariant from 'tiny-invariant'; -import messagePreset from '../util/screen-reader-message-preset'; +import messagePreset from '../../../screen-reader-message-preset'; import * as timings from '../../../debug/timings'; -import getExpiringAnnounce from './expiring-announce'; +import getExpiringAnnounce, { + type ExpiringAnnounce, +} from './expiring-announce'; import getAsyncMarshal, { type AsyncMarshal } from './async-marshal'; import type { DropResult, @@ -22,6 +24,7 @@ import type { OnDragEndResponder, } from '../../../types'; import { isCombineEqual, isCriticalEqual, areLocationsEqual } from './is-equal'; +import { tryGetDestination, tryGetCombine } from '../../get-impact-location'; const withTimings = (key: string, fn: Function) => { timings.start(key); @@ -56,7 +59,7 @@ const execute = ( return; } - const willExpire: Announce = getExpiringAnnounce(announce); + const willExpire: ExpiringAnnounce = getExpiringAnnounce(announce); const provided: ResponderProvided = { announce: willExpire, }; @@ -122,8 +125,9 @@ export default (getResponders: () => Responders, announce: Announce) => { // Passing in the critical location again as it can change during a drag const update = (critical: Critical, impact: DragImpact) => { - const location: ?DraggableLocation = impact.destination; - const combine: ?Combine = impact.merge ? impact.merge.combine : null; + const location: ?DraggableLocation = tryGetDestination(impact); + const combine: ?Combine = tryGetCombine(impact); + invariant( dragging, 'Cannot fire onDragMove when onDragStart has not been called', diff --git a/src/state/middleware/scroll-listener.js b/src/state/middleware/scroll-listener.js new file mode 100644 index 0000000000..0a15f4eb72 --- /dev/null +++ b/src/state/middleware/scroll-listener.js @@ -0,0 +1,31 @@ +// @flow +import type { Position } from 'css-box-model'; +import { moveByWindowScroll } from '../action-creators'; +import type { MiddlewareStore, Action, Dispatch } from '../store-types'; +import getScrollListener from '../../view/scroll-listener'; + +// TODO: this is taken from auto-scroll. Let's make it a util +const shouldEnd = (action: Action): boolean => + action.type === 'DROP_COMPLETE' || + action.type === 'DROP_ANIMATE' || + action.type === 'CLEAN'; + +export default (store: MiddlewareStore) => { + const listener = getScrollListener({ + onWindowScroll: (newScroll: Position) => { + store.dispatch(moveByWindowScroll({ newScroll })); + }, + }); + + return (next: Dispatch) => (action: Action): any => { + if (!listener.isActive() && action.type === 'INITIAL_PUBLISH') { + listener.start(); + } + + if (listener.isActive() && shouldEnd(action)) { + listener.stop(); + } + + next(action); + }; +}; diff --git a/src/state/middleware/util/validate-dimensions.js b/src/state/middleware/util/validate-dimensions.js new file mode 100644 index 0000000000..fc4bdee5e1 --- /dev/null +++ b/src/state/middleware/util/validate-dimensions.js @@ -0,0 +1,74 @@ +// @flow +import type { + Critical, + DimensionMap, + DroppableId, + DraggableDimensionMap, + DraggableDimension, +} from '../../../types'; +import getDraggablesInsideDroppable from '../../get-draggables-inside-droppable'; +import { warning } from '../../../dev-warning'; + +function checkIndexesAreConsecutive( + droppableId: DroppableId, + draggables: DraggableDimensionMap, +) { + const insideDestination = getDraggablesInsideDroppable( + droppableId, + draggables, + ); + + // no point running if there are 1 or less items + if (insideDestination.length <= 1) { + return; + } + + const indexes: number[] = insideDestination.map( + (d: DraggableDimension): number => d.descriptor.index, + ); + + type ErrorMap = { + [index: number]: true, + }; + const errors: ErrorMap = {}; + + for (let i = 1; i < indexes.length; i++) { + const current: number = indexes[i]; + const previous: number = indexes[i - 1]; + + if (current !== previous + 1) { + errors[current] = true; + } + } + + // all good! + if (!Object.keys(errors).length) { + return; + } + + const formatted: string = indexes + .map((index: number): string => { + const hasError: boolean = Boolean(errors[index]); + + return hasError ? `[๐Ÿ”ฅ${index}]` : `${index}`; + }) + .join(', '); + + warning(` + Detected non-consecutive Draggable indexes + + (This can cause unexpected bugs) + + ${formatted} + `); +} + +export default function validateDimensions( + critical: Critical, + dimensions: DimensionMap, +): void { + // wrapping entire block for better minification + if (process.env.NODE_ENV !== 'production') { + checkIndexesAreConsecutive(critical.droppable.id, dimensions.draggables); + } +} diff --git a/src/state/move-in-direction/index.js b/src/state/move-in-direction/index.js index ced7fc4a4a..7080aa1980 100644 --- a/src/state/move-in-direction/index.js +++ b/src/state/move-in-direction/index.js @@ -69,7 +69,7 @@ export default ({ state, type }: Args): ?PublicResult => { viewport: state.viewport, previousClientSelection: state.current.client.selection, previousImpact: state.impact, - onLift: state.onLift, + afterCritical: state.afterCritical, }) : moveCrossAxis({ isMovingForward, @@ -78,8 +78,7 @@ export default ({ state, type }: Args): ?PublicResult => { isOver, draggables, droppables, - previousImpact: state.impact, viewport: state.viewport, - onLift: state.onLift, + afterCritical: state.afterCritical, }); }; diff --git a/src/state/move-in-direction/move-cross-axis/get-closest-draggable.js b/src/state/move-in-direction/move-cross-axis/get-closest-draggable.js index 8705ae9031..2518bf117b 100644 --- a/src/state/move-in-direction/move-cross-axis/get-closest-draggable.js +++ b/src/state/move-in-direction/move-cross-axis/get-closest-draggable.js @@ -4,7 +4,7 @@ import type { Viewport, DraggableDimension, DroppableDimension, - OnLift, + LiftEffect, } from '../../../types'; import { distance } from '../../position'; import { isTotallyVisible } from '../../visibility/is-visible'; @@ -21,7 +21,7 @@ type Args = {| destination: DroppableDimension, // the droppables inside the destination insideDestination: DraggableDimension[], - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -29,7 +29,7 @@ export default ({ viewport, destination, insideDestination, - onLift, + afterCritical, }: Args): ?DraggableDimension => { const sorted: DraggableDimension[] = insideDestination .filter((draggable: DraggableDimension): boolean => @@ -37,7 +37,7 @@ export default ({ // but must be visible in the droppable // We can improve this, but this limitation is easier for now isTotallyVisible({ - target: getCurrentPageBorderBox(draggable, onLift), + target: getCurrentPageBorderBox(draggable, afterCritical), destination, viewport: viewport.frame, withDroppableDisplacement: true, @@ -49,14 +49,14 @@ export default ({ pageBorderBoxCenter, withDroppableDisplacement( destination, - getCurrentPageBorderBoxCenter(a, onLift), + getCurrentPageBorderBoxCenter(a, afterCritical), ), ); const distanceToB = distance( pageBorderBoxCenter, withDroppableDisplacement( destination, - getCurrentPageBorderBoxCenter(b, onLift), + getCurrentPageBorderBoxCenter(b, afterCritical), ), ); diff --git a/src/state/move-in-direction/move-cross-axis/index.js b/src/state/move-in-direction/move-cross-axis/index.js index f436630005..e87ede0f6f 100644 --- a/src/state/move-in-direction/move-cross-axis/index.js +++ b/src/state/move-in-direction/move-cross-axis/index.js @@ -8,7 +8,7 @@ import type { DroppableDimensionMap, DragImpact, Viewport, - OnLift, + LiftEffect, } from '../../../types'; import getBestCrossAxisDroppable from './get-best-cross-axis-droppable'; import getClosestDraggable from './get-closest-draggable'; @@ -29,11 +29,9 @@ type Args = {| // all the dimensions in the system draggables: DraggableDimensionMap, droppables: DroppableDimensionMap, - // any previous impact - previousImpact: DragImpact, // the current viewport viewport: Viewport, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -43,9 +41,8 @@ export default ({ isOver, draggables, droppables, - previousImpact, viewport, - onLift, + afterCritical, }: Args): ?PublicResult => { // not considering the container scroll changes as container scrolling cancels a keyboard drag @@ -72,7 +69,7 @@ export default ({ viewport, destination, insideDestination, - onLift, + afterCritical, }); const impact: ?DragImpact = moveToNewDroppable({ @@ -82,9 +79,8 @@ export default ({ draggables, moveRelativeTo, insideDestination, - previousImpact, viewport, - onLift, + afterCritical, }); if (!impact) { @@ -96,7 +92,7 @@ export default ({ draggable, droppable: destination, draggables, - onLift, + afterCritical, }); const clientSelection: Position = getClientFromPageBorderBoxCenter({ diff --git a/src/state/move-in-direction/move-cross-axis/move-to-new-droppable.js b/src/state/move-in-direction/move-cross-axis/move-to-new-droppable.js index d7e450e2bd..1b706cfabc 100644 --- a/src/state/move-in-direction/move-cross-axis/move-to-new-droppable.js +++ b/src/state/move-in-direction/move-cross-axis/move-to-new-droppable.js @@ -1,25 +1,21 @@ // @flow import type { Position } from 'css-box-model'; -import invariant from 'tiny-invariant'; import type { DragImpact, DraggableDimension, DraggableDimensionMap, DroppableDimension, - Displacement, Viewport, DisplacedBy, - OnLift, + LiftEffect, } from '../../../types'; import getDisplacedBy from '../../get-displaced-by'; -import getDisplacement from '../../get-displacement'; -import getDisplacementMap from '../../get-displacement-map'; -import { noMovement } from '../../no-impact'; +import { emptyGroups, noDisplacedBy } from '../../no-impact'; import getPageBorderBoxCenter from '../../get-center-from-impact/get-page-border-box-center'; import isTotallyVisibleInNewLocation from '../move-to-next-place/is-totally-visible-in-new-location'; import { addPlaceholder } from '../../droppable/with-placeholder'; -import removeDraggableFromList from '../../remove-draggable-from-list'; import isHomeOf from '../../droppable/is-home-of'; +import calculateReorderImpact from '../../calculate-drag-impact/calculate-reorder-impact'; type Args = {| previousPageBorderBoxCenter: Position, @@ -28,9 +24,8 @@ type Args = {| draggable: DraggableDimension, draggables: DraggableDimensionMap, destination: DroppableDimension, - previousImpact: DragImpact, viewport: Viewport, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -40,9 +35,8 @@ export default ({ draggable, draggables, destination, - previousImpact, viewport, - onLift, + afterCritical, }: Args): ?DragImpact => { if (!moveRelativeTo) { // Draggables available, but none are candidates for movement @@ -52,19 +46,22 @@ export default ({ // Try move to top of empty list if it is visible const proposed: DragImpact = { - movement: noMovement, - destination: { - droppableId: destination.descriptor.id, - index: 0, + displaced: emptyGroups, + displacedBy: noDisplacedBy, + at: { + type: 'REORDER', + destination: { + droppableId: destination.descriptor.id, + index: 0, + }, }, - merge: null, }; const proposedPageBorderBoxCenter: Position = getPageBorderBoxCenter({ impact: proposed, draggable, droppable: destination, draggables, - onLift, + afterCritical, }); // need to add room for a placeholder in a foreign list @@ -86,58 +83,39 @@ export default ({ } const isGoingBeforeTarget: boolean = Boolean( - previousPageBorderBoxCenter[destination.axis.line] < + // Using <= as we optimise slightly for moving before items in a new list + // This is nicer in lists with fixed height items + previousPageBorderBoxCenter[destination.axis.line] <= moveRelativeTo.page.borderBox.center[destination.axis.line], ); - // Moving to a populated list - const targetIndex: number = insideDestination.indexOf(moveRelativeTo); - invariant(targetIndex !== -1, 'Cannot find target in list'); - const proposedIndex: number = (() => { - // TODO: is this logic correct? + const relativeTo: number = moveRelativeTo.descriptor.index; + if (moveRelativeTo.descriptor.id === draggable.descriptor.id) { - return targetIndex; + return relativeTo; } if (isGoingBeforeTarget) { - return targetIndex; + return relativeTo; } - return targetIndex + 1; + return relativeTo + 1; })(); - const displaced: Displacement[] = removeDraggableFromList( - draggable, - insideDestination, - ) - .slice(proposedIndex) - .map((dimension: DraggableDimension): Displacement => - getDisplacement({ - draggable: dimension, - destination, - viewport: viewport.frame, - previousImpact, - onLift, - }), - ); - const displacedBy: DisplacedBy = getDisplacedBy( destination.axis, draggable.displaceBy, ); - const impact: DragImpact = { - movement: { - displacedBy, - displaced, - map: getDisplacementMap(displaced), - }, - destination: { - droppableId: destination.descriptor.id, - index: proposedIndex, - }, - merge: null, - }; - return impact; + return calculateReorderImpact({ + draggable, + insideDestination, + destination, + viewport, + displacedBy, + // last groups won't be relevant + last: emptyGroups, + index: proposedIndex, + }); }; diff --git a/src/state/move-in-direction/move-cross-axis/without-starting-displacement.js b/src/state/move-in-direction/move-cross-axis/without-starting-displacement.js index 627e8fb707..fdcff6f02a 100644 --- a/src/state/move-in-direction/move-cross-axis/without-starting-displacement.js +++ b/src/state/move-in-direction/move-cross-axis/without-starting-displacement.js @@ -1,31 +1,31 @@ // @flow import type { Position, Rect, Spacing } from 'css-box-model'; -import type { DraggableDimension, OnLift } from '../../../types'; +import type { DraggableDimension, LiftEffect } from '../../../types'; import { negate, subtract } from '../../position'; import { offsetByPosition } from '../../spacing'; -import didStartDisplaced from '../../starting-displaced/did-start-displaced'; +import didStartAfterCritical from '../../did-start-after-critical'; export const getCurrentPageBorderBoxCenter = ( draggable: DraggableDimension, - onLift: OnLift, + afterCritical: LiftEffect, ): Position => { // If an item started displaced it is now resting // in a non-displaced location const original: Position = draggable.page.borderBox.center; - return didStartDisplaced(draggable.descriptor.id, onLift) - ? subtract(original, onLift.displacedBy.point) + return didStartAfterCritical(draggable.descriptor.id, afterCritical) + ? subtract(original, afterCritical.displacedBy.point) : original; }; export const getCurrentPageBorderBox = ( draggable: DraggableDimension, - onLift: OnLift, + afterCritical: LiftEffect, ): Spacing => { // If an item started displaced it is now resting // in a non-displaced location const original: Rect = draggable.page.borderBox; - return didStartDisplaced(draggable.descriptor.id, onLift) - ? offsetByPosition(original, negate(onLift.displacedBy.point)) + return didStartAfterCritical(draggable.descriptor.id, afterCritical) + ? offsetByPosition(original, negate(afterCritical.displacedBy.point)) : original; }; diff --git a/src/state/move-in-direction/move-to-next-place/index.js b/src/state/move-in-direction/move-to-next-place/index.js index 44681e7bbe..a06be6f8f4 100644 --- a/src/state/move-in-direction/move-to-next-place/index.js +++ b/src/state/move-in-direction/move-to-next-place/index.js @@ -6,7 +6,7 @@ import type { DraggableDimensionMap, DragImpact, Viewport, - OnLift, + LiftEffect, } from '../../../types'; import type { PublicResult } from '../move-in-direction-types'; import getDraggablesInsideDroppable from '../../get-draggables-inside-droppable'; @@ -28,7 +28,7 @@ type Args = {| viewport: Viewport, previousClientSelection: Position, previousPageBorderBoxCenter: Position, - onLift: OnLift, + afterCritical: LiftEffect, |}; export default ({ @@ -40,7 +40,7 @@ export default ({ viewport, previousPageBorderBoxCenter, previousClientSelection, - onLift, + afterCritical, }: Args): ?PublicResult => { if (!destination.isEnabled) { return null; @@ -54,7 +54,6 @@ export default ({ const impact: ?DragImpact = moveToNextCombine({ - isInHomeList, isMovingForward, draggable, destination, @@ -69,7 +68,8 @@ export default ({ destination, insideDestination, previousImpact, - onLift, + viewport, + afterCritical, }); if (!impact) { @@ -81,7 +81,7 @@ export default ({ draggable, droppable: destination, draggables, - onLift, + afterCritical, }); const isVisibleInNewLocation: boolean = isTotallyVisibleInNewLocation({ @@ -122,7 +122,6 @@ export default ({ destination, draggables, maxScrollChange: distance, - onLift, }); return { diff --git a/src/state/move-in-direction/move-to-next-place/move-to-next-combine/index.js b/src/state/move-in-direction/move-to-next-place/move-to-next-combine/index.js index 0a0faed8f0..cb16d7bee8 100644 --- a/src/state/move-in-direction/move-to-next-place/move-to-next-combine/index.js +++ b/src/state/move-in-direction/move-to-next-place/move-to-next-combine/index.js @@ -6,15 +6,18 @@ import type { DragImpact, CombineImpact, DraggableLocation, + DraggableId, } from '../../../../types'; import { forward, backward, } from '../../../user-direction/user-direction-preset'; +import { tryGetDestination } from '../../../get-impact-location'; +import { findIndex } from '../../../../native-with-fallback'; +import removeDraggableFromList from '../../../remove-draggable-from-list'; export type Args = {| isMovingForward: boolean, - isInHomeList: boolean, draggable: DraggableDimension, destination: DroppableDimension, insideDestination: DraggableDimension[], @@ -23,77 +26,77 @@ export type Args = {| export default ({ isMovingForward, - isInHomeList, draggable, destination, - insideDestination: originalInsideDestination, + insideDestination, previousImpact, }: Args): ?DragImpact => { if (!destination.isCombineEnabled) { return null; } - // we move from a merge to a reorder - if (previousImpact.merge) { + const location: ?DraggableLocation = tryGetDestination(previousImpact); + + if (!location) { return null; } - // we are on a location, and we are trying to combine onto a sibling - // that sibling might be displaced + function getImpact(target: DraggableId) { + const at: CombineImpact = { + type: 'COMBINE', + whenEntered: isMovingForward ? forward : backward, + combine: { + draggableId: target, + droppableId: destination.descriptor.id, + }, + }; + return { + ...previousImpact, + at, + }; + } - const location: ?DraggableLocation = previousImpact.destination; - invariant(location, 'Need a previous location to move from into a combine'); + const all: DraggableId[] = previousImpact.displaced.all; + const closestId: ?DraggableId = all.length ? all[0] : null; - const currentIndex: number = location.index; + if (isMovingForward) { + return closestId ? getImpact(closestId) : null; + } - // update the insideDestination list to reflect the current list order - // TODO: cleanup - const currentInsideDestination: DraggableDimension[] = (() => { - const shallow = originalInsideDestination.slice(); + const withoutDraggable = removeDraggableFromList( + draggable, + insideDestination, + ); - // if we are in the home list we need to remove the item from its original position - // before we insert it into its new position - if (isInHomeList) { - shallow.splice(draggable.descriptor.index, 1); + // Moving backwards + + // if nothing is displaced - move backwards onto the last item + if (!closestId) { + if (!withoutDraggable.length) { + return null; } + const last: DraggableDimension = + withoutDraggable[withoutDraggable.length - 1]; + return getImpact(last.descriptor.id); + } - // put the draggable into its current position in the list - shallow.splice(location.index, 0, draggable); - return shallow; - })(); + // We are moving from being between two displaced items + // backwards onto the first one - const targetIndex: number = isMovingForward - ? currentIndex + 1 - : currentIndex - 1; + // need to find the first item before the closest + const indexOfClosest: number = findIndex( + withoutDraggable, + d => d.descriptor.id === closestId, + ); + invariant(indexOfClosest !== -1, 'Could not find displaced item in set'); - if (targetIndex < 0) { - return null; - } + const proposedIndex: number = indexOfClosest - 1; - // The last item that can be grouped with is the last one - if (targetIndex > currentInsideDestination.length - 1) { + // There is no displaced item before + if (proposedIndex < 0) { return null; } - // TODO: what if target is original!? - const target: DraggableDimension = currentInsideDestination[targetIndex]; - invariant(target !== draggable, 'Cannot combine with self'); - - const merge: CombineImpact = { - whenEntered: isMovingForward ? forward : backward, - combine: { - draggableId: target.descriptor.id, - droppableId: destination.descriptor.id, - }, - }; - - const impact: DragImpact = { - // grouping does not modify the existing displacement - movement: previousImpact.movement, - // grouping removes the destination - destination: null, - merge, - }; - - return impact; + const before: DraggableDimension = withoutDraggable[proposedIndex]; + return getImpact(before.descriptor.id); }; diff --git a/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-combine.js b/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-combine.js index 0d77b9609f..d28b29c33f 100644 --- a/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-combine.js +++ b/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-combine.js @@ -1,99 +1,52 @@ // @flow import type { DroppableDimension, - DragImpact, - CombineImpact, + Combine, DraggableDimension, DraggableDimensionMap, + DisplacementGroups, DraggableId, - DragMovement, - OnLift, + LiftEffect, } from '../../../../types'; -import type { Instruction } from './move-to-next-index-types'; -import didStartDisplaced from '../../../starting-displaced/did-start-displaced'; +import didStartAfterCritical from '../../../did-start-after-critical'; type Args = {| isMovingForward: boolean, destination: DroppableDimension, - previousImpact: DragImpact, + displaced: DisplacementGroups, draggables: DraggableDimensionMap, - merge: CombineImpact, - onLift: OnLift, + combine: Combine, + afterCritical: LiftEffect, |}; export default ({ isMovingForward, destination, - previousImpact, draggables, - merge, - onLift, -}: Args): ?Instruction => { + combine, + afterCritical, +}: Args): ?number => { if (!destination.isCombineEnabled) { return null; } - - const movement: DragMovement = previousImpact.movement; - const combineId: DraggableId = merge.combine.draggableId; - const combine: DraggableDimension = draggables[combineId]; - const combineIndex: number = combine.descriptor.index; - const wasDisplacedAtStart: boolean = didStartDisplaced(combineId, onLift); - - if (wasDisplacedAtStart) { - const hasDisplacedFromStart: boolean = !movement.map[combineId]; - - if (hasDisplacedFromStart) { - if (isMovingForward) { - return { - proposedIndex: combineIndex, - modifyDisplacement: false, - }; - } - - return { - proposedIndex: combineIndex - 1, - modifyDisplacement: true, - }; - } - - // move into position of combine - if (isMovingForward) { - return { - proposedIndex: combineIndex, - modifyDisplacement: true, - }; - } - - return { - proposedIndex: combineIndex - 1, - modifyDisplacement: false, - }; - } - - const isDisplaced: boolean = Boolean(movement.map[combineId]); - - if (isDisplaced) { + const combineId: DraggableId = combine.draggableId; + const combineWith: DraggableDimension = draggables[combineId]; + const combineWithIndex: number = combineWith.descriptor.index; + const didCombineWithStartAfterCritical: boolean = didStartAfterCritical( + combineId, + afterCritical, + ); + + if (didCombineWithStartAfterCritical) { if (isMovingForward) { - return { - proposedIndex: combineIndex + 1, - modifyDisplacement: true, - }; + return combineWithIndex; } - return { - proposedIndex: combineIndex, - modifyDisplacement: false, - }; + return combineWithIndex - 1; } if (isMovingForward) { - return { - proposedIndex: combineIndex + 1, - modifyDisplacement: false, - }; + return combineWithIndex + 1; } - return { - proposedIndex: combineIndex, - modifyDisplacement: true, - }; + return combineWithIndex; }; diff --git a/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-reorder.js b/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-reorder.js index cc343ee51b..571f3f98ea 100644 --- a/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-reorder.js +++ b/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-reorder.js @@ -1,43 +1,43 @@ // @flow import type { DraggableDimension, DraggableLocation } from '../../../../types'; -import type { Instruction } from './move-to-next-index-types'; type Args = {| isMovingForward: boolean, isInHomeList: boolean, location: DraggableLocation, - draggable: DraggableDimension, insideDestination: DraggableDimension[], |}; export default ({ isMovingForward, isInHomeList, - draggable, - insideDestination: initialInside, + insideDestination, location, -}: Args): ?Instruction => { - const insideDestination: DraggableDimension[] = initialInside.slice(); - const currentIndex: number = location.index; - const isInForeignList: boolean = !isInHomeList; - - // in foreign list we need to insert the item into the right spot - if (isInForeignList) { - insideDestination.splice(location.index, 0, draggable); +}: Args): ?number => { + // cannot move in the list + if (!insideDestination.length) { + return null; } + + const currentIndex: number = location.index; const proposedIndex: number = isMovingForward ? currentIndex + 1 : currentIndex - 1; - if (proposedIndex < 0) { + // Accounting for lists that might not start with an index of 0 + const firstIndex: number = insideDestination[0].descriptor.index; + const lastIndex: number = + insideDestination[insideDestination.length - 1].descriptor.index; + + // When in foreign list we allow movement after the last item + const upperBound: number = isInHomeList ? lastIndex : lastIndex + 1; + + if (proposedIndex < firstIndex) { return null; } - if (proposedIndex > insideDestination.length - 1) { + if (proposedIndex > upperBound) { return null; } - return { - proposedIndex, - modifyDisplacement: true, - }; + return proposedIndex; }; diff --git a/src/state/move-in-direction/move-to-next-place/move-to-next-index/index.js b/src/state/move-in-direction/move-to-next-place/move-to-next-index/index.js index 91db020a78..3998e5c362 100644 --- a/src/state/move-in-direction/move-to-next-place/move-to-next-index/index.js +++ b/src/state/move-in-direction/move-to-next-place/move-to-next-index/index.js @@ -5,17 +5,13 @@ import type { DroppableDimension, DraggableDimensionMap, DragImpact, - DisplacedBy, - Displacement, - OnLift, + LiftEffect, + Viewport, + ImpactLocation, } from '../../../../types'; -import type { Instruction } from './move-to-next-index-types'; -import getDisplacementMap from '../../../get-displacement-map'; -import { addClosest, removeClosest } from '../update-displacement'; -import getDisplacedBy from '../../../get-displaced-by'; -import fromReorder from './from-reorder'; +import calculateReorderImpact from '../../../calculate-drag-impact/calculate-reorder-impact'; import fromCombine from './from-combine'; -import removeDraggableFromList from '../../../remove-draggable-from-list'; +import fromReorder from './from-reorder'; export type Args = {| isMovingForward: boolean, @@ -25,7 +21,8 @@ export type Args = {| destination: DroppableDimension, insideDestination: DraggableDimension[], previousImpact: DragImpact, - onLift: OnLift, + viewport: Viewport, + afterCritical: LiftEffect, |}; export default ({ @@ -36,78 +33,54 @@ export default ({ destination, insideDestination, previousImpact, - onLift, + viewport, + afterCritical, }: Args): ?DragImpact => { - const instruction: ?Instruction = (() => { - // moving from reorder - if (previousImpact.destination) { - return fromReorder({ - isMovingForward, - isInHomeList, - draggable, - location: previousImpact.destination, - insideDestination, - }); - } - - // moving from merge - if (previousImpact.merge) { - return fromCombine({ - isMovingForward, - destination, - previousImpact, - draggables, - merge: previousImpact.merge, - onLift, - }); - } - - invariant('Cannot move to next spot without a destination or merge'); - return null; - })(); - - if (instruction == null) { - return null; - } + const wasAt: ?ImpactLocation = previousImpact.at; + invariant(wasAt, 'Cannot move in direction without previous impact location'); - const { proposedIndex, modifyDisplacement } = instruction; - const displacedBy: DisplacedBy = getDisplacedBy( - destination.axis, - draggable.displaceBy, - ); - - const displaced: Displacement[] = (() => { - const lastDisplaced: Displacement[] = previousImpact.movement.displaced; - - if (!modifyDisplacement) { - return lastDisplaced; - } - - if (isMovingForward) { - return removeClosest(lastDisplaced); + if (wasAt.type === 'REORDER') { + const newIndex: ?number = fromReorder({ + isMovingForward, + isInHomeList, + location: wasAt.destination, + insideDestination, + }); + // TODO: can we just pass new index on? + if (newIndex == null) { + return null; } - - // moving backwards - will increase the amount of displaced items - - const withoutDraggable: DraggableDimension[] = removeDraggableFromList( + return calculateReorderImpact({ draggable, insideDestination, - ); + destination, + viewport, + last: previousImpact.displaced, + displacedBy: previousImpact.displacedBy, + index: newIndex, + }); + } - const atProposedIndex: DraggableDimension = withoutDraggable[proposedIndex]; - return addClosest(atProposedIndex, lastDisplaced); - })(); + // COMBINE + const newIndex: ?number = fromCombine({ + isMovingForward, + destination, + displaced: previousImpact.displaced, + draggables, + combine: wasAt.combine, + afterCritical, + }); + if (newIndex == null) { + return null; + } - return { - movement: { - displacedBy, - displaced, - map: getDisplacementMap(displaced), - }, - destination: { - droppableId: destination.descriptor.id, - index: proposedIndex, - }, - merge: null, - }; + return calculateReorderImpact({ + draggable, + insideDestination, + destination, + viewport, + last: previousImpact.displaced, + displacedBy: previousImpact.displacedBy, + index: newIndex, + }); }; diff --git a/src/state/move-in-direction/move-to-next-place/move-to-next-index/move-to-next-index-types.js b/src/state/move-in-direction/move-to-next-place/move-to-next-index/move-to-next-index-types.js deleted file mode 100644 index 9db9d7a137..0000000000 --- a/src/state/move-in-direction/move-to-next-place/move-to-next-index/move-to-next-index-types.js +++ /dev/null @@ -1,6 +0,0 @@ -// @flow - -export type Instruction = {| - proposedIndex: number, - modifyDisplacement: boolean, -|}; diff --git a/src/state/move-in-direction/move-to-next-place/update-displacement.js b/src/state/move-in-direction/move-to-next-place/update-displacement.js deleted file mode 100644 index 59125d3131..0000000000 --- a/src/state/move-in-direction/move-to-next-place/update-displacement.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow -import type { DraggableDimension, Displacement } from '../../../types'; - -export const addClosest = ( - add: DraggableDimension, - displaced: Displacement[], -): Displacement[] => { - const added: Displacement = { - draggableId: add.descriptor.id, - isVisible: true, - shouldAnimate: true, - }; - return [added, ...displaced]; -}; - -export const removeClosest = (displaced: Displacement[]): Displacement[] => - displaced.slice(1); diff --git a/src/state/no-impact.js b/src/state/no-impact.js index 57e6075c58..b62a3b169f 100644 --- a/src/state/no-impact.js +++ b/src/state/no-impact.js @@ -1,5 +1,10 @@ // @flow -import type { DragMovement, DragImpact, DisplacedBy } from '../types'; +import type { + DisplacementGroups, + DragImpact, + DisplacedBy, + LiftEffect, +} from '../types'; import { origin } from './position'; export const noDisplacedBy: DisplacedBy = { @@ -7,16 +12,22 @@ export const noDisplacedBy: DisplacedBy = { value: 0, }; -export const noMovement: DragMovement = { - displaced: [], - map: {}, - displacedBy: noDisplacedBy, +export const emptyGroups: DisplacementGroups = { + invisible: {}, + visible: {}, + all: [], }; const noImpact: DragImpact = { - movement: noMovement, - destination: null, - merge: null, + displaced: emptyGroups, + displacedBy: noDisplacedBy, + at: null, }; export default noImpact; + +export const noAfterCritical: LiftEffect = { + inVirtualList: false, + effected: {}, + displacedBy: noDisplacedBy, +}; diff --git a/src/state/post-reducer/when-moving/refresh-snap.js b/src/state/post-reducer/when-moving/refresh-snap.js index f4d7325db4..0fd50e3eb8 100644 --- a/src/state/post-reducer/when-moving/refresh-snap.js +++ b/src/state/post-reducer/when-moving/refresh-snap.js @@ -44,7 +44,6 @@ Args): StateWhenUpdatesAllowed => { viewport, destination, draggables, - onLift: state.onLift, }); const clientSelection: Position = getClientBorderBoxCenter({ @@ -53,7 +52,7 @@ Args): StateWhenUpdatesAllowed => { droppable: destination, draggables, viewport, - onLift: state.onLift, + afterCritical: state.afterCritical, }); return update({ diff --git a/src/state/post-reducer/when-moving/update.js b/src/state/post-reducer/when-moving/update.js index 62d8bd742c..5b8dae49f2 100644 --- a/src/state/post-reducer/when-moving/update.js +++ b/src/state/post-reducer/when-moving/update.js @@ -99,7 +99,7 @@ export default ({ previousImpact: state.impact, viewport, userDirection, - onLift: state.onLift, + afterCritical: state.afterCritical, }); const withUpdatedPlaceholders: DroppableDimensionMap = recomputePlaceholders({ diff --git a/src/state/publish-while-dragging-in-virtual/index.js b/src/state/publish-while-dragging-in-virtual/index.js new file mode 100644 index 0000000000..2c43589ce5 --- /dev/null +++ b/src/state/publish-while-dragging-in-virtual/index.js @@ -0,0 +1,147 @@ +// @flow +import type { + DimensionMap, + DraggingState, + CollectingState, + DropPendingState, + Published, + Scrollable, + DraggableId, + DraggableDimension, + DroppableDimensionMap, + DraggableDimensionMap, + DroppableDimension, + DragImpact, +} from '../../types'; +import * as timings from '../../debug/timings'; +import getDragImpact from '../get-drag-impact'; +import adjustAdditionsForScrollChanges from '../publish-while-dragging/update-draggables/adjust-additions-for-scroll-changes'; +import { toDraggableMap, toDroppableMap } from '../dimension-structures'; +import getLiftEffect from '../get-lift-effect'; +import scrollDroppable from '../droppable/scroll-droppable'; + +type Args = {| + state: CollectingState | DropPendingState, + published: Published, +|}; + +const timingsKey: string = 'Processing dynamic changes'; + +export default ({ + state, + published, +}: Args): DraggingState | DropPendingState => { + timings.start(timingsKey); + + // TODO: update window scroll (needs to be a part of the published object) + + // The scroll might be different to what is currently in the state + // We want to ensure the new draggables are in step with the state + const withScrollChange: DroppableDimension[] = published.modified.map( + (droppable: DroppableDimension): DroppableDimension => { + const existing: DroppableDimension = + state.dimensions.droppables[droppable.descriptor.id]; + + // TODO: need to ensure collector is okay with collecting from non-scroll containers + // TODO: collector should be updated to simply return a list of current scroll positions + const frame: ?Scrollable = existing.frame; + if (!frame) { + return droppable; + } + const scrolled: DroppableDimension = scrollDroppable( + existing, + frame.scroll.current, + ); + return scrolled; + }, + ); + + const droppables: DroppableDimensionMap = { + ...state.dimensions.droppables, + ...toDroppableMap(withScrollChange), + }; + + const updated: DraggableDimension[] = adjustAdditionsForScrollChanges({ + additions: published.additions, + updatedDroppables: droppables, + viewport: state.viewport, + }); + + const draggables: DraggableDimensionMap = { + ...state.dimensions.draggables, + ...toDraggableMap(updated), + }; + + // remove all the old ones (except for the critical) + // we do this so that list operations remain fast + // TODO: need to test the impact of this like crazy + published.removals.forEach((id: DraggableId) => { + delete draggables[id]; + }); + + const dimensions: DimensionMap = { + droppables, + draggables, + }; + + const draggable: DraggableDimension = + dimensions.draggables[state.critical.draggable.id]; + const home: DroppableDimension = + dimensions.droppables[state.critical.droppable.id]; + + const { impact: onLiftImpact, afterCritical } = getLiftEffect({ + draggable, + home, + draggables, + viewport: state.viewport, + }); + + const impact: DragImpact = getDragImpact({ + pageBorderBoxCenter: state.current.page.borderBoxCenter, + draggable: dimensions.draggables[state.critical.draggable.id], + draggables: dimensions.draggables, + droppables: dimensions.droppables, + // starting from a fresh slate + previousImpact: state.impact, + viewport: state.viewport, + userDirection: state.userDirection, + afterCritical, + }); + + timings.finish(timingsKey); + + const draggingState: DraggingState = { + // appeasing flow + phase: 'DRAGGING', + ...state, + // eslint-disable-next-line + phase: 'DRAGGING', + impact, + onLiftImpact, + dimensions, + afterCritical, + // not animating this movement + forceShouldAnimate: false, + }; + + if (state.phase === 'COLLECTING') { + return draggingState; + } + + // There was a DROP_PENDING + // Staying in the DROP_PENDING phase + // setting isWaiting for false + + const dropPending: DropPendingState = { + // appeasing flow + phase: 'DROP_PENDING', + ...draggingState, + // eslint-disable-next-line + phase: 'DROP_PENDING', + // No longer waiting + reason: state.reason, + isWaiting: false, + }; + + return dropPending; +}; diff --git a/src/state/publish-while-dragging/index.js b/src/state/publish-while-dragging/index.js index 5e182ec9dd..a7fae15053 100644 --- a/src/state/publish-while-dragging/index.js +++ b/src/state/publish-while-dragging/index.js @@ -15,7 +15,7 @@ import type { import * as timings from '../../debug/timings'; import whatIsDraggedOver from '../droppable/what-is-dragged-over'; import getDragImpact from '../get-drag-impact'; -import getHomeOnLift from '../get-home-on-lift'; +import getLiftEffects from '../get-lift-effect'; import getDragPositions from './get-drag-positions'; import updateDraggables from './update-draggables'; import updateDroppables from './update-droppables'; diff --git a/src/state/publish-while-dragging/with-no-animated-displacement.js b/src/state/publish-while-dragging/with-no-animated-displacement.js index 4f1471a6c4..e6cbba49b8 100644 --- a/src/state/publish-while-dragging/with-no-animated-displacement.js +++ b/src/state/publish-while-dragging/with-no-animated-displacement.js @@ -1,6 +1,6 @@ // @flow import type { DragImpact, Displacement } from '../../types'; -import getDisplacementMap from '../get-displacement-map'; +// import getDisplacementMap from '../get-displacement-map'; export default (impact: DragImpact): DragImpact => { const displaced: Displacement[] = impact.movement.displaced; diff --git a/src/state/reducer.js b/src/state/reducer.js index 1c21f7416c..34f9cb9e95 100644 --- a/src/state/reducer.js +++ b/src/state/reducer.js @@ -29,8 +29,9 @@ import { toDroppableList } from './dimension-structures'; import { forward } from './user-direction/user-direction-preset'; import update from './post-reducer/when-moving/update'; import refreshSnap from './post-reducer/when-moving/refresh-snap'; -import getHomeOnLift from './get-home-on-lift'; +import getLiftEffect from './get-lift-effect'; import patchDimensionMap from './patch-dimension-map'; +import publishWhileDraggingInVirtual from './publish-while-dragging-in-virtual'; const isSnapping = (state: StateWhenUpdatesAllowed): boolean => state.movementMode === 'SNAP'; @@ -103,7 +104,7 @@ export default (state: State = idle, action: Action): State => { dimensions.droppables, ).every((item: DroppableDimension) => !item.isFixedOnPage); - const { impact, onLift } = getHomeOnLift({ + const { impact, afterCritical } = getLiftEffect({ draggable, home, draggables: dimensions.draggables, @@ -120,7 +121,7 @@ export default (state: State = idle, action: Action): State => { current: initial, isWindowScrollAllowed, impact, - onLift, + afterCritical, onLiftImpact: impact, viewport, userDirection: forward, @@ -161,7 +162,7 @@ export default (state: State = idle, action: Action): State => { `Unexpected ${action.type} received in phase ${state.phase}`, ); - return publishWhileDragging({ + return publishWhileDraggingInVirtual({ state, published: action.payload, }); @@ -420,10 +421,10 @@ export default (state: State = idle, action: Action): State => { // Moving into a new phase const result: DropAnimatingState = { phase: 'DROP_ANIMATING', - dimensions: state.dimensions, completed, dropDuration, newHomeClientOffset, + dimensions: state.dimensions, }; return result; diff --git a/src/state/registry/create-registry.js b/src/state/registry/create-registry.js new file mode 100644 index 0000000000..ba5ebbf0e1 --- /dev/null +++ b/src/state/registry/create-registry.js @@ -0,0 +1,162 @@ +// @flow +import invariant from 'tiny-invariant'; +import type { TypeId, DraggableId, DroppableId } from '../../types'; +import type { + Registry, + DraggableAPI, + DroppableAPI, + DraggableEntry, + DroppableEntry, + RegistryEvent, + Subscriber, + Unsubscribe, + DraggableEntryMap, + DroppableEntryMap, +} from './registry-types'; +import { values } from '../../native-with-fallback'; + +type EntryMap = { + draggables: DraggableEntryMap, + droppables: DroppableEntryMap, +}; + +export default function createRegistry(): Registry { + const entries: EntryMap = { + draggables: {}, + droppables: {}, + }; + + const subscribers: Subscriber[] = []; + + function subscribe(cb: Subscriber): Unsubscribe { + subscribers.push(cb); + + return function unsubscribe(): void { + const index: number = subscribers.indexOf(cb); + + // might have been removed by a clean + if (index === -1) { + return; + } + + subscribers.splice(index, 1); + }; + } + + function notify(event: RegistryEvent) { + if (subscribers.length) { + subscribers.forEach(cb => cb(event)); + } + } + + function findDraggableById(id: DraggableId): ?DraggableEntry { + return entries.draggables[id] || null; + } + + function getDraggableById(id: DraggableId): DraggableEntry { + const entry: ?DraggableEntry = findDraggableById(id); + invariant(entry, `Cannot find draggable entry with id [${id}]`); + return entry; + } + + const draggableAPI: DraggableAPI = { + register: (entry: DraggableEntry) => { + entries.draggables[entry.descriptor.id] = entry; + notify({ type: 'ADDITION', value: entry }); + }, + update: (entry: DraggableEntry, last: DraggableEntry) => { + const current: ?DraggableEntry = entries.draggables[last.descriptor.id]; + + // item already removed + if (!current) { + return; + } + + // id already used for another mount + if (current.uniqueId !== entry.uniqueId) { + return; + } + + // We are safe to delete the old entry and add a new one + delete entries.draggables[last.descriptor.id]; + entries.draggables[entry.descriptor.id] = entry; + }, + unregister: (entry: DraggableEntry) => { + const draggableId: DraggableId = entry.descriptor.id; + const current: ?DraggableEntry = findDraggableById(draggableId); + + // can occur if cleaned before unregistration + if (!current) { + return; + } + + // outdated uniqueId + if (entry.uniqueId !== current.uniqueId) { + return; + } + + delete entries.draggables[draggableId]; + notify({ type: 'REMOVAL', value: entry.descriptor }); + }, + getById: getDraggableById, + findById: findDraggableById, + exists: (id: DraggableId): boolean => Boolean(findDraggableById(id)), + getAllByType: (type: TypeId): DraggableEntry[] => + values(entries.draggables).filter( + (entry: DraggableEntry): boolean => entry.descriptor.type === type, + ), + }; + + function findDroppableById(id: DroppableId): ?DroppableEntry { + return entries.droppables[id] || null; + } + + function getDroppableById(id: DroppableId): DroppableEntry { + const entry: ?DroppableEntry = findDroppableById(id); + invariant(entry, `Cannot find droppable entry with id [${id}]`); + return entry; + } + + const droppableAPI: DroppableAPI = { + register: (entry: DroppableEntry) => { + entries.droppables[entry.descriptor.id] = entry; + }, + unregister: (entry: DroppableEntry) => { + const current: ?DroppableEntry = findDroppableById(entry.descriptor.id); + + // can occur if cleaned before an unregistry + if (!current) { + return; + } + + // already changed + if (entry.uniqueId !== current.uniqueId) { + return; + } + + delete entries.droppables[entry.descriptor.id]; + }, + getById: getDroppableById, + findById: findDroppableById, + exists: (id: DroppableId): boolean => Boolean(findDroppableById(id)), + getAllByType: (type: TypeId): DroppableEntry[] => + values(entries.droppables).filter( + (entry: DroppableEntry): boolean => entry.descriptor.type === type, + ), + }; + + function clean(): void { + // kill entries + entries.draggables = {}; + entries.droppables = {}; + // remove all subscribers + subscribers.length = 0; + } + + return { + draggable: draggableAPI, + droppable: droppableAPI, + subscribe, + clean, + }; +} diff --git a/src/state/registry/registry-types.js b/src/state/registry/registry-types.js new file mode 100644 index 0000000000..67bfda6f8e --- /dev/null +++ b/src/state/registry/registry-types.js @@ -0,0 +1,98 @@ +// @flow +import type { Position } from 'css-box-model'; +import type { + Id, + DraggableId, + DraggableDescriptor, + DraggableOptions, + DraggableDimension, + DroppableId, + ScrollOptions, + DroppableDescriptor, + DroppableDimension, + TypeId, +} from '../../types'; + +export type GetDraggableDimensionFn = ( + windowScroll: Position, +) => DraggableDimension; + +export type DraggableEntry = {| + uniqueId: Id, + descriptor: DraggableDescriptor, + options: DraggableOptions, + getDimension: GetDraggableDimensionFn, +|}; + +export type DraggableAPI = {| + register: (entry: DraggableEntry) => void, + update: (entry: DraggableEntry, last: DraggableEntry) => void, + unregister: (entry: DraggableEntry) => void, + exists: (id: DraggableId) => boolean, + getById: (id: DraggableId) => DraggableEntry, + findById: (id: DraggableId) => ?DraggableEntry, + getAllByType: (type: TypeId) => DraggableEntry[], +|}; + +export type GetDroppableDimensionFn = ( + windowScroll: Position, + options: ScrollOptions, +) => DroppableDimension; + +export type RecollectDroppableOptions = {| + withoutPlaceholder: boolean, +|}; + +export type DroppableCallbacks = {| + // a drag is starting + getDimensionAndWatchScroll: GetDroppableDimensionFn, + recollect: (options: RecollectDroppableOptions) => DroppableDimension, + // scroll a droppable + scroll: (change: Position) => void, + // If the Droppable is listening for scroll events - it needs to stop! + // Can be called on droppables that have not been asked to watch scroll + dragStopped: () => void, +|}; + +export type DroppableEntry = {| + uniqueId: Id, + descriptor: DroppableDescriptor, + callbacks: DroppableCallbacks, +|}; + +export type DraggableEntryMap = { + [id: DraggableId]: DraggableEntry, +}; + +export type DroppableEntryMap = { + [id: DroppableId]: DroppableEntry, +}; + +export type DroppableAPI = {| + register: (entry: DroppableEntry) => void, + unregister: (entry: DroppableEntry) => void, + exists: (id: DraggableId) => boolean, + getById: (id: DroppableId) => DroppableEntry, + findById: (id: DroppableId) => ?DroppableEntry, + getAllByType: (type: TypeId) => DroppableEntry[], +|}; + +export type RegistryEvent = + | {| + type: 'ADDITION', + value: DraggableEntry, + |} + | {| + type: 'REMOVAL', + value: DraggableDescriptor, + |}; + +export type Subscriber = (event: RegistryEvent) => void; +export type Unsubscribe = () => void; + +export type Registry = {| + draggable: DraggableAPI, + droppable: DroppableAPI, + subscribe: (cb: Subscriber) => Unsubscribe, + clean: () => void, +|}; diff --git a/src/state/registry/use-registry.js b/src/state/registry/use-registry.js new file mode 100644 index 0000000000..19a5864ab8 --- /dev/null +++ b/src/state/registry/use-registry.js @@ -0,0 +1,20 @@ +// @flow +import { useEffect } from 'react'; +import { useMemo } from 'use-memo-one'; +import type { Registry } from './registry-types'; +import createRegistry from './create-registry'; + +export default function useRegistry(): Registry { + const registry: Registry = useMemo(createRegistry, []); + + useEffect(() => { + return function unmount() { + // clean up the registry to avoid any leaks + // doing it after an animation frame so that other things unmounting + // can continue to interact with the registry + requestAnimationFrame(registry.clean); + }; + }, [registry]); + + return registry; +} diff --git a/src/state/starting-displaced/did-start-displaced.js b/src/state/starting-displaced/did-start-displaced.js deleted file mode 100644 index c2cc9a8e4e..0000000000 --- a/src/state/starting-displaced/did-start-displaced.js +++ /dev/null @@ -1,5 +0,0 @@ -// @flow -import type { DraggableId, OnLift } from '../../types'; - -export default (draggableId: DraggableId, onLift: OnLift): boolean => - Boolean(onLift.wasDisplaced[draggableId]); diff --git a/src/state/update-displacement-visibility/recompute.js b/src/state/update-displacement-visibility/recompute.js index f15029ab8a..d3a5d59846 100644 --- a/src/state/update-displacement-visibility/recompute.js +++ b/src/state/update-displacement-visibility/recompute.js @@ -1,43 +1,54 @@ // @flow import type { + DraggableDimension, DroppableDimension, DraggableDimensionMap, DragImpact, - Displacement, Viewport, - OnLift, + DraggableId, + DisplacementGroups, } from '../../types'; -import getDisplacement from '../get-displacement'; -import withNewDisplacement from './with-new-displacement'; +import getDisplacementGroups from '../get-displacement-groups'; type RecomputeArgs = {| impact: DragImpact, + draggables: DraggableDimensionMap, destination: DroppableDimension, viewport: Viewport, - onLift: OnLift, - draggables: DraggableDimensionMap, forceShouldAnimate?: boolean, |}; +function getDraggables( + ids: DraggableId[], + draggables: DraggableDimensionMap, +): DraggableDimension[] { + return ids.map((id: DraggableId): DraggableDimension => draggables[id]); +} + export default ({ impact, viewport, - destination, draggables, - onLift, + destination, forceShouldAnimate, }: RecomputeArgs): DragImpact => { - const updated: Displacement[] = impact.movement.displaced.map( - (entry: Displacement) => - getDisplacement({ - draggable: draggables[entry.draggableId], - destination, - previousImpact: impact, - viewport: viewport.frame, - onLift, - forceShouldAnimate, - }), + const last: DisplacementGroups = impact.displaced; + const afterDragging: DraggableDimension[] = getDraggables( + last.all, + draggables, ); - return withNewDisplacement(impact, updated); + const displaced: DisplacementGroups = getDisplacementGroups({ + afterDragging, + destination, + displacedBy: impact.displacedBy, + viewport: viewport.frame, + forceShouldAnimate, + last, + }); + + return { + ...impact, + displaced, + }; }; diff --git a/src/state/update-displacement-visibility/speculatively-increase.js b/src/state/update-displacement-visibility/speculatively-increase.js index 33772e9884..47a4bb4aba 100644 --- a/src/state/update-displacement-visibility/speculatively-increase.js +++ b/src/state/update-displacement-visibility/speculatively-increase.js @@ -1,19 +1,21 @@ // @flow import type { Position } from 'css-box-model'; import type { + DraggableId, DroppableDimension, DraggableDimension, DraggableDimensionMap, DragImpact, Displacement, + DisplacementGroups, + DraggableIdMap, + DisplacementMap, Viewport, - OnLift, } from '../../types'; import scrollViewport from '../scroll-viewport'; import scrollDroppable from '../droppable/scroll-droppable'; import { add } from '../position'; -import getDisplacement from '../get-displacement'; -import withNewDisplacement from './with-new-displacement'; +import getDisplacementGroups from '../get-displacement-groups'; type SpeculativeArgs = {| impact: DragImpact, @@ -21,19 +23,35 @@ type SpeculativeArgs = {| viewport: Viewport, draggables: DraggableDimensionMap, maxScrollChange: Position, - onLift: OnLift, |}; +function getDraggables( + ids: DraggableId[], + draggables: DraggableDimensionMap, +): DraggableDimension[] { + return ids.map((id: DraggableId): DraggableDimension => draggables[id]); +} + +function tryGetVisible( + id: DraggableId, + groups: DisplacementGroups[], +): ?Displacement { + for (let i = 0; i < groups.length; i++) { + const displacement: ?Displacement = groups[i].visible[id]; + if (displacement) { + return displacement; + } + } + return null; +} + export default ({ impact, viewport, destination, draggables, maxScrollChange, - onLift, }: SpeculativeArgs): DragImpact => { - const displaced: Displacement[] = impact.movement.displaced; - const scrolledViewport: Viewport = scrollViewport( viewport, add(viewport.scroll.current, maxScrollChange), @@ -45,45 +63,49 @@ export default ({ ) : destination; - const updated: Displacement[] = displaced.map((entry: Displacement) => { - // already visible: do not need to speculatively increase - if (entry.isVisible) { - return entry; - } - - const draggable: DraggableDimension = draggables[entry.draggableId]; + const last: DisplacementGroups = impact.displaced; + const withViewportScroll: DisplacementGroups = getDisplacementGroups({ + afterDragging: getDraggables(last.all, draggables), + destination, + displacedBy: impact.displacedBy, + viewport: scrolledViewport.frame, + last, + // we want the addition to be animated + forceShouldAnimate: false, + }); + const withDroppableScroll: DisplacementGroups = getDisplacementGroups({ + afterDragging: getDraggables(last.all, draggables), + destination: scrolledDroppable, + displacedBy: impact.displacedBy, + viewport: viewport.frame, + last, + // we want the addition to be animated + forceShouldAnimate: false, + }); - // check if would be visibly displaced in a scrolled droppable or viewport + const invisible: DraggableIdMap = {}; + const visible: DisplacementMap = {}; + const groups: DisplacementGroups[] = [ + // this will populate the previous entries with the correct animation values + last, + withViewportScroll, + withDroppableScroll, + ]; - const withScrolledViewport: Displacement = getDisplacement({ - draggable, - destination, - previousImpact: impact, - viewport: scrolledViewport.frame, - onLift, - forceShouldAnimate: false, - }); + last.all.forEach((id: DraggableId) => { + const displacement: ?Displacement = tryGetVisible(id, groups); - if (withScrolledViewport.isVisible) { - return withScrolledViewport; + if (displacement) { + visible[id] = displacement; + return; } - - const withScrolledDroppable: Displacement = getDisplacement({ - draggable, - destination: scrolledDroppable, - previousImpact: impact, - viewport: viewport.frame, - onLift, - forceShouldAnimate: false, - }); - - if (withScrolledDroppable.isVisible) { - return withScrolledDroppable; - } - - // still not visible - return entry; + invisible[id] = true; }); - return withNewDisplacement(impact, updated); + const newImpact: DragImpact = { + ...impact, + displaced: { all: last.all, invisible, visible }, + }; + + return newImpact; }; diff --git a/src/state/update-displacement-visibility/with-new-displacement.js b/src/state/update-displacement-visibility/with-new-displacement.js deleted file mode 100644 index 090566c2cb..0000000000 --- a/src/state/update-displacement-visibility/with-new-displacement.js +++ /dev/null @@ -1,12 +0,0 @@ -// @flow -import type { DragImpact, Displacement } from '../../types'; -import getDisplacementMap from '../get-displacement-map'; - -export default (impact: DragImpact, displaced: Displacement[]): DragImpact => ({ - ...impact, - movement: { - ...impact.movement, - displaced, - map: getDisplacementMap(displaced), - }, -}); diff --git a/src/types.js b/src/types.js index e6f09d82bb..1cf274a5b1 100644 --- a/src/types.js +++ b/src/types.js @@ -5,10 +5,14 @@ export type Id = string; export type DraggableId = Id; export type DroppableId = Id; export type TypeId = Id; +export type ContextId = Id; +export type ElementId = Id; +export type DroppableMode = 'STANDARD' | 'VIRTUAL'; export type DroppableDescriptor = {| id: DroppableId, type: TypeId, + mode: DroppableMode, |}; export type DraggableDescriptor = {| @@ -21,6 +25,12 @@ export type DraggableDescriptor = {| type: TypeId, |}; +export type DraggableOptions = {| + canDragInteractiveElements: boolean, + shouldRespectForcePress: boolean, + isEnabled: boolean, +|}; + export type Direction = 'horizontal' | 'vertical'; export type VerticalAxis = {| @@ -144,12 +154,19 @@ export type DraggableLocation = {| index: number, |}; +export type DraggableIdMap = { + [id: DraggableId]: true, +}; + +export type DroppableIdMap = { + [id: DroppableId]: true, +}; + export type DraggableDimensionMap = { [key: DraggableId]: DraggableDimension }; export type DroppableDimensionMap = { [key: DroppableId]: DroppableDimension }; export type Displacement = {| draggableId: DraggableId, - isVisible: boolean, shouldAnimate: boolean, |}; @@ -160,15 +177,6 @@ export type DisplacedBy = {| point: Position, |}; -export type DragMovement = {| - // The draggables that need to move in response to a drag. - // Ordered by closest draggable to the *current* location of the dragging item - displaced: Displacement[], - // displaced as a map - map: DisplacementMap, - displacedBy: DisplacedBy, -|}; - export type VerticalUserDirection = 'up' | 'down'; export type HorizontalUserDirection = 'left' | 'right'; @@ -181,19 +189,35 @@ export type Combine = {| draggableId: DraggableId, droppableId: DroppableId, |}; +export type DisplacementGroups = {| + all: DraggableId[], + visible: DisplacementMap, + invisible: DraggableIdMap, +|}; + +export type ReorderImpact = {| + type: 'REORDER', + destination: DraggableLocation, +|}; export type CombineImpact = {| - // This has an impact on the hitbox for a grouping action + type: 'COMBINE', whenEntered: UserDirection, combine: Combine, |}; +export type ImpactLocation = ReorderImpact | CombineImpact; + +export type Displaced = {| + forwards: DisplacementGroups, + backwards: DisplacementGroups, +|}; + export type DragImpact = {| - movement: DragMovement, - // a reorder location - destination: ?DraggableLocation, - // a merge location - merge: ?CombineImpact, + // TODO: Displaced + displaced: DisplacementGroups, + displacedBy: DisplacedBy, + at: ?ImpactLocation, |}; export type ClientPositions = {| @@ -272,6 +296,12 @@ export type Viewport = {| scroll: ScrollDetails, |}; +export type LiftEffect = {| + inVirtualList: boolean, + effected: DraggableIdMap, + displacedBy: DisplacedBy, +|}; + export type DimensionMap = {| draggables: DraggableDimensionMap, droppables: DroppableDimensionMap, @@ -287,6 +317,7 @@ export type CompletedDrag = {| critical: Critical, result: DropResult, impact: DragImpact, + afterCritical: LiftEffect, |}; export type IdleState = {| @@ -295,15 +326,6 @@ export type IdleState = {| shouldFlush: boolean, |}; -export type DraggableIdMap = { - [id: DraggableId]: true, -}; - -export type OnLift = {| - wasDisplaced: DraggableIdMap, - displacedBy: DisplacedBy, -|}; - export type DraggingState = {| phase: 'DRAGGING', isDragging: true, @@ -315,7 +337,7 @@ export type DraggingState = {| userDirection: UserDirection, impact: DragImpact, viewport: Viewport, - onLift: OnLift, + afterCritical: LiftEffect, onLiftImpact: DragImpact, // when there is a fixed list we want to opt out of this behaviour isWindowScrollAllowed: boolean, @@ -394,3 +416,61 @@ export type Responders = {| // always required onDragEnd: OnDragEndResponder, |}; + +// ## Sensors +export type StopDragOptions = {| + shouldBlockNextClick: boolean, +|}; + +type DragActions = {| + drop: (args?: StopDragOptions) => void, + cancel: (args?: StopDragOptions) => void, + isActive: () => boolean, + shouldRespectForcePress: () => boolean, +|}; + +export type FluidDragActions = {| + ...DragActions, + move: (clientSelection: Position) => void, +|}; + +export type SnapDragActions = {| + ...DragActions, + moveUp: () => void, + moveDown: () => void, + moveRight: () => void, + moveLeft: () => void, +|}; + +export type PreDragActions = {| + // discover if the lock is still active + isActive: () => boolean, + // whether it has been indicated if force press should be respected + shouldRespectForcePress: () => boolean, + // lift the current item + fluidLift: (clientSelection: Position) => FluidDragActions, + snapLift: () => SnapDragActions, + // cancel the pre drag without starting a drag. Releases the lock + abort: () => void, +|}; + +export type TryGetLockOptions = { + sourceEvent?: Event, +}; + +export type TryGetLock = ( + draggableId: DraggableId, + forceStop?: () => void, + options?: TryGetLockOptions, +) => ?PreDragActions; + +export type SensorAPI = {| + tryGetLock: TryGetLock, + canGetLock: (id: DraggableId) => boolean, + isLockClaimed: () => boolean, + tryReleaseLock: () => void, + findClosestDraggableId: (event: Event) => ?DraggableId, + findOptionsForDraggable: (id: DraggableId) => ?DraggableOptions, +|}; + +export type Sensor = (api: SensorAPI) => void; diff --git a/src/view/context/app-context.js b/src/view/context/app-context.js index 45dcf6dc7a..226f32cf24 100644 --- a/src/view/context/app-context.js +++ b/src/view/context/app-context.js @@ -1,13 +1,18 @@ // @flow import React from 'react'; -import type { DraggableId } from '../../types'; +import type { DraggableId, ContextId, ElementId } from '../../types'; import type { DimensionMarshal } from '../../state/dimension-marshal/dimension-marshal-types'; +import type { FocusMarshal } from '../use-focus-marshal/focus-marshal-types'; +import type { Registry } from '../../state/registry/registry-types'; export type AppContextValue = {| - marshal: DimensionMarshal, - style: string, + focus: FocusMarshal, + contextId: ContextId, canLift: (id: DraggableId) => boolean, isMovementAllowed: () => boolean, + liftInstructionId: ElementId, + marshal: DimensionMarshal, + registry: Registry, |}; export default React.createContext(null); diff --git a/src/view/context/droppable-context.js b/src/view/context/droppable-context.js index a8e27227af..4e11d8e6c7 100644 --- a/src/view/context/droppable-context.js +++ b/src/view/context/droppable-context.js @@ -1,8 +1,9 @@ // @flow import React from 'react'; -import type { DroppableId, TypeId } from '../../types'; +import type { DraggableId, DroppableId, TypeId } from '../../types'; export type DroppableContextValue = {| + isUsingCloneFor: ?DraggableId, droppableId: DroppableId, type: TypeId, |}; diff --git a/src/view/data-attributes.js b/src/view/data-attributes.js index a6c9b7d551..8402fcf152 100644 --- a/src/view/data-attributes.js +++ b/src/view/data-attributes.js @@ -1,6 +1,37 @@ // @flow -export const prefix: string = 'data-react-beautiful-dnd'; -export const dragHandle: string = `${prefix}-drag-handle`; -export const draggable: string = `${prefix}-draggable`; -export const droppable: string = `${prefix}-droppable`; -export const placeholder: string = `${prefix}-placeholder`; +export const prefix: string = 'data-rbd'; +export const dragHandle = (() => { + const base = `${prefix}-drag-handle`; + + return { + base, + draggableId: `${base}-draggable-id`, + contextId: `${base}-context-id`, + }; +})(); + +export const draggable = (() => { + const base: string = `${prefix}-draggable`; + return { + base, + contextId: `${base}-context-id`, + id: `${base}-id`, + }; +})(); + +export const droppable = (() => { + const base: string = `${prefix}-droppable`; + return { + base, + contextId: `${base}-context-id`, + id: `${base}-id`, + }; +})(); + +export const placeholder = { + contextId: `${prefix}-placeholder-context-id`, +}; + +export const scrollContainer = { + contextId: `${prefix}-scroll-container-context-id`, +}; diff --git a/src/view/drag-drop-context/app.jsx b/src/view/drag-drop-context/app.jsx index a09480b28f..9cce89ad9a 100644 --- a/src/view/drag-drop-context/app.jsx +++ b/src/view/drag-drop-context/app.jsx @@ -10,13 +10,24 @@ import canStartDrag from '../../state/can-start-drag'; import scrollWindow from '../window/scroll-window'; import createAutoScroller from '../../state/auto-scroller'; import useStyleMarshal from '../use-style-marshal/use-style-marshal'; +import useFocusMarshal from '../use-focus-marshal'; +import useRegistry from '../../state/registry/use-registry'; +import type { Registry } from '../../state/registry/registry-types'; +import type { FocusMarshal } from '../use-focus-marshal/focus-marshal-types'; import type { AutoScroller } from '../../state/auto-scroller/auto-scroller-types'; import type { StyleMarshal } from '../use-style-marshal/style-marshal-types'; import type { DimensionMarshal, Callbacks as DimensionMarshalCallbacks, } from '../../state/dimension-marshal/dimension-marshal-types'; -import type { DraggableId, State, Responders, Announce } from '../../types'; +import type { + DraggableId, + State, + Responders, + Announce, + Sensor, + ElementId, +} from '../../types'; import type { Store, Action } from '../../state/store-types'; import StoreContext from '../context/store-context'; import { @@ -30,17 +41,24 @@ import { } from '../../state/action-creators'; import isMovementAllowed from '../../state/is-movement-allowed'; import useAnnouncer from '../use-announcer'; +import useDragHandleDescription from '../use-lift-instruction'; import AppContext, { type AppContextValue } from '../context/app-context'; import useStartupValidation from './use-startup-validation'; import usePrevious from '../use-previous-ref'; import { warning } from '../../dev-warning'; +import useSensorMarshal from '../use-sensor-marshal/use-sensor-marshal'; type Props = {| ...Responders, - uniqueId: number, + contextId: string, setOnError: (onError: Function) => void, // we do not technically need any children for this component children: Node | null, + + // sensors + sensors?: Sensor[], + enableDefaultSensors?: ?boolean, + liftInstruction: string, |}; const createResponders = (props: Props): Responders => ({ @@ -60,7 +78,7 @@ function getStore(lazyRef: LazyStoreRef): Store { } export default function App(props: Props) { - const { uniqueId, setOnError } = props; + const { contextId, setOnError, sensors, liftInstruction } = props; const lazyStoreRef: LazyStoreRef = useRef(null); useStartupValidation(); @@ -72,8 +90,13 @@ export default function App(props: Props) { return createResponders(lastPropsRef.current); }, [lastPropsRef]); - const announce: Announce = useAnnouncer(uniqueId); - const styleMarshal: StyleMarshal = useStyleMarshal(uniqueId); + const announce: Announce = useAnnouncer(contextId); + + const liftInstructionId: ElementId = useDragHandleDescription( + contextId, + liftInstruction, + ); + const styleMarshal: StyleMarshal = useStyleMarshal(contextId); const lazyDispatch: Action => void = useCallback((action: Action): void => { getStore(lazyStoreRef).dispatch(action); @@ -94,10 +117,12 @@ export default function App(props: Props) { ), [lazyDispatch], ); - const dimensionMarshal: DimensionMarshal = useMemo( - () => createDimensionMarshal(callbacks), - [callbacks], - ); + + const registry: Registry = useRegistry(); + + const dimensionMarshal: DimensionMarshal = useMemo(() => { + return createDimensionMarshal(registry, callbacks); + }, [registry, callbacks]); const autoScroller: AutoScroller = useMemo( () => @@ -115,16 +140,26 @@ export default function App(props: Props) { [dimensionMarshal.scrollDroppable, lazyDispatch], ); + const focusMarshal: FocusMarshal = useFocusMarshal(contextId); + const store: Store = useMemo( () => createStore({ - dimensionMarshal, - styleMarshal, announce, autoScroller, + dimensionMarshal, + focusMarshal, getResponders, + styleMarshal, }), - [announce, autoScroller, dimensionMarshal, getResponders, styleMarshal], + [ + announce, + autoScroller, + dimensionMarshal, + focusMarshal, + getResponders, + styleMarshal, + ], ); // Checking for unexpected store changes @@ -162,18 +197,33 @@ export default function App(props: Props) { const appContext: AppContextValue = useMemo( () => ({ marshal: dimensionMarshal, - style: styleMarshal.styleContext, + focus: focusMarshal, + contextId, canLift: getCanLift, isMovementAllowed: getIsMovementAllowed, + liftInstructionId, + registry, }), [ + contextId, dimensionMarshal, + focusMarshal, getCanLift, getIsMovementAllowed, - styleMarshal.styleContext, + liftInstructionId, + registry, ], ); + useSensorMarshal({ + contextId, + store, + registry, + customSensors: sensors, + // default to 'true' unless 'false' is explicitly passed + enableDefaultSensors: props.enableDefaultSensors !== false, + }); + // Clean store when unmounting useEffect(() => { return tryResetStore; diff --git a/src/view/drag-drop-context/drag-drop-context.jsx b/src/view/drag-drop-context/drag-drop-context.jsx index 156e573efb..32705d53bd 100644 --- a/src/view/drag-drop-context/drag-drop-context.jsx +++ b/src/view/drag-drop-context/drag-drop-context.jsx @@ -1,14 +1,19 @@ // @flow import React, { type Node } from 'react'; import { useMemo } from 'use-memo-one'; -import type { Responders } from '../../types'; +import type { Responders, ContextId, Sensor } from '../../types'; import ErrorBoundary from '../error-boundary'; +import preset from '../../screen-reader-message-preset'; import App from './app'; type Props = {| ...Responders, // we do not technically need any children for this component children: Node | null, + + sensors?: Sensor[], + enableDefaultSensors?: ?boolean, + liftInstruction?: string, |}; let instanceCount: number = 0; @@ -19,14 +24,21 @@ export function resetServerContext() { } export default function DragDropContext(props: Props) { - const uniqueId: number = useMemo(() => instanceCount++, []); + const contextId: ContextId = useMemo(() => `${instanceCount++}`, []); + const liftInstruction: string = + props.liftInstruction || preset.liftInstruction; // We need the error boundary to be on the outside of App // so that it can catch any errors caused by App return ( {setOnError => ( - + {props.children} )} diff --git a/src/view/draggable/check-own-props.js b/src/view/draggable/check-own-props.js deleted file mode 100644 index d7aefa0c7d..0000000000 --- a/src/view/draggable/check-own-props.js +++ /dev/null @@ -1,16 +0,0 @@ -// @flow -import invariant from 'tiny-invariant'; -import type { Props } from './draggable-types'; - -export default (props: Props) => { - // Number.isInteger will be provided by @babel/runtime-corejs2 - invariant( - Number.isInteger(props.index), - 'Draggable requires an integer index prop', - ); - invariant(props.draggableId, 'Draggable requires a draggableId'); - invariant( - typeof props.isDragDisabled === 'boolean', - 'isDragDisabled must be a boolean', - ); -}; diff --git a/src/view/draggable/connected-draggable.js b/src/view/draggable/connected-draggable.js index 56ef1df932..6176ac4ae2 100644 --- a/src/view/draggable/connected-draggable.js +++ b/src/view/draggable/connected-draggable.js @@ -5,38 +5,25 @@ import { Component } from 'react'; import memoizeOne from 'memoize-one'; import { connect } from 'react-redux'; import Draggable from './draggable'; -import { origin } from '../../state/position'; +import { origin, negate } from '../../state/position'; import isStrictEqual from '../is-strict-equal'; import { curves, combine } from '../../animation'; -import { - lift as liftAction, - move as moveAction, - moveUp as moveUpAction, - moveDown as moveDownAction, - moveLeft as moveLeftAction, - moveRight as moveRightAction, - drop as dropAction, - dropAnimationFinished as dropAnimationFinishedAction, - moveByWindowScroll as moveByWindowScrollAction, -} from '../../state/action-creators'; +import { dropAnimationFinished as dropAnimationFinishedAction } from '../../state/action-creators'; import type { State, DraggableId, DroppableId, - DragMovement, DraggableDimension, - CombineImpact, Displacement, CompletedDrag, DragImpact, - DisplacementMap, MovementMode, DropResult, + LiftEffect, } from '../../types'; import type { MapProps, OwnProps, - DefaultProps, DispatchProps, Selector, StateSnapshot, @@ -45,19 +32,27 @@ import type { import whatIsDraggedOver from '../../state/droppable/what-is-dragged-over'; import StoreContext from '../context/store-context'; import whatIsDraggedOverFromResult from '../../state/droppable/what-is-dragged-over-from-result'; +import { tryGetCombine } from '../../state/get-impact-location'; const getCombineWithFromResult = (result: DropResult): ?DraggableId => { return result.combine ? result.combine.draggableId : null; }; const getCombineWithFromImpact = (impact: DragImpact): ?DraggableId => { - return impact.merge ? impact.merge.combine.draggableId : null; + return impact.at && impact.at.type === 'COMBINE' + ? impact.at.combine.draggableId + : null; }; -// Returning a function to ensure each -// Draggable gets its own selector -export const makeMapStateToProps = (): Selector => { - const getDraggingSnapshot = memoizeOne( +type TrySelect = (state: State, ownProps: OwnProps) => ?MapProps; + +function getDraggableSelector(): TrySelect { + const memoizedOffset = memoizeOne((x: number, y: number): Position => ({ + x, + y, + })); + + const getMemoizedSnapshot = memoizeOne( ( mode: MovementMode, draggingOver: ?DroppableId, @@ -74,34 +69,7 @@ export const makeMapStateToProps = (): Selector => { }), ); - const getSecondarySnapshot = memoizeOne( - (combineTargetFor: ?DraggableId): StateSnapshot => ({ - isDragging: false, - isDropAnimating: false, - dropAnimation: null, - mode: null, - draggingOver: null, - combineTargetFor, - combineWith: null, - }), - ); - - const defaultMapProps: MapProps = { - mapped: { - type: 'SECONDARY', - offset: origin, - combineTargetFor: null, - shouldAnimateDisplacement: true, - snapshot: getSecondarySnapshot(null), - }, - }; - - const memoizedOffset = memoizeOne((x: number, y: number): Position => ({ - x, - y, - })); - - const getDraggingProps = memoizeOne(( + const getMemoizedProps = memoizeOne(( offset: Position, mode: MovementMode, dimension: DraggableDimension, @@ -120,65 +88,11 @@ export const makeMapStateToProps = (): Selector => { offset, dimension, forceShouldAnimate, - snapshot: getDraggingSnapshot(mode, draggingOver, combineWith, null), + snapshot: getMemoizedSnapshot(mode, draggingOver, combineWith, null), }, })); - const getSecondaryProps = memoizeOne( - ( - offset: Position, - combineTargetFor: ?DraggableId = null, - shouldAnimateDisplacement: boolean, - ): MapProps => ({ - mapped: { - type: 'SECONDARY', - offset, - combineTargetFor, - shouldAnimateDisplacement, - snapshot: getSecondarySnapshot(combineTargetFor), - }, - }), - ); - - const getSecondaryMovement = ( - ownId: DraggableId, - draggingId: DraggableId, - impact: DragImpact, - ): ?MapProps => { - // Doing this cuts 50% of the time to move - // Otherwise need to loop over every item in every selector (yuck!) - const map: DisplacementMap = impact.movement.map; - const displacement: ?Displacement = map[ownId]; - const movement: DragMovement = impact.movement; - const merge: ?CombineImpact = impact.merge; - const isCombinedWith: boolean = Boolean( - merge && merge.combine.draggableId === ownId, - ); - const displacedBy: Position = movement.displacedBy.point; - const offset: Position = memoizedOffset(displacedBy.x, displacedBy.y); - - if (isCombinedWith) { - return getSecondaryProps( - displacement ? offset : origin, - draggingId, - displacement ? displacement.shouldAnimate : true, - ); - } - - // does not need to move - if (!displacement) { - return null; - } - - // do not need to do anything - if (!displacement.isVisible) { - return null; - } - - return getSecondaryProps(offset, null, displacement.shouldAnimate); - }; - - const draggingSelector = (state: State, ownProps: OwnProps): ?MapProps => { + const selector: TrySelect = (state: State, ownProps: OwnProps): ?MapProps => { // Dragging if (state.isDragging) { // not the dragging item @@ -195,7 +109,7 @@ export const makeMapStateToProps = (): Selector => { const combineWith: ?DraggableId = getCombineWithFromImpact(state.impact); const forceShouldAnimate: ?boolean = state.forceShouldAnimate; - return getDraggingProps( + return getMemoizedProps( memoizedOffset(offset.x, offset.y), mode, dimension, @@ -241,7 +155,7 @@ export const makeMapStateToProps = (): Selector => { combineWith, mode, forceShouldAnimate: null, - snapshot: getDraggingSnapshot( + snapshot: getMemoizedSnapshot( mode, draggingOver, combineWith, @@ -254,7 +168,94 @@ export const makeMapStateToProps = (): Selector => { return null; }; - const secondarySelector = (state: State, ownProps: OwnProps): ?MapProps => { + return selector; +} + +function getSecondarySnapshot(combineTargetFor: ?DraggableId): StateSnapshot { + return { + isDragging: false, + isDropAnimating: false, + dropAnimation: null, + mode: null, + draggingOver: null, + combineTargetFor, + combineWith: null, + }; +} + +function getSecondarySelector(): TrySelect { + const memoizedOffset = memoizeOne((x: number, y: number): Position => ({ + x, + y, + })); + + const getMemoizedSnapshot = memoizeOne(getSecondarySnapshot); + + const getMemoizedProps = memoizeOne( + ( + offset: Position, + combineTargetFor: ?DraggableId = null, + shouldAnimateDisplacement: boolean, + ): MapProps => ({ + mapped: { + type: 'SECONDARY', + offset, + combineTargetFor, + shouldAnimateDisplacement, + snapshot: getMemoizedSnapshot(combineTargetFor), + }, + }), + ); + + // Is we are the combine target for something then we need to publish that + // otherwise we will return null to get the default props + const getFallback = (combineTargetFor: ?DraggableId): ?MapProps => { + return combineTargetFor + ? getMemoizedProps(origin, combineTargetFor, true) + : null; + }; + + const getProps = ( + ownId: DraggableId, + draggingId: DraggableId, + impact: DragImpact, + afterCritical: LiftEffect, + ): ?MapProps => { + const displacement: ?Displacement = impact.displaced.visible[ownId]; + const isAfterCriticalInVirtualList: boolean = Boolean( + afterCritical.inVirtualList && afterCritical.effected[ownId], + ); + + const combineTargetFor: ?DraggableId = tryGetCombine(impact) + ? draggingId + : null; + + if (!displacement) { + if (!isAfterCriticalInVirtualList) { + return getFallback(combineTargetFor); + } + + // when not over a list we close the gap + + const change: Position = negate(afterCritical.displacedBy.point); + const offset: Position = memoizedOffset(change.x, change.y); + return getMemoizedProps(offset, combineTargetFor, true); + } + + if (isAfterCriticalInVirtualList) { + return getFallback(combineTargetFor); + } + const displaceBy: Position = impact.displacedBy.point; + const offset: Position = memoizedOffset(displaceBy.x, displaceBy.y); + + return getMemoizedProps( + offset, + combineTargetFor, + displacement.shouldAnimate, + ); + }; + + const selector: TrySelect = (state: State, ownProps: OwnProps): ?MapProps => { // Dragging if (state.isDragging) { // we do not care about the dragging item @@ -262,10 +263,11 @@ export const makeMapStateToProps = (): Selector => { return null; } - return getSecondaryMovement( + return getProps( ownProps.draggableId, state.critical.draggable.id, state.impact, + state.afterCritical, ); } @@ -276,10 +278,11 @@ export const makeMapStateToProps = (): Selector => { if (completed.result.draggableId === ownProps.draggableId) { return null; } - return getSecondaryMovement( + return getProps( ownProps.draggableId, completed.result.draggableId, completed.impact, + completed.afterCritical, ); } @@ -287,6 +290,25 @@ export const makeMapStateToProps = (): Selector => { return null; }; + return selector; +} + +const defaultMapProps: MapProps = { + mapped: { + type: 'SECONDARY', + offset: origin, + combineTargetFor: null, + shouldAnimateDisplacement: true, + snapshot: getSecondarySnapshot(null), + }, +}; + +// Returning a function to ensure each +// Draggable gets its own selector +export const makeMapStateToProps = (): Selector => { + const draggingSelector: TrySelect = getDraggableSelector(); + const secondarySelector: TrySelect = getSecondarySelector(); + const selector = (state: State, ownProps: OwnProps): MapProps => draggingSelector(state, ownProps) || secondarySelector(state, ownProps) || @@ -296,39 +318,13 @@ export const makeMapStateToProps = (): Selector => { }; const mapDispatchToProps: DispatchProps = { - lift: liftAction, - move: moveAction, - moveUp: moveUpAction, - moveDown: moveDownAction, - moveLeft: moveLeftAction, - moveRight: moveRightAction, - moveByWindowScroll: moveByWindowScrollAction, - drop: dropAction, dropAnimationFinished: dropAnimationFinishedAction, }; -const defaultProps = ({ - isDragDisabled: false, - // Cannot drag interactive elements by default - disableInteractiveElementBlocking: false, - // Not respecting browser force touch interaction - // by default for a more consistent experience - shouldRespectForcePress: false, -}: DefaultProps); - -// Abstract class allows to specify props and defaults to component. -// All other ways give any or do not let add default props. -// eslint-disable-next-line -/*:: -class DraggableType extends Component { - static defaultProps = defaultProps; -} -*/ - // Leaning heavily on the default shallow equality checking // that `connect` provides. // It avoids needing to do it own within `Draggable` -const ConnectedDraggable: typeof DraggableType = (connect( +const ConnectedDraggable = connect( // returning a function so each component can do its own memoization makeMapStateToProps, mapDispatchToProps, @@ -345,8 +341,6 @@ const ConnectedDraggable: typeof DraggableType = (connect( // Switching to a strictEqual as we return a memoized object on changes areStatePropsEqual: isStrictEqual, }, -): any)(Draggable); - -ConnectedDraggable.defaultProps = defaultProps; +)(Draggable); export default ConnectedDraggable; diff --git a/src/view/draggable/draggable-api.jsx b/src/view/draggable/draggable-api.jsx new file mode 100644 index 0000000000..255ea778b3 --- /dev/null +++ b/src/view/draggable/draggable-api.jsx @@ -0,0 +1,46 @@ +// @flow +import React from 'react'; +import type { DraggableId } from '../../types'; +import type { PublicOwnProps, PrivateOwnProps } from './draggable-types'; +import ConnectedDraggable from './connected-draggable'; +import useRequiredContext from '../use-required-context'; +import DroppableContext, { + type DroppableContextValue, +} from '../context/droppable-context'; + +export function PrivateDraggable(props: PrivateOwnProps) { + const droppableContext: DroppableContextValue = useRequiredContext( + DroppableContext, + ); + + // The droppable can render a clone of the draggable item. + // In that case we unmount the existing dragging item + const isUsingCloneFor: ?DraggableId = droppableContext.isUsingCloneFor; + if (isUsingCloneFor === props.draggableId && !props.isClone) { + return null; + } + + return ; +} + +export function PublicDraggable(props: PublicOwnProps) { + // default values for props + const isEnabled: boolean = + typeof props.isDragDisabled === 'boolean' ? !props.isDragDisabled : true; + const canDragInteractiveElements: boolean = Boolean( + props.disableInteractiveElementBlocking, + ); + const shouldRespectForcePress: boolean = Boolean( + props.shouldRespectForcePress, + ); + + return ( + + ); +} diff --git a/src/view/draggable/draggable-types.js b/src/view/draggable/draggable-types.js index 9824b40f78..00372ab151 100644 --- a/src/view/draggable/draggable-types.js +++ b/src/view/draggable/draggable-types.js @@ -7,19 +7,10 @@ import type { DraggableDimension, State, MovementMode, + ContextId, + ElementId, } from '../../types'; -import { - lift, - move, - moveByWindowScroll, - moveUp, - moveDown, - moveRight, - moveLeft, - drop, - dropAnimationFinished, -} from '../../state/action-creators'; -import type { DragHandleProps } from '../use-drag-handle/drag-handle-types'; +import { dropAnimationFinished } from '../../state/action-creators'; export type DraggingStyle = {| position: 'fixed', @@ -62,11 +53,30 @@ export type DraggableProps = {| // inline style style: ?DraggableStyle, // used for shared global styles - 'data-react-beautiful-dnd-draggable': string, + 'data-rbd-draggable-context-id': string, + 'data-rbd-draggable-id': string, // used to know when a transition ends onTransitionEnd: ?(event: TransitionEvent) => void, |}; +export type DragHandleProps = {| + // what draggable the handle belongs to + 'data-rbd-drag-handle-draggable-id': DraggableId, + + // What DragDropContext the drag handle is in + 'data-rbd-drag-handle-context-id': ContextId, + + // id of drag handle aria description for screen readers + 'aria-labelledby': ElementId, + + // Allow tabbing to this element + tabIndex: number, + + // Stop html5 drag and drop + draggable: boolean, + onDragStart: (event: DragEvent) => void, +|}; + export type Provided = {| draggableProps: DraggableProps, // will be null if the draggable is disabled @@ -95,14 +105,6 @@ export type StateSnapshot = {| |}; export type DispatchProps = {| - lift: typeof lift, - move: typeof move, - moveByWindowScroll: typeof moveByWindowScroll, - moveUp: typeof moveUp, - moveDown: typeof moveDown, - moveRight: typeof moveRight, - moveLeft: typeof moveLeft, - drop: typeof drop, dropAnimationFinished: typeof dropAnimationFinished, |}; @@ -138,17 +140,29 @@ export type MapProps = {| export type ChildrenFn = (Provided, StateSnapshot) => Node | null; -export type DefaultProps = {| - isDragDisabled: boolean, - disableInteractiveElementBlocking: boolean, +export type PublicOwnProps = {| + draggableId: DraggableId, + index: number, + children: ChildrenFn, + + // optional own props + isDragDisabled?: boolean, + disableInteractiveElementBlocking?: boolean, + shouldRespectForcePress?: boolean, +|}; + +export type PrivateOwnProps = {| + ...PublicOwnProps, + isClone: boolean, + + // no longer optional + isEnabled: boolean, + canDragInteractiveElements: boolean, shouldRespectForcePress: boolean, |}; export type OwnProps = {| - ...DefaultProps, - draggableId: DraggableId, - index: number, - children: ChildrenFn, + ...PrivateOwnProps, |}; export type Props = {| diff --git a/src/view/draggable/draggable.jsx b/src/view/draggable/draggable.jsx index bbdf7e2157..7357452626 100644 --- a/src/view/draggable/draggable.jsx +++ b/src/view/draggable/draggable.jsx @@ -1,27 +1,23 @@ // @flow import { useRef } from 'react'; -import { type Position } from 'css-box-model'; -import invariant from 'tiny-invariant'; import { useMemo, useCallback } from 'use-memo-one'; import getStyle from './get-style'; -import useDragHandle from '../use-drag-handle/use-drag-handle'; +import useDraggablePublisher, { + type Args as PublisherArgs, +} from '../use-draggable-publisher/use-draggable-publisher'; +import AppContext from '../context/app-context'; import type { - Args as DragHandleArgs, - Callbacks as DragHandleCallbacks, + Props, + Provided, + DraggableStyle, DragHandleProps, -} from '../use-drag-handle/drag-handle-types'; -import type { MovementMode } from '../../types'; -import useDraggableDimensionPublisher, { - type Args as DimensionPublisherArgs, -} from '../use-draggable-dimension-publisher/use-draggable-dimension-publisher'; -import * as timings from '../../debug/timings'; -import type { Props, Provided, DraggableStyle } from './draggable-types'; -import getWindowScroll from '../window/get-window-scroll'; -// import throwIfRefIsInvalid from '../throw-if-invalid-inner-ref'; -// import checkOwnProps from './check-own-props'; -import AppContext, { type AppContextValue } from '../context/app-context'; +} from './draggable-types'; +import { useValidation, useClonePropValidation } from './use-validation'; import useRequiredContext from '../use-required-context'; -import useValidation from './use-validation'; + +function preventHtml5Dnd(event: DragEvent) { + event.preventDefault(); +} export default function Draggable(props: Props) { // reference to DOM node @@ -32,129 +28,76 @@ export default function Draggable(props: Props) { const getRef = useCallback((): ?HTMLElement => ref.current, []); // context - const appContext: AppContextValue = useRequiredContext(AppContext); - - // Validating props and innerRef - useValidation(props, getRef); + const { contextId, liftInstructionId } = useRequiredContext(AppContext); // props const { // ownProps children, draggableId, - isDragDisabled, + isEnabled, shouldRespectForcePress, - disableInteractiveElementBlocking: canDragInteractiveElements, + canDragInteractiveElements, index, + isClone, // mapProps mapped, // dispatchProps - moveUp: moveUpAction, - move: moveAction, - drop: dropAction, - moveDown: moveDownAction, - moveRight: moveRightAction, - moveLeft: moveLeftAction, - moveByWindowScroll: moveByWindowScrollAction, - lift: liftAction, dropAnimationFinished: dropAnimationFinishedAction, } = props; - // The dimension publisher: talks to the marshal - const forPublisher: DimensionPublisherArgs = useMemo( - () => ({ - draggableId, - index, - getDraggableRef: getRef, - }), - [draggableId, getRef, index], - ); - useDraggableDimensionPublisher(forPublisher); - - // The Drag handle - - const onLift = useCallback( - (options: { clientSelection: Position, movementMode: MovementMode }) => { - timings.start('LIFT'); - const el: ?HTMLElement = ref.current; - invariant(el); - invariant(!isDragDisabled, 'Cannot lift a Draggable when it is disabled'); - const { clientSelection, movementMode } = options; - - liftAction({ - id: draggableId, - clientSelection, - movementMode, - }); - timings.finish('LIFT'); - }, - [draggableId, isDragDisabled, liftAction], - ); - - const getShouldRespectForcePress = useCallback( - () => shouldRespectForcePress, - [shouldRespectForcePress], - ); - - const callbacks: DragHandleCallbacks = useMemo( - () => ({ - onLift, - onMove: (clientSelection: Position) => - moveAction({ client: clientSelection }), - onDrop: () => dropAction({ reason: 'DROP' }), - onCancel: () => dropAction({ reason: 'CANCEL' }), - onMoveUp: moveUpAction, - onMoveDown: moveDownAction, - onMoveRight: moveRightAction, - onMoveLeft: moveLeftAction, - onWindowScroll: () => - moveByWindowScrollAction({ - newScroll: getWindowScroll(), - }), - }), - [ - dropAction, - moveAction, - moveByWindowScrollAction, - moveDownAction, - moveLeftAction, - moveRightAction, - moveUpAction, - onLift, - ], - ); + // Validating props and innerRef + useValidation(props, getRef); - const isDragging: boolean = mapped.type === 'DRAGGING'; - const isDropAnimating: boolean = - mapped.type === 'DRAGGING' && Boolean(mapped.dropping); - - const dragHandleArgs: DragHandleArgs = useMemo( - () => ({ - draggableId, - isDragging, - isDropAnimating, - isEnabled: !isDragDisabled, - callbacks, - getDraggableRef: getRef, - canDragInteractiveElements, - getShouldRespectForcePress, - }), - [ - callbacks, - canDragInteractiveElements, - draggableId, - getRef, - getShouldRespectForcePress, - isDragDisabled, - isDragging, - isDropAnimating, - ], + // Clones do not speak to the dimension marshal + // We are violating the rules of hooks here: conditional hooks. + // In this specific use case it is okay as an item will always either be a + // clone or not for it's whole lifecycle + /* eslint-disable react-hooks/rules-of-hooks */ + + // Being super sure that isClone is not changing during a draggable lifecycle + useClonePropValidation(isClone); + if (!isClone) { + const forPublisher: PublisherArgs = useMemo( + () => ({ + draggableId, + index, + getDraggableRef: getRef, + canDragInteractiveElements, + shouldRespectForcePress, + isEnabled, + }), + [ + canDragInteractiveElements, + draggableId, + getRef, + index, + isEnabled, + shouldRespectForcePress, + ], + ); + useDraggablePublisher(forPublisher); + } + /* eslint-enable react-hooks/rules-of-hooks */ + + const dragHandleProps: ?DragHandleProps = useMemo( + () => + isEnabled + ? { + tabIndex: 0, + 'data-rbd-drag-handle-draggable-id': draggableId, + 'data-rbd-drag-handle-context-id': contextId, + 'aria-labelledby': liftInstructionId, + // Opting out of html5 drag and drops + draggable: false, + onDragStart: preventHtml5Dnd, + } + : null, + [contextId, draggableId, isEnabled, liftInstructionId], ); - const dragHandleProps: ?DragHandleProps = useDragHandle(dragHandleArgs); - const onMoveEnd = useCallback( (event: TransitionEvent) => { if (mapped.type !== 'DRAGGING') { @@ -184,7 +127,8 @@ export default function Draggable(props: Props) { const result: Provided = { innerRef: setRef, draggableProps: { - 'data-react-beautiful-dnd-draggable': appContext.style, + 'data-rbd-draggable-context-id': contextId, + 'data-rbd-draggable-id': draggableId, style, onTransitionEnd, }, @@ -192,7 +136,7 @@ export default function Draggable(props: Props) { }; return result; - }, [appContext.style, dragHandleProps, mapped, onMoveEnd, setRef]); + }, [contextId, dragHandleProps, draggableId, mapped, onMoveEnd, setRef]); return children(provided, mapped.snapshot); } diff --git a/src/view/draggable/index.js b/src/view/draggable/index.js index 6e1e102393..0375d796dd 100644 --- a/src/view/draggable/index.js +++ b/src/view/draggable/index.js @@ -1,2 +1,2 @@ // @flow -export { default } from './connected-draggable'; +export { PublicDraggable as default } from './draggable-api'; diff --git a/src/view/draggable/use-validation.js b/src/view/draggable/use-validation.js index 6680ddd4fb..385fd957d0 100644 --- a/src/view/draggable/use-validation.js +++ b/src/view/draggable/use-validation.js @@ -1,5 +1,5 @@ // @flow -import { useEffect } from 'react'; +import { useRef, useEffect } from 'react'; import invariant from 'tiny-invariant'; import type { Props } from './draggable-types'; import checkIsValidInnerRef from '../check-is-valid-inner-ref'; @@ -12,31 +12,29 @@ function checkOwnProps(props: Props) { 'Draggable requires an integer index prop', ); invariant(props.draggableId, 'Draggable requires a draggableId'); - invariant( - typeof props.isDragDisabled === 'boolean', - 'isDragDisabled must be a boolean', - ); -} - -function checkForOutdatedProps(props: Props) { - if (Object.prototype.hasOwnProperty.call(props, 'shouldRespectForceTouch')) { - warning( - 'shouldRespectForceTouch has been renamed to shouldRespectForcePress', - ); - } } - -export default function useValidation( - props: Props, - getRef: () => ?HTMLElement, -) { +export function useValidation(props: Props, getRef: () => ?HTMLElement) { // running after every update in development useEffect(() => { // wrapping entire block for better minification if (process.env.NODE_ENV !== 'production') { checkOwnProps(props); - checkForOutdatedProps(props); - checkIsValidInnerRef(getRef()); + + // TODO: run check when virtual? + if (props.mapped.type !== 'DRAGGING') { + checkIsValidInnerRef(getRef()); + } } }); } + +// we expect isClone not to change for entire component's life +export function useClonePropValidation(isClone: boolean) { + const initialRef = useRef(isClone); + + useEffect(() => { + if (isClone !== initialRef.current) { + warning('Draggable isClone prop value changed during component life'); + } + }, [isClone]); +} diff --git a/src/view/droppable/connected-droppable.js b/src/view/droppable/connected-droppable.js index 26f80f557c..0127211f75 100644 --- a/src/view/droppable/connected-droppable.js +++ b/src/view/droppable/connected-droppable.js @@ -1,4 +1,5 @@ // @flow +import invariant from 'tiny-invariant'; // eslint-disable-next-line no-unused-vars import { Component } from 'react'; import { connect } from 'react-redux'; @@ -20,6 +21,8 @@ import type { Selector, DispatchProps, StateSnapshot, + UseClone, + RenderClone, } from './droppable-types'; import Droppable from './droppable'; import isStrictEqual from '../is-strict-equal'; @@ -27,6 +30,7 @@ import whatIsDraggedOver from '../../state/droppable/what-is-dragged-over'; import { updateViewportMaxScroll as updateViewportMaxScrollAction } from '../../state/action-creators'; import StoreContext from '../context/store-context'; import whatIsDraggedOverFromResult from '../../state/droppable/what-is-dragged-over-from-result'; +import getHomeLocation from '../../state/get-home-location'; const isMatchingType = (type: TypeId, critical: Critical): boolean => type === critical.droppable.type; @@ -47,6 +51,7 @@ export const makeMapStateToProps = (): Selector => { draggingOverWith: null, draggingFromThisWith: null, }, + useClone: null, }; const idleWithoutAnimation = { @@ -60,14 +65,24 @@ export const makeMapStateToProps = (): Selector => { isDraggingOver: boolean, dragging: DraggableDimension, snapshot: StateSnapshot, + whenDraggingClone: ?RenderClone, ): MapProps => { const isHome: boolean = dragging.descriptor.droppableId === id; if (isHome) { + const useClone: ?UseClone = whenDraggingClone + ? { + render: whenDraggingClone, + draggableId: dragging.descriptor.id, + source: getHomeLocation(dragging.descriptor), + } + : null; + return { placeholder: dragging.placeholder, shouldAnimatePlaceholder: false, snapshot, + useClone, }; } @@ -81,6 +96,7 @@ export const makeMapStateToProps = (): Selector => { // Animating placeholder in foreign list shouldAnimatePlaceholder: true, snapshot, + useClone: null, }; }, ); @@ -111,6 +127,7 @@ export const makeMapStateToProps = (): Selector => { const id: DroppableId = ownProps.droppableId; const type: TypeId = ownProps.type; + const whenDraggingClone: ?RenderClone = ownProps.whenDraggingClone; if (state.isDragging) { const critical: Critical = state.critical; @@ -126,7 +143,13 @@ export const makeMapStateToProps = (): Selector => { // Snapshot based on current impact const snapshot: StateSnapshot = getSnapshot(id, isDraggingOver, dragging); - return getMapProps(id, isDraggingOver, dragging, snapshot); + return getMapProps( + id, + isDraggingOver, + dragging, + snapshot, + whenDraggingClone, + ); } if (state.phase === 'DROP_ANIMATING') { @@ -154,6 +177,7 @@ export const makeMapStateToProps = (): Selector => { whatIsDraggedOver(completed.impact) === id, dragging, snapshot, + whenDraggingClone, ); } @@ -171,7 +195,9 @@ export const makeMapStateToProps = (): Selector => { // Looking at impact as this controls the placeholder const wasOver: boolean = whatIsDraggedOver(completed.impact) === id; - const wasCombining: boolean = Boolean(completed.impact.merge); + const wasCombining: boolean = Boolean( + completed.impact.at && completed.impact.at.type === 'COMBINE', + ); // need to cut any animations: sadly a memoization fail // we need to do this for all lists as there might be @@ -200,12 +226,20 @@ const mapDispatchToProps: DispatchProps = { updateViewportMaxScroll: updateViewportMaxScrollAction, }; +function getBody(): HTMLElement { + invariant(document.body, 'document.body is not ready'); + return document.body; +} + const defaultProps = ({ + mode: 'STANDARD', type: 'DEFAULT', direction: 'vertical', isDropDisabled: false, isCombineEnabled: false, ignoreContainerClipping: false, + whenDraggingClone: null, + getContainerForClone: getBody, }: DefaultProps); // Abstract class allows to specify props and defaults to component. @@ -220,7 +254,7 @@ class DroppableType extends Component { // Leaning heavily on the default shallow equality checking // that `connect` provides. // It avoids needing to do it own within `Droppable` -const ConnectedDroppable: typeof DroppableType = (connect( +const ConnectedDroppable: typeof DroppableType = connect( // returning a function so each component can do its own memoization makeMapStateToProps, // no dispatch props for droppable @@ -237,7 +271,7 @@ const ConnectedDroppable: typeof DroppableType = (connect( // Switching to a strictEqual as we return a memoized object on changes areStatePropsEqual: isStrictEqual, }, -): any)(Droppable); +)(Droppable); ConnectedDroppable.defaultProps = defaultProps; diff --git a/src/view/droppable/droppable-types.js b/src/view/droppable/droppable-types.js index b9929bc94b..8b6bad8aba 100644 --- a/src/view/droppable/droppable-types.js +++ b/src/view/droppable/droppable-types.js @@ -7,12 +7,21 @@ import type { Direction, Placeholder, State, + ContextId, + DraggableLocation, + DroppableMode, } from '../../types'; +import type { + StateSnapshot as DraggableStateSnapshot, + Provided as DraggableProvided, +} from '../draggable/draggable-types'; import { updateViewportMaxScroll } from '../../state/action-creators'; export type DroppableProps = {| // used for shared global styles - 'data-react-beautiful-dnd-droppable': string, + 'data-rbd-droppable-context-id': ContextId, + // Used to lookup. Currently not used for drag and drop lifecycle + 'data-rbd-droppable-id': DroppableId, |}; export type Provided = {| @@ -21,6 +30,18 @@ export type Provided = {| droppableProps: DroppableProps, |}; +export type RenderClone = ( + provided: DraggableProvided, + snapshot: DraggableStateSnapshot, + source: DraggableLocation, +) => Node; + +export type UseClone = {| + draggableId: DraggableId, + source: DraggableLocation, + render: RenderClone, +|}; + export type StateSnapshot = {| // Is the Droppable being dragged over? isDraggingOver: boolean, @@ -39,14 +60,18 @@ export type MapProps = {| shouldAnimatePlaceholder: boolean, // snapshot based on redux state to be provided to consumers snapshot: StateSnapshot, + useClone: ?UseClone, |}; export type DefaultProps = {| + mode: DroppableMode, type: TypeId, isDropDisabled: boolean, isCombineEnabled: boolean, direction: Direction, + whenDraggingClone: ?RenderClone, ignoreContainerClipping: boolean, + getContainerForClone: () => HTMLElement, |}; export type DispatchProps = {| @@ -57,6 +82,7 @@ export type OwnProps = {| ...DefaultProps, children: (Provided, StateSnapshot) => Node, droppableId: DroppableId, + whenDraggingClone: ?RenderClone, |}; export type Props = {| diff --git a/src/view/droppable/droppable.jsx b/src/view/droppable/droppable.jsx index c896f6968e..138821101c 100644 --- a/src/view/droppable/droppable.jsx +++ b/src/view/droppable/droppable.jsx @@ -1,9 +1,11 @@ // @flow import invariant from 'tiny-invariant'; +import ReactDOM from 'react-dom'; import { useMemo, useCallback } from 'use-memo-one'; import React, { useRef, useContext, type Node } from 'react'; -import type { Props, Provided } from './droppable-types'; -import useDroppableDimensionPublisher from '../use-droppable-dimension-publisher'; +import type { DraggableId } from '../../types'; +import type { Props, Provided, UseClone } from './droppable-types'; +import useDroppablePublisher from '../use-droppable-publisher'; import Placeholder from '../placeholder'; import AppContext, { type AppContextValue } from '../context/app-context'; import DroppableContext, { @@ -12,14 +14,19 @@ import DroppableContext, { // import useAnimateInOut from '../use-animate-in-out/use-animate-in-out'; import getMaxWindowScroll from '../window/get-max-window-scroll'; import useValidation from './use-validation'; +import type { + StateSnapshot as DraggableStateSnapshot, + Provided as DraggableProvided, +} from '../draggable/draggable-types'; import AnimateInOut, { type AnimateProvided, } from '../animate-in-out/animate-in-out'; +import { PrivateDraggable } from '../draggable/draggable-api'; export default function Droppable(props: Props) { const appContext: ?AppContextValue = useContext(AppContext); invariant(appContext, 'Could not find app context'); - const { style: styleContext, isMovementAllowed } = appContext; + const { contextId, isMovementAllowed } = appContext; const droppableRef = useRef(null); const placeholderRef = useRef(null); @@ -30,14 +37,19 @@ export default function Droppable(props: Props) { children, droppableId, type, + mode, direction, ignoreContainerClipping, isDropDisabled, isCombineEnabled, // map props snapshot, + useClone, // dispatch props updateViewportMaxScroll, + + // clone (ownProps) + getContainerForClone, } = props; const getDroppableRef = useCallback( @@ -62,9 +74,10 @@ export default function Droppable(props: Props) { } }, [isMovementAllowed, updateViewportMaxScroll]); - useDroppableDimensionPublisher({ + useDroppablePublisher({ droppableId, type, + mode, direction, isDropDisabled, isCombineEnabled, @@ -73,11 +86,6 @@ export default function Droppable(props: Props) { getPlaceholderRef, }); - // const instruction: ?AnimateProvided = useAnimateInOut({ - // on: props.placeholder, - // shouldAnimate: props.shouldAnimatePlaceholder, - // }); - const placeholder: Node = ( )} @@ -101,18 +109,22 @@ export default function Droppable(props: Props) { innerRef: setDroppableRef, placeholder, droppableProps: { - 'data-react-beautiful-dnd-droppable': styleContext, + 'data-rbd-droppable-id': droppableId, + 'data-rbd-droppable-context-id': contextId, }, }), - [placeholder, setDroppableRef, styleContext], + [contextId, droppableId, placeholder, setDroppableRef], ); + const isUsingCloneFor: ?DraggableId = useClone ? useClone.draggableId : null; + const droppableContext: ?DroppableContextValue = useMemo( () => ({ droppableId, type, + isUsingCloneFor, }), - [droppableId, type], + [droppableId, isUsingCloneFor, type], ); useValidation({ @@ -121,9 +133,36 @@ export default function Droppable(props: Props) { getPlaceholderRef: () => placeholderRef.current, }); + function getClone(): ?Node { + if (!useClone) { + return null; + } + const { draggableId, source, render } = useClone; + + const node: Node = ( + + {( + draggableProvided: DraggableProvided, + draggableSnapshot: DraggableStateSnapshot, + ) => render(draggableProvided, draggableSnapshot, source)} + + ); + + return ReactDOM.createPortal(node, getContainerForClone()); + } + return ( {children(provided, snapshot)} + {getClone()} ); } diff --git a/src/view/droppable/use-validation.js b/src/view/droppable/use-validation.js index 63299971ea..ce5d6fafa2 100644 --- a/src/view/droppable/use-validation.js +++ b/src/view/droppable/use-validation.js @@ -5,58 +5,96 @@ import type { Props } from './droppable-types'; import { warning } from '../../dev-warning'; import checkIsValidInnerRef from '../check-is-valid-inner-ref'; -function checkOwnProps(props: Props) { - invariant(props.droppableId, 'A Droppable requires a droppableId prop'); - invariant( - typeof props.isDropDisabled === 'boolean', - 'isDropDisabled must be a boolean', - ); - invariant( - typeof props.isCombineEnabled === 'boolean', - 'isCombineEnabled must be a boolean', - ); - invariant( - typeof props.ignoreContainerClipping === 'boolean', - 'ignoreContainerClipping must be a boolean', - ); +type Args = {| + props: Props, + getDroppableRef: () => ?HTMLElement, + getPlaceholderRef: () => ?HTMLElement, +|}; + +type CheckFn = (args: Args) => void; + +function isBoolean(value: mixed): boolean { + return typeof value === 'boolean'; } -function checkPlaceholderRef(props: Props, placeholderEl: ?HTMLElement) { - if (!props.placeholder) { - return; - } +function run(args: Args, checks: CheckFn[]) { + checks.forEach((check: CheckFn) => check(args)); +} - if (placeholderEl) { - return; - } +const shared: CheckFn[] = [ + function required({ props }: Args) { + invariant(props.droppableId, 'A Droppable requires a droppableId prop'); + }, + function boolean({ props }: Args) { + invariant( + isBoolean(props.isDropDisabled), + 'isDropDisabled must be a boolean', + ); + invariant( + isBoolean(props.isCombineEnabled), + 'isCombineEnabled must be a boolean', + ); + invariant( + isBoolean(props.ignoreContainerClipping), + 'ignoreContainerClipping must be a boolean', + ); + }, + function ref({ getDroppableRef }: Args) { + checkIsValidInnerRef(getDroppableRef()); + }, +]; - warning(` - Droppable setup issue [droppableId: "${props.droppableId}"]: - DroppableProvided > placeholder could not be found. +const standard: CheckFn[] = [ + function placeholder({ props, getPlaceholderRef }: Args) { + if (!props.placeholder) { + return; + } - Please be sure to add the {provided.placeholder} React Node as a child of your Droppable. - More information: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/droppable.md - `); -} + const ref: ?HTMLElement = getPlaceholderRef(); -type Args = {| - props: Props, - getDroppableRef: () => ?HTMLElement, - getPlaceholderRef: () => ?HTMLElement, -|}; + if (ref) { + return; + } -export default function useValidation({ - props, - getDroppableRef, - getPlaceholderRef, -}: Args) { + warning(` + Droppable setup issue [droppableId: "${props.droppableId}"]: + DroppableProvided > placeholder could not be found. + + Please be sure to add the {provided.placeholder} React Node as a child of your Droppable. + More information: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/droppable.md + `); + }, +]; + +const virtual: CheckFn[] = [ + function hasClone({ props }: Args) { + invariant( + props.whenDraggingClone, + 'Must provide a clone render function (whenDraggingClone) for virtual lists', + ); + }, + function hasNoPlaceholder({ getPlaceholderRef }: Args) { + invariant( + !getPlaceholderRef(), + 'Expected virtual list to not have a placeholder', + ); + }, +]; + +export default function useValidation(args: Args) { // Running on every update useEffect(() => { // wrapping entire block for better minification if (process.env.NODE_ENV !== 'production') { - checkOwnProps(props); - checkIsValidInnerRef(getDroppableRef()); - checkPlaceholderRef(props, getPlaceholderRef()); + run(args, shared); + + if (args.props.mode === 'STANDARD') { + run(args, standard); + } + + if (args.props.mode === 'VIRTUAL') { + run(args, virtual); + } } }); } diff --git a/src/view/event-bindings/bind-events.js b/src/view/event-bindings/bind-events.js new file mode 100644 index 0000000000..11094e5503 --- /dev/null +++ b/src/view/event-bindings/bind-events.js @@ -0,0 +1,39 @@ +// @flow +import type { EventBinding, EventOptions } from './event-types'; + +type UnbindFn = () => void; + +function getOptions( + shared?: EventOptions, + fromBinding: ?EventOptions, +): EventOptions { + return { + ...shared, + ...fromBinding, + }; +} + +export default function bindEvents( + el: HTMLElement, + bindings: EventBinding[], + sharedOptions?: EventOptions, +): Function { + const unbindings: UnbindFn[] = bindings.map( + (binding: EventBinding): UnbindFn => { + const options: Object = getOptions(sharedOptions, binding.options); + + el.addEventListener(binding.eventName, binding.fn, options); + + return function unbind() { + el.removeEventListener(binding.eventName, binding.fn, options); + }; + }, + ); + + // Return a function to unbind events + return function unbindAll() { + unbindings.forEach((unbind: UnbindFn) => { + unbind(); + }); + }; +} diff --git a/src/view/use-drag-handle/util/event-types.js b/src/view/event-bindings/event-types.js similarity index 69% rename from src/view/use-drag-handle/util/event-types.js rename to src/view/event-bindings/event-types.js index 42e68d31c7..55bb533a94 100644 --- a/src/view/use-drag-handle/util/event-types.js +++ b/src/view/event-bindings/event-types.js @@ -3,6 +3,8 @@ export type EventOptions = {| passive?: boolean, capture?: boolean, + // sometimes an event might only event want to be bound once + once?: boolean, |}; export type EventBinding = {| diff --git a/src/view/placeholder/placeholder.jsx b/src/view/placeholder/placeholder.jsx index 8f3d12c78e..7fb2abc6ec 100644 --- a/src/view/placeholder/placeholder.jsx +++ b/src/view/placeholder/placeholder.jsx @@ -5,6 +5,7 @@ import type { Spacing } from 'css-box-model'; import type { Placeholder as PlaceholderType, InOutAnimationMode, + ContextId, } from '../../types'; import { transitions } from '../../animation'; import { noSpacing } from '../../state/spacing'; @@ -31,7 +32,7 @@ export type Props = {| onClose: () => void, innerRef?: () => ?HTMLElement, onTransitionEnd: () => void, - styleContext: string, + contextId: ContextId, |}; type Size = {| @@ -124,7 +125,7 @@ function Placeholder(props: Props): Node { animateOpenTimerRef.current = null; }, []); - const { animate, onTransitionEnd, onClose, styleContext } = props; + const { animate, onTransitionEnd, onClose, contextId } = props; const [isAnimatingOpenOnMount, setIsAnimatingOpenOnMount] = useState( props.animate === 'open', ); @@ -186,7 +187,7 @@ function Placeholder(props: Props): Node { return React.createElement(props.placeholder.tagName, { style, - 'data-react-beautiful-dnd-placeholder': styleContext, + 'data-rbd-placeholder-context-id': contextId, onTransitionEnd: onSizeChangeEnd, ref: props.innerRef, }); diff --git a/src/view/scroll-listener.js b/src/view/scroll-listener.js new file mode 100644 index 0000000000..c24290d9ab --- /dev/null +++ b/src/view/scroll-listener.js @@ -0,0 +1,72 @@ +// @flow +import invariant from 'tiny-invariant'; +import type { Position } from 'css-box-model'; +import rafSchd from 'raf-schd'; +import bindEvents from './event-bindings/bind-events'; +import type { EventBinding } from './event-bindings/event-types'; +import getWindowScroll from './window/get-window-scroll'; + +type OnWindowScroll = (newScroll: Position) => void; + +type Args = {| + onWindowScroll: OnWindowScroll, +|}; + +type Result = {| + start: () => void, + stop: () => void, + isActive: () => boolean, +|}; + +function noop() {} + +function getWindowScrollBinding(update: () => void): EventBinding { + return { + eventName: 'scroll', + // ## Passive: true + // Eventual consistency is fine because we use position: fixed on the item + // ## Capture: false + // Scroll events on elements do not bubble, but they go through the capture phase + // https://twitter.com/alexandereardon/status/985994224867819520 + // Using capture: false here as we want to avoid intercepting droppable scroll requests + options: { passive: true, capture: false }, + fn: (event: UIEvent) => { + // IE11 fix: + // Scrollable events still bubble up and are caught by this handler in ie11. + // We can ignore this event + if (event.currentTarget !== window) { + return; + } + + update(); + }, + }; +} + +export default function getScrollListener({ onWindowScroll }: Args): Result { + function updateScroll() { + // letting the update function read the latest scroll when called + onWindowScroll(getWindowScroll()); + } + + const scheduled = rafSchd(updateScroll); + const binding: EventBinding = getWindowScrollBinding(scheduled); + let unbind: () => void = noop; + + function isActive(): boolean { + return unbind !== noop; + } + + function start() { + invariant(!isActive(), 'Cannot start scroll listener when already active'); + unbind = bindEvents(window, [binding]); + } + function stop() { + invariant(isActive(), 'Cannot stop scroll listener when not active'); + scheduled.cancel(); + unbind(); + unbind = noop; + } + + return { start, stop, isActive }; +} diff --git a/src/view/use-announcer/use-announcer.js b/src/view/use-announcer/use-announcer.js index 79dfbddecd..3ad1222a5a 100644 --- a/src/view/use-announcer/use-announcer.js +++ b/src/view/use-announcer/use-announcer.js @@ -2,30 +2,16 @@ import { useRef, useEffect } from 'react'; import invariant from 'tiny-invariant'; import { useMemo, useCallback } from 'use-memo-one'; -import type { Announce } from '../../types'; +import type { Announce, ContextId } from '../../types'; import { warning } from '../../dev-warning'; import getBodyElement from '../get-body-element'; +import visuallyHidden from '../visually-hidden-style'; -// 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)', - // for if 'clip' is ever removed - 'clip-path': 'inset(100%)', -}; - -export const getId = (uniqueId: number): string => - `react-beautiful-dnd-announcement-${uniqueId}`; - -export default function useAnnouncer(uniqueId: number): Announce { - const id: string = useMemo(() => getId(uniqueId), [uniqueId]); +export const getId = (contextId: ContextId): string => + `rbd-announcement-${contextId}`; + +export default function useAnnouncer(contextId: ContextId): Announce { + const id: string = useMemo(() => getId(contextId), [contextId]); const ref = useRef(null); useEffect(() => { @@ -52,12 +38,16 @@ export default function useAnnouncer(uniqueId: number): Announce { getBodyElement().appendChild(el); return () => { - const toBeRemoved: ?HTMLElement = ref.current; - invariant(toBeRemoved, 'Cannot unmount announcement node'); - - // Remove from body - getBodyElement().removeChild(toBeRemoved); - ref.current = null; + // unmounting after a timeout to let any annoucements + // during a mount be published + setTimeout(function remove() { + const toBeRemoved: ?HTMLElement = ref.current; + invariant(toBeRemoved, 'Cannot unmount announcement node'); + + // Remove from body + getBodyElement().removeChild(toBeRemoved); + ref.current = null; + }); }; }, [id]); diff --git a/src/view/use-drag-handle/drag-handle-types.js b/src/view/use-drag-handle/drag-handle-types.js deleted file mode 100644 index 0d746aae3f..0000000000 --- a/src/view/use-drag-handle/drag-handle-types.js +++ /dev/null @@ -1,61 +0,0 @@ -// @flow -import { type Position } from 'css-box-model'; -import type { MovementMode, DraggableId } from '../../types'; - -export type Callbacks = {| - onLift: ({ - clientSelection: Position, - movementMode: MovementMode, - }) => mixed, - onMove: (point: Position) => mixed, - onWindowScroll: () => mixed, - onMoveUp: () => mixed, - onMoveDown: () => mixed, - onMoveRight: () => mixed, - onMoveLeft: () => mixed, - onDrop: () => mixed, - onCancel: () => mixed, -|}; - -export type DragHandleProps = {| - // If a consumer is using a portal then the item will lose focus - // when moving to the portal. This breaks keyboard dragging. - // To get around this we manually apply focus if needed when mounting - onFocus: () => void, - onBlur: () => void, - - // Used to initiate dragging - onMouseDown: (event: MouseEvent) => void, - onKeyDown: (event: KeyboardEvent) => void, - onTouchStart: (event: TouchEvent) => void, - - // Control styling from style marshal - 'data-react-beautiful-dnd-drag-handle': string, - - // Aria role (nicer screen reader text) - 'aria-roledescription': string, - - // Allow tabbing to this element - tabIndex: number, - - // Stop html5 drag and drop - draggable: boolean, - onDragStart: (event: DragEvent) => void, -|}; - -export type Args = {| - draggableId: DraggableId, - // callbacks provided by the draggable - callbacks: Callbacks, - isEnabled: boolean, - // whether the application thinks a drag is occurring - isDragging: boolean, - // whether the application thinks a drop is occurring - isDropAnimating: boolean, - // get the ref of the draggable - getDraggableRef: () => ?HTMLElement, - // whether interactive elements should be permitted to start a drag - canDragInteractiveElements: boolean, - // whether force press interactions should be respected - getShouldRespectForcePress: () => boolean, -|}; diff --git a/src/view/use-drag-handle/index.js b/src/view/use-drag-handle/index.js deleted file mode 100644 index 56db94fce8..0000000000 --- a/src/view/use-drag-handle/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { default } from './use-drag-handle'; diff --git a/src/view/use-drag-handle/sensor/use-keyboard-sensor.js b/src/view/use-drag-handle/sensor/use-keyboard-sensor.js deleted file mode 100644 index ab1c14893d..0000000000 --- a/src/view/use-drag-handle/sensor/use-keyboard-sensor.js +++ /dev/null @@ -1,263 +0,0 @@ -// @flow -import type { Position } from 'css-box-model'; -import { useRef } from 'react'; -import { useMemo, useCallback } from 'use-memo-one'; -import invariant from 'tiny-invariant'; -import type { EventBinding } from '../util/event-types'; -import { bindEvents, unbindEvents } from '../util/bind-events'; -import createScheduler from '../util/create-scheduler'; -import * as keyCodes from '../../key-codes'; -import supportedPageVisibilityEventName from '../util/supported-page-visibility-event-name'; -import preventStandardKeyEvents from '../util/prevent-standard-key-events'; -import type { Callbacks } from '../drag-handle-types'; -import getBorderBoxCenterPosition from '../../get-border-box-center-position'; - -export type Args = {| - callbacks: Callbacks, - getDraggableRef: () => ?HTMLElement, - getWindow: () => HTMLElement, - canStartCapturing: (event: Event) => boolean, - onCaptureStart: (abort: () => void) => void, - onCaptureEnd: () => void, -|}; -export type OnKeyDown = (event: KeyboardEvent) => void; - -type KeyMap = { - [key: number]: true, -}; - -const scrollJumpKeys: KeyMap = { - [keyCodes.pageDown]: true, - [keyCodes.pageUp]: true, - [keyCodes.home]: true, - [keyCodes.end]: true, -}; - -function noop() {} - -export default function useKeyboardSensor(args: Args): OnKeyDown { - const { - canStartCapturing, - getWindow, - callbacks, - onCaptureStart, - onCaptureEnd, - getDraggableRef, - } = args; - const isDraggingRef = useRef(false); - const unbindWindowEventsRef = useRef<() => void>(noop); - - const getIsDragging = useCallback(() => isDraggingRef.current, []); - - const schedule = useMemo(() => { - invariant( - !getIsDragging(), - 'Should not recreate scheduler while capturing', - ); - return createScheduler(callbacks); - }, [callbacks, getIsDragging]); - - const stop = useCallback(() => { - if (!getIsDragging()) { - return; - } - - schedule.cancel(); - unbindWindowEventsRef.current(); - isDraggingRef.current = false; - onCaptureEnd(); - }, [getIsDragging, onCaptureEnd, schedule]); - - const cancel = useCallback(() => { - const wasDragging: boolean = isDraggingRef.current; - stop(); - - if (wasDragging) { - callbacks.onCancel(); - } - }, [callbacks, stop]); - - const windowBindings: EventBinding[] = useMemo(() => { - invariant( - !getIsDragging(), - 'Should not recreate window bindings when dragging', - ); - return [ - // any mouse actions kills a drag - { - eventName: 'mousedown', - fn: cancel, - }, - { - eventName: 'mouseup', - fn: cancel, - }, - { - eventName: 'click', - fn: cancel, - }, - { - eventName: 'touchstart', - fn: cancel, - }, - // resizing the browser kills a drag - { - eventName: 'resize', - fn: cancel, - }, - // kill if the user is using the mouse wheel - // We are not supporting wheel / trackpad scrolling with keyboard dragging - { - eventName: 'wheel', - fn: cancel, - // chrome says it is a violation for this to not be passive - // it is fine for it to be passive as we just cancel as soon as we get - // any event - options: { passive: true }, - }, - // Need to respond instantly to a jump scroll request - // Not using the scheduler - { - eventName: 'scroll', - // Scroll events on elements do not bubble, but they go through the capture phase - // https://twitter.com/alexandereardon/status/985994224867819520 - // Using capture: false here as we want to avoid intercepting droppable scroll requests - options: { capture: false }, - fn: (event: UIEvent) => { - // IE11 fix: - // Scrollable events still bubble up and are caught by this handler in ie11. - // We can ignore this event - if (event.currentTarget !== getWindow()) { - return; - } - - callbacks.onWindowScroll(); - }, - }, - // Cancel on page visibility change - { - eventName: supportedPageVisibilityEventName, - fn: cancel, - }, - ]; - }, [callbacks, cancel, getIsDragging, getWindow]); - - const bindWindowEvents = useCallback(() => { - const win: HTMLElement = getWindow(); - const options = { capture: true }; - - // setting up our unbind before we bind - unbindWindowEventsRef.current = () => - unbindEvents(win, windowBindings, options); - - bindEvents(win, windowBindings, options); - }, [getWindow, windowBindings]); - - const startDragging = useCallback(() => { - invariant(!isDraggingRef.current, 'Cannot start a drag while dragging'); - - const ref: ?HTMLElement = getDraggableRef(); - invariant(ref, 'Cannot start a keyboard drag without a draggable ref'); - isDraggingRef.current = true; - - onCaptureStart(stop); - bindWindowEvents(); - - const center: Position = getBorderBoxCenterPosition(ref); - callbacks.onLift({ - clientSelection: center, - movementMode: 'SNAP', - }); - }, [bindWindowEvents, callbacks, getDraggableRef, onCaptureStart, stop]); - - const onKeyDown: OnKeyDown = useCallback( - (event: KeyboardEvent) => { - // not dragging yet - if (!getIsDragging()) { - // We may already be lifting on a child draggable. - // We do not need to use an EventMarshal here as - // we always call preventDefault on the first input - if (event.defaultPrevented) { - return; - } - - // Cannot lift at this time - if (!canStartCapturing(event)) { - return; - } - - if (event.keyCode !== keyCodes.space) { - return; - } - - // Calling preventDefault as we are consuming the event - event.preventDefault(); - startDragging(); - return; - } - - // already dragging - - // Cancelling - if (event.keyCode === keyCodes.escape) { - event.preventDefault(); - cancel(); - return; - } - - // Dropping - if (event.keyCode === keyCodes.space) { - // need to stop parent Draggable's thinking this is a lift - event.preventDefault(); - stop(); - callbacks.onDrop(); - return; - } - - // Movement - - if (event.keyCode === keyCodes.arrowDown) { - event.preventDefault(); - schedule.moveDown(); - return; - } - - if (event.keyCode === keyCodes.arrowUp) { - event.preventDefault(); - schedule.moveUp(); - return; - } - - if (event.keyCode === keyCodes.arrowRight) { - event.preventDefault(); - schedule.moveRight(); - return; - } - - if (event.keyCode === keyCodes.arrowLeft) { - event.preventDefault(); - schedule.moveLeft(); - return; - } - - // preventing scroll jumping at this time - if (scrollJumpKeys[event.keyCode]) { - event.preventDefault(); - return; - } - - preventStandardKeyEvents(event); - }, - [ - callbacks, - canStartCapturing, - cancel, - getIsDragging, - schedule, - startDragging, - stop, - ], - ); - - return onKeyDown; -} diff --git a/src/view/use-drag-handle/sensor/use-mouse-sensor.js b/src/view/use-drag-handle/sensor/use-mouse-sensor.js deleted file mode 100644 index 5800be25f7..0000000000 --- a/src/view/use-drag-handle/sensor/use-mouse-sensor.js +++ /dev/null @@ -1,346 +0,0 @@ -// @flow -import type { Position } from 'css-box-model'; -import { useRef } from 'react'; -import invariant from 'tiny-invariant'; -import { useMemo, useCallback } from 'use-memo-one'; -import type { EventBinding } from '../util/event-types'; -import createEventMarshal, { - type EventMarshal, -} from '../util/create-event-marshal'; -import type { Callbacks } from '../drag-handle-types'; -import { bindEvents, unbindEvents } from '../util/bind-events'; -import createScheduler from '../util/create-scheduler'; -import * as keyCodes from '../../key-codes'; -import supportedPageVisibilityEventName from '../util/supported-page-visibility-event-name'; -import createPostDragEventPreventer, { - type EventPreventer, -} from '../util/create-post-drag-event-preventer'; -import isSloppyClickThresholdExceeded from '../util/is-sloppy-click-threshold-exceeded'; -import preventStandardKeyEvents from '../util/prevent-standard-key-events'; - -export type Args = {| - callbacks: Callbacks, - onCaptureStart: (abort: Function) => void, - onCaptureEnd: () => void, - getDraggableRef: () => ?HTMLElement, - getWindow: () => HTMLElement, - canStartCapturing: (event: Event) => boolean, - getShouldRespectForcePress: () => boolean, -|}; - -export type OnMouseDown = (event: MouseEvent) => void; - -// Custom event format for force press inputs -// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button -const primaryButton: number = 0; -const noop = () => {}; - -// shared management of mousedown without needing to call preventDefault() -const mouseDownMarshal: EventMarshal = createEventMarshal(); - -export default function useMouseSensor(args: Args): OnMouseDown { - const { - canStartCapturing, - getWindow, - callbacks, - // Currently always respecting force press due to safari bug (see below) - // getShouldRespectForcePress, - onCaptureStart, - onCaptureEnd, - } = args; - const pendingRef = useRef(null); - const isDraggingRef = useRef(false); - const unbindWindowEventsRef = useRef<() => void>(noop); - const getIsCapturing = useCallback( - () => Boolean(pendingRef.current || isDraggingRef.current), - [], - ); - - const schedule = useMemo(() => { - invariant( - !getIsCapturing(), - 'Should not recreate scheduler while capturing', - ); - return createScheduler(callbacks); - }, [callbacks, getIsCapturing]); - - const postDragEventPreventer: EventPreventer = useMemo( - () => createPostDragEventPreventer(getWindow), - [getWindow], - ); - - const stop = useCallback(() => { - if (!getIsCapturing()) { - return; - } - - schedule.cancel(); - unbindWindowEventsRef.current(); - - const shouldBlockClick: boolean = isDraggingRef.current; - - mouseDownMarshal.reset(); - if (shouldBlockClick) { - postDragEventPreventer.preventNext(); - } - // resetting refs - pendingRef.current = null; - isDraggingRef.current = false; - - // releasing the capture - onCaptureEnd(); - }, [getIsCapturing, onCaptureEnd, postDragEventPreventer, schedule]); - - const cancel = useCallback(() => { - const wasDragging: boolean = isDraggingRef.current; - stop(); - - if (wasDragging) { - callbacks.onCancel(); - } - }, [callbacks, stop]); - - const startDragging = useCallback(() => { - invariant(!isDraggingRef.current, 'Cannot start a drag while dragging'); - const pending: ?Position = pendingRef.current; - invariant(pending, 'Cannot start a drag without a pending drag'); - - pendingRef.current = null; - isDraggingRef.current = true; - - callbacks.onLift({ - clientSelection: pending, - movementMode: 'FLUID', - }); - }, [callbacks]); - - const windowBindings: EventBinding[] = useMemo(() => { - invariant( - !getIsCapturing(), - 'Should not recreate window bindings while capturing', - ); - - const bindings: EventBinding[] = [ - { - eventName: 'mousemove', - fn: (event: MouseEvent) => { - const { button, clientX, clientY } = event; - if (button !== primaryButton) { - return; - } - - const point: Position = { - x: clientX, - y: clientY, - }; - - // Already dragging - if (isDraggingRef.current) { - // preventing default as we are using this event - event.preventDefault(); - schedule.move(point); - return; - } - - // There should be a pending drag at this point - const pending: ?Position = pendingRef.current; - - if (!pending) { - // this should be an impossible state - // we cannot use kill directly as it checks if there is a pending drag - stop(); - invariant( - false, - 'Expected there to be an active or pending drag when window mousemove event is received', - ); - } - - // threshold not yet exceeded - if (!isSloppyClickThresholdExceeded(pending, point)) { - return; - } - - // preventing default as we are using this event - event.preventDefault(); - startDragging(); - }, - }, - { - eventName: 'mouseup', - fn: (event: MouseEvent) => { - const wasDragging: boolean = isDraggingRef.current; - stop(); - - if (wasDragging) { - // preventing default as we are using this event - event.preventDefault(); - callbacks.onDrop(); - } - }, - }, - { - eventName: 'mousedown', - fn: (event: MouseEvent) => { - // this can happen during a drag when the user clicks a button - // other than the primary mouse button - if (isDraggingRef.current) { - event.preventDefault(); - } - - cancel(); - }, - }, - { - eventName: 'keydown', - fn: (event: KeyboardEvent) => { - // Abort if any keystrokes while a drag is pending - if (pendingRef.current) { - stop(); - return; - } - - // cancelling a drag - if (event.keyCode === keyCodes.escape) { - event.preventDefault(); - cancel(); - return; - } - - preventStandardKeyEvents(event); - }, - }, - { - eventName: 'resize', - fn: cancel, - }, - { - eventName: 'scroll', - // ## Passive: true - // Eventual consistency is fine because we use position: fixed on the item - // ## Capture: false - // Scroll events on elements do not bubble, but they go through the capture phase - // https://twitter.com/alexandereardon/status/985994224867819520 - // Using capture: false here as we want to avoid intercepting droppable scroll requests - // TODO: can result in awkward drop position - options: { passive: true, capture: false }, - fn: (event: UIEvent) => { - // IE11 fix: - // Scrollable events still bubble up and are caught by this handler in ie11. - // We can ignore this event - if (event.currentTarget !== getWindow()) { - return; - } - - // stop a pending drag - if (pendingRef.current) { - stop(); - return; - } - // getCallbacks().onWindowScroll(); - schedule.windowScrollMove(); - }, - }, - // Need to opt out of dragging if the user is a force press - // Only for safari which has decided to introduce its own custom way of doing things - // https://developer.apple.com/library/content/documentation/AppleApplications/Conceptual/SafariJSProgTopics/RespondingtoForceTouchEventsfromJavaScript.html - { - eventName: 'webkitmouseforcedown', - fn: () => { - // In order to opt out of force press correctly we need to call - // event.preventDefault() on webkitmouseforcewillbegin - // We have no way of doing this in this branch so we are always respecting force touches - // There is a correct fix in the `virtual` branch - cancel(); - }, - }, - // Cancel on page visibility change - { - eventName: supportedPageVisibilityEventName, - fn: cancel, - }, - ]; - return bindings; - }, [ - getIsCapturing, - cancel, - startDragging, - schedule, - stop, - callbacks, - getWindow, - ]); - - const bindWindowEvents = useCallback(() => { - const win: HTMLElement = getWindow(); - const options = { capture: true }; - - // setting up our unbind before we bind - unbindWindowEventsRef.current = () => - unbindEvents(win, windowBindings, options); - - bindEvents(win, windowBindings, options); - }, [getWindow, windowBindings]); - - const startPendingDrag = useCallback( - (point: Position) => { - invariant(!pendingRef.current, 'Expected there to be no pending drag'); - pendingRef.current = point; - onCaptureStart(stop); - bindWindowEvents(); - }, - [bindWindowEvents, onCaptureStart, stop], - ); - - const onMouseDown = useCallback( - (event: MouseEvent) => { - if (mouseDownMarshal.isHandled()) { - return; - } - - invariant( - !getIsCapturing(), - 'Should not be able to perform a mouse down while a drag or pending drag is occurring', - ); - - // We do not need to prevent the event on a dropping draggable as - // the mouse down event will not fire due to pointer-events: none - // https://codesandbox.io/s/oxo0o775rz - if (!canStartCapturing(event)) { - return; - } - - // only starting a drag if dragging with the primary mouse button - if (event.button !== primaryButton) { - return; - } - - // Do not start a drag if any modifier key is pressed - if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) { - return; - } - - // Registering that this event has been handled. - // This is to prevent parent draggables using this event - // to start also. - // Ideally we would not use preventDefault() as we are not sure - // if this mouse down is part of a drag interaction - // Unfortunately we do to prevent the element obtaining focus (see below). - mouseDownMarshal.handle(); - - // Unfortunately we do need to prevent the drag handle from getting focus on mousedown. - // This goes against our policy on not blocking events before a drag has started. - // See [How we use dom events](/docs/guides/how-we-use-dom-events.md). - event.preventDefault(); - - const point: Position = { - x: event.clientX, - y: event.clientY, - }; - - startPendingDrag(point); - }, - [canStartCapturing, getIsCapturing, startPendingDrag], - ); - - return onMouseDown; -} diff --git a/src/view/use-drag-handle/sensor/use-touch-sensor.js b/src/view/use-drag-handle/sensor/use-touch-sensor.js deleted file mode 100644 index 38177dcc42..0000000000 --- a/src/view/use-drag-handle/sensor/use-touch-sensor.js +++ /dev/null @@ -1,403 +0,0 @@ -// @flow -import type { Position } from 'css-box-model'; -import { useRef } from 'react'; -import invariant from 'tiny-invariant'; -import { useMemo, useCallback } from 'use-memo-one'; -import type { EventBinding } from '../util/event-types'; -import createEventMarshal, { - type EventMarshal, -} from '../util/create-event-marshal'; -import type { Callbacks } from '../drag-handle-types'; -import { bindEvents, unbindEvents } from '../util/bind-events'; -import createScheduler from '../util/create-scheduler'; -import * as keyCodes from '../../key-codes'; -import supportedPageVisibilityEventName from '../util/supported-page-visibility-event-name'; -import createPostDragEventPreventer, { - type EventPreventer, -} from '../util/create-post-drag-event-preventer'; -import useLayoutEffect from '../../use-isomorphic-layout-effect'; - -export type Args = {| - callbacks: Callbacks, - getDraggableRef: () => ?HTMLElement, - getWindow: () => HTMLElement, - canStartCapturing: (event: Event) => boolean, - getShouldRespectForcePress: () => boolean, - onCaptureStart: (abort: () => void) => void, - onCaptureEnd: () => void, -|}; -export type OnTouchStart = (event: TouchEvent) => void; - -type PendingDrag = {| - longPressTimerId: TimeoutID, - point: Position, -|}; - -type TouchWithForce = Touch & { - force: number, -}; - -// Decreased from 150 as a work around for an issue for forcepress on iOS -// https://github.com/atlassian/react-beautiful-dnd/issues/1401 -export const timeForLongPress: number = 120; -export const forcePressThreshold: number = 0.15; -const touchStartMarshal: EventMarshal = createEventMarshal(); -const noop = (): void => {}; - -export default function useTouchSensor(args: Args): OnTouchStart { - const { - callbacks, - getWindow, - canStartCapturing, - getShouldRespectForcePress, - onCaptureStart, - onCaptureEnd, - } = args; - const pendingRef = useRef(null); - const isDraggingRef = useRef(false); - const hasMovedRef = useRef(false); - const unbindWindowEventsRef = useRef<() => void>(noop); - const getIsCapturing = useCallback( - () => Boolean(pendingRef.current || isDraggingRef.current), - [], - ); - const postDragClickPreventer: EventPreventer = useMemo( - () => createPostDragEventPreventer(getWindow), - [getWindow], - ); - - const schedule = useMemo(() => { - invariant( - !getIsCapturing(), - 'Should not recreate scheduler while capturing', - ); - return createScheduler(callbacks); - }, [callbacks, getIsCapturing]); - - const stop = useCallback(() => { - if (!getIsCapturing()) { - return; - } - - schedule.cancel(); - unbindWindowEventsRef.current(); - touchStartMarshal.reset(); - hasMovedRef.current = false; - onCaptureEnd(); - - // if dragging - prevent the next click - if (isDraggingRef.current) { - postDragClickPreventer.preventNext(); - isDraggingRef.current = false; - return; - } - - const pending: ?PendingDrag = pendingRef.current; - invariant(pending, 'Expected a pending drag'); - - clearTimeout(pending.longPressTimerId); - pendingRef.current = null; - }, [getIsCapturing, onCaptureEnd, postDragClickPreventer, schedule]); - - const cancel = useCallback(() => { - const wasDragging: boolean = isDraggingRef.current; - stop(); - - if (wasDragging) { - callbacks.onCancel(); - } - }, [callbacks, stop]); - - const windowBindings: EventBinding[] = useMemo(() => { - invariant( - !getIsCapturing(), - 'Should not recreate window bindings while capturing', - ); - - const bindings: EventBinding[] = [ - { - eventName: 'touchmove', - // Opting out of passive touchmove (default) so as to prevent scrolling while moving - // Not worried about performance as effect of move is throttled in requestAnimationFrame - // Using `capture: false` due to a recent horrible firefox bug: https://twitter.com/alexandereardon/status/1125904207184187393 - options: { passive: false, capture: false }, - fn: (event: TouchEvent) => { - // Drag has not yet started and we are waiting for a long press. - if (!isDraggingRef.current) { - stop(); - return; - } - - // At this point we are dragging - - if (!hasMovedRef.current) { - hasMovedRef.current = true; - } - - const touch: ?Touch = event.touches[0]; - - if (!touch) { - return; - } - - const point: Position = { - x: touch.clientX, - y: touch.clientY, - }; - - // We need to prevent the default event in order to block native scrolling - // Also because we are using it as part of a drag we prevent the default action - // as a sign that we are using the event - event.preventDefault(); - schedule.move(point); - }, - }, - { - eventName: 'touchend', - fn: (event: TouchEvent) => { - // drag had not started yet - do not prevent the default action - if (!isDraggingRef.current) { - stop(); - return; - } - - // already dragging - this event is directly ending a drag - event.preventDefault(); - stop(); - callbacks.onDrop(); - }, - }, - { - eventName: 'touchcancel', - fn: (event: TouchEvent) => { - // drag had not started yet - do not prevent the default action - if (!isDraggingRef.current) { - stop(); - return; - } - - // already dragging - this event is directly ending a drag - event.preventDefault(); - cancel(); - }, - }, - // another touch start should not happen without a - // touchend or touchcancel. However, just being super safe - { - eventName: 'touchstart', - fn: cancel, - }, - // If the orientation of the device changes - kill the drag - // https://davidwalsh.name/orientation-change - { - eventName: 'orientationchange', - fn: cancel, - }, - // some devices fire resize if the orientation changes - { - eventName: 'resize', - fn: cancel, - }, - // ## Passive: true - // For scroll events we are okay with eventual consistency. - // Passive scroll listeners is the default behavior for mobile - // but we are being really clear here - // ## Capture: false - // Scroll events on elements do not bubble, but they go through the capture phase - // https://twitter.com/alexandereardon/status/985994224867819520 - // Using capture: false here as we want to avoid intercepting droppable scroll requests - { - eventName: 'scroll', - options: { passive: true, capture: false }, - fn: () => { - // stop a pending drag - if (pendingRef.current) { - stop(); - return; - } - schedule.windowScrollMove(); - }, - }, - // Long press can bring up a context menu - // need to opt out of this behavior - { - eventName: 'contextmenu', - fn: (event: Event) => { - // always opting out of context menu events - event.preventDefault(); - }, - }, - // On some devices it is possible to have a touch interface with a keyboard. - // On any keyboard event we cancel a touch drag - { - eventName: 'keydown', - fn: (event: KeyboardEvent) => { - if (!isDraggingRef.current) { - cancel(); - return; - } - - // direct cancel: we are preventing the default action - // indirect cancel: we are not preventing the default action - - // escape is a direct cancel - if (event.keyCode === keyCodes.escape) { - event.preventDefault(); - } - cancel(); - }, - }, - // Need to opt out of dragging if the user is a force press - // Only for webkit which has decided to introduce its own custom way of doing things - // https://developer.apple.com/library/content/documentation/AppleApplications/Conceptual/SafariJSProgTopics/RespondingtoForceTouchEventsfromJavaScript.html - // NOTE: this function is back-ported from the `virtual` branch - { - eventName: 'touchforcechange', - fn: (event: TouchEvent) => { - const touch: TouchWithForce = (event.touches[0]: any); - const isForcePress: boolean = touch.force >= forcePressThreshold; - - if (!isForcePress) { - return; - } - - const shouldRespect: boolean = getShouldRespectForcePress(); - - if (pendingRef.current) { - if (shouldRespect) { - cancel(); - } - // If not respecting we just let the event go through - // It will not have an impact on the browser until - // there has been a sufficient time ellapsed - return; - } - - // DRAGGING - - if (shouldRespect) { - if (hasMovedRef.current) { - // After the user has moved we do not allow the dragging item to be force pressed - // This prevents strange behaviour such as a link preview opening mid drag - event.preventDefault(); - return; - } - // indirect cancel - cancel(); - return; - } - // not respecting during a drag - event.preventDefault(); - }, - }, - // Cancel on page visibility change - { - eventName: supportedPageVisibilityEventName, - fn: cancel, - }, - ]; - return bindings; - }, [ - callbacks, - cancel, - getIsCapturing, - getShouldRespectForcePress, - schedule, - stop, - ]); - - const bindWindowEvents = useCallback(() => { - const win: HTMLElement = getWindow(); - const options = { capture: true }; - - // setting up our unbind before we bind - unbindWindowEventsRef.current = () => - unbindEvents(win, windowBindings, options); - - bindEvents(win, windowBindings, options); - }, [getWindow, windowBindings]); - - const startDragging = useCallback(() => { - const pending: ?PendingDrag = pendingRef.current; - invariant(pending, 'Cannot start a drag without a pending drag'); - - isDraggingRef.current = true; - pendingRef.current = null; - hasMovedRef.current = false; - - callbacks.onLift({ - clientSelection: pending.point, - movementMode: 'FLUID', - }); - }, [callbacks]); - - const startPendingDrag = useCallback( - (event: TouchEvent) => { - invariant(!pendingRef.current, 'Expected there to be no pending drag'); - const touch: Touch = event.touches[0]; - const { clientX, clientY } = touch; - const point: Position = { - x: clientX, - y: clientY, - }; - const longPressTimerId: TimeoutID = setTimeout( - startDragging, - timeForLongPress, - ); - - const pending: PendingDrag = { - point, - longPressTimerId, - }; - - pendingRef.current = pending; - onCaptureStart(stop); - bindWindowEvents(); - }, - [bindWindowEvents, onCaptureStart, startDragging, stop], - ); - - const onTouchStart = (event: TouchEvent) => { - if (touchStartMarshal.isHandled()) { - return; - } - - invariant( - !getIsCapturing(), - 'Should not be able to perform a touch start while a drag or pending drag is occurring', - ); - - // We do not need to prevent the event on a dropping draggable as - // the touchstart event will not fire due to pointer-events: none - // https://codesandbox.io/s/oxo0o775rz - if (!canStartCapturing(event)) { - return; - } - - // We need to stop parents from responding to this event - which may cause a double lift - // We also need to NOT call event.preventDefault() so as to maintain as much standard - // browser interactions as possible. - // This includes navigation on anchors which we want to preserve - touchStartMarshal.handle(); - startPendingDrag(event); - }; - - // This is needed for safari - // Simply adding a non capture, non passive 'touchmove' listener. - // This forces event.preventDefault() in dynamically added - // touchmove event handlers to actually work - // https://github.com/atlassian/react-beautiful-dnd/issues/1374 - useLayoutEffect(function webkitHack() { - const unbind = bindEvents(window, [ - { - eventName: 'touchmove', - fn: noop, - options: { capture: false, passive: false }, - }, - ]); - - return unbind; - }, []); - - return onTouchStart; -} diff --git a/src/view/use-drag-handle/use-drag-handle.js b/src/view/use-drag-handle/use-drag-handle.js deleted file mode 100644 index ac32f0f8cc..0000000000 --- a/src/view/use-drag-handle/use-drag-handle.js +++ /dev/null @@ -1,236 +0,0 @@ -// @flow -import invariant from 'tiny-invariant'; -import { useRef } from 'react'; -import { useMemo, useCallback } from 'use-memo-one'; -import type { Args, DragHandleProps } from './drag-handle-types'; -import getWindowFromEl from '../window/get-window-from-el'; -import useRequiredContext from '../use-required-context'; -import AppContext, { type AppContextValue } from '../context/app-context'; -import useMouseSensor, { - type Args as MouseSensorArgs, -} from './sensor/use-mouse-sensor'; -import shouldAllowDraggingFromTarget from './util/should-allow-dragging-from-target'; -import useKeyboardSensor, { - type Args as KeyboardSensorArgs, -} from './sensor/use-keyboard-sensor'; -import useTouchSensor, { - type Args as TouchSensorArgs, -} from './sensor/use-touch-sensor'; -import usePreviousRef from '../use-previous-ref'; -import { warning } from '../../dev-warning'; -import useValidation from './use-validation'; -import useFocusRetainer from './use-focus-retainer'; -import useLayoutEffect from '../use-isomorphic-layout-effect'; - -function preventHtml5Dnd(event: DragEvent) { - event.preventDefault(); -} - -type Capturing = {| - abort: () => void, -|}; - -export default function useDragHandle(args: Args): ?DragHandleProps { - // Capturing - const capturingRef = useRef(null); - const onCaptureStart = useCallback((abort: () => void) => { - invariant( - !capturingRef.current, - 'Cannot start capturing while something else is', - ); - capturingRef.current = { - abort, - }; - }, []); - const onCaptureEnd = useCallback(() => { - invariant( - capturingRef.current, - 'Cannot stop capturing while nothing is capturing', - ); - capturingRef.current = null; - }, []); - const abortCapture = useCallback(() => { - invariant(capturingRef.current, 'Cannot abort capture when there is none'); - capturingRef.current.abort(); - }, []); - - const { canLift, style: styleContext }: AppContextValue = useRequiredContext( - AppContext, - ); - const { - isDragging, - isEnabled, - draggableId, - callbacks, - getDraggableRef, - getShouldRespectForcePress, - canDragInteractiveElements, - } = args; - const lastArgsRef = usePreviousRef(args); - - useValidation({ isEnabled, getDraggableRef }); - - const getWindow = useCallback( - (): HTMLElement => getWindowFromEl(getDraggableRef()), - [getDraggableRef], - ); - - const canStartCapturing = useCallback( - (event: Event) => { - // Cannot lift when disabled - if (!isEnabled) { - return false; - } - // Something on this element might be capturing. - // A drag might not have started yet - // We want to prevent anything else from capturing - if (capturingRef.current) { - return false; - } - - // Do not drag if anything else in the system is dragging - if (!canLift(draggableId)) { - return false; - } - - // Check if we are dragging an interactive element - return shouldAllowDraggingFromTarget(event, canDragInteractiveElements); - }, - [canDragInteractiveElements, canLift, draggableId, isEnabled], - ); - - const { onBlur, onFocus } = useFocusRetainer(args); - - const mouseArgs: MouseSensorArgs = useMemo( - () => ({ - callbacks, - getDraggableRef, - getWindow, - canStartCapturing, - onCaptureStart, - onCaptureEnd, - getShouldRespectForcePress, - }), - [ - callbacks, - getDraggableRef, - getWindow, - canStartCapturing, - onCaptureStart, - onCaptureEnd, - getShouldRespectForcePress, - ], - ); - const onMouseDown = useMouseSensor(mouseArgs); - - const keyboardArgs: KeyboardSensorArgs = useMemo( - () => ({ - callbacks, - getDraggableRef, - getWindow, - canStartCapturing, - onCaptureStart, - onCaptureEnd, - }), - [ - callbacks, - canStartCapturing, - getDraggableRef, - getWindow, - onCaptureEnd, - onCaptureStart, - ], - ); - const onKeyDown = useKeyboardSensor(keyboardArgs); - - const touchArgs: TouchSensorArgs = useMemo( - () => ({ - callbacks, - getDraggableRef, - getWindow, - canStartCapturing, - getShouldRespectForcePress, - onCaptureStart, - onCaptureEnd, - }), - [ - callbacks, - getDraggableRef, - getWindow, - canStartCapturing, - getShouldRespectForcePress, - onCaptureStart, - onCaptureEnd, - ], - ); - const onTouchStart = useTouchSensor(touchArgs); - - // aborting on unmount - - useLayoutEffect(() => { - // only when unmounting - return () => { - if (!capturingRef.current) { - return; - } - abortCapture(); - - if (lastArgsRef.current.isDragging) { - // eslint-disable-next-line react-hooks/exhaustive-deps - lastArgsRef.current.callbacks.onCancel(); - } - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - // No longer enabled but still capturing: need to abort and cancel if needed - if (!isEnabled && capturingRef.current) { - abortCapture(); - if (lastArgsRef.current.isDragging) { - warning( - 'You have disabled dragging on a Draggable while it was dragging. The drag has been cancelled', - ); - callbacks.onCancel(); - } - } - - // Handle aborting - // No longer dragging but still capturing: need to abort - // Using a layout effect to ensure that there is a flip from isDragging => !isDragging - // When there is a pending drag !isDragging will always be true - useLayoutEffect(() => { - if (!isDragging && capturingRef.current) { - abortCapture(); - } - }, [abortCapture, isDragging]); - - const props: ?DragHandleProps = useMemo(() => { - if (!isEnabled) { - return null; - } - return { - onMouseDown, - onKeyDown, - onTouchStart, - onFocus, - onBlur, - tabIndex: 0, - 'data-react-beautiful-dnd-drag-handle': styleContext, - // English default. Consumers are welcome to add their own start instruction - 'aria-roledescription': 'Draggable item. Press space bar to lift', - // Opting out of html5 drag and drops - draggable: false, - onDragStart: preventHtml5Dnd, - }; - }, [ - isEnabled, - onBlur, - onFocus, - onKeyDown, - onMouseDown, - onTouchStart, - styleContext, - ]); - - return props; -} diff --git a/src/view/use-drag-handle/use-focus-retainer.js b/src/view/use-drag-handle/use-focus-retainer.js deleted file mode 100644 index 08f5c4b0a1..0000000000 --- a/src/view/use-drag-handle/use-focus-retainer.js +++ /dev/null @@ -1,108 +0,0 @@ -// @flow -import invariant from 'tiny-invariant'; -import { useRef } from 'react'; -import { useCallback } from 'use-memo-one'; -import type { Args } from './drag-handle-types'; -import usePrevious from '../use-previous-ref'; -import focusRetainer from './util/focus-retainer'; -import getDragHandleRef from './util/get-drag-handle-ref'; -import useLayoutEffect from '../use-isomorphic-layout-effect'; - -export type Result = {| - onBlur: () => void, - onFocus: () => void, -|}; - -function noop() {} - -export default function useFocusRetainer(args: Args): Result { - const isFocusedRef = useRef(false); - const lastArgsRef = usePrevious(args); - const { getDraggableRef } = args; - - const onFocus = useCallback(() => { - isFocusedRef.current = true; - }, []); - const onBlur = useCallback(() => { - isFocusedRef.current = false; - }, []); - - // This effect handles: - // - giving focus on mount - // - registering focus on unmount - useLayoutEffect(() => { - // mounting: try to restore focus - const first: Args = lastArgsRef.current; - if (!first.isEnabled) { - return noop; - } - const draggable: ?HTMLElement = getDraggableRef(); - invariant(draggable, 'Drag handle could not obtain draggable ref'); - - const dragHandle: HTMLElement = getDragHandleRef(draggable); - - focusRetainer.tryRestoreFocus(first.draggableId, dragHandle); - - // unmounting: try to retain focus - return () => { - // eslint-disable-next-line react-hooks/exhaustive-deps - const last: Args = lastArgsRef.current; - const shouldRetainFocus = ((): boolean => { - // will not restore if not enabled - if (!last.isEnabled) { - return false; - } - // not focused - if (!isFocusedRef.current) { - return false; - } - - // a drag is finishing - return last.isDragging || last.isDropAnimating; - })(); - - if (shouldRetainFocus) { - focusRetainer.retain(last.draggableId); - } - }; - }, [getDraggableRef, lastArgsRef]); - - // will always be null on the first render as nothing has mounted yet - const lastDraggableRef = useRef(null); - - // This effect restores focus to an element when a - // ref changes while a component is still mounted. - // This can happen when a drag handle is moved into a portal - useLayoutEffect(() => { - // this can happen on the first mount - no draggable ref is set - // this effect is not handling initial mounting - if (!lastDraggableRef.current) { - return; - } - - const draggableRef: ?HTMLElement = getDraggableRef(); - - // Cannot focus on nothing - if (!draggableRef) { - return; - } - - // no change in ref - if (draggableRef === lastDraggableRef.current) { - return; - } - - // ref has changed - let's do this - if (isFocusedRef.current && lastArgsRef.current.isEnabled) { - getDragHandleRef(draggableRef).focus(); - } - - // Doing our own should run check - }); - - useLayoutEffect(() => { - lastDraggableRef.current = getDraggableRef(); - }); - - return { onBlur, onFocus }; -} diff --git a/src/view/use-drag-handle/use-validation.js b/src/view/use-drag-handle/use-validation.js deleted file mode 100644 index f6dfc6973c..0000000000 --- a/src/view/use-drag-handle/use-validation.js +++ /dev/null @@ -1,26 +0,0 @@ -// @flow -import { useEffect } from 'react'; -import invariant from 'tiny-invariant'; -import getDragHandleRef from './util/get-drag-handle-ref'; - -type Args = {| - isEnabled: boolean, - getDraggableRef: () => ?HTMLElement, -|}; - -export default function useValidation({ isEnabled, getDraggableRef }: Args) { - // validate ref on mount - useEffect(() => { - // wrapping entire block for better minification - if (process.env.NODE_ENV !== 'production') { - // There will be no drag handle ref when disabled - if (!isEnabled) { - return; - } - - const draggableRef: ?HTMLElement = getDraggableRef(); - invariant(draggableRef, 'Drag handle was unable to find draggable ref'); - getDragHandleRef(draggableRef); - } - }, [getDraggableRef, isEnabled]); -} diff --git a/src/view/use-drag-handle/util/bind-events.js b/src/view/use-drag-handle/util/bind-events.js deleted file mode 100644 index 6530914aae..0000000000 --- a/src/view/use-drag-handle/util/bind-events.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow -import type { EventBinding, EventOptions } from './event-types'; - -const getOptions = ( - shared?: EventOptions, - fromBinding: ?EventOptions, -): EventOptions => ({ - ...shared, - ...fromBinding, -}); - -export const bindEvents = ( - el: HTMLElement, - bindings: EventBinding[], - sharedOptions?: EventOptions, -) => { - bindings.forEach((binding: EventBinding) => { - const options: Object = getOptions(sharedOptions, binding.options); - - el.addEventListener(binding.eventName, binding.fn, options); - }); -}; - -export const unbindEvents = ( - el: HTMLElement, - bindings: EventBinding[], - sharedOptions?: EventOptions, -) => { - bindings.forEach((binding: EventBinding) => { - const options: Object = getOptions(sharedOptions, binding.options); - - el.removeEventListener(binding.eventName, binding.fn, options); - }); -}; diff --git a/src/view/use-drag-handle/util/create-event-marshal.js b/src/view/use-drag-handle/util/create-event-marshal.js deleted file mode 100644 index eee13c6811..0000000000 --- a/src/view/use-drag-handle/util/create-event-marshal.js +++ /dev/null @@ -1,32 +0,0 @@ -// @flow -import invariant from 'tiny-invariant'; - -export type EventMarshal = {| - handle: () => void, - isHandled: () => boolean, - reset: () => void, -|}; - -export default (): EventMarshal => { - let isMouseDownHandled: boolean = false; - - const handle = (): void => { - invariant( - !isMouseDownHandled, - 'Cannot handle mouse down as it is already handled', - ); - isMouseDownHandled = true; - }; - - const isHandled = (): boolean => isMouseDownHandled; - - const reset = (): void => { - isMouseDownHandled = false; - }; - - return { - handle, - isHandled, - reset, - }; -}; diff --git a/src/view/use-drag-handle/util/create-post-drag-event-preventer.js b/src/view/use-drag-handle/util/create-post-drag-event-preventer.js deleted file mode 100644 index 361f239751..0000000000 --- a/src/view/use-drag-handle/util/create-post-drag-event-preventer.js +++ /dev/null @@ -1,68 +0,0 @@ -// @flow -/* eslint-disable no-use-before-define */ -import type { EventBinding, EventOptions } from './event-types'; -import { bindEvents, unbindEvents } from './bind-events'; - -type GetWindowFn = () => HTMLElement; - -export type EventPreventer = {| - preventNext: () => void, - abort: () => void, -|}; - -const sharedOptions: EventOptions = { capture: true }; - -export default (getWindow: GetWindowFn): EventPreventer => { - let isBound: boolean = false; - - const bind = () => { - if (isBound) { - return; - } - isBound = true; - bindEvents(getWindow(), pointerEvents, sharedOptions); - }; - - const unbind = () => { - if (!isBound) { - return; - } - isBound = false; - unbindEvents(getWindow(), pointerEvents, sharedOptions); - }; - - const pointerEvents: EventBinding[] = [ - { - eventName: 'click', - fn: (event: MouseEvent) => { - event.preventDefault(); - unbind(); - }, - }, - // These events signal that the click prevention is no longer needed - { - eventName: 'mousedown', - // a new mouse interaction is starting: we can unbind - fn: unbind, - }, - { - eventName: 'touchstart', - fn: unbind, - }, - ]; - - const preventNext = (): void => { - if (isBound) { - unbind(); - } - - bind(); - }; - - const preventer: EventPreventer = { - preventNext, - abort: unbind, - }; - - return preventer; -}; diff --git a/src/view/use-drag-handle/util/create-scheduler.js b/src/view/use-drag-handle/util/create-scheduler.js deleted file mode 100644 index 1b2d671947..0000000000 --- a/src/view/use-drag-handle/util/create-scheduler.js +++ /dev/null @@ -1,40 +0,0 @@ -// @flow -import { type Position } from 'css-box-model'; -import memoizeOne from 'memoize-one'; -import rafSchd from 'raf-schd'; -import type { Callbacks } from '../drag-handle-types'; - -export default (callbacks: Callbacks) => { - const memoizedMove = memoizeOne((x: number, y: number) => { - const point: Position = { x, y }; - callbacks.onMove(point); - }); - - const move = rafSchd((point: Position) => memoizedMove(point.x, point.y)); - const moveUp = rafSchd(callbacks.onMoveUp); - const moveDown = rafSchd(callbacks.onMoveDown); - const moveRight = rafSchd(callbacks.onMoveRight); - const moveLeft = rafSchd(callbacks.onMoveLeft); - const windowScrollMove = rafSchd(callbacks.onWindowScroll); - - const cancel = () => { - // cancel all of the next animation frames - - move.cancel(); - moveUp.cancel(); - moveDown.cancel(); - moveRight.cancel(); - moveLeft.cancel(); - windowScrollMove.cancel(); - }; - - return { - move, - moveUp, - moveDown, - moveRight, - moveLeft, - windowScrollMove, - cancel, - }; -}; diff --git a/src/view/use-drag-handle/util/focus-retainer.js b/src/view/use-drag-handle/util/focus-retainer.js deleted file mode 100644 index 2df6465a38..0000000000 --- a/src/view/use-drag-handle/util/focus-retainer.js +++ /dev/null @@ -1,95 +0,0 @@ -// @flow -import getDragHandleRef from './get-drag-handle-ref'; -import { warning } from '../../../dev-warning'; -import type { DraggableId } from '../../../types'; - -type FocusRetainer = {| - retain: (draggableId: DraggableId) => void, - tryRestoreFocus: ( - draggableId: DraggableId, - draggableRef: HTMLElement, - ) => void, -|}; - -// our shared state -let retainingFocusFor: ?DraggableId = null; - -// Using capture: true as focus events do not bubble -// Additionally doing this prevents us from intercepting the initial -// focus event as it does not bubble up to this listener -const listenerOptions = { capture: true }; - -// If we focus on -const clearRetentionOnFocusChange = (() => { - let isBound: boolean = false; - - const bind = () => { - if (isBound) { - return; - } - - isBound = true; - - // eslint-disable-next-line no-use-before-define - window.addEventListener('focus', onWindowFocusChange, listenerOptions); - }; - - const unbind = () => { - if (!isBound) { - return; - } - - isBound = false; - // eslint-disable-next-line no-use-before-define - window.removeEventListener('focus', onWindowFocusChange, listenerOptions); - }; - - // focusin will fire after the focus event fires on the element - const onWindowFocusChange = () => { - // unbinding self after single use - unbind(); - retainingFocusFor = null; - }; - - const result = () => bind(); - result.cancel = () => unbind(); - - return result; -})(); - -const retain = (id: DraggableId) => { - retainingFocusFor = id; - clearRetentionOnFocusChange(); -}; - -const tryRestoreFocus = (id: DraggableId, draggableRef: HTMLElement) => { - // Not needing to retain focus - if (!retainingFocusFor) { - return; - } - // Not needing to retain focus for this draggable - if (id !== retainingFocusFor) { - return; - } - - // We are about to force focus onto a drag handle - - retainingFocusFor = null; - // no need to clear it - we are already clearing it - clearRetentionOnFocusChange.cancel(); - - const dragHandleRef: ?HTMLElement = getDragHandleRef(draggableRef); - - if (!dragHandleRef) { - warning('Could not find drag handle in the DOM to focus on it'); - return; - } - dragHandleRef.focus(); -}; - -const retainer: FocusRetainer = { - retain, - tryRestoreFocus, -}; - -export default retainer; diff --git a/src/view/use-drag-handle/util/get-drag-handle-ref.js b/src/view/use-drag-handle/util/get-drag-handle-ref.js deleted file mode 100644 index 55e70b6ca9..0000000000 --- a/src/view/use-drag-handle/util/get-drag-handle-ref.js +++ /dev/null @@ -1,49 +0,0 @@ -// @flow -import invariant from 'tiny-invariant'; -import { dragHandle } from '../../data-attributes'; -import isSvgElement from '../../is-type-of-element/is-svg-element'; -import isHtmlElement from '../../is-type-of-element/is-html-element'; - -const selector: string = `[${dragHandle}]`; - -const throwIfSVG = (el: mixed) => { - invariant( - !isSvgElement(el), - `A drag handle cannot be an SVGElement: it has inconsistent focus support. - - More information: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/guides/dragging-svgs.md`, - ); -}; - -// If called when the component is disabled then the data -// attribute will not be present -const getDragHandleRef = (draggableRef: HTMLElement): HTMLElement => { - if (draggableRef.hasAttribute(dragHandle)) { - throwIfSVG(draggableRef); - return draggableRef; - } - - // find the first nested drag handle - // querySelector will return the first match on a breadth first search which is what we want - // Search will fail when the drag handle is disabled - // https://codepen.io/alexreardon/pen/erOqyZ - const el: ?HTMLElement = draggableRef.querySelector(selector); - - throwIfSVG(draggableRef); - - invariant( - el, - ` - Cannot find drag handle element inside of Draggable. - Please be sure to apply the {...provided.dragHandleProps} to your Draggable - - More information: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/api/draggable.md - `, - ); - - invariant(isHtmlElement(el), 'A drag handle must be a HTMLElement'); - - return el; -}; - -export default getDragHandleRef; diff --git a/src/view/use-drag-handle/util/is-sloppy-click-threshold-exceeded.js b/src/view/use-drag-handle/util/is-sloppy-click-threshold-exceeded.js deleted file mode 100644 index e73f3f2789..0000000000 --- a/src/view/use-drag-handle/util/is-sloppy-click-threshold-exceeded.js +++ /dev/null @@ -1,9 +0,0 @@ -// @flow -import { type Position } from 'css-box-model'; -// The amount of pixels that need to move before we consider the movement -// a drag rather than a click. -export const sloppyClickThreshold: number = 5; - -export default (original: Position, current: Position): boolean => - Math.abs(current.x - original.x) >= sloppyClickThreshold || - Math.abs(current.y - original.y) >= sloppyClickThreshold; diff --git a/src/view/use-draggable-dimension-publisher/index.js b/src/view/use-draggable-dimension-publisher/index.js deleted file mode 100644 index 04c9114c8b..0000000000 --- a/src/view/use-draggable-dimension-publisher/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { default } from './use-draggable-dimension-publisher'; diff --git a/src/view/use-draggable-dimension-publisher/use-draggable-dimension-publisher.js b/src/view/use-draggable-dimension-publisher/use-draggable-dimension-publisher.js deleted file mode 100644 index e61c16dfb7..0000000000 --- a/src/view/use-draggable-dimension-publisher/use-draggable-dimension-publisher.js +++ /dev/null @@ -1,78 +0,0 @@ -// @flow -import { useRef } from 'react'; -import { type Position } from 'css-box-model'; -import invariant from 'tiny-invariant'; -import { useMemo, useCallback } from 'use-memo-one'; -import type { - DraggableDescriptor, - DraggableDimension, - DraggableId, -} from '../../types'; -import type { DimensionMarshal } from '../../state/dimension-marshal/dimension-marshal-types'; -import useRequiredContext from '../use-required-context'; -import AppContext, { type AppContextValue } from '../context/app-context'; -import getDimension from './get-dimension'; -import DroppableContext, { - type DroppableContextValue, -} from '../context/droppable-context'; -import useLayoutEffect from '../use-isomorphic-layout-effect'; - -export type Args = {| - draggableId: DraggableId, - index: number, - getDraggableRef: () => ?HTMLElement, -|}; - -export default function useDraggableDimensionPublisher(args: Args) { - const { draggableId, index, getDraggableRef } = args; - // App context - const appContext: AppContextValue = useRequiredContext(AppContext); - const marshal: DimensionMarshal = appContext.marshal; - - // Droppable context - const droppableContext: DroppableContextValue = useRequiredContext( - DroppableContext, - ); - const { droppableId, type } = droppableContext; - - const descriptor: DraggableDescriptor = useMemo(() => { - const result = { - id: draggableId, - droppableId, - type, - index, - }; - return result; - }, [draggableId, droppableId, index, type]); - - const publishedDescriptorRef = useRef(descriptor); - - const makeDimension = useCallback( - (windowScroll?: Position): DraggableDimension => { - const latest: DraggableDescriptor = publishedDescriptorRef.current; - const el: ?HTMLElement = getDraggableRef(); - invariant(el, 'Cannot get dimension when no ref is set'); - return getDimension(latest, el, windowScroll); - }, - [getDraggableRef], - ); - - // handle mounting / unmounting - useLayoutEffect(() => { - marshal.registerDraggable(publishedDescriptorRef.current, makeDimension); - return () => marshal.unregisterDraggable(publishedDescriptorRef.current); - }, [makeDimension, marshal]); - - // handle updates to descriptor - useLayoutEffect(() => { - // this will happen when mounting - if (publishedDescriptorRef.current === descriptor) { - return; - } - - const previous: DraggableDescriptor = publishedDescriptorRef.current; - publishedDescriptorRef.current = descriptor; - - marshal.updateDraggable(previous, descriptor, makeDimension); - }, [descriptor, makeDimension, marshal]); -} diff --git a/src/view/use-draggable-dimension-publisher/get-dimension.js b/src/view/use-draggable-publisher/get-dimension.js similarity index 100% rename from src/view/use-draggable-dimension-publisher/get-dimension.js rename to src/view/use-draggable-publisher/get-dimension.js diff --git a/src/view/use-draggable-publisher/index.js b/src/view/use-draggable-publisher/index.js new file mode 100644 index 0000000000..70c3a1467f --- /dev/null +++ b/src/view/use-draggable-publisher/index.js @@ -0,0 +1,2 @@ +// @flow +export { default } from './use-draggable-publisher'; diff --git a/src/view/use-draggable-publisher/use-draggable-publisher.js b/src/view/use-draggable-publisher/use-draggable-publisher.js new file mode 100644 index 0000000000..9ff8136555 --- /dev/null +++ b/src/view/use-draggable-publisher/use-draggable-publisher.js @@ -0,0 +1,113 @@ +// @flow +import { type Position } from 'css-box-model'; +import invariant from 'tiny-invariant'; +import { useMemo, useCallback } from 'use-memo-one'; +import { useRef } from 'react'; +import type { + DraggableDescriptor, + DraggableDimension, + DraggableId, + Id, + DraggableOptions, +} from '../../types'; +import type { + Registry, + DraggableEntry, +} from '../../state/registry/registry-types'; +import useRequiredContext from '../use-required-context'; +import AppContext, { type AppContextValue } from '../context/app-context'; +import makeDimension from './get-dimension'; +import DroppableContext, { + type DroppableContextValue, +} from '../context/droppable-context'; +import useLayoutEffect from '../use-isomorphic-layout-effect'; +import useUniqueId from '../use-unique-id'; + +export type Args = {| + draggableId: DraggableId, + index: number, + getDraggableRef: () => ?HTMLElement, + ...DraggableOptions, +|}; + +export default function useDraggablePublisher(args: Args) { + const uniqueId: Id = useUniqueId('draggable'); + + const { + draggableId, + index, + getDraggableRef, + canDragInteractiveElements, + shouldRespectForcePress, + isEnabled, + } = args; + + // App context + const appContext: AppContextValue = useRequiredContext(AppContext); + const registry: Registry = appContext.registry; + + // Droppable context + const droppableContext: DroppableContextValue = useRequiredContext( + DroppableContext, + ); + const { droppableId, type } = droppableContext; + + const descriptor: DraggableDescriptor = useMemo(() => { + const result = { + id: draggableId, + droppableId, + type, + index, + }; + return result; + }, [draggableId, droppableId, index, type]); + + const options: DraggableOptions = useMemo( + () => ({ + canDragInteractiveElements, + shouldRespectForcePress, + isEnabled, + }), + [canDragInteractiveElements, isEnabled, shouldRespectForcePress], + ); + + const getDimension = useCallback( + (windowScroll?: Position): DraggableDimension => { + const el: ?HTMLElement = getDraggableRef(); + invariant(el, 'Cannot get dimension when no ref is set'); + return makeDimension(descriptor, el, windowScroll); + }, + [descriptor, getDraggableRef], + ); + + const entry: DraggableEntry = useMemo( + () => ({ + uniqueId, + descriptor, + options, + getDimension, + }), + [descriptor, getDimension, options, uniqueId], + ); + + const publishedRef = useRef(entry); + const isFirstPublishRef = useRef(true); + + // mounting and unmounting + useLayoutEffect(() => { + registry.draggable.register(publishedRef.current); + return () => registry.draggable.unregister(publishedRef.current); + }, [registry.draggable]); + + // updates while mounted + useLayoutEffect(() => { + if (isFirstPublishRef.current) { + isFirstPublishRef.current = false; + return; + } + + const last: DraggableEntry = publishedRef.current; + publishedRef.current = entry; + registry.draggable.update(entry, last); + }, [entry, registry.draggable]); +} diff --git a/src/view/use-droppable-dimension-publisher/index.js b/src/view/use-droppable-dimension-publisher/index.js deleted file mode 100644 index 21a4c1fa25..0000000000 --- a/src/view/use-droppable-dimension-publisher/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// @flow -export { default } from './use-droppable-dimension-publisher'; diff --git a/src/view/use-droppable-dimension-publisher/check-for-nested-scroll-container.js b/src/view/use-droppable-publisher/check-for-nested-scroll-container.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/check-for-nested-scroll-container.js rename to src/view/use-droppable-publisher/check-for-nested-scroll-container.js diff --git a/src/view/use-droppable-dimension-publisher/get-closest-scrollable.js b/src/view/use-droppable-publisher/get-closest-scrollable.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/get-closest-scrollable.js rename to src/view/use-droppable-publisher/get-closest-scrollable.js diff --git a/src/view/use-droppable-dimension-publisher/get-dimension.js b/src/view/use-droppable-publisher/get-dimension.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/get-dimension.js rename to src/view/use-droppable-publisher/get-dimension.js diff --git a/src/view/use-droppable-dimension-publisher/get-env.js b/src/view/use-droppable-publisher/get-env.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/get-env.js rename to src/view/use-droppable-publisher/get-env.js diff --git a/src/view/use-droppable-dimension-publisher/get-listener-options.js b/src/view/use-droppable-publisher/get-listener-options.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/get-listener-options.js rename to src/view/use-droppable-publisher/get-listener-options.js diff --git a/src/view/use-droppable-dimension-publisher/get-scroll.js b/src/view/use-droppable-publisher/get-scroll.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/get-scroll.js rename to src/view/use-droppable-publisher/get-scroll.js diff --git a/src/view/use-droppable-publisher/index.js b/src/view/use-droppable-publisher/index.js new file mode 100644 index 0000000000..c57336d89a --- /dev/null +++ b/src/view/use-droppable-publisher/index.js @@ -0,0 +1,2 @@ +// @flow +export { default } from './use-droppable-publisher'; diff --git a/src/view/use-droppable-dimension-publisher/is-in-fixed-container.js b/src/view/use-droppable-publisher/is-in-fixed-container.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/is-in-fixed-container.js rename to src/view/use-droppable-publisher/is-in-fixed-container.js diff --git a/src/view/use-droppable-dimension-publisher/use-droppable-dimension-publisher.js b/src/view/use-droppable-publisher/use-droppable-publisher.js similarity index 85% rename from src/view/use-droppable-dimension-publisher/use-droppable-dimension-publisher.js rename to src/view/use-droppable-publisher/use-droppable-publisher.js index 63a37a94f3..8714117f5c 100644 --- a/src/view/use-droppable-dimension-publisher/use-droppable-dimension-publisher.js +++ b/src/view/use-droppable-publisher/use-droppable-publisher.js @@ -6,21 +6,24 @@ import rafSchedule from 'raf-schd'; import { useMemo, useCallback } from 'use-memo-one'; import memoizeOne from 'memoize-one'; import checkForNestedScrollContainers from './check-for-nested-scroll-container'; +import * as dataAttr from '../data-attributes'; import { origin } from '../../state/position'; import getScroll from './get-scroll'; import type { - DimensionMarshal, + DroppableEntry, DroppableCallbacks, RecollectDroppableOptions, -} from '../../state/dimension-marshal/dimension-marshal-types'; +} from '../../state/registry/registry-types'; import getEnv, { type Env } from './get-env'; import type { + Id, DroppableId, TypeId, DroppableDimension, DroppableDescriptor, Direction, ScrollOptions, + DroppableMode, } from '../../types'; import getDimension from './get-dimension'; import AppContext, { type AppContextValue } from '../context/app-context'; @@ -30,10 +33,12 @@ import getListenerOptions from './get-listener-options'; import useRequiredContext from '../use-required-context'; import usePreviousRef from '../use-previous-ref'; import useLayoutEffect from '../use-isomorphic-layout-effect'; +import useUniqueId from '../use-unique-id'; type Props = {| droppableId: DroppableId, type: TypeId, + mode: DroppableMode, direction: Direction, isDropDisabled: boolean, isCombineEnabled: boolean, @@ -52,17 +57,21 @@ type WhileDragging = {| const getClosestScrollableFromDrag = (dragging: ?WhileDragging): ?Element => (dragging && dragging.env.closestScrollable) || null; -export default function useDroppableDimensionPublisher(args: Props) { +export default function useDroppablePublisher(args: Props) { const whileDraggingRef = useRef(null); const appContext: AppContextValue = useRequiredContext(AppContext); - const marshal: DimensionMarshal = appContext.marshal; + const uniqueId: Id = useUniqueId('droppable'); + const { registry, marshal } = appContext; const previousRef = usePreviousRef(args); - const descriptor = useMemo(() => { - return { + + const descriptor = useMemo( + () => ({ id: args.droppableId, type: args.type, - }; - }, [args.droppableId, args.type]); + mode: args.mode, + }), + [args.droppableId, args.mode, args.type], + ); const publishedDescriptorRef = useRef(descriptor); const memoizedUpdateScroll = useMemo( @@ -88,6 +97,7 @@ export default function useDroppableDimensionPublisher(args: Props) { }, []); const updateScroll = useCallback(() => { + // reading scroll value when called so value will be the latest const scroll: Position = getClosestScroll(); memoizedUpdateScroll(scroll.x, scroll.y); }, [getClosestScroll, memoizedUpdateScroll]); @@ -143,23 +153,29 @@ export default function useDroppableDimensionPublisher(args: Props) { shouldClipSubject: !previous.ignoreContainerClipping, }); - if (env.closestScrollable) { - // bind scroll listener + const scrollable: ?Element = env.closestScrollable; - env.closestScrollable.addEventListener( + if (scrollable) { + scrollable.setAttribute( + dataAttr.scrollContainer.contextId, + appContext.contextId, + ); + + // bind scroll listener + scrollable.addEventListener( 'scroll', onClosestScroll, getListenerOptions(dragging.scrollOptions), ); // print a debug warning if using an unsupported nested scroll container setup if (process.env.NODE_ENV !== 'production') { - checkForNestedScrollContainers(env.closestScrollable); + checkForNestedScrollContainers(scrollable); } } return dimension; }, - [descriptor, onClosestScroll, previousRef], + [appContext.contextId, descriptor, onClosestScroll, previousRef], ); const recollect = useCallback( (options: RecollectDroppableOptions): DroppableDimension => { @@ -206,6 +222,7 @@ export default function useDroppableDimensionPublisher(args: Props) { // unwatch scroll scheduleScrollUpdate.cancel(); + closest.removeAttribute(dataAttr.scrollContainer.contextId); closest.removeEventListener( 'scroll', onClosestScroll, @@ -234,12 +251,21 @@ export default function useDroppableDimensionPublisher(args: Props) { }; }, [dragStopped, getDimensionAndWatchScroll, recollect, scroll]); + const entry: DroppableEntry = useMemo( + () => ({ + uniqueId, + descriptor, + callbacks, + }), + [callbacks, descriptor, uniqueId], + ); + // Register with the marshal and let it know of: // - any descriptor changes // - when it unmounts useLayoutEffect(() => { - publishedDescriptorRef.current = descriptor; - marshal.registerDroppable(descriptor, callbacks); + publishedDescriptorRef.current = entry.descriptor; + registry.droppable.register(entry); return () => { if (whileDraggingRef.current) { @@ -249,9 +275,9 @@ export default function useDroppableDimensionPublisher(args: Props) { dragStopped(); } - marshal.unregisterDroppable(descriptor); + registry.droppable.unregister(entry); }; - }, [callbacks, descriptor, dragStopped, marshal]); + }, [callbacks, descriptor, dragStopped, entry, marshal, registry.droppable]); // update is enabled with the marshal // only need to update when there is a drag diff --git a/src/view/use-droppable-dimension-publisher/without-placeholder.js b/src/view/use-droppable-publisher/without-placeholder.js similarity index 100% rename from src/view/use-droppable-dimension-publisher/without-placeholder.js rename to src/view/use-droppable-publisher/without-placeholder.js diff --git a/src/view/use-focus-marshal/focus-marshal-types.js b/src/view/use-focus-marshal/focus-marshal-types.js new file mode 100644 index 0000000000..de176878f5 --- /dev/null +++ b/src/view/use-focus-marshal/focus-marshal-types.js @@ -0,0 +1,13 @@ +// @flow +import type { DraggableId } from '../../types'; + +export type Unregister = () => void; + +export type Register = (id: DraggableId, focus: () => void) => Unregister; + +export type FocusMarshal = {| + register: Register, + tryRecordFocus: (tryRecordFor: DraggableId) => void, + tryRestoreFocusRecorded: () => void, + tryShiftRecord: (previous: DraggableId, redirectTo: DraggableId) => void, +|}; diff --git a/src/view/use-focus-marshal/index.js b/src/view/use-focus-marshal/index.js new file mode 100644 index 0000000000..cb96ff715e --- /dev/null +++ b/src/view/use-focus-marshal/index.js @@ -0,0 +1,2 @@ +// @flow +export { default } from './use-focus-marshal'; diff --git a/src/view/use-focus-marshal/use-focus-marshal.js b/src/view/use-focus-marshal/use-focus-marshal.js new file mode 100644 index 0000000000..c14b8cc396 --- /dev/null +++ b/src/view/use-focus-marshal/use-focus-marshal.js @@ -0,0 +1,149 @@ +// @flow +import { useRef } from 'react'; +import { useMemo, useCallback } from 'use-memo-one'; +import type { DraggableId, ContextId } from '../../types'; +import type { FocusMarshal, Unregister } from './focus-marshal-types'; +import { dragHandle as dragHandleAttr } from '../data-attributes'; +import { warning } from '../../dev-warning'; +import useLayoutEffect from '../use-isomorphic-layout-effect'; +import { find, toArray } from '../../native-with-fallback'; +import isHtmlElement from '../is-type-of-element/is-html-element'; + +type Entry = {| + id: DraggableId, + focus: () => void, +|}; + +type EntryMap = { + [id: DraggableId]: Entry, +}; + +function getDragHandle( + contextId: ContextId, + draggableId: DraggableId, +): ?HTMLElement { + // find the drag handle + const selector: string = `[${dragHandleAttr.contextId}="${contextId}"]`; + const possible: Element[] = toArray(document.querySelectorAll(selector)); + + if (!possible.length) { + warning(`Unable to find any drag handles in the context "${contextId}"`); + return null; + } + + const handle: ?Element = find(possible, (el: Element): boolean => { + return el.getAttribute(dragHandleAttr.draggableId) === draggableId; + }); + + if (!handle) { + warning( + `Unable to find drag handle with id "${draggableId}" as no handle with a matching id was found`, + ); + return null; + } + + if (!isHtmlElement(handle)) { + warning('drag handle needs to be a HTMLElement'); + return null; + } + + return handle; +} + +export default function useFocusMarshal(contextId: ContextId): FocusMarshal { + const entriesRef = useRef({}); + const recordRef = useRef(null); + const restoreFocusFrameRef = useRef(null); + + const register = useCallback(function register( + id: DraggableId, + focus: () => void, + ): Unregister { + const entry: Entry = { id, focus }; + entriesRef.current[id] = entry; + + return function unregister() { + const entries: EntryMap = entriesRef.current; + const current: Entry = entries[id]; + // entry might have been overrided by another registration + if (current !== entry) { + delete entries[id]; + } + }; + }, + []); + + const tryGiveFocus = useCallback( + function tryGiveFocus(tryGiveFocusTo: DraggableId) { + const handle: ?HTMLElement = getDragHandle(contextId, tryGiveFocusTo); + + if (handle && handle !== document.activeElement) { + handle.focus(); + } + }, + [contextId], + ); + + const tryShiftRecord = useCallback(function tryShiftRecord( + previous: DraggableId, + redirectTo: DraggableId, + ) { + if (recordRef.current === previous) { + recordRef.current = redirectTo; + } + }, + []); + + const tryRestoreFocusRecorded = useCallback( + function tryRestoreFocusRecorded() { + restoreFocusFrameRef.current = requestAnimationFrame(() => { + restoreFocusFrameRef.current = null; + const record: ?DraggableId = recordRef.current; + if (record) { + tryGiveFocus(record); + } + }); + }, + [tryGiveFocus], + ); + + function tryRecordFocus(id: DraggableId) { + // clear any existing record + recordRef.current = null; + + const focused: ?Element = document.activeElement; + + // no item focused so it cannot be our item + if (!focused) { + return; + } + + // focused element is not a drag handle or does not have the right id + if (focused.getAttribute(dragHandleAttr.draggableId) !== id) { + return; + } + + recordRef.current = id; + } + + useLayoutEffect(() => { + return function clearFrameOnUnmount() { + const frameId: ?AnimationFrameID = restoreFocusFrameRef.current; + if (frameId) { + cancelAnimationFrame(frameId); + } + }; + }, []); + + const marshal: FocusMarshal = useMemo( + () => ({ + register, + tryRecordFocus, + tryRestoreFocusRecorded, + tryShiftRecord, + }), + [register, tryRestoreFocusRecorded, tryShiftRecord], + ); + + return marshal; +} diff --git a/src/view/use-lift-instruction/index.js b/src/view/use-lift-instruction/index.js new file mode 100644 index 0000000000..4b48aa83f7 --- /dev/null +++ b/src/view/use-lift-instruction/index.js @@ -0,0 +1,2 @@ +// @flow +export { default } from './use-lift-instruction'; diff --git a/src/view/use-lift-instruction/use-lift-instruction.js b/src/view/use-lift-instruction/use-lift-instruction.js new file mode 100644 index 0000000000..32728fd0af --- /dev/null +++ b/src/view/use-lift-instruction/use-lift-instruction.js @@ -0,0 +1,51 @@ +// @flow +import { useRef, useEffect } from 'react'; +import invariant from 'tiny-invariant'; +import { useMemo } from 'use-memo-one'; +import type { ContextId, ElementId } from '../../types'; +import getBodyElement from '../get-body-element'; +import visuallyHidden from '../visually-hidden-style'; + +export const getId = (contextId: ContextId): string => + `rbd-lift-instruction-${contextId}`; + +export default function useLiftInstruction( + contextId: ContextId, + liftInstruction: string, +): ElementId { + const id: string = useMemo(() => getId(contextId), [contextId]); + const ref = useRef(null); + + useEffect( + function mount() { + invariant(!ref.current, 'Description node already mounted'); + + const el: HTMLElement = document.createElement('div'); + ref.current = el; + + // identifier + el.id = id; + + // add the description text + el.textContent = liftInstruction; + + // hide the element visually + Object.assign(el.style, visuallyHidden); + + // Add to body + getBodyElement().appendChild(el); + + return function unmount() { + const toBeRemoved: ?HTMLElement = ref.current; + invariant(toBeRemoved, 'Cannot unmount description node'); + + // Remove from body + getBodyElement().removeChild(toBeRemoved); + ref.current = null; + }; + }, + [id, liftInstruction], + ); + + return id; +} diff --git a/src/view/use-sensor-marshal/closest.js b/src/view/use-sensor-marshal/closest.js new file mode 100644 index 0000000000..550a8ddb8f --- /dev/null +++ b/src/view/use-sensor-marshal/closest.js @@ -0,0 +1,50 @@ +// @flow +import { find } from '../../native-with-fallback'; + +const supportedMatchesName: string = ((): string => { + const base: string = 'matches'; + + // Server side rendering + if (typeof document === 'undefined') { + return base; + } + + // See https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API + const candidates: string[] = [ + base, + 'msMatchesSelector', + 'webkitMatchesSelector', + ]; + + const value: ?string = find( + candidates, + (name: string): boolean => name in Element.prototype, + ); + + return value || base; +})(); + +function closestPonyfill(el: ?Element, selector: string) { + if (el == null) { + return null; + } + + // Element.prototype.matches is supported in ie11 with a different name + // https://caniuse.com/#feat=matchesselector + // $FlowFixMe - dynamic property + if (el[supportedMatchesName](selector)) { + return el; + } + + // recursively look up the tree + return closestPonyfill(el.parentElement, selector); +} + +export default function closest(el: Element, selector: string): ?Element { + // Using native closest for maximum speed where we can + // if (el.closest) { + // return el.closest(selector); + // } + // ie11: damn you! + return closestPonyfill(el, selector); +} diff --git a/src/view/use-sensor-marshal/index.js b/src/view/use-sensor-marshal/index.js new file mode 100644 index 0000000000..7bb70be854 --- /dev/null +++ b/src/view/use-sensor-marshal/index.js @@ -0,0 +1,2 @@ +// @flow +export { default } from './use-sensor-marshal'; diff --git a/src/view/use-drag-handle/util/should-allow-dragging-from-target.js b/src/view/use-sensor-marshal/is-event-in-interactive-element.js similarity index 71% rename from src/view/use-drag-handle/util/should-allow-dragging-from-target.js rename to src/view/use-sensor-marshal/is-event-in-interactive-element.js index fe43adce04..39288cca73 100644 --- a/src/view/use-drag-handle/util/should-allow-dragging-from-target.js +++ b/src/view/use-sensor-marshal/is-event-in-interactive-element.js @@ -1,5 +1,5 @@ // @flow -import isElement from '../../is-type-of-element/is-element'; +import isHtmlElement from '../is-type-of-element/is-html-element'; export type TagNameMap = { [tagName: string]: true, @@ -16,10 +16,7 @@ export const interactiveTagNames: TagNameMap = { audio: true, }; -const isAnInteractiveElement = ( - parent: Element, - current: ?Element, -): boolean => { +function isAnInteractiveElement(parent: Element, current: ?Element) { if (current == null) { return false; } @@ -53,20 +50,17 @@ const isAnInteractiveElement = ( // recursion to check parent return isAnInteractiveElement(parent, current.parentElement); -}; - -export default (event: Event, canDragInteractiveElements: boolean): boolean => { - // Allowing drag with all element types - if (canDragInteractiveElements) { - return true; - } +} - const { target, currentTarget } = event; +export default function isEventInInteractiveElement( + draggable: Element, + event: Event, +): boolean { + const target: EventTarget = event.target; - // Technically target and currentTarget are EventTarget's and do not have to be elements - if (!isElement(target) || !isElement(currentTarget)) { - return true; + if (!isHtmlElement(target)) { + return false; } - return !isAnInteractiveElement(currentTarget, target); -}; + return isAnInteractiveElement(draggable, target); +} diff --git a/src/view/use-sensor-marshal/lock.js b/src/view/use-sensor-marshal/lock.js new file mode 100644 index 0000000000..a88f93db46 --- /dev/null +++ b/src/view/use-sensor-marshal/lock.js @@ -0,0 +1,48 @@ +// @flow +import invariant from 'tiny-invariant'; + +export type Lock = {| + abandon: () => void, +|}; + +export type LockAPI = {| + isClaimed: () => boolean, + isActive: (lock: Lock) => boolean, + claim: (abandon: () => void) => Lock, + release: () => void, + tryAbandon: () => void, +|}; + +export default function create(): LockAPI { + let lock: ?Lock = null; + + function isClaimed(): boolean { + return Boolean(lock); + } + + function isActive(value: Lock): boolean { + return value === lock; + } + + function claim(abandon: () => void): Lock { + invariant(!lock, 'Cannot claim lock as it is already claimed'); + const newLock: Lock = { abandon }; + // update singleton + lock = newLock; + // return lock + return newLock; + } + function release() { + invariant(lock, 'Cannot release lock when there is no lock'); + lock = null; + } + + function tryAbandon() { + if (lock) { + lock.abandon(); + release(); + } + } + + return { isClaimed, isActive, claim, release, tryAbandon }; +} diff --git a/src/view/use-sensor-marshal/sensors/use-keyboard-sensor.js b/src/view/use-sensor-marshal/sensors/use-keyboard-sensor.js new file mode 100644 index 0000000000..f2c55beed6 --- /dev/null +++ b/src/view/use-sensor-marshal/sensors/use-keyboard-sensor.js @@ -0,0 +1,243 @@ +// @flow +import invariant from 'tiny-invariant'; +import { useRef } from 'react'; +import { useMemo, useCallback } from 'use-memo-one'; +import type { + SensorAPI, + PreDragActions, + SnapDragActions, + DraggableId, +} from '../../../types'; +import type { + EventBinding, + EventOptions, +} from '../../event-bindings/event-types'; +import * as keyCodes from '../../key-codes'; +import bindEvents from '../../event-bindings/bind-events'; +import preventStandardKeyEvents from './util/prevent-standard-key-events'; +import supportedPageVisibilityEventName from './util/supported-page-visibility-event-name'; +import useLayoutEffect from '../../use-isomorphic-layout-effect'; + +function noop() {} + +type KeyMap = { + [key: number]: true, +}; + +const scrollJumpKeys: KeyMap = { + [keyCodes.pageDown]: true, + [keyCodes.pageUp]: true, + [keyCodes.home]: true, + [keyCodes.end]: true, +}; + +function getDraggingBindings( + actions: SnapDragActions, + stop: () => void, +): EventBinding[] { + function cancel() { + stop(); + actions.cancel(); + } + + function drop() { + stop(); + actions.drop(); + } + + return [ + { + eventName: 'keydown', + fn: (event: KeyboardEvent) => { + if (event.keyCode === keyCodes.escape) { + event.preventDefault(); + cancel(); + return; + } + + // Dropping + if (event.keyCode === keyCodes.space) { + // need to stop parent Draggable's thinking this is a lift + event.preventDefault(); + drop(); + return; + } + + // Movement + + if (event.keyCode === keyCodes.arrowDown) { + event.preventDefault(); + actions.moveDown(); + return; + } + + if (event.keyCode === keyCodes.arrowUp) { + event.preventDefault(); + actions.moveUp(); + return; + } + + if (event.keyCode === keyCodes.arrowRight) { + event.preventDefault(); + actions.moveRight(); + return; + } + + if (event.keyCode === keyCodes.arrowLeft) { + event.preventDefault(); + actions.moveLeft(); + return; + } + + // preventing scroll jumping at this time + if (scrollJumpKeys[event.keyCode]) { + event.preventDefault(); + return; + } + + preventStandardKeyEvents(event); + }, + }, + // any mouse actions kills a drag + { + eventName: 'mousedown', + fn: cancel, + }, + { + eventName: 'mouseup', + fn: cancel, + }, + { + eventName: 'click', + fn: cancel, + }, + { + eventName: 'touchstart', + fn: cancel, + }, + // resizing the browser kills a drag + { + eventName: 'resize', + fn: cancel, + }, + // kill if the user is using the mouse wheel + // We are not supporting wheel / trackpad scrolling with keyboard dragging + { + eventName: 'wheel', + fn: cancel, + // chrome says it is a violation for this to not be passive + // it is fine for it to be passive as we just cancel as soon as we get + // any event + options: { passive: true }, + }, + // Cancel on page visibility change + { + eventName: supportedPageVisibilityEventName, + fn: cancel, + }, + ]; +} + +export default function useKeyboardSensor(api: SensorAPI) { + const unbindEventsRef = useRef<() => void>(noop); + + const startCaptureBinding: EventBinding = useMemo( + () => ({ + eventName: 'keydown', + fn: function onKeyDown(event: KeyboardEvent) { + // Event already used + if (event.defaultPrevented) { + return; + } + + // Need to start drag with a spacebar press + if (event.keyCode !== keyCodes.space) { + return; + } + + const draggableId: ?DraggableId = api.findClosestDraggableId(event); + + if (!draggableId) { + return; + } + + const preDrag: ?PreDragActions = api.tryGetLock( + draggableId, + // abort function not defined yet + // eslint-disable-next-line no-use-before-define + stop, + { sourceEvent: event }, + ); + + // Cannot start capturing at this time + if (!preDrag) { + return; + } + + // we are consuming the event + event.preventDefault(); + let isCapturing: boolean = true; + + // There is no pending period for a keyboard drag + // We can lift immediately + const actions: SnapDragActions = preDrag.snapLift(); + + // unbind this listener + unbindEventsRef.current(); + + // setup our function to end everything + function stop() { + invariant( + isCapturing, + 'Cannot stop capturing a keyboard drag when not capturing', + ); + isCapturing = false; + + // unbind dragging bindings + unbindEventsRef.current(); + // start listening for capture again + // eslint-disable-next-line no-use-before-define + listenForCapture(); + } + + // bind dragging listeners + unbindEventsRef.current = bindEvents( + window, + getDraggingBindings(actions, stop), + { capture: true, passive: false }, + ); + }, + }), + // not including startPendingDrag as it is not defined initially + // eslint-disable-next-line react-hooks/exhaustive-deps + [api], + ); + + const listenForCapture = useCallback( + function tryStartCapture() { + const options: EventOptions = { + passive: false, + capture: true, + }; + + unbindEventsRef.current = bindEvents( + window, + [startCaptureBinding], + options, + ); + }, + [startCaptureBinding], + ); + + useLayoutEffect( + function mount() { + listenForCapture(); + + // kill any pending window events when unmounting + return function unmount() { + unbindEventsRef.current(); + }; + }, + [listenForCapture], + ); +} diff --git a/src/view/use-sensor-marshal/sensors/use-mouse-sensor.js b/src/view/use-sensor-marshal/sensors/use-mouse-sensor.js new file mode 100644 index 0000000000..a191687478 --- /dev/null +++ b/src/view/use-sensor-marshal/sensors/use-mouse-sensor.js @@ -0,0 +1,384 @@ +// @flow +import invariant from 'tiny-invariant'; +import { useRef } from 'react'; +import { useCallback, useMemo } from 'use-memo-one'; +import type { Position } from 'css-box-model'; +import type { + PreDragActions, + FluidDragActions, + DraggableId, + SensorAPI, + DraggableOptions, +} from '../../../types'; +import type { + EventBinding, + EventOptions, +} from '../../event-bindings/event-types'; +import bindEvents from '../../event-bindings/bind-events'; +import * as keyCodes from '../../key-codes'; +import preventStandardKeyEvents from './util/prevent-standard-key-events'; +import supportedPageVisibilityEventName from './util/supported-page-visibility-event-name'; +import useLayoutEffect from '../../use-isomorphic-layout-effect'; +import { noop } from '../../../empty'; + +// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button +export const primaryButton: number = 0; +export const sloppyClickThreshold: number = 5; + +function isSloppyClickThresholdExceeded( + original: Position, + current: Position, +): boolean { + return ( + Math.abs(current.x - original.x) >= sloppyClickThreshold || + Math.abs(current.y - original.y) >= sloppyClickThreshold + ); +} +type Idle = {| + type: 'IDLE', +|}; + +type Pending = {| + type: 'PENDING', + point: Position, + actions: PreDragActions, +|}; + +type Dragging = {| + type: 'DRAGGING', + actions: FluidDragActions, +|}; + +type Phase = Idle | Pending | Dragging; + +const idle: Idle = { type: 'IDLE' }; + +type GetCaptureArgs = {| + cancel: () => void, + completed: () => void, + getPhase: () => Phase, + setPhase: (phase: Phase) => void, +|}; + +function getCaptureBindings({ + cancel, + completed, + getPhase, + setPhase, +}: GetCaptureArgs): EventBinding[] { + return [ + { + eventName: 'mousemove', + fn: (event: MouseEvent) => { + const { button, clientX, clientY } = event; + if (button !== primaryButton) { + return; + } + + const point: Position = { + x: clientX, + y: clientY, + }; + + const phase: Phase = getPhase(); + + // Already dragging + if (phase.type === 'DRAGGING') { + // preventing default as we are using this event + event.preventDefault(); + phase.actions.move(point); + return; + } + + // There should be a pending drag at this point + invariant(phase.type === 'PENDING', 'Cannot be IDLE'); + const pending: Position = phase.point; + + // threshold not yet exceeded + if (!isSloppyClickThresholdExceeded(pending, point)) { + return; + } + + // preventing default as we are using this event + event.preventDefault(); + + const actions: FluidDragActions = phase.actions.fluidLift(pending); + + setPhase({ + type: 'DRAGGING', + actions, + }); + }, + }, + { + eventName: 'mouseup', + fn: (event: MouseEvent) => { + const phase: Phase = getPhase(); + + if (phase.type !== 'DRAGGING') { + cancel(); + return; + } + + // preventing default as we are using this event + event.preventDefault(); + phase.actions.drop({ shouldBlockNextClick: true }); + completed(); + }, + }, + { + eventName: 'mousedown', + fn: (event: MouseEvent) => { + // this can happen during a drag when the user clicks a button + // other than the primary mouse button + if (getPhase().type === 'DRAGGING') { + event.preventDefault(); + } + + cancel(); + }, + }, + { + eventName: 'keydown', + fn: (event: KeyboardEvent) => { + const phase: Phase = getPhase(); + // Abort if any keystrokes while a drag is pending + if (phase.type === 'PENDING') { + cancel(); + return; + } + + // cancelling a drag + if (event.keyCode === keyCodes.escape) { + event.preventDefault(); + cancel(); + return; + } + + preventStandardKeyEvents(event); + }, + }, + { + eventName: 'resize', + fn: cancel, + }, + { + eventName: 'scroll', + // kill a pending drag if there is a window scroll + options: { passive: true, capture: false }, + fn: () => { + if (getPhase().type === 'PENDING') { + cancel(); + } + }, + }, + + // Need to opt out of dragging if the user is a force press + // Only for safari which has decided to introduce its own custom way of doing things + // https://developer.apple.com/library/content/documentation/AppleApplications/Conceptual/SafariJSProgTopics/RespondingtoForceTouchEventsfromJavaScript.html + { + eventName: 'webkitmouseforcedown', + // it is considered a indirect cancel so we do not + // prevent default in any situation. + fn: (event: Event) => { + const phase: Phase = getPhase(); + invariant(phase.type !== 'IDLE', 'Unexpected phase'); + + if (phase.actions.shouldRespectForcePress()) { + cancel(); + return; + } + + // This technically doesn't do anything. + // It won't do anything if `webkitmouseforcewillbegin` is prevented. + // But it is a good signal that we want to opt out of this + + event.preventDefault(); + }, + }, + // Cancel on page visibility change + { + eventName: supportedPageVisibilityEventName, + fn: cancel, + }, + ]; +} + +export default function useMouseSensor(api: SensorAPI) { + const phaseRef = useRef(idle); + const unbindEventsRef = useRef<() => void>(noop); + + const startCaptureBinding: EventBinding = useMemo( + () => ({ + eventName: 'mousedown', + fn: function onMouseDown(event: MouseEvent) { + // Event already used + if (event.defaultPrevented) { + return; + } + // only starting a drag if dragging with the primary mouse button + if (event.button !== primaryButton) { + return; + } + + // Do not start a drag if any modifier key is pressed + if (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) { + return; + } + + const draggableId: ?DraggableId = api.findClosestDraggableId(event); + + if (!draggableId) { + return; + } + + const actions: ?PreDragActions = api.tryGetLock( + draggableId, + // stop is defined later + // eslint-disable-next-line no-use-before-define + stop, + { sourceEvent: event }, + ); + + if (!actions) { + return; + } + + // consuming the event + event.preventDefault(); + + const point: Position = { + x: event.clientX, + y: event.clientY, + }; + + // unbind this listener + unbindEventsRef.current(); + // using this function before it is defined as their is a circular usage pattern + // eslint-disable-next-line no-use-before-define + startPendingDrag(actions, point); + }, + }), + // not including startPendingDrag as it is not defined initially + // eslint-disable-next-line react-hooks/exhaustive-deps + [api], + ); + + const preventForcePressBinding: EventBinding = useMemo( + () => ({ + eventName: 'webkitmouseforcewillbegin', + fn: (event: Event) => { + if (event.defaultPrevented) { + return; + } + + const id: ?DraggableId = api.findClosestDraggableId(event); + + if (!id) { + return; + } + + const options: ?DraggableOptions = api.findOptionsForDraggable(id); + + if (!options) { + return; + } + + if (options.shouldRespectForcePress) { + return; + } + + if (!api.canGetLock(id)) { + return; + } + + event.preventDefault(); + }, + }), + [api], + ); + + const listenForCapture = useCallback( + function listenForCapture() { + const options: EventOptions = { + passive: false, + capture: true, + }; + + unbindEventsRef.current = bindEvents( + window, + [preventForcePressBinding, startCaptureBinding], + options, + ); + }, + [preventForcePressBinding, startCaptureBinding], + ); + + const stop = useCallback(() => { + const current: Phase = phaseRef.current; + if (current.type === 'IDLE') { + return; + } + + phaseRef.current = idle; + unbindEventsRef.current(); + + listenForCapture(); + }, [listenForCapture]); + + const cancel = useCallback(() => { + const phase: Phase = phaseRef.current; + stop(); + if (phase.type === 'DRAGGING') { + phase.actions.cancel({ shouldBlockNextClick: true }); + } + if (phase.type === 'PENDING') { + phase.actions.abort(); + } + }, [stop]); + + const bindCapturingEvents = useCallback( + function bindCapturingEvents() { + const options = { capture: true, passive: false }; + const bindings: EventBinding[] = getCaptureBindings({ + cancel, + completed: stop, + getPhase: () => phaseRef.current, + setPhase: (phase: Phase) => { + phaseRef.current = phase; + }, + }); + + unbindEventsRef.current = bindEvents(window, bindings, options); + }, + [cancel, stop], + ); + + const startPendingDrag = useCallback( + function startPendingDrag(actions: PreDragActions, point: Position) { + invariant( + phaseRef.current.type === 'IDLE', + 'Expected to move from IDLE to PENDING drag', + ); + phaseRef.current = { + type: 'PENDING', + point, + actions, + }; + bindCapturingEvents(); + }, + [bindCapturingEvents], + ); + + useLayoutEffect( + function mount() { + listenForCapture(); + + // kill any pending window events when unmounting + return function unmount() { + unbindEventsRef.current(); + }; + }, + [listenForCapture], + ); +} diff --git a/src/view/use-sensor-marshal/sensors/use-touch-sensor.js b/src/view/use-sensor-marshal/sensors/use-touch-sensor.js new file mode 100644 index 0000000000..b1a12a3ad2 --- /dev/null +++ b/src/view/use-sensor-marshal/sensors/use-touch-sensor.js @@ -0,0 +1,464 @@ +// @flow +import invariant from 'tiny-invariant'; +import { useRef } from 'react'; +import { useCallback, useMemo } from 'use-memo-one'; +import type { Position } from 'css-box-model'; +import type { + DraggableId, + SensorAPI, + PreDragActions, + FluidDragActions, +} from '../../../types'; +import type { + EventBinding, + EventOptions, +} from '../../event-bindings/event-types'; +import bindEvents from '../../event-bindings/bind-events'; +import * as keyCodes from '../../key-codes'; +import supportedPageVisibilityEventName from './util/supported-page-visibility-event-name'; +import { noop } from '../../../empty'; +import useLayoutEffect from '../../use-isomorphic-layout-effect'; +import isHtmlElement from '../../is-type-of-element/is-html-element'; + +type TouchWithForce = Touch & { + force: number, +}; + +type Idle = {| + type: 'IDLE', +|}; + +type Pending = {| + type: 'PENDING', + point: Position, + actions: PreDragActions, + longPressTimerId: TimeoutID, +|}; + +type Dragging = {| + type: 'DRAGGING', + actions: FluidDragActions, + hasMoved: boolean, +|}; + +type Phase = Idle | Pending | Dragging; + +const idle: Idle = { type: 'IDLE' }; +// Decreased from 150 as a work around for an issue for forcepress on iOS +// https://github.com/atlassian/react-beautiful-dnd/issues/1401 +export const timeForLongPress: number = 120; +export const forcePressThreshold: number = 0.15; + +type GetBindingArgs = {| + cancel: () => void, + completed: () => void, + getPhase: () => Phase, +|}; + +function getWindowBindings({ + cancel, + getPhase, +}: GetBindingArgs): EventBinding[] { + return [ + // If the orientation of the device changes - kill the drag + // https://davidwalsh.name/orientation-change + { + eventName: 'orientationchange', + fn: cancel, + }, + // some devices fire resize if the orientation changes + { + eventName: 'resize', + fn: cancel, + }, + // Long press can bring up a context menu + // need to opt out of this behavior + { + eventName: 'contextmenu', + fn: (event: Event) => { + // always opting out of context menu events + event.preventDefault(); + }, + }, + // On some devices it is possible to have a touch interface with a keyboard. + // On any keyboard event we cancel a touch drag + { + eventName: 'keydown', + fn: (event: KeyboardEvent) => { + if (getPhase().type !== 'DRAGGING') { + cancel(); + return; + } + + // direct cancel: we are preventing the default action + // indirect cancel: we are not preventing the default action + + // escape is a direct cancel + if (event.keyCode === keyCodes.escape) { + event.preventDefault(); + } + cancel(); + }, + }, + // Cancel on page visibility change + { + eventName: supportedPageVisibilityEventName, + fn: cancel, + }, + ]; +} + +// All of the touch events get applied to the initial target of the touch interaction +// This plays well with the target being unmounted during a drag +function getTargetBindings({ + cancel, + completed, + getPhase, +}: GetBindingArgs): EventBinding[] { + return [ + { + eventName: 'touchmove', + // Opting out of passive touchmove (default) so as to prevent scrolling while moving + // Not worried about performance as effect of move is throttled in requestAnimationFrame + // Using `capture: false` due to a recent horrible firefox bug: https://twitter.com/alexandereardon/status/1125904207184187393 + options: { capture: false }, + fn: (event: TouchEvent) => { + const phase: Phase = getPhase(); + // Drag has not yet started and we are waiting for a long press. + if (phase.type !== 'DRAGGING') { + cancel(); + return; + } + + // At this point we are dragging + phase.hasMoved = true; + + const { clientX, clientY } = event.touches[0]; + + const point: Position = { + x: clientX, + y: clientY, + }; + + // We need to prevent the default event in order to block native scrolling + // Also because we are using it as part of a drag we prevent the default action + // as a sign that we are using the event + event.preventDefault(); + phase.actions.move(point); + }, + }, + { + eventName: 'touchend', + fn: (event: TouchEvent) => { + const phase: Phase = getPhase(); + // drag had not started yet - do not prevent the default action + if (phase.type !== 'DRAGGING') { + cancel(); + return; + } + + // ending the drag + event.preventDefault(); + phase.actions.drop({ shouldBlockNextClick: true }); + completed(); + }, + }, + { + eventName: 'touchcancel', + fn: (event: TouchEvent) => { + // drag had not started yet - do not prevent the default action + if (getPhase().type !== 'DRAGGING') { + cancel(); + return; + } + + // already dragging - this event is directly ending a drag + event.preventDefault(); + cancel(); + }, + }, + // Need to opt out of dragging if the user is a force press + // Only for webkit which has decided to introduce its own custom way of doing things + // https://developer.apple.com/library/content/documentation/AppleApplications/Conceptual/SafariJSProgTopics/RespondingtoForceTouchEventsfromJavaScript.html + { + eventName: 'touchforcechange', + fn: (event: TouchEvent) => { + const phase: Phase = getPhase(); + + // needed to use phase.actions + invariant(phase.type !== 'IDLE'); + + // This is not fantastic logic, but it is done to account for + // and issue with forcepress on iOS + // Calling event.preventDefault() will currently opt out of scrolling and clicking + // https://github.com/atlassian/react-beautiful-dnd/issues/1401 + + const touch: TouchWithForce = (event.touches[0]: any); + const isForcePress: boolean = touch.force >= forcePressThreshold; + + if (!isForcePress) { + return; + } + + const shouldRespect: boolean = phase.actions.shouldRespectForcePress(); + + if (phase.type === 'PENDING') { + if (shouldRespect) { + cancel(); + } + // If not respecting we just let the event go through + // It will not have an impact on the browser until + // there has been a sufficient time ellapsed + return; + } + + // 'DRAGGING' + + if (shouldRespect) { + if (phase.hasMoved) { + // After the user has moved we do not allow the dragging item to be force pressed + // This prevents strange behaviour such as a link preview opening mid drag + event.preventDefault(); + return; + } + // indirect cancel + cancel(); + return; + } + + // not respecting during a drag + event.preventDefault(); + }, + }, + // Cancel on page visibility change + { + eventName: supportedPageVisibilityEventName, + fn: cancel, + }, + // Not adding a cancel on touchstart as this handler will pick up the initial touchstart event + ]; +} + +export default function useMouseSensor(api: SensorAPI) { + const phaseRef = useRef(idle); + const unbindEventsRef = useRef<() => void>(noop); + + const getPhase = useCallback(function getPhase(): Phase { + return phaseRef.current; + }, []); + + const setPhase = useCallback(function setPhase(phase: Phase) { + phaseRef.current = phase; + }, []); + + const startCaptureBinding: EventBinding = useMemo( + () => ({ + eventName: 'touchstart', + fn: function onTouchStart(event: TouchEvent) { + // Event already used by something else + if (event.defaultPrevented) { + return; + } + + // We need to NOT call event.preventDefault() so as to maintain as much standard + // browser interactions as possible. + // This includes navigation on anchors which we want to preserve + + const draggableId: ?DraggableId = api.findClosestDraggableId(event); + + if (!draggableId) { + return; + } + + const actions: ?PreDragActions = api.tryGetLock( + draggableId, + // eslint-disable-next-line no-use-before-define + stop, + { sourceEvent: event }, + ); + + // could not start a drag + if (!actions) { + return; + } + + const touch: Touch = event.touches[0]; + const { clientX, clientY } = touch; + const point: Position = { + x: clientX, + y: clientY, + }; + const target: EventTarget = event.target; + invariant( + isHtmlElement(target), + 'Expected touch target to be an element', + ); + + // unbind this event handler + unbindEventsRef.current(); + + // eslint-disable-next-line no-use-before-define + startPendingDrag(actions, point, target); + }, + }), + // not including stop or startPendingDrag as it is not defined initially + // eslint-disable-next-line react-hooks/exhaustive-deps + [api], + ); + + const listenForCapture = useCallback( + function listenForCapture() { + const options: EventOptions = { + capture: true, + passive: false, + }; + + unbindEventsRef.current = bindEvents( + window, + [startCaptureBinding], + options, + ); + }, + [startCaptureBinding], + ); + + const stop = useCallback(() => { + const current: Phase = phaseRef.current; + if (current.type === 'IDLE') { + return; + } + + // aborting any pending drag + if (current.type === 'PENDING') { + clearTimeout(current.longPressTimerId); + } + + setPhase(idle); + unbindEventsRef.current(); + + listenForCapture(); + }, [listenForCapture, setPhase]); + + const cancel = useCallback(() => { + const phase: Phase = phaseRef.current; + stop(); + if (phase.type === 'DRAGGING') { + phase.actions.cancel({ shouldBlockNextClick: true }); + } + if (phase.type === 'PENDING') { + phase.actions.abort(); + } + }, [stop]); + + const bindCapturingEvents = useCallback( + function bindCapturingEvents(target: HTMLElement) { + const options: EventOptions = { capture: true, passive: false }; + const args: GetBindingArgs = { + cancel, + completed: stop, + getPhase, + }; + + // When removing a drag handle, such as moving into a portal or clone, + // touch events stop being published to the window. + // Even though the handle is removed, if you attach events to it they will + // continue to fire for the interaction. Strange, but hey - that's the web + // https://gist.github.com/parris/dda613e3ae78f14eb2dc9fa0f4bfce3d + // https://stackoverflow.com/questions/33298828/touch-move-event-dont-fire-after-touch-start-target-is-removed + const unbindTarget = bindEvents(target, getTargetBindings(args), options); + const unbindWindow = bindEvents(window, getWindowBindings(args), options); + + unbindEventsRef.current = function unbindAll() { + unbindTarget(); + unbindWindow(); + }; + }, + [cancel, getPhase, stop], + ); + + const startDragging = useCallback( + function startDragging() { + const phase: Phase = getPhase(); + invariant( + phase.type === 'PENDING', + `Cannot start dragging from phase ${phase.type}`, + ); + + const actions: FluidDragActions = phase.actions.fluidLift(phase.point); + + setPhase({ + type: 'DRAGGING', + actions, + hasMoved: false, + }); + }, + [getPhase, setPhase], + ); + + const startPendingDrag = useCallback( + function startPendingDrag( + actions: PreDragActions, + point: Position, + target: HTMLElement, + ) { + invariant( + getPhase().type === 'IDLE', + 'Expected to move from IDLE to PENDING drag', + ); + + const longPressTimerId: TimeoutID = setTimeout( + startDragging, + timeForLongPress, + ); + + setPhase({ + type: 'PENDING', + point, + actions, + longPressTimerId, + }); + + bindCapturingEvents(target); + }, + [bindCapturingEvents, getPhase, setPhase, startDragging], + ); + + useLayoutEffect( + function mount() { + listenForCapture(); + + return function unmount() { + // remove any existing listeners + unbindEventsRef.current(); + + // need to kill any pending drag start timer + const phase: Phase = getPhase(); + if (phase.type === 'PENDING') { + clearTimeout(phase.longPressTimerId); + setPhase(idle); + } + }; + }, + [getPhase, listenForCapture, setPhase], + ); + + // This is needed for safari + // Simply adding a non capture, non passive 'touchmove' listener. + // This forces event.preventDefault() in dynamically added + // touchmove event handlers to actually work + // https://github.com/atlassian/react-beautiful-dnd/issues/1374 + useLayoutEffect(function webkitHack() { + const unbind = bindEvents(window, [ + { + eventName: 'touchmove', + // using a new noop function for each usage as a single `removeEventListener()` + // call will remove all handlers with the same reference + // https://codesandbox.io/s/removing-multiple-handlers-with-same-reference-fxe15 + fn: () => {}, + options: { capture: false, passive: false }, + }, + ]); + + return unbind; + }, []); +} diff --git a/src/view/use-drag-handle/util/prevent-standard-key-events.js b/src/view/use-sensor-marshal/sensors/util/prevent-standard-key-events.js similarity index 85% rename from src/view/use-drag-handle/util/prevent-standard-key-events.js rename to src/view/use-sensor-marshal/sensors/util/prevent-standard-key-events.js index c4f30a6576..f7865b2e6e 100644 --- a/src/view/use-drag-handle/util/prevent-standard-key-events.js +++ b/src/view/use-sensor-marshal/sensors/util/prevent-standard-key-events.js @@ -1,5 +1,5 @@ // @flow -import * as keyCodes from '../../key-codes'; +import * as keyCodes from '../../../key-codes'; type KeyMap = { [key: number]: true, diff --git a/src/view/use-drag-handle/util/supported-page-visibility-event-name.js b/src/view/use-sensor-marshal/sensors/util/supported-page-visibility-event-name.js similarity index 91% rename from src/view/use-drag-handle/util/supported-page-visibility-event-name.js rename to src/view/use-sensor-marshal/sensors/util/supported-page-visibility-event-name.js index 970536a8d3..4f1379968e 100644 --- a/src/view/use-drag-handle/util/supported-page-visibility-event-name.js +++ b/src/view/use-sensor-marshal/sensors/util/supported-page-visibility-event-name.js @@ -1,5 +1,5 @@ // @flow -import { find } from '../../../native-with-fallback'; +import { find } from '../../../../native-with-fallback'; const supportedEventName: string = ((): string => { const base: string = 'visibilitychange'; diff --git a/src/view/use-sensor-marshal/try-get-closest-draggable-id-from-event.js b/src/view/use-sensor-marshal/try-get-closest-draggable-id-from-event.js new file mode 100644 index 0000000000..2d2627ef4e --- /dev/null +++ b/src/view/use-sensor-marshal/try-get-closest-draggable-id-from-event.js @@ -0,0 +1,31 @@ +// @flow +import type { ContextId, DraggableId } from '../../types'; +import * as attributes from '../data-attributes'; +import closest from './closest'; +import isHtmlElement from '../is-type-of-element/is-html-element'; +import { warning } from '../../dev-warning'; + +function getSelector(contextId: ContextId): string { + return `[${attributes.dragHandle.contextId}="${contextId}"]`; +} + +export default function tryGetClosestDraggableIdFromEvent( + contextId: ContextId, + event: Event, +): ?DraggableId { + const target: ?EventTarget = event.target; + + if (!isHtmlElement(target)) { + warning('event.target must be a HTMLElement'); + return null; + } + + const selector: string = getSelector(contextId); + const handle: ?Element = closest(target, selector); + + if (!handle) { + return null; + } + + return handle.getAttribute(attributes.dragHandle.draggableId); +} diff --git a/src/view/use-sensor-marshal/try-get-draggable.js b/src/view/use-sensor-marshal/try-get-draggable.js new file mode 100644 index 0000000000..007828c7b5 --- /dev/null +++ b/src/view/use-sensor-marshal/try-get-draggable.js @@ -0,0 +1,30 @@ +// @flow +import type { DraggableId, ContextId } from '../../types'; +import * as attributes from '../data-attributes'; +import { find, toArray } from '../../native-with-fallback'; +import { warning } from '../../dev-warning'; +import isHtmlElement from '../is-type-of-element/is-html-element'; + +export default function tryGetDraggable( + contextId: ContextId, + draggableId: DraggableId, +): ?HTMLElement { + // cannot create a selector with the draggable id as it might not be a valid attribute selector + const selector: string = `[${attributes.draggable.contextId}="${contextId}"]`; + const possible: Element[] = toArray(document.querySelectorAll(selector)); + + const draggable: ?Element = find(possible, (el: Element): boolean => { + return el.getAttribute(attributes.draggable.id) === draggableId; + }); + + if (!draggable) { + return null; + } + + if (!isHtmlElement(draggable)) { + warning('Draggable element is not a HTMLElement'); + return null; + } + + return draggable; +} diff --git a/src/view/use-sensor-marshal/use-sensor-marshal.js b/src/view/use-sensor-marshal/use-sensor-marshal.js new file mode 100644 index 0000000000..8854131eda --- /dev/null +++ b/src/view/use-sensor-marshal/use-sensor-marshal.js @@ -0,0 +1,469 @@ +// @flow +import rafSchd from 'raf-schd'; +import invariant from 'tiny-invariant'; +import { useState } from 'react'; +import { useCallback, useMemo } from 'use-memo-one'; +import type { Position } from 'css-box-model'; +import type { + ContextId, + State, + Sensor, + StopDragOptions, + PreDragActions, + FluidDragActions, + SnapDragActions, + DraggableId, + SensorAPI, + TryGetLock, + TryGetLockOptions, + DraggableOptions, +} from '../../types'; +import create, { type Lock, type LockAPI } from './lock'; +import type { Store, Action } from '../../state/store-types'; +import canStartDrag from '../../state/can-start-drag'; +import { + move as moveAction, + moveUp as moveUpAction, + moveRight as moveRightAction, + moveDown as moveDownAction, + moveLeft as moveLeftAction, + drop as dropAction, + lift as liftAction, + type LiftArgs as LiftActionArgs, +} from '../../state/action-creators'; +import type { + Registry, + DraggableEntry, +} from '../../state/registry/registry-types'; +import useMouseSensor from './sensors/use-mouse-sensor'; +import useKeyboardSensor from './sensors/use-keyboard-sensor'; +import useTouchSensor from './sensors/use-touch-sensor'; +import useValidateSensorHooks from './use-validate-sensor-hooks'; +import isEventInInteractiveElement from './is-event-in-interactive-element'; +import getBorderBoxCenterPosition from '../get-border-box-center-position'; +import { warning } from '../../dev-warning'; +import useLayoutEffect from '../use-isomorphic-layout-effect'; +import { noop } from '../../empty'; +import findClosestDraggableIdFromEvent from './try-get-closest-draggable-id-from-event'; +import tryGetDraggable from './try-get-draggable'; + +function preventDefault(event: Event) { + event.preventDefault(); +} + +type LockPhase = 'PRE_DRAG' | 'DRAGGING' | 'COMPLETED'; + +type IsActiveArgs = {| + expected: LockPhase, + phase: LockPhase, + isLockActive: () => boolean, + shouldWarn: boolean, +|}; + +function isActive({ + expected, + phase, + isLockActive, + shouldWarn, +}: IsActiveArgs): boolean { + // lock is no longer active + if (!isLockActive()) { + if (shouldWarn) { + warning(` + Cannot perform action. + The sensor no longer has an action lock. + + Tips: + + - Throw away your action handlers when forceStop() is called + - Check actions.isActive() if you really need to + `); + } + return false; + } + // wrong phase + if (expected !== phase) { + if (shouldWarn) { + warning(` + Cannot perform action. + The actions you used belong to an outdated phase + + Current phase: ${expected} + You called an action from outdated phase: ${phase} + + Tips: + + - Do not use preDragActions actions after calling preDragActions.lift() + `); + } + return false; + } + return true; +} + +type CanStartArgs = {| + lockAPI: LockAPI, + registry: Registry, + store: Store, + draggableId: DraggableId, +|}; + +function canStart({ + lockAPI, + store, + registry, + draggableId, +}: CanStartArgs): boolean { + // lock is already claimed - cannot start + if (lockAPI.isClaimed()) { + return false; + } + + const entry: ?DraggableEntry = registry.draggable.findById(draggableId); + + if (!entry) { + warning(`Unable to find draggable with id: ${draggableId}`); + return false; + } + + // draggable is not enabled - cannot start + if (!entry.options.isEnabled) { + return false; + } + + // Application might now allow dragging right now + if (!canStartDrag(store.getState(), draggableId)) { + return false; + } + + return true; +} + +type TryStartArgs = {| + lockAPI: LockAPI, + contextId: ContextId, + registry: Registry, + store: Store, + draggableId: DraggableId, + forceSensorStop: ?() => void, + sourceEvent: ?Event, +|}; + +function tryStart({ + lockAPI, + contextId, + store, + registry, + draggableId, + forceSensorStop, + sourceEvent, +}: TryStartArgs): ?PreDragActions { + const shouldStart: boolean = canStart({ + lockAPI, + store, + registry, + draggableId, + }); + + if (!shouldStart) { + return null; + } + + const entry: DraggableEntry = registry.draggable.getById(draggableId); + const el: ?HTMLElement = tryGetDraggable(contextId, entry.descriptor.id); + + if (!el) { + warning(`Unable to find draggable element with id: ${draggableId}`); + return null; + } + + // Do not allow dragging from interactive elements + if ( + sourceEvent && + !entry.options.canDragInteractiveElements && + isEventInInteractiveElement(el, sourceEvent) + ) { + return null; + } + + // claiming lock + const lock: Lock = lockAPI.claim(forceSensorStop || noop); + let phase: LockPhase = 'PRE_DRAG'; + + function getShouldRespectForcePress(): boolean { + const item: DraggableEntry = registry.draggable.getById(draggableId); + return item.options.shouldRespectForcePress; + } + + function isLockActive(): boolean { + return lockAPI.isActive(lock); + } + + function tryDispatch(expected: LockPhase, getAction: () => Action): void { + if (isActive({ expected, phase, isLockActive, shouldWarn: true })) { + store.dispatch(getAction()); + } + } + + const tryDispatchWhenDragging = tryDispatch.bind(this, 'DRAGGING'); + + type LiftArgs = {| + liftActionArgs: LiftActionArgs, + cleanup: () => void, + actions: Object, + |}; + + function lift(args: LiftArgs) { + function completed() { + lockAPI.release(); + phase = 'COMPLETED'; + } + // Double lift = bad + if (phase !== 'PRE_DRAG') { + completed(); + invariant(phase === 'PRE_DRAG', `Cannot lift in phase ${phase}`); + } + + store.dispatch(liftAction(args.liftActionArgs)); + + // We are now in the DRAGGING phase + phase = 'DRAGGING'; + + function finish( + reason: 'CANCEL' | 'DROP', + options?: StopDragOptions = { shouldBlockNextClick: false }, + ) { + args.cleanup(); + + // block next click if requested + if (options.shouldBlockNextClick) { + window.addEventListener('click', preventDefault, { + // only blocking a single click + once: true, + passive: false, + capture: true, + }); + } + + // releasing + completed(); + store.dispatch(dropAction({ reason })); + } + + return { + isActive: () => + isActive({ + expected: 'DRAGGING', + phase, + isLockActive, + // Do not want to want warnings for boolean checks + shouldWarn: false, + }), + shouldRespectForcePress: getShouldRespectForcePress, + drop: (options?: StopDragOptions) => finish('DROP', options), + cancel: (options?: StopDragOptions) => finish('CANCEL', options), + ...args.actions, + }; + } + + function fluidLift(clientSelection: Position): FluidDragActions { + const move = rafSchd((client: Position) => { + tryDispatchWhenDragging(() => moveAction({ client })); + }); + + const api = lift({ + liftActionArgs: { + id: draggableId, + clientSelection, + movementMode: 'FLUID', + }, + cleanup: () => move.cancel(), + actions: { move }, + }); + + return { + ...api, + move, + }; + } + + function snapLift(): SnapDragActions { + const actions = { + moveUp: () => tryDispatchWhenDragging(moveUpAction), + moveRight: () => tryDispatchWhenDragging(moveRightAction), + moveDown: () => tryDispatchWhenDragging(moveDownAction), + moveLeft: () => tryDispatchWhenDragging(moveLeftAction), + }; + + return lift({ + liftActionArgs: { + id: draggableId, + clientSelection: getBorderBoxCenterPosition(el), + movementMode: 'SNAP', + }, + cleanup: noop, + actions, + }); + } + + function abortPreDrag() { + const shouldRelease: boolean = isActive({ + expected: 'PRE_DRAG', + phase, + isLockActive, + shouldWarn: true, + }); + + if (shouldRelease) { + lockAPI.release(); + } + } + + const preDrag: PreDragActions = { + isActive: () => + isActive({ + expected: 'PRE_DRAG', + phase, + isLockActive, + // Do not want to want warnings for boolean checks + shouldWarn: false, + }), + shouldRespectForcePress: getShouldRespectForcePress, + fluidLift, + snapLift, + abort: abortPreDrag, + }; + + return preDrag; +} + +type SensorMarshalArgs = {| + contextId: ContextId, + registry: Registry, + store: Store, + customSensors: ?(Sensor[]), + enableDefaultSensors: boolean, +|}; + +const defaultSensors: Sensor[] = [ + useMouseSensor, + useKeyboardSensor, + useTouchSensor, +]; + +export default function useSensorMarshal({ + contextId, + store, + registry, + customSensors, + enableDefaultSensors, +}: SensorMarshalArgs) { + const useSensors: Sensor[] = [ + ...(enableDefaultSensors ? defaultSensors : []), + ...(customSensors || []), + ]; + const lockAPI: LockAPI = useState(() => create())[0]; + + const tryAbandonLock = useCallback( + function tryAbandonLock(previous: State, current: State) { + if (previous.isDragging && !current.isDragging) { + lockAPI.tryAbandon(); + } + }, + [lockAPI], + ); + + // We need to abort any capturing if there is no longer a drag + useLayoutEffect( + function listenToStore() { + let previous: State = store.getState(); + const unsubscribe = store.subscribe(() => { + const current: State = store.getState(); + tryAbandonLock(previous, current); + previous = current; + }); + + // unsubscribe from store when unmounting + return unsubscribe; + }, + [lockAPI, store, tryAbandonLock], + ); + + // abort any lock on unmount + useLayoutEffect(() => { + return lockAPI.tryAbandon; + }, [lockAPI.tryAbandon]); + + const canGetLock = useCallback( + (draggableId: DraggableId): boolean => { + return canStart({ + lockAPI, + registry, + store, + draggableId, + }); + }, + [lockAPI, registry, store], + ); + + const tryGetLock: TryGetLock = useCallback( + ( + draggableId: DraggableId, + forceStop?: () => void, + options?: TryGetLockOptions, + ): ?PreDragActions => + tryStart({ + lockAPI, + registry, + contextId, + store, + draggableId, + forceSensorStop: forceStop, + sourceEvent: + options && options.sourceEvent ? options.sourceEvent : null, + }), + [contextId, lockAPI, registry, store], + ); + + const findClosestDraggableId = useCallback( + (event: Event): ?DraggableId => + findClosestDraggableIdFromEvent(contextId, event), + [contextId], + ); + + const findOptionsForDraggable = useCallback( + (id: DraggableId): ?DraggableOptions => { + const entry: ?DraggableEntry = registry.draggable.findById(id); + return entry ? entry.options : null; + }, + [registry.draggable], + ); + + const tryReleaseLock = useCallback(lockAPI.tryAbandon, [lockAPI]); + const isLockClaimed = useCallback(lockAPI.isClaimed, [lockAPI]); + + const api: SensorAPI = useMemo( + () => ({ + canGetLock, + tryGetLock, + findClosestDraggableId, + findOptionsForDraggable, + tryReleaseLock, + isLockClaimed, + }), + [ + canGetLock, + tryGetLock, + findClosestDraggableId, + findOptionsForDraggable, + tryReleaseLock, + isLockClaimed, + ], + ); + + // Bad ass + useValidateSensorHooks(useSensors); + for (let i = 0; i < useSensors.length; i++) { + useSensors[i](api); + } +} diff --git a/src/view/use-sensor-marshal/use-validate-sensor-hooks.js b/src/view/use-sensor-marshal/use-validate-sensor-hooks.js new file mode 100644 index 0000000000..89c6ba2716 --- /dev/null +++ b/src/view/use-sensor-marshal/use-validate-sensor-hooks.js @@ -0,0 +1,18 @@ +// @flow +import invariant from 'tiny-invariant'; +import { useEffect } from 'react'; +import type { Sensor } from '../../types'; +import usePreviousRef from '../use-previous-ref'; + +export default function useValidateSensorHooks(sensorHooks: Sensor[]) { + const previousRef = usePreviousRef(sensorHooks); + + useEffect(() => { + if (process.env.NODE_ENV !== 'production') { + invariant( + previousRef.current.length === sensorHooks.length, + 'Cannot change the amount of sensor hooks after mounting', + ); + } + }); +} diff --git a/src/view/use-style-marshal/get-styles.js b/src/view/use-style-marshal/get-styles.js index 8a4f4a38da..a7aea9c3f7 100644 --- a/src/view/use-style-marshal/get-styles.js +++ b/src/view/use-style-marshal/get-styles.js @@ -1,4 +1,5 @@ // @flow +import type { ContextId } from '../../types'; import { transitions } from '../../animation'; import * as attributes from '../data-attributes'; @@ -38,8 +39,8 @@ const getStyles = (rules: Rule[], property: string): string => const noPointerEvents: string = 'pointer-events: none;'; -export default (uniqueContext: string): Styles => { - const getSelector = makeGetSelector(uniqueContext); +export default (contextId: ContextId): Styles => { + const getSelector = makeGetSelector(contextId); // ## Drag handle styles @@ -76,7 +77,7 @@ export default (uniqueContext: string): Styles => { cursor: grab; `; return { - selector: getSelector(attributes.dragHandle), + selector: getSelector(attributes.dragHandle.contextId), styles: { always: ` -webkit-touch-callout: none; @@ -104,7 +105,7 @@ export default (uniqueContext: string): Styles => { transition: ${transitions.outOfTheWay}; `; return { - selector: getSelector(attributes.draggable), + selector: getSelector(attributes.draggable.contextId), styles: { dragging: transition, dropAnimating: transition, @@ -122,7 +123,7 @@ export default (uniqueContext: string): Styles => { // When we drop a Draggable it already has the correct scroll applied. const droppable: Rule = { - selector: getSelector(attributes.droppable), + selector: getSelector(attributes.droppable.contextId), styles: { always: `overflow-anchor: none;`, // need pointer events on the droppable to allow manual scrolling diff --git a/src/view/use-style-marshal/style-marshal-types.js b/src/view/use-style-marshal/style-marshal-types.js index 16e95c0372..60f44b3d3b 100644 --- a/src/view/use-style-marshal/style-marshal-types.js +++ b/src/view/use-style-marshal/style-marshal-types.js @@ -5,5 +5,4 @@ export type StyleMarshal = {| dragging: () => void, dropping: (reason: DropReason) => void, resting: () => void, - styleContext: string, |}; diff --git a/src/view/use-style-marshal/use-style-marshal.js b/src/view/use-style-marshal/use-style-marshal.js index ddbc795720..c2c9ea2cfd 100644 --- a/src/view/use-style-marshal/use-style-marshal.js +++ b/src/view/use-style-marshal/use-style-marshal.js @@ -4,7 +4,7 @@ import memoizeOne from 'memoize-one'; import { useMemo, useCallback } from 'use-memo-one'; import invariant from 'tiny-invariant'; import type { StyleMarshal } from './style-marshal-types'; -import type { DropReason } from '../../types'; +import type { ContextId, DropReason } from '../../types'; import getStyles, { type Styles } from './get-styles'; import { prefix } from '../data-attributes'; import useLayoutEffect from '../use-isomorphic-layout-effect'; @@ -21,11 +21,8 @@ const createStyleEl = (): HTMLStyleElement => { return el; }; -export default function useStyleMarshal(uniqueId: number) { - const uniqueContext: string = useMemo(() => `${uniqueId}`, [uniqueId]); - const styles: Styles = useMemo(() => getStyles(uniqueContext), [ - uniqueContext, - ]); +export default function useStyleMarshal(contextId: ContextId) { + const styles: Styles = useMemo(() => getStyles(contextId), [contextId]); const alwaysRef = useRef(null); const dynamicRef = useRef(null); @@ -60,8 +57,8 @@ export default function useStyleMarshal(uniqueId: number) { dynamicRef.current = dynamic; // for easy identification - always.setAttribute(`${prefix}-always`, uniqueContext); - dynamic.setAttribute(`${prefix}-dynamic`, uniqueContext); + always.setAttribute(`${prefix}-always`, contextId); + dynamic.setAttribute(`${prefix}-dynamic`, contextId); // add style tags to head getHead().appendChild(always); @@ -87,7 +84,7 @@ export default function useStyleMarshal(uniqueId: number) { setDynamicStyle, styles.always, styles.resting, - uniqueContext, + contextId, ]); const dragging = useCallback(() => setDynamicStyle(styles.dragging), [ @@ -117,9 +114,8 @@ export default function useStyleMarshal(uniqueId: number) { dragging, dropping, resting, - styleContext: uniqueContext, }), - [dragging, dropping, resting, uniqueContext], + [dragging, dropping, resting], ); return marshal; diff --git a/src/view/use-unique-id.js b/src/view/use-unique-id.js new file mode 100644 index 0000000000..537ed1d23f --- /dev/null +++ b/src/view/use-unique-id.js @@ -0,0 +1,11 @@ +// @flow +import { useRef } from 'react'; +import type { Id } from '../types'; + +let count: number = 0; + +export default function useUniqueId(prefix: string): Id { + const countRef = useRef(count++); + + return `${prefix}::${countRef.current}`; +} diff --git a/src/view/visually-hidden-style.js b/src/view/visually-hidden-style.js new file mode 100644 index 0000000000..856279bdeb --- /dev/null +++ b/src/view/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 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/stories/3-board.stories.stories.js b/stories/3-board.stories.stories.js index ced9d1c294..1337ff3af4 100644 --- a/stories/3-board.stories.stories.js +++ b/stories/3-board.stories.stories.js @@ -11,6 +11,7 @@ const data = { storiesOf('board', module) .add('simple', () => ) + .add('dragging a clone', () => ) .add('medium data set', () => ) .add('large data set', () => ) .add('long lists in a short container', () => ( @@ -19,6 +20,9 @@ storiesOf('board', module) .add('scrollable columns', () => ( )) - .add('with combine enabled', () => ( + .add('with combining', () => ( + )) + .add('with combining and cloning', () => ( + )); diff --git a/stories/40-programmatic.stories.js b/stories/40-programmatic.stories.js new file mode 100644 index 0000000000..24a8dcd5a6 --- /dev/null +++ b/stories/40-programmatic.stories.js @@ -0,0 +1,10 @@ +// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import WithControls from './src/programmatic/with-controls'; +import Runsheet from './src/programmatic/runsheet'; +import { quotes } from './src/data'; + +storiesOf('Programmatic dragging', module) + .add('with controls', () => ) + .add('with runsheet', () => ); diff --git a/stories/45-virtual.stories.js b/stories/45-virtual.stories.js new file mode 100644 index 0000000000..625e9747ac --- /dev/null +++ b/stories/45-virtual.stories.js @@ -0,0 +1,14 @@ +// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import ReactWindow from './src/virtual/react-window'; +import { getQuotes, generateQuoteMap } from './src/data'; +import Board from './src/virtual/board'; + +storiesOf('Virtual', module) + .add('list with react-window', () => ( + + )) + .add('board with react-window', () => ( + + )); diff --git a/stories/50-multiple-contexts.stories.js b/stories/50-multiple-contexts.stories.js new file mode 100644 index 0000000000..7ee00578a8 --- /dev/null +++ b/stories/50-multiple-contexts.stories.js @@ -0,0 +1,8 @@ +// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import MultipleContexts from './src/programmatic/multiple-contexts'; + +storiesOf('Multiple contexts', module).add('with multiple contexts', () => ( + +)); diff --git a/stories/src/accessible/task.jsx b/stories/src/accessible/task.jsx index 3b99d3a7ba..0223974a07 100644 --- a/stories/src/accessible/task.jsx +++ b/stories/src/accessible/task.jsx @@ -57,7 +57,6 @@ export default class Task extends Component { isDragging={snapshot.isDragging} {...provided.draggableProps} {...provided.dragHandleProps} - aria-roledescription="Draggable task. Press space bar to lift" blur={blur} > {this.props.task.content} diff --git a/stories/src/board/board.jsx b/stories/src/board/board.jsx index 645f1f116b..e635c801cd 100644 --- a/stories/src/board/board.jsx +++ b/stories/src/board/board.jsx @@ -32,6 +32,7 @@ type Props = {| withScrollableColumns?: boolean, isCombineEnabled?: boolean, containerHeight?: string, + useClone?: boolean, |}; type State = {| @@ -117,7 +118,12 @@ export default class Board extends Component { render() { const columns: QuoteMap = this.state.columns; const ordered: string[] = this.state.ordered; - const { containerHeight } = this.props; + const { + containerHeight, + useClone, + isCombineEnabled, + withScrollableColumns, + } = this.props; const board = ( { type="COLUMN" direction="horizontal" ignoreContainerClipping={Boolean(containerHeight)} - isCombineEnabled={this.props.isCombineEnabled} + isCombineEnabled={isCombineEnabled} > {(provided: DroppableProvided) => ( @@ -135,8 +141,9 @@ export default class Board extends Component { index={index} title={key} quotes={columns[key]} - isScrollable={this.props.withScrollableColumns} - isCombineEnabled={this.props.isCombineEnabled} + isScrollable={withScrollableColumns} + isCombineEnabled={isCombineEnabled} + useClone={useClone} /> ))} {provided.placeholder} diff --git a/stories/src/board/column.jsx b/stories/src/board/column.jsx index 8bc0f4b2a7..528fb53590 100644 --- a/stories/src/board/column.jsx +++ b/stories/src/board/column.jsx @@ -36,6 +36,7 @@ type Props = {| index: number, isScrollable?: boolean, isCombineEnabled?: boolean, + useClone?: boolean, |}; export default class Column extends Component { @@ -64,6 +65,7 @@ export default class Column extends Component { quotes={quotes} internalScroll={this.props.isScrollable} isCombineEnabled={Boolean(this.props.isCombineEnabled)} + useClone={Boolean(this.props.useClone)} /> )} diff --git a/stories/src/custom-drop/funny-drop.jsx b/stories/src/custom-drop/funny-drop.jsx index e5b7952047..d31fc2a2c6 100644 --- a/stories/src/custom-drop/funny-drop.jsx +++ b/stories/src/custom-drop/funny-drop.jsx @@ -43,7 +43,7 @@ const getStyle = ( } const { moveTo, curve, duration } = dropping; const translate = `translate(${moveTo.x}px, ${moveTo.y}px)`; - const rotate = 'rotate(0.5turn)'; + const rotate = 'rotate(1turn)'; return { ...style, transform: `${translate} ${rotate}`, diff --git a/stories/src/data.js b/stories/src/data.js index f167807b55..0aa9213356 100644 --- a/stories/src/data.js +++ b/stories/src/data.js @@ -1,10 +1,16 @@ // @flow +/* eslint-disable import/no-unresolved */ +/* eslint-disable import/no-webpack-loader-syntax */ import { colors } from '@atlaskit/theme'; import type { Author, Quote, QuoteMap } from './types'; -import jakeImg from '../assets/jake.png'; -import finnImg from '../assets/finn.png'; -import bmoImg from '../assets/bmo.png'; -import princessImg from '../assets/princess.png'; +// $ExpectError - flow cannot resolve the import +import finnImg from '!!url-loader!../static/media/finn-min.png'; +// $ExpectError - flow cannot resolve the import +import bmoImg from '!!url-loader!../static/media/bmo-min.png'; +// $ExpectError - flow cannot resolve the import +import princessImg from '!!url-loader!../static/media/princess-min.png'; +// $ExpectError - flow cannot resolve the import +import jakeImg from '!!url-loader!../static/media/jake-min.png'; const jake: Author = { id: '1', @@ -13,7 +19,7 @@ const jake: Author = { avatarUrl: jakeImg, colors: { soft: colors.Y50, - hard: colors.Y200, + hard: colors.N400A, }, }; @@ -24,7 +30,7 @@ const BMO: Author = { avatarUrl: bmoImg, colors: { soft: colors.G50, - hard: colors.G200, + hard: colors.N400A, }, }; @@ -35,7 +41,7 @@ const finn: Author = { avatarUrl: finnImg, colors: { soft: colors.B50, - hard: colors.B200, + hard: colors.N400A, }, }; @@ -46,7 +52,7 @@ const princess: Author = { avatarUrl: princessImg, colors: { soft: colors.P50, - hard: colors.P200, + hard: colors.N400A, }, }; diff --git a/stories/src/dynamic/with-controls.jsx b/stories/src/dynamic/with-controls.jsx index 2e14816579..9a6269061a 100644 --- a/stories/src/dynamic/with-controls.jsx +++ b/stories/src/dynamic/with-controls.jsx @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-syntax */ // @flow import React from 'react'; import styled from '@emotion/styled'; diff --git a/stories/src/multi-drag/task.jsx b/stories/src/multi-drag/task.jsx index 73ca96e1dd..266217e85e 100644 --- a/stories/src/multi-drag/task.jsx +++ b/stories/src/multi-drag/task.jsx @@ -59,7 +59,7 @@ const Container = styled.div` margin-bottom: ${grid}px; border-radius: ${borderRadius}px; font-size: 18px; - border: 1px solid ${colors.N90}; + border: 3px solid ${colors.N90}; ${props => props.isDragging ? `box-shadow: 2px 2px 1px ${colors.N90};` : ''} ${props => props.isGhosting @@ -72,7 +72,7 @@ const Container = styled.div` /* avoid default outline which looks lame with the position: absolute; */ &:focus { outline: none; - border-color: ${colors.N200}; + border-color: ${colors.G200}; } `; /* stylelint-disable block-no-empty */ @@ -108,10 +108,6 @@ export default class Task extends Component { provided: DraggableProvided, snapshot: DraggableStateSnapshot, ) => { - if (provided.dragHandleProps) { - provided.dragHandleProps.onKeyDown(event); - } - if (event.defaultPrevented) { return; } diff --git a/stories/src/primatives/quote-item.jsx b/stories/src/primatives/quote-item.jsx index 79ed551ae3..b3b0904026 100644 --- a/stories/src/primatives/quote-item.jsx +++ b/stories/src/primatives/quote-item.jsx @@ -5,12 +5,15 @@ import { colors } from '@atlaskit/theme'; import { borderRadius, grid } from '../constants'; import type { Quote, AuthorColors } from '../types'; import type { DraggableProvided } from '../../../src'; +import useLayoutEffect from '../../../src/view/use-isomorphic-layout-effect'; type Props = { quote: Quote, isDragging: boolean, provided: DraggableProvided, + isClone?: boolean, isGroupedOver?: boolean, + style?: Object, }; const getBackgroundColor = ( @@ -32,6 +35,28 @@ const getBackgroundColor = ( const getBorderColor = (isDragging: boolean, authorColors: AuthorColors) => isDragging ? authorColors.hard : 'transparent'; +const imageSize: number = 40; + +const CloneBadge = styled.div` + background: ${colors.G100}; + bottom: ${grid / 2}px; + border: 2px solid ${colors.G200}; + border-radius: 50%; + box-sizing: border-box; + font-size: 10px; + position: absolute; + right: -${imageSize / 3}px; + top: -${imageSize / 3}px; + transform: rotate(40deg); + + height: ${imageSize}px; + width: ${imageSize}px; + + display: flex; + justify-content: center; + align-items: center; +`; + const Container = styled.a` border-radius: ${borderRadius}px; border: 2px solid transparent; @@ -40,8 +65,9 @@ const Container = styled.a` getBackgroundColor(props.isDragging, props.isGroupedOver, props.colors)}; box-shadow: ${({ isDragging }) => isDragging ? `2px 2px 1px ${colors.N70}` : 'none'}; + box-sizing: border-box; padding: ${grid}px; - min-height: 40px; + min-height: ${imageSize}px; margin-bottom: ${grid}px; user-select: none; @@ -65,8 +91,8 @@ const Container = styled.a` `; const Avatar = styled.img` - width: 40px; - height: 40px; + width: ${imageSize}px; + height: ${imageSize}px; border-radius: 50%; margin-right: ${grid}px; flex-shrink: 0; @@ -105,6 +131,7 @@ const Footer = styled.div` `; const Author = styled.small` + color: ${props => props.colors.hard}; flex-grow: 0; margin: 0; background-color: ${props => props.colors.soft}; @@ -122,6 +149,17 @@ const QuoteId = styled.small` text-align: right; `; +function getStyle(provided: DraggableProvided, style: ?Object) { + if (!style) { + return provided.draggableProps.style; + } + + return { + ...provided.draggableProps.style, + ...style, + }; +} + // Previously this extended React.Component // That was a good thing, because using React.PureComponent can hide // issues with the selectors. However, moving it over does can considerable @@ -130,19 +168,28 @@ const QuoteId = styled.small` // things we should be doing in the selector as we do not know if consumers // will be using PureComponent function QuoteItem(props: Props) { - const { quote, isDragging, isGroupedOver, provided } = props; + const { quote, isDragging, isGroupedOver, provided, style, isClone } = props; + + useLayoutEffect(() => { + console.log('mounting', quote.id); + return () => console.log('unmounting', quote.id); + }, [quote.id]); return ( + {isClone ? Clone : null}
{quote.content}