@data-fair/lib-vue 1.21.1 → 1.22.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/async-action.js +43 -40
- package/computed-deep-diff.js +9 -0
- package/concept-filters.js +22 -20
- package/deep-diff.d.ts +3 -0
- package/deep-diff.js +14 -0
- package/fetch.js +57 -50
- package/locale-dayjs-global.js +4 -4
- package/locale-dayjs.js +33 -32
- package/package.json +2 -1
- package/reactive-search-params-global.js +3 -3
- package/reactive-search-params.js +140 -124
- package/session.js +369 -325
- package/ui-notif.js +80 -63
- package/vite.d.ts +1 -0
- package/vite.js +15 -14
- package/ws.js +62 -58
|
@@ -1,139 +1,155 @@
|
|
|
1
1
|
// inspired by useUrlSearchParams (https://github.com/vueuse/vueuse/blob/main/packages/core/useUrlSearchParams/index.ts)
|
|
2
2
|
// but even simpler, without array values, always in history mode, and shared in a app plugin
|
|
3
|
-
import { reactive, watch, inject, computed } from 'vue'
|
|
4
|
-
import Debug from 'debug'
|
|
5
|
-
const debug = Debug('reactive-search-params')
|
|
6
|
-
debug.log = console.log.bind(console)
|
|
3
|
+
import { reactive, watch, inject, computed } from 'vue';
|
|
4
|
+
import Debug from 'debug';
|
|
5
|
+
const debug = Debug('reactive-search-params');
|
|
6
|
+
debug.log = console.log.bind(console);
|
|
7
7
|
const applySearchParams = (state, queryParams) => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const unusedKeys = new Set(Object.keys(state));
|
|
9
|
+
for (const key of Object.keys(queryParams)) {
|
|
10
|
+
const value = queryParams[key];
|
|
11
|
+
if (typeof value === 'string') {
|
|
12
|
+
state[key] = value;
|
|
13
|
+
unusedKeys.delete(key);
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
const lastValue = value[value.length - 1];
|
|
17
|
+
if (typeof lastValue === 'string') {
|
|
18
|
+
state[key] = lastValue;
|
|
19
|
+
unusedKeys.delete(key);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
14
22
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (typeof lastValue === 'string') {
|
|
18
|
-
state[key] = lastValue
|
|
19
|
-
unusedKeys.delete(key)
|
|
20
|
-
}
|
|
23
|
+
for (const unusedKey of unusedKeys) {
|
|
24
|
+
delete state[unusedKey];
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
debug('using nuxt 3 router implicitly')
|
|
35
|
-
} catch (e) {
|
|
36
|
-
// nothing to do
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const state = reactive({})
|
|
40
|
-
// 2 modes, 1 based on vue router, 1 based on window.location.search
|
|
41
|
-
if (router) {
|
|
42
|
-
debug('initialize reactive search params based on vue router')
|
|
43
|
-
watch(router.currentRoute, (route) => {
|
|
44
|
-
debug('route.query changed', route.query)
|
|
45
|
-
applySearchParams(state, route.query)
|
|
46
|
-
}, { immediate: true })
|
|
47
|
-
watch(state, () => {
|
|
48
|
-
debug('state changed', state)
|
|
49
|
-
router?.replace({ query: state })
|
|
50
|
-
})
|
|
51
|
-
} else {
|
|
52
|
-
debug('initialize reactive search params based on window.location.search')
|
|
53
|
-
window.addEventListener('popstate', () => {
|
|
54
|
-
debug('update state based on window.location.search', window.location.search)
|
|
55
|
-
applySearchParams(state, Object.fromEntries(new URLSearchParams(window.location.search)))
|
|
56
|
-
})
|
|
57
|
-
applySearchParams(state, Object.fromEntries(new URLSearchParams(window.location.search)))
|
|
58
|
-
const updateUrl = () => {
|
|
59
|
-
debug('update url based on state', state)
|
|
60
|
-
const params = new URLSearchParams('')
|
|
61
|
-
for (const key of Object.keys(state)) {
|
|
62
|
-
const value = state[key]
|
|
63
|
-
if (value !== null && value !== undefined && value !== '') {
|
|
64
|
-
params.set(key, value)
|
|
26
|
+
};
|
|
27
|
+
export function getReactiveSearchParams(router) {
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
if (!import.meta.env?.SSR && !router) {
|
|
30
|
+
try {
|
|
31
|
+
// nuxt 3 way of reading router
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
router = __unctx__.get('nuxt-app').use().$router;
|
|
34
|
+
debug('using nuxt 3 router implicitly');
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
// nothing to do
|
|
65
38
|
}
|
|
66
|
-
}
|
|
67
|
-
const newQuery = params.toString()
|
|
68
|
-
const newSearch = newQuery.length > 0 ? '?' + newQuery : ''
|
|
69
|
-
if (newSearch !== window.location.search) {
|
|
70
|
-
window.history.replaceState(window.history.state, window.document.title, window.location.pathname + newSearch)
|
|
71
|
-
}
|
|
72
39
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
40
|
+
const state = reactive({});
|
|
41
|
+
// 2 modes, 1 based on vue router, 1 based on window.location.search
|
|
42
|
+
if (router) {
|
|
43
|
+
debug('initialize reactive search params based on vue router');
|
|
44
|
+
watch(router.currentRoute, (route) => {
|
|
45
|
+
debug('route.query changed', route.query);
|
|
46
|
+
applySearchParams(state, route.query);
|
|
47
|
+
}, { immediate: true });
|
|
48
|
+
watch(state, () => {
|
|
49
|
+
debug('state changed', state);
|
|
50
|
+
router?.replace({ query: state });
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
debug('initialize reactive search params based on window.location.search');
|
|
55
|
+
window.addEventListener('popstate', () => {
|
|
56
|
+
debug('update state based on window.location.search', window.location.search);
|
|
57
|
+
applySearchParams(state, Object.fromEntries(new URLSearchParams(window.location.search)));
|
|
58
|
+
});
|
|
59
|
+
applySearchParams(state, Object.fromEntries(new URLSearchParams(window.location.search)));
|
|
60
|
+
const updateUrl = () => {
|
|
61
|
+
debug('update url based on state', state);
|
|
62
|
+
const params = new URLSearchParams('');
|
|
63
|
+
for (const key of Object.keys(state)) {
|
|
64
|
+
const value = state[key];
|
|
65
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
66
|
+
params.set(key, value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const newQuery = params.toString();
|
|
70
|
+
const newSearch = newQuery.length > 0 ? '?' + newQuery : '';
|
|
71
|
+
if (newSearch !== window.location.search) {
|
|
72
|
+
window.history.replaceState(window.history.state, window.document.title, window.location.pathname + newSearch);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
watch(state, () => {
|
|
76
|
+
updateUrl();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return state;
|
|
78
80
|
}
|
|
79
81
|
// uses pattern for SSR friendly plugin/composable, cf https://antfu.me/posts/composable-vue-vueday-2021#shared-state-ssr-friendly
|
|
80
|
-
export const reactiveSearchParamsKey = Symbol('reactiveSearchParams')
|
|
81
|
-
export function createReactiveSearchParams
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
export const reactiveSearchParamsKey = Symbol('reactiveSearchParams');
|
|
83
|
+
export function createReactiveSearchParams(router) {
|
|
84
|
+
const reactiveSearchParams = getReactiveSearchParams(router);
|
|
85
|
+
return {
|
|
86
|
+
install(app) { app.provide(reactiveSearchParamsKey, reactiveSearchParams); },
|
|
87
|
+
state: reactiveSearchParams
|
|
88
|
+
};
|
|
87
89
|
}
|
|
88
|
-
export function useReactiveSearchParams
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
export function useReactiveSearchParams() {
|
|
91
|
+
const reactiveSearchParams = inject(reactiveSearchParamsKey);
|
|
92
|
+
if (!reactiveSearchParams)
|
|
93
|
+
throw new Error('useReactiveSearchParams requires using the plugin createReactiveSearchParams');
|
|
94
|
+
return reactiveSearchParams;
|
|
92
95
|
}
|
|
93
96
|
export const useStringSearchParam = (key, options = {}) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
const reactiveSearchParams = useReactiveSearchParams();
|
|
98
|
+
const defaultValue = typeof options === 'string' ? options : (options.default ?? '');
|
|
99
|
+
return computed({
|
|
100
|
+
get: () => reactiveSearchParams[key] ?? defaultValue,
|
|
101
|
+
set: (value) => {
|
|
102
|
+
if (value === defaultValue)
|
|
103
|
+
delete reactiveSearchParams[key];
|
|
104
|
+
else
|
|
105
|
+
reactiveSearchParams[key] = value;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
103
109
|
export const useBooleanSearchParam = (key, options = {}) => {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
const reactiveSearchParams = useReactiveSearchParams();
|
|
111
|
+
const defaultValue = typeof options === 'boolean' ? options : (options.default ?? false);
|
|
112
|
+
const strings = (typeof options !== 'boolean' && options.strings) || ['1', '0'];
|
|
113
|
+
return computed({
|
|
114
|
+
get: () => key in reactiveSearchParams ? (reactiveSearchParams[key] === strings[0] || reactiveSearchParams[key] === 'true') : defaultValue,
|
|
115
|
+
set: (value) => {
|
|
116
|
+
if (value === defaultValue)
|
|
117
|
+
delete reactiveSearchParams[key];
|
|
118
|
+
else
|
|
119
|
+
reactiveSearchParams[key] = value ? strings[0] : strings[1];
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
};
|
|
114
123
|
export const useNumberSearchParam = (key) => {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
const reactiveSearchParams = useReactiveSearchParams();
|
|
125
|
+
return computed({
|
|
126
|
+
get: () => {
|
|
127
|
+
if (key in reactiveSearchParams) {
|
|
128
|
+
const value = Number(reactiveSearchParams[key]);
|
|
129
|
+
if (!isNaN(value))
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
},
|
|
134
|
+
set: (value) => {
|
|
135
|
+
if (value === null)
|
|
136
|
+
delete reactiveSearchParams[key];
|
|
137
|
+
else
|
|
138
|
+
reactiveSearchParams[key] = '' + value;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
};
|
|
129
142
|
export const useStringsArraySearchParam = (key, options = {}) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
const reactiveSearchParams = useReactiveSearchParams();
|
|
144
|
+
// const style = typeof options === 'string' ? options : (options.style ?? 'csv')
|
|
145
|
+
return computed({
|
|
146
|
+
get: () => reactiveSearchParams[key] ? reactiveSearchParams[key]?.split(',') : [],
|
|
147
|
+
set: (value) => {
|
|
148
|
+
if (value.length === 0)
|
|
149
|
+
delete reactiveSearchParams[key];
|
|
150
|
+
else
|
|
151
|
+
reactiveSearchParams[key] = value.join(',');
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
export default useReactiveSearchParams;
|