MuuriComponent API

Props

In this documentation the props of the MuuriComponent are grouped into three categories in order to clarify their usefulness.

Interaction props ⚙️

These are the props to use to interact with the functionality of the MuuriComponent.


ref

The ref for the Muuri instance used inside the MuuriComponent. See more here.

  • Accepted types: React.RefObject, function.
const muuriRef = useRef();
<MuuriComponent ref={muuriRef} />;
<MuuriComponent ref={function (grid) {}} />

id

The id of the MuuriComponent.

  • Accepted types: string.
<MuuriComponent id={'id'} />

groupIds

The ids of the virtual groups to which the MuuriComponent belongs, it is possible to change them in any render. This option is used here.

  • Accepted types: string[].
<MuuriComponent groupIds={['GroupA', 'GroupB']} />

gridProps

The props of the DOM element generated by the MuuriComponent.

  • Accepted types: object.
<MuuriComponent gridProps={{className: 'grid'}} />

dragEnabled

Should Items be draggable?

  • Default value: false.
  • Accepted types: boolean.
<MuuriComponent dragEnabled={true} />

filter

The filter function is executed for every Item in the instance. If the return value of the predicate is truthy the Item in question will be shown and otherwise hidden. Remember to provide a memoized value to avoid useless re-filtering (as the component will re-filter each time the value change). See more here.

  • Accepted types: function.

The function receives the data of the Item as its argument.

  • data  —  object
    • The data of the item to filter.
  • returns  —  boolean
    • If the item should be visible or hidden.
const filter = useCallback((itemData) => {
// Show only the items that respect the condition.
return itemData.someData === 'someValue';
}, []);
<MuuriComponent filter={filter} />;

sort

There are two ways to sort the Items based on their data. The first is simply by providing a function as the comparer. It works almost identically to native array sort, the only difference is that the sort is always stable. Alternatively you can sort by the data you have provided for the Items. Just provide the data key(s) as a string (separated by space) and the Items will be sorted based on the provided data keys. The last method is to provide an ordered list of Items keys and is not based on data. If you are using a function or an array, remember to provide a memoized value to avoid useless re-sorting (as the component will re-sort each time the value change). See more here.

  • Accepted types: string, function, array.

If you provide a function it will receive the data of two Items to compare as arguments.

  • dataA  —  object
    • The data of the first item to compare.
  • dataB  —  object
    • The data of the second item to compare.
  • returns  —  number
    • A number representing the comparison of the two items.
const sort = useCallback((dataItemA, dataItemB) => {
// Sort by id.
return dataItemA.id - dataItemB.id;
}, []);
<MuuriComponent propsToData={({id}) => ({id})} sort={sort} />;
<MuuriComponent
propsToData={({id, tag}) => ({id, tag})}
// Sort by id and by tag.
sort={'id tag'}
/>
<MuuriComponent
propsToData={({id, tag}) => ({id, tag})}
// Sort some keys ascending and some keys descending.
sort={'id tag:desc'}
/>
const [sort] = useState(['2', '1']);
<MuuriComponent sort={sort}>
<Item key={'1'} />
<Item key={'2'} />
</MuuriComponent>;

sortOptions

With this options you can change the sorting order (default ascending).
Remember to provide a memoized value to avoid useless re-sorting (as the component will re-sort each time the value change).

  • Accepted types: object.
  • Default value: { descending: false }
const [sort] = useState({
value: 'id',
options: {descending: true},
});
<MuuriComponent sort={sort.value} sortOptions={sort.options} />;

addOptions

With this options you can decide how the MuuriComponent will manage the new Items added with the CSS display property set to none, If show is true the Item will be added with a showing animation, otherwise the Item will be hidden. Note that if the filter props is set it takes precedence over the decision of which Items are visible or not.

  • Accepted types: object.
  • Default value: { show: true }
<MuuriComponent addOptions={{show: false}} />

propsToData

The function is executed for each Item in the instance. The returned object represents the data of the Item in question. See more here.

  • Accepted types: function.

The function receives the props of the Item as its argument.

  • props  —  object
    • The props of the item.
  • returns  —  object
    • The data of the item.
const items = [{id: 1}, {id: 2}];
const children = items.map(({id}) => <Item id={id} />);
// The id prop will be used as data.
<MuuriComponent propsToData={({id}) => ({id})}>{children}</MuuriComponent>;

