@1money/hooks 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/es/index.d.ts CHANGED
@@ -9,3 +9,5 @@ export { default as useSyncState } from './useSyncState';
9
9
  export { default as useUpdateEffect } from './useUpdateEffect';
10
10
  export { default as useLayoutState, useTimeoutLock } from './useLayoutState';
11
11
  export type { Updater } from './useLayoutState';
12
+ export { default as useQueryState, queryString, queryNumber, queryBoolean, queryJson, } from './useQueryState';
13
+ export type { Parser, Serializer, QueryStateOptions, } from './useQueryState';
package/es/index.js CHANGED
@@ -8,4 +8,5 @@ export { default as usePrevious } from "./usePrevious";
8
8
  export { default as useSafeState } from "./useSafeState";
9
9
  export { default as useSyncState } from "./useSyncState";
10
10
  export { default as useUpdateEffect } from "./useUpdateEffect";
11
- export { default as useLayoutState, useTimeoutLock } from "./useLayoutState";
11
+ export { default as useLayoutState, useTimeoutLock } from "./useLayoutState";
12
+ export { default as useQueryState, queryString, queryNumber, queryBoolean, queryJson } from "./useQueryState";
@@ -0,0 +1,64 @@
1
+ /** Turn a raw query string into a typed value. */
2
+ export type Parser<T> = (value: string) => T;
3
+ /** Turn a typed value back into a query string. */
4
+ export type Serializer<T> = (value: T) => string;
5
+ export interface QueryStateOptions<T> {
6
+ /**
7
+ * Parse the raw `string` read from the URL into `T`.
8
+ * Defaults to identity (the raw string).
9
+ */
10
+ parser?: Parser<T>;
11
+ /**
12
+ * Serialize `T` back into a `string` for the URL.
13
+ * Defaults to `String(value)`.
14
+ */
15
+ serializer?: Serializer<T>;
16
+ /**
17
+ * Value returned when the param is absent from
18
+ * the URL. When set, the hook never returns
19
+ * `null`.
20
+ */
21
+ defaultValue?: T;
22
+ /**
23
+ * How the URL is mutated:
24
+ * - `'replace'` (default) — `history.replaceState`,
25
+ * does not add a history entry.
26
+ * - `'push'` — `history.pushState`, back/forward
27
+ * navigates between values.
28
+ */
29
+ history?: 'push' | 'replace';
30
+ }
31
+ type SetQueryState<T> = (value: T | null | ((prev: T | null) => T | null)) => void;
32
+ /** Identity parser used when none is supplied. */
33
+ export declare const queryString: Parser<string>;
34
+ /** Parse a numeric query param. `NaN` for non-numbers. */
35
+ export declare const queryNumber: Parser<number>;
36
+ /** Parse a boolean query param. Only `'true'` is true. */
37
+ export declare const queryBoolean: Parser<boolean>;
38
+ /** Parse a JSON-encoded query param. */
39
+ export declare const queryJson: Parser<unknown>;
40
+ /**
41
+ * Sync a piece of React state with a URL query
42
+ * parameter, so it survives refreshes and is
43
+ * shareable via the link.
44
+ *
45
+ * Reads/writes go through native
46
+ * `history.pushState/replaceState`, which keeps it
47
+ * compatible with the Next.js App Router (it does
48
+ * not trigger a route re-mount). Because the value
49
+ * is reactive, using it as a SWR/React Query key
50
+ * makes dependent requests refetch automatically.
51
+ *
52
+ * @param key The query parameter name
53
+ * @param options Parsing, serialization and history
54
+ * behaviour
55
+ * @returns A `[value, setValue]` tuple. `setValue`
56
+ * accepts a value, an updater function, or `null`
57
+ * to remove the param.
58
+ */
59
+ declare function useQueryState(key: string): [string | null, SetQueryState<string>];
60
+ declare function useQueryState<T>(key: string, options: QueryStateOptions<T> & {
61
+ defaultValue: T;
62
+ }): [T, SetQueryState<T>];
63
+ declare function useQueryState<T>(key: string, options: QueryStateOptions<T>): [T | null, SetQueryState<T>];
64
+ export default useQueryState;
@@ -0,0 +1,133 @@
1
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
6
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
+ import { useState, useEffect } from 'react';
8
+ import useMemoizedFn from "../useMemoizedFn";
9
+
10
+ /** Turn a raw query string into a typed value. */
11
+
12
+ /** Turn a typed value back into a query string. */
13
+
14
+ /** Identity parser used when none is supplied. */
15
+ export var queryString = function queryString(value) {
16
+ return value;
17
+ };
18
+
19
+ /** Parse a numeric query param. `NaN` for non-numbers. */
20
+ export var queryNumber = function queryNumber(value) {
21
+ return Number(value);
22
+ };
23
+
24
+ /** Parse a boolean query param. Only `'true'` is true. */
25
+ export var queryBoolean = function queryBoolean(value) {
26
+ return value === 'true';
27
+ };
28
+
29
+ /** Parse a JSON-encoded query param. */
30
+ export var queryJson = function queryJson(value) {
31
+ return JSON.parse(value);
32
+ };
33
+ var isBrowser = typeof window !== 'undefined';
34
+
35
+ /**
36
+ * Subscribers re-read the URL when any instance
37
+ * mutates it. `history.pushState/replaceState` do
38
+ * not emit `popstate`, so we notify manually.
39
+ */
40
+ var listeners = new Set();
41
+ var emit = function emit() {
42
+ listeners.forEach(function (fn) {
43
+ return fn();
44
+ });
45
+ };
46
+
47
+ /**
48
+ * Sync a piece of React state with a URL query
49
+ * parameter, so it survives refreshes and is
50
+ * shareable via the link.
51
+ *
52
+ * Reads/writes go through native
53
+ * `history.pushState/replaceState`, which keeps it
54
+ * compatible with the Next.js App Router (it does
55
+ * not trigger a route re-mount). Because the value
56
+ * is reactive, using it as a SWR/React Query key
57
+ * makes dependent requests refetch automatically.
58
+ *
59
+ * @param key The query parameter name
60
+ * @param options Parsing, serialization and history
61
+ * behaviour
62
+ * @returns A `[value, setValue]` tuple. `setValue`
63
+ * accepts a value, an updater function, or `null`
64
+ * to remove the param.
65
+ */
66
+
67
+ // eslint-disable-next-line no-redeclare
68
+
69
+ // eslint-disable-next-line no-redeclare
70
+
71
+ // eslint-disable-next-line no-redeclare
72
+ function useQueryState(key) {
73
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
74
+ var parser = options.parser,
75
+ _options$serializer = options.serializer,
76
+ serializer = _options$serializer === void 0 ? String : _options$serializer,
77
+ defaultValue = options.defaultValue,
78
+ _options$history = options.history,
79
+ history = _options$history === void 0 ? 'replace' : _options$history;
80
+ var read = useMemoizedFn(function () {
81
+ if (!isBrowser) {
82
+ return defaultValue !== null && defaultValue !== void 0 ? defaultValue : null;
83
+ }
84
+ var params = new URLSearchParams(window.location.search);
85
+ var raw = params.get(key);
86
+ if (raw === null) {
87
+ return defaultValue !== null && defaultValue !== void 0 ? defaultValue : null;
88
+ }
89
+ return parser ? parser(raw) : raw;
90
+ });
91
+ var _useState = useState(read),
92
+ _useState2 = _slicedToArray(_useState, 2),
93
+ value = _useState2[0],
94
+ setValue = _useState2[1];
95
+ useEffect(function () {
96
+ var handler = function handler() {
97
+ return setValue(read());
98
+ };
99
+ listeners.add(handler);
100
+ window.addEventListener('popstate', handler);
101
+ // Resync in case the URL changed between the
102
+ // initial render and this effect running.
103
+ handler();
104
+ return function () {
105
+ listeners.delete(handler);
106
+ window.removeEventListener('popstate', handler);
107
+ };
108
+ // `read` is stable via useMemoizedFn.
109
+ }, [key, read]);
110
+ var set = useMemoizedFn(function (next) {
111
+ if (!isBrowser) {
112
+ return;
113
+ }
114
+ var prev = read();
115
+ var resolved = typeof next === 'function' ? next(prev) : next;
116
+ var params = new URLSearchParams(window.location.search);
117
+ if (resolved === null || resolved === undefined) {
118
+ params.delete(key);
119
+ } else {
120
+ params.set(key, serializer(resolved));
121
+ }
122
+ var search = params.toString();
123
+ var url = window.location.pathname + (search ? "?".concat(search) : '') + window.location.hash;
124
+ if (history === 'push') {
125
+ window.history.pushState(null, '', url);
126
+ } else {
127
+ window.history.replaceState(null, '', url);
128
+ }
129
+ emit();
130
+ });
131
+ return [value, set];
132
+ }
133
+ export default useQueryState;
package/lib/index.d.ts CHANGED
@@ -9,3 +9,5 @@ export { default as useSyncState } from './useSyncState';
9
9
  export { default as useUpdateEffect } from './useUpdateEffect';
