Skip to content

Commit

Permalink
feat: @emotion/css 를 적용한다
Browse files Browse the repository at this point in the history
  • Loading branch information
loki-class101 committed Jan 6, 2025
1 parent a12f175 commit 2c34420
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 140 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"@docusaurus/preset-classic": "2.1.0",
"@docusaurus/remark-plugin-npm2yarn": "2.1.0",
"@docusaurus/theme-live-codeblock": "2.1.0",
"@emotion/css": "11.13.5",
"@emotion/native": "11.9.3",
"@emotion/react": "11.10.4",
"@emotion/styled": "11.10.4",
Expand Down
80 changes: 42 additions & 38 deletions packages/vibrant-core/src/lib/Box/Box.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,58 @@
import type { ComponentType, FC, ReactElement } from 'react';
import { createElement, forwardRef, memo } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/css';
import { useComposedRef, useLayoutEvent } from '@vibrant-ui/utils';
import { OnColorContainer } from '../OnColorContainer';
import type { BoxElements, BoxProps } from './BoxProps';
import { interpolation, shouldForwardProp } from './BoxProps';

export const Box = memo(
styled(
forwardRef<HTMLDivElement, BoxProps>(
(
{
as,
base,
onLayout,
ariaLabel,
ariaChecked,
ariaLabelledBy,
ariaCurrent,
ariaSelected,
backgroundColor,
...restProps
},
ref
) => {
const { ref: layoutEventRef } = useLayoutEvent(onLayout);
const composeRef = useComposedRef(ref, layoutEventRef);
forwardRef<HTMLDivElement, BoxProps>(
(
{
as,
base,
onLayout,
ariaLabel,
ariaChecked,
ariaLabelledBy,
ariaCurrent,
ariaSelected,
backgroundColor,
...restProps
},
ref
) => {
const { ref: layoutEventRef } = useLayoutEvent(onLayout);
const composeRef = useComposedRef(ref, layoutEventRef);

const element = createElement(base ?? as ?? 'div', {
ref: composeRef,
...(base && as ? { as } : {}),
'aria-label': ariaLabel,
'aria-checked': ariaChecked,
'aria-labelledby': ariaLabelledBy,
'aria-current': ariaCurrent,
'aria-selected': ariaSelected,
...restProps,
});
const className = Object.entries(interpolation({ ...restProps, backgroundColor } ?? {}))
.map(([key, value]) => css({ [key]: value }))
.join(' ');

if (backgroundColor) {
return <OnColorContainer backgroundColor={backgroundColor}>{element}</OnColorContainer>;
}
const domAttributeProps = Object.fromEntries(
Object.entries({ ...restProps }).filter(([key, _]) => shouldForwardProp(key))
);

return element;
const element = createElement(base ?? as ?? 'div', {
ref: composeRef,
...(base && as ? { as } : {}),
'aria-label': ariaLabel,
'aria-checked': ariaChecked,
'aria-labelledby': ariaLabelledBy,
'aria-current': ariaCurrent,
'aria-selected': ariaSelected,
...domAttributeProps,
className,
});

if (backgroundColor) {
return <OnColorContainer backgroundColor={backgroundColor}>{element}</OnColorContainer>;
}
),
{
shouldForwardProp,

return element;
}
)(interpolation)
)
) as <
BaseComponent extends ComponentType<any> | undefined = undefined,
ElementName extends BoxElements | undefined = undefined
Expand Down
67 changes: 40 additions & 27 deletions packages/vibrant-core/src/lib/ScrollBox/ScrollBox.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,53 @@
import { createElement, forwardRef } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/css';
import { useComposedRef, useLayoutEvent } from '@vibrant-ui/utils';
import { transformResponsiveValue } from '../transformResponsiveValue';
import type { ScrollBoxProps } from './ScrollBoxProps';
import { interpolation, shouldForwardProp } from './ScrollBoxProps';

const SystemScrollBox = styled(
forwardRef<any, ScrollBoxProps>(
({ as = 'div', ariaChecked, ariaCurrent, ariaLabel, ariaLabelledBy, ariaSelected, ...restProps }, ref) =>
createElement(as, {
ref,
'aria-label': ariaLabel,
'aria-checked': ariaChecked,
'aria-labelledby': ariaLabelledBy,
'aria-current': ariaCurrent,
'aria-selected': ariaSelected,
...restProps,
})
),
{
shouldForwardProp,
}
)(interpolation);

export const ScrollBox = forwardRef<any, ScrollBoxProps>(
({ keyboardShouldPersistTaps: _, scrollEnabled = true, onLayout, ...restProps }, ref) => {
export const ScrollBox = forwardRef<unknown, ScrollBoxProps>(
(
{
as = 'div',
ariaChecked,
ariaCurrent,
ariaLabel,
ariaLabelledBy,
ariaSelected,
scrollEnabled = true,
onLayout,
...restProps
},
ref
) => {
const { ref: layoutEventRef } = useLayoutEvent(onLayout);
const composeRef = useComposedRef(ref, layoutEventRef);

return (
<SystemScrollBox
ref={composeRef}
{...restProps}
overflow={transformResponsiveValue(scrollEnabled, value => (value ? 'auto' : 'hidden'))}
/>
const className = Object.entries(
interpolation({
...restProps,
overflow: transformResponsiveValue(scrollEnabled, value => (value ? 'auto' : 'hidden')),
})
)
.map(([key, value]) => css({ [key]: value }))
.join(' ');

const domAttributeProps = Object.fromEntries(
Object.entries({ ...restProps }).filter(([key, _]) => shouldForwardProp(key))
);

const element = createElement(as, {
ref: composeRef,
'aria-label': ariaLabel,
'aria-checked': ariaChecked,
'aria-labelledby': ariaLabelledBy,
'aria-current': ariaCurrent,
'aria-selected': ariaSelected,
...domAttributeProps,
className,
});

return element;
}
);

Expand Down
29 changes: 16 additions & 13 deletions packages/vibrant-core/src/lib/Text/Text.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import type { FC } from 'react';
import { createElement, forwardRef } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/css';
import { nl2br } from '../nl2br';
import type { TextProps } from './TextProps';
import { interpolation, shouldForwardProp } from './TextProps';

export const Text: FC<TextProps> = styled(
forwardRef<unknown, TextProps>(({ as = 'span', children, ...restProps }, ref) =>
createElement(as, {
ref,
children: typeof children === 'string' ? nl2br(children) : children,
...restProps,
})
),
{
shouldForwardProp,
}
)(interpolation);
export const Text: FC<TextProps> = forwardRef<unknown, TextProps>(({ as = 'span', children, ...restProps }, ref) => {
const className = Object.entries(interpolation({ ...restProps } ?? {}))
.map(([key, value]) => css({ [key]: value }))
.join(' ');

const domAttributeProps = Object.fromEntries(
Object.entries({ ...restProps }).filter(([key, _]) => shouldForwardProp(key))
);

return createElement(as, {
ref,
children: typeof children === 'string' ? nl2br(children) : children,
domAttributeProps,
className,
});
});
(Text as FC).displayName = 'Text';
140 changes: 78 additions & 62 deletions packages/vibrant-core/src/lib/TextInput/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { createElement, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import type { FormEvent, KeyboardEvent } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/css';
import { createShouldForwardProp } from '../createShouldForwardProp';
import type { SystemProps, TextInputProps, TextInputRef } from './TextInputProps';
import { HTMLAutoCompleteOptions, interpolation, replaceValue, systemPropNames } from './TextInputProps';
Expand All @@ -9,10 +9,6 @@ type HTMLInputProps = Exclude<keyof JSX.IntrinsicElements['input'], keyof System

const shouldForwardProp = createShouldForwardProp<HTMLInputProps>(systemPropNames);

const SystemTextInput = styled<'input', HTMLInputProps>('input', {
shouldForwardProp,
})(interpolation);

export const TextInput = forwardRef<TextInputRef, TextInputProps>(
(
{
Expand Down Expand Up @@ -74,74 +70,94 @@ export const TextInput = forwardRef<TextInputRef, TextInputProps>(
clear: () => {
setValue('');

onValueChange?.({ value: '', prevent: () => {}, target: innerRef.current });
onValueChange?.({
value: '',
prevent: () => {},
target: innerRef.current,
});
},
isFocused: () => document.activeElement === innerRef.current,
}));

return (
<SystemTextInput
ref={innerRef}
type={type === 'number' ? 'text' : type}
value={value}
enterKeyHint={enterKeyType}
inputMode={inputMode}
autoCapitalize={autoCapitalize}
autoComplete={HTMLAutoCompleteOptions[autoComplete]}
onFocus={() => {
setIsFocused(true);

onFocus?.();
}}
onBlur={() => {
setIsFocused(false);

onBlur?.();
}}
onKeyDown={(event: KeyboardEvent<HTMLInputElement>) => {
const { key } = event.nativeEvent;

if (key === 'Enter') {
onSubmit?.(value);

return;
const styleProps = interpolation({
...restProps,
...(hidden
? {
position: 'absolute',
height: 0,
opacity: 0,
}
: {}),
...(isFocused ? focusStyle : {}),
});

onKeyPress?.({ key, prevent: () => event.preventDefault() });
}}
onInput={(event: FormEvent<HTMLInputElement>) => {
const replacedValue = replaceValue({
pattern: type === 'number' ? /\d/ : pattern,
value: event.currentTarget.value,
});
const classNames = Object.entries(interpolation(styleProps)).map(([key, value]) => css({ [key]: value }));

let isPrevented = false;
const domAttributeProps = Object.fromEntries(
Object.entries(restProps).filter(([key, _]) => shouldForwardProp(key))
);

if (value === replacedValue) {
event.preventDefault();
return createElement('input', {
ref: innerRef,
type: type === 'number' ? 'text' : type,
value,
enterKeyHint: enterKeyType,
inputMode,
autoCapitalize,
autoComplete: HTMLAutoCompleteOptions[autoComplete],
onFocus: () => {
setIsFocused(true);

return;
}
onFocus?.();
},
onBlur: () => {
setIsFocused(false);

onValueChange?.({
value: replacedValue,
prevent: () => {
isPrevented = true;
onBlur?.();
},

event.preventDefault();
},
target: innerRef.current,
});
onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => {
const { key } = event.nativeEvent;

if (!isPrevented) {
setValue(replacedValue);
}
}}
{...restProps}
{...(isFocused ? focusStyle : {})}
{...(hidden ? { position: 'absolute', height: 0, opacity: 0 } : {})}
/>
);
if (key === 'Enter') {
onSubmit?.(value);

return;
}

onKeyPress?.({ key, prevent: () => event.preventDefault() });
},
onInput: (event: FormEvent<HTMLInputElement>) => {
const replacedValue = replaceValue({
pattern: type === 'number' ? /\d/ : pattern,
value: event.currentTarget.value,
});

let isPrevented = false;

if (value === replacedValue) {
event.preventDefault();

return;
}

onValueChange?.({
value: replacedValue,
prevent: () => {
isPrevented = true;

event.preventDefault();
},
target: innerRef.current,
});

if (!isPrevented) {
setValue(replacedValue);
}
},
...domAttributeProps,
className: classNames.join(' '),
});
}
);

Expand Down
Loading

0 comments on commit 2c34420

Please sign in to comment.