Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .changeset/masonry-solid2-migration.md
Original file line number Diff line number Diff line change
@@ -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<T>` (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<VoidFunction | undefined>` 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.
2 changes: 1 addition & 1 deletion packages/masonry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
6 changes: 3 additions & 3 deletions packages/masonry/package.json
Original file line number Diff line number Diff line change
@@ -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 <gthetarnav@gmail.com>",
"contributors": [],
Expand Down Expand Up @@ -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:^"
Expand Down
7 changes: 3 additions & 4 deletions packages/masonry/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,18 @@ export function createMasonry<T>(
options: MasonryOptionsNoElements<T> | MasonryOptions<T, any>,
): Accessor<any[]> & { height: Accessor<number> } {
const { source, mapHeight, mapElement } = options,
[memo, setMemo] = createSignal<VoidFunction>(),
[memo, setMemo] = createSignal<VoidFunction | undefined>(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<typeof mapped> => []),
void 0,
{ equals: (a, b) => a.length === b.length },
),
height = setMemo(() =>
Expand Down
71 changes: 37 additions & 34 deletions packages/masonry/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -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", () => {
Expand All @@ -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]);
Expand Down Expand Up @@ -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();
});
});
31 changes: 29 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.