diff --git a/packages/audio/dev/index.tsx b/packages/audio/dev/index.tsx index b9dea4595..6df2ad096 100644 --- a/packages/audio/dev/index.tsx +++ b/packages/audio/dev/index.tsx @@ -76,7 +76,7 @@ const App: Component = () => {
+ + +// Suspends until first GPS fix, then updates live: + + + ``` #### Definition @@ -64,16 +126,16 @@ console.log(watcher.error); ```ts createGeolocationWatcher( enabled: MaybeAccessor, - options: MaybeAccessor + options?: MaybeAccessor ): { - location: GeolocationCoordinates | null, - error: GeolocationPositionError | null + location: Accessor; + error: Accessor; } ``` -#### Types +--- -The values returned in the location property are as follows: +## Types ```ts interface GeolocationCoordinates { @@ -87,7 +149,7 @@ interface GeolocationCoordinates { } ``` -The options property defaults to the following value unless overwritten: +Default position options (overridden by anything you pass): ```ts const geolocationDefaults: PositionOptions = { @@ -103,10 +165,8 @@ You may view a working example here: https://stackblitz.com/edit/vitejs-vite-dvk ## Primitive Ideas -We're always looking to enhance our primitives. Some ideas: - -- `createDistance` (supply a lat/lng and reactively calculate the difference in km/m) -- `createWithinRadius` (a signal for tracking if a user is within a radius boundary) +- `createDistance` — supply a lat/lng and reactively calculate the distance in km/m +- `createWithinRadius` — a signal for tracking if a user is within a radius boundary ## Changelog diff --git a/packages/geolocation/dev/client.tsx b/packages/geolocation/dev/client.tsx index 3704c65eb..e56af6c65 100644 --- a/packages/geolocation/dev/client.tsx +++ b/packages/geolocation/dev/client.tsx @@ -1,19 +1,20 @@ -import { type Component, createEffect, onMount, Show } from "solid-js"; -import { createGeolocation } from "../src/index.js"; +import { type Component, Suspense, Show, createEffect, onMount } from "solid-js"; +import { createGeolocationWatcher } from "../src/index.js"; import * as L from "leaflet"; - import "leaflet/dist/leaflet.css"; const Client: Component = () => { - let ref: HTMLDivElement; + let ref!: HTMLDivElement; let map: L.Map; - let marker: L.Marker; - const [location] = createGeolocation({ + let marker: L.Marker | undefined; + + const { location, error } = createGeolocationWatcher(true, { enableHighAccuracy: false, maximumAge: 0, timeout: Number.POSITIVE_INFINITY, }); + onMount(() => { map = L.map(ref).setView([37.0643592, -26.1593362], 1); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { @@ -21,35 +22,44 @@ const Client: Component = () => { attribution: "© OpenStreetMap", }).addTo(map); }); + createEffect(() => { - const coordinates = location(); - if (map && coordinates && !location.error) { - const latLng: L.LatLngExpression = [coordinates.latitude, coordinates.longitude]; + const coords = location(); + if (map && coords) { + const latLng: L.LatLngExpression = [coords.latitude, coords.longitude]; + marker?.remove(); map.setView(latLng, 14); marker = L.marker(latLng).addTo(map); } }); + return (
Could not detect coordinates, check permissions.
} - when={!location.error} - > -
+ fallback={
- Accuracy: {(location()?.accuracy || 0).toFixed(2)} + Could not detect coordinates: {error()?.message ?? "unknown error"} +
+ } + when={!error()} + > + Acquiring GPS fix...
}> +
+
+ Accuracy: {(location().accuracy ?? 0).toFixed(2)} +
+
+ Altitude: {(location().altitude ?? 0).toFixed(2)} +
- Altitude: {(location()?.altitude || 0).toFixed(2)} + {location().latitude}, {location().longitude}
-
+ -
(ref = el)} /> -
- {location()?.latitude}, {location()?.longitude} -
+
(ref = el)} />
diff --git a/packages/geolocation/package.json b/packages/geolocation/package.json index aeaa19de5..36dd799b2 100644 --- a/packages/geolocation/package.json +++ b/packages/geolocation/package.json @@ -1,6 +1,6 @@ { "name": "@solid-primitives/geolocation", - "version": "1.5.4", + "version": "2.0.0", "description": "Primitives to query geolocation and observe changes.", "author": "David Di Biase ", "license": "MIT", @@ -13,6 +13,8 @@ "name": "geolocation", "stage": 3, "list": [ + "makeGeolocation", + "makeGeolocationWatcher", "createGeolocation", "createGeolocationWatcher" ], @@ -50,14 +52,14 @@ "devDependencies": { "@types/leaflet": "^1.9.8", "leaflet": "^1.9.4", - "solid-js": "^1.9.7" + "solid-js": "^2.0.0-beta.6" }, "dependencies": { "@solid-primitives/static-store": "workspace:^", "@solid-primitives/utils": "workspace:^" }, "peerDependencies": { - "solid-js": "^1.6.12" + "solid-js": "^2.0.0-beta.6" }, "typesVersions": {} } diff --git a/packages/geolocation/src/index.ts b/packages/geolocation/src/index.ts index 5d1b34c01..f885c05f1 100644 --- a/packages/geolocation/src/index.ts +++ b/packages/geolocation/src/index.ts @@ -1,8 +1,6 @@ -import { createStaticStore } from "@solid-primitives/static-store"; -import { access, type MaybeAccessor } from "@solid-primitives/utils"; -import type { Resource } from "solid-js"; -import { createComputed, createResource, onCleanup } from "solid-js"; import { isServer } from "solid-js/web"; +import { type Accessor, createEffect, createMemo, createSignal, onCleanup } from "solid-js"; +import { access, noop, type MaybeAccessor } from "@solid-primitives/utils"; const geolocationDefaults: PositionOptions = { enableHighAccuracy: false, @@ -10,94 +8,206 @@ const geolocationDefaults: PositionOptions = { timeout: Number.POSITIVE_INFINITY, }; +const mergeOptions = (options?: PositionOptions): PositionOptions => + Object.assign({}, geolocationDefaults, options); + +/** + * Performs a single geolocation query. Non-reactive — no Solid owner required. + * + * @param options - Position options + * @returns Tuple of `[query, cleanup]` + * + * @example + * ```ts + * const [query, cleanup] = makeGeolocation(); + * const coords = await query(); + * cleanup(); + * ``` + */ +export const makeGeolocation = ( + options?: PositionOptions, +): [query: () => Promise, cleanup: VoidFunction] => { + if (isServer) + return [() => Promise.reject(new Error("Geolocation is not available on the server.")), noop]; + + let active = true; + const query = () => + new Promise((resolve, reject) => { + if (!active) return; + if (!("geolocation" in navigator)) { + return reject(new Error("Geolocation is not supported.")); + } + navigator.geolocation.getCurrentPosition( + res => resolve(res.coords), + error => reject(Object.assign(new Error(error.message), error)), + mergeOptions(options), + ); + }); + + return [query, () => (active = false)]; +}; + +/** + * Starts a continuous geolocation watcher. Non-reactive — no Solid owner required. + * + * @param options - Position options + * @returns Tuple of `[{ location, error }, cleanup]` + * + * @example + * ```ts + * const [{ location, error }, cleanup] = makeGeolocationWatcher(); + * ``` + */ +export const makeGeolocationWatcher = ( + options?: PositionOptions, +): [ + store: { location: GeolocationCoordinates | null; error: GeolocationPositionError | null }, + cleanup: VoidFunction, +] => { + if (isServer) return [{ location: null, error: null }, noop]; + + const store = { + location: null as GeolocationCoordinates | null, + error: null as GeolocationPositionError | null, + }; + + const watchId = navigator.geolocation.watchPosition( + res => { + store.location = res.coords; + store.error = null; + }, + err => { + store.location = null; + store.error = err; + }, + mergeOptions(options), + ); + + return [store, () => navigator.geolocation.clearWatch(watchId)]; +}; + /** - * Generates a basic primitive to perform unary geolocation querying and updating. + * Reactive one-shot geolocation query. Returns an async accessor that suspends + * until the position resolves, integrating with `` / `` boundaries. + * Re-queries when `options` changes or when `refetch` is called. * - * @param options - @type PositionOptions - * @param options.enableHighAccuracy - Enable if the locator should be very accurate - * @param options.maximumAge - Maximum cached position age - * @param options.timeout - Amount of time before the error callback is evoked, if 0 then never - * @return Returns a `Resource` and refetch option resolving the location coordinates, refetch function and loading value. + * @param options - Reactive position options + * @returns Tuple of `[location, refetch]` * * @example * ```ts - * const [location, refetch, loading] = createGeolocation(); + * const [location, refetch] = createGeolocation(); + * // In JSX — suspends until first fix: + * // + * //
{location().latitude}, {location().longitude}
+ * //
+ * // Check if re-querying in the background: + * // location())}>Updating... * ``` */ export const createGeolocation = ( options?: MaybeAccessor, -): [location: Resource, refetch: VoidFunction] => { +): [location: Accessor, refetch: VoidFunction] => { if (isServer) { - return [ - Object.assign(() => {}, { error: undefined, loading: true }) as Resource, - () => { - /* noop */ - }, - ]; + const stub = () => { + throw new Error("Geolocation is not available on the server."); + }; + return [stub as Accessor, noop]; } - const [location, { refetch }] = createResource( - () => Object.assign(geolocationDefaults, access(options)), - options => - new Promise((resolve, reject) => { - if (!("geolocation" in navigator)) { - return reject("Geolocation is not supported."); - } - navigator.geolocation.getCurrentPosition( - res => resolve(res.coords), - error => reject(Object.assign(new Error(error.message), error)), - options, - ); - }), - ); - return [location, refetch]; + + const [version, bump] = createSignal(0); + + const location = createMemo(() => { + version(); // invalidated by refetch() + access(options); // invalidated when options change reactively + + return new Promise((resolve, reject) => { + if (!("geolocation" in navigator)) { + return reject(new Error("Geolocation is not supported.")); + } + navigator.geolocation.getCurrentPosition( + res => resolve(res.coords), + error => reject(Object.assign(new Error(error.message), error)), + mergeOptions(access(options)), + ); + }); + }) as unknown as Accessor; + + return [location, () => bump(v => v + 1)]; }; /** - * Creates a primitive that allows for real-time geolocation watching. + * Watches geolocation in real-time. Returns signal accessors for `location` and `error`. + * `location` suspends on the first fix — subsequent updates flow reactively without re-suspending. + * The watcher starts and stops reactively based on the `enabled` parameter. * - * @param enabled - Specify if the location should be updated periodically (used to temporarily disable location watching) - * @param options - @type PositionOptions - * @param options.enableHighAccuracy - Enable if the locator should be very accurate - * @param options.maximumAge - Maximum cached position age - * @param options.timeout - Amount of time before the error callback is evoked, if 0 then never - * @return Returns a location signal + * @param enabled - Whether the watcher should be active + * @param options - Reactive position options + * @returns `{ location, error }` — both are signal accessors * * @example * ```ts - * const [location, error] = createGeolocationWatcher(); + * const [enabled, setEnabled] = createSignal(true); + * const { location, error } = createGeolocationWatcher(enabled); + * // Suspends until first GPS fix, then updates reactively: + * // + * // + * // + * // Show recoverable errors without an error boundary: + * // Permission denied — * ``` */ export const createGeolocationWatcher = ( enabled: MaybeAccessor, options?: MaybeAccessor, ): { - location: GeolocationCoordinates | null; - error: GeolocationPositionError | null; + location: Accessor; + error: Accessor; } => { if (isServer) { - return { location: null, error: null }; + return { + location: () => { + throw new Error("Geolocation is not available on the server."); + }, + error: () => null, + }; } - const [store, setStore] = createStaticStore<{ - location: null | GeolocationCoordinates; - error: null | GeolocationPositionError; - }>({ - location: null, - error: null, - }); - let registeredHandlerID: number | null; - const clearGeolocator = () => - registeredHandlerID && navigator.geolocation.clearWatch(registeredHandlerID); - // Implement as an effect to allow switching locator on/off - createComputed(() => { + + // Undefined initial state causes to hold until the first fix arrives. + const [location, setLocation] = createSignal(undefined); + const [error, setError] = createSignal(null); + + let watchId: number | null = null; + + const clearWatch = () => { + if (watchId !== null) { + navigator.geolocation.clearWatch(watchId); + watchId = null; + } + }; + + createEffect(() => { if (access(enabled)) { - return (registeredHandlerID = navigator.geolocation.watchPosition( - res => setStore({ location: res.coords, error: null }), - error => setStore({ location: null, error }), - Object.assign(geolocationDefaults, access(options)), - )); + watchId = navigator.geolocation.watchPosition( + res => { + setLocation(() => res.coords); + setError(null); + }, + err => { + setError(err); + }, + mergeOptions(access(options)), + ); + } else { + clearWatch(); } - clearGeolocator(); }); - onCleanup(clearGeolocator); - return store; + + onCleanup(clearWatch); + + // Cast: undefined initial value causes suspension until first position update. + return { + location: location as Accessor, + error, + }; }; diff --git a/packages/geolocation/test/index.test.ts b/packages/geolocation/test/index.test.ts index bc83ad8d0..643c40f8d 100644 --- a/packages/geolocation/test/index.test.ts +++ b/packages/geolocation/test/index.test.ts @@ -1,45 +1,185 @@ import "./setup"; import { mockCoordinates } from "./setup.js"; import { createRoot, createSignal } from "solid-js"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; -import { createGeolocation, createGeolocationWatcher } from "../src/index.js"; +import { + makeGeolocation, + makeGeolocationWatcher, + createGeolocation, + createGeolocationWatcher, +} from "../src/index.js"; + +// ── makeGeolocation ─────────────────────────────────────────────────────────── + +describe("makeGeolocation", () => { + it("resolves coordinates without a Solid owner", async () => { + const [query, cleanup] = makeGeolocation(); + const coords = await query(); + expect(coords).toBe(mockCoordinates); + cleanup(); + }); + + it("cleanup prevents resolution of subsequent queries", async () => { + const [query, cleanup] = makeGeolocation(); + cleanup(); + // query after cleanup should not resolve (it returns without calling getCurrentPosition) + let resolved = false; + query().then(() => (resolved = true)); + await Promise.resolve(); + expect(resolved).toBe(false); + }); + + it("rejects when geolocation fails", async () => { + navigator.geolocation.getCurrentPosition = (_, reject: (error: any) => void) => { + reject({ code: 1, message: "Permission denied" }); + }; + const [query, cleanup] = makeGeolocation(); + await expect(query()).rejects.toThrow("Permission denied"); + cleanup(); + }); +}); + +// ── makeGeolocationWatcher ──────────────────────────────────────────────────── + +describe("makeGeolocationWatcher", () => { + it("starts watching and provides initial location without a Solid owner", () => { + const [store, cleanup] = makeGeolocationWatcher(); + expect(store.location).toBe(mockCoordinates); + expect(store.error).toBe(null); + cleanup(); + }); + + it("cleanup calls clearWatch", () => { + const clearWatch = vi.spyOn(navigator.geolocation, "clearWatch"); + const [, cleanup] = makeGeolocationWatcher(); + cleanup(); + expect(clearWatch).toHaveBeenCalled(); + clearWatch.mockRestore(); + }); +}); + +// ── createGeolocation ───────────────────────────────────────────────────────── describe("createGeolocation", () => { - it("test basic geolocation", () => + it("resolves coordinates via async accessor", () => createRoot(async dispose => { const [location] = createGeolocation(); - expect(location.loading).toBe(true); - await location.loading; - expect(location.loading).toBe(false); - expect(location()).toBe(mockCoordinates); + const coords = await location(); + expect(coords).toBe(mockCoordinates); dispose(); })); - it("test basic geolocation error", () => + it("rejects with an Error on failure", () => createRoot(async dispose => { navigator.geolocation.getCurrentPosition = (_, reject: (error: any) => void) => { reject({ code: 1, message: "GeoLocation error" }); }; const [location] = createGeolocation(); + await expect(location()).rejects.toThrow("GeoLocation error"); + dispose(); + })); + + it("refetch triggers a new position query", () => + createRoot(async dispose => { + let callCount = 0; + navigator.geolocation.getCurrentPosition = (resolve: PositionCallback) => { + callCount++; + resolve({ coords: mockCoordinates } as GeolocationPosition); + }; + const [location, refetch] = createGeolocation(); + await location(); + expect(callCount).toBe(1); + refetch(); + await location(); + expect(callCount).toBe(2); + dispose(); + })); + + it("re-queries when reactive options change", () => + createRoot(async dispose => { + let lastOptions: PositionOptions | undefined; + navigator.geolocation.getCurrentPosition = ( + resolve: PositionCallback, + _: any, + opts?: PositionOptions, + ) => { + lastOptions = opts; + resolve({ coords: mockCoordinates } as GeolocationPosition); + }; + const [opts, setOpts] = createSignal({ enableHighAccuracy: false }); + const [location] = createGeolocation(opts); + await location(); + expect(lastOptions?.enableHighAccuracy).toBe(false); + setOpts({ enableHighAccuracy: true }); await location(); - expect(location.loading).toBe(false); - expect(location.error).toBeInstanceOf(Error); - expect(location.error.code).toBe(1); - expect(location.error.message).toBe("GeoLocation error"); + expect(lastOptions?.enableHighAccuracy).toBe(true); dispose(); })); }); -describe("createGeolocation", () => { - it("test basic geolocation", () => - createRoot(async dispose => { - const [enabled, setEnabled] = createSignal(false); - const watcher = createGeolocationWatcher(enabled); - expect(watcher.location).toBe(null); - expect(watcher.error).toBe(null); - await setEnabled(true); - expect(watcher.location).toBe(mockCoordinates); +// ── createGeolocationWatcher ────────────────────────────────────────────────── + +describe("createGeolocationWatcher", () => { + it("location and error are signal accessors", () => + createRoot(dispose => { + const { location, error } = createGeolocationWatcher(true); + expect(typeof location).toBe("function"); + expect(typeof error).toBe("function"); + dispose(); + })); + + it("location updates after first watchPosition callback", () => + createRoot(async dispose => { + const { location } = createGeolocationWatcher(true); + // Allow effect + watchPosition callback to run + await Promise.resolve(); + await Promise.resolve(); + expect(location()).toBe(mockCoordinates); + dispose(); + })); + + it("location is undefined (suspending) before first fix when disabled", () => + createRoot(dispose => { + const { location } = createGeolocationWatcher(false); + expect(location()).toBeUndefined(); + dispose(); + })); + + it("error() is null on success", () => + createRoot(async dispose => { + const { error } = createGeolocationWatcher(true); + await Promise.resolve(); + expect(error()).toBe(null); + dispose(); + })); + + it("error() is set when watchPosition fails", () => + createRoot(async dispose => { + navigator.geolocation.watchPosition = ( + _: PositionCallback, + errorCallback: PositionErrorCallback, + ) => { + errorCallback({ code: 1, message: "Denied" } as GeolocationPositionError); + return 0; + }; + const { error } = createGeolocationWatcher(true); + await Promise.resolve(); + await Promise.resolve(); + expect(error()?.message).toBe("Denied"); + dispose(); + })); + + it("clears the watcher when disabled", () => + createRoot(async dispose => { + const clearWatch = vi.spyOn(navigator.geolocation, "clearWatch"); + const [enabled, setEnabled] = createSignal(true); + createGeolocationWatcher(enabled); + await Promise.resolve(); + setEnabled(false); + await Promise.resolve(); + expect(clearWatch).toHaveBeenCalled(); + clearWatch.mockRestore(); dispose(); })); }); diff --git a/packages/geolocation/test/server.test.ts b/packages/geolocation/test/server.test.ts index d84a1a907..47f3d517a 100644 --- a/packages/geolocation/test/server.test.ts +++ b/packages/geolocation/test/server.test.ts @@ -1,16 +1,34 @@ -import { createGeolocation, createGeolocationWatcher } from "../src/index.js"; +import { + makeGeolocation, + makeGeolocationWatcher, + createGeolocation, + createGeolocationWatcher, +} from "../src/index.js"; import { describe, expect, it } from "vitest"; describe("API doesn't break in SSR", () => { + it("makeGeolocation() - SSR", async () => { + const [query, cleanup] = makeGeolocation(); + expect(cleanup).toBeInstanceOf(Function); + await expect(query()).rejects.toThrow(); + }); + + it("makeGeolocationWatcher() - SSR", () => { + const [store, cleanup] = makeGeolocationWatcher(); + expect(store.location).toBe(null); + expect(store.error).toBe(null); + expect(cleanup).toBeInstanceOf(Function); + }); + it("createGeolocation() - SSR", () => { const [location, refetch] = createGeolocation(); - expect(location()).toBe(undefined); - expect(location.loading).toBe(true); - expect(location.error).toBe(undefined); + expect(() => location()).toThrow(); expect(refetch).toBeInstanceOf(Function); }); it("createGeolocationWatcher() - SSR", () => { - expect(createGeolocationWatcher(true)).toEqual({ location: null, error: null }); + const { location, error } = createGeolocationWatcher(true); + expect(() => location()).toThrow(); + expect(error()).toBe(null); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecadfdb95..505b2ba30 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -365,8 +365,8 @@ importers: specifier: ^1.9.4 version: 1.9.4 solid-js: - specifier: ^1.9.7 - version: 1.9.7 + specifier: ^2.0.0-beta.6 + version: 2.0.0-experimental.16 packages/gestures: devDependencies: @@ -1048,10 +1048,10 @@ importers: version: link:../packages/utils '@solidjs/meta': specifier: ^0.29.3 - version: 0.29.4(solid-js@1.9.7) + version: 0.29.4(solid-js@2.0.0-experimental.16) '@solidjs/router': specifier: ^0.13.1 - version: 0.13.6(solid-js@1.9.7) + version: 0.13.6(solid-js@2.0.0-experimental.16) clsx: specifier: ^2.0.0 version: 2.1.1 @@ -1078,13 +1078,13 @@ importers: version: 1.77.8 solid-dismiss: specifier: ^1.7.121 - version: 1.8.2(solid-js@1.9.7) + version: 1.8.2(solid-js@2.0.0-experimental.16) solid-icons: specifier: ^1.1.0 - version: 1.1.0(solid-js@1.9.7) + version: 1.1.0(solid-js@2.0.0-experimental.16) solid-tippy: specifier: ^0.2.1 - version: 0.2.1(solid-js@1.9.7)(tippy.js@6.3.7) + version: 0.2.1(solid-js@2.0.0-experimental.16)(tippy.js@6.3.7) tippy.js: specifier: ^6.3.7 version: 6.3.7 @@ -2587,6 +2587,9 @@ packages: peerDependencies: solid-js: ^1.5.3 + '@solidjs/signals@0.11.3': + resolution: {integrity: sha512-udMfutYPOlcxKUmc5+n1QtarsxOiAlC6LJY2TqFyaMwdXgo+reiYUcYGDlOiAPXfCLE0lavZHQ/6GT5pJbXKBA==} + '@solidjs/start@1.1.4': resolution: {integrity: sha512-ma1TBYqoTju87tkqrHExMReM5Z/+DTXSmi30CCTavtwuR73Bsn4rVGqm528p4sL2koRMfAuBMkrhuttjzhL68g==} peerDependencies: @@ -5892,10 +5895,20 @@ packages: peerDependencies: seroval: ^1.0 + seroval-plugins@1.5.2: + resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + seroval@1.3.2: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} + seroval@1.5.2: + resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==} + engines: {node: '>=10'} + serve-placeholder@2.0.2: resolution: {integrity: sha512-/TMG8SboeiQbZJWRlfTCqMs2DD3SZgWp0kDQePz9yUuCnDfDh/92gf7/PxGhzXTKBIPASIHxFcZndoNbp6QOLQ==} @@ -6001,6 +6014,9 @@ packages: solid-js@1.9.7: resolution: {integrity: sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==} + solid-js@2.0.0-experimental.16: + resolution: {integrity: sha512-zZ1dU7cR0EnvLnrYiRLQbCFiDw5blLdlqmofgLzKUYE1TCMWDcisBlSwz0Ez8l4yXB4adbdhtaYCuynH4xSq9A==} + solid-refresh@0.6.3: resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} peerDependencies: @@ -8576,18 +8592,20 @@ snapshots: dependencies: solid-js: 1.9.7 - '@solidjs/meta@0.29.4(solid-js@1.9.7)': + '@solidjs/meta@0.29.4(solid-js@2.0.0-experimental.16)': dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 - '@solidjs/router@0.13.6(solid-js@1.9.7)': + '@solidjs/router@0.13.6(solid-js@2.0.0-experimental.16)': dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 '@solidjs/router@0.8.4(solid-js@1.9.7)': dependencies: solid-js: 1.9.7 + '@solidjs/signals@0.11.3': {} + '@solidjs/start@1.1.4(solid-js@1.9.7)(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))': dependencies: '@tanstack/server-functions-plugin': 1.121.0(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) @@ -12441,8 +12459,14 @@ snapshots: dependencies: seroval: 1.3.2 + seroval-plugins@1.5.2(seroval@1.5.2): + dependencies: + seroval: 1.5.2 + seroval@1.3.2: {} + seroval@1.5.2: {} + serve-placeholder@2.0.2: dependencies: defu: 6.1.4 @@ -12557,13 +12581,13 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - solid-dismiss@1.8.2(solid-js@1.9.7): + solid-dismiss@1.8.2(solid-js@2.0.0-experimental.16): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 - solid-icons@1.1.0(solid-js@1.9.7): + solid-icons@1.1.0(solid-js@2.0.0-experimental.16): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 solid-js@1.9.7: dependencies: @@ -12571,6 +12595,13 @@ snapshots: seroval: 1.3.2 seroval-plugins: 1.3.2(seroval@1.3.2) + solid-js@2.0.0-experimental.16: + dependencies: + '@solidjs/signals': 0.11.3 + csstype: 3.1.3 + seroval: 1.5.2 + seroval-plugins: 1.5.2(seroval@1.5.2) + solid-refresh@0.6.3(solid-js@1.9.7): dependencies: '@babel/generator': 7.27.5 @@ -12580,9 +12611,9 @@ snapshots: transitivePeerDependencies: - supports-color - solid-tippy@0.2.1(solid-js@1.9.7)(tippy.js@6.3.7): + solid-tippy@0.2.1(solid-js@2.0.0-experimental.16)(tippy.js@6.3.7): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 tippy.js: 6.3.7 solid-transition-group@0.2.3(solid-js@1.9.7):