From 034e07c1f4c53a54e7269d4ca190ce66b98aa3e6 Mon Sep 17 00:00:00 2001 From: David Di Biase <1168397+davedbase@users.noreply.github.com> Date: Tue, 5 May 2026 12:59:06 -0400 Subject: [PATCH] Port to Solid 2.0 beta 10 --- .changeset/masonry-solid2-migration.md | 17 ++++++ packages/masonry/README.md | 2 +- packages/masonry/package.json | 6 +-- packages/masonry/src/index.ts | 7 ++- packages/masonry/test/index.test.ts | 71 ++++++++++++++------------ pnpm-lock.yaml | 31 ++++++++++- 6 files changed, 90 insertions(+), 44 deletions(-) create mode 100644 .changeset/masonry-solid2-migration.md diff --git a/.changeset/masonry-solid2-migration.md b/.changeset/masonry-solid2-migration.md new file mode 100644 index 000000000..2754cf245 --- /dev/null +++ b/.changeset/masonry-solid2-migration.md @@ -0,0 +1,17 @@ +--- +"@solid-primitives/masonry": major +--- + +Migrate to Solid.js v2.0 (beta.10) + +## Breaking Changes + +**Peer dependency**: `solid-js@^2.0.0-beta.10` is now required. + +### `@solid-primitives/masonry` + +- `mapArray` callback signature changed: the first argument is now `Accessor` (not `T` directly). The implementation now calls `source()` internally, so the public API is unchanged. +- `createMemo` no longer accepts a separate initial-value argument. The `getColumns` memo options (`equals`) are now passed as the second argument directly. +- `createSignal` with `ownedWrite: true` — allows `createMasonry` to be called from within reactive scopes (component bodies, `createRoot`, effects) without throwing `SIGNAL_WRITE_IN_OWNED_SCOPE`. +- Signal writes inside tests moved outside `createRoot` scope to match Solid 2.0 owned-scope write rules. +- `flush()` added after reactive signal writes in tests to commit pending values before assertions. diff --git a/packages/masonry/README.md b/packages/masonry/README.md index a5e2d5cff..0a8a7ac97 100644 --- a/packages/masonry/README.md +++ b/packages/masonry/README.md @@ -47,7 +47,7 @@ to force the items to wrap. - `mapHeight` - A function that maps the source item to a numeric height value. This function is not reactive, it will be called only once for each item. The value may relate to any unit of your choosing. - To provede a reactice height, return an accessor. + To provide a reactive height, return an accessor. - `mapElement` - A function that maps the source item to an element to render. diff --git a/packages/masonry/package.json b/packages/masonry/package.json index cb47caf34..f130c3adb 100644 --- a/packages/masonry/package.json +++ b/packages/masonry/package.json @@ -1,6 +1,6 @@ { "name": "@solid-primitives/masonry", - "version": "0.1.3", + "version": "1.0.0", "description": "Primitives for creating a reactive masonry layout.", "author": "Damian Tarnawski ", "contributors": [], @@ -52,11 +52,11 @@ "test:ssr": "pnpm run vitest --mode ssr" }, "peerDependencies": { - "solid-js": "^1.6.12" + "solid-js": "^2.0.0-beta.10" }, "devDependencies": { "@solid-primitives/media": "workspace:^", - "solid-js": "^1.9.7" + "solid-js": "2.0.0-beta.10" }, "dependencies": { "@solid-primitives/utils": "workspace:^" diff --git a/packages/masonry/src/index.ts b/packages/masonry/src/index.ts index c14fb1033..61e069382 100644 --- a/packages/masonry/src/index.ts +++ b/packages/masonry/src/index.ts @@ -155,19 +155,18 @@ export function createMasonry( options: MasonryOptionsNoElements | MasonryOptions, ): Accessor & { height: Accessor } { const { source, mapHeight, mapElement } = options, - [memo, setMemo] = createSignal(), + [memo, setMemo] = createSignal(undefined, { ownedWrite: true }), mapped = createMemo( mapArray( source, mapElement && mapElement.length > 1 - ? (source, index) => mapData(source, () => memo()?.(), mapHeight, mapElement, index) - : source => mapData(source, () => memo()?.(), mapHeight, mapElement, noopIndex), + ? (source, index) => mapData(source(), () => memo()?.(), mapHeight, mapElement, index) + : source => mapData(source(), () => memo()?.(), mapHeight, mapElement, noopIndex), ), ), columns = asAccessor(options.columns), getColumns = createMemo( () => Array.from({ length: columns() }, (): ReturnType => []), - void 0, { equals: (a, b) => a.length === b.length }, ), height = setMemo(() => diff --git a/packages/masonry/test/index.test.ts b/packages/masonry/test/index.test.ts index a95858675..9f7395e99 100644 --- a/packages/masonry/test/index.test.ts +++ b/packages/masonry/test/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from "vitest"; -import { createRoot, createSignal } from "solid-js"; +import { createRoot, createSignal, flush } from "solid-js"; import { createMasonry } from "../src/index.js"; describe("createMasonry", () => { @@ -21,6 +21,7 @@ describe("createMasonry", () => { expect(masonry.height()).toBe(4); setSource([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); + flush(); expect(masonry().map(i => i.source)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); expect(masonry().map(i => i.order())).toEqual([0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7]); @@ -102,45 +103,47 @@ describe("createMasonry", () => { }); test("changing columns", () => { - createRoot(dispose => { - const [source] = createSignal([1, 2, 3, 4, 5, 6]); + const source = [1, 2, 3, 4, 5, 6]; + const { dispose, masonry, setColumns } = createRoot(dispose => { const [columns, setColumns] = createSignal(3); const masonry = createMasonry({ - source, + source: () => source, columns, mapHeight: () => 1, }); + return { dispose, masonry, setColumns }; + }); - /* - 1 2 3 - 4 5 6 - */ - - expect(masonry().map(i => i.source)).toEqual(source()); - expect(masonry().map(i => i.order())).toEqual([ - /* 1 */ 0, /* 2 */ 2, /* 3 */ 4, /* 4 */ 1, /* 5 */ 3, /* 6 */ 5, - ]); - expect(masonry().map(i => i.margin())).toEqual([0, 0, 0, 0, 0, 0]); - expect(masonry().map(i => i.column())).toEqual([0, 1, 2, 0, 1, 2]); - expect(masonry.height()).toBe(2); - - setColumns(2); - - /* - 1 2 - 3 4 - 5 6 - */ - - expect(masonry().map(i => i.source)).toEqual(source()); - expect(masonry().map(i => i.order())).toEqual([ - /* 1 */ 0, /* 2 */ 3, /* 3 */ 1, /* 4 */ 4, /* 5 */ 2, /* 6 */ 5, - ]); - expect(masonry().map(i => i.margin())).toEqual([0, 0, 0, 0, 0, 0]); - expect(masonry().map(i => i.column())).toEqual([0, 1, 0, 1, 0, 1]); - expect(masonry.height()).toBe(3); + /* + 1 2 3 + 4 5 6 + */ + + expect(masonry().map(i => i.source)).toEqual(source); + expect(masonry().map(i => i.order())).toEqual([ + /* 1 */ 0, /* 2 */ 2, /* 3 */ 4, /* 4 */ 1, /* 5 */ 3, /* 6 */ 5, + ]); + expect(masonry().map(i => i.margin())).toEqual([0, 0, 0, 0, 0, 0]); + expect(masonry().map(i => i.column())).toEqual([0, 1, 2, 0, 1, 2]); + expect(masonry.height()).toBe(2); + + setColumns(2); + flush(); + + /* + 1 2 + 3 4 + 5 6 + */ + + expect(masonry().map(i => i.source)).toEqual(source); + expect(masonry().map(i => i.order())).toEqual([ + /* 1 */ 0, /* 2 */ 3, /* 3 */ 1, /* 4 */ 4, /* 5 */ 2, /* 6 */ 5, + ]); + expect(masonry().map(i => i.margin())).toEqual([0, 0, 0, 0, 0, 0]); + expect(masonry().map(i => i.column())).toEqual([0, 1, 0, 1, 0, 1]); + expect(masonry.height()).toBe(3); - dispose(); - }); + dispose(); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 726871879..e241e4ebd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -550,8 +550,8 @@ importers: specifier: workspace:^ version: link:../media solid-js: - specifier: ^1.9.7 - version: 1.9.7 + specifier: 2.0.0-beta.10 + version: 2.0.0-beta.10 packages/match: devDependencies: @@ -2366,36 +2366,42 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.1': resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.1': resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.1': resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.1': resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.1': resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [musl] '@parcel/watcher-wasm@2.3.0': resolution: {integrity: sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA==} @@ -2506,36 +2512,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} @@ -2672,56 +2684,67 @@ packages: resolution: {integrity: sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.43.0': resolution: {integrity: sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.43.0': resolution: {integrity: sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.43.0': resolution: {integrity: sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loongarch64-gnu@4.43.0': resolution: {integrity: sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-powerpc64le-gnu@4.43.0': resolution: {integrity: sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.43.0': resolution: {integrity: sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.43.0': resolution: {integrity: sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.43.0': resolution: {integrity: sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.43.0': resolution: {integrity: sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.43.0': resolution: {integrity: sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.43.0': resolution: {integrity: sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==} @@ -5208,24 +5231,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}