@servicetitan/marketing-ui 0.5.0 → 0.8.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/dist/components/image-cropper/image-cropper.d.ts +23 -0
- package/dist/components/image-cropper/image-cropper.d.ts.map +1 -0
- package/dist/components/image-cropper/image-cropper.js +146 -0
- package/dist/components/image-cropper/image-cropper.js.map +1 -0
- package/dist/components/image-cropper/image-cropper.stories.d.ts +10 -0
- package/dist/components/image-cropper/image-cropper.stories.d.ts.map +1 -0
- package/dist/components/image-cropper/image-cropper.stories.js +55 -0
- package/dist/components/image-cropper/image-cropper.stories.js.map +1 -0
- package/dist/components/ui/date-range-picker/date-range-picker.d.ts +10 -0
- package/dist/components/ui/date-range-picker/date-range-picker.d.ts.map +1 -0
- package/dist/components/ui/date-range-picker/date-range-picker.js +77 -0
- package/dist/components/ui/date-range-picker/date-range-picker.js.map +1 -0
- package/dist/components/ui/date-range-picker/date-range-picker.module.less +42 -0
- package/dist/components/ui/date-range-picker/date-range-picker.stories.d.ts +10 -0
- package/dist/components/ui/date-range-picker/date-range-picker.stories.d.ts.map +1 -0
- package/dist/components/ui/date-range-picker/date-range-picker.stories.js +17 -0
- package/dist/components/ui/date-range-picker/date-range-picker.stories.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/date/__mocks__/date-mock.d.ts +5 -0
- package/dist/utils/date/__mocks__/date-mock.d.ts.map +1 -0
- package/dist/utils/date/__mocks__/date-mock.js +23 -0
- package/dist/utils/date/__mocks__/date-mock.js.map +1 -0
- package/dist/utils/date/date-range-picker-options.d.ts +45 -0
- package/dist/utils/date/date-range-picker-options.d.ts.map +1 -0
- package/dist/utils/date/date-range-picker-options.js +138 -0
- package/dist/utils/date/date-range-picker-options.js.map +1 -0
- package/dist/utils/date/date-range-picker-state.d.ts +24 -0
- package/dist/utils/date/date-range-picker-state.d.ts.map +1 -0
- package/dist/utils/date/date-range-picker-state.js +73 -0
- package/dist/utils/date/date-range-picker-state.js.map +1 -0
- package/dist/utils/date/date-tenant.d.ts +17 -0
- package/dist/utils/date/date-tenant.d.ts.map +1 -0
- package/dist/utils/date/date-tenant.js +51 -0
- package/dist/utils/date/date-tenant.js.map +1 -0
- package/dist/utils/date/date.d.ts +11 -0
- package/dist/utils/date/date.d.ts.map +1 -0
- package/dist/utils/date/date.js +22 -0
- package/dist/utils/date/date.js.map +1 -0
- package/dist/utils/date/index.d.ts +5 -0
- package/dist/utils/date/index.d.ts.map +1 -0
- package/dist/utils/date/index.js +17 -0
- package/dist/utils/date/index.js.map +1 -0
- package/dist/utils/history/history.d.ts +9 -3
- package/dist/utils/history/history.d.ts.map +1 -1
- package/dist/utils/history/history.js +9 -7
- package/dist/utils/history/history.js.map +1 -1
- package/dist/utils/history/index.d.ts +1 -0
- package/dist/utils/history/index.d.ts.map +1 -1
- package/dist/utils/history/index.js +1 -0
- package/dist/utils/history/index.js.map +1 -1
- package/dist/utils/history/query-params-handler.d.ts +1 -0
- package/dist/utils/history/query-params-handler.d.ts.map +1 -1
- package/dist/utils/history/query-params-handler.js +3 -0
- package/dist/utils/history/query-params-handler.js.map +1 -1
- package/dist/utils/history/url-params-handler.d.ts +18 -0
- package/dist/utils/history/url-params-handler.d.ts.map +1 -0
- package/dist/utils/history/url-params-handler.js +64 -0
- package/dist/utils/history/url-params-handler.js.map +1 -0
- package/dist/utils/history/use-query-params.d.ts.map +1 -1
- package/dist/utils/history/use-query-params.js +5 -3
- package/dist/utils/history/use-query-params.js.map +1 -1
- package/dist/utils/history/use-url-params.d.ts +5 -5
- package/dist/utils/history/use-url-params.d.ts.map +1 -1
- package/dist/utils/history/use-url-params.js +4 -19
- package/dist/utils/history/use-url-params.js.map +1 -1
- package/dist/utils/{use-init-effect.d.ts → invariable-hooks.d.ts} +6 -1
- package/dist/utils/invariable-hooks.d.ts.map +1 -0
- package/dist/utils/{use-init-effect.js → invariable-hooks.js} +11 -2
- package/dist/utils/invariable-hooks.js.map +1 -0
- package/dist/utils/param-parsers.d.ts +2 -1
- package/dist/utils/param-parsers.d.ts.map +1 -1
- package/dist/utils/param-parsers.js +21 -1
- package/dist/utils/param-parsers.js.map +1 -1
- package/package.json +5 -3
- package/src/components/image-cropper/image-cropper.stories.tsx +69 -0
- package/src/components/image-cropper/image-cropper.tsx +108 -0
- package/src/components/ui/date-range-picker/date-range-picker.module.less +42 -0
- package/src/components/ui/date-range-picker/date-range-picker.module.less.d.ts +4 -0
- package/src/components/ui/date-range-picker/date-range-picker.stories.tsx +22 -0
- package/src/components/ui/date-range-picker/date-range-picker.tsx +118 -0
- package/src/index.ts +2 -1
- package/src/utils/__tests__/param-parsers.test.ts +11 -2
- package/src/utils/date/__mocks__/date-mock.ts +23 -0
- package/src/utils/date/__tests__/date-range-picker.test.ts +139 -0
- package/src/utils/date/__tests__/date-tenant.test.ts +38 -0
- package/src/utils/date/date-range-picker-options.ts +167 -0
- package/src/utils/date/date-range-picker-state.ts +62 -0
- package/src/utils/date/date-tenant.ts +49 -0
- package/src/utils/date/date.ts +29 -0
- package/src/utils/date/index.ts +4 -0
- package/src/utils/history/__tests__/history.test.ts +9 -2
- package/src/utils/history/__tests__/url-params-handler.test.ts +32 -0
- package/src/utils/history/__tests__/use-url-params.test.ts +2 -1
- package/src/utils/history/history.ts +27 -10
- package/src/utils/history/index.ts +1 -0
- package/src/utils/history/query-params-handler.ts +4 -0
- package/src/utils/history/url-params-handler.ts +65 -0
- package/src/utils/history/use-query-params.ts +5 -3
- package/src/utils/history/use-url-params.ts +7 -32
- package/src/utils/{use-init-effect.ts → invariable-hooks.ts} +10 -1
- package/src/utils/param-parsers.ts +26 -1
- package/dist/utils/use-init-effect.d.ts.map +0 -1
- package/dist/utils/use-init-effect.js.map +0 -1
|
@@ -9,7 +9,7 @@ type Keys = 'lorem' | 'ipsum' | 'dolor';
|
|
|
9
9
|
|
|
10
10
|
interface UrlParams {
|
|
11
11
|
lorem: { year: number };
|
|
12
|
-
ipsum: { name
|
|
12
|
+
ipsum: { name?: 'Search' | 'Display' };
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
interface QueryParams {
|
|
@@ -19,7 +19,7 @@ interface QueryParams {
|
|
|
19
19
|
const UrlMap: Record<Keys, string> = {
|
|
20
20
|
dolor: '/',
|
|
21
21
|
lorem: '/lorem/:year(\\d+)',
|
|
22
|
-
ipsum: '/ipsum/:name(Search|Display)',
|
|
22
|
+
ipsum: '/ipsum/:name(Search|Display)?',
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const handlers = {
|
|
@@ -48,6 +48,7 @@ describe('useParamsHistory', () => {
|
|
|
48
48
|
cb(
|
|
49
49
|
useParamsHistory<Keys, UrlParams, QueryParams>(
|
|
50
50
|
UrlMap,
|
|
51
|
+
undefined,
|
|
51
52
|
paramHandler ? handlers : undefined
|
|
52
53
|
)
|
|
53
54
|
)
|
|
@@ -81,6 +82,12 @@ describe('useParamsHistory', () => {
|
|
|
81
82
|
expect(result).toBe('/ipsum/Search');
|
|
82
83
|
});
|
|
83
84
|
|
|
85
|
+
it('check optional url params', () => {
|
|
86
|
+
const result = renderHookText(hook => hook.href('ipsum'));
|
|
87
|
+
|
|
88
|
+
expect(result).toBe('/ipsum');
|
|
89
|
+
});
|
|
90
|
+
|
|
84
91
|
it('uses query param handler', () => {
|
|
85
92
|
const result = renderHookText(
|
|
86
93
|
hook => hook.href('dolor', undefined, { to: 'Search', from: new Date(2021, 8, 9) }),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { UrlParamsHandler } from '../url-params-handler';
|
|
2
|
+
|
|
3
|
+
describe('UrlParamsHandler', () => {
|
|
4
|
+
const handler = new UrlParamsHandler<{
|
|
5
|
+
str?: string;
|
|
6
|
+
numb?: number;
|
|
7
|
+
bool?: boolean;
|
|
8
|
+
dt?: Date;
|
|
9
|
+
strArr?: string[];
|
|
10
|
+
numbArr?: number[];
|
|
11
|
+
}>({
|
|
12
|
+
str: UrlParamsHandler.parserString,
|
|
13
|
+
numb: UrlParamsHandler.parserNumber,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('parses url params', () => {
|
|
17
|
+
const result = handler.parse({ str: 'check', numb: '12' });
|
|
18
|
+
|
|
19
|
+
expect(result).toEqual({
|
|
20
|
+
str: 'check',
|
|
21
|
+
numb: 12,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('generates url string', () => {
|
|
26
|
+
const result = handler.toString({
|
|
27
|
+
numb: 15,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
expect(result).toEqual({ numb: '15' });
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -4,6 +4,7 @@ import { createMemoryHistory, History } from 'history';
|
|
|
4
4
|
import { Router, Route } from 'react-router-dom';
|
|
5
5
|
import { useUrlParams } from '../use-url-params';
|
|
6
6
|
import { paramParsers, StringParamParser } from '../../param-parsers';
|
|
7
|
+
import { UrlParamsHandler } from '../url-params-handler';
|
|
7
8
|
|
|
8
9
|
type ParsersFromValues<Values extends Record<string, any | undefined>> = {
|
|
9
10
|
[Prop in keyof Values]: StringParamParser<Values[Prop]>;
|
|
@@ -30,7 +31,7 @@ describe('useUrlParams', () => {
|
|
|
30
31
|
Route,
|
|
31
32
|
{ path },
|
|
32
33
|
React.createElement(() => {
|
|
33
|
-
result = useUrlParams(paramHandler);
|
|
34
|
+
result = useUrlParams(UrlParamsHandler.from(paramHandler));
|
|
34
35
|
|
|
35
36
|
return null;
|
|
36
37
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
1
|
import { useHistory, generatePath } from 'react-router-dom';
|
|
3
|
-
import { createPath } from 'history';
|
|
2
|
+
import { createPath, History } from 'history';
|
|
3
|
+
import { useInvariableMemo } from '../invariable-hooks';
|
|
4
4
|
import { QueryParamsHandler } from './query-params-handler';
|
|
5
|
+
import { UrlParamsHandler } from './url-params-handler';
|
|
5
6
|
|
|
6
7
|
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void
|
|
7
8
|
? I
|
|
@@ -17,12 +18,17 @@ export interface ParametrizedHistory<
|
|
|
17
18
|
href: Overloading<Keys, UrlMappings, QueryMappings, string>;
|
|
18
19
|
push: Overloading<Keys, UrlMappings, QueryMappings, void>;
|
|
19
20
|
replace: Overloading<Keys, UrlMappings, QueryMappings, void>;
|
|
21
|
+
history: History;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
type AllOverloads<Keys extends string, UrlMappings, QueryMappings, O> = {
|
|
23
25
|
[Prop in Keys]: Prop extends keyof UrlMappings
|
|
24
26
|
? Prop extends keyof QueryMappings
|
|
25
|
-
?
|
|
27
|
+
? Partial<UrlMappings[Prop]> extends UrlMappings[Prop]
|
|
28
|
+
? (key: Prop, urlParams?: UrlMappings[Prop], queryParams?: QueryMappings[Prop]) => O
|
|
29
|
+
: (key: Prop, urlParams: UrlMappings[Prop], queryParams?: QueryMappings[Prop]) => O
|
|
30
|
+
: Partial<UrlMappings[Prop]> extends UrlMappings[Prop]
|
|
31
|
+
? (key: Prop, urlParams?: UrlMappings[Prop]) => O
|
|
26
32
|
: (key: Prop, urlParams: UrlMappings[Prop]) => O
|
|
27
33
|
: Prop extends keyof QueryMappings
|
|
28
34
|
? (key: Prop, urlParams?: undefined, queryParams?: QueryMappings[Prop]) => O
|
|
@@ -33,10 +39,14 @@ type Overloading<Keys extends string, UrlMappings, QueryMappings, O> = UnionToIn
|
|
|
33
39
|
Values<AllOverloads<Keys, UrlMappings, QueryMappings, O>>
|
|
34
40
|
>;
|
|
35
41
|
|
|
36
|
-
type
|
|
42
|
+
type QueryParamHandlers<QueryMappings> = {
|
|
37
43
|
[Prop in keyof QueryMappings]?: QueryParamsHandler<QueryMappings[Prop]>;
|
|
38
44
|
};
|
|
39
45
|
|
|
46
|
+
type UrlParamHandlers<QueryMappings> = {
|
|
47
|
+
[Prop in keyof QueryMappings]?: UrlParamsHandler<QueryMappings[Prop]>;
|
|
48
|
+
};
|
|
49
|
+
|
|
40
50
|
/**
|
|
41
51
|
* Create parameterized history to check passed arguments
|
|
42
52
|
*
|
|
@@ -75,16 +85,17 @@ type ParamHandlers<QueryMappings> = {
|
|
|
75
85
|
*/
|
|
76
86
|
export const useParamsHistory = <Keys extends string, PU = void, PQ = void>(
|
|
77
87
|
paths: Record<Keys, string>,
|
|
78
|
-
|
|
88
|
+
urlHandlers?: UrlParamHandlers<PU>,
|
|
89
|
+
queryHandlers?: QueryParamHandlers<PQ>
|
|
79
90
|
): ParametrizedHistory<Keys, PU, PQ> => {
|
|
80
91
|
const history = useHistory();
|
|
81
92
|
|
|
82
|
-
return
|
|
93
|
+
return useInvariableMemo(() => {
|
|
83
94
|
const generateLocation = (path: Keys, urlParams?: any, queryParams?: any) => {
|
|
84
95
|
let searchParams = undefined;
|
|
85
96
|
|
|
86
97
|
if (queryParams) {
|
|
87
|
-
const hand = (
|
|
98
|
+
const hand = (queryHandlers as any)?.[path as any] as QueryParamsHandler<any>;
|
|
88
99
|
|
|
89
100
|
if (hand) {
|
|
90
101
|
searchParams = '?' + hand.toString(queryParams);
|
|
@@ -93,13 +104,19 @@ export const useParamsHistory = <Keys extends string, PU = void, PQ = void>(
|
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
const urlHandler = (urlHandlers as any)?.[path] as UrlParamsHandler<any>;
|
|
108
|
+
|
|
96
109
|
return {
|
|
97
|
-
pathname: generatePath(
|
|
110
|
+
pathname: generatePath(
|
|
111
|
+
paths[path],
|
|
112
|
+
urlHandler ? urlHandler.toString(urlParams) : urlParams
|
|
113
|
+
),
|
|
98
114
|
search: searchParams,
|
|
99
115
|
};
|
|
100
116
|
};
|
|
101
117
|
|
|
102
118
|
return {
|
|
119
|
+
history,
|
|
103
120
|
path: ((key: Keys, urlParams?: unknown, queryParams?: unknown) => {
|
|
104
121
|
return createPath(generateLocation(key, urlParams, queryParams));
|
|
105
122
|
}) as Overloading<Keys, PU, PQ, string>,
|
|
@@ -111,9 +128,9 @@ export const useParamsHistory = <Keys extends string, PU = void, PQ = void>(
|
|
|
111
128
|
push: ((key: Keys, urlParams?: unknown, queryParams?: unknown) => {
|
|
112
129
|
history.push(createPath(generateLocation(key, urlParams, queryParams)));
|
|
113
130
|
}) as Overloading<Keys, PU, PQ, void>,
|
|
114
|
-
replace: ((key: Keys, urlParams?:
|
|
131
|
+
replace: ((key: Keys, urlParams?: Partial<PU>, queryParams?: unknown) => {
|
|
115
132
|
history.replace(createPath(generateLocation(key, urlParams, queryParams)));
|
|
116
133
|
}) as Overloading<Keys, PU, PQ, void>,
|
|
117
134
|
};
|
|
118
|
-
}
|
|
135
|
+
});
|
|
119
136
|
};
|
|
@@ -80,6 +80,10 @@ export class QueryParamsHandler<Values extends Record<string, any | undefined>>
|
|
|
80
80
|
|
|
81
81
|
constructor(private handlers: HandlersFromValues<Values>) {}
|
|
82
82
|
|
|
83
|
+
static from<T>(handlers: HandlersFromValues<T>) {
|
|
84
|
+
return new QueryParamsHandler<T>(handlers);
|
|
85
|
+
}
|
|
86
|
+
|
|
83
87
|
toString(params: Values): string {
|
|
84
88
|
const keys = Object.keys(this.handlers);
|
|
85
89
|
const url = new URLSearchParams();
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { paramParsers, StringParamParser } from '../param-parsers';
|
|
2
|
+
import { keys } from '../helpers';
|
|
3
|
+
|
|
4
|
+
type HandlersFromValues<Values extends Record<string, any | undefined>> = {
|
|
5
|
+
[Prop in keyof Values]: StringParamParser<Values[Prop]>;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type StringParams<T extends Record<string, any>> = {
|
|
9
|
+
[Prop in keyof T]: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export class UrlParamsHandler<Values extends Record<string, any | undefined>> {
|
|
13
|
+
static readonly parserString = paramParsers.uri;
|
|
14
|
+
static readonly parserNumber = paramParsers.number;
|
|
15
|
+
|
|
16
|
+
constructor(private parsers: HandlersFromValues<Values>) {}
|
|
17
|
+
|
|
18
|
+
static from<T>(parsers: HandlersFromValues<T>) {
|
|
19
|
+
return new UrlParamsHandler<T>(parsers);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
toString(values?: Partial<Values>): Partial<StringParams<Values>> {
|
|
23
|
+
const params: Partial<StringParams<Values>> = {};
|
|
24
|
+
|
|
25
|
+
if (!values) {
|
|
26
|
+
return params;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for (const key of keys(values)) {
|
|
30
|
+
const parser = this.parsers[key];
|
|
31
|
+
|
|
32
|
+
if (!parser) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const value = values[key];
|
|
37
|
+
|
|
38
|
+
if (value !== undefined) {
|
|
39
|
+
params[key] = parser.stringify(value!);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return params;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
parse(params: StringParams<Values>): Partial<Values> {
|
|
47
|
+
const values: Partial<Values> = {};
|
|
48
|
+
|
|
49
|
+
for (const key of keys(params)) {
|
|
50
|
+
const parser = this.parsers?.[key];
|
|
51
|
+
|
|
52
|
+
if (!parser) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const value = params[key];
|
|
57
|
+
|
|
58
|
+
if (value !== undefined) {
|
|
59
|
+
values[key] = parser.parse(value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return values;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
|
|
2
2
|
import { useHistory } from 'react-router-dom';
|
|
3
3
|
import { createPath } from 'history';
|
|
4
4
|
import { QueryParamsHandler } from './query-params-handler';
|
|
5
|
+
import { useInvariableMemo } from '../invariable-hooks';
|
|
5
6
|
|
|
6
7
|
export interface QueryParamsHook<T extends Record<string, any | undefined>> {
|
|
7
8
|
values: T;
|
|
@@ -32,11 +33,12 @@ function useQueryParams<T extends Record<string, any>>(
|
|
|
32
33
|
function useQueryParams<T>(handler?: QueryParamsHandler<T>): QueryParamsHook<T> {
|
|
33
34
|
const history = useHistory();
|
|
34
35
|
const search = history.location.search || '';
|
|
36
|
+
const memoHandler = useInvariableMemo(() => handler);
|
|
35
37
|
|
|
36
38
|
return useMemo(() => {
|
|
37
|
-
const currentValues =
|
|
39
|
+
const currentValues = memoHandler ? memoHandler.parse(search) : parseParams<T>(search);
|
|
38
40
|
const stringify = (params: T) =>
|
|
39
|
-
|
|
41
|
+
memoHandler ? memoHandler.toString(params) : stringifyParams(params);
|
|
40
42
|
|
|
41
43
|
const createPathWithParams = (pathName: string, params: T) =>
|
|
42
44
|
createPath({ pathname: pathName, search: stringify(params) });
|
|
@@ -61,7 +63,7 @@ function useQueryParams<T>(handler?: QueryParamsHandler<T>): QueryParamsHook<T>
|
|
|
61
63
|
pathname: createPath({ pathname: pathName, search: stringify(params) }),
|
|
62
64
|
}),
|
|
63
65
|
};
|
|
64
|
-
}, [search,
|
|
66
|
+
}, [search, memoHandler, history]);
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
export { useQueryParams };
|
|
@@ -1,44 +1,19 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { useParams } from 'react-router-dom';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { UrlParamsHandler } from './url-params-handler';
|
|
4
|
+
import { useInvariableMemo } from '../invariable-hooks';
|
|
5
5
|
|
|
6
6
|
type StringParams<T extends Record<string, any>> = {
|
|
7
7
|
[Prop in keyof T]: string | undefined;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function useUrlParams<T extends Record<string, string>>(): Partial<T>;
|
|
15
|
-
function useUrlParams<T extends Record<string, any>>(parsers: ParsersFromValues<T>): Partial<T>;
|
|
16
|
-
function useUrlParams<T>(parsers?: ParsersFromValues<T>): Partial<T> {
|
|
10
|
+
function useUrlParams<T extends Record<string, string>>(): StringParams<T>;
|
|
11
|
+
function useUrlParams<T extends Record<string, any>>(parsers: UrlParamsHandler<T>): Partial<T>;
|
|
12
|
+
function useUrlParams<T>(handler?: UrlParamsHandler<T>): Partial<T> | StringParams<T> {
|
|
17
13
|
const params = useParams<StringParams<T>>();
|
|
14
|
+
const memoHandler = useInvariableMemo(() => handler);
|
|
18
15
|
|
|
19
|
-
return useMemo(() =>
|
|
20
|
-
if (!parsers) {
|
|
21
|
-
return params as unknown as Partial<T>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const values: Partial<T> = {};
|
|
25
|
-
|
|
26
|
-
for (const key of keys(params)) {
|
|
27
|
-
const parser = parsers[key];
|
|
28
|
-
|
|
29
|
-
if (!parser) {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const value = params[key];
|
|
34
|
-
|
|
35
|
-
if (value !== undefined) {
|
|
36
|
-
values[key] = parser.parse(value);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return values;
|
|
41
|
-
}, [parsers, params]);
|
|
16
|
+
return useMemo(() => (memoHandler ? memoHandler.parse(params) : params), [params, memoHandler]);
|
|
42
17
|
}
|
|
43
18
|
|
|
44
19
|
export { useUrlParams };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* runs effect only once for component
|
|
@@ -13,3 +13,12 @@ export function useInitEffect(init: () => void, dispose?: () => void) {
|
|
|
13
13
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
14
14
|
}, []);
|
|
15
15
|
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* gets memo only once
|
|
19
|
+
* @param memo method that returns memoed data
|
|
20
|
+
*/
|
|
21
|
+
export function useInvariableMemo<T>(memo: () => T): T {
|
|
22
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
23
|
+
return useMemo(memo, []);
|
|
24
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { keys } from './helpers';
|
|
2
|
+
|
|
1
3
|
export interface StringParamParser<T> {
|
|
2
4
|
stringify(value: T): string | undefined;
|
|
3
5
|
parse(query: string): T | undefined;
|
|
@@ -12,7 +14,7 @@ const stringParser: StringParamParser<string> = {
|
|
|
12
14
|
},
|
|
13
15
|
};
|
|
14
16
|
|
|
15
|
-
const
|
|
17
|
+
const stringSetParser = <T extends string>(values: (string | T)[]): StringParamParser<T> => ({
|
|
16
18
|
stringify(value) {
|
|
17
19
|
return value || undefined;
|
|
18
20
|
},
|
|
@@ -25,6 +27,28 @@ const stringEnumParser = <T extends string>(values: T[]): StringParamParser<T> =
|
|
|
25
27
|
},
|
|
26
28
|
});
|
|
27
29
|
|
|
30
|
+
const stringEnumParser = <TS extends string, TV>(map: Record<TS, TV>): StringParamParser<TV> => ({
|
|
31
|
+
stringify(value) {
|
|
32
|
+
for (const key of keys(map)) {
|
|
33
|
+
if (map[key] === value) {
|
|
34
|
+
return key;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return undefined;
|
|
39
|
+
},
|
|
40
|
+
parse(query) {
|
|
41
|
+
const key = query as TS;
|
|
42
|
+
|
|
43
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
44
|
+
if (map.hasOwnProperty(key)) {
|
|
45
|
+
return map[key];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return undefined;
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
28
52
|
const uriParser: StringParamParser<string> = {
|
|
29
53
|
stringify(value) {
|
|
30
54
|
return value || undefined;
|
|
@@ -70,6 +94,7 @@ const boolParser: StringParamParser<boolean> = {
|
|
|
70
94
|
|
|
71
95
|
export const paramParsers = {
|
|
72
96
|
string: stringParser,
|
|
97
|
+
stringSet: stringSetParser,
|
|
73
98
|
stringEnum: stringEnumParser,
|
|
74
99
|
uri: uriParser,
|
|
75
100
|
number: numberParser,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-init-effect.d.ts","sourceRoot":"","sources":["../../src/utils/use-init-effect.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,QAOnE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-init-effect.js","sourceRoot":"","sources":["../../src/utils/use-init-effect.ts"],"names":[],"mappings":";;;AAAA,iCAAkC;AAElC;;;;GAIG;AACH,SAAgB,aAAa,CAAC,IAAgB,EAAE,OAAoB;IAChE,iBAAS,CAAC,GAAG,EAAE;QACX,IAAI,EAAE,CAAC;QAEP,OAAO,OAAO,CAAC;QACf,uDAAuD;IAC3D,CAAC,EAAE,EAAE,CAAC,CAAC;AACX,CAAC;AAPD,sCAOC"}
|