Skip to content
Merged
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
45 changes: 45 additions & 0 deletions .changeset/media-solid2-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
"@solid-primitives/media": major
"@solid-primitives/event-listener": major
"@solid-primitives/rootless": major
"@solid-primitives/static-store": major
"@solid-primitives/utils": major
---

Migrate to Solid.js v2.0 (beta.7)

## Breaking Changes

**Peer dependency**: `solid-js@^2.0.0-beta.7` and `@solidjs/web@^2.0.0-beta.7` are now required.

### `@solid-primitives/media`

- `isServer` now imported from `@solidjs/web` (not `solid-js/web`)
- Requires Solid.js v2 — `classList` is replaced by `class` with object/array forms in consuming code

### `@solid-primitives/utils`

- `isServer` import moved from `solid-js/web` to `@solidjs/web`
- `createHydratableSignal`: uses `onSettled` (was `onMount`) and `sharedConfig.hydrating` (was `sharedConfig.context`) for hydration detection
- `INTERNAL_OPTIONS`: `{ internal: true }` changed to `{ pureWrite: true }` to match Solid 2.0 `SignalOptions`
- `defaultEquals` now aliases `isEqual` (was `equalFn`)
- `defer`: `AccessorArray<S>` type replaced with `Accessor<S>[]` (type was removed in Solid 2.0)

### `@solid-primitives/static-store`

- `isServer` import moved from `solid-js/web` to `@solidjs/web`
- `createStaticStore`: uses `getObserver` (was `getListener`) and `{ pureWrite: true }` (was `{ internal: true }`)
- Removed explicit `batch()` calls — updates are automatically batched in Solid 2.0
- `createHydratableStaticStore`: uses `onSettled` (was `onMount`) and `sharedConfig.hydrating` (was `sharedConfig.context`)

### `@solid-primitives/rootless`

- `isServer` import moved from `solid-js/web` to `@solidjs/web`
- `createHydratableSingletonRoot`: uses `sharedConfig.hydrating` (was `sharedConfig.context`)
- `createRootPool`: removed `batch()` calls — Solid 2.0 auto-batches on microtasks

### `@solid-primitives/event-listener`

- `isServer` import moved from `solid-js/web` to `@solidjs/web` across all source files
- `createEventListener` and `createRenderEffect` converted to split compute/apply effect pattern required by Solid 2.0
- `eventListener` directive converted to split effect pattern; cleanup is returned from apply phase instead of using `onCleanup`
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"rehype-highlight": "^7.0.2",
"rehype-slug": "^6.0.0",
"remark-gfm": "^4.0.1",
"solid-js": "^1.9.7",
"solid-js": "2.0.0-beta.10",
"typescript": "^5.8.3",
"vinxi": "^0.5.7",
"vite": "^6.3.5",
Expand Down
4 changes: 2 additions & 2 deletions packages/audio/dev/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const App: Component = () => {
<div class="flex flex-col items-center">
<div class="flex items-center justify-center space-x-4 rounded-full bg-white p-1 shadow">
<button
class="scale-200 flex cursor-pointer border-none bg-transparent"
class="flex scale-200 cursor-pointer border-none bg-transparent"
disabled={audio.state == AudioState.ERROR}
onClick={() => setPlaying(audio.state == AudioState.PLAYING ? false : true)}
>
Expand All @@ -97,7 +97,7 @@ const App: Component = () => {
step="0.1"
max={audio.duration}
value={audio.currentTime}
class="form-range w-40 cursor-pointer appearance-none rounded-3xl bg-gray-200 transition hover:bg-gray-300 focus:outline-none focus:ring-0"
class="form-range w-40 cursor-pointer appearance-none rounded-3xl bg-gray-200 transition hover:bg-gray-300 focus:ring-0 focus:outline-none"
/>
<div class="flex px-2">
<Icon class="w-6 text-blue-600" path={speakerWave} />
Expand Down
6 changes: 4 additions & 2 deletions packages/event-listener/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,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"
}
}
2 changes: 1 addition & 1 deletion packages/event-listener/src/components.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isServer } from "solid-js/web";
import { isServer } from "@solidjs/web";
import { keys } from "@solid-primitives/utils";
import { type Component } from "solid-js";
import { makeEventListener } from "./eventListener.js";
Expand Down
35 changes: 23 additions & 12 deletions packages/event-listener/src/eventListener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
tryOnCleanup,
} from "@solid-primitives/utils";
import { type Accessor, createEffect, createRenderEffect, createSignal } from "solid-js";
import { isServer } from "solid-js/web";
import { isServer } from "@solidjs/web";
import type {
EventListenerDirectiveProps,
EventMapOf,
Expand Down Expand Up @@ -110,17 +110,28 @@ export function createEventListener(
): void {
if (isServer) return;

const attachListeners = () => {
asArray(access(targets)).forEach(el => {
if (el) asArray(access(type)).forEach(type => makeEventListener(el, type, handler, options));
});
type State = { els: EventTarget[]; types: string[] };

const compute = (): State => ({
els: asArray(access(targets)).filter(Boolean) as EventTarget[],
types: asArray(access(type)) as string[],
});

const apply = ({ els, types }: State) => {
const cleanups: VoidFunction[] = [];
for (const el of els)
for (const t of types) {
el.addEventListener(t, handler, options);
cleanups.push(el.removeEventListener.bind(el, t, handler, options));
}
return () => cleanups.forEach(c => c());
};

// if the target is an accessor the listeners will be added on the first effect (onMount)
// so that when passed a jsx ref it will be availabe
if (typeof targets === "function") createEffect(attachListeners);
// if the target is an accessor the listeners will be added on the first effect (after mount)
// so that when passed a jsx ref it will be available
if (typeof targets === "function") createEffect(compute, apply);
// if the target prop is NOT an accessor, the event listeners can be added right away
else createRenderEffect(attachListeners);
else createRenderEffect(compute, apply);
}

// Possible targets prop shapes:
Expand Down Expand Up @@ -192,9 +203,9 @@ export function createEventSignal(
* <button use:eventListener={["click", () => {...}]}>Click me!</button>
*/
export const eventListener: Directive<EventListenerDirectiveProps> = (target, props) => {
createEffect(() => {
const [type, handler, options] = props();
makeEventListener(target, type, handler, options);
createEffect(props, ([type, handler, options]) => {
target.addEventListener(type, handler, options);
return () => target.removeEventListener(type, handler, options);
});
};

Expand Down
2 changes: 1 addition & 1 deletion packages/event-listener/src/eventListenerMap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type AnyFunction, entries, type Many, type MaybeAccessor } from "@solid-primitives/utils";
import { createEventListener } from "./eventListener.js";
import type { EventMapOf, TargetWithEventMap, EventListenerOptions } from "./types.js";
import { isServer } from "solid-js/web";
import { isServer } from "@solidjs/web";

export type EventHandlersMap<EventMap> = {
[EventName in keyof EventMap]: (event: EventMap[EventName]) => void;
Expand Down
2 changes: 1 addition & 1 deletion packages/event-listener/src/eventListenerStack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createCallbackStack } from "@solid-primitives/utils";
import { onCleanup } from "solid-js";
import { makeEventListener } from "./eventListener.js";
import type { EventMapOf, TargetWithEventMap, EventListenerOptions } from "./types.js";
import { isServer } from "solid-js/web";
import { isServer } from "@solidjs/web";

export type EventListenerStackOn<EventMap extends Record<string, any>> = {
<T extends keyof EventMap>(
Expand Down
Loading