Skip to content

Commit

Permalink
feat(usesxtokens): useSxToken -> useSxTokens (#19)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: useSxToken is changed to useSxTokens
  • Loading branch information
mym0404 committed Mar 16, 2024
2 parents 0a8d8d0 + 32b2530 commit a0b002d
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 54 deletions.
12 changes: 7 additions & 5 deletions doc/docs/advanced/get-token-value.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
sidebar_position: 1
---

# Get token value with useSxToken
# Get token value with useSxTokens

To get individual token values for a theme, you can use the `useSxToken` hook.
To get individual token values for a theme, you can use the `useSxTokens` hook.

This is useful when it is cumbersome to get the style by passing `SxProps` to the `useSx` hook or when individual token values are needed.

Expand All @@ -17,14 +17,16 @@ const MyView = (
disabled?: boolean;
readonly?: boolean;
}) => {
const backgroundColor = useSxToken('colors', readonly || disabled ? 'gray500' : 'gray200');
const [backgroundColor, error] = useSxTokens('colors', [readonly || disabled ? 'gray500' : 'gray200', 'red500']);
g
return <View style={{ backgroundColor }} />
return <View style={{ backgroundColor, borderColor: error, ... }} />
}
```

:::info
To operate properly, you must use it in the Context inside `StyledSystemProvider` or pass the theme object as an option.

Additionally, `undefined` is returned when attempting to reference a key that does not exist.
Otherwise, `undefined` is returned for every position in the returned array.

Additionally, `undefined` is returned at that index when attempting to reference a key that does not exist.
:::
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
sidebar_position: 1
---

# useSxToken를 이용해 토큰값 얻기
# useSxTokens를 이용해 토큰값 얻기

테마의 개별적인 토큰 값을 얻으려면 `useSxToken` 훅을 사용할 수 있습니다.
테마의 개별적인 토큰 값을 얻으려면 `useSxTokens` 훅을 사용할 수 있습니다.

이는 `SxProps``useSx` 훅에 전달해 style을 얻기 번거롭거나 개별적인 토큰 값이 필요할 때 유용합니다.

Expand All @@ -17,14 +17,16 @@ const MyView = (
disabled?: boolean;
readonly?: boolean;
}) => {
const backgroundColor = useSxToken('colors', readonly || disabled ? 'gray500' : 'gray200');

return <View style={{ backgroundColor }} />
const [backgroundColor, error] = useSxTokens('colors', [readonly || disabled ? 'gray500' : 'gray200', 'red500']);
g
return <View style={{ backgroundColor, borderColor: error, ... }} />
}
```

:::info
`StyledSystemProvider`내부의 Context에서 사용하거나 옵션으로 테마 객체를 전달해야 정상적으로 동작합니다.

또한, 존재하지 않는 키를 참조하려고 할 시에도 `undefined`가 반환됩니다.
그렇지 않다면 반환 배열의 모든 자리에 `undefined`가 반환됩니다.

또한, 존재하지 않는 키를 참조하려고 할 시에도 해당 인덱스의 자리에 `undefined`가 반환됩니다.
:::
35 changes: 0 additions & 35 deletions src/hook/useSxToken.ts

This file was deleted.

16 changes: 8 additions & 8 deletions src/hook/useSxToken.test.ts → src/hook/useSxTokens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react-hooks';
import type { ThemedDict } from '../@types/ThemedDict';
import type { ThemedTypings } from '../@types/ThemedTypings';

import { useSxToken } from './useSxToken';
import { useSxTokens } from './useSxTokens';

const theme: ThemedDict = {
colors: {
Expand All @@ -27,32 +27,32 @@ const theme: ThemedDict = {
export function expectResult<T extends keyof ThemedTypings, V extends ThemedTypings[T]>(
theme: ThemedDict,
tokenGroup: T,
tokenValue: Exclude<V, null | undefined>,
expectation: any,
tokenValues: Array<Exclude<V, null | undefined>>,
expectation: any[],
) {
const {
result: { current },
} = renderHook(() => useSxToken(tokenGroup, tokenValue, { theme }));
} = renderHook(() => useSxTokens(tokenGroup, tokenValues, { theme }));

return expect(current).toEqual(expectation);
}

describe('valid case', () => {
it('colors', () => {
expectResult(theme, 'colors', 'red', 'red');
expectResult(theme, 'colors', ['red'], ['red']);
});

it('radii', () => {
expectResult(theme, 'radii', 'sm' as any, 8);
expectResult(theme, 'radii', ['sm' as any], [8]);
});
});

describe('edge case', () => {
it('cannot find value if tokenValue is not in tokenType', () => {
expectResult(theme, 'radii', '' as any, undefined);
expectResult(theme, 'radii', ['' as any], [undefined]);
});

it('cannot find value if theme is undefined', () => {
expectResult(undefined as any, 'radii', '' as any, undefined);
expectResult(undefined as any, 'radii', ['' as any], [undefined]);
});
});
42 changes: 42 additions & 0 deletions src/hook/useSxTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useContext } from 'react';
import { generateArray } from '@mj-studio/js-util';

import type { ThemedDict } from '../@types/ThemedDict';
import type { ThemedTypings } from '../@types/ThemedTypings';
import { printWarning } from '../internal/util/printWarning';
import { StyledSystemContext } from '../provider/StyledSystemProvider';

export type UseSxTokensOptions = {
theme?: ThemedDict;
};
export const useSxTokens = <T extends keyof ThemedTypings, V extends ThemedTypings[T]>(
tokenType: T,
tokenValues: Array<Exclude<V, null | undefined>>,
{ theme: optionTheme }: UseSxTokensOptions = {},
): Array<ThemedDict[T][keyof ThemedDict[T]]> => {
const styledSystemContext = useContext(StyledSystemContext);

const theme = optionTheme ?? styledSystemContext?.theme;

if (!theme) {
printWarning('theme not found from useSxTokens, undefineds will be returned.');

return generateArray(tokenValues.length).map(() => undefined) as any;
}

const ret: Array<ThemedDict[T][keyof ThemedDict[T]]> = [];

for (let i = 0; i < tokenValues.length; i++) {
const tokenValue = tokenValues[i];
if (!(tokenValue in theme[tokenType])) {
printWarning(
`tokenValue ${String(tokenValue)} at index ${i} doesn't exist in tokenType ${tokenType} from useSxTokens, undefined will be returned.`,
);
ret.push(undefined as any);
} else {
ret.push(theme[tokenType][tokenValue]);
}
}

return ret;
};

0 comments on commit a0b002d

Please sign in to comment.