{"id":31516070,"url":"https://github.com/cuire/svelte-grid-extended","last_synced_at":"2025-10-03T05:02:01.840Z","repository":{"id":62075131,"uuid":"538170740","full_name":"cuire/svelte-grid-extended","owner":"cuire","description":"A draggable and resizable grid layout, for Svelte","archived":false,"fork":false,"pushed_at":"2024-11-25T16:03:53.000Z","size":1900,"stargazers_count":112,"open_issues_count":25,"forks_count":15,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-09-30T12:53:41.677Z","etag":null,"topics":["drag","dragable","grid","resizable","resize","svelte"],"latest_commit_sha":null,"homepage":"https://svelte-grid-extended.vercel.app","language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cuire.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-18T16:31:36.000Z","updated_at":"2025-09-18T07:10:58.000Z","dependencies_parsed_at":"2024-02-19T15:10:51.998Z","dependency_job_id":"cf3a214d-96ab-4c85-a2fe-02149820e257","html_url":"https://github.com/cuire/svelte-grid-extended","commit_stats":{"total_commits":77,"total_committers":3,"mean_commits":"25.666666666666668","dds":"0.18181818181818177","last_synced_commit":"f9a81666433c2867b20d38799ebe6110cb9502de"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/cuire/svelte-grid-extended","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuire%2Fsvelte-grid-extended","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuire%2Fsvelte-grid-extended/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuire%2Fsvelte-grid-extended/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuire%2Fsvelte-grid-extended/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cuire","download_url":"https://codeload.github.com/cuire/svelte-grid-extended/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuire%2Fsvelte-grid-extended/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278014390,"owners_count":25915449,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-02T02:00:08.890Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drag","dragable","grid","resizable","resize","svelte"],"created_at":"2025-10-03T05:00:45.753Z","updated_at":"2025-10-03T05:02:01.832Z","avatar_url":"https://github.com/cuire.png","language":"Svelte","funding_links":[],"categories":["Svelte"],"sub_categories":[],"readme":"# svelte-grid-extended 🍾\n\n[![npm version](https://badge.fury.io/js/svelte-grid-extended.svg)](https://badge.fury.io/js/svelte-grid-extended)\n\n\u003c!-- image at .github/images/santa.gif --\u003e\n\u003cimg src=\".github/images/santa.gif\" width=\"100%\" /\u003e\n\n## Description\n\nSvelte-Grid-Extended is a draggable, resizable ~~and responsive~~ grid layout. The package is created as extended verison of [svelte-grid](https://github.com/vaheqelyan/svelte-grid).\n\n## Installation\n\nWith NPM:\n\n```sh\nnpm install svelte-grid-extended\n```\n\nWith Yarn:\n\n```shPackage currently in alpha, please consider that it **will** be changed in the future\nyarn add svelte-grid-extended\n```\n\nWith pnpm:\n\n```sh\npnpm add svelte-grid-extended\n```\n\n### Table of Contents\n\n- [Description](#description)\n- [Installation](#installation)\n- [Table of Contents](#table-of-contents)\n- [Usage](#usage)\n- [Basic](#basic)\n- [Static grid](#static-grid)\n- [Grid without bounds](#grid-without-bounds)\n- [Styling](#styling)\n- [Disable interactions](#disable-interactions)\n- [Collision Behavior](#collision-behavior)\n  - [None](#none)\n  - [Push](#push)\n  - [Compress](#compress)\n- [Custom move/resize handle](#custom-moveresize-handle)\n- [Two way binding](#two-way-binding)\n- [API Documentation](#api-documentation)\n- [Grid props](#grid-props)\n- [GridItem props](#griditem-props)\n- [Style related props:](#style-related-props)\n- [Events](#events)\n- [Grid Controller](#grid-controller)\n- [Methods](#methods)\n  - [getFirstAvailablePosition(w, h)](#getfirstavailablepositionw-h)\n  - [Example](#example)\n- [📜 License](#-license)\n\n## Usage\n\n### Basic\n\n✨ [repl](https://svelte.dev/repl/effd88614c0c4372864ebeb582415a21?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\u003c/script\u003e\n\n\u003cGrid cols={10} rows={10}\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\"\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\"\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\n### Static grid\n\nWhen `cols` or `rows` and `itemsSize` are set, grid becomes static and ignores the size of the container.\n\nIt can be set to both dimensions or just one.\n\nBoth:\n✨ [repl](https://svelte.dev/repl/7d431c0884d343529e5e98fcbe74afbd?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tconst itemSize = { width: 100, height: 40 };\n\u003c/script\u003e\n\n\u003cGrid {itemSize} cols={10} rows={10}\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\"\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\"\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\nOnly rows:\n✨ [repl](https://svelte.dev/repl/53994707c9f84d2cad2f9eac5a9f9ea6?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tconst itemSize = { height: 40 };\n\u003c/script\u003e\n\n\u003cGrid {itemSize} cols={10} rows={10}\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\"\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\"\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\n### Grid without bounds\n\nWhen `cols` or/and `rows` set to 0, grid grows infinitly. The grid container adapts its width and height to fit all elements.\n\nIt can be set to both dimensions or just one.\n\n✨ [repl](https://svelte.dev/repl/ade95bbc3a7445518df6a51c3fd9be2e?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tconst itemSize = { width: 100, height: 40 };\n\u003c/script\u003e\n\n\u003cGrid {itemSize} cols={0} rows={0}\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\"\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\"\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\n### Styling\n\nGrid can be styled with classes passed to various props. Check [Style related props](#style-related-props) section for more info.\n\n✨ [repl](https://svelte.dev/repl/97243bc1472d42ff944e47c30b72d73d?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\u003c/script\u003e\n\n\u003cGrid class=\"grid-container\" cols={10} rows={10}\u003e\n\t\u003cGridItem\n\t\tx={0}\n\t\ty={0}\n\t\tclass=\"grid-item\"\n\t\tactiveClass=\"grid-item-active\"\n\t\tpreviewClass=\"bg-green-500 rounded\"\n\t\tresizerClass=\"\"\n\t\u003e\n\t\t\u003cdiv class=\"item\"\u003e{item.id}\u003c/div\u003e\n\t\u003c/GridItem\u003e\n\u003c/Grid\u003e\n\n\u003cstyle\u003e\n\t:global(.grid-container) {\n\t\topacity: 0.7;\n\t}\n\n\t:global(.grid-item) {\n\t\ttransition:\n\t\t\twidth 4s,\n\t\t\theight 4s;\n\t\ttransition:\n\t\t\ttransform 4s,\n\t\t\topacity 4s;\n\t}\n\n\t:global(.grid-item-active) {\n\t\topacity: 0.1;\n\t}\n\n\t/* tailwind classes */\n\t:global(.bg-red-500) {\n\t\tbackground-color: rgb(202, 33, 33);\n\t}\n\n\t:global(.rounded) {\n\t\tborder-radius: 0.25rem;\n\t}\n\u003c/style\u003e\n```\n\n### Disable interactions\n\nTo disable interactions, set `readOnly` prop to `true`. Or set `movable` and/or `resizable` to `false` on specific item.\n\nRead Only grid: ✨ [repl](https://svelte.dev/repl/e7183ff3136c47fe94fcd5398573aef5?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\u003c/script\u003e\n\n\u003cGrid cols={10} rows={10} readOnly\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\"\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\"\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\nMake item non-interactive: ✨ [repl](https://svelte.dev/repl/50f1acb8be5b426896cb6d9b6c10e9f8?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\u003c/script\u003e\n\n\u003cGrid cols={10} rows={10}\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\" movable={false}\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\" resizable={false}\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\n### Collision Behavior\n\nThe `collision` prop controls how the grid handles collisions. There are three available options: `none`, `push`, and `compress`.\n\n#### None\n\nSetting `collision` prop to `none` will ignore any collisions. This is the default behavior.\n\n✨ [repl](https://svelte.dev/repl/c549a05c30b84793b2bab156f49bedd3?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tconst items = [\n\t\t{ id: '0', x: 0, y: 0, w: 2, h: 5 },\n\t\t{ id: '1', x: 2, y: 2, w: 2, h: 2 },\n\t\t{ id: '2', x: 2, y: 0, w: 1, h: 2 },\n\t\t{ id: '3', x: 3, y: 0, w: 2, h: 2 },\n\t\t{ id: '4', x: 4, y: 2, w: 1, h: 3 },\n\t\t{ id: '5', x: 8, y: 0, w: 2, h: 8 }\n\t];\n\n\tconst itemSize = { height: 40 };\n\u003c/script\u003e\n\n\u003cGrid {itemSize} cols={10} collision=\"none\"\u003e\n\t{#each items as item}\n\t\t\u003cGridItem x={item.x} y={item.y} w={item.w} h={item.h}\u003e\n\t\t\t\u003cdiv class=\"item\"\u003e{item.id}\u003c/div\u003e\n\t\t\u003c/GridItem\u003e\n\t{/each}\n\u003c/Grid\u003e\n```\n\n#### Push\n\nSetting `collision` prop to `push` will cause grid items to move to the first available space when colliding. The grid will grow vertically as needed to accommodate all items.\n\n✨ [repl](https://svelte.dev/repl/36abb5e5be6f4b0ebe637b2676ccf606?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tconst items = [\n\t\t{ id: '0', x: 0, y: 0, w: 2, h: 5 },\n\t\t{ id: '1', x: 2, y: 2, w: 2, h: 2 },\n\t\t{ id: '2', x: 2, y: 0, w: 1, h: 2 },\n\t\t{ id: '3', x: 3, y: 0, w: 2, h: 2 },\n\t\t{ id: '4', x: 4, y: 2, w: 1, h: 3 },\n\t\t{ id: '5', x: 8, y: 0, w: 2, h: 8 }\n\t];\n\n\tconst itemSize = { height: 40 };\n\u003c/script\u003e\n\n\u003cGrid {itemSize} cols={10} collision=\"push\"\u003e\n\t{#each items as item}\n\t\t\u003cGridItem x={item.x} y={item.y} w={item.w} h={item.h}\u003e\n\t\t\t\u003cdiv class=\"item\"\u003e{item.id}\u003c/div\u003e\n\t\t\u003c/GridItem\u003e\n\t{/each}\n\u003c/Grid\u003e\n```\n\n#### Compress\n\nSetting `collision` prop to `compress` will compress items vertically towards the top into any available space when colliding. The grid will grow vertically as needed to accommodate all items.\n\n✨ [repl](https://svelte.dev/repl/86cff54f2efa437285c3245ecb713702?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tconst items = [\n\t\t{ id: '0', x: 0, y: 0, w: 2, h: 5 },\n\t\t{ id: '1', x: 2, y: 2, w: 2, h: 2 },\n\t\t{ id: '2', x: 2, y: 0, w: 1, h: 2 },\n\t\t{ id: '3', x: 3, y: 0, w: 2, h: 2 },\n\t\t{ id: '4', x: 4, y: 2, w: 1, h: 3 },\n\t\t{ id: '5', x: 8, y: 0, w: 2, h: 8 }\n\t];\n\n\tconst itemSize = { height: 40 };\n\u003c/script\u003e\n\n\u003cGrid {itemSize} cols={10} collision=\"compress\"\u003e\n\t{#each items as item}\n\t\t\u003cGridItem x={item.x} y={item.y} w={item.w} h={item.h}\u003e\n\t\t\t\u003cdiv class=\"item\"\u003e{item.id}\u003c/div\u003e\n\t\t\u003c/GridItem\u003e\n\t{/each}\n\u003c/Grid\u003e\n```\n\n\u003e ⚠️ Setting `collision` to `push` or `compress` will set `rows` to `0` so `ItemSize.height` must be setted.\n\n### Custom move/resize handle\n\n✨ [repl](https://svelte.dev/repl/5f9dbbd845cc40f6a222734856fc9b1d?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\u003c/script\u003e\n\n\u003cGrid cols={10} rows={10}\u003e\n\t\u003cGridItem x={0} y={0}\u003e\n\t\t\u003cdiv slot=\"moveHandle\" let:moveStart\u003e\n\t\t\t\u003cdiv on:pointerdown={moveStart}\u003eMOVE\u003c/div\u003e\n\t\t\u003c/div\u003e\n\n\t\t\u003cdiv slot=\"resizeHandle\" let:resizeStart\u003e\n\t\t\t\u003cdiv on:pointerdown={resizeStart}\u003eResize\u003c/div\u003e\n\t\t\u003c/div\u003e\n\n\t\t\u003c!-- content --\u003e\n\t\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\n### Two way binding\n\n✨ [repl](https://svelte.dev/repl/ef5d5716505642b7a9212c3d0c7b6803?version=4.1.1)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem } from 'svelte-grid-extended';\n\n\tlet items = [\n\t\t{ x: 6, y: 0, w: 2, h: 2, data: { text: '🎅' } },\n\t\t{ x: 6, y: 2, w: 2, h: 2, data: { text: '🤶' } }\n\t];\n\n\tconst itemsBackup = structuredClone(items);\n\n\tfunction resetGrid() {\n\t\titems = structuredClone(itemsBackup);\n\t}\n\u003c/script\u003e\n\n\u003cbutton on:click={resetGrid}\u003e RESET \u003c/button\u003e\n\n\u003cGrid cols={10} {itemSize}\u003e\n\t{#each items as item}\n\t\t\u003cGridItem bind:x={item.x} bind:y={item.y} bind:w={item.w} bind:h={item.h}\u003e\n\t\t\t{item.data.text}\n\t\t\u003c/GridItem\u003e\n\t{/each}\n\u003c/Grid\u003e\n```\n\n## API Documentation\n\n### Grid props\n\n| prop         | description                                                                                                            | type                                | default |\n| ------------ | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ------- |\n| cols         | Grid columns count. If set to 0, grid will grow infinitly. Must be \u003e= 0.                                               | number                              | 0       |\n| rows         | Grid rows count. If set to 0, grid will grow infinitly. Must be \u003e= 0.                                                  | number                              | 0       |\n| itemSize     | Size of the grid item. If not set, grid will calculate it based on container size.                                     | { width?: number, height?: number } | {}      |\n| gap          | Gap between grid items.                                                                                                | number                              | 10      |\n| bounds       | Should grid items be bounded by the grid container.                                                                    | boolean                             | false   |\n| readonly     | If true disables interaction with grid items.                                                                          | boolean                             | false   |\n| collision    | Collision behavior of grid items. [About](#collision-behavior)                                                         | none \\| push \\| compress            | none    |\n| autoCompress | Auto compress the grid items when programmatically changing grid items. Only works with 'compress' collision strategy. | boolean                             | true    |\n\n\u003e ⚠️ if `cols` or/and `rows` are set to 0, `itemSize.width` or/and `itemSize.height` must be setted.\n\n\u003e ⚠️ Setting `collision` to `push` or `compress` will set `rows` to `0` so `ItemSize.height` must be setted.\n\n### GridItem props\n\n| prop      | description                                                                                        | type                                  | default        |\n| --------- | -------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------- |\n| id        | Unique id of the item. Used to compare items during collision tests                                | string                                | uuid.v4        |\n| x         | X position of the item in grid units.                                                              | number                                | required       |\n| y         | Y position of the item in grid units.                                                              | number                                | required       |\n| w         | Width of the item in grid units.                                                                   | number                                | 1              |\n| h         | Height of the item in grid units.                                                                  | number                                | 1              |\n| min       | Minimum size of the item in Grid Units.                                                            | { w: number, h: number }              | { w: 1, h: 1 } |\n| max       | Maximum size of the item in Grid Units. If not provided, the item will be able to grow infinitely. | { w: number, h: number } \\| undefined | undefined      |\n| movable   | If true, item can be moved by user.                                                                | boolean                               | true           |\n| resizable | If true, item can be resized by user.                                                              | boolean                               | true           |\n\n### Style related props:\n\nComponent can be styled with css framework of your choice, global classes or `style` prop. To do so, you can use the following props:\n\n- `\u003cGrid class=\"...\" /\u003e` - class name for grid container.\n- `\u003cGrid style=\"...\" /\u003e` - inline style for grid container.\n- `\u003cGridItem class=\"...\" /\u003e` - class name for grid item.\n- `\u003cGridItem activeClass=\"...\" /\u003e` - class name that applies when item is currently being dragged or resized. By default, it is used to make active grid item transparent.\n- `\u003cGridItem previewClass=\"...\" /\u003e` - class name for preview where item will be placed after interaction.\n- `\u003cGridItem resizerClass=\"...\" /\u003e` - class name for item's resize handle.\n- `\u003cGridItem style=\"...\" /\u003e` - inline style for grid item.\n\nTo understand how to use these props, look at `\u003cGrid /\u003e` component simplified structure.\n\n\u003e 📄 `active` is variable that indicates if grid item is currently being dragged or resized:\n\n```svelte\n\u003c!-- Grid --\u003e\n\u003cdiv class={class}\u003e\n\t\u003c!-- GridItem --\u003e\n\t\u003cdiv class={itemClass} class:activeClass={active}\u003e\n\t\t\u003cslot /\u003e\n\t\t\u003c!-- Resizer --\u003e\n\t\t\u003cdiv class={resizerClass} /\u003e\n\t\t\u003c!-- Resizer --\u003e\n\t\u003c/div\u003e\n\n\t{#if active}\n\t\t\u003c!-- GridItemGhost --\u003e\n\t\t\u003cdiv class={previewClass} /\u003e\n\t{/if}\n\n\t\u003c!-- /GridItem --\u003e\n\u003c/div\u003e\n\u003c!-- /Grid --\u003e\n```\n\n## Events\n\nGrid emits the following events:\n\n| event name | description                          | payload            |\n| ---------- | ------------------------------------ | ------------------ |\n| change     | Emitted when grid items are changed. | {item: LayoutItem} |\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem, type LayoutChangeDetail } from 'svelte-grid-extended';\n\n\tfunction logItem(event: CustomEvent\u003cLayoutChangeDetail\u003e) {\n\t\tconsole.log(event.detail.item);\n\t}\n\u003c/script\u003e\n\n\u003cGrid cols={10} rows={10} on:change={logItem}\u003e\n\t\u003cGridItem x={1} y={0} class=\"item\" on:change={logItem}\u003eHey\u003c/GridItem\u003e\n\t\u003cGridItem x={3} y={3} w={4} class=\"item\" on:previewchange={logItem}\u003eHoy\u003c/GridItem\u003e\n\u003c/Grid\u003e\n```\n\n## Grid Controller\n\nThe Grid Controller provides utility functions that allow for more advanced control and customization of the grid. It's obtained from the Grid component using the `bind:controller` attribute, offering a way to interact with the grid in a programmatic and flexible manner.\n\n### Methods\n\n#### getFirstAvailablePosition(w, h)\n\nFinds the first available position within the grid that can accommodate an item of the specified width (w) and height (h). This method is useful when dynamically adding new items to the grid, ensuring that they fit into the first available space that can hold them.\n\n**Parameters:**\n\n- `w` (number): Width of the item.\n- `h` (number): Height of the item.\n\n**Returns:**\n\n- An object containing the `x` and `y` coordinates of the first available position, or `null` if no position is available.\n\n##### Example\n\n✨ [repl](https://svelte.dev/repl/6af014e1f754458dbc15c1823dbdca3c?version=4.1.2)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem, type GridController } from 'svelte-grid-extended';\n\n\tlet items = [\n\t\t{ id: '1', x: 0, y: 0, w: 2, h: 5 },\n\t\t{ id: '2', x: 2, y: 2, w: 2, h: 2 }\n\t];\n\n\tlet gridController: GridController;\n\n\tfunction addNewItem() {\n\t\tconst w = Math.floor(Math.random() * 2) + 1;\n\t\tconst h = Math.floor(Math.random() * 5) + 1;\n\t\tconst newPosition = gridController.getFirstAvailablePosition(w, h);\n\t\titems = newPosition\n\t\t\t? [...items, { id: crypto.randomUUID(), x: newPosition.x, y: newPosition.y, w, h }]\n\t\t\t: items;\n\t}\n\n\tconst itemSize = { height: 40 };\n\u003c/script\u003e\n\n\u003cbutton on:click={addNewItem}\u003eAdd New Item\u003c/button\u003e\n\n\u003cGrid {itemSize} cols={10} collision=\"push\" bind:controller={gridController}\u003e\n\t{#each items as { id, x, y, w, h } (id)}\n\t\t\u003cdiv transition:fade={{ duration: 300 }}\u003e\n\t\t\t\u003cGridItem {id} bind:x bind:y bind:w bind:h\u003e\n\t\t\t\t\u003cdiv\u003e{id}\u003c/div\u003e\n\t\t\t\u003c/GridItem\u003e\n\t\t\u003c/div\u003e\n\t{/each}\n\u003c/Grid\u003e\n```\n\n#### compress()\n\nCompresses all items vertically towards the top into any available space.\n\n##### Example\n\n✨ [repl](https://svelte.dev/repl/79bcc70f11944d9e9b03970de731b3e2?version=4.2.11)\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n\timport Grid, { GridItem, type GridController } from 'svelte-grid-extended';\n\n\tlet items = [\n\t\t{ id: '1', x: 0, y: 0, w: 2, h: 5 },\n\t\t{ id: '2', x: 2, y: 2, w: 2, h: 2 }\n\t];\n\n\tlet gridController: GridController;\n\n\tfunction compressItems() {\n\t\tgridController.compress();\n\t}\n\n\tconst itemSize = { height: 40 };\n\u003c/script\u003e\n\n\u003cbutton class=\"btn\" on:click={compressItems}\u003eCompress Items\u003c/button\u003e\n\n\u003cGrid {itemSize} cols={10} collision=\"push\" bind:controller={gridController}\u003e\n\t{#each items as item (item.id)}\n\t\t\u003cGridItem id={item.id} bind:x={item.x} bind:y={item.y} bind:w={item.w} bind:h={item.h}\u003e\n\t\t\t\u003cdiv class=\"item\"\u003e{item.id.slice(0, 5)}\u003c/div\u003e\n\t\t\u003c/GridItem\u003e\n\t{/each}\n\u003c/Grid\u003e\n```\n\n## 📜 License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuire%2Fsvelte-grid-extended","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcuire%2Fsvelte-grid-extended","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuire%2Fsvelte-grid-extended/lists"}