forceSync

Sorting and filtering are not reapplied with a new rendering if their value does not change. If forceSync is true, they will be reapplied even if their values ​​have not changed.

  • Accepted types: boolean.
  • Default value: false
<MuuriComponent forceSync />

instantLayout

If true the Items will be positioned instantly without any animation.

  • Accepted types: boolean.
  • Default value: false
<MuuriComponent instantLayout />

Layout props ⚙️

These are the props that determine how the MuuriComponent will work, from layout up to the speed of animations. These props can only be chosen when the component is mounted, modifying them in subsequent renders will have no effect.

Default values

The default options are stored in MuuriComponent.defaultProps object, which in it's default state contains the following configuration:

<MuuriComponent
// Default show animation.
showDuration={300}
showEasing={'ease'}
// Default hide animation.
hideDuration={300}
hideEasing={'ease'}
// Item's visible/hidden state styles.
visibleStyles={{
opacity: '1',
transform: 'scale(1)',
}}
hiddenStyles={{
opacity: '0',
transform: 'scale(0.5)',
}}
// Layout.
layout={{
fillGaps: false,
horizontal: false,
alignRight: false,
alignBottom: false,
rounding: true,
}}
layoutOnResize={100}
layoutDuration={300}
layoutEasing={'ease'}
// Drag & Drop.
dragContainer={null}
dragHandle={null}
dragFixed={false}
dragStartPredicate={{
distance: 0,
delay: 0,
handle: false,
}}
dragAxis={null}
dragSort={true}
dragSortHeuristics={{
sortInterval: 100,
minDragDistance: 10,
minBounceBackAngle: 1,
}}
dragSortPredicate={{
threshold: 50,
action: 'move',
migrateAction: 'move',
}}
dragRelease={{
duration: 300,
easing: 'ease',
useDragContainer: true,
}}
dragCssProps={{
touchAction: 'none',
userSelect: 'none',
userDrag: 'none',
tapHighlightColor: 'rgba(0, 0, 0, 0)',
touchCallout: 'none',
contentZooming: 'none',
}}
dragPlaceholder={{
enabled: false,
createElement: null,
onCreate: null,
onRemove: null,
}}
// Classnames.
containerClass={'muuri'}
itemClass={'muuri-item'}
itemVisibleClass={'muuri-item-shown'}
itemHiddenClass={'muuri-item-hidden'}
itemPositioningClass={'muuri-item-positioning'}
itemDraggingClass={'muuri-item-dragging'}
itemReleasingClass={'muuri-item-releasing'}
itemPlaceholderClass={'muuri-item-placeholder'}
/>

You can modify the default options easily:

MuuriComponent.defaultOptions.showDuration = 400;
MuuriComponent.defaultOptions.dragSortPredicate.action = 'swap';

showDuration

Show animation duration in milliseconds. Set to 0 to disable show animation.

  • Default value: 300.
  • Accepted types: number.
<MuuriComponent showDuration={600} />

showEasing

Show animation easing. Accepts any valid Animation easing value.

  • Default value: 'ease'.
  • Accepted types: string.
<MuuriComponent showEasing={'cubic-bezier(0.215, 0.61, 0.355, 1)'} />

hideDuration

Hide animation duration in milliseconds. Set to 0 to disable hide animation.

  • Default value: 300.
  • Accepted types: number.
<MuuriComponent hideDuration={600} />

hideEasing

Hide animation easing. Accepts any valid Animation easing value.

  • Default value: 'ease'.
  • Accepted types: string.
<MuuriComponent hideEasing={'cubic-bezier(0.215, 0.61, 0.355, 1)'} />

visibleStyles

The styles that will be applied to all visible Items. These styles are also used for the show/hide animations which means that you have to have the same style properties in visibleStyles and hiddenStyles options. Be sure to define all style properties camel cased.

  • Default value: {opacity: 1, transform: 'scale(1)'}.
  • Accepted types: object.
<MuuriComponent
visibleStyles={{
opacity: 1,
transform: 'rotate(45deg)',
}}
hiddenStyles={{
opacity: 0,
transform: 'rotate(-45deg)',
}}
/>

hiddenStyles

