From 68b803a17f694231d67499f466a32721159c68a8 Mon Sep 17 00:00:00 2001 From: David Di Biase <1168397+davedbase@users.noreply.github.com> Date: Sun, 3 May 2026 13:02:02 -0400 Subject: [PATCH] Adapt to Solid 2.0 beta 10 --- .../resize-observer-solid2-migration.md | 17 +++++++++ packages/resize-observer/README.md | 8 ++--- packages/resize-observer/package.json | 8 +++-- packages/resize-observer/src/index.ts | 35 +++++++++++-------- packages/resize-observer/test/index.test.ts | 13 ++++--- pnpm-lock.yaml | 7 ++-- 6 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 .changeset/resize-observer-solid2-migration.md diff --git a/.changeset/resize-observer-solid2-migration.md b/.changeset/resize-observer-solid2-migration.md new file mode 100644 index 000000000..7792e6174 --- /dev/null +++ b/.changeset/resize-observer-solid2-migration.md @@ -0,0 +1,17 @@ +--- +"@solid-primitives/resize-observer": major +--- + +Migrate to Solid.js v2.0 (beta.10) + +## Breaking Changes + +**Peer dependencies**: `solid-js@^2.0.0-beta.10` and `@solidjs/web@^2.0.0-beta.10` are now required. + +### `@solid-primitives/resize-observer` + +- `isServer` now imported from `@solidjs/web` (not `solid-js/web`) +- `createResizeObserver`: internal `createEffect` converted to the Solid 2.0 split compute/apply pattern +- `createElementSize`: internal `createEffect` converted to split compute/apply pattern; element cleanup (`unobserve`) is returned from apply phase instead of using `onCleanup` +- `createElementSize`: `sharedConfig.context` replaced with `sharedConfig.hydrating` for hydration detection +- `createStore` setter in consuming code now requires a function argument (Solid 2.0 store API change) diff --git a/packages/resize-observer/README.md b/packages/resize-observer/README.md index 7eb188020..8cfa8d774 100644 --- a/packages/resize-observer/README.md +++ b/packages/resize-observer/README.md @@ -75,8 +75,8 @@ import { createResizeObserver } from "@solid-primitives/resize-observer"; let ref!: HTMLDivElement; -// can in onMount if the target variable isn't yet populated -onMount(() => { +// can use onSettled if the target variable isn't yet populated +onSettled(() => { createResizeObserver(ref, ({ width, height }, el) => { if (el === ref) console.log(width, height); }); @@ -95,10 +95,10 @@ createResizeObserver(targets, ({ width, height }, el) => {}); // updating the signal will unobserve removed elements and observe added ones setTargets(p => [...p, element]); -// createResizeObserver supports top-lever store arrays too +// createResizeObserver supports top-level store arrays too const [targets, setTargets] = createStore([document.body]); createResizeObserver(targets, ({ width, height }, el) => {}); -setTargets(targets.length, element); +setTargets(prev => [...prev, element]); ``` ## `createWindowSize` diff --git a/packages/resize-observer/package.json b/packages/resize-observer/package.json index ae69bcaee..45ce12780 100644 --- a/packages/resize-observer/package.json +++ b/packages/resize-observer/package.json @@ -1,6 +1,6 @@ { "name": "@solid-primitives/resize-observer", - "version": "2.1.5", + "version": "3.0.0", "description": "Reactive primitives for observing resizing of HTML elements.", "author": "Moshe Udimar", "contributors": [ @@ -58,10 +58,12 @@ "@solid-primitives/utils": "workspace:^" }, "peerDependencies": { - "solid-js": "^1.6.12" + "@solidjs/web": "^2.0.0-beta.10", + "solid-js": "^2.0.0-beta.10" }, "typesVersions": {}, "devDependencies": { - "solid-js": "^1.9.7" + "@solidjs/web": "2.0.0-beta.10", + "solid-js": "2.0.0-beta.10" } } diff --git a/packages/resize-observer/src/index.ts b/packages/resize-observer/src/index.ts index 3ed37d9de..4a0485517 100644 --- a/packages/resize-observer/src/index.ts +++ b/packages/resize-observer/src/index.ts @@ -11,7 +11,7 @@ import { filterNonNullable, } from "@solid-primitives/utils"; import { type Accessor, createEffect, onCleanup, sharedConfig } from "solid-js"; -import { isServer } from "solid-js/web"; +import { isServer } from "@solidjs/web"; type ResizeObserverEntryGeneric = ResizeObserverEntry & { readonly target: T }; type ResizeObserverCallbackGeneric = ( @@ -88,11 +88,12 @@ export function createResizeObserver( } }, options); - createEffect((prev: T[]) => { - const refs = filterNonNullable(asArray(access(targets))); - handleDiffArray(refs, prev, observe, unobserve); - return refs; - }, []); + createEffect( + () => filterNonNullable(asArray(access(targets))), + (refs: T[], prev?: T[]) => { + handleDiffArray(refs, prev ?? [], observe, unobserve); + }, + ); } const WINDOW_SIZE_FALLBACK = { width: 0, height: 0 } as const satisfies Size; @@ -177,21 +178,25 @@ export function createElementSize( const isFn = typeof target === "function"; const [size, setSize] = createStaticStore( - sharedConfig.context || isFn ? ELEMENT_SIZE_FALLBACK : getElementSize(target), + sharedConfig.hydrating || isFn ? ELEMENT_SIZE_FALLBACK : getElementSize(target), ); const ro = new ResizeObserver(([e]) => setSize(getElementSize(e!.target))); onCleanup(() => ro.disconnect()); if (isFn) { - createEffect(() => { - const el = target(); - if (el) { - setSize(getElementSize(el)); - ro.observe(el); - onCleanup(() => ro.unobserve(el)); - } - }); + createEffect( + () => (target as Accessor)(), + (el: Element | false | null | undefined) => { + if (el) { + setSize(getElementSize(el)); + ro.observe(el); + return () => ro.unobserve(el); + } else { + setSize(ELEMENT_SIZE_FALLBACK); + } + }, + ); } else { ro.observe(target); onCleanup(() => ro.unobserve(target)); diff --git a/packages/resize-observer/test/index.test.ts b/packages/resize-observer/test/index.test.ts index ad703dbf6..a2fcbf7ee 100644 --- a/packages/resize-observer/test/index.test.ts +++ b/packages/resize-observer/test/index.test.ts @@ -1,6 +1,5 @@ import { describe, test, expect, afterAll } from "vitest"; -import { createRoot, createSignal, onMount } from "solid-js"; -import { createStore } from "solid-js/store"; +import { createRoot, createSignal, createStore, flush, onSettled } from "solid-js"; import { Size, createElementSize, @@ -64,6 +63,7 @@ describe("createResizeObserver", () => { createResizeObserver(div1, () => {}); return dispose; }); + flush(); expect(targets.size).toBe(1); expect(targets.has(div1)).toBeTruthy(); @@ -77,6 +77,7 @@ describe("createResizeObserver", () => { createResizeObserver([div1, div2], () => {}); return dispose; }); + flush(); expect(targets.size).toBe(2); expect(targets.has(div1)).toBeTruthy(); expect(targets.has(div2)).toBeTruthy(); @@ -92,11 +93,13 @@ describe("createResizeObserver", () => { expect(targets.size, "targets shouldn't be connected synchronously").toBe(0); return { dispose, setRefs }; }); + flush(); expect(targets.size).toBe(1); expect(targets.has(div1)).toBeTruthy(); setRefs([div2, div3]); + flush(); expect(targets.size).toBe(2); expect(targets.has(div2)).toBeTruthy(); expect(targets.has(div3)).toBeTruthy(); @@ -112,11 +115,13 @@ describe("createResizeObserver", () => { expect(targets.size, "targets shouldn't be connected synchronously").toBe(0); return { dispose, setRefs }; }); + flush(); expect(targets.size).toBe(1); expect(targets.has(div1)).toBeTruthy(); - setRefs([div2, div3]); + setRefs(() => [div2, div3]); + flush(); expect(targets.size).toBe(2); expect(targets.has(div2)).toBeTruthy(); expect(targets.has(div3)).toBeTruthy(); @@ -158,7 +163,7 @@ describe("createElementSize", () => { expect(size.width).toBe(null); expect(size.height).toBe(null); - onMount(() => { + onSettled(() => { expect(size.width).toBe(100); expect(size.height).toBe(200); dispose(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f59c63a9c..a62d8b76a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -776,9 +776,12 @@ importers: specifier: workspace:^ version: link:../utils devDependencies: + '@solidjs/web': + specifier: 2.0.0-beta.10 + version: 2.0.0-beta.10(solid-js@2.0.0-beta.10) solid-js: - specifier: ^1.9.7 - version: 1.9.7 + specifier: 2.0.0-beta.10 + version: 2.0.0-beta.10 packages/resource: devDependencies: