{"_id":"@arisbh/svelte-mosaic","_rev":"5-373f76fc842e33f67cdf580c655d02da","name":"@arisbh/svelte-mosaic","dist-tags":{"latest":"1.1.3"},"versions":{"1.0.0":{"name":"@arisbh/svelte-mosaic","version":"1.0.0","keywords":["svelte","svelte5","grid","mosaic","drag","draggable","resize","resizable","fluid","responsive","dashboard","layout","accessible","a11y"],"author":{"url":"https://github.com/AristideBH","name":"Aristide Benoist-Hossein"},"license":"MIT","_id":"@arisbh/svelte-mosaic@1.0.0","maintainers":[{"name":"arisbh","email":"aristide.bruneau@gmail.com"}],"homepage":"https://github.com/AristideBH/svelte-grid#readme","bugs":{"url":"https://github.com/AristideBH/svelte-grid/issues"},"dist":{"shasum":"047f943e0b2af06f209152efdbc7e1b1c63df1ec","tarball":"https://registry.npmjs.org/@arisbh/svelte-mosaic/-/svelte-mosaic-1.0.0.tgz","fileCount":28,"integrity":"sha512-QZ5QAqiGbU86QTonB4c7u3U4sh5iLdEIJxZy/lww8Q7f2wNZcDOp8lD8XtoOSLVaz694/p/1+2HvwyYiUNLYDg==","signatures":[{"sig":"MEUCIDLiYk2l2DjTrJiEn2SPphw5Yt3FI8Cf64Psbhy7wydeAiEApgGnu1K6SV9K1w8ByCVTJT9ZkvqPWD8mVE8SHnBSN/k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":79903},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./helper":{"types":"./dist/utils/helper.d.ts","import":"./dist/utils/helper.js","require":"./dist/utils/helper.js"},"./styles":{"import":"./dist/svelte-mosaic.css"}},"gitHead":"1f8e7ffaa579bcaa581af2fae86882d1784416f2","scripts":{"dev":"vite dev","lint":"eslint .","build":"vite build && npm run package","check":"svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","package":"svelte-package -i src/lib","preview":"vite preview","check:watch":"svelte-check --tsconfig ./tsconfig.json --watch"},"_npmUser":{"name":"arisbh","email":"aristide.bruneau@gmail.com"},"repository":{"url":"git+https://github.com/AristideBH/svelte-grid.git","type":"git"},"_npmVersion":"10.9.2","description":"A responsive, draggable and resizable grid layout for Svelte 5. Full TypeScript, runes API, keyboard a11y, programmatic control, and more.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.13.1","typesVersions":{"*":{"helper":["./dist/utils/helper.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","eslint":"^9.0.0","svelte":"^5.0.0","globals":"^15.0.0","prettier":"^3.0.0","tweakpane":"^4.0.5","typescript":"^5.0.0","svelte-check":"^4.0.0","@sveltejs/kit":"^2.0.0","@sveltejs/package":"^2.0.0","typescript-eslint":"^8.0.0","eslint-plugin-svelte":"^2.0.0","@sveltejs/adapter-auto":"^3.0.0","prettier-plugin-svelte":"^3.0.0"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-mosaic_1.0.0_1780303999756_0.14286693683060325","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@arisbh/svelte-mosaic","version":"1.1.0","keywords":["svelte","svelte5","grid","mosaic","drag","draggable","resize","resizable","fluid","responsive","dashboard","layout","accessible","a11y"],"author":{"url":"https://github.com/AristideBH","name":"Aristide Benoist-Hossein"},"license":"MIT","_id":"@arisbh/svelte-mosaic@1.1.0","maintainers":[{"name":"arisbh","email":"aristide.bruneau@gmail.com"}],"homepage":"https://github.com/AristideBH/svelte-grid#readme","bugs":{"url":"https://github.com/AristideBH/svelte-grid/issues"},"dist":{"shasum":"10493e88493ec48c395358ce845520765a3895b0","tarball":"https://registry.npmjs.org/@arisbh/svelte-mosaic/-/svelte-mosaic-1.1.0.tgz","fileCount":3,"integrity":"sha512-zJjBd9yN3DzN4q80FRZ0q0iopnu2yH7fF0Ozry6YkOLtCq/iShsueIfbZxOuceu0eM4aGszej3gjY7UNveme7w==","signatures":[{"sig":"MEUCIQC9/sgmCjPkG40l1EiulFDanJrR2EdM89Qbk14yFYersgIgbAnvKzGf7mCjt5Fb0E653LKceq6g4P4gPiAY3TB4BN8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19173},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./helper":{"types":"./dist/utils/helper.d.ts","import":"./dist/utils/helper.js","require":"./dist/utils/helper.js"},"./styles":{"import":"./dist/svelte-mosaic.css"}},"gitHead":"4a2071324b539a759b5a1558262c2fc8f0fe1ac3","scripts":{"dev":"vite dev","lint":"eslint .","build":"vite build && npm run package","check":"svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","package":"svelte-package -i src/lib","preview":"vite preview","check:watch":"svelte-check --tsconfig ./tsconfig.json --watch"},"_npmUser":{"name":"arisbh","email":"aristide.bruneau@gmail.com"},"repository":{"url":"git+https://github.com/AristideBH/svelte-grid.git","type":"git"},"_npmVersion":"10.9.2","description":"A responsive, draggable and resizable grid layout for Svelte 5. Full TypeScript, runes API, keyboard a11y, programmatic control, and more.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.13.1","typesVersions":{"*":{"helper":["./dist/utils/helper.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","eslint":"^9.0.0","svelte":"^5.0.0","globals":"^15.0.0","prettier":"^3.0.0","tweakpane":"^4.0.5","typescript":"^5.0.0","svelte-check":"^4.0.0","@sveltejs/kit":"^2.0.0","@sveltejs/package":"^2.0.0","typescript-eslint":"^8.0.0","eslint-plugin-svelte":"^2.0.0","@sveltejs/adapter-auto":"^3.0.0","prettier-plugin-svelte":"^3.0.0"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-mosaic_1.1.0_1780406081976_0.9829452341520215","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@arisbh/svelte-mosaic","version":"1.1.1","keywords":["svelte","svelte5","grid","mosaic","drag","draggable","resize","resizable","fluid","responsive","dashboard","layout","accessible","a11y"],"author":{"url":"https://github.com/AristideBH","name":"Aristide Benoist-Hossein"},"license":"MIT","_id":"@arisbh/svelte-mosaic@1.1.1","maintainers":[{"name":"arisbh","email":"aristide.bruneau@gmail.com"}],"homepage":"https://github.com/AristideBH/svelte-grid#readme","bugs":{"url":"https://github.com/AristideBH/svelte-grid/issues"},"dist":{"shasum":"cf361222df9b4f763e6693c7426e66c90b1bb60b","tarball":"https://registry.npmjs.org/@arisbh/svelte-mosaic/-/svelte-mosaic-1.1.1.tgz","fileCount":28,"integrity":"sha512-sVaWUJut40mIODODXr05x9o0gNSl9wgFDMbTcatQlI4AEAkVmX+vnce0MM8+kJbXk/vGTIxhRheCHVUpTL3n7w==","signatures":[{"sig":"MEQCIEJURcwO6NUc/Dm0cdBu5rAbLpkcrLw5FdfuCeWpNUCTAiAKbEKkeT24MoawK61chIpq4sVuUHvMEhexZAR1t8xV2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":90356},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./helper":{"types":"./dist/utils/helper.d.ts","import":"./dist/utils/helper.js","require":"./dist/utils/helper.js"},"./styles":{"import":"./dist/svelte-mosaic.css"}},"gitHead":"76a2ca3a8cab8420d73930a4bd0d4e0f41d8ebc9","scripts":{"dev":"vite dev","lint":"eslint .","build":"vite build && npm run package","check":"svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","package":"svelte-package -i src/lib","preview":"vite preview","check:watch":"svelte-check --tsconfig ./tsconfig.json --watch"},"_npmUser":{"name":"arisbh","email":"aristide.bruneau@gmail.com"},"repository":{"url":"git+https://github.com/AristideBH/svelte-grid.git","type":"git"},"_npmVersion":"10.9.2","description":"A responsive, draggable and resizable grid layout for Svelte 5. Full TypeScript, runes API, keyboard a11y, programmatic control, and more.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.13.1","typesVersions":{"*":{"helper":["./dist/utils/helper.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","eslint":"^9.0.0","svelte":"^5.0.0","globals":"^15.0.0","prettier":"^3.0.0","tweakpane":"^4.0.5","typescript":"^5.0.0","svelte-check":"^4.0.0","@sveltejs/kit":"^2.0.0","@sveltejs/package":"^2.0.0","typescript-eslint":"^8.0.0","eslint-plugin-svelte":"^2.0.0","@sveltejs/adapter-auto":"^3.0.0","prettier-plugin-svelte":"^3.0.0"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-mosaic_1.1.1_1780406786838_0.010366001655462975","host":"s3://npm-registry-packages-npm-production"}},"1.1.2":{"name":"@arisbh/svelte-mosaic","version":"1.1.2","keywords":["svelte","svelte5","grid","mosaic","drag","draggable","resize","resizable","fluid","responsive","dashboard","layout","accessible","a11y"],"author":{"url":"https://github.com/AristideBH","name":"Aristide Benoist-Hossein"},"license":"MIT","_id":"@arisbh/svelte-mosaic@1.1.2","maintainers":[{"name":"arisbh","email":"aristide.bruneau@gmail.com"}],"homepage":"https://github.com/AristideBH/svelte-grid#readme","bugs":{"url":"https://github.com/AristideBH/svelte-grid/issues"},"dist":{"shasum":"dc557c2c2995dcd2ee6c6506637d90ffd85de3ab","tarball":"https://registry.npmjs.org/@arisbh/svelte-mosaic/-/svelte-mosaic-1.1.2.tgz","fileCount":3,"integrity":"sha512-NAX3WUbd0ORmkHuXCa1/nFdsv3H9uWY6Z3/QZfIwyVQf67t/Ccz8uG19UDiRvk8TQqUxl0RwkfBdbKk/c7jLGw==","signatures":[{"sig":"MEUCIGelYqCJ+EV9BCRxRLC5cj4QTgKfMWC/0D6y5PrsQBxgAiEA+H74GNP++JmbEgKNBdMHQaAP8bUkbzf7BtWzGsipb8k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19181},"type":"module","types":"./dist/index.d.ts","svelte":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./helper":{"types":"./dist/utils/helper.d.ts","import":"./dist/utils/helper.js","require":"./dist/utils/helper.js"},"./styles":{"import":"./dist/svelte-mosaic.css"}},"gitHead":"36d0b4e1d598c48ae4d1e950497638f337289cde","scripts":{"dev":"vite dev","lint":"eslint .","build":"vite build && npm run package","check":"svelte-check --tsconfig ./tsconfig.json","format":"prettier --write .","package":"svelte-package -i src/lib","preview":"vite preview","check:watch":"svelte-check --tsconfig ./tsconfig.json --watch"},"_npmUser":{"name":"arisbh","email":"aristide.bruneau@gmail.com"},"repository":{"url":"git+https://github.com/AristideBH/svelte-grid.git","type":"git"},"_npmVersion":"10.9.2","description":"A responsive, draggable and resizable grid layout for Svelte 5. Full TypeScript, runes API, keyboard a11y, programmatic control, and more.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.13.1","typesVersions":{"*":{"helper":["./dist/utils/helper.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","eslint":"^9.0.0","svelte":"^5.0.0","globals":"^15.0.0","prettier":"^3.0.0","tweakpane":"^4.0.5","typescript":"^5.0.0","svelte-check":"^4.0.0","@sveltejs/kit":"^2.0.0","@sveltejs/package":"^2.0.0","typescript-eslint":"^8.0.0","eslint-plugin-svelte":"^2.0.0","@sveltejs/adapter-auto":"^3.0.0","prettier-plugin-svelte":"^3.0.0"},"peerDependencies":{"svelte":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/svelte-mosaic_1.1.2_1780406964162_0.18401281465817942","host":"s3://npm-registry-packages-npm-production"}},"1.1.3":{"name":"@arisbh/svelte-mosaic","version":"1.1.3","description":"A responsive, draggable and resizable grid layout for Svelte 5. Full TypeScript, runes API, keyboard a11y, programmatic control, and more.","type":"module","license":"MIT","author":{"name":"Aristide Benoist-Hossein","url":"https://github.com/AristideBH"},"repository":{"type":"git","url":"git+https://github.com/AristideBH/svelte-grid.git"},"bugs":{"url":"https://github.com/AristideBH/svelte-grid/issues"},"homepage":"https://github.com/AristideBH/svelte-grid#readme","keywords":["svelte","svelte5","grid","mosaic","drag","draggable","resize","resizable","fluid","responsive","dashboard","layout","accessible","a11y"],"scripts":{"dev":"vite dev","build":"vite build && npm run package","preview":"vite preview","package":"svelte-package -i src/lib","check":"svelte-check --tsconfig ./tsconfig.json","check:watch":"svelte-check --tsconfig ./tsconfig.json --watch","lint":"eslint .","format":"prettier --write ."},"exports":{".":{"types":"./dist/index.d.ts","svelte":"./dist/index.js"},"./helper":{"types":"./dist/utils/helper.d.ts","import":"./dist/utils/helper.js","require":"./dist/utils/helper.js"},"./styles":{"import":"./dist/svelte-mosaic.css"}},"svelte":"./dist/index.js","types":"./dist/index.d.ts","typesVersions":{"*":{"helper":["./dist/utils/helper.d.ts"]}},"sideEffects":["**/*.css"],"peerDependencies":{"svelte":"^5.0.0"},"devDependencies":{"@sveltejs/adapter-auto":"^3.0.0","@sveltejs/kit":"^2.0.0","@sveltejs/package":"^2.0.0","eslint":"^9.0.0","eslint-plugin-svelte":"^2.0.0","globals":"^15.0.0","prettier":"^3.0.0","prettier-plugin-svelte":"^3.0.0","svelte":"^5.0.0","svelte-check":"^4.0.0","tweakpane":"^4.0.5","typescript":"^5.0.0","typescript-eslint":"^8.0.0","vite":"^8.0.0"},"_id":"@arisbh/svelte-mosaic@1.1.3","gitHead":"ce36f58889fe750debdb4d2dcafe8d00f5ee503b","_nodeVersion":"22.13.1","_npmVersion":"10.9.2","dist":{"integrity":"sha512-vJf0y5XXJLOr3QsckSS/l4jt+5GTB/NhXWxMeel5KoUwkCi1kjaBAYIw/YO+LYIQ0DR/wOg/BDv2eaRl6R62OQ==","shasum":"2b2a8107d4e547d9df6b6c403cb560896457f2ef","tarball":"https://registry.npmjs.org/@arisbh/svelte-mosaic/-/svelte-mosaic-1.1.3.tgz","fileCount":28,"unpackedSize":90356,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHiTdfWDC9+NrKVngYYW/b25OGwzL5VyIoC6IDEBs811AiAAvgzvgWUAurot1Vd3Op5q/oTwGnurFH0pnDMT3jI0nQ=="}]},"_npmUser":{"name":"arisbh","email":"aristide.bruneau@gmail.com"},"directories":{},"maintainers":[{"name":"arisbh","email":"aristide.bruneau@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/svelte-mosaic_1.1.3_1780407125634_0.6867992017231179"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-01T08:53:19.597Z","modified":"2026-06-02T13:32:05.896Z","1.0.0":"2026-06-01T08:53:19.897Z","1.1.0":"2026-06-02T13:14:42.125Z","1.1.1":"2026-06-02T13:26:26.995Z","1.1.2":"2026-06-02T13:29:24.327Z","1.1.3":"2026-06-02T13:32:05.773Z"},"bugs":{"url":"https://github.com/AristideBH/svelte-grid/issues"},"author":{"name":"Aristide Benoist-Hossein","url":"https://github.com/AristideBH"},"license":"MIT","homepage":"https://github.com/AristideBH/svelte-grid#readme","keywords":["svelte","svelte5","grid","mosaic","drag","draggable","resize","resizable","fluid","responsive","dashboard","layout","accessible","a11y"],"repository":{"type":"git","url":"git+https://github.com/AristideBH/svelte-grid.git"},"description":"A responsive, draggable and resizable grid layout for Svelte 5. Full TypeScript, runes API, keyboard a11y, programmatic control, and more.","maintainers":[{"name":"arisbh","email":"aristide.bruneau@gmail.com"}],"readme":"# svelte-mosaic\n\n<p>\n  <a href=\"https://www.npmjs.com/package/@arisbh/svelte-mosaic\"><img src=\"https://img.shields.io/npm/v/@arisbh/svelte-mosaic?style=for-the-badge\" alt=\"npm version\"/></a>\n  <a href=\"https://www.npmjs.com/package/@arisbh/svelte-mosaic\"><img src=\"https://img.shields.io/npm/dm/@arisbh/svelte-mosaic?style=for-the-badge\" alt=\"npm downloads\"/></a>\n  <img src=\"https://img.shields.io/badge/Svelte-5-FF3E00?style=for-the-badge&logo=svelte\" alt=\"Svelte 5\"/>\n  <img src=\"https://img.shields.io/badge/TypeScript-ready-3178C6?style=for-the-badge&logo=typescript\" alt=\"TypeScript\"/>\n  <a href=\"https://github.com/AristideBH/svelte-grid\"><img src=\"https://img.shields.io/github/stars/AristideBH/svelte-grid?style=for-the-badge\" alt=\"GitHub stars\"/></a>\n</p>\n\n![svelte-mosaic demo](https://s13.gifyu.com/images/bITel.gif)\n\nA responsive, draggable and resizable grid layout for **Svelte 5**, with full TypeScript support, keyboard accessibility, and a programmatic control API.\n\n> **Based on [vaheqelyan/svelte-grid](https://github.com/vaheqelyan/svelte-grid)** (MIT). Svelte 5 migration, TypeScript rewrite, SvelteKit demo, and extended features by [AristideBH](https://github.com/AristideBH).\n\n> **v1 (formerly v6) is a breaking change from the original.** See the [migration guide](#migration-from-svelte-grid-v5) below.\n\n---\n\n## Features\n\n- **Svelte 5 runes API** — `$state`, `$derived`, snippets\n- Full TypeScript — exported types for all props and events\n- Draggable and resizable widgets\n- Fixed / static widgets\n- Responsive breakpoints via `cols` definition\n- Configurable gap between items\n- Custom drag and resize handles\n- Soft autoscroll during drag\n- Fill-space mode\n- Layout serializable as plain JSON\n- No jQuery, no 3rd-party runtime dependencies\n- **Auto-height 1-D lists** — `rowHeight=\"auto\"` for vertical sortable lists where each row sizes to its content\n- **Auto-width 1-D lists** — `colWidth=\"auto\"` for horizontal sortable lists where each item sizes to its content width\n- **Fixed column width** — `colWidth={number}` for shrink-to-fit grid columns\n\n---\n\n## Installation\n\n```bash\nnpm i @arisbh/svelte-mosaic\n```\n\n---\n\n## Basic Usage\n\n```svelte\n<script lang=\"ts\">\n  import Grid from '@arisbh/svelte-mosaic';\n  import { gridHelp } from '@arisbh/svelte-mosaic/helper';\n  import type { GridItem, ColsDefinition } from '@arisbh/svelte-mosaic';\n\n  const cols: ColsDefinition = [[1100, 12], [768, 6], [0, 3]];\n\n  let items = $state<GridItem[]>([\n    {\n      id: '1',\n      data: 'Widget 1',\n      12: gridHelp.item({ x: 0, y: 0, w: 2, h: 2 }),\n      6:  gridHelp.item({ x: 0, y: 0, w: 3, h: 2 }),\n      3:  gridHelp.item({ x: 0, y: 0, w: 3, h: 2 }),\n    },\n    {\n      id: '2',\n      data: 'Widget 2',\n      12: gridHelp.item({ x: 2, y: 0, w: 4, h: 3 }),\n      6:  gridHelp.item({ x: 0, y: 2, w: 6, h: 3 }),\n      3:  gridHelp.item({ x: 0, y: 2, w: 3, h: 3 }),\n    },\n  ]);\n</script>\n\n<Grid bind:items {cols} rowHeight={80} onchange={({ unsafeItem }) => console.log(unsafeItem)}>\n  {#snippet children({ movePointerDown, dataItem, item })}\n    <div onpointerdown={movePointerDown} style=\"height: 100%; padding: 12px;\">\n      <strong>{dataItem.data}</strong>\n      <small>{item.w}×{item.h}</small>\n    </div>\n  {/snippet}\n</Grid>\n```\n\n---\n\n## Grid Props\n\n| Prop | Type | Default | Description |\n|---|---|---|---|\n| `items` | `GridItem[]` | **required** | Array of grid items. Use `bind:items` for two-way binding. |\n| `cols` | `ColsDefinition` | **required** | Breakpoints: `[[maxWidth, cols], ...]` |\n| `rowHeight` | `number \\| \"auto\"` | **required** | Row height in px, or `\"auto\"` for content-driven height in a 1-D vertical list |\n| `colWidth` | `number \\| \"auto\"` | — | Column width in px (shrinks-to-fit), or `\"auto\"` for content-driven width in a 1-D horizontal list |\n| `gap` | `[number, number]` | `[10, 10]` | `[gapX, gapY]` in pixels |\n| `fillSpace` | `boolean` | `false` | Items rearrange around the active item during drag |\n| `fastStart` | `boolean` | `false` | Hide grid until layout is computed on mount |\n| `throttleUpdate` | `number` | `100` | Throttle (ms) for container resize recalculation |\n| `throttleResize` | `number` | `100` | Throttle (ms) for matrix recalc during drag/resize |\n| `sensor` | `number` | `20` | Autoscroll proximity sensor in pixels |\n| `scroller` | `HTMLElement` | `document.documentElement` | Custom scroll container element |\n| `readOnly` | `boolean` | `false` | Globally disable all drag and resize interactions |\n| `rows` | `number` | `0` | Minimum number of visible rows (also the boundary for `bounds`) |\n| `bounds` | `boolean` | `false` | Prevent items from being moved or resized past the `rows` limit |\n| `controller` | `GridController` | — | Programmatic controller. Use `bind:controller` to access it |\n| `autoCompress` | `boolean` | `false` | Automatically compact items upward on every external `items` change |\n| `compact` | `boolean` | `false` | Compact items upward after every drag/resize |\n| `collision` | `\"push\"\\|\"none\"\\|\"compress\"` | `\"push\"` | Collision mode: push others away, allow overlap, or push + compact |\n| `unstyled` | `boolean` | `false` | Strip all cosmetic defaults (shadow, cursor, focus-ring) — ideal for Tailwind/shadcn theming |\n\n---\n\n## Event Callbacks\n\n| Prop | Payload | Description |\n|---|---|---|\n| `onmount` | `{ cols, xPerPx, yPerPx }` | Fired once when the grid initialises and measures its container |\n| `onresize` | `{ cols, xPerPx, yPerPx, width }` | Fired when the container changes width |\n| `onchange` | `{ unsafeItem, id, cols }` | Fired continuously while dragging or resizing |\n| `onpointerup` | `{ id, cols }` | Fired when a drag or resize ends |\n| `ondragstart` | `{ id, cols }` | Fired when a drag begins |\n| `onresizestart` | `{ id, cols }` | Fired when a resize begins |\n| `onexternaldrop` | `{ x, y, w, h, cols, data }` | Fired when an external draggable is dropped onto the grid |\n\n---\n\n## Snippet Parameters\n\nThe `children` snippet receives a single object:\n\n| Parameter | Type | Description |\n|---|---|---|\n| `movePointerDown` | `(e: PointerEvent) => void` | Attach to your drag handle's `onpointerdown` |\n| `resizePointerDown` | `(e: PointerEvent) => void` | Attach to a custom resize handle when `customResizer: true` |\n| `dataItem` | `GridItem` | Full item object (all breakpoints + your data) |\n| `item` | `BreakpointItem` | Item config for the active breakpoint |\n| `index` | `number` | Index in the `items` array |\n\n---\n\n## Item Data Structure\n\nEach item in the `items` array is a `GridItem`:\n\n```ts\ninterface GridItem<TData = unknown> {\n  id: string;                          // unique identifier\n  data?: TData;                        // your custom payload\n  [cols: number]: BreakpointItem;      // layout config per column count\n}\n\ninterface BreakpointItem {\n  x: number;                  // column position (0-based)\n  y: number;                  // row position (0-based)\n  w: number;                  // width in columns\n  h: number;                  // height in rows\n  draggable?: boolean;        // default: true\n  resizable?: boolean;        // default: true\n  fixed?: boolean;            // prevent all interaction\n  customDragger?: boolean;    // use your own drag handle\n  customResizer?: boolean;    // use your own resize handle\n  min?: { w?: number; h?: number };\n  max?: { w?: number; h?: number; y?: number };\n}\n```\n\n---\n\n## Helper Functions\n\n```ts\nimport { gridHelp } from '@arisbh/svelte-mosaic/helper';\n```\n\n| Function | Description |\n|---|---|\n| `gridHelp.item(obj)` | Create a `BreakpointItem` with defaults filled in |\n| `gridHelp.normalize(items, col)` | Remove overlapping items at a given column count |\n| `gridHelp.adjust(items, col)` | Pack items tightly (fill empty spaces) |\n| `gridHelp.compact(items, col)` | Compact items upward (alias for `compactY`) |\n| `gridHelp.findSpace(item, items, cols)` | Find the first free `{x, y}` position for an item |\n| `gridHelp.gridToPixel(item, xPerPx, yPerPx, gapX, gapY)` | Convert grid coords to pixel rect |\n| `gridHelp.pixelToGrid(px, xPerPx, yPerPx, gapX, gapY)` | Convert pixel rect to grid coords |\n\n---\n\n## GridController\n\n`GridController` provides a programmatic API for reading and mutating the grid without touching `items` directly. Obtain an instance with `bind:controller`:\n\n```svelte\n<script lang=\"ts\">\n  import Grid, { GridController } from '@arisbh/svelte-mosaic';\n\n  let controller = $state<GridController | undefined>(undefined);\n</script>\n\n<Grid bind:items {cols} {rowHeight} bind:controller>...</Grid>\n\n<button onclick={() => controller?.addItem({ w: 2, h: 2, data: 'New' })}>Add</button>\n<button onclick={() => controller?.compress()}>Compress</button>\n```\n\n| Method | Returns | Description |\n|---|---|---|\n| `addItem(input)` | `void` | Add a new item; auto-places it if `x`/`y` are omitted |\n| `compress()` | `void` | Compact all items upward, removing gaps |\n| `getFirstAvailablePosition(w, h)` | `{x, y} \\| null` | Find the first free grid cell that fits `w×h` |\n\n---\n\n## Responsive Breakpoints\n\n`cols` is an array of `[maxContainerWidth, columnCount]` tuples, sorted descending:\n\n```ts\nconst cols: ColsDefinition = [\n  [1400, 12],  // ≤ 1400px wide → 12 columns\n  [900,   6],  // ≤  900px wide →  6 columns\n  [0,     3],  // any smaller  →  3 columns\n];\n```\n\nEach item object has a key for every column count it should support:\n\n```ts\n{\n  id: '1',\n  12: gridHelp.item({ x: 0, y: 0, w: 4, h: 2 }),\n   6: gridHelp.item({ x: 0, y: 0, w: 3, h: 2 }),\n   3: gridHelp.item({ x: 0, y: 0, w: 3, h: 3 }),\n}\n```\n\nItems without a breakpoint definition automatically inherit from the closest defined one.\n\n---\n\n## Custom Drag Handle\n\nSet `customDragger: true` on the item's breakpoint config, then attach `movePointerDown` to your handle:\n\n```svelte\n<Grid bind:items {cols} rowHeight={80}>\n  {#snippet children({ movePointerDown, dataItem, item })}\n    <div style=\"height: 100%;\">\n      {#if item.customDragger}\n        <div class=\"handle\" onpointerdown={movePointerDown}>⠿ drag</div>\n      {/if}\n      <p>{dataItem.data}</p>\n    </div>\n  {/snippet}\n</Grid>\n```\n\n---\n\n## CSS Custom Properties\n\nAll visual tokens are exposed as CSS custom properties. Override them on `.svlt-grid-container` (or any ancestor):\n\n```css\n/* Plain CSS */\n:global(.svlt-grid-container) {\n  --svlt-handle-corner: 24px;   /* corner resize handle size */\n  --svlt-handle-edge:   10px;   /* edge resize handle thickness */\n  --svlt-shadow-bg:     rgba(99, 102, 241, 0.2);\n  --svlt-shadow-radius: 6px;\n  --svlt-active-opacity: 0.6;\n  --svlt-cursor-grab:    grab;\n  --svlt-cursor-grabbing: grabbing;\n  --svlt-focus-ring:     #4a90e2;\n  --svlt-handle-color:   rgba(0, 0, 0, 0.4);\n}\n```\n\n**Tailwind / shadcn-svelte** — set `unstyled={true}` on the Grid to remove all opinionated cosmetic defaults, then style with Tailwind utilities or map shadcn tokens:\n\n```css\n/* globals.css — map shadcn tokens to svelte-grid variables */\n:root {\n  --svlt-shadow-bg:     hsl(var(--muted));\n  --svlt-shadow-radius: var(--radius);\n  --svlt-focus-ring:    hsl(var(--ring));\n  --svlt-handle-color:  hsl(var(--muted-foreground));\n}\n```\n\n---\n\n## Svelte Context\n\nAny component rendered inside a Grid snippet can call `getGridContext()` to access live grid metrics without extra prop-drilling:\n\n```svelte\n<script>\n  import { getGridContext } from '@arisbh/svelte-mosaic';\n  const grid = getGridContext(); // returns undefined outside a Grid\n</script>\n\n<p>Column width: {grid?.xPerPx()}px — {grid?.cols()} cols</p>\n<p>Read-only: {grid?.readOnly()}</p>\n```\n\n| Property | Type | Description |\n|---|---|---|\n| `xPerPx()` | `number` | Pixels per column |\n| `yPerPx()` | `number` | Pixels per row (rowHeight) |\n| `cols()` | `number` | Active column count |\n| `gapX()` / `gapY()` | `number` | Gap in pixels |\n| `readOnly()` | `boolean` | Current readOnly state |\n| `collision()` | `string` | Current collision mode |\n\n---\n\n## Styling\n\nUse `:global(...)` to style internal elements:\n\n```svelte\n<style>\n  :global(.svlt-grid-shadow)        { background: rgba(0,0,0,0.12); border-radius: 6px; }\n  :global(.svlt-grid-container)     { background: #f5f5f5; }\n  :global(.svlt-grid-resizer::after){ border-color: white !important; }\n  :global(.svlt-grid-active)        { opacity: 0.8; }\n</style>\n```\n\n| Class | Element |\n|---|---|\n| `.svlt-grid-container` | Outer container div |\n| `.svlt-grid-item` | Wrapper around each item |\n| `.svlt-grid-shadow` | Drop-target indicator during drag/resize |\n| `.svlt-grid-resizer` | Built-in resize handle (bottom-right corner) |\n| `.svlt-grid-active` | Item currently being dragged or resized |\n\n---\n\n## TypeScript\n\nAll types are exported from the main entry point:\n\n```ts\nimport type {\n  GridItem, BreakpointItem, ColsDefinition, Gap, SnippetArgs,\n  ResizeDir, ExternalDropEvent, CollisionBehavior,\n  GridControllerInterface, NewItemInput, PixelRect, GridRect,\n} from '@arisbh/svelte-mosaic';\n\nimport { getGridContext, type GridContext } from '@arisbh/svelte-mosaic';\n```\n\n---\n\n## 1-D Auto Lists\n\n### Vertical — `rowHeight=\"auto\"`\n\nEach row sizes to its own content height. Useful for sortable lists with variable-height cards, wrapping text, or dynamic content. Resize handles are disabled (height is content-owned); drag reorders by midpoint swap.\n\n```svelte\n<script lang=\"ts\">\n  import Grid, { gridHelp } from '@arisbh/svelte-mosaic';\n\n  const COLS = 1;\n  const cols = [[9999, COLS]];\n\n  let items = $state([\n    { id: '1', data: 'Short', [COLS]: gridHelp.item({ x: 0, y: 0, w: 1, h: 1 }) },\n    { id: '2', data: 'A much longer item with wrapping text…', [COLS]: gridHelp.item({ x: 0, y: 1, w: 1, h: 1 }) },\n  ]);\n</script>\n\n<Grid bind:items {cols} rowHeight=\"auto\" gap={[0, 8]} fastStart>\n  {#snippet children({ dataItem, movePointerDown })}\n    <div onpointerdown={movePointerDown}>{dataItem.data}</div>\n  {/snippet}\n</Grid>\n```\n\n> **Constraints:** 1-D (single column) only. Item `y` = order index. `autoCompress` is supported.\n\n---\n\n### Horizontal — `colWidth=\"auto\"`\n\nEach item sizes to its own content width. Useful for tag lists, nav bars, and chip rows. Container shrinks to fit total content width.\n\n```svelte\n<script lang=\"ts\">\n  import Grid, { gridHelp } from '@arisbh/svelte-mosaic';\n\n  const COLS = 4;\n  const cols = [[9999, COLS]];\n\n  let items = $state([\n    { id: '1', data: 'Home',     [COLS]: gridHelp.item({ x: 0, y: 0, w: 1, h: 1 }) },\n    { id: '2', data: 'About',    [COLS]: gridHelp.item({ x: 1, y: 0, w: 1, h: 1 }) },\n    { id: '3', data: 'Services', [COLS]: gridHelp.item({ x: 2, y: 0, w: 1, h: 1 }) },\n    { id: '4', data: 'Contact',  [COLS]: gridHelp.item({ x: 3, y: 0, w: 1, h: 1 }) },\n  ]);\n</script>\n\n<Grid bind:items {cols} rowHeight={48} colWidth=\"auto\" gap={[8, 0]} fastStart>\n  {#snippet children({ dataItem, movePointerDown })}\n    <div onpointerdown={movePointerDown}>{dataItem.data}</div>\n  {/snippet}\n</Grid>\n```\n\n> **Constraints:** 1-D (single row) only. Item `x` = order index. `cols` must match the number of items.\n\n---\n\n## Migration from svelte-grid v5\n\n| v5 (Svelte 3) | v6 (Svelte 5) |\n|---|---|\n| `on:change={handler}` | `onchange={handler}` |\n| `on:mount={handler}` | `onmount={handler}` |\n| `on:resize={handler}` | `onresize={handler}` |\n| `on:pointerup={handler}` | `onpointerup={handler}` |\n| `let:item let:index let:movePointerDown ...` | `{#snippet children({ item, index, movePointerDown, ... })}` |\n| `import gridHelp from 'svelte-grid/build/helper'` | `import { gridHelp } from '@arisbh/svelte-mosaic/helper'` |\n| `export let items` (implicit bind) | `bind:items` (explicit two-way binding) |\n\n---\n\n## License\n\nMIT © [Vahe Araqelyan](https://github.com/vaheqelyan) (original library)  \nMIT © [AristideBH](https://github.com/AristideBH) (Svelte 5 migration & new features)\n","readmeFilename":"README.md"}