The styles that will be applied to all hidden Items. These styles are also used for the show/hide animations which means that you have to have the same style properties in visibleStyles and hiddenStyles options. Be sure to define all style properties camel cased.

  • Default value: {opacity: 0, transform: 'scale(0.5)'}.
  • Accepted types: object.
<MuuriComponent
visibleStyles={{
opacity: 1,
transform: 'rotate(45deg)',
}}
hiddenStyles={{
opacity: 0,
transform: 'rotate(-45deg)',
}}
/>

layoutOnResize

Should Muuri automatically trigger layout method on window resize? Set to false to disable. When a number or true is provided Muuri will automatically position the Items every time window is resized. The provided number (true is transformed to 0) equals to the amount of time (in milliseconds) that is waited before Items are positioned after each window resize event.

  • Default value: 150.
  • Accepted types: boolean, number.
// No layout on resize.
<MuuriComponent
layoutOnResize={false}
>
// Layout on resize (instantly).
<MuuriComponent
layoutOnResize
>
// Layout on resize (with 200ms debounce).
<MuuriComponent
layoutOnResize={200}
>

layoutDuration

The duration for Item's layout animation in milliseconds. Set to 0 to disable.

  • Default value: 300.
  • Accepted types: number.
<MuuriComponent layoutDuration={600} />

layoutEasing

The easing for Item's layout animation. Accepts any valid Animation easing value.

  • Default value: 'ease'.
  • Accepted types: string.
<MuuriComponent layoutEasing={'cubic-bezier(0.215, 0.61, 0.355, 1)'} />

dragFixed

Should the CSS width, height and padding-top properties of the element be temporarily fixed when dragging? See more here.

  • Default value: false.
  • Accepted types: boolean.
<MuuriComponent dragFixed />

dragContainer

The element (or its ref) the dragged Item should be appended to for the duration of the drag. If set to null (which is also the default value) the MuuriComponent element will be used.

  • Default value: null.
  • Accepted types: React.RefObject, element, null.
<MuuriComponent dragContainer={document.body} />
const ref = useRef();
<div className={'dragContainer'} ref={ref}>
<MuuriComponent dragContainer={ref} />
</div>;

dragHandle

The element within the Item element that should be used as the drag handle. This should be a CSS selector which will be fed to element.querySelector() as is to obtain the handle element when the Item is instantiated. If no valid element is found or if this is null Muuri will use the Item element as the handle.

  • Default value: null.
  • Accepted types: string, null.
<MuuriComponent dragHandle={'.handle'} />

dragStartPredicate

A function that determines when the Item should start to move when the Item is being dragged. By default uses the built-in predicate which has some configurable options.

  • Default value: {distance: 0, delay: 0}.
  • Accepted types: function, object.

If an object is provided the default sort predicate handler will be used. You can define the following properties:

  • distance—  number
    • Default value: 0.
    • How many pixels must be dragged before the dragging starts.
  • delay—  number
    • Default value: 0.
    • How long (in milliseconds) the user must drag before the dragging starts.

If you provide a function you can totally customize the drag start logic. When the user starts to drag an Item this predicate function will be called until you return true or false. If you return true the Item will begin to move whenever the Item is dragged. If you return false the Item will not be moved at all. Note that after you have returned true or false this function will not be called until the Item is released and dragged again. Remember that you can enable / disable drag and drop for the single Item with the useDraggable hook.

The predicate function receives two arguments:

  • item—  Muuri.Item
    • The Item that's being dragged.
  • event—  object
    • The drag event (Muuri.Dragger event).
// Configure the default predicate.
<MuuriComponent
dragStartPredicate={{
distance: 10,
delay: 100,
}}
/>
// Provide your own predicate.
<MuuriComponent
dragStartPredicate={function (item, e) {
// Start moving the item after the item has been dragged for one second.
if (e.deltaTime > 1000) {
return true;
}
}}
/>
// Provide your own predicate.
<MuuriComponent
dragStartPredicate={function (item, e) {
const key = item.getKey();
const data = item.getData();
// Implement your logic...
}}
/>

dragAxis

Force Items to be moved only vertically or horizontally when dragged. Set to 'x' for horizontal movement and to 'y' for vertical movement. By default Items can be dragged both vertically and horizontally.

  • Default value: 'xy'.
  • Accepted types: string.
  • Allowed values: 'x', 'y', 'xy'.
