Skip to content

Commit

Permalink
Merge pull request #29 from mj-studio-library/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
mym0404 committed Mar 19, 2024
2 parents 18458e1 + dfb8d25 commit dd08b15
Show file tree
Hide file tree
Showing 16 changed files with 617 additions and 369 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
- alpha

jobs:
publish-packages:
Expand Down Expand Up @@ -45,4 +46,11 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
with:
branches: 'main'
branches: |
[
'main',
{
name: 'alpha',
prerelease: true
}
]
20 changes: 10 additions & 10 deletions doc/docs/usage/component.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ import { SxProps, useSx } from 'react-native-themed-styled-system';

type StyledViewProps = PropsWithChildren<ViewProps & SxProps>;
const StyledView = forwardRef((props: StyledViewProps, ref: Ref<View>) => {
const { viewStyle, filteredProps } = useSx(props);
return <View ref={ref} style={viewStyle()} {...filteredProps} />;
const { getStyle, filteredProps } = useSx(props);
return <View ref={ref} style={getStyle()} {...filteredProps} />;
});

export { StyledView };
Expand All @@ -52,15 +52,15 @@ export type { StyledViewProps };

`useSx` is responsible for receiving `SxProps` and converting it to `ViewStyle`.

You can call the `viewStyle` function returned by `useSx` and pass it to the `style` prop of the desired view.
You can call the `getStyle` function returned by `useSx` and pass it to the `style` prop of the desired view.

:::warning
The prop type of a component containing the `SxProps` type includes all the keys included in `SxProps`.

Therefore, if all props from the parent are passed through object destruction like in the existing `{...props}`, the keys do not overlap.
You need to be careful not to do so.

Also, when using `props` as is, it must always come before `style` so as not to overwrite the `style` of `viewStyle()`.
Also, when using `props` as is, it must always come before `style` so as not to overwrite the `style` of `getStyle()`.

To prevent this, you can use `filteredProps` in the return value of `useSx`.