10
10
  export { default as useLayoutState, useTimeoutLock } from './useLayoutState';
11
11
  export type { Updater } from './useLayoutState';
12
+ export { default as useQueryState, queryString, queryNumber, queryBoolean, queryJson, } from './useQueryState';
13
+ export type { Parser, Serializer, QueryStateOptions, } from './useQueryState';
package/lib/index.js CHANGED
@@ -27,8 +27,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/index.ts
30
- var src_exports = {};
31
- __export(src_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ queryBoolean: () => import_useQueryState.queryBoolean,
33
+ queryJson: () => import_useQueryState.queryJson,
34
+ queryNumber: () => import_useQueryState.queryNumber,
35
+ queryString: () => import_useQueryState.queryString,
32
36
  useControlledState: () => import_useControlledState.default,
33
37
  useEventCallback: () => import_useEventCallback.default,
34
38
  useLatest: () => import_useLatest.default,
@@ -36,12 +40,13 @@ __export(src_exports, {
36
40
  useLayoutState: () => import_useLayoutState.default,
37
41
  useMemoizedFn: () => import_useMemoizedFn.default,
38
42
  usePrevious: () => import_usePrevious.default,
43
+ useQueryState: () => import_useQueryState.default,
39
44
  useSafeState: () => import_useSafeState.default,
40
45
  useSyncState: () => import_useSyncState.default,
41
46
  useTimeoutLock: () => import_useLayoutState.useTimeoutLock,
42
47
  useUpdateEffect: () => import_useUpdateEffect.default
43
48
  });
44
- module.exports = __toCommonJS(src_exports);
49
+ module.exports = __toCommonJS(index_exports);
45
50
  var import_useControlledState = __toESM(require("./useControlledState"));
46
51
  var import_useEventCallback = __toESM(require("./useEventCallback"));
47
52
  var import_useLatest = __toESM(require("./useLatest"));
@@ -52,8 +57,13 @@ var import_useSafeState = __toESM(require("./useSafeState"));
52
57
  var import_useSyncState = __toESM(require("./useSyncState"));
53
58
  var import_useUpdateEffect = __toESM(require("./useUpdateEffect"));
54
59
  var import_useLayoutState = __toESM(require("./useLayoutState"));
60
+ var import_useQueryState = __toESM(require("./useQueryState"));
55
61
  // Annotate the CommonJS export names for ESM import in node:
56
62
  0 && (module.exports = {
63
+ queryBoolean,
64
+ queryJson,
65
+ queryNumber,
66
+ queryString,
57
67
  useControlledState,
58
68
  useEventCallback,
59
69
  useLatest,
@@ -61,6 +71,7 @@ var import_useLayoutState = __toESM(require("./useLayoutState"));
61
71
  useLayoutState,
62
72
  useMemoizedFn,
63
73
  usePrevious,
74
+ useQueryState,
64
75
  useSafeState,
65
76
  useSyncState,
66
77
  useTimeoutLock,
@@ -27,11 +27,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/useControlledState/index.ts
30
- var useControlledState_exports = {};
31
- __export(useControlledState_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  default: () => useControlledState
33
33
  });
34
- module.exports = __toCommonJS(useControlledState_exports);
34
+ module.exports = __toCommonJS(index_exports);
35
35
  var import_react = require("react");
36
36
  var import_useLayoutEffect = __toESM(require("../useLayoutEffect"));
37
37
  function useControlledState(defaultStateValue, value) {
@@ -27,11 +27,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/useEventCallback/index.ts
30
- var useEventCallback_exports = {};
31
- __export(useEventCallback_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  default: () => useEventCallback
33
33
  });
34
- module.exports = __toCommonJS(useEventCallback_exports);
34
+ module.exports = __toCommonJS(index_exports);
35
35
  var import_react = require("react");
36
36
  var import_useLatest = __toESM(require("../useLatest"));
37
37
  function useEventCallback(fn) {
@@ -17,11 +17,11 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/useLatest/index.ts
20
- var useLatest_exports = {};
21
- __export(useLatest_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  default: () => useLatest
23
23
  });
24
- module.exports = __toCommonJS(useLatest_exports);
24
+ module.exports = __toCommonJS(index_exports);
25
25
  var import_react = require("react");
26
26
  function useLatest(value) {
27
27
  const ref = (0, import_react.useRef)(value);
@@ -17,11 +17,11 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/useLayoutEffect/index.ts
20
- var useLayoutEffect_exports = {};
21
- __export(useLayoutEffect_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  default: () => useLayoutEffect
23
23
  });
24
- module.exports = __toCommonJS(useLayoutEffect_exports);
24
+ module.exports = __toCommonJS(index_exports);
25
25
  var import_react = require("react");
26
26
  function useLayoutEffect(effect, deps) {
27
27
  const isMounted = (0, import_react.useRef)(false);
@@ -17,12 +17,12 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/useLayoutState/index.ts
20
- var useLayoutState_exports = {};
21
- __export(useLayoutState_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  default: () => useLayoutState,
23
23
  useTimeoutLock: () => useTimeoutLock
24
24
  });
25
- module.exports = __toCommonJS(useLayoutState_exports);
25
+ module.exports = __toCommonJS(index_exports);
26
26
  var import_react = require("react");
27
27
  function useLayoutState(defaultState) {
28
28
  const stateRef = (0, import_react.useRef)(defaultState);
@@ -17,11 +17,11 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/useMemoizedFn/index.ts
20
- var useMemoizedFn_exports = {};
21
- __export(useMemoizedFn_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  default: () => useMemoizedFn
23
23
  });
24
- module.exports = __toCommonJS(useMemoizedFn_exports);
24
+ module.exports = __toCommonJS(index_exports);
25
25
  var import_react = require("react");
26
26
  function useMemoizedFn(fn) {
27
27
  const fnRef = (0, import_react.useRef)(fn);
@@ -17,11 +17,11 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/usePrevious/index.ts
20
- var usePrevious_exports = {};
21
- __export(usePrevious_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  default: () => usePrevious
23
23
  });
24
- module.exports = __toCommonJS(usePrevious_exports);
24
+ module.exports = __toCommonJS(index_exports);
25
25
  var import_react = require("react");
26
26
  function usePrevious(value) {
27
27
  const ref = (0, import_react.useRef)(void 0);
@@ -0,0 +1,64 @@
1
+ /** Turn a raw query string into a typed value. */
2
+ export type Parser<T> = (value: string) => T;
3
+ /** Turn a typed value back into a query string. */
4
+ export type Serializer<T> = (value: T) => string;
5
+ export interface QueryStateOptions<T> {
6
+ /**
7
+ * Parse the raw `string` read from the URL into `T`.
8
+ * Defaults to identity (the raw string).
9
+ */
10
+ parser?: Parser<T>;
11
+ /**
12
+ * Serialize `T` back into a `string` for the URL.
13
+ * Defaults to `String(value)`.
14
+ */
15
+ serializer?: Serializer<T>;
16
+ /**
17
+ * Value returned when the param is absent from
18
+ * the URL. When set, the hook never returns
19
+ * `null`.
20
+ */
21
+ defaultValue?: T;
22
+ /**
23
+ * How the URL is mutated:
24
+ * - `'replace'` (default) — `history.replaceState`,
25
+ * does not add a history entry.
26
+ * - `'push'` — `history.pushState`, back/forward
27
+ * navigates between values.
28
+ */
29
+ history?: 'push' | 'replace';
30
+ }
31
+ type SetQueryState<T> = (value: T | null | ((prev: T | null) => T | null)) => void;
32
+ /** Identity parser used when none is supplied. */
33
+ export declare const queryString: Parser<string>;
34
+ /** Parse a numeric query param. `NaN` for non-numbers. */
35
+ export declare const queryNumber: Parser<number>;
36
+ /** Parse a boolean query param. Only `'true'` is true. */
37
+ export declare const queryBoolean: Parser<boolean>;
38
+ /** Parse a JSON-encoded query param. */
39
+ export declare const queryJson: Parser<unknown>;
40
+ /**
41
+ * Sync a piece of React state with a URL query
42
+ * parameter, so it survives refreshes and is
43
+ * shareable via the link.
44
+ *
45
+ * Reads/writes go through native
46
+ * `history.pushState/replaceState`, which keeps it
47
+ * compatible with the Next.js App Router (it does
48
+ * not trigger a route re-mount). Because the value
49
+ * is reactive, using it as a SWR/React Query key
50
+ * makes dependent requests refetch automatically.
51
+ *
52
+ * @param key The query parameter name
53
+ * @param options Parsing, serialization and history
54
+ * behaviour
55
+ * @returns A `[value, setValue]` tuple. `setValue`
56
+ * accepts a value, an updater function, or `null`
57
+ * to remove the param.
58
+ */
59
+ declare function useQueryState(key: string): [string | null, SetQueryState<string>];
60
+ declare function useQueryState<T>(key: string, options: QueryStateOptions<T> & {
61
+ defaultValue: T;
62
+ }): [T, SetQueryState<T>];
63
+ declare function useQueryState<T>(key: string, options: QueryStateOptions<T>): [T | null, SetQueryState<T>];
64
+ export default useQueryState;
@@ -0,0 +1,116 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/useQueryState/index.ts
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ default: () => index_default,
33
+ queryBoolean: () => queryBoolean,
34
+ queryJson: () => queryJson,
35
+ queryNumber: () => queryNumber,
36
+ queryString: () => queryString
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+ var import_react = require("react");
40
+ var import_useMemoizedFn = __toESM(require("../useMemoizedFn"));
41
+ var queryString = (value) => value;
42
+ var queryNumber = (value) => Number(value);
43
+ var queryBoolean = (value) => value === "true";
44
+ var queryJson = (value) => JSON.parse(value);
45
+ var isBrowser = typeof window !== "undefined";
46
+ var listeners = /* @__PURE__ */ new Set();
47
+ var emit = () => {
48
+ listeners.forEach((fn) => fn());
49
+ };
50
+ function useQueryState(key, options = {}) {
51
+ const {
52
+ parser,
53
+ serializer = String,
54
+ defaultValue,
55
+ history = "replace"
56
+ } = options;
57
+ const read = (0, import_useMemoizedFn.default)(() => {
58
+ if (!isBrowser) {
59
+ return defaultValue ?? null;
60
+ }
61
+ const params = new URLSearchParams(
62
+ window.location.search
63
+ );
64
+ const raw = params.get(key);
65
+ if (raw === null) {
66
+ return defaultValue ?? null;
67
+ }
68
+ return parser ? parser(raw) : raw;
69
+ });
70
+ const [value, setValue] = (0, import_react.useState)(read);
71
+ (0, import_react.useEffect)(() => {
72
+ const handler = () => setValue(read());
73
+ listeners.add(handler);
74
+ window.addEventListener("popstate", handler);
75
+ handler();
76
+ return () => {
77
+ listeners.delete(handler);
78
+ window.removeEventListener(
79
+ "popstate",
80
+ handler
81
+ );
82
+ };
83
+ }, [key, read]);
84
+ const set = (0, import_useMemoizedFn.default)((next) => {
85
+ if (!isBrowser) {
86
+ return;
87
+ }
88
+ const prev = read();
89
+ const resolved = typeof next === "function" ? next(prev) : next;
90
+ const params = new URLSearchParams(
91
+ window.location.search
92
+ );
93
+ if (resolved === null || resolved === void 0) {
94
+ params.delete(key);
95
+ } else {
96
+ params.set(key, serializer(resolved));
97
+ }
98
+ const search = params.toString();
99
+ const url = window.location.pathname + (search ? `?${search}` : "") + window.location.hash;
100
+ if (history === "push") {
101
+ window.history.pushState(null, "", url);
102
+ } else {
103
+ window.history.replaceState(null, "", url);
104
+ }
105
+ emit();
106
+ });
107
+ return [value, set];
108
+ }
109
+ var index_default = useQueryState;
110
+ // Annotate the CommonJS export names for ESM import in node:
111
+ 0 && (module.exports = {
112
+ queryBoolean,
113
+ queryJson,
114
+ queryNumber,
115
+ queryString
116
+ });
@@ -17,11 +17,11 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/useSafeState/index.ts
20
- var useSafeState_exports = {};
21
- __export(useSafeState_exports, {
22
- default: () => useSafeState_default
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
+ default: () => index_default
23
23
  });
24
- module.exports = __toCommonJS(useSafeState_exports);
24
+ module.exports = __toCommonJS(index_exports);
25
25
  var import_react = require("react");
26
26
  function useSafeState(initialState) {
27
27
  const isMountedRef = (0, import_react.useRef)(true);
@@ -39,4 +39,4 @@ function useSafeState(initialState) {
39
39
  }, []);
40
40
  return [state, setSafeState];
41
41
  }
42
- var useSafeState_default = useSafeState;
42
+ var index_default = useSafeState;
@@ -27,11 +27,11 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
 
29
29
  // src/useSyncState/index.ts
30
- var useSyncState_exports = {};
31
- __export(useSyncState_exports, {
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
32
  default: () => useSyncState
33
33
  });
34
- module.exports = __toCommonJS(useSyncState_exports);
34
+ module.exports = __toCommonJS(index_exports);
35
35
  var import_react = require("react");
36
36
  var import_useEventCallback = __toESM(require("../useEventCallback"));
37
37
  var UNINITIALIZED = Symbol("useSyncState.uninitialized");
@@ -17,11 +17,11 @@ var __copyProps = (to, from, except, desc) => {
17
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
18
 
19
19
  // src/useUpdateEffect/index.ts
20
- var useUpdateEffect_exports = {};
21
- __export(useUpdateEffect_exports, {
20
+ var index_exports = {};
21
+ __export(index_exports, {
22
22
  default: () => useUpdateEffect
23
23
  });
24
- module.exports = __toCommonJS(useUpdateEffect_exports);
24
+ module.exports = __toCommonJS(index_exports);
25
25
  var import_react = require("react");
26
26
  function useUpdateEffect(effect, deps) {
27
27
  const isMounted = (0, import_react.useRef)(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1money/hooks",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "React hooks for 1money front-end projects",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -41,6 +41,11 @@
41
41
  "import": "./es/useLayoutState/index.js",
42
42
  "require": "./lib/useLayoutState/index.js"
43
43
  },
44
+ "./useQueryState": {
45
+ "types": "./es/useQueryState/index.d.ts",
46
+ "import": "./es/useQueryState/index.js",
47
+ "require": "./lib/useQueryState/index.js"
48
+ },
44
49
  "./useMemoizedFn": {
45
50
  "types": "./es/useMemoizedFn/index.d.ts",
46
51
  "import": "./es/useMemoizedFn/index.js",
@@ -89,29 +94,43 @@
89
94
  },
90
95
  "license": "MIT",
91
96
  "devDependencies": {
92
- "@eslint/js": "^9.24.0",
97
+ "@eslint/js": "^9.39.4",
93
98
  "@testing-library/react": "^16.3.2",
94
- "@testing-library/react-hooks": "^8.0.1",
95
- "@types/jest": "29.5.12",
96
- "@types/node": "~18.19.86",
97
- "@types/react": "~19.1.2",
99
+ "@types/node": "^20.19.0",
100
+ "@types/react": "^19.2.14",
98
101
  "@types/react-dom": "^19.2.3",
99
- "@typescript-eslint/eslint-plugin": "~8.23.0",
100
- "@typescript-eslint/parser": "~8.23.0",
101
- "eslint": "~9.20.1",
102
- "eslint-config-prettier": "~10.0.3",
103
- "eslint-plugin-prettier": "~5.2.6",
102
+ "@typescript-eslint/eslint-plugin": "^8.58.1",
103
+ "@typescript-eslint/parser": "^8.58.1",
104
+ "eslint": "^9.39.4",
105
+ "eslint-config-prettier": "^10.1.8",
106
+ "eslint-plugin-prettier": "^5.5.5",
104
107
  "eslint-plugin-react": "~7.37.5",
105
- "father": "^4.5.1",
108
+ "father": "^4.6.17",
106
109
  "globals": "^15.15.0",
107
- "jest": "~29.7.0",
108
- "jest-environment-jsdom": "^29.7.0",
109
- "jsdom": "^29.0.0",
110
+ "jsdom": "^29.0.2",
110
111
  "prettier": "~3.5.3",
111
112
  "react": "^19.1.0",
112
113
  "react-dom": "^19.2.4",
113
- "ts-jest": "~29.2.6",
114
114
  "typescript": "~5.5.4",
115
- "vitest": "^4.1.0"
115
+ "vite": "^8.0.5",
116
+ "vitest": "^4.1.4"
117
+ },
118
+ "pnpm": {
119
+ "overrides": {
120
+ "@babel/runtime": "7.26.10",
121
+ "@eslint/plugin-kit": "0.3.4",
122
+ "@tootallnate/once": "3.0.1",
123
+ "ajv@6.12.6": "6.14.0",
124
+ "brace-expansion@2.0.2": "2.0.3",
125
+ "esbuild": "0.25.0",
126
+ "flatted": "3.4.2",
127
+ "lodash": "4.18.0",
128
+ "minimatch@3.0.8": "3.1.5",
129
+ "minimatch@3.1.2": "3.1.5",
130
+ "picomatch@2.3.1": "2.3.2",
131
+ "picomatch@4.0.3": "4.0.4",
132
+ "send": "0.19.0",
133
+ "yaml": "1.10.3"
134
+ }
116
135
  }
117
136
  }