@coveord/plasma-mantine 55.5.1 → 55.6.0
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/.turbo/turbo-build.log +3 -3
- package/.turbo/turbo-test.log +49 -49
- package/dist/.tsbuildinfo +1 -1
- package/dist/cjs/components/table/index.d.ts +1 -1
- package/dist/cjs/components/table/index.d.ts.map +1 -1
- package/dist/cjs/components/table/index.js.map +1 -1
- package/dist/cjs/components/table/use-table.d.ts.map +1 -1
- package/dist/cjs/components/table/use-table.js +177 -162
- package/dist/cjs/components/table/use-table.js.map +1 -1
- package/dist/cjs/components/table/use-url-synced-state.d.ts +8 -4
- package/dist/cjs/components/table/use-url-synced-state.d.ts.map +1 -1
- package/dist/cjs/components/table/use-url-synced-state.js +94 -67
- package/dist/cjs/components/table/use-url-synced-state.js.map +1 -1
- package/dist/esm/components/table/index.d.ts +1 -1
- package/dist/esm/components/table/index.d.ts.map +1 -1
- package/dist/esm/components/table/index.js.map +1 -1
- package/dist/esm/components/table/use-table.d.ts.map +1 -1
- package/dist/esm/components/table/use-table.js +116 -95
- package/dist/esm/components/table/use-table.js.map +1 -1
- package/dist/esm/components/table/use-url-synced-state.d.ts +8 -4
- package/dist/esm/components/table/use-url-synced-state.d.ts.map +1 -1
- package/dist/esm/components/table/use-url-synced-state.js +59 -44
- package/dist/esm/components/table/use-url-synced-state.js.map +1 -1
- package/package.json +1 -1
- package/src/components/table/__tests__/use-url-synced-state.unit.spec.ts +2 -1
- package/src/components/table/index.ts +1 -1
- package/src/components/table/use-table.ts +109 -79
- package/src/components/table/use-url-synced-state.ts +79 -64
|
@@ -1,30 +1,21 @@
|
|
|
1
1
|
import {Dispatch, SetStateAction, useMemo, useState} from 'react';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* A search param entry defines the
|
|
4
|
+
* A search param entry defines the encoded value of a search parameter as `[key, value, alwaysEmit?]`.
|
|
5
|
+
* The third entry is an optional boolean that defaults to `false`.
|
|
6
|
+
* Setting `alwaysEmit` to `true` means any non-nullish value is always written to the search params,
|
|
7
|
+
* even if it matches the initial value. It is also written on initialization.
|
|
5
8
|
*/
|
|
6
|
-
export type SearchParamEntry = [string, string | null | undefined];
|
|
9
|
+
export type SearchParamEntry = [string, string | null | undefined, boolean?];
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
|
-
*
|
|
12
|
+
* Get the index of the ? in a URL that denotes the start of the "search".
|
|
13
|
+
* Performs a nested search for '#/', to detect hash router urls and take the params of the hash in that case.
|
|
10
14
|
*
|
|
11
|
-
* @param
|
|
12
|
-
* @
|
|
13
|
-
* @param filter Optional filter that allows to treat non-empty values as empty (e.g. to not set default values).
|
|
15
|
+
* @param url The URL to search.
|
|
16
|
+
* @returns The location of the question mark, or `-1` if not found.
|
|
14
17
|
*/
|
|
15
|
-
const
|
|
16
|
-
target: Map<string, string> | URLSearchParams,
|
|
17
|
-
entries: Iterable<SearchParamEntry>,
|
|
18
|
-
filter: (entry: Readonly<SearchParamEntry>) => boolean,
|
|
19
|
-
): void => {
|
|
20
|
-
for (const entry of entries) {
|
|
21
|
-
if (entry[1] && filter(entry)) {
|
|
22
|
-
target.set(entry[0], entry[1]);
|
|
23
|
-
} else {
|
|
24
|
-
target.delete(entry[0]);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
};
|
|
18
|
+
const indexOfSearch = (url: string): number => url.indexOf('?', url.indexOf('#/') + 1);
|
|
28
19
|
|
|
29
20
|
/**
|
|
30
21
|
* Read the **current** search params from `window.location`, with support for detecting React's HashRouter.
|
|
@@ -32,21 +23,28 @@ const applyValues = (
|
|
|
32
23
|
*
|
|
33
24
|
* @returns The `URLSearchParams` instance, and a function that can be used to get an updated href.
|
|
34
25
|
*/
|
|
35
|
-
const getSearchParams = ():
|
|
26
|
+
const getSearchParams = (): URLSearchParams => {
|
|
36
27
|
const href = window.location.href;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
28
|
+
const searchStart = indexOfSearch(href);
|
|
29
|
+
return new URLSearchParams(searchStart < 0 ? undefined : href.substring(searchStart));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Apply the search params to the current location, using `replaceState` (no navigation history).
|
|
34
|
+
* Note that only parameters in the `params` argument will be set, any other current params will be removed.
|
|
35
|
+
*
|
|
36
|
+
* @param params The parameters to apply.
|
|
37
|
+
*/
|
|
38
|
+
const applySearchParams = (params: URLSearchParams): void => {
|
|
39
|
+
const currentHref = window.location.href;
|
|
40
|
+
const index = indexOfSearch(currentHref);
|
|
41
|
+
let nextHref = index < 0 ? currentHref : currentHref.substring(0, index);
|
|
42
|
+
if (params.size > 0) {
|
|
43
|
+
nextHref = nextHref.concat('?', params.toString());
|
|
44
|
+
}
|
|
45
|
+
if (nextHref !== currentHref) {
|
|
46
|
+
window.history.replaceState(null, '', nextHref);
|
|
47
|
+
}
|
|
50
48
|
};
|
|
51
49
|
|
|
52
50
|
export interface UseUrlSyncedStateOptions<T> {
|
|
@@ -55,7 +53,7 @@ export interface UseUrlSyncedStateOptions<T> {
|
|
|
55
53
|
* These values are also treated as defaults, and if the current state matches the initialState,
|
|
56
54
|
* no value will be written to the search params.
|
|
57
55
|
*/
|
|
58
|
-
initialState: T
|
|
56
|
+
initialState: T | (() => T);
|
|
59
57
|
/**
|
|
60
58
|
* The serializer function is used to determine how the state is translated to url search parameters.
|
|
61
59
|
* Called each time the state changes.
|
|
@@ -72,10 +70,11 @@ export interface UseUrlSyncedStateOptions<T> {
|
|
|
72
70
|
* May return a partial state, values that are not deserialed are taken from the `initialState`.
|
|
73
71
|
* Called only once when initializing the state.
|
|
74
72
|
* @param params All the search parameters of the current url.
|
|
73
|
+
* @param initialState The initialState, can be used to take defaults from.
|
|
75
74
|
* @returns The initial state based on the current url.
|
|
76
75
|
* @example (params) => params.get('filter') ?? '',
|
|
77
76
|
*/
|
|
78
|
-
deserializer: (params: URLSearchParams) => T;
|
|
77
|
+
deserializer: (params: URLSearchParams, initialState: T) => T;
|
|
79
78
|
/**
|
|
80
79
|
* Whether the state should be synced with the url, defaults to `true`.
|
|
81
80
|
* When set to `false`, the hook behaves just like a regular `useState` hook from react.
|
|
@@ -83,38 +82,54 @@ export interface UseUrlSyncedStateOptions<T> {
|
|
|
83
82
|
sync?: boolean;
|
|
84
83
|
}
|
|
85
84
|
|
|
85
|
+
const getInitialState = <T>(options: UseUrlSyncedStateOptions<T>): T =>
|
|
86
|
+
options.initialState instanceof Function ? options.initialState() : options.initialState;
|
|
87
|
+
|
|
86
88
|
export const useUrlSyncedState = <T>(options: UseUrlSyncedStateOptions<T>) => {
|
|
87
89
|
const sync = options.sync !== false;
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
// Capture the initial state as a map, to compare values and not set them if they match.
|
|
90
|
+
const [state, setState] = useState<T>(() => {
|
|
91
|
+
const initialState = getInitialState(options);
|
|
92
|
+
return sync ? options.deserializer(getSearchParams(), initialState) : initialState;
|
|
93
|
+
});
|
|
94
|
+
// Capture the initial state as a map (first render only!), to compare values and see if they should be set to the params.
|
|
94
95
|
const initialStateSerialized = useMemo(() => {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
96
|
+
const stateMap = new Map<string, string>();
|
|
97
|
+
let initialize: URLSearchParams | null = null;
|
|
98
|
+
for (const [key, value, alwaysEmit] of options.serializer(getInitialState(options))) {
|
|
99
|
+
stateMap.set(key, value);
|
|
100
|
+
if (alwaysEmit && value) {
|
|
101
|
+
initialize ??= getSearchParams();
|
|
102
|
+
initialize.set(key, value);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (initialize) {
|
|
106
|
+
applySearchParams(initialize);
|
|
107
|
+
}
|
|
108
|
+
return stateMap;
|
|
109
|
+
}, []);
|
|
110
|
+
|
|
111
|
+
const enhancedSetState = useMemo<Dispatch<SetStateAction<T>>>(() => {
|
|
112
|
+
if (!sync) {
|
|
113
|
+
return setState;
|
|
114
|
+
}
|
|
115
|
+
return (updater: SetStateAction<T>) => {
|
|
116
|
+
setState((old) => {
|
|
117
|
+
const newValue = updater instanceof Function ? updater(old) : updater;
|
|
118
|
+
|
|
119
|
+
const search = getSearchParams();
|
|
120
|
+
for (const [key, value, alwaysEmit] of options.serializer(newValue)) {
|
|
121
|
+
if (value && (alwaysEmit || !Object.is(initialStateSerialized.get(key), value))) {
|
|
122
|
+
search.set(key, value);
|
|
123
|
+
} else {
|
|
124
|
+
search.delete(key);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
applySearchParams(search);
|
|
128
|
+
|
|
129
|
+
return newValue;
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
}, [sync]);
|
|
118
133
|
|
|
119
134
|
return [state, enhancedSetState] as const;
|
|
120
135
|
};
|