⚠️ Package currently in alpha, please consider that it will be changed in the future.
Svelte-Grid-Extended is a draggable, resizable and responsive grid layout. The package is created as extended verison of svelte-grid, and will implement all of its features in future releases.
With NPM:
npm install svelte-grid-extended
With Yarn:
yarn add svelte-grid-extended
With pnpm:
pnpm install svelte-grid-extended
prop | description | type | default |
---|---|---|---|
cols | Grid columns count. If set to 0, grid will grow infinitly. Must be >= 0. | number | 0 |
rows | Grid rows count. If set to 0, grid will grow infinitly. Must be >= 0. | number | 0 |
itemSize | Size of the grid item. If not set, grid will calculate it based on container size. | { width?: number, height?: number } | {} |
items | Array of grid items. | Layout<T> | requried |
gap | Gap between grid items. | number | 10 |
bounds | Should grid items be bounded by the grid container. | boolean | false |
readonly | If true disables interaction with grid items. | boolean | false |
⚠️ ifcols
or/androws
are set to 0,itemSize.width
or/anditemSize.height
must be setted.
Layout<T>
are represented as an array of objects, items of which must have the following properties:
prop | description | type | default |
---|---|---|---|
id | Unique id of the item. Used to compare items during collision tests | string | requried |
x | X position of the item in grid units. | number | requried |
y | Y position of the item in grid units. | number | requried |
w | Width of the item in grid units. | number | requried |
h | Height of the item in grid units. | number | requried |
movable | If true, item can be moved by user. | boolean | true |
resizable | If true, item can be resized by user. | boolean | true |
data | Custom attributes. 🦌 | T | undefined |
Component can be styled with css framework of your choice or with global classes. To do so, you can use the following props:
class
- class name for grid container.itemClass
- class name for grid item.itemActiveClass
- class name that applies when item is currently being dragged or resized. By default, it is used to make active grid item transparent.itemPreviewClass
- class name for preview where item will be placed after interaction.resizerClass
- class name for item's resize handle.
To understand how to use these props, look at <Grid />
component simplified structure.
📄
active
is variable that indicates if grid item is currently being dragged or resized:
<!-- Grid -->
<div class={class}>
<!-- GridItem -->
<div class={itemClass} class:itemActiveClass={active}>
<slot />
<!-- Resizer -->
<div class={resizerClass} />
<!-- Resizer -->
</div>
{#if active}
<!-- GridItemGhost -->
<div class={itemPreviewClass} />
{/if}
<!-- /GridItem -->
</div>
<!-- /Grid -->
Grid emits the following events:
event name | description | payload |
---|---|---|
change | Emitted when grid items are changed. | {item: LayoutItem} |
<script lang="ts">
import Grid, { type LayoutChangeDetail } from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 3, h: 1 }
];
function hanleGridChange(event: CustomEvent<LayoutChangeDetail>) {
console.log(event.detail.item);
}
</script>
<Grid {items} cols={10} rows={10} on:change={hanleGridChange}>
<div>Content</div>
</Grid>
✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 3, h: 1 }
];
</script>
<Grid {items} cols={10} rows={10}>
<div>Content</div>
</Grid>
When cols
or rows
and itemsSize
are set, grid becomes static and ignores the size of the container.
It can be set to both dimensions or just one.
Both: ✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 1, h: 1 }
];
const itemSize = { width: 100, height: 40 };
</script>
<Grid {items} {itemSize} cols={10} rows={10}>
<div>Content</div>
</Grid>
Only rows: ✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 1, h: 1 }
];
const itemSize = { height: 40 };
</script>
<Grid {items} {itemSize} cols={10} rows={10}>
<div>Content</div>
</Grid>
When cols
or/and rows
set to 0, grid grows infinitly. The grid container adapts its width and height to fit all elements.
It can be set to both dimensions or just one.
✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 1, h: 1 }
];
const itemSize = { width: 100, height: 40 };
</script>
<Grid {items} {itemSize} cols={0} rows={0}>
<div>Content</div>
</Grid>
Grid can be styled with classes passed to various props. Check Style related props section for more info.
✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 1, h: 1 }
];
</script>
<Grid
{items}
class="grid-container"
itemClass="grid-item"
itemActiveClass="grid-item-active"
itemPreviewClass="bg-red-500 rounded"
>
<div>Content</div>
</Grid>
<style>
:global(.grid-container) {
opacity: 0.7;
}
:global(.grid-item) {
transition: width 4s, height 4s;
transition: transform 4s, opacity 4s;
}
:global(.grid-item-active) {
opacity: 0.1;
}
/* tailwind classes */
:global(.bg-red-500) {
background-color: rgb(202, 33, 33);
}
:global(.rounded) {
border-radius: 0.25rem;
}
</style>
To disable interactions, set readOnly
prop to true
. Or set movable
and/or resizable
to false
on specific item.
Read Only grid: ✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1 },
{ id: '1', x: 0, y: 1, w: 1, h: 1 }
];
</script>
<Grid {items} cols={10} rows={10} readOnly>
<div>Content</div>
</Grid>
Make item non-interactive: ✨ repl
<script lang="ts">
import Grid from 'svelte-grid-extended';
const items = [
{ id: '0', x: 0, y: 0, w: 1, h: 1, movable: false },
{ id: '1', x: 0, y: 1, w: 1, h: 1, movable: false, resizable: false }
];
</script>
<Grid {items} cols={10} rows={10}>
<div>Content</div>
</Grid>