@codeleap/web 4.0.1 → 4.1.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/package.json +3 -3
- package/src/components/Collapse/index.tsx +3 -4
- package/src/components/EmptyPlaceholder/index.tsx +9 -5
- package/src/components/EmptyPlaceholder/types.ts +1 -0
- package/src/components/List/ListLayout.tsx +2 -1
- package/src/components/List/index.tsx +2 -0
- package/src/components/List/types.ts +2 -0
- package/src/components/Select/index.tsx +10 -6
- package/src/components/Select/styles.ts +11 -2
- package/src/components/Select/types.ts +2 -1
- package/src/lib/hooks/useCropPicker.ts +6 -4
- package/src/lib/tools/navigation/{index.ts → index.tsx} +21 -19
- package/src/lib/tools/navigation/types.ts +8 -9
- package/src/types/utility.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeleap/web",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/codeleap-uk/internal-libs-monorepo.git",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"lint": "eslint -c .eslintrc.js --fix \"./src/**/*.{ts,tsx,js,jsx}\""
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@radix-ui/react-progress": "
|
|
23
|
+
"@radix-ui/react-progress": "1.1.0",
|
|
24
24
|
"@radix-ui/react-slider": "1.1.1",
|
|
25
25
|
"@radix-ui/react-tooltip": "^1.0.6",
|
|
26
26
|
"@tiptap/react": "2.1.16",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"react-dropzone": "^14.2.3",
|
|
34
34
|
"react-image-crop": "^10.1.8",
|
|
35
35
|
"react-input-mask": "^2.0.4",
|
|
36
|
-
"react-number-format": "^5.2
|
|
36
|
+
"react-number-format": "^5.4.2",
|
|
37
37
|
"react-select": "^5.7.3",
|
|
38
38
|
"react-slick": "^0.29.0",
|
|
39
39
|
"slick-carousel": "^1.8.1",
|
|
@@ -26,10 +26,9 @@ export const Collapse = (props: CollapseProps) => {
|
|
|
26
26
|
animate={{ height: open ? 'auto' : 0, opacity: open ? 1 : 0 }}
|
|
27
27
|
transition={{ duration: 0.2 }}
|
|
28
28
|
{...rest}
|
|
29
|
-
style={
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}}
|
|
29
|
+
style={open ? styles?.['wrapper:open'] : styles?.['wrapper:closed']}
|
|
30
|
+
// @ts-expect-error css type
|
|
31
|
+
css={[styles.wrapper, open ? styles?.['wrapper:open'] : styles?.['wrapper:closed']]}
|
|
33
32
|
>
|
|
34
33
|
{children}
|
|
35
34
|
</motion.div>
|
|
@@ -27,6 +27,7 @@ export const EmptyPlaceholder = (props: EmptyPlaceholderProps) => {
|
|
|
27
27
|
imageWrapperProps,
|
|
28
28
|
indicatorProps,
|
|
29
29
|
debugName,
|
|
30
|
+
ImageComponent,
|
|
30
31
|
} = {
|
|
31
32
|
...EmptyPlaceholder.defaultProps,
|
|
32
33
|
...props,
|
|
@@ -39,11 +40,14 @@ export const EmptyPlaceholder = (props: EmptyPlaceholderProps) => {
|
|
|
39
40
|
const activityIndicatorStyles = useNestedStylesByKey('loader', styles)
|
|
40
41
|
|
|
41
42
|
const _Image = React.useMemo(() => {
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
|
|
44
|
+
if (!TypeGuards.isNil(image)) {
|
|
45
|
+
|
|
46
|
+
return <ImageComponent
|
|
44
47
|
{...imageProps}
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
source={image as HTMLImageElement['src']}
|
|
50
|
+
|
|
47
51
|
css={styles.image}
|
|
48
52
|
/>
|
|
49
53
|
}
|
|
@@ -102,7 +106,7 @@ export const EmptyPlaceholder = (props: EmptyPlaceholderProps) => {
|
|
|
102
106
|
EmptyPlaceholder.styleRegistryName = 'EmptyPlaceholder'
|
|
103
107
|
EmptyPlaceholder.elements = ['wrapper', 'loader', 'title', 'description', 'image', 'imageWrapper', 'icon']
|
|
104
108
|
EmptyPlaceholder.rootElement = 'wrapper'
|
|
105
|
-
|
|
109
|
+
EmptyPlaceholder.ImageComponent = 'img'
|
|
106
110
|
EmptyPlaceholder.withVariantTypes = <S extends AnyRecord>(styles: S) => {
|
|
107
111
|
return EmptyPlaceholder as (props: StyledComponentProps<EmptyPlaceholderProps, typeof styles>) => IJSX
|
|
108
112
|
}
|
|
@@ -56,6 +56,7 @@ export const ListLayout = (props: ListLayoutProps) => {
|
|
|
56
56
|
ListLoadingIndicatorComponent,
|
|
57
57
|
scrollableRef,
|
|
58
58
|
showFooter = true,
|
|
59
|
+
wrapperProps,
|
|
59
60
|
} = props
|
|
60
61
|
|
|
61
62
|
const getKeyStyle = (key: ListParts) => mergeStyles([
|
|
@@ -67,7 +68,7 @@ export const ListLayout = (props: ListLayoutProps) => {
|
|
|
67
68
|
const showIndicator = (isFetching || isFetchingNextPage) && !TypeGuards.isNil(ListLoadingIndicatorComponent)
|
|
68
69
|
|
|
69
70
|
return (
|
|
70
|
-
<View style={getKeyStyle('wrapper')} ref={scrollableRef}>
|
|
71
|
+
<View style={getKeyStyle('wrapper')} ref={scrollableRef} {...wrapperProps}>
|
|
71
72
|
{!!ListHeaderComponent ? <ListHeaderComponent /> : null}
|
|
72
73
|
|
|
73
74
|
{isEmpty ? <ListEmptyComponent debugName={debugName} {...placeholder} /> : null}
|
|
@@ -33,6 +33,7 @@ export function List(props: ListProps) {
|
|
|
33
33
|
reloadTimeout,
|
|
34
34
|
showFooter,
|
|
35
35
|
style,
|
|
36
|
+
layoutWrapperProps,
|
|
36
37
|
} = allProps
|
|
37
38
|
|
|
38
39
|
const styles = useStylesFor(List.styleRegistryName, style)
|
|
@@ -75,6 +76,7 @@ export function List(props: ListProps) {
|
|
|
75
76
|
<ListLayout
|
|
76
77
|
{...allProps}
|
|
77
78
|
{...layoutProps}
|
|
79
|
+
wrapperProps={layoutWrapperProps}
|
|
78
80
|
styles={styles}
|
|
79
81
|
showFooter={reloadingLayout ? false : showFooter}
|
|
80
82
|
>
|
|
@@ -12,6 +12,7 @@ export type ListLayoutProps = Omit<ListProps, 'renderItem'> & UseInfiniteScrollR
|
|
|
12
12
|
styles: StylesOf<ListComposition>
|
|
13
13
|
children?: React.ReactNode
|
|
14
14
|
showFooter?: boolean
|
|
15
|
+
wrapperProps?: Partial<ViewProps>
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export type ListRefreshControlComponent = Partial<ListLayoutProps> & {
|
|
@@ -64,4 +65,5 @@ export type ListProps<T extends ListItem = ListItem> =
|
|
|
64
65
|
masonryProps?: Partial<ListMasonryProps<T>>
|
|
65
66
|
reloadTimeout?: number
|
|
66
67
|
showFooter?: boolean
|
|
68
|
+
layoutWrapperProps?: Partial<ViewProps>
|
|
67
69
|
}
|
|
@@ -29,7 +29,9 @@ const DefaultOption = (props: TCustomOption & { component: (props: TCustomOption
|
|
|
29
29
|
debugName,
|
|
30
30
|
} = props
|
|
31
31
|
|
|
32
|
-
const
|
|
32
|
+
const optionProps = props?.data?.itemProps
|
|
33
|
+
|
|
34
|
+
const styles = optionsStyles({ isSelected, isFocused, baseStyles: (optionProps?.style ?? itemProps?.style ?? {}) })
|
|
33
35
|
|
|
34
36
|
let _Component = null
|
|
35
37
|
|
|
@@ -41,6 +43,7 @@ const DefaultOption = (props: TCustomOption & { component: (props: TCustomOption
|
|
|
41
43
|
rightIcon={isSelected && selectedIcon}
|
|
42
44
|
debugName={debugName}
|
|
43
45
|
{...itemProps}
|
|
46
|
+
{...optionProps}
|
|
44
47
|
style={styles}
|
|
45
48
|
/>
|
|
46
49
|
)
|
|
@@ -162,7 +165,7 @@ const defaultFormatPlaceholderNoItems = (props: PlaceholderProps & { text: strin
|
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
export const Select = forwardRef<HTMLInputElement, SelectProps>(
|
|
165
|
-
|
|
168
|
+
<T extends string | number = string, Multi extends boolean = false>
|
|
166
169
|
(props: SelectProps<T, Multi>, inputRef: React.ForwardedRef<HTMLInputElement>) => {
|
|
167
170
|
|
|
168
171
|
type Option = FormTypes.Option<T>
|
|
@@ -221,7 +224,7 @@ export const Select = forwardRef<HTMLInputElement, SelectProps>(
|
|
|
221
224
|
|
|
222
225
|
const _innerInputRef = useRef<any>(null)
|
|
223
226
|
const innerInputRef = selectRef || _innerInputRef
|
|
224
|
-
const innerWrapperRef = useRef(null)
|
|
227
|
+
const innerWrapperRef = useRef<HTMLDivElement>(null)
|
|
225
228
|
|
|
226
229
|
const hasSelectedOptionState = !TypeGuards.isNil(_selectedOption) && TypeGuards.isFunction(_setSelectedOption)
|
|
227
230
|
|
|
@@ -259,11 +262,12 @@ export const Select = forwardRef<HTMLInputElement, SelectProps>(
|
|
|
259
262
|
loadingStyles,
|
|
260
263
|
inputMultiValueStyles,
|
|
261
264
|
menuWrapperStyles,
|
|
262
|
-
// @ts-expect-error
|
|
265
|
+
// @ts-expect-error
|
|
263
266
|
} = useSelectStyles({ ...props, styleRegistryName: Select.styleRegistryName }, {
|
|
264
267
|
error: !!hasError,
|
|
265
268
|
focused: isFocused,
|
|
266
269
|
disabled: isDisabled,
|
|
270
|
+
parentWidth: innerWrapperRef?.current?.clientWidth,
|
|
267
271
|
})
|
|
268
272
|
|
|
269
273
|
useImperativeHandle(inputRef, () => {
|
|
@@ -410,6 +414,7 @@ export const Select = forwardRef<HTMLInputElement, SelectProps>(
|
|
|
410
414
|
tabSelectsValue={false}
|
|
411
415
|
tabIndex={0}
|
|
412
416
|
backspaceRemovesValue={true}
|
|
417
|
+
menuPortalTarget={typeof document === 'undefined' ? undefined : document.body}
|
|
413
418
|
{...otherProps}
|
|
414
419
|
{..._props}
|
|
415
420
|
onKeyDown={isFocused ? handleKeyDown : null}
|
|
@@ -424,7 +429,6 @@ export const Select = forwardRef<HTMLInputElement, SelectProps>(
|
|
|
424
429
|
defaultOptions={loadOptionsOnMount}
|
|
425
430
|
ref={innerInputRef}
|
|
426
431
|
closeMenuOnSelect={closeOnSelect}
|
|
427
|
-
menuPortalTarget={innerWrapperRef.current}
|
|
428
432
|
placeholder={(loadOptionsOnMount && !loadedOptions) ? loadingMessage : placeholder}
|
|
429
433
|
isDisabled={isDisabled}
|
|
430
434
|
isClearable={clearable}
|
|
@@ -467,7 +471,7 @@ export const Select = forwardRef<HTMLInputElement, SelectProps>(
|
|
|
467
471
|
/>
|
|
468
472
|
</InputBase>
|
|
469
473
|
)
|
|
470
|
-
|
|
474
|
+
}) as StyledComponentWithProps<SelectProps>
|
|
471
475
|
|
|
472
476
|
Select.styleRegistryName = 'Select'
|
|
473
477
|
|
|
@@ -49,6 +49,7 @@ export type ComponentState = {
|
|
|
49
49
|
error?: boolean
|
|
50
50
|
focused?: boolean
|
|
51
51
|
disabled?: boolean
|
|
52
|
+
parentWidth?: number
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export type OptionState = {
|
|
@@ -60,7 +61,7 @@ export type OptionState = {
|
|
|
60
61
|
export function useSelectStyles<T, Multi extends boolean>(props: UseSelectStylesProps, state: ComponentState) {
|
|
61
62
|
const { style } = props
|
|
62
63
|
|
|
63
|
-
const { error, focused, disabled } = state
|
|
64
|
+
const { error, focused, disabled, parentWidth } = state
|
|
64
65
|
|
|
65
66
|
const styles = useStylesFor(props?.styleRegistryName, style)
|
|
66
67
|
|
|
@@ -121,10 +122,18 @@ export function useSelectStyles<T, Multi extends boolean>(props: UseSelectStyles
|
|
|
121
122
|
wrapper: stylesKey('itemsWrapper'),
|
|
122
123
|
}
|
|
123
124
|
|
|
125
|
+
const parseMenuPortalStyles = (baseStyles: CSSObjectWithLabel) => {
|
|
126
|
+
return {
|
|
127
|
+
...baseStyles,
|
|
128
|
+
width: parentWidth,
|
|
129
|
+
left: `calc(${baseStyles.left}px - ((${parentWidth}px - ${baseStyles.width}px) / 2))`
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
124
133
|
const reactSelectStyles: StylesConfig<FormTypes.Option<T>, Multi, GroupBase<FormTypes.Option<T>>> = {
|
|
125
134
|
container: (baseStyles) => stylesKey('inputContainer', baseStyles),
|
|
126
135
|
control: () => stylesKey('inputContainer'),
|
|
127
|
-
menuPortal: (baseStyles) => stylesKey('listPortal', baseStyles),
|
|
136
|
+
menuPortal: (baseStyles) => stylesKey('listPortal', parseMenuPortalStyles(baseStyles)),
|
|
128
137
|
menu: (baseStyles) => stylesKey('listWrapper', baseStyles),
|
|
129
138
|
menuList: (baseStyles) => stylesKey('list', baseStyles),
|
|
130
139
|
group: () => ({}),
|
|
@@ -27,7 +27,7 @@ type DynamicSelectProps<T, Multi extends boolean> =
|
|
|
27
27
|
>)
|
|
28
28
|
|
|
29
29
|
export type ReactSelectProps<T, Multi extends boolean = false> = Omit<InputBaseProps, 'style'> & {
|
|
30
|
-
options: FormTypes.Options<T>
|
|
30
|
+
options: FormTypes.Options<T> & { itemProps?: ButtonProps }
|
|
31
31
|
value: SelectValue<T, Multi>
|
|
32
32
|
onValueChange?: (value: SelectValue<T, Multi>) => void
|
|
33
33
|
multiple?: Multi
|
|
@@ -45,6 +45,7 @@ export type ComponentPartProps = {
|
|
|
45
45
|
export type TCustomOption = OptionProps & ComponentPartProps & ComponentCommonProps & {
|
|
46
46
|
optionsStyles: (state: OptionState) => OptionState['baseStyles']
|
|
47
47
|
selectedIcon?: string
|
|
48
|
+
data: OptionProps['data'] & { itemProps?: ButtonProps}
|
|
48
49
|
itemProps?: ButtonProps
|
|
49
50
|
styles?: OptionState['baseStyles']
|
|
50
51
|
}
|
|
@@ -16,6 +16,8 @@ export type UseCropPickerProps = Partial<ReactCropProps> & {
|
|
|
16
16
|
ref: React.MutableRefObject<FileInputRef> | React.Ref<FileInputRef>
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
type ImageType = 'png' | 'jpeg' | 'webp'
|
|
20
|
+
|
|
19
21
|
export function readImage(file: File | Blob): Promise<ImageReading> {
|
|
20
22
|
const reader = new FileReader()
|
|
21
23
|
return new Promise<ImageReading>((resolve) => {
|
|
@@ -28,7 +30,7 @@ export function readImage(file: File | Blob): Promise<ImageReading> {
|
|
|
28
30
|
})
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
export function cropImage(image: ImageReading, crop: Crop): Promise<[string, Blob]> {
|
|
33
|
+
export function cropImage(image: ImageReading, crop: Crop, type: ImageType): Promise<[string, Blob]> {
|
|
32
34
|
const canvas = document.createElement('canvas')
|
|
33
35
|
const ctx = canvas.getContext('2d', { alpha: true })
|
|
34
36
|
|
|
@@ -61,7 +63,7 @@ export function cropImage(image: ImageReading, crop: Crop): Promise<[string, Blo
|
|
|
61
63
|
readImage(blob).then(cropped => {
|
|
62
64
|
resolve([cropped.src, blob])
|
|
63
65
|
}).catch(reject)
|
|
64
|
-
},
|
|
66
|
+
}, `image/${type}`)
|
|
65
67
|
})
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -93,9 +95,9 @@ export function useCropPicker({
|
|
|
93
95
|
setTimeout(() => setImage(null), 500)
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
const onConfirmCrop = async () => {
|
|
98
|
+
const onConfirmCrop = async (imageType: ImageType = 'jpeg') => {
|
|
97
99
|
setIsLoading(true)
|
|
98
|
-
const [preview, croppedFile] = await cropImage(image, relativeCrop)
|
|
100
|
+
const [preview, croppedFile] = await cropImage(image, relativeCrop, imageType)
|
|
99
101
|
onResolved([
|
|
100
102
|
{
|
|
101
103
|
file: new File([croppedFile], 'cropped.jpg'),
|
|
@@ -5,7 +5,7 @@ const IS_SSR = typeof window === 'undefined' || typeof history === 'undefined'
|
|
|
5
5
|
|
|
6
6
|
const defaultConfig: Partial<Config> = {
|
|
7
7
|
historyEnabled: false,
|
|
8
|
-
getMetadata: () => {}
|
|
8
|
+
getMetadata: () => {},
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export type {
|
|
@@ -13,7 +13,7 @@ export type {
|
|
|
13
13
|
Routes,
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export class Navigation<O extends object, R extends object = {}> {
|
|
16
|
+
export class Navigation<O extends object, R extends object = {}, C extends Record<string, any> = {}> {
|
|
17
17
|
private _history: History = {}
|
|
18
18
|
|
|
19
19
|
private config: Config = defaultConfig
|
|
@@ -22,6 +22,8 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
22
22
|
return this._history
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
public context: C = {} as C
|
|
26
|
+
|
|
25
27
|
private putHistory(path: RoutePath, info: any = {}) {
|
|
26
28
|
const idx = Object.keys(this._history).length + 1
|
|
27
29
|
|
|
@@ -34,7 +36,7 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
34
36
|
path,
|
|
35
37
|
metadata: this.config?.getMetadata?.(),
|
|
36
38
|
info,
|
|
37
|
-
}
|
|
39
|
+
},
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
this._history = this.merge(this._history, value)
|
|
@@ -53,7 +55,7 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
53
55
|
|
|
54
56
|
constructor(
|
|
55
57
|
routes: R,
|
|
56
|
-
navigator: Navigator<O>,
|
|
58
|
+
navigator: Navigator<O, C>,
|
|
57
59
|
config: Config = {},
|
|
58
60
|
) {
|
|
59
61
|
this.navigator = navigator
|
|
@@ -69,15 +71,15 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
69
71
|
* @returns Is on the route - boolean
|
|
70
72
|
*/
|
|
71
73
|
public isCurrentRoute<T extends keyof Routes<R>>(
|
|
72
|
-
route: T,
|
|
74
|
+
route: T,
|
|
73
75
|
// @ts-expect-error
|
|
74
76
|
routeParams: Record<Routes<R>[T], string|number> = {} as any,
|
|
75
|
-
exact
|
|
77
|
+
exact = false,
|
|
76
78
|
) {
|
|
77
79
|
if (IS_SSR) return false
|
|
78
|
-
|
|
80
|
+
|
|
79
81
|
let path = window?.location?.pathname
|
|
80
|
-
|
|
82
|
+
|
|
81
83
|
// @ts-ignore
|
|
82
84
|
const routePath = this.getPathWithParams(route, routeParams)
|
|
83
85
|
|
|
@@ -99,7 +101,7 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
99
101
|
if (path?.includes(routePath)) {
|
|
100
102
|
return true
|
|
101
103
|
}
|
|
102
|
-
|
|
104
|
+
|
|
103
105
|
return false
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -134,9 +136,9 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
134
136
|
* @returns Path - string
|
|
135
137
|
*/
|
|
136
138
|
public getPathWithParams<T extends keyof Routes<R>>(
|
|
137
|
-
route: T,
|
|
139
|
+
route: T,
|
|
138
140
|
// @ts-expect-error
|
|
139
|
-
routeParams: Record<Routes<R>[T], string|number> = {} as any
|
|
141
|
+
routeParams: Record<Routes<R>[T], string|number> = {} as any,
|
|
140
142
|
) {
|
|
141
143
|
let path = this.getPath(route)
|
|
142
144
|
|
|
@@ -162,7 +164,7 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
/**
|
|
165
|
-
* Function to navigate to the previous page, if history is enabled, the penultimate record will be used,
|
|
167
|
+
* Function to navigate to the previous page, if history is enabled, the penultimate record will be used,
|
|
166
168
|
* otherwise the browser's own api with "history.back()"
|
|
167
169
|
*/
|
|
168
170
|
public goBack() {
|
|
@@ -182,7 +184,7 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
const info = this.merge(historyData?.info, {
|
|
185
|
-
'action': 'goBack'
|
|
187
|
+
'action': 'goBack',
|
|
186
188
|
})
|
|
187
189
|
|
|
188
190
|
this.to(historyData?.path, historyData?.info?.options ?? {}, info)
|
|
@@ -194,9 +196,9 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
194
196
|
* @param options Route parameters (marked by {{}}), which will be automatically shown if they exist, and navigator options and route queryParams can also be passed through the "params" property
|
|
195
197
|
*/
|
|
196
198
|
public navigate<T extends keyof Routes<R>>(
|
|
197
|
-
route: T,
|
|
199
|
+
route: T,
|
|
198
200
|
// @ts-expect-error
|
|
199
|
-
options: Record<Routes<R>[T], string|number> & O & { params?: RouteParams } = {} as any
|
|
201
|
+
options: Record<Routes<R>[T], string|number> & O & { params?: RouteParams } = {} as any,
|
|
200
202
|
) {
|
|
201
203
|
// @ts-ignore
|
|
202
204
|
let path = this.getPath(route)
|
|
@@ -229,15 +231,15 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
229
231
|
|
|
230
232
|
if (typeof params === 'object') {
|
|
231
233
|
let searchParams = null
|
|
232
|
-
|
|
234
|
+
|
|
233
235
|
for (const paramKey in (params ?? {})) {
|
|
234
236
|
const value = params?.[paramKey]
|
|
235
237
|
const param = `${paramKey}=${encodeURIComponent(value)}`
|
|
236
238
|
const separator = searchParams == null ? '' : '&'
|
|
237
|
-
|
|
239
|
+
|
|
238
240
|
searchParams = `${searchParams ?? ''}${separator}${param}`
|
|
239
241
|
}
|
|
240
|
-
|
|
242
|
+
|
|
241
243
|
if (typeof searchParams === 'string') {
|
|
242
244
|
if (path?.endsWith('/')) {
|
|
243
245
|
path = path.slice(0, -1)
|
|
@@ -268,7 +270,7 @@ export class Navigation<O extends object, R extends object = {}> {
|
|
|
268
270
|
this.putHistory(path, this.merge(options, info))
|
|
269
271
|
}
|
|
270
272
|
|
|
271
|
-
this.navigator(path, options)
|
|
273
|
+
this.navigator(path, options, this.context)
|
|
272
274
|
}
|
|
273
275
|
|
|
274
276
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
1
|
export type ExtractParams<T extends string> =
|
|
3
|
-
T extends `${infer _Start}{{${infer Param}}}${infer Rest}`
|
|
4
|
-
? Param | ExtractParams<Rest>
|
|
2
|
+
T extends `${infer _Start}{{${infer Param}}}${infer Rest}`
|
|
3
|
+
? Param | ExtractParams<Rest>
|
|
5
4
|
: never
|
|
6
5
|
|
|
7
6
|
type Params<T> = {
|
|
@@ -10,8 +9,8 @@ type Params<T> = {
|
|
|
10
9
|
|
|
11
10
|
// @ts-ignore
|
|
12
11
|
type ExtractRoutes<T, PM, Prefix extends string = ''> = {
|
|
13
|
-
[K in keyof T & string]:
|
|
14
|
-
T[K] extends string
|
|
12
|
+
[K in keyof T & string]:
|
|
13
|
+
T[K] extends string
|
|
15
14
|
? {
|
|
16
15
|
// @ts-ignore
|
|
17
16
|
[P in `${Prefix}${Prefix extends '' ? '' : '.'}${K}`]: PM[K]
|
|
@@ -19,7 +18,7 @@ type ExtractRoutes<T, PM, Prefix extends string = ''> = {
|
|
|
19
18
|
: ExtractRoutes<T[K], PM[K], `${Prefix}${Prefix extends '' ? '' : '.'}${K}`>
|
|
20
19
|
}[keyof T]
|
|
21
20
|
|
|
22
|
-
type UnionToIntersection<U> =
|
|
21
|
+
type UnionToIntersection<U> =
|
|
23
22
|
(U extends any ? (x: U)=> void : never) extends ((x: infer I)=>void) ? I : never
|
|
24
23
|
|
|
25
24
|
export type Routes<T> = UnionToIntersection<ExtractRoutes<T, Params<T>>>
|
|
@@ -32,7 +31,7 @@ export type RouteParams = {
|
|
|
32
31
|
[x: string]: string
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
export type Navigator<O extends object = {}> = (path: RoutePath, options: O) => void
|
|
34
|
+
export type Navigator<O extends object = {}, C extends Record<string, any> = {}> = (path: RoutePath, options: O, context?: C) => void
|
|
36
35
|
|
|
37
36
|
export type AnyValue = {
|
|
38
37
|
[key: string]: any
|
|
@@ -40,8 +39,8 @@ export type AnyValue = {
|
|
|
40
39
|
|
|
41
40
|
export type HistoryData = {
|
|
42
41
|
origin: string
|
|
43
|
-
date: Date
|
|
44
|
-
path: RoutePath
|
|
42
|
+
date: Date
|
|
43
|
+
path: RoutePath
|
|
45
44
|
metadata: any
|
|
46
45
|
info: any
|
|
47
46
|
}
|
package/src/types/utility.ts
CHANGED
|
@@ -22,6 +22,11 @@ export type ElementMap = {
|
|
|
22
22
|
'section': WithChildren<JSX.IntrinsicElements['section']>
|
|
23
23
|
'header': WithChildren<JSX.IntrinsicElements['header']>
|
|
24
24
|
'footer': WithChildren<JSX.IntrinsicElements['footer']>
|
|
25
|
+
'nav': WithChildren<JSX.IntrinsicElements['nav']>
|
|
26
|
+
'article': WithChildren<JSX.IntrinsicElements['article']>
|
|
27
|
+
'ul': WithChildren<JSX.IntrinsicElements['ul']>
|
|
28
|
+
'ol': WithChildren<JSX.IntrinsicElements['ol']>
|
|
29
|
+
'aside': WithChildren<JSX.IntrinsicElements['aside']>
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
export type NativeHTMLElement = keyof ElementMap
|