Remove DatePicker and Selectbox modal components
All checks were successful
forgejo/Procyon/procyon/pipeline/head This commit looks good

This commit is contained in:
Roman Jaroš 2024-06-14 18:58:16 +00:00
parent 11cb5d65db
commit 2763fb6ab2
25 changed files with 10318 additions and 7977 deletions

View file

@ -42,6 +42,7 @@
"react-native-svg": "15.1.0", "react-native-svg": "15.1.0",
"react-native-web": "0.19.12", "react-native-web": "0.19.12",
"scroll-into-view-if-needed": "3.0.10", "scroll-into-view-if-needed": "3.0.10",
"lucide-react-native": "^0.379.0",
"tiny-invariant": "1.3.3", "tiny-invariant": "1.3.3",
"values.js": "^2.1.1", "values.js": "^2.1.1",
"wouter": "2.12.1", "wouter": "2.12.1",
@ -88,7 +89,6 @@
"esprima": "4.0.1", "esprima": "4.0.1",
"http-server": "14.1.1", "http-server": "14.1.1",
"jest": "29.7.0", "jest": "29.7.0",
"lucide-react-native": "^0.379.0",
"nightwatch": "3.3.5", "nightwatch": "3.3.5",
"postcss-cli": "11.0.0", "postcss-cli": "11.0.0",
"postcss-loader": "8.1.0", "postcss-loader": "8.1.0",

View file

@ -28,6 +28,7 @@
"@emotion/styled": "^11.11.5", "@emotion/styled": "^11.11.5",
"clsx": "2.1.0", "clsx": "2.1.0",
"date-fns": "3.3.1", "date-fns": "3.3.1",
"lucide-react-native": "^0.379.0",
"ramda": "0.29.1", "ramda": "0.29.1",
"scroll-into-view-if-needed": "3.1.0", "scroll-into-view-if-needed": "3.1.0",
"react-native-reanimated": "3.7.0", "react-native-reanimated": "3.7.0",

View file

