@basiln/utils 0.1.0 → 0.1.2
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/CHANGELOG.md +125 -5
- package/dist/Choose.js +50 -0
- package/dist/Choose.js.map +1 -0
- package/dist/Choose.mjs +7 -0
- package/dist/Choose.mjs.map +1 -0
- package/dist/Flex.js +70 -0
- package/dist/Flex.js.map +1 -0
- package/dist/Flex.mjs +10 -0
- package/dist/Flex.mjs.map +1 -0
- package/dist/If.js +35 -0
- package/dist/If.js.map +1 -0
- package/dist/If.mjs +7 -0
- package/dist/If.mjs.map +1 -0
- package/dist/SafeArea.js +91 -0
- package/dist/SafeArea.js.map +1 -0
- package/dist/SafeArea.mjs +10 -0
- package/dist/SafeArea.mjs.map +1 -0
- package/dist/Spacing.js +49 -0
- package/dist/Spacing.js.map +1 -0
- package/dist/Spacing.mjs +8 -0
- package/dist/Spacing.mjs.map +1 -0
- package/dist/Validate.js +43 -0
- package/dist/Validate.js.map +1 -0
- package/dist/Validate.mjs +7 -0
- package/dist/Validate.mjs.map +1 -0
- package/dist/chunk-7WNTKDNW.mjs +26 -0
- package/dist/chunk-7WNTKDNW.mjs.map +1 -0
- package/dist/chunk-C7VOPXT2.mjs +23 -0
- package/dist/chunk-C7VOPXT2.mjs.map +1 -0
- package/dist/chunk-FUGA35PJ.mjs +22 -0
- package/dist/chunk-FUGA35PJ.mjs.map +1 -0
- package/dist/chunk-GQPOYY4X.mjs +77 -0
- package/dist/chunk-GQPOYY4X.mjs.map +1 -0
- package/dist/chunk-LKUAG7PE.mjs +22 -0
- package/dist/chunk-LKUAG7PE.mjs.map +1 -0
- package/dist/chunk-OIJ4AVT7.mjs +37 -0
- package/dist/chunk-OIJ4AVT7.mjs.map +1 -0
- package/dist/chunk-Q3B6WSD7.mjs +42 -0
- package/dist/chunk-Q3B6WSD7.mjs.map +1 -0
- package/dist/chunk-QD5QDTUG.mjs +14 -0
- package/dist/chunk-QD5QDTUG.mjs.map +1 -0
- package/dist/chunk-R23KSR7N.mjs +19 -0
- package/dist/chunk-R23KSR7N.mjs.map +1 -0
- package/dist/chunk-SJJHTYZC.mjs +30 -0
- package/dist/chunk-SJJHTYZC.mjs.map +1 -0
- package/dist/chunk-T7K7QYTL.mjs +9 -0
- package/dist/chunk-T7K7QYTL.mjs.map +1 -0
- package/dist/chunk-U4T3KW7L.mjs +67 -0
- package/dist/chunk-U4T3KW7L.mjs.map +1 -0
- package/dist/chunk-UFRXNT2I.mjs +11 -0
- package/dist/chunk-UFRXNT2I.mjs.map +1 -0
- package/dist/chunk-WHYNBO2G.mjs +12 -0
- package/dist/chunk-WHYNBO2G.mjs.map +1 -0
- package/dist/chunk-WOYL5AA5.mjs +39 -0
- package/dist/chunk-WOYL5AA5.mjs.map +1 -0
- package/dist/chunk-XBGZ3YNL.mjs +20 -0
- package/dist/chunk-XBGZ3YNL.mjs.map +1 -0
- package/dist/chunk-Z4QPISK7.mjs +36 -0
- package/dist/chunk-Z4QPISK7.mjs.map +1 -0
- package/dist/coerceCssPixelValue.js +33 -0
- package/dist/coerceCssPixelValue.js.map +1 -0
- package/dist/coerceCssPixelValue.mjs +7 -0
- package/dist/coerceCssPixelValue.mjs.map +1 -0
- package/dist/composeEventHandlers.js +38 -0
- package/dist/composeEventHandlers.js.map +1 -0
- package/dist/composeEventHandlers.mjs +7 -0
- package/dist/composeEventHandlers.mjs.map +1 -0
- package/dist/constants/josa.js +105 -0
- package/dist/constants/josa.js.map +1 -0
- package/dist/constants/josa.mjs +15 -0
- package/dist/constants/josa.mjs.map +1 -0
- package/dist/createContext.js +56 -0
- package/dist/createContext.js.map +1 -0
- package/dist/createContext.mjs +7 -0
- package/dist/createContext.mjs.map +1 -0
- package/dist/ellipsis.js +45 -0
- package/dist/ellipsis.js.map +1 -0
- package/dist/ellipsis.mjs +9 -0
- package/dist/ellipsis.mjs.map +1 -0
- package/dist/getVar.js +36 -0
- package/dist/getVar.js.map +1 -0
- package/dist/getVar.mjs +7 -0
- package/dist/getVar.mjs.map +1 -0
- package/dist/hasBatchim.js +111 -0
- package/dist/hasBatchim.js.map +1 -0
- package/dist/hasBatchim.mjs +8 -0
- package/dist/hasBatchim.mjs.map +1 -0
- package/dist/hexToRgba.js +61 -0
- package/dist/hexToRgba.js.map +1 -0
- package/dist/hexToRgba.mjs +7 -0
- package/dist/hexToRgba.mjs.map +1 -0
- package/dist/index.d.ts +174 -0
- package/dist/index.js +456 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +64 -0
- package/dist/index.mjs.map +1 -0
- package/dist/josa.js +133 -0
- package/dist/josa.js.map +1 -0
- package/dist/josa.mjs +9 -0
- package/dist/josa.mjs.map +1 -0
- package/dist/queryString.js +91 -0
- package/dist/queryString.js.map +1 -0
- package/dist/queryString.mjs +7 -0
- package/dist/queryString.mjs.map +1 -0
- package/dist/useSafeArea.js +49 -0
- package/dist/useSafeArea.js.map +1 -0
- package/dist/useSafeArea.mjs +8 -0
- package/dist/useSafeArea.mjs.map +1 -0
- package/package.json +6 -4
- package/src/Choose.tsx +18 -10
- package/src/Flex.tsx +51 -0
- package/src/If.tsx +6 -2
- package/src/SafeArea.tsx +46 -0
- package/src/Spacing.tsx +30 -0
- package/src/Validate.ts +25 -0
- package/src/coerceCssPixelValue.ts +5 -0
- package/src/composeEventHandlers.ts +1 -1
- package/src/constants/josa.ts +72 -0
- package/src/createContext.tsx +5 -5
- package/src/ellipsis.ts +19 -0
- package/src/getVar.ts +1 -1
- package/src/hasBatchim.ts +31 -0
- package/src/hexToRgba.ts +45 -0
- package/src/index.ts +34 -3
- package/src/josa.ts +50 -0
- package/src/queryString.ts +134 -0
- package/src/useSafeArea.ts +24 -0
- package/tsup.config.ts +5 -5
- package/LICENSE +0 -21
- package/src/types/Choose.ts +0 -14
- package/src/types/If.ts +0 -6
- package/src/types/getVar.ts +0 -1
- package/src/types/index.ts +0 -9
@@ -3,7 +3,7 @@
|
|
3
3
|
export function composeEventHandlers<E>(
|
4
4
|
originalEventHandler?: (event: E) => void,
|
5
5
|
ourEventHandler?: (event: E) => void,
|
6
|
-
{ checkForDefaultPrevented = true } = {}
|
6
|
+
{ checkForDefaultPrevented = true } = {}
|
7
7
|
) {
|
8
8
|
return function handleEvent(event: E) {
|
9
9
|
originalEventHandler?.(event);
|
@@ -0,0 +1,72 @@
|
|
1
|
+
export const COMPLETE_HANGUL_START_CHARCODE = '가'.charCodeAt(0);
|
2
|
+
export const COMPLETE_HANGUL_END_CHARCODE = '힣'.charCodeAt(0);
|
3
|
+
|
4
|
+
export const NUMBER_OF_JONGSEONG = 28;
|
5
|
+
export const NUMBER_OF_JUNGSEONG = 21;
|
6
|
+
|
7
|
+
const DISASSEMBLED_CONSONANTS_BY_CONSONANT = {
|
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
|
+
} as const;
|
40
|
+
|
41
|
+
export const JONGSEONGS = (
|
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
|
+
] as const
|
72
|
+
).map((consonant) => DISASSEMBLED_CONSONANTS_BY_CONSONANT[consonant]);
|
package/src/createContext.tsx
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import {
|
2
2
|
useMemo,
|
3
3
|
createContext as createContextRaw,
|
4
4
|
useContext as useContextRaw,
|
@@ -7,10 +7,10 @@ import React, {
|
|
7
7
|
|
8
8
|
export function createContext<ContextValueType extends object | null>(
|
9
9
|
rootComponentName: string,
|
10
|
-
defaultContext?: ContextValueType
|
10
|
+
defaultContext?: ContextValueType
|
11
11
|
) {
|
12
12
|
const Context = createContextRaw<ContextValueType | undefined>(
|
13
|
-
defaultContext
|
13
|
+
defaultContext
|
14
14
|
);
|
15
15
|
|
16
16
|
function Provider(props: PropsWithChildren<ContextValueType>) {
|
@@ -18,7 +18,7 @@ export function createContext<ContextValueType extends object | null>(
|
|
18
18
|
|
19
19
|
const value = useMemo(
|
20
20
|
() => contextValues,
|
21
|
-
[contextValues]
|
21
|
+
[contextValues]
|
22
22
|
) as ContextValueType;
|
23
23
|
|
24
24
|
return <Context.Provider value={value}>{children}</Context.Provider>;
|
@@ -28,7 +28,7 @@ export function createContext<ContextValueType extends object | null>(
|
|
28
28
|
const context = useContextRaw(Context);
|
29
29
|
if (context == null) {
|
30
30
|
throw new Error(
|
31
|
-
`${consumerName}은 ${rootComponentName}하위에서 사용해야
|
31
|
+
`${consumerName}은 ${rootComponentName}하위에서 사용해야 합니다.`
|
32
32
|
);
|
33
33
|
}
|
34
34
|
|
package/src/ellipsis.ts
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
import { css } from 'styled-components';
|
2
|
+
|
3
|
+
export type MultiLineEllipsisProps = {
|
4
|
+
line: number;
|
5
|
+
};
|
6
|
+
|
7
|
+
export const ellipsis = css`
|
8
|
+
overflow: hidden;
|
9
|
+
white-space: nowrap;
|
10
|
+
text-overflow: ellipsis;
|
11
|
+
`;
|
12
|
+
|
13
|
+
export const multiLineEllipsis = ({ line }: MultiLineEllipsisProps) => css`
|
14
|
+
display: -webkit-box;
|
15
|
+
overflow: hidden;
|
16
|
+
text-overflow: ellipsis;
|
17
|
+
-webkit-line-clamp: ${line};
|
18
|
+
-webkit-box-orient: vertical;
|
19
|
+
`;
|
package/src/getVar.ts
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
import {
|
2
|
+
COMPLETE_HANGUL_END_CHARCODE,
|
3
|
+
COMPLETE_HANGUL_START_CHARCODE,
|
4
|
+
NUMBER_OF_JONGSEONG,
|
5
|
+
} from './constants/josa';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* 한글 음절의 받침 유무를 확인합니다.
|
9
|
+
* @param str - 검사할 문자열
|
10
|
+
* @returns 받침이 있으면 true, 없으면 false
|
11
|
+
*/
|
12
|
+
export function hasBatchim(str: string): boolean {
|
13
|
+
const lastChar = str[str.length - 1];
|
14
|
+
if (!lastChar) return false;
|
15
|
+
|
16
|
+
const charCode = lastChar.charCodeAt(0);
|
17
|
+
|
18
|
+
// 한글 완성형 문자인지 확인
|
19
|
+
if (
|
20
|
+
charCode < COMPLETE_HANGUL_START_CHARCODE ||
|
21
|
+
charCode > COMPLETE_HANGUL_END_CHARCODE
|
22
|
+
) {
|
23
|
+
return false;
|
24
|
+
}
|
25
|
+
|
26
|
+
// 받침 코드 계산
|
27
|
+
const batchimCode =
|
28
|
+
(charCode - COMPLETE_HANGUL_START_CHARCODE) % NUMBER_OF_JONGSEONG;
|
29
|
+
|
30
|
+
return batchimCode > 0; // 받침이 있으면 true
|
31
|
+
}
|
package/src/hexToRgba.ts
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
export type HexToRgbaProps = { hex: string; alpha?: number };
|
2
|
+
|
3
|
+
function parseHexToDecimal(hex: string): number {
|
4
|
+
return parseInt(hex, 16);
|
5
|
+
}
|
6
|
+
|
7
|
+
function validateHex(hex: string): string {
|
8
|
+
const match = /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.exec(hex);
|
9
|
+
if (!match) {
|
10
|
+
throw new Error(
|
11
|
+
`Invalid hex value: "${hex}". Expected formats: "#RGB", "RGB", "#RRGGBB", or "RRGGBB".`
|
12
|
+
);
|
13
|
+
}
|
14
|
+
return match[1];
|
15
|
+
}
|
16
|
+
|
17
|
+
function expandHex(hex: string): string {
|
18
|
+
return hex.length === 3
|
19
|
+
? hex
|
20
|
+
.split('')
|
21
|
+
.map((char) => char + char)
|
22
|
+
.join('')
|
23
|
+
: hex;
|
24
|
+
}
|
25
|
+
|
26
|
+
function isValidAlpha(alpha: number): boolean {
|
27
|
+
return alpha >= 0 && alpha <= 1;
|
28
|
+
}
|
29
|
+
|
30
|
+
export function hexToRgba({ hex, alpha = 1 }: HexToRgbaProps): string {
|
31
|
+
if (!isValidAlpha(alpha)) {
|
32
|
+
throw new Error(
|
33
|
+
`Invalid alpha value. Must be between 0 and 1, received: ${alpha}`
|
34
|
+
);
|
35
|
+
}
|
36
|
+
|
37
|
+
const validatedHex = validateHex(hex);
|
38
|
+
const expandedHex = expandHex(validatedHex);
|
39
|
+
|
40
|
+
const r = parseHexToDecimal(expandedHex.slice(0, 2));
|
41
|
+
const g = parseHexToDecimal(expandedHex.slice(2, 4));
|
42
|
+
const b = parseHexToDecimal(expandedHex.slice(4, 6));
|
43
|
+
|
44
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
45
|
+
}
|
package/src/index.ts
CHANGED
@@ -1,5 +1,36 @@
|
|
1
|
-
export {
|
1
|
+
export {
|
2
|
+
Choose,
|
3
|
+
type ChooseWhenProps,
|
4
|
+
type ChooseProps,
|
5
|
+
type ChooseOtherwiseProps,
|
6
|
+
} from './Choose';
|
7
|
+
|
2
8
|
export { composeEventHandlers } from './composeEventHandlers';
|
9
|
+
|
3
10
|
export { createContext } from './createContext';
|
4
|
-
|
5
|
-
export {
|
11
|
+
|
12
|
+
export { getVar, type VariableType } from './getVar';
|
13
|
+
|
14
|
+
export { If, type IfProps } from './If';
|
15
|
+
|
16
|
+
export { Flex, type FlexProps } from './Flex';
|
17
|
+
|
18
|
+
export {
|
19
|
+
ellipsis,
|
20
|
+
multiLineEllipsis,
|
21
|
+
type MultiLineEllipsisProps,
|
22
|
+
} from './ellipsis';
|
23
|
+
|
24
|
+
export { hexToRgba, type HexToRgbaProps } from './hexToRgba';
|
25
|
+
|
26
|
+
export { josa, type JosaProps } from './josa';
|
27
|
+
|
28
|
+
export { Validate } from './Validate';
|
29
|
+
|
30
|
+
export { Spacing, type SpacingProps } from './Spacing';
|
31
|
+
|
32
|
+
export { useSafeArea, type SafeAreaCssValueProps } from './useSafeArea';
|
33
|
+
|
34
|
+
export { SafeArea, type SafeAreaProps } from './SafeArea';
|
35
|
+
|
36
|
+
export { queryString } from './queryString';
|
package/src/josa.ts
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
import { hasBatchim } from './hasBatchim';
|
2
|
+
|
3
|
+
type JosaOption = '이/가' | '을/를' | '은/는';
|
4
|
+
|
5
|
+
type ExtractJosaOption<T> = T extends `${infer A}/${infer B}` ? A | B : never;
|
6
|
+
|
7
|
+
export type JosaProps<U extends JosaOption> = {
|
8
|
+
word: string;
|
9
|
+
josa: U;
|
10
|
+
};
|
11
|
+
|
12
|
+
/**
|
13
|
+
* 주어진 단어와 조사 옵션을 기반으로 올바른 조사를 반환합니다.
|
14
|
+
* @returns 단어와 올바른 조사가 결합된 문자열
|
15
|
+
*/
|
16
|
+
export function josa<U extends JosaOption>(
|
17
|
+
props: JosaProps<U>
|
18
|
+
): `${JosaProps<U>['word']}${ExtractJosaOption<U>}` {
|
19
|
+
const { word, josa } = props;
|
20
|
+
|
21
|
+
if (!word) {
|
22
|
+
return word as `${JosaProps<U>['word']}${ExtractJosaOption<U>}`;
|
23
|
+
}
|
24
|
+
|
25
|
+
return `${word}${josaPicker({
|
26
|
+
word,
|
27
|
+
josa,
|
28
|
+
})}` as `${JosaProps<U>['word']}${ExtractJosaOption<U>}`;
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* 주어진 단어와 조사 옵션을 기반으로 올바른 조사를 선택합니다.
|
33
|
+
* @returns 올바른 조사
|
34
|
+
*/
|
35
|
+
function josaPicker<U extends JosaOption>(
|
36
|
+
props: JosaProps<U>
|
37
|
+
): ExtractJosaOption<U> {
|
38
|
+
const { word, josa } = props;
|
39
|
+
|
40
|
+
if (!word) {
|
41
|
+
return josa.split('/')[0] as ExtractJosaOption<U>;
|
42
|
+
}
|
43
|
+
|
44
|
+
const has받침 = hasBatchim(word);
|
45
|
+
const index = has받침 ? 0 : 1;
|
46
|
+
|
47
|
+
return josa.split('/')[index] as ExtractJosaOption<U>;
|
48
|
+
}
|
49
|
+
|
50
|
+
josa.pick = josaPicker;
|
@@ -0,0 +1,134 @@
|
|
1
|
+
/**
|
2
|
+
* @description 쿼리 스트링을 생성합니다.
|
3
|
+
* @example createSearchParamString({ a: 1, b: 2, c: 3 }) // 'a=1&b=2&c=3'
|
4
|
+
*/
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
6
|
+
function createSearchParamString(params: Record<string, any>) {
|
7
|
+
return (
|
8
|
+
new URLSearchParams(
|
9
|
+
Object.entries(params)
|
10
|
+
.filter(([, value]) => value != null)
|
11
|
+
.map(([key, value]) => {
|
12
|
+
if (Array.isArray(value)) {
|
13
|
+
return value.map((x) => [key, x]);
|
14
|
+
}
|
15
|
+
return [[key, value]];
|
16
|
+
})
|
17
|
+
.flat()
|
18
|
+
)
|
19
|
+
.toString()
|
20
|
+
// Convert space characters to '%20' according to RFC3986 spec, from RFC1738.
|
21
|
+
.replace(/\+/g, '%20')
|
22
|
+
);
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* @description 물음표를 포함한 쿼리 스트링을 생성합니다.
|
27
|
+
* @example createQueryString({ a: 1, b: 2, c: 3 }) // '?a=1&b=2&c=3'
|
28
|
+
*/
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
30
|
+
function createQueryString(params: Record<string, any>) {
|
31
|
+
const queryString = createSearchParamString(params);
|
32
|
+
|
33
|
+
if (queryString === '') {
|
34
|
+
return '';
|
35
|
+
}
|
36
|
+
|
37
|
+
return `?${queryString}`;
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @description 이터러블에서 키와 값을 가진 객체로 변환합니다.
|
42
|
+
* @example fromEntries([['a', 1], ['b', 2], ['c', 3]]) // { a: 1, b: 2, c: 3 }
|
43
|
+
*/
|
44
|
+
function fromEntries<T extends readonly [string | number, unknown]>(
|
45
|
+
iterable: Iterable<T>
|
46
|
+
) {
|
47
|
+
const result: Record<string | number | symbol, T[1]> = {};
|
48
|
+
|
49
|
+
for (const [key, value] of Array.from(iterable)) {
|
50
|
+
if (result[key]) {
|
51
|
+
if (Array.isArray(result[key])) {
|
52
|
+
(result[key] as Array<string | number>).push(value as string | number);
|
53
|
+
} else {
|
54
|
+
result[key] = [result[key], value];
|
55
|
+
}
|
56
|
+
} else {
|
57
|
+
result[key] = value;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
return result;
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* @description 쿼리 스트링을 객체로 변환합니다.
|
66
|
+
* @example parseQueryString('?a=1&b=2&c=3') // { a: '1', b: '2', c: '3' }
|
67
|
+
*/
|
68
|
+
function parseQueryString<Result = Record<string, string>>(
|
69
|
+
queryString: string = typeof location !== 'undefined' ? location.search : ''
|
70
|
+
): Result {
|
71
|
+
const query = queryString.trim().replace(/^[?#&]/, '');
|
72
|
+
|
73
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
74
|
+
return fromEntries(new URLSearchParams(query)) as any;
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* @description 쿼리 스트링에서 특정 키의 값을 가져옵니다.
|
79
|
+
*
|
80
|
+
* @param name 가져올 쿼리 스트링의 키
|
81
|
+
* @param parser 가져온 값을 파싱할 함수
|
82
|
+
* @returns 파싱된 값
|
83
|
+
*
|
84
|
+
* @example
|
85
|
+
* url: 'http://example.com/?a=1'
|
86
|
+
* getQueryString('a') // '1'
|
87
|
+
* getQueryString('a', parseInt) // 1
|
88
|
+
* getQueryString('b') // undefined
|
89
|
+
* getQueryString('b', parseInt) // undefined
|
90
|
+
*/
|
91
|
+
function getQueryString(name: string): string | undefined;
|
92
|
+
function getQueryString<T>(
|
93
|
+
name: string,
|
94
|
+
parser: (val: string) => T
|
95
|
+
): T | undefined;
|
96
|
+
function getQueryString<T = string>(name: string, parser?: (val: string) => T) {
|
97
|
+
const value = queryString.parse<{ [name: string]: string | undefined }>()[
|
98
|
+
name
|
99
|
+
];
|
100
|
+
|
101
|
+
if (parser == null || value == null) {
|
102
|
+
return value;
|
103
|
+
} else {
|
104
|
+
return parser(value);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* @description 기존 쿼리 스트링에 새로운 쿼리 스트링을 추가합니다.
|
110
|
+
* @example setQueryString({ qs: '?a=1', key: 'b', value: '2' }) // '?a=1&b=2'
|
111
|
+
*/
|
112
|
+
function setQueryString({
|
113
|
+
qs,
|
114
|
+
key,
|
115
|
+
value,
|
116
|
+
}: {
|
117
|
+
qs: string;
|
118
|
+
key: string;
|
119
|
+
value: string;
|
120
|
+
}) {
|
121
|
+
const parsed = parseQueryString(qs);
|
122
|
+
|
123
|
+
return createQueryString({
|
124
|
+
...parsed,
|
125
|
+
[key]: value,
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
export const queryString = {
|
130
|
+
create: createQueryString,
|
131
|
+
parse: parseQueryString,
|
132
|
+
get: getQueryString,
|
133
|
+
set: setQueryString,
|
134
|
+
};
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { coerceCssPixelValue, type CSSPixelValue } from './coerceCssPixelValue';
|
2
|
+
|
3
|
+
export type SafeAreaCssValueProps = {
|
4
|
+
top?: CSSPixelValue;
|
5
|
+
bottom?: CSSPixelValue;
|
6
|
+
left?: CSSPixelValue;
|
7
|
+
right?: CSSPixelValue;
|
8
|
+
};
|
9
|
+
|
10
|
+
const useSafeArea = ({
|
11
|
+
top: T = 0,
|
12
|
+
bottom: B = 0,
|
13
|
+
left: L = 0,
|
14
|
+
right: R = 0,
|
15
|
+
}: SafeAreaCssValueProps = {}) => {
|
16
|
+
const top = `max(${coerceCssPixelValue(T)}, env(safe-area-inset-top))`;
|
17
|
+
const bottom = `max(${coerceCssPixelValue(B)}, env(safe-area-inset-bottom))`;
|
18
|
+
const left = `max(${coerceCssPixelValue(L)}, env(safe-area-inset-left))`;
|
19
|
+
const right = `max(${coerceCssPixelValue(R)}, env(safe-area-inset-right))`;
|
20
|
+
|
21
|
+
return { top, bottom, left, right };
|
22
|
+
};
|
23
|
+
|
24
|
+
export { useSafeArea };
|
package/tsup.config.ts
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
import { defineConfig } from
|
2
|
-
import pkgJson from
|
1
|
+
import { defineConfig } from 'tsup';
|
2
|
+
import pkgJson from './package.json';
|
3
3
|
|
4
4
|
const external = [...Object.keys((pkgJson as any).peerDependencies || {})];
|
5
5
|
|
6
6
|
export default defineConfig({
|
7
|
-
entry: [
|
8
|
-
format: [
|
7
|
+
entry: ['src/**/*.{ts,tsx}'],
|
8
|
+
format: ['esm', 'cjs'],
|
9
9
|
sourcemap: true,
|
10
10
|
clean: true,
|
11
|
-
dts:
|
11
|
+
dts: 'src/index.ts',
|
12
12
|
external,
|
13
13
|
});
|
package/LICENSE
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
MIT License
|
2
|
-
|
3
|
-
Copyright (c) 2024 SeedN
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|
package/src/types/Choose.ts
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
import { ReactNode } from 'react';
|
2
|
-
|
3
|
-
export type ChooseWhenProps = {
|
4
|
-
condition: boolean;
|
5
|
-
children: ReactNode;
|
6
|
-
};
|
7
|
-
|
8
|
-
export type ChooseProps = {
|
9
|
-
children: ReactNode;
|
10
|
-
};
|
11
|
-
|
12
|
-
export type ChooseOtherwiseProps = {
|
13
|
-
children: ReactNode;
|
14
|
-
};
|
package/src/types/If.ts
DELETED
package/src/types/getVar.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export type VariableType = `--${string}`;
|