refactor(infra): directory structure (#4615)

This commit is contained in:
Joooye_34
2023-10-18 23:30:08 +08:00
committed by GitHub
parent 814d552be8
commit bed9310519
1150 changed files with 539 additions and 584 deletions

View File

@@ -0,0 +1,39 @@
import { expect } from '@storybook/jest';
import type { Meta, StoryFn } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import { Input } from '.';
export default {
title: 'AFFiNE/Input',
component: Input,
} satisfies Meta<typeof Input>;
export const Basic: StoryFn<typeof Input> = () => {
return <Input data-testid="test-input" defaultValue="test" />;
};
Basic.play = async ({ canvasElement }) => {
const element = within(canvasElement);
const item = element.getByTestId('test-input') as HTMLInputElement;
expect(item).toBeTruthy();
expect(item.value).toBe('test');
userEvent.clear(item);
userEvent.type(item, 'test 2');
expect(item.value).toBe('test 2');
};
export const DynamicHeight: StoryFn<typeof Input> = () => {
return <Input width={200} data-testid="test-input" />;
};
DynamicHeight.play = async ({ canvasElement }) => {
const element = within(canvasElement);
const item = element.getByTestId('test-input') as HTMLInputElement;
expect(item).toBeTruthy();
expect(item.getBoundingClientRect().width).toBe(200);
};
export const NoBorder: StoryFn<typeof Input> = () => {
return <Input noBorder={true} data-testid="test-input" />;
};

View File

@@ -0,0 +1,3 @@
export * from './input';
import { Input } from './input';
export default Input;

View File

@@ -0,0 +1,123 @@
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import type {
ChangeEvent,
CSSProperties,
FocusEvent,
FocusEventHandler,
ForwardedRef,
InputHTMLAttributes,
KeyboardEvent,
KeyboardEventHandler,
ReactNode,
} from 'react';
import { forwardRef, useCallback, useState } from 'react';
import { input, inputWrapper, widthVar } from './style.css';
export type InputProps = {
disabled?: boolean;
width?: CSSProperties['width'];
onChange?: (value: string) => void;
onBlur?: FocusEventHandler<HTMLInputElement>;
onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
noBorder?: boolean;
status?: 'error' | 'success' | 'warning' | 'default';
size?: 'default' | 'large' | 'extraLarge';
preFix?: ReactNode;
endFix?: ReactNode;
type?: HTMLInputElement['type'];
inputStyle?: CSSProperties;
onEnter?: () => void;
} & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size'>;
export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
{
disabled,
width,
onChange: propsOnChange,
noBorder = false,
className,
status = 'default',
style = {},
inputStyle = {},
size = 'default',
onFocus,
onBlur,
preFix,
endFix,
onEnter,
onKeyDown,
...otherProps
}: InputProps,
ref: ForwardedRef<HTMLInputElement>
) {
const [isFocus, setIsFocus] = useState(false);
return (
<div
className={clsx(inputWrapper, className, {
// status
disabled: disabled,
'no-border': noBorder,
focus: isFocus,
// color
error: status === 'error',
success: status === 'success',
warning: status === 'warning',
default: status === 'default',
// size
large: size === 'large',
'extra-large': size === 'extraLarge',
})}
style={{
...assignInlineVars({
[widthVar]: width ? `${width}px` : '100%',
}),
...style,
}}
>
{preFix}
<input
className={clsx(input, {
large: size === 'large',
'extra-large': size === 'extraLarge',
})}
ref={ref}
disabled={disabled}
style={inputStyle}
onFocus={useCallback(
(e: FocusEvent<HTMLInputElement>) => {
setIsFocus(true);
onFocus?.(e);
},
[onFocus]
)}
onBlur={useCallback(
(e: FocusEvent<HTMLInputElement>) => {
setIsFocus(false);
onBlur?.(e);
},
[onBlur]
)}
onChange={useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
propsOnChange?.(e.target.value);
},
[propsOnChange]
)}
onKeyDown={useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
onEnter?.();
}
onKeyDown?.(e);
},
[onKeyDown, onEnter]
)}
{...otherProps}
/>
{endFix}
</div>
);
});

View File

@@ -0,0 +1,85 @@
import { createVar, style } from '@vanilla-extract/css';
export const widthVar = createVar('widthVar');
export const inputWrapper = style({
vars: {
[widthVar]: '100%',
},
width: widthVar,
height: 28,
padding: '4px 10px',
color: 'var(--affine-icon-color)',
border: '1px solid var(--affine-border-color)',
backgroundColor: 'var(--affine-white-10)',
borderRadius: 8,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: 8,
// icon size
fontSize: '16px',
selectors: {
'&.no-border': {
border: 'unset',
},
// size
'&.large': {
height: 32,
// icon size
fontSize: '20px',
},
'&.extra-large': {
height: 40,
padding: '8px 10px',
// icon size
fontSize: '20px',
},
// color
'&.disabled': {
background: 'var(--affine-hover-color)',
},
'&.error': {
borderColor: 'var(--affine-error-color)',
},
'&.success': {
borderColor: 'var(--affine-success-color)',
},
'&.warning': {
borderColor: 'var(--affine-warning-color)',
},
'&.default.focus': {
borderColor: 'var(--affine-primary-color)',
boxShadow: 'var(--affine-active-shadow)',
},
},
});
export const input = style({
width: '0',
flex: 1,
fontSize: 'var(--affine-font-xs)',
lineHeight: '20px',
fontWeight: '500',
color: 'var(--affine-text-primary-color)',
boxSizing: 'border-box',
// prevent default style
WebkitAppearance: 'none',
WebkitTapHighlightColor: 'transparent',
outline: 'none',
border: 'none',
selectors: {
'&::placeholder': {
color: 'var(--affine-placeholder-color)',
},
'&:disabled': {
color: 'var(--affine-text-disable-color)',
},
'&.large, &.extra-large': {
fontSize: 'var(--affine-font-base)',
lineHeight: '24px',
},
},
});