// Move items only horizontally when dragged.
<MuuriComponent dragAxis={'x'} />
// Move items only vertically when dragged.
<MuuriComponent dragAxis={'y'} />

dragSort

Should the Items be sorted during drag? A simple boolean will do just fine here.

Alternatively you can do some advanced stuff and control within which MuuriComponents a specific Item can be sorted and dragged into. To do that you can simply provide the groupId of these Muuricomponents. If you want to implement a more complex logic, different for each Item, you can provide a function which receives the dragged Item as its first argument and should return an array of grids. See more here.

  • Default value: true.
  • Accepted types: boolean, object, function.
// Disable drag sorting.
<MuuriComponent dragSort={false} />
// Enable it only in the MuuriComponent parent.
<MuuriComponent dragSort={true} />
// Enable it only among MuuriComponents of a certain group.
<MuuriComponent groupIds={['GroupA']} dragSort={{groupId: 'GroupA'}} />
import {muuriMap} from 'muuri-react';
// Custom logic.
<MuuriComponent
id={'id'}
groupIds={['groupId']}
dragSort={(item) => {
// Dragged component.
const key = item.getKey();
const data = item.getData();
// Some Muuri instances.
const currentGrid = item.getGrid();
const gridsArray = muuriMap.getGroup('groupId');
const grid = muuriMap.get('id');
// Implement your logic...
// Return an array of Muuri instances into
// which the item can be dragged and sorted.
return anArrayOfGrids;
}}
/>;

dragSortHeuristics

Defines various heuristics so that sorting during drag would be smoother and faster.

  • Default value: {sortInterval: 100, minDragDistance: 10, minBounceBackAngle: 1}.
  • Accepted types: object.

You can define the following properties:

  • sortInterval—  number
    • Default value: 100.
    • Defines the amount of time the dragged Item must be still before dragSortPredicate function is called.
  • minDragDistance—  number
    • Default value: 10.
    • Defines how much (in pixels) the Item must be dragged before dragSortPredicate can be called.
  • minBounceBackAngle—  number
    • Default value: 1.
    • Defines the minimum angle (in radians) of the delta vector between the last movement vector and the current movement vector that is required for the dragged Item to be allowed to be sorted to it's previous index. The problem this heuristic is trying to solve is the scenario where you drag an Item over a much bigger Item and the bigger Item moves, but it's still overlapping the dragged Item after repositioning. Now when you move the dragged Item again another sort is triggered and the bigger Item moves back to it's previous position. This bouncing back and forth can go on for quite a while and it looks quite erratic. The fix we do here is that, by default, we disallow an Item to be moved back to it's previous position, unless it's drag direction changes enough. And what is enough? That's what you can define here. Note that this option works in tandem with minDragDistance and needs it to be set to 3 at minimum to be enabled at all.
<MuuriComponent
dragEnabled={true}
dragSortHeuristics={{
sortInterval: 10,
minDragDistance: 5,
minBounceBackAngle: Math.PI / 2,
}}
/>

dragSortPredicate

Defines the logic for the sort procedure during dragging an Item.

  • Default value: {action: 'move', migrateAction: 'move', threshold: 50}.
  • Accepted types: function, object.

If an object is provided the default sort predicate handler will be used. You can define the following properties:

  • action—  string
    • Default value: 'move'.
    • Allowed values: 'move', 'swap'.
    • Should the dragged Item be moved to the new position or should it swap places with the Item it overlaps?
  • migrateAction—  string
    • Default value: 'move'.
    • Allowed values: 'move', 'swap'.
    • Should the dragged Item be moved to the new position or should it swap places with the Item it overlaps when the dragged Item is moved to another grid?
  • threshold—  number
    • Default value: 50.
    • Allowed values: 1 - 100.
    • How many percent the intersection area between the dragged Item and the compared Item should be from the maximum potential intersection area between the Items before sorting is triggered.

Alternatively you can provide your own callback function where you can define your own custom sort logic. The callback function receives two arguments:

  • item—  Muuri.Item
    • The Item that's being dragged.
  • event—  object
    • The drag event (Muuri.Dragger event).

The callback should return a falsy value if sorting should not occur. If, however, sorting should occur the callback should return an object containing the following properties:

  • index—  number
    • The index where the Item should be moved to.
  • grid—  Muuri
    • The grid where the Item should be moved to.
    • Defaults to the Item's current grid.
    • Optional.
  • action—  string
    • The movement method.
    • Default value: 'move'.
    • Allowed values: 'move' or 'swap'.
    • Optional.
