-
Notifications
You must be signed in to change notification settings - Fork 30
/
utils.ts
88 lines (79 loc) · 2.34 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { useBreakpointValue } from "@chakra-ui/media-query";
import { useTheme } from "@chakra-ui/system";
import type { CommonPropsAndClassName, GroupBase } from "react-select";
import type { Size, SizeProp } from "./types";
/**
* Clean Common Props
*
* Borrowed from the original `react-select` package
*
* @see {@link https://github.com/JedWatson/react-select/blob/2f94e8d/packages/react-select/src/utils.ts#L79-L110}
*/
export const cleanCommonProps = <
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>,
AdditionalProps,
>(
props: Partial<CommonPropsAndClassName<Option, IsMulti, Group>> &
AdditionalProps
): Omit<
AdditionalProps,
keyof CommonPropsAndClassName<Option, IsMulti, Group>
> => {
// className
const {
className, // not listed in commonProps documentation, needs to be removed to allow Emotion to generate classNames
clearValue,
cx,
getStyles,
getClassNames,
getValue,
hasValue,
isMulti,
isRtl,
options, // not listed in commonProps documentation
selectOption,
selectProps,
setValue,
theme, // not listed in commonProps documentation
...innerProps
} = props;
return { ...innerProps };
};
/** A typeguard to ensure the default size on the Input component is valid. */
const isSize = (size: unknown): size is Size => {
const isString = typeof size === "string";
return isString && ["sm", "md", "lg"].includes(size);
};
const getDefaultSize = (size: unknown): Size => {
if (isSize(size)) {
return size;
}
if (size === "xs") {
return "sm";
}
// This shouldn't be necessary but it might help the size get closer to the
// user's goal if they have `xl` as a custom size.
if (size === "xl") {
return "lg";
}
return "md";
};
export const useSize = (size: SizeProp | undefined): Size => {
const chakraTheme = useTheme();
const defaultSize = getDefaultSize(
chakraTheme.components.Input.defaultProps.size
);
// Ensure that the size used is one of the options, either `sm`, `md`, or `lg`
const definedSize: SizeProp = size ?? defaultSize;
// Or, if a breakpoint is passed, get the size based on the current screen size
const realSize: Size =
useBreakpointValue<Size>(
typeof definedSize === "string" ? [definedSize] : definedSize,
{
fallback: "md",
}
) || defaultSize;
return realSize;
};