Expand Down Expand Up @@ -102,11 +102,11 @@ const ScreenErrorFallback = (props: Props) => {
//highlight-next-line
const { title, body } = props;
//highlight-next-line
const { viewStyle } = useSx(props);
const { getStyle } = useSx(props);
return (
<View
//highlight-next-line
style={viewStyle({ center: true })}
style={getStyle({ center: true })}
pointerEvents={'box-none'}
>
```
Expand All @@ -117,7 +117,7 @@ There are a few things to keep in mind.
There is no need to add `style` as a prop to `style` of `View`.
2. Always pass all `props` objects themselves to `useSx` to avoid missing any properties. `useSx`
Properties that are not used internally are ignored and not changed.
3. `viewStyle` can receive `SxProps` as an argument and consider it in the result.
3. `getStyle` can receive `SxProps` as an argument and consider it in the result.
4. `center` is a shortcut for `justifyContent: center`, `alignItems: center`.

## Example without Props destruction
Expand All @@ -137,10 +137,10 @@ type StyledScrollViewProps = PropsWithChildren<
SxProps
>;
const StyledScrollView = forwardRef((props: StyledScrollViewProps, ref: Ref<ScrollView>) => {
const { viewStyle, filteredProps } = useSx(props);
const { viewStyle: contentContainerStyle } = useSx(props.contentContainerSx);
const { getStyle, filteredProps } = useSx(props);
const { getStyle: contentContainerStyle } = useSx(props.contentContainerSx);
return (
<ScrollView ref={ref} style={viewStyle()} contentContainerStyle={contentContainerStyle()} {...filteredProps} />
<ScrollView ref={ref} style={getStyle()} contentContainerStyle={contentContainerStyle()} {...filteredProps} />
);
});

Expand Down
10 changes: 5 additions & 5 deletions doc/docs/usage/style-parsing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const props = {
1. Props’ `style` prop
2. Styles of `SxProps`, such as `ml` and `w` of Props
3. Styles inside the `sx` prop of Props
4. First argument of `viewStyle(sx?: SxProps)`
4. First argument of `getStyle(sx?: SxProps)`

**The priority is calculated as 1 > 3 > 2 > 4.**

Expand All @@ -34,12 +34,12 @@ describe('style parse priority', () => {
expectResult(emptyTheme, { w: 1, sx: { w: 2 } }, { width: 2 });
});

it('prop property > viewStyle parameter', () => {
expectResult(emptyTheme, { w: 1, viewStyleSx: { w: 2 } }, { width: 1 });
it('prop property > getStyle parameter', () => {
expectResult(emptyTheme, { w: 1, getStyleSx: { w: 2 } }, { width: 1 });
});

it('style prop property > viewStyle parameter', () => {
expectResult(emptyTheme, { style: { width: 1 }, viewStyleSx: { w: 2 } }, { width: 1 });
it('style prop property > getStyle parameter', () => {
expectResult(emptyTheme, { style: { width: 1 }, getStyleSx: { w: 2 } }, { width: 1 });
});
});
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ import { SxProps, useSx } from 'react-native-themed-styled-system';

type StyledViewProps = PropsWithChildren<ViewProps & SxProps>;
const StyledView = forwardRef((props: StyledViewProps, ref: Ref<View>) => {
const { viewStyle, filteredProps } = useSx(props);
return <View ref={ref} style={viewStyle()} {...filteredProps} />;
const { getStyle, filteredProps } = useSx(props);
return <View ref={ref} style={getStyle()} {...filteredProps} />;
});

export { StyledView };
Expand All @@ -52,15 +52,15 @@ export type { StyledViewProps };

`useSx``SxProps`를 받아 이를 `ViewStyle`로 변환하는 역할을 합니다.

`useSx`가 반환하는 `viewStyle` 함수를 호출해 원하는 뷰의 `style` prop에 전달할 수 있습니다.
`useSx`가 반환하는 `getStyle` 함수를 호출해 원하는 뷰의 `style` prop에 전달할 수 있습니다.

:::warning
`SxProps` 타입을 포함한 컴포넌트의 prop type은 `SxProps`에 포함되는 키들이 모두 포함됩니다.

따라서 기존에 `{...props}` 처럼 object destruction을 통해 부모로부터의 prop이 모두 전달되는 경우 키가 겹치지
않는지 주의가 필요합니다.

또한 `props`를 그대로 쓸 시, `style`보다 항상 이전에 와서 `viewStyle()``style`을 덮어씌우지 않게 해야합니다.
또한 `props`를 그대로 쓸 시, `style`보다 항상 이전에 와서 `getStyle()``style`을 덮어씌우지 않게 해야합니다.

이것을 방지하려면 `useSx`의 반환값 중 `filteredProps`를 사용하면 됩니다.

Expand Down Expand Up @@ -102,11 +102,11 @@ const ScreenErrorFallback = (props: Props) => {
// highlight-next-line
const { title, body } = props;
// highlight-next-line
const { viewStyle } = useSx(props);
const { getStyle } = useSx(props);
return (
<View
// highlight-next-line
style={viewStyle({ center: true })}
style={getStyle({ center: true })}
pointerEvents={'box-none'}
>
```
Expand All @@ -117,7 +117,7 @@ const ScreenErrorFallback = (props: Props) => {
`View`의 `style`에 prop으로 들어온 `style`도 같이 넣어줄 필요가 없습니다.
2. 누락되는 속성이 없게 항상 모든 `props` 객체 자체를 `useSx`로 넘기도록 합니다. `useSx`는
내부적으로 쓰이지 않는 속성들은 무시하고 변경시키지 않습니다.
3. `viewStyle`은 `SxProps`를 인자로 받아 결과에 고려시킬 수 있습니다.
3. `getStyle`은 `SxProps`를 인자로 받아 결과에 고려시킬 수 있습니다.
4. `center`는 `justifyContent: center`, `alignItems: center` 의 단축 속성입니다.

## Props destruction을 사용하지 않는 예시
Expand All @@ -137,10 +137,10 @@ type StyledScrollViewProps = PropsWithChildren<
SxProps
>;
const StyledScrollView = forwardRef((props: StyledScrollViewProps, ref: Ref<ScrollView>) => {
const { viewStyle, filteredProps } = useSx(props);
const { viewStyle: contentContainerStyle } = useSx(props.contentContainerSx);
const { getStyle, filteredProps } = useSx(props);
const { getStyle: contentContainerStyle } = useSx(props.contentContainerSx);
return (
<ScrollView ref={ref} style={viewStyle()} contentContainerStyle={contentContainerStyle()} {...filteredProps} />
<ScrollView ref={ref} style={getStyle()} contentContainerStyle={contentContainerStyle()} {...filteredProps} />
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const props = {
1. Props의 `style` prop
2. Props의 `ml`, `w` 같은 `SxProps`의 스타일들
3. Props의 `sx` prop 내부의 스타일들
4. `viewStyle(sx?: SxProps)`의 첫 인자
4. `getStyle(sx?: SxProps)`의 첫 인자

**이에 따른 우선순위는 1 > 3 > 2 > 4 > 로 계산됩니다.**

Expand All @@ -34,12 +34,12 @@ describe('style parse priority', () => {
expectResult(emptyTheme, { w: 1, sx: { w: 2 } }, { width: 2 });
});

it('prop property > viewStyle parameter', () => {
expectResult(emptyTheme, { w: 1, viewStyleSx: { w: 2 } }, { width: 1 });
it('prop property > getStyle parameter', () => {
expectResult(emptyTheme, { w: 1, getStyleSx: { w: 2 } }, { width: 1 });
});

it('style prop property > viewStyle parameter', () => {
expectResult(emptyTheme, { style: { width: 1 }, viewStyleSx: { w: 2 } }, { width: 1 });
it('style prop property > getStyle parameter', () => {
expectResult(emptyTheme, { style: { width: 1 }, getStyleSx: { w: 2 } }, { width: 1 });
});
});
```
Expand Down
115 changes: 81 additions & 34 deletions src/@types/SxProps.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { ViewStyle } from 'react-native';
import type { TextStyle, ViewStyle } from 'react-native';

import type { Token } from './Token';

export type SxPropKeys = keyof SxProps;
export type SxPropsKeys = keyof SxProps;
export type TextSxPropsKey = keyof TextSxProps;
/**
* Always modify if you change API
*/
export const _allPropList = [
export const _viewStylePropList = [
'style',
'sx',
'backgroundColor',
'bg',
'borderColor',
Expand Down Expand Up @@ -58,7 +60,6 @@ export const _allPropList = [
'minHeight',
'maxH',
'maxHeight',
'sx',
'flex',
'alignItems',
'alignContent',
Expand Down Expand Up @@ -89,13 +90,37 @@ export const _allPropList = [
'borderTopRightRadius',
'borderBottomLeftRadius',
'borderBottomRightRadius',
] satisfies (SxPropKeys | 'style')[];

] satisfies (SxPropsKeys | 'style')[];
export const _textStylePropList = [
'color',
'textDecorationColor',
'textShadowColor',
'fontFamily',
'fontSize',
'fontStyle',
'fontWeight',
'weight',
'letterSpacing',
'lineHeight',
'textAlign',
'align',
'textDecorationLine',
'textDecorationStyle',
'textShadowOffset',
'textShadowRadius',
'textTransform',
'userSelect',
] satisfies (Omit<TextSxPropsKey, keyof TextSxPropsKey> | 'style')[];
type ThemedColorTokenProps = {
backgroundColor: Token<'colors'>;
bg: Token<'colors'>; // backgroundColor
borderColor: Token<'colors'>;
};
type ThemedColorTokenTextProps = {
color: Token<'colors'>;
textDecorationColor: Token<'colors'>;
textShadowColor: Token<'colors'>;
};

type ThemedSpaceTokenProps = {
margin: Token<'space'>;
Expand Down Expand Up @@ -163,38 +188,60 @@ type ThemedRadiiTokenProps = {
bottomRightRadius: Token<'radii'>; // borderBottomRightRadius
};

type ThemedViewStyleProps = {
flex: ViewStyle['flex'];
alignItems: ViewStyle['alignItems'];
alignContent: ViewStyle['alignContent'];
justifyContent: ViewStyle['justifyContent'];
flexWrap: ViewStyle['flexWrap'];
flexDirection: ViewStyle['flexDirection'];
flexGrow: ViewStyle['flexGrow'];
flexShrink: ViewStyle['flexShrink'];
flexBasis: ViewStyle['flexBasis'];
alignSelf: ViewStyle['alignSelf'];
position: ViewStyle['position'];
pos: ViewStyle['position']; // position
borderWidth: ViewStyle['borderWidth'];
borderTopWidth: ViewStyle['borderTopWidth'];
borderRightWidth: ViewStyle['borderRightWidth'];
borderBottomWidth: ViewStyle['borderBottomWidth'];
borderLeftWidth: ViewStyle['borderLeftWidth'];
opacity: ViewStyle['opacity'];
overflow: ViewStyle['overflow'];
transform: ViewStyle['transform'];
aspectRatio: ViewStyle['aspectRatio'];
display: ViewStyle['display'];
elevation: ViewStyle['elevation'];
zIndex: ViewStyle['zIndex'];
absoluteFill?: boolean; // shortcut - position: absoulte, t,r,b,l: 0
center?: boolean; // shortcut - justifyContent, alignItems: center
};

type ThemedTextStyleProps = {
fontFamily: TextStyle['fontFamily'];
fontSize: TextStyle['fontSize'];
fontStyle: TextStyle['fontStyle'];
fontWeight: TextStyle['fontWeight'];
weight: TextStyle['fontWeight']; // fontWeight
letterSpacing: TextStyle['letterSpacing'];
lineHeight: TextStyle['lineHeight'];
textAlign: TextStyle['textAlign'];
align: TextStyle['textAlign']; // textAlign
textDecorationLine: TextStyle['textDecorationLine'];
textDecorationStyle: TextStyle['textDecorationStyle'];
textShadowOffset: TextStyle['textShadowOffset'];
textShadowRadius: TextStyle['textShadowRadius'];
textTransform: TextStyle['textTransform'];
userSelect: TextStyle['userSelect'];
};

type BaseSxProps = Partial<
{
flex: ViewStyle['flex'];
alignItems: ViewStyle['alignItems'];
alignContent: ViewStyle['alignContent'];
justifyContent: ViewStyle['justifyContent'];
flexWrap: ViewStyle['flexWrap'];
flexDirection: ViewStyle['flexDirection'];
flexGrow: ViewStyle['flexGrow'];
flexShrink: ViewStyle['flexShrink'];
flexBasis: ViewStyle['flexBasis'];
alignSelf: ViewStyle['alignSelf'];
position: ViewStyle['position'];
pos: ViewStyle['position']; // position
borderWidth: ViewStyle['borderWidth'];
borderTopWidth: ViewStyle['borderTopWidth'];
borderRightWidth: ViewStyle['borderRightWidth'];
borderBottomWidth: ViewStyle['borderBottomWidth'];
borderLeftWidth: ViewStyle['borderLeftWidth'];
opacity: ViewStyle['opacity'];
overflow: ViewStyle['overflow'];
transform: ViewStyle['transform'];
aspectRatio: ViewStyle['aspectRatio'];
display: ViewStyle['display'];
elevation: ViewStyle['elevation'];
zIndex: ViewStyle['zIndex'];
absoluteFill?: boolean; // shortcut - position: absoulte, t,r,b,l: 0
center?: boolean; // shortcut - justifyContent, alignItems: center
} & ThemedSpaceTokenProps &
ThemedViewStyleProps &
ThemedSpaceTokenProps &
ThemedSizeTokenProps &
ThemedColorTokenProps &
ThemedRadiiTokenProps
>;

export type SxProps = BaseSxProps & { sx?: BaseSxProps };
export type TextSxProps = SxProps & Partial<ThemedColorTokenTextProps & ThemedTextStyleProps>;
Loading

0 comments on commit dd08b15

Please sign in to comment.