eddev 2.0.0-beta.122 → 2.0.0-beta.124

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.
@@ -1,10 +1,81 @@
1
+ /**
2
+ * Search param API object.
3
+ */
1
4
  export type SearchParamAPI<T> = {
5
+ /**
6
+ * Set an individual parameter value by key.
7
+ *
8
+ * If the value is an array, then one or more `key[]` parameters will be set. Otherwise, a single `key` parameter will be set.
9
+ *
10
+ * If the value is `null` or `undefined`, the parameter will be removed from the query string.
11
+ *
12
+ * @param key The search parameter name
13
+ * @param value The value to set
14
+ */
2
15
  set<K extends keyof T>(key: K, value: T[K]): void;
3
- setAll: (value: T) => void;
16
+ /**
17
+ * Set multiple parameters at once.
18
+ *
19
+ * @param value
20
+ * @returns
21
+ */
22
+ setAll: (value: Partial<T>) => void;
23
+ /**
24
+ * Returns a memoized setter function for a specific key.
25
+ *
26
+ * This is useful when you want to pass a setter function to a child component, without needing to pass the entire API object.
27
+ *
28
+ * For example:
29
+ * ```tsx
30
+ * <input value={params.mode} onChange={api.setter("mode")} />
31
+ * ```
32
+ *
33
+ * @param key The search parameter name
34
+ * @returns (value: T) => void
35
+ */
4
36
  setter<K extends keyof T>(key: K): (value: T[K]) => void;
37
+ /**
38
+ * Reset all parameters to their default values.
39
+ */
5
40
  reset(): void;
41
+ /**
42
+ * Gets the current value of a parameter. In most cases, you should use the `params` object returned from `useSearchParams` instead of this method.
43
+ */
6
44
  get<K extends keyof T>(key: K): T[K];
7
45
  };
8
- export declare function useSearchParams<T extends {
9
- [K: string]: any;
10
- }>(defaultValue: T): [T, SearchParamAPI<T>];
46
+ /**
47
+ * Provides type-safe read/write access to query string parameters, integrating with the routing system.
48
+ *
49
+ * - Call `useSearchParams` with a default value object, which defines the expected shape of the query string parameters.
50
+ * - Only keys that are present in the default value object will be handled, and all others will be ignored.
51
+ * - Arrays of values are supported, and you should use a default value of `[]` for that key. You may want to cast the default parameter as an array of the expected type (eg. `myValue: [] as string[]`) to ensure that the parameter type is correct.
52
+ * - This hook returns a tuple with the current query string parameters object, and an API object with methods to interact with the query string. See {@link SearchParamAPI} for more details.
53
+ *
54
+ * For example:
55
+ * ```tsx
56
+ * const [params, api] = useSearchParams({
57
+ * mode: "list" as "list" | "grid",
58
+ * page: 1,
59
+ * tags: [] as string[],
60
+ * })
61
+ *
62
+ * api.set("mode", "grid")
63
+ * api.set("tags", ["tag1", "tag2"])
64
+ * ```
65
+ *
66
+ * Note that if a parameter is set back to it's default value, it'll actually be _removed_ from the updated query string, keeping the URL clean when only the default values are set.
67
+ *
68
+ * ```tsx
69
+ * api.set("mode", "grid")
70
+ * // url becomes: "/?mode=grid"
71
+ * // params.mode === 'grid'
72
+ *
73
+ * api.set("mode", "list")
74
+ * // url becomes: "/"
75
+ * // params.mode === 'list'
76
+ * ```
77
+ *
78
+ * @param defaultValue - The default value object, defining the expected shape of the query string parameters.
79
+ * @returns A tuple of the resolve parameter object, and a {@link SearchParamAPI} object with methods to interact with the query string.
80
+ */
81
+ export declare function useSearchParams<T extends object>(defaultValue: T): [T, SearchParamAPI<T>];
@@ -1,30 +1,89 @@
1
- import { useMemo } from "react";
1
+ import { useMemo, useRef } from "react";
2
2
  import { useRoute } from "./useRoute.js";
3
3
  import { useRouter } from "./useRouter.js";
