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 dae91b83a..2d629098c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -553,8 +553,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: