"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/core/src/index.ts var src_exports = {}; __export(src_exports, { useUrlState: () => useUrlState, useUrlStateWithRouter: () => useUrlStateWithRouter }); module.exports = __toCommonJS(src_exports); var import_react3 = require("react"); // packages/core/src/handlers.ts var import_react2 = require("react"); // packages/core/src/utils.ts var import_react = require("react"); function isNil(value) { return value === null || value === void 0; } function urlParamsToObject(params) { const object = {}; for (const [key, value] of params.entries()) { if (isNil(object[key])) { object[key] = value; continue; } const currentValue = object[key]; if (Array.isArray(currentValue)) { currentValue.push(value); } else { object[key] = [currentValue, value]; } } return object; } function searchIsEmpty(search) { return !search || search.indexOf("=") === -1; } function shallowEqual(a, b) { if (a === b) { return true; } if (typeof a !== "object" || typeof b !== "object") { return false; } if (a === null || b === null) { return false; } const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) { return false; } for (const key of aKeys) { if ("toString" in a && "toString" in b && typeof a.toString === "function" && typeof b.toString === "function") { if (a.toString() !== b.toString()) { return false; } } else if (a[key] !== b[key]) { return false; } } return true; } function useShallowEqualValue(value) { const ref = (0, import_react.useRef)(value); if (!shallowEqual(value, ref.current)) { console.log("not equal"); ref.current = value; } return ref.current; } function serializeValue(value) { if (isNil(value)) { return void 0; } if (typeof value === "object") { if (value instanceof Date) { return value.toISOString(); } else if (Array.isArray(value)) { return value.map((v) => { if (typeof v === "object") { return JSON.stringify(v); } return serializeValue(v); }); } else { return value?.toString?.(); } } return value?.toString(); } function serializeObjectToUrlParams(object) { const params = new URLSearchParams(); Object.keys(object).forEach((key) => { const value = serializeValue(object[key]); if (value === void 0 || value === null) { return; } if (Array.isArray(value)) { value.forEach((v) => { if (isNil(v)) { return; } params.append(key, v); }); return; } params.append(key, value); }); return `?${params.toString()}`; } // packages/core/src/handlers.ts function usePush(router) { return (0, import_react2.useCallback)( (href) => { router.push(href); }, [router] ); } function useHandlers(push, stateRef) { const setState = (0, import_react2.useCallback)( (state) => { if (typeof state === "function") { state = state(stateRef.current.data); } const href = serializeObjectToUrlParams(state); push(href); }, [push, stateRef] ); const setValues = (0, import_react2.useCallback)( (state) => { if (typeof state === "function") { state = state(stateRef.current.data); } const href = serializeObjectToUrlParams({ ...stateRef.current.data, ...state }); push(href); }, [push, stateRef] ); const setValue = (0, import_react2.useCallback)( (key, value) => { const href = serializeObjectToUrlParams({ ...stateRef.current.data, [key]: value }); push(href); }, [push, stateRef] ); return (0, import_react2.useMemo)( () => ({ setState, setValue, setValues }), [setState, setValue, setValues] ); } // packages/core/src/router.ts var genericRouterCurrentStateString = ""; var GenericRouter = class { constructor(options) { this.options = options; this.interval = 0; this.subscribers = /* @__PURE__ */ new Map(); this.options = { poolingIntervalMs: 100, ...options }; } push(href) { window.history.pushState({}, "", href); this.onSearchParamsChange(); } subscribe(fn) { this.subscribers.set(fn, fn); if (!this.interval) { this.startPolling(); } } unsubscribe(fn) { this.subscribers.delete(fn); if (this.subscribers.size === 0) { this.stopPolling(); } } onSearchParamsChange() { if (window.location.search !== genericRouterCurrentStateString) { genericRouterCurrentStateString = window.location.search; this.subscribers.forEach( (subscriber) => subscriber(genericRouterCurrentStateString) ); } } startPolling() { if (typeof window !== "undefined") { this.interval = setInterval(() => { this.onSearchParamsChange(); }, this.options.poolingIntervalMs); } } stopPolling() { if (this.interval) { clearInterval(this.interval); } } }; var genericRouterInstance = null; function getGenericRouter() { if (!genericRouterInstance) { genericRouterInstance = new GenericRouter({}); } return genericRouterInstance; } // packages/core/src/index.ts function useUrlState(schema, initialValue, options) { const [router] = (0, import_react3.useState)(() => getGenericRouter()); return useUrlStateWithRouter(schema, initialValue || null, { applyInitialValue: false, ...options, router }); } function useUrlStateWithRouter(schema, initialValue, options) { const schemaRef = (0, import_react3.useRef)(schema); const cachedInitialValue = useShallowEqualValue(initialValue); const [state, setState] = (0, import_react3.useState)({ data: cachedInitialValue, error: null, isError: false, isReady: false }); const stateRef = (0, import_react3.useRef)(state); stateRef.current = state; const recalculateState = (0, import_react3.useCallback)((searchString) => { const params = new URLSearchParams(searchString); const object = urlParamsToObject(params); const validationResult = schemaRef.current.safeParse(object); const result = validationResult.success ? { success: true, data: validationResult.data ?? null, error: null } : { success: false, data: object, error: validationResult.error }; setState({ data: result.data, isError: !result.success, error: result.error, isReady: true }); }, []); (0, import_react3.useEffect)(() => { options.router.subscribe(recalculateState); return () => { options.router.unsubscribe(recalculateState); }; }, [options.router, recalculateState]); const push = usePush(options.router); const handlers = useHandlers(push, stateRef); (0, import_react3.useEffect)(() => { const searchString = window.location.search; if (!searchIsEmpty(searchString)) { recalculateState(searchString); } else if (cachedInitialValue && options.applyInitialValue) { handlers.setState(cachedInitialValue); } else { setState((st) => ({ ...st, isReady: true })); } }, [ cachedInitialValue, handlers, options.applyInitialValue, recalculateState ]); return { ...state, ...handlers }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { useUrlState, useUrlStateWithRouter });