4
+ import { parseQuery } from "../utils.js";
5
+ import { hash } from "object-code";
6
+ /**
7
+ * Provides type-safe read/write access to query string parameters, integrating with the routing system.
8
+ *
9
+ * - Call `useSearchParams` with a default value object, which defines the expected shape of the query string parameters.
10
+ * - Only keys that are present in the default value object will be handled, and all others will be ignored.
11
+ * - Arrays of values are supported, and you should use a default value of `[]` for that key. You may want to cast the default parameter as an array of the expected type (eg. `myValue: [] as string[]`) to ensure that the parameter type is correct.
12
+ * - This hook returns a tuple with the current query string parameters object, and an API object with methods to interact with the query string. See {@link SearchParamAPI} for more details.
13
+ *
14
+ * For example:
15
+ * ```tsx
16
+ * const [params, api] = useSearchParams({
17
+ * mode: "list" as "list" | "grid",
18
+ * page: 1,
19
+ * tags: [] as string[],
20
+ * })
21
+ *
22
+ * api.set("mode", "grid")
23
+ * api.set("tags", ["tag1", "tag2"])
24
+ * ```
25
+ *
26
+ * Note that if a parameter is set back to it's default value, it'll actually be _removed_ from the updated query string, keeping the URL clean when only the default values are set.
27
+ *
28
+ * ```tsx
29
+ * api.set("mode", "grid")
30
+ * // url becomes: "/?mode=grid"
31
+ * // params.mode === 'grid'
32
+ *
33
+ * api.set("mode", "list")
34
+ * // url becomes: "/"
35
+ * // params.mode === 'list'
36
+ * ```
37
+ *
38
+ * @param defaultValue - The default value object, defining the expected shape of the query string parameters.
39
+ * @returns A tuple of the resolve parameter object, and a {@link SearchParamAPI} object with methods to interact with the query string.
40
+ */
4
41
  export function useSearchParams(defaultValue) {
5
42
  const route = useRoute();
6
43
  const replaceQuery = useRouter((r) => r.replaceQuery);
7
- const result = useMemo(() => ({
44
+ const merged = useMemo(() => ({
8
45
  ...defaultValue,
9
46
  ...route.query,
10
47
  }), [route.query]);
48
+ const values = useRef(merged);
49
+ values.current = merged;
50
+ // Memoized setters
51
+ const setters = useMemo(() => ({}), []);
52
+ // Gets the current value, directly from the source.
53
+ function get() {
54
+ if (env.client) {
55
+ return { ...defaultValue, ...parseQuery(document.location.search) };
56
+ }
57
+ else {
58
+ return merged;
59
+ }
60
+ }
61
+ // Main update function
11
62
  const update = (patch) => {
12
- const value = { ...result, ...patch };
63
+ const value = { ...get(), ...patch };
13
64
  for (let key in defaultValue) {
14
- if (defaultValue[key] === value[key] || [null, undefined].includes(value[key])) {
65
+ if (hash(defaultValue[key]) === hash(value[key]) || [null, undefined].includes(value[key])) {
15
66
  delete value[key];
16
67
  }
17
68
  }
69
+ values.current = value;
18
70
  replaceQuery(value);
19
71
  };
20
72
  return [
21
- result,
22
- {
23
- set: (key, value) => update({ ...result, [key]: value }),
24
- setAll: (value) => update(value),
25
- setter: (key) => (value) => update({ ...result, [key]: value }),
73
+ values.current,
74
+ useMemo(() => ({
75
+ set: (key, value) => update({ [key]: value }),
76
+ setAll: (value) => update({
77
+ ...defaultValue,
78
+ ...value,
79
+ }),
80
+ setter: (key) => {
81
+ if (!setters[key])
82
+ setters[key] = (value) => update({ [key]: value });
83
+ return setters[key];
84
+ },
26
85
  reset: () => update({}),
27
- get: (key) => result[key],
28
- },
86
+ get: (key) => values.current[key],
87
+ }), []),
29
88
  ];
30
89
  }
@@ -1 +1 @@
1
- export declare const VERSION = "2.0.0-beta.122";
1
+ export declare const VERSION = "2.0.0-beta.124";
@@ -1 +1 @@
1
- export const VERSION = "2.0.0-beta.122";
1
+ export const VERSION = "2.0.0-beta.124";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eddev",
3
- "version": "2.0.0-beta.122",
3
+ "version": "2.0.0-beta.124",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",