// Customize the default predicate.
<MuuriComponent
dragSortPredicate={{
threshold: 90,
action: 'swap',
}}
/>
// Provide your own predicate.
<MuuriComponent
dragSortPredicate={function (item, e) {
if (e.deltaTime < 1000) return false;
return {
index: Math.round(e.deltaTime / 1000) % 2 === 0 ? -1 : 0,
action: 'swap',
};
}}
/>
import { ItemDrag } from "muuri-react";
// Pro tip: use the default predicate as fallback in your custom predicate.
<MuuriComponent
dragSortPredicate={function (item, e) {
if (item.getElement().classList.contains("no-sort")) return false;
return ItemDrag.defaultSortPredicate(item, {
action: "swap",
threshold: 75
/>
}}
/>

dragRelease

  • Default value: { duration: 300, easing: 'ease', useDragContainer: true }.
  • Accepted types: object.

You can define the following properties:

  • duration — number
    • Default value: 300.
    • The duration for Item's drag release animation. Set to 0 to disable.
  • easing — string
    • Default value: 'ease'.
    • The easing for Item's drag release animation. Accepts any valid Animation easing value.
  • useDragContainer — boolean
    • Default value: true.
    • If true the Item element will remain within the dragContainer for the duration of the release process. Otherwise the Item element will be inserted within the grid element (if not already inside it) at the beginning of the release process.
<MuuriComponent
dragRelease={{
duration: 600,
easing: 'ease-out',
useDragContainer: false,
}}
/>

dragCssProps

Drag specific CSS properties that Muuri sets to the draggable Item elements. Muuri automatically prefixes the properties before applying them to the element. touchAction property is required to be always defined, but the other properties are optional and can be omitted by setting their value to an empty string if you want to e.g. define them via CSS only.

  • Default value: {touchAction: 'none', userSelect: 'none', userDrag: 'none', tapHighlightColor: 'rgba(0, 0, 0, 0)', touchCallout: 'none', contentZooming: 'none'}.
  • Accepted types: object.

You can define the following properties:

// Only set the required touch-action CSS property via the options if you for
// example want to set the other props via CSS instead.
<MuuriComponent
dragEnabled={true}
dragCssProps={{
touchAction: 'pan-y',
userSelect: '',
userDrag: '',
tapHighlightColor: '',
touchCallout: '',
contentZooming: '',
}}
/>

dragPlaceholder

If you want a placeholder Item to appear for the duration of an Item's drag & drop procedure you can enable and configure it here. The placeholder animation duration is fetched from the grid's layoutDuration option and easing from the grid's layoutEasing option. Note that a special placeholder class is given to all drag placeholders and is customizable via itemPlaceholderClass option.

  • Default value: {enabled: false, createElement: null, onCreate: null, onRemove: null}.
  • Accepted types: object.

You can define the following properties:

  • enabled  —  boolean
    • Default value: false.
    • Is the placeholder enabled?
  • createElement  —  function / null
    • Default value: null.
    • If defined, this method will be used to create the DOM element that is used for the placeholder. By default a new div element is created when a placeholder is summoned.
  • onCreate  —  function / null
    • Default value: null.
    • An optional callback that will be called after a placeholder is created for an Item.
  • onRemove  —  function / null
    • Default value: null.
    • An optional callback that will be called after a placeholder is removed from the grid.
<MuuriComponent
dragEnabled={true}
dragPlaceholder={{
enabled: true,
createElement: function (item) {
return item.getElement().cloneNode(true);
},
}}
/>

containerClass

Container element's class name.

  • Default value: 'muuri'.
  • Accepted types: string.
<MuuriComponent containerClass={'foo'} />

itemClass

Item element's class name.

  • Default value: 'muuri-item'.
  • Accepted types: string.
<MuuriComponent itemClass={'foo-item'} />

itemVisibleClass

Visible Item's class name.

  • Default value: 'muuri-item-shown'.
  • Accepted types: string.
<MuuriComponent itemVisibleClass={'foo-item-shown'} />

itemHiddenClass

Hidden Item's class name.

  • Default value: 'muuri-item-hidden'.
  • Accepted types: string.
<MuuriComponent itemHiddenClass={'foo-item-hidden'} />

itemPositioningClass

This class name will be added to the Item element for the duration of positioning.

  • Default value: 'muuri-item-positioning'.
  • Accepted types: string.
<MuuriComponent itemPositioningClass={'foo-item-positioning'} />

itemDraggingClass

This class name will be added to the Item element for the duration of drag.

  • Default value: 'muuri-item-dragging'.
  • Accepted types: string.
<MuuriComponent itemDraggingClass={'foo-item-dragging'} />

itemReleasingClass

This class name will be added to the Item element for the duration of release.

  • Default value: 'muuri-item-releasing'.
  • Accepted types: string.
<MuuriComponent itemReleasingClass={'foo-item-releasing'} />

itemPlaceholderClass

This class name will be added to the drag placeholder element.

  • Default value: 'muuri-item-placeholder'.
  • Accepted types: string.
<MuuriComponent itemPlaceholderClass={'foo-item-placeholder'} />

Event props ⚙️

All the events can be listened through the Muuri instance. Some events can also be listened through the MuuriComponent props for convenience.


onSend

A function called when an Item is transferred from a MuuriComponent to another, if your project use this functionality then it is mandatory to use this property to synchronize the state of the Items with the change. The function will receive the information about the event as its argument as shown in the example above. See more here.

  • Accepted types: function.

Arguments

  • payload.key  —  string
    • The key of the transferred Item.
  • payload.fromId  —  string
    • The id of the old MuuriComponent.
  • payload.fromIndex  —  number
    • The index of the Item in the old MuuriComponent.
  • payload.fromGroupIds  —  string[]
    • The group ids of the old MuuriComponent.
  • payload.fromGrid  —  Muuri
    • The old Muuri instance.
  • payload.toId  —  string
    • The id of the new MuuriComponent.
  • payload.toIndex  —  number
    • The index of the Item in the new MuuriComponent.
  • payload.toGroupIds  —  string[]
    • The group ids of the new MuuriComponent.
  • payload.toGrid  —  Muuri
    • The new Muuri instance.
const [items, setItems] = useState([]);
<MuuriComponent
onSend={function ({
// The key of the transferred item.
key,
// The id of the old MuuriComponent.
fromId,
// The id of the new MuuriComponent.
toId,
}) {
// Sync the state.
}}
/>;

onDragStart

Triggered when dragging of an Item begins.

  • Accepted types: function.

Arguments

  • item  —  Muuri.Item
    • The dragged Item.
  • event  —  object
    • Muuri.Dragger event data.
<MuuriComponent
onDragStart={function (item, event) {
console.log(
item.getKey(),
item.getData(),
item.getGrid(),
item.getElement()
);
}}
/>

onDragEnd

Triggered when dragging of an Item ends.

  • Accepted types: function.

Arguments

  • item  —  Muuri.Item
    • The dragged Item.
<MuuriComponent
onDragEnd={function (item) {
console.log(
item.getKey(),
item.getData(),
item.getGrid(),
item.getElement()
);
}}
/>

onFilter

Triggered when the filter is applied.

  • Accepted types: function.

Arguments

  • shownItems  —  array
    • The Items that are shown.
  • hiddenItems  —  array
    • The Items that are hidden.
<MuuriComponent
onDragEnd={function (shownItems, hiddenItems) {
console.log(shownItems);
console.log(hiddenItems);
}}
/>

onSort

Triggered when the sort is applied.

  • Accepted types: function.

Arguments

  • currentOrder  —  array
    • All Items in their current order.
  • previousOrder  —  array
    • All Items in their previous order.
<MuuriComponent
onDragEnd={function (currentOrder, previousOrder) {
console.log(currentOrder);
console.log(previousOrder);
}}
/>

onMount

A function that will be called when the component will mount, it receive the Muuri instance as argument.

  • Accepted types: function.

Arguments

  • grid  —  Muuri
    • The internal Muuri instance.
<MuuriComponent onMount={function (grid) {}} />

onUnmount

A function that will be called when the component will mount, it receive the Muuri instance as argument.

  • Accepted types: function.

Arguments

  • grid  —  Muuri
    • The internal Muuri instance.
<MuuriComponent onUnmount={function (grid) {}} />