Security News
Supply Chain Attack Detected in Solana's web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
react-movable
Advanced tools
See all the other examples and their source code!
yarn add react-movable
import * as React from 'react';
import { List, arrayMove } from 'react-movable';
const SuperSimple: React.FC = () => {
const [items, setItems] = React.useState(['Item 1', 'Item 2', 'Item 3']);
return (
<List
values={items}
onChange={({ oldIndex, newIndex }) =>
setItems(arrayMove(items, oldIndex, newIndex))
}
renderList={({ children, props }) => <ul {...props}>{children}</ul>}
renderItem={({ value, props }) => <li {...props}>{value}</li>}
/>
);
};
tab
and shift+tab
to focus itemsspace
to lift or drop the itemj
or arrow down
to move the lifted item downk
or arrow up
to move the lifted item upescape
to cancel the lift and return the item to its initial position<List />
propsrenderList: (props: {
children: React.ReactNode;
isDragged: boolean;
props: {
ref: React.RefObject<any>;
};
}) => React.ReactNode;
renderList
prop to define your list (root) element. Your function gets three parameters and should return a React component:
props
containing ref
- this needs to be spread over the root list element, note that items need to be direct children of the DOM element that's being set with this ref
children
- the content of the listisDragged
- true
if any item is being draggedrenderItem: (params: {
value: Value;
index?: number;
isDragged: boolean;
isSelected: boolean;
isOutOfBounds: boolean;
props: {
key?: number;
tabIndex?: number;
'aria-roledescription'?: string;
onKeyDown?: (e: React.KeyboardEvent) => void;
onWheel?: (e: React.WheelEvent) => void;
style?: React.CSSProperties;
ref?: React.RefObject<any>;
};
}) => React.ReactNode;
renderItem
prop to define your item element. Your function gets 5 parameters and should return a React component:
value
- an item of the array you passed into the values
propindex
- the item index (order)isDragged
- true
if the item is dragged, great for styling purposesisSelected
- true
if the item is lifted with the space
isOutOfBounds
- true
if the item is dragged far left or rightprops
- it has multiple props that you need to spread over your item element. Since one of these is ref
, if you're spreading over a custom component, it must be wrapped in React.forwardRef
like in the "Custom component" example.values: Value[]
An array of values. The value can be a string or any more complex object. The length of the values
array equals the number of rendered items.
onChange: (meta: { oldIndex: number; newIndex: number, targetRect: ClientRect }) => void
Called when the item is dropped to a new location:
oldIndex
- the initial position of the element (0 indexed)newIndex
- the new position of the element (0 indexed), -1 when removableByMove
is set and item dropped out of boundstargetRect
- getBoundingClientRect of dropped itemThe List component is stateless
and controlled
so you need to implement this function to change the order of input values
. Check the initial example.
beforeDrag?: (params: { elements: Element[]; index: number }) => void;
Called when a valid drag is initiated. It provides a direct access to all list DOM elements and the index of dragged item. This can be useful when you need to do some upfront measurements like when building a table with variable column widths.
removableByMove: boolean;
Default is false
. When set to true
and an item is dragged far left or far right (out of bounds), the original gap disappears (animated) and following item drop will cause onChange
being called with newIndex = -1
. You can use that to remove the item from your values
state. Example.
transitionDuration: number;
The duration of CSS transitions. By default it's 300ms. You can set it to 0 to disable all animations.
lockVertically: boolean;
If true
, the dragged element can move only vertically when being dragged.
voiceover: {
item: (position: number) => string;
lifted: (position: number) => string;
dropped: (from: number, to: number) => string;
moved: (position: number, up: boolean) => string;
canceled: (position: number) => string;
}
In order to support screen reader users, react-movable
is triggering different messages when user is interacting with the list. There is already a set of English messages included but you can override it with this prop.
container?: Element;
Provide custom DOM element where moved item will be rendered.
arrayMove
and arrayRemove
There are also additional two helper functions being exported:
arrayMove: <T>(array: T[], from: number, to: number) => T[];
arrayRemove: <T>(array: T[], index: number) => T[];
They are useful when you need to manipulate the state of values
when onChange
is triggered.
There are two main ways how you can implement drag and drop today:
There are multiple great libraries in React's ecosystem already. DnD can get pretty complicated so each one of them covers different use-cases and has different goals:
react-dnd is a general purpose DnD library that makes amazing job abstracting quirky HTML5 API. It provides well thought out lower-level DnD primitives and let you build anything you want.
react-beautiful-dnd is a really beautiful DnD library for lists. It comes with a great support for accessibility and it's packed with awesome features. It doesn't use HTML5 API so it doesn't impose any of its limitations.
react-sortable-hoc provides a set of higher order components to make your lists dnd-able. It has many features and approaches similar to react-beautiful-dnd
but it's more minimalistic and lacks some features as accessibility or unopinionated styling.
So why react-movable
was created? There are two main goals:
react-dnd
or react-beautiful-dnd
(~3kB vs ~30kB) and half of the size of react-sortable-hoc
(~7kB). That's especially important when you intend to use react-movable
as a dependency in your own library. However, that also means that some features are left out - for example, the horizontal DnD is not supported.16.3
since the new createRef
and createPortal
APIs are used.If you need the features above, please give a try to react-beautiful-dnd
. It's a really well-designed library with all those features and gives you a lot of power to customize! If you are building an application heavy on DnD interactions, it might be your best bet! react-movable
's goal is not to be feature complete with react-beautiful-dnd
.
Other feature requests will be thoroughly vetted. Again, the primary goal is to keep the size down while supporting main use-cases!
This library is tightly coupled to many DOM APIs. It would be very hard to write unit tests that would not involve a lot of mocking. Or we could re-architect the library to better abstract all DOM interfaces but that would mean more code and bigger footprint.
Instead of that, react-movable
is thoroughly tested by end to end tests powered by puppeteer. It tests all user interactions:
All tests are automatically ran in Travis CI with headless chromium. This way, the public API is well tested, including pixel-perfect positioning. Also, the tests are pretty fast, reliable and very descriptive.
Do you want to run them in the dev
mode (slows down operations, opens the browser)?
yarn ladle serve #start the ladle server
yarn test:e2e:dev #run the e2e tests
yarn test:e2e
If you are using react-movable, please open a PR and add yourself to this list!
This is how you can spin up the dev environment:
git clone https://github.com/tajo/react-movable
cd react-movable
yarn
yarn ladle serve
I wrote an article about Building a Drag and Drop List.
Also, gave a talk at React Advanced London: What a Drag (2019):
The popular React DnD libraries were already mentioned in the motivation part. Big shoutout to react-beautiful-dnd
❤️ ️ for supporting multiple great features and adding first-class support for accessibility! It was strongly used as an inspiration for react-movable
!
Big thanks to BrowserStack for letting the maintainers use their service to debug browser issues.
And Netlify for free hosting.
FAQs
Drag and drop lists.
The npm package react-movable receives a total of 27,738 weekly downloads. As such, react-movable popularity was classified as popular.
We found that react-movable demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.