@ -193,7 +193,7 @@ export function Calendar({
}, [workDate, type, View, layout, onClick]); }, [workDate, type, View, layout, onClick]);
return ( return (
<Grid> <Grid style={{ gap: 6 }}>
{!isNilOrEmpty(title) && ( {!isNilOrEmpty(title) && (
<GridRow> <GridRow>
<GridCol> <GridCol>
@ -237,5 +237,6 @@ const CalendarWeekContainer = styled(GridRow)(() => {
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-around', justifyContent: 'space-around',
alignItems: 'center',
}; };
}); });

View file

@ -85,10 +85,10 @@ const CalendarDateContainer = styled.View<{
}>(({ theme, type, isSelected, isToday, isOtherMonth }) => { }>(({ theme, type, isSelected, isToday, isOtherMonth }) => {
return { return {
borderRadius: theme.spacing.sm, borderRadius: theme.spacing.sm,
backgroundColor: theme.palette.base.main, margin: 1,
...(isToday && { ...(isToday && {
backgroundColor: theme.palette.primary.main, backgroundColor: theme.palette.primary.dark,
}), }),
...(isOtherMonth && ...(isOtherMonth &&
type !== 'months' && { type !== 'months' && {
@ -114,7 +114,6 @@ const CalendarDateText = styled.Text<{
...(isToday && { ...(isToday && {
color: theme.palette.primary.light, color: theme.palette.primary.light,
fontWeight: 'bold',
}), }),
...(isOtherMonth && ...(isOtherMonth &&
type !== 'months' && { type !== 'months' && {

View file

@ -1,14 +1,14 @@
import React, { useCallback, useState } from 'react'; import React, { useState } from 'react';
import { useTheme } from '@emotion/react';
import { format, format as formatFn, parse } from 'date-fns'; import { format, format as formatFn, parse } from 'date-fns';
import { CalendarFoldIcon } from 'lucide-react-native'; import { CalendarFoldIcon } from 'lucide-react-native';
import { View } from 'react-native'; import { View } from 'react-native';
import { useModal } from '@procyon/components/Modal/context'; import { Calendar } from '@procyon/components/Calendar';
import { InputElementType } from '@procyon/types/form'; import { InputElementType } from '@procyon/types/form';
import { IMask, Masked } from '@procyon/utils/imask'; import { IMask, Masked } from '@procyon/utils/imask';
import { TextField } from '../TextField'; import { TextField } from './TextField';
import { DatePickerModal } from './DatePickerModal';
export const DEFAULT_DATE_FORMAT = 'dd.MM.yyyy'; export const DEFAULT_DATE_FORMAT = 'dd.MM.yyyy';
@ -33,35 +33,16 @@ export const DatePicker: React.FC<DatePickerProps> = ({
return undefined; return undefined;
}; };
const theme = useTheme();
const [value, setValue] = useState<string | undefined>(formatValue(others.value)); const [value, setValue] = useState<string | undefined>(formatValue(others.value));
const [openModal, closeModal] = useModal(name, { const [toggle, setToggle] = useState<boolean>(false);
style: { container: { width: 400 } },
});
const handleDateClick = (value: Date): void => { const handleDateClick = (value: Date) => {
onChange?.(value); onChange?.(value);
setValue(formatValue(value)); setValue(formatValue(value));
}; setToggle(false);
const modalComponent = useCallback(
(props) => (
<DatePickerModal
format={dateFormat}
name={name}
value={others.value}
closeModal={closeModal}
onChange={handleDateClick}
{...props}
/>
),
[format, name, others.value],
);
const handleOpenModal = (): void => {
openModal({
Component: modalComponent,
});
}; };
const mask = const mask =
@ -96,24 +77,47 @@ export const DatePicker: React.FC<DatePickerProps> = ({
}); });
return ( return (
<TextField <View style={{ position: 'relative' }}>
name={name} <TextField
label={label} name={name}
placeholder={dateFormat} label={label}
LeftIcon={(props) => ( placeholder={dateFormat}
<View style={{ cursor: 'pointer' } as any}> LeftIcon={(props) => (
<CalendarFoldIcon onClick={handleOpenModal} {...props} /> <View style={{ cursor: 'pointer' } as any}>
<CalendarFoldIcon onClick={() => setToggle(!toggle)} {...props} />
</View>
)}
{...others}
mask={mask}
value={value ?? ''}
onChange={(value) => {
if (mask.isComplete && !!onChange) {
onChange(parse(mask.value, dateFormat, new Date()));
}
setValue(value ?? undefined);
}}
/>
{toggle && (
<View
style={[
{
position: 'absolute',
top: 65,
margin: theme.spacing.sm,
marginHorizontal: 0,
padding: theme.spacing.md,
borderColor: theme.palette.primary.main,
borderWidth: 1,
borderRadius: theme.rounded.md,
},
]}>
<Calendar
onClick={handleDateClick}
value={others.value}
selected={others.value}
/>
</View> </View>
)} )}
{...others} </View>
mask={mask}
value={value ?? ''}
onChange={(value) => {
if (mask.isComplete && !!onChange) {
onChange(parse(mask.value, dateFormat, new Date()));
}
setValue(value ?? undefined);
}}
/>
); );
}; };

View file

@ -1,28 +0,0 @@
import React, { FC, useCallback } from 'react';
import { Calendar } from '../Calendar';
import { ModalId } from '../Modal/context';
export type DatePickerModalProps = {
closeModal: () => void;
format: ModalId;
name: ModalId;
onChange: (value: Date) => void;
value: Date | undefined;
};
export const DatePickerModal: FC<DatePickerModalProps> = (props) => {
const { onChange, closeModal, value } = props;
const setActiveOption = useCallback(
(value: Date) => {
onChange?.(value);
closeModal();
},
[onChange, closeModal],
);
return (
<Calendar selected={value ?? undefined} value={value} onClick={setActiveOption} />
);
};

View file

@ -1 +0,0 @@
export { DatePicker, DatePickerProps } from './DatePicker';

View file

@ -47,8 +47,6 @@ const GridColContainer = styled.View<{
const br = mQ(theme); const br = mQ(theme);
return { return {
padding: 2,
...br.xs({ ...br.xs({
flex: (100 / getSize('xs', gridCols)) * getSize('xs', cols), flex: (100 / getSize('xs', gridCols)) * getSize('xs', cols),
}), }),

View file

@ -36,7 +36,7 @@ export const ListItem: FC<ListItemProps> = ({
const handleClick = debounceAfter(() => { const handleClick = debounceAfter(() => {
onClick?.(value, children); onClick?.(value, children);
}, 200); }, 100);
const rippleColor = useMemo(() => { const rippleColor = useMemo(() => {
const val = new Values(theme.palette[color!].main); const val = new Values(theme.palette[color!].main);
@ -59,7 +59,14 @@ export const ListItem: FC<ListItemProps> = ({
style={[style?.container]} style={[style?.container]}
onPress={handleClick} onPress={handleClick}
ref={rippleAnimationRef}> ref={rippleAnimationRef}>
<RippleEffect ref={rippleAnimationRef} color={rippleColor}> <RippleEffect
ref={rippleAnimationRef}
color={rippleColor}
style={{
container: {
padding: theme.spacing.md,
},
}}>
{typeof children === 'string' ? ( {typeof children === 'string' ? (
<ListItemView> <ListItemView>
<ListItemText color={color} size={size}> <ListItemText color={color} size={size}>
@ -67,7 +74,7 @@ export const ListItem: FC<ListItemProps> = ({
</ListItemText> </ListItemText>
</ListItemView> </ListItemView>
) : ( ) : (
<ListItemView>{children}</ListItemView> children
)} )}
</RippleEffect> </RippleEffect>
</ListItemContainer> </ListItemContainer>
@ -82,6 +89,7 @@ const ListItemContainer = styled.Pressable<{
return { return {
borderBottomWidth: 1, borderBottomWidth: 1,
borderColor: theme.palette.primary.light, borderColor: theme.palette.primary.light,
backgroundColor: theme.palette.base.light,
...(selected && { ...(selected && {
backgroundColor: theme.palette[color!].light, backgroundColor: theme.palette[color!].light,
@ -92,9 +100,11 @@ const ListItemContainer = styled.Pressable<{
}; };
}); });
const ListItemView = styled.View(({ theme }) => { export const ListItemView = styled.View(() => {
return { return {
padding: theme.spacing.md, display: 'flex',
flexDirection: 'row',
alignItems: 'center',
}; };
}); });

View file

@ -3,10 +3,10 @@ import styled from '@emotion/native';
import { View } from 'react-native'; import { View } from 'react-native';
import { Label } from '@procyon/components/Label'; import { Label } from '@procyon/components/Label';
import { RadioItem } from '@procyon/components/RadioButton/RadioItem'; import { RadioItem } from '@procyon/components/RadioItem';
import { InputElementType } from '@procyon/types/form'; import { InputElementType } from '@procyon/types/form';
import { FieldMessage } from '../FieldMessage'; import { FieldMessage } from './FieldMessage';
export type RadioButtonProps = Omit< export type RadioButtonProps = Omit<
{ {

View file

@ -1,2 +0,0 @@
export { RadioButton, RadioButtonProps } from './RadioButton';
export { RadioItem, RadioItemProps } from './RadioItem';

View file

@ -3,7 +3,7 @@ import styled from '@emotion/native';
import { useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import { CircleCheckIcon, CircleIcon } from 'lucide-react-native'; import { CircleCheckIcon, CircleIcon } from 'lucide-react-native';
import { RadioButtonProps } from '@procyon/components/RadioButton/RadioButton'; import { RadioButtonProps } from '@procyon/components/RadioButton';
export type RadioItemProps = { export type RadioItemProps = {
children: string; children: string;

View file

@ -0,0 +1,122 @@
import React, {
Children,
FC,
isValidElement,
ReactNode,
useEffect,
useState,
} from 'react';
import styled from '@emotion/native';
import { ChevronDownIcon } from 'lucide-react-native';
import { Platform, Pressable, View } from 'react-native';
import { List, ListProps } from '@procyon/components/List';
import { ListItem } from '@procyon/components/ListItem';
import { InputElementType } from '@procyon/types/form';
import { TextField, TextFieldProps } from './TextField';
export type SelectboxProps = Omit<
InputElementType<string> & {
children: ReactNode;
clearable?: boolean;
onChange?: (value: string) => void;
style?: {
input?: TextFieldProps['style'];
list?: ListProps['style'];
};
},
'onFocus' | 'onClick' | 'onBlur'
>;
const findPreSelectedItems = (children: ReactNode, initValue: string): ReactNode => {
return Children.map(Children.toArray(children), (child: ReactNode) => {
const elementChild = child as ReactNode;
if (isValidElement(elementChild)) {
if (elementChild.type === ListItem && elementChild.props.value === initValue) {
return elementChild.props.children;
}
}
return null;
});
};
export const Selectbox: FC<SelectboxProps> = (props) => {
const { value, onChange, label, children, message, ...others } = props;
const [toggle, setToggle] = useState<boolean>(false);
const [renderValue, setRenderValue] = useState<ReactNode>(null);
const handleClick = (value: string, renderValue: ReactNode) => {
setRenderValue(renderValue);
onChange?.(value);
setToggle(false);
};
useEffect(() => {
if (value) {
setRenderValue(findPreSelectedItems(children, value));
}
}, []);
return (
<View style={{ position: 'relative' }}>
<TextField
{...others}
style={{
...(props.style?.input ?? {}),
input: [],
}}
label={label}
Input={(props) =>
typeof renderValue === 'string' ? (
<FieldText {...props} style={[props.style?.input]}>
{renderValue}
</FieldText>
) : (
renderValue ?? <View />
)
}
message={message}
onClick={() => setToggle(!toggle)}
RightIcon={(props) => (
<Pressable
onPressIn={() => setToggle(!toggle)}
style={[Platform.OS === 'web' && { cursor: 'pointer' }]}>
<ChevronDownIcon {...props} />
</Pressable>
)}
/>
{toggle && (
<List
{...others}
selected={value}
onClick={handleClick}
style={{
container: [
{
position: 'absolute',
top: 65,
width: '100%',
marginHorizontal: 0,
},
props.style?.list?.container,
],
}}>
{children}
</List>
)}
</View>
);
};
const FieldText = styled.Text<{
size: SelectboxProps['size'];
}>(({ theme, size }) => {
return {
...(Platform.OS === 'web' && { cursor: 'pointer' }),
color: theme.palette.text.main,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize[size!],
};
});

View file

@ -1,120 +0,0 @@
import React, { Children, FC, isValidElement, ReactNode, useEffect } from 'react';
import { mergeDeepRight } from 'ramda';
import styled from '@emotion/native';
import { PointerIcon } from 'lucide-react-native';
import { Pressable, View } from 'react-native';
import { ListItem } from '@procyon/components/ListItem';
import { Modal, useModal } from '@procyon/components/Modal/context';
import { SelectboxProvider, useSelectbox } from '@procyon/components/Selectbox/context';
import { InputElementType } from '@procyon/types/form';
import { TextField, TextFieldProps } from '../TextField';
import { SelectboxModal, SelectboxModalProps } from './SelectboxModal';
export type SelectboxProps = Omit<
InputElementType<string> & {
children: ReactNode;
clearable?: boolean;
onChange?: (value: string) => void;
style?: {
input?: TextFieldProps['style'];
list?: SelectboxModalProps['style'];
modal?: Modal<any>['style'];
};
},
'onFocus' | 'onClick' | 'onBlur'
>;
const findPreSelectedItems = (children: ReactNode, initValue: string): ReactNode => {
return Children.map(Children.toArray(children), (child: ReactNode) => {
const elementChild = child as ReactNode;
if (isValidElement(elementChild)) {
if (elementChild.type === ListItem && elementChild.props.value === initValue) {
return elementChild.props.children;
}
}
return null;
});
};
const SelectboxComponent: FC<SelectboxProps> = (props) => {
const { value, onChange, name, label, children, message, ...others } = props;
const { renderValue, setRenderValue } = useSelectbox();
const handleClick = (value: string, renderValue: ReactNode) => {
setRenderValue(renderValue);
onChange?.(value);
};
const handleOptionRemove = () => {
onChange?.(undefined);
};
const [openModal, closeModal] = useModal(name, {
style: mergeDeepRight({ container: { maxWidth: 300 } }, props.style?.modal ?? {}),
Component: (modalProps: object) => (
<SelectboxModal
name={name!}
closeModal={closeModal}
onChange={handleClick}
onRemove={handleOptionRemove}
style={props.style?.list}
clearable={props.clearable}
value={value}
{...modalProps}>
{children}
</SelectboxModal>
),
});
useEffect(() => {
if (value) {
setRenderValue(findPreSelectedItems(children, value));
}
}, []);
return (
<TextField
{...others}
style={{
...props.style,
input: [],
}}
label={label}
Input={(props) => (
<FieldText {...props} style={[props.style?.input]}>
{renderValue ?? <View />}
</FieldText>
)}
message={message}
onClick={() => openModal()}
RightIcon={(props) => (
<Pressable
onPress={() => openModal()}
style={[{ cursor: 'pointer' } as any]}
{...props}>
<PointerIcon />
</Pressable>
)}
/>
);
};
export const Selectbox: FC<SelectboxProps> = ({ children, ...props }) => (
<SelectboxProvider>
<SelectboxComponent {...props}>{children}</SelectboxComponent>
</SelectboxProvider>
);
const FieldText = styled.Text<{
size: SelectboxProps['size'];
}>(({ theme, size }) => {
return {
cursor: 'pointer' as any,
color: theme.palette.text.main,
fontFamily: theme.fontFamily,
fontSize: theme.fontSize[size!],
};
});

View file

@ -1,66 +0,0 @@
import React, { FC, ReactNode } from 'react';
import { mergeDeepRight } from 'ramda';
import { TrashIcon } from 'lucide-react-native';
import { List, ListProps } from '@procyon/components/List';
import { Button } from '../Button';
import { ModalId } from '../Modal/context';
export type SelectboxModalProps = {
children: ReactNode;
clearable?: boolean;
closeModal: () => void;
name: ModalId;
onChange: (value: string, renderValue: ReactNode) => void;
onRemove: () => void;
style?: {
container: NonNullable<ListProps['style']>['container'];
};
value?: string;
};
export const SelectboxModal: FC<SelectboxModalProps> = ({
onChange,
onRemove,
closeModal,
style,
clearable,
value,
children,
...others
}) => {
const handleChange = (value: string, renderValue: ReactNode) => {
onChange(value, renderValue);
closeModal();
};
const removeActiveOption = (): void => {
onRemove();
closeModal();
};
return (
<>
<List
{...others}
selected={value}
onClick={handleChange}
style={mergeDeepRight(
{
container: {
maxHeight: 250,
},
},
style ?? {},
)}>
{children}
</List>
{clearable && (
<Button size="sm" color="negative" onClick={removeActiveOption} variant="text">
<TrashIcon fontSize={20} />
</Button>
)}
</>
);
};

View file

@ -1,34 +0,0 @@
import React, {
createContext,
Dispatch,
FC,
ReactNode,
SetStateAction,
useContext,
useState,
} from 'react';
export type SelectboxContext = {
renderValue: ReactNode | null;
setRenderValue: Dispatch<SetStateAction<ReactNode | null>>;
};
const SelectboxContext = createContext<SelectboxContext>({} as any);
export type SelectboxProviderProps = {
children: ReactNode;
};
export const SelectboxProvider: FC<SelectboxProviderProps> = ({ children, ...props }) => {
const [renderValue, setRenderValue] = useState(null);
return (
<SelectboxContext.Provider value={{ renderValue, setRenderValue, ...props }}>
{children}
</SelectboxContext.Provider>
);
};
export const useSelectbox = () => {
return useContext(SelectboxContext);
};

View file

@ -1 +0,0 @@
export { Selectbox, SelectboxProps } from './Selectbox';

View file

@ -1,11 +1,10 @@
import React, { FC, useState } from 'react'; import React, { FC } from 'react';
import styled from '@emotion/native'; import styled from '@emotion/native';
import { Theme, useTheme } from '@emotion/react'; import { useTheme } from '@emotion/react';
import { import {
InputModeOptions, InputModeOptions,
Pressable, Pressable,
StyleProp, StyleProp,
Text,
TextInputFocusEventData, TextInputFocusEventData,
TextStyle, TextStyle,
View, View,
@ -73,8 +72,6 @@ export const TextField: React.FC<TextFieldProps> = (props) => {
loading, loading,
} = props; } = props;
const [focused, setFocused] = useState(false);
const theme = useTheme(); const theme = useTheme();
const applyMask = (val: typeof props.value) => { const applyMask = (val: typeof props.value) => {
@ -93,12 +90,10 @@ export const TextField: React.FC<TextFieldProps> = (props) => {
const handleFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => { const handleFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
onFocus?.(e.nativeEvent.text, e); onFocus?.(e.nativeEvent.text, e);
setFocused(true);
}; };
const handleBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>): void => { const handleBlur = (e: NativeSyntheticEvent<TextInputFocusEventData>): void => {
onBlur?.(e.nativeEvent.text, e); onBlur?.(e.nativeEvent.text, e);
setFocused(false);
}; };
const handleChange = (e: NativeSyntheticEvent<TextInputChangeEventData>): void => { const handleChange = (e: NativeSyntheticEvent<TextInputChangeEventData>): void => {
@ -115,17 +110,17 @@ export const TextField: React.FC<TextFieldProps> = (props) => {
{label} {label}
</Label> </Label>
<Skeleton active={loading || false} layout={[{ key: '1', height: 40 }]}> <Skeleton active={loading || false} layout={[{ key: '1', height: 40 }]}>
<TextFieldWrapper color={color} disabled={disabled} focused={focused}> <TextFieldWrapper color={color} disabled={disabled}>
{LeftIcon && ( {LeftIcon && (
<TextFieldIconContainer style={[style?.icon]}> <TextFieldIconContainer>
<LeftIcon style={[textFieldIcon({ icon: true, color, size, theme })]} /> <LeftIcon style={[style?.icon]} color={theme.palette[color!].main} />
</TextFieldIconContainer> </TextFieldIconContainer>
)} )}
{leftText && ( {leftText && (
<TextFieldIconContainer> <TextFieldIconContainer>
<Text style={[textFieldIcon({ icon: false, color, size, theme })]}> <TextFieldText color={color} size={size}>
{leftText} {leftText}
</Text> </TextFieldText>
</TextFieldIconContainer> </TextFieldIconContainer>
)} )}
<Pressable <Pressable
@ -159,15 +154,15 @@ export const TextField: React.FC<TextFieldProps> = (props) => {
/> />
</Pressable> </Pressable>
{RightIcon && ( {RightIcon && (
<TextFieldIconContainer style={[style?.icon]}> <TextFieldIconContainer>
<RightIcon style={[textFieldIcon({ icon: true, color, size, theme })]} /> <RightIcon style={[style?.icon]} color={theme.palette[color!].main} />
</TextFieldIconContainer> </TextFieldIconContainer>
)} )}
{rightText && ( {rightText && (
<TextFieldIconContainer> <TextFieldIconContainer>
<Text style={[textFieldIcon({ icon: false, color, size, theme })]}> <TextFieldText color={color} size={size}>
{rightText} {rightText}
</Text> </TextFieldText>
</TextFieldIconContainer> </TextFieldIconContainer>
)} )}
</TextFieldWrapper> </TextFieldWrapper>
@ -180,8 +175,7 @@ export const TextField: React.FC<TextFieldProps> = (props) => {
const TextFieldWrapper = styled.View<{ const TextFieldWrapper = styled.View<{
color: TextFieldProps['color']; color: TextFieldProps['color'];
disabled: boolean; disabled: boolean;
focused: boolean; }>(({ theme, color, disabled }) => {
}>(({ theme, color, focused, disabled }) => {
return { return {
height: 40, height: 40,
display: 'flex', display: 'flex',
@ -190,11 +184,11 @@ const TextFieldWrapper = styled.View<{
borderRadius: theme.rounded.sm - 1, borderRadius: theme.rounded.sm - 1,
paddingHorizontal: theme.spacing.lg, paddingHorizontal: theme.spacing.lg,
borderWidth: 2, borderWidth: 2,
borderColor: new Values(theme.palette[color!].main).tint(80).rgbString(), borderColor: new Values(theme.palette[color!].main).tint(30).rgbString(),
backgroundColor: new Values(theme.palette[color!].light).tint(50).rgbString(), backgroundColor: new Values(theme.palette[color!].light).tint(50).rgbString(),
...(focused && { ...(color === 'primary' && {
borderColor: new Values(theme.palette[color!].main).tint(30).rgbString(), backgroundColor: theme.palette.base.light,
}), }),
...(disabled && { ...(disabled && {
@ -225,18 +219,13 @@ const TextFieldIconContainer = styled.View(() => {
}; };
}); });
const textFieldIcon = ({ const TextFieldText = styled.Text<{
icon,
theme,
color,
size,
}: {
color: TextFieldProps['color']; color: TextFieldProps['color'];
icon: boolean;
size: TextFieldProps['size']; size: TextFieldProps['size'];
theme: Theme; }>(({ theme, color, size }) => {
}) => ({ return {
color: theme.palette[color!].main, color: theme.palette[color!].main,
fontSize: theme.fontSize[size!] + (icon ? 4 : 0), fontSize: theme.fontSize[size!],
fontFamily: theme.fontFamily, fontFamily: theme.fontFamily,
};
}); });

View file

@ -12,40 +12,47 @@ export const Typography: FC<TypographyProps> = ({ children, size = 'h5' }) => {
const TypographyText = styled.Text<{ const TypographyText = styled.Text<{
size: TypographyProps['size']; size: TypographyProps['size'];
}>(({ size, theme }) => { }>(
switch (size) { ({ theme }) => {
case 'h1': { return {
return { fontFamily: theme.fontFamily,
fontSize: theme.fontSize['xxxl'], };
}; },
({ size, theme }) => {
switch (size) {
case 'h1': {
return {
fontSize: theme.fontSize['xxxl'],
};
}
case 'h2': {
return {
fontSize: theme.fontSize['xxl'],
};
}
case 'h3': {
return {
fontSize: theme.fontSize['xl'],
};
}
case 'h4': {
return {
fontSize: theme.fontSize['lg'],
};
}
case 'h5': {
return {
fontSize: theme.fontSize['md'],
};
}
case 'text': {
return {
fontSize: theme.fontSize['sm'],
};
}
default: {
return {};
}
} }
case 'h2': { },
return { );
fontSize: theme.fontSize['xxl'],
};
}
case 'h3': {
return {
fontSize: theme.fontSize['xl'],
};
}
case 'h4': {
return {
fontSize: theme.fontSize['lg'],
};
}
case 'h5': {
return {
fontSize: theme.fontSize['md'],
};
}
case 'text': {
return {
fontSize: theme.fontSize['sm'],
};
}
default: {
return {};
}
}
});

View file

@ -4,7 +4,7 @@ import { useController, useFormContext } from 'react-hook-form';
import { Checkbox } from '@procyon/components/Checkbox'; import { Checkbox } from '@procyon/components/Checkbox';
import { DatePicker } from '@procyon/components/DatePicker'; import { DatePicker } from '@procyon/components/DatePicker';
import { RadioButton } from '@procyon/components/RadioButton/RadioButton'; import { RadioButton } from '@procyon/components/RadioButton';
import { Selectbox } from '@procyon/components/Selectbox'; import { Selectbox } from '@procyon/components/Selectbox';
import { TextField } from '@procyon/components/TextField'; import { TextField } from '@procyon/components/TextField';
import { TimePicker } from '@procyon/components/TimePicker'; import { TimePicker } from '@procyon/components/TimePicker';

View file

@ -2,7 +2,7 @@ import { FieldValues, SubmitErrorHandler, SubmitHandler } from 'react-hook-form'
import { CheckboxProps } from '@procyon/components/Checkbox'; import { CheckboxProps } from '@procyon/components/Checkbox';
import { DatePickerProps } from '@procyon/components/DatePicker'; import { DatePickerProps } from '@procyon/components/DatePicker';
import { RadioButtonProps } from '@procyon/components/RadioButton/RadioButton'; import { RadioButtonProps } from '@procyon/components/RadioButton';
import { SelectboxProps } from '@procyon/components/Selectbox'; import { SelectboxProps } from '@procyon/components/Selectbox';
import { TextFieldProps } from '@procyon/components/TextField'; import { TextFieldProps } from '@procyon/components/TextField';
import { TimePickerProps } from '@procyon/components/TimePicker'; import { TimePickerProps } from '@procyon/components/TimePicker';

17610
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Meta, StoryObj } from '@storybook/react'; import { Meta, StoryObj } from '@storybook/react';
import { RadioButton } from '@procyon/components/RadioButton/RadioButton'; import { RadioButton } from '@procyon/components/RadioButton';
import { RadioItem } from '@procyon/components/RadioButton/RadioItem'; import { RadioItem } from '@procyon/components/RadioItem';
type Story = StoryObj<typeof RadioButton>; type Story = StoryObj<typeof RadioButton>;

View file

@ -1,8 +1,8 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Meta, StoryObj } from '@storybook/react'; import { Meta, StoryObj } from '@storybook/react';
import { Text, View } from 'react-native'; import { View } from 'react-native';
import { ListItem, ListItemValue } from '@procyon/components/ListItem'; import { ListItem, ListItemText } from '@procyon/components/ListItem';
import { ModalProvider } from '@procyon/components/Modal/context'; import { ModalProvider } from '@procyon/components/Modal/context';
import { Modals } from '@procyon/components/Modal/Modals'; import { Modals } from '@procyon/components/Modal/Modals';
import { Selectbox } from '@procyon/components/Selectbox'; import { Selectbox } from '@procyon/components/Selectbox';
@ -41,26 +41,21 @@ export const Default: Story = {
label: 'I am Selectbox', label: 'I am Selectbox',
}, },
render: function Component(args) { render: function Component(args) {
const [value, setValue] = useState<ListItemValue | undefined>(undefined); const [value, setValue] = useState<string | undefined>(undefined);
const onValueChange = (item: ListItemValue) => { const onValueChange = (item: string) => {
args.onChange?.(item); args.onChange?.(item);
setValue(item); setValue(item);
}; };
return ( return (
<Selectbox value={value} {...args} onChange={onValueChange}> <Selectbox value={value} {...args} onChange={onValueChange}>
<ListItem id="item1" value="Item 1"> <ListItem value="Item 1">Item 1</ListItem>
Item 1 <ListItem value="Item 2" color="negative">
</ListItem>
<ListItem id="item2" value="Item 2" color="negative">
Item 2 Item 2
</ListItem> </ListItem>
<ListItem id="item3" value="Doplhin"> <ListItem value="Doplhin">
<View> <ListItemText style={{ fontSize: 20 }}>Doplhin</ListItemText>
<Text style={{ fontSize: 20 }}>Doplhin</Text>
</View>
<Text>Is a smart animal</Text>
</ListItem> </ListItem>
</Selectbox> </Selectbox>
); );

View file

@ -1,14 +1,13 @@
import React from 'react'; import React from 'react';
import { action } from '@storybook/addon-actions'; import { action } from '@storybook/addon-actions';
import { FlagIcon } from 'lucide-react-native'; import { FlagIcon } from 'lucide-react-native';
import { View } from 'react-native';
import * as yup from 'yup'; import * as yup from 'yup';
import { Button } from '@procyon/components/Button'; import { Button } from '@procyon/components/Button';
import { Grid, GridCol, GridRow } from '@procyon/components/Grid'; import { Grid, GridCol, GridRow } from '@procyon/components/Grid';
import { ListItem, ListItemText } from '@procyon/components/ListItem'; import { ListItem, ListItemText, ListItemView } from '@procyon/components/ListItem';
import { Puzzle } from '@procyon/components/Puzzle'; import { Puzzle } from '@procyon/components/Puzzle';
import { RadioItem } from '@procyon/components/RadioButton'; import { RadioItem } from '@procyon/components/RadioItem';
import { Field, FieldWrapper } from '@procyon/forms/Field'; import { Field, FieldWrapper } from '@procyon/forms/Field';
import { Form } from '@procyon/forms/Form'; import { Form } from '@procyon/forms/Form';
import { useForm } from '@procyon/forms/useForm'; import { useForm } from '@procyon/forms/useForm';
@ -63,16 +62,10 @@ export const ExampleForm = () => {
<Field component="SELECT" name="selectBox" label="SelectBox"> <Field component="SELECT" name="selectBox" label="SelectBox">
<ListItem value="item1">Item 1</ListItem> <ListItem value="item1">Item 1</ListItem>
<ListItem value="item2" color="negative"> <ListItem value="item2" color="negative">
<View <ListItemView style={{ gap: 6 }}>
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: 6,
}}>
<FlagIcon color="black" fill="red" strokeWidth={1} /> <FlagIcon color="black" fill="red" strokeWidth={1} />
<ListItemText>Item 2</ListItemText> <ListItemText>Item 2</ListItemText>
</View> </ListItemView>
</ListItem> </ListItem>
</Field> </Field>
<Field component="DATE" name="datePicker" label="DatePicker" /> <Field component="DATE" name="datePicker" label="DatePicker" />