Remove unused hooks and utils, simplify Field component, and adjust imports
Some checks failed
forgejo/Procyon/procyon/pipeline/head There was a failure building this commit

This commit is contained in:
Roman Jaroš 2024-07-08 15:48:13 +00:00
parent deebdb261d
commit cda0d4569f
39 changed files with 2963 additions and 4872 deletions

View file

@ -18,7 +18,7 @@ import {
import { TolgeeChain, TolgeeProvider, useTolgee } from '@procyon/localization/tolgee';
import { buildColorTheme } from '@procyon/styles/theme/color';
import { baseTheme } from '@procyon/styles/theme/base';
import { MediaQueryProvider } from '@procyon/hooks/useMediaQuery';
import { MediaQueryProvider } from '@procyon/styles/useMediaQuery';
import { ModalProvider } from '@procyon/components/Modal/context';
import { Modals } from '@procyon/components/Modal';
import { Theme } from '@emotion/react';

View file

@ -26,77 +26,70 @@
"test": "jest --passWithNoTests"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/native": "^11.11.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"clsx": "2.1.0",
"date-fns": "3.3.1",
"postcss": "8.4.33",
"lucide-react-native": "^0.402.0",
"ramda": "0.29.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.74.1",
"react-native-advanced-ripple": "1.0.0",
"react-native-gesture-handler": "^2.16.2",
"react-native-gesture-handler": "^2.16.1",
"react-native-reanimated": "3.7.0",
"react-native-svg": "15.1.0",
"react-native-web": "0.19.12",
"scroll-into-view-if-needed": "3.0.10",
"lucide-react-native": "^0.379.0",
"scroll-into-view-if-needed": "3.1.0",
"tiny-invariant": "1.3.3",
"values.js": "^2.1.1",
"wouter": "2.12.1",
"wouter": "3.3.1",
"yup": "1.3.3"
},
"devDependencies": {
"@babel/core": "7.23.9",
"@babel/preset-env": "^7.23.9",
"@babel/preset-typescript": "7.23.3",
"@storybook/addon-actions": "^8.1.5",
"@storybook/addon-essentials": "^8.1.5",
"@storybook/addon-links": "^8.1.5",
"@storybook/addon-mdx-gfm": "^8.1.5",
"@storybook/addon-react-native-web": "0.0.23",
"@storybook/addon-viewport": "^8.1.5",
"@babel/core": "7.24.7",
"@babel/preset-env": "^7.24.7",
"@babel/preset-typescript": "7.24.7",
"@storybook/addon-actions": "^8.1.11",
"@storybook/addon-essentials": "^8.1.11",
"@storybook/addon-links": "^8.1.11",
"@storybook/addon-mdx-gfm": "^8.1.11",
"@storybook/addon-react-native-web": "0.0.24",
"@storybook/addon-viewport": "^8.1.11",
"@storybook/addon-webpack5-compiler-babel": "^3.0.3",
"@storybook/blocks": "^8.1.5",
"@storybook/manager-api": "^8.1.5",
"@storybook/react": "^8.1.5",
"@storybook/react-native": "7.6.19",
"@storybook/react-webpack5": "^8.1.5",
"@storybook/types": "^8.1.5",
"@storybook/blocks": "^8.1.11",
"@storybook/manager-api": "^8.1.11",
"@storybook/react": "^8.1.11",
"@storybook/react-native": "7.6.20",
"@storybook/react-webpack5": "^8.1.11",
"@storybook/types": "^8.1.11",
"@types/jest": "29.5.12",
"@types/mdx": "2.0.10",
"@types/node": "18.18.2",
"@types/ramda": "0.29.10",
"@types/react": "18.2.52",
"@types/react-dom": "18.2.18",
"@types/yup": "0.29.14",
"@typescript-eslint/eslint-plugin": "6.20.0",
"@typescript-eslint/parser": "6.20.0",
"autoprefixer": "10.4.17",
"@types/mdx": "2.0.13",
"@types/node": "20.14.10",
"@types/ramda": "0.30.1",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@typescript-eslint/eslint-plugin": "7.15.0",
"@typescript-eslint/parser": "7.15.0",
"autoprefixer": "10.4.19",
"babel-loader": "^9.1.3",
"babel-plugin-react-native-web": "^0.19.10",
"babel-plugin-react-native-web": "^0.19.12",
"cross-env": "7.0.3",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-mdx": "3.1.5",
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-simple-import-sort": "10.0.0",
"eslint-plugin-typescript-sort-keys": "3.1.0",
"eslint-plugin-react": "7.34.3",
"eslint-plugin-react-hooks": "4.6.2",
"eslint-plugin-simple-import-sort": "12.1.1",
"eslint-plugin-typescript-sort-keys": "3.2.0",
"esprima": "4.0.1",
"http-server": "14.1.1",
"jest": "29.7.0",
"nightwatch": "3.3.5",
"postcss-cli": "11.0.0",
"postcss-loader": "8.1.0",
"prettier": "3.2.4",
"prettier": "3.3.2",
"raw-loader": "4.0.2",
"storybook": "^8.1.5",
"tailwindcss": "3.4.1",
"ts-jest": "29.1.2",
"ts-jest": "29.1.5",
"ts-node": "10.9.2",
"tsconfig-paths": "4.2.0",
"typescript": "5.3.3"

View file

@ -16,12 +16,6 @@
"linkDirectory": false
},
"dependencies": {
"@procyon/auth": "workspace:^",
"@procyon/types": "workspace:^",
"@procyon/utils": "workspace:^",
"async-mutex": "0.4.1"
},
"peerDependencies": {
"@reduxjs/toolkit": "2.1.0"
"@procyon/auth": "workspace:^"
}
}

View file

@ -15,11 +15,5 @@
{
"path": "../auth/tsconfig.build.json"
},
{
"path": "../utils/tsconfig.build.json"
},
{
"path": "../types/tsconfig.build.json"
},
],
}

View file

@ -20,18 +20,16 @@
"@procyon/localization": "workspace:^",
"@procyon/types": "workspace:^",
"@procyon/utils": "workspace:^",
"@procyon/styles": "workspace:^"
"@procyon/styles": "workspace:^",
"values.js": "^2.1.1"
},
"peerDependencies": {
"@emotion/react": "^11.11.4",
"@emotion/native": "^11.11.0",
"@emotion/styled": "^11.11.5",
"clsx": "2.1.0",
"@emotion/native": "^11.11.0",
"date-fns": "3.3.1",
"lucide-react-native": "^0.379.0",
"ramda": "0.29.1",
"scroll-into-view-if-needed": "3.1.0",
"react-native-reanimated": "3.7.0",
"react-native-svg": "15.1.0"
"lucide-react-native": "^0.379.0",
"react-native-reanimated": "3.7.0"
}
}

View file

@ -36,7 +36,7 @@ export const Alert: FC<AlertProps> = ({ color = 'secondary', title, Icon, childr
);
};
const MessageContainer = styled.View<{
const MessageContainer = styled(View)<{
color: AlertProps['color'];
}>(({ theme, color }) => {
return {

View file

@ -1,13 +1,13 @@
import React, { FC, ReactNode, useState } from 'react';
import styled from '@emotion/native';
import { Theme } from '@emotion/react';
import { MenuIcon } from 'lucide-react-native';
import { View } from 'react-native';
import { Modals } from '@procyon/components/Modal/Modals';
import { Toasters } from '@procyon/components/Toaster';
import { ToastersProps } from '@procyon/components/Toaster/Toasters';
import { useScreenDimensions } from '@procyon/hooks/useScreenDimensions';
import { mQ } from '@procyon/styles/mq';
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
export type AppLayoutProps = {
Footer?: FC;
@ -31,7 +31,7 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
const enabledSideNav = !!SideNav;
const enabledTopNav = !!TopNav || !!UserNav;
useScreenDimensions();
const mq = useMediaQuery();
const [sideCollapsed, setSideCollapsed] = useState(false);
const [topCollapsed, setTopCollapsed] = useState(true);
@ -47,10 +47,11 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
return (
<AppLayoutContainer>
{enabledTopNav && (
<AppLayoutTopNav onPress={toggleTop}>
<AppLayoutTopLeftSide placeholder={!Logo}>
<AppLayoutTopNav mq={mq} onPress={toggleTop}>
<AppLayoutTopLeftSide mq={mq} placeholder={!Logo}>
<AppLayoutLogo>{Logo ?? <View />}</AppLayoutLogo>
<AppLayoutMenuToggle
mq={mq}
style={{
marginBottom: 2,
}}
@ -58,12 +59,14 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
/>
</AppLayoutTopLeftSide>
<AppLayoutNavSection
mq={mq}
visible={!topCollapsed}
direction="row"
justifyContent="flex-start">
{TopNav?.map((Nav: any, i) => <Nav key={i} />)}
</AppLayoutNavSection>
<AppLayoutNavSection
mq={mq}
visible={!topCollapsed}
direction="row"
justifyContent="flex-end">
@ -71,11 +74,12 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
</AppLayoutNavSection>
</AppLayoutTopNav>
)}
<AppLayoutContent>
<AppLayoutContent mq={mq}>
{enabledSideNav && (
<AppLayoutSideNav onPress={toggleSide}>
<AppLayoutMenuToggle style={{ minWidth: 30 }} strokeWidth={1} />
<AppLayoutSideNav mq={mq} onPress={toggleSide}>
<AppLayoutMenuToggle mq={mq} style={{ minWidth: 30 }} strokeWidth={1} />
<AppLayoutNavSection
mq={mq}
visible={sideCollapsed}
direction="column"
justifyContent="center">
@ -92,25 +96,25 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
);
};
const AppLayoutContainer = styled.View(({ theme }) => {
const AppLayoutContainer = styled(View)(({ theme }) => {
return {
backgroundColor: theme.palette.background.main,
};
});
const AppLayoutNavSection = styled.View<{
const AppLayoutNavSection = styled(View)<{
direction: 'row' | 'column';
justifyContent: 'flex-start' | 'center' | 'flex-end';
mq: keyof Theme['breakpoints'];
visible: boolean;
}>(({ theme, direction, visible, justifyContent }) => {
const br = mQ(theme);
}>(({ theme, direction, visible, justifyContent, mq }) => {
return {
display: 'flex',
flexDirection: direction,
columnGap: 4,
rowGap: 4,
...br.xs({
...(mq === 'xs' && {
marginTop: theme.spacing.sm,
flexWrap: 'wrap',
flex: 1,
@ -124,34 +128,35 @@ const AppLayoutNavSection = styled.View<{
};
});
const AppLayoutTopNav = styled.Pressable(({ theme }) => {
const br = mQ(theme);
return {
backgroundColor: theme.palette.primary.light,
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
columnGap: 4,
alignItems: 'center',
padding: theme.spacing.sm,
const AppLayoutTopNav = styled.Pressable<{ mq: keyof Theme['breakpoints'] }>(
({ theme, mq }) => {
return {
backgroundColor: theme.palette.primary.light,
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
columnGap: 4,
alignItems: 'center',
padding: theme.spacing.sm,
...br.xs({
flexDirection: 'column',
alignItems: 'stretch',
}),
};
});
...(mq === 'xs' && {
flexDirection: 'column',
alignItems: 'stretch',
}),
};
},
);
const AppLayoutTopLeftSide = styled.View<{
const AppLayoutTopLeftSide = styled(View)<{
mq: keyof Theme['breakpoints'];
placeholder: boolean;
}>(({ theme, placeholder }) => {
const br = mQ(theme);
}>(({ placeholder, mq }) => {
return {
...(placeholder && {
display: 'none',
}),
...br.xs({
...(mq === 'xs' && {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
@ -168,33 +173,36 @@ const AppLayoutLogo = styled.Text(({ theme }) => {
};
});
const AppLayoutMenuToggle = styled(MenuIcon)(({ theme }) => {
const br = mQ(theme);
const AppLayoutMenuToggle = styled(MenuIcon)<{
mq: keyof Theme['breakpoints'];
}>(({ mq }) => {
return {
display: 'none',
...br.xs({
...(mq === 'xs' && {
display: 'flex',
}),
};
});
const AppLayoutContent = styled.View(({ theme }) => {
const br = mQ(theme);
const AppLayoutContent = styled(View)<{
mq: keyof Theme['breakpoints'];
}>(({ theme, mq }) => {
return {
display: 'flex',
flexDirection: 'row',
gap: 4,
marginTop: theme.spacing.md,
...br.xs({
...(mq === 'xs' && {
flexDirection: 'column',
marginTop: theme.spacing.sm,
}),
};
});
const AppLayoutSideNav = styled.Pressable(({ theme }) => {
const br = mQ(theme);
const AppLayoutSideNav = styled.Pressable<{
mq: keyof Theme['breakpoints'];
}>(({ theme, mq }) => {
return {
width: 150,
borderRadius: theme.rounded.small,
@ -206,7 +214,7 @@ const AppLayoutSideNav = styled.Pressable(({ theme }) => {
padding: theme.spacing.sm,
marginRight: 2,
...br.xs({
...(mq === 'xs' && {
width: 'auto',
flexDirection: 'row',
flexWrap: 'wrap',
@ -215,7 +223,7 @@ const AppLayoutSideNav = styled.Pressable(({ theme }) => {
};
});
const AppLayoutPage = styled.View(({ theme }) => {
const AppLayoutPage = styled(View)(({ theme }) => {
return {
padding: theme.spacing.md,
flex: 1,

View file

@ -1,15 +1,19 @@
import React, { ReactNode, useMemo, useState } from 'react';
import React, { FC, ReactNode, useMemo, useState } from 'react';
import styled, { css } from '@emotion/native';
import { LucideProps } from 'lucide-react-native';
import { Platform, StyleProp, TextStyle, View, ViewStyle } from 'react-native';
import { useAnimatedRef } from 'react-native-reanimated';
import Values from 'values.js';
import { RippleEffect } from '@procyon/components/RippleEffect';
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
import { Stack } from '@procyon/components/Stack';
import { useTheme } from '@procyon/styles/ThemeProvider';
import { isDark } from '@procyon/utils/color';
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
import { isDark } from '@procyon/styles/utils/color';
export type ButtonProps = {
LeftIcon?: FC<LucideProps>;
RightIcon?: FC<LucideProps>;
children: ReactNode;
color?: 'primary' | 'secondary' | 'positive' | 'negative';
disabled?: boolean;
@ -33,6 +37,8 @@ export const Button: React.FC<ButtonProps> = (props) => {
variant = 'contained',
fullWidth,
style,
LeftIcon,
RightIcon,
} = props;
const rippleAnimateRef = useAnimatedRef<View>();
@ -79,14 +85,18 @@ export const Button: React.FC<ButtonProps> = (props) => {
style?.container,
],
}}>
<ButtonText
variant={variant}
size={size}
color={color}
style={[style?.text]}
disabled={disabled}>
{children}
</ButtonText>
<Stack direction="row" gap={1} alignItems="center">
{LeftIcon && <LeftIcon />}
<ButtonText
variant={variant}
size={size}
color={color}
style={[style?.text]}
disabled={disabled}>
{children}
</ButtonText>
{RightIcon && <RightIcon />}
</Stack>
</RippleEffect>
</ButtonContainer>
);

View file

@ -10,7 +10,7 @@ import { Platform, StyleProp, View, ViewStyle } from 'react-native';
import { ButtonProps } from '@procyon/components/Button';
import { useTheme } from '@procyon/styles/ThemeProvider';
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
import { notNil } from '@procyon/utils/nil';
export type ButtonGroupProps = {
children: ReactNode[];
@ -29,7 +29,7 @@ export const ButtonGroup = forwardRef(
ref: MutableRefObject<View>,
) => {
const { theme } = useTheme();
const filteredChildren = children.filter((val) => !isNilOrEmpty(val));
const filteredChildren = children.filter(notNil);
return (
<View

View file

@ -6,7 +6,7 @@ import { add, endOfMonth, getWeeksInMonth, startOfMonth, sub } from 'date-fns';
import { Grid } from '@procyon/components/Grid';
import { Stack } from '@procyon/components/Stack';
import { useTheme } from '@procyon/styles/ThemeProvider';
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
import { notNil } from '@procyon/utils/nil';
import { CalendarWeek } from './CalendarWeek';
import { Controls, ControlsProps } from './Controls';
@ -189,7 +189,7 @@ export function Calendar({
return (
<Stack direction="column" gap={theme.spacing.xl}>
{!isNilOrEmpty(title) && <CalendarTitle>{title}</CalendarTitle>}
{notNil(title) && <CalendarTitle>{title}</CalendarTitle>}
<ControlsView
layout={layout}
onNextClick={handleClickNext}

View file

@ -86,7 +86,7 @@ export const DateSlot: FC<DateSlotProps> = ({
);
};
const CalendarDateContainer = styled.View<{
const CalendarDateContainer = styled(View)<{
hovered: boolean;
isOtherMonth: boolean;
isSelected: DateSlotProps['isSelected'];

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react';
import styled from '@emotion/native';
import { StyleProp, TextStyle, ViewStyle } from 'react-native';
import { StyleProp, TextStyle, View, ViewStyle } from 'react-native';
import { CalendarProps } from '@procyon/components/Calendar/index';
import { Grid } from '@procyon/components/Grid';
@ -50,7 +50,7 @@ export const WeekDays: FC<WeekDaysProps> = ({ workDate, layout, longNames, style
);
};
const CalendarWeekDaysContainer = styled.View(({ theme }) => {
const CalendarWeekDaysContainer = styled(View)(({ theme }) => {
return {
borderBottomWidth: 1,
borderColor: theme.palette.primary.dark,
@ -59,7 +59,7 @@ const CalendarWeekDaysContainer = styled.View(({ theme }) => {
};
});
const CalendarWeekDays = styled.View(() => {
const CalendarWeekDays = styled(View)(() => {
return {
alignItems: 'center',
};

View file

@ -10,7 +10,7 @@ import Animated, {
import { FieldMessage } from '@procyon/components/FieldMessage';
import { Label } from '@procyon/components/Label';
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
import { InputElementType } from '@procyon/types/form';
export type CheckboxProps<V = boolean> = Omit<
@ -137,7 +137,7 @@ const CheckboxInput = styled.Pressable<{
},
);
const CheckboxSwitch = styled.View<{
const CheckboxSwitch = styled(View)<{
checked: CheckboxProps['checked'];
color: CheckboxProps['color'];
disabled: CheckboxProps['disabled'];

View file

@ -2,7 +2,7 @@ import React, { Children, FC, ReactNode } from 'react';
import { range } from 'ramda';
import { StyleProp, View, ViewStyle } from 'react-native';
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
export type GridProps = {
children: ReactNode;

View file

@ -1,6 +1,12 @@
import React, { FC } from 'react';
import styled from '@emotion/native';
import { FlatList, GestureResponderEvent, StyleProp, ViewStyle } from 'react-native';
import {
FlatList,
GestureResponderEvent,
StyleProp,
View,
ViewStyle,
} from 'react-native';
import { ListItem, ListItemProps } from '@procyon/components/ListItem';
@ -74,7 +80,7 @@ export const List = <Items extends ListData[]>({
);
};
const ListContainer = styled.View(({ theme }) => {
const ListContainer = styled(View)(({ theme }) => {
return {
borderRadius: theme.rounded.small,
backgroundColor: theme.palette.background.main,

View file

@ -1,13 +1,13 @@
import React, { ReactNode, useMemo, useState } from 'react';
import styled from '@emotion/native';
import { GestureResponderEvent, StyleProp, View, ViewProps } from 'react-native';
import { GestureResponderEvent, StyleProp, Text, View, ViewProps } from 'react-native';
import { useAnimatedRef } from 'react-native-reanimated';
import Values from 'values.js';
import { ListData } from '@procyon/components/List';
import { RippleEffect } from '@procyon/components/RippleEffect';
import { useTheme } from '@procyon/styles/ThemeProvider';
import { isDark } from '@procyon/utils/color';
import { isDark } from '@procyon/styles/utils/color';
import { debounceAfter } from '@procyon/utils/debounce';
type CommonProps<Item extends ListData> = {
@ -125,7 +125,7 @@ const ListItemContainer = styled.Pressable<{
};
});
export const ListItemView = styled.View(() => {
export const ListItemView = styled(View)(() => {
return {
display: 'flex',
flexDirection: 'row',
@ -133,7 +133,7 @@ export const ListItemView = styled.View(() => {
};
});
export const ListItemText = styled.Text<{
export const ListItemText = styled(Text)<{
color?: ListItemProps<any, any>['color'];
hover?: boolean;
selected?: ListItemProps<any, any>['selected'];

View file

@ -1,9 +1,9 @@
import React, { useEffect } from 'react';
import styled from '@emotion/native';
import { Modal, Platform, View } from 'react-native';
import { Modal, Platform, Pressable, Text, View } from 'react-native';
import Values from 'values.js';
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
import { notNil } from '@procyon/utils/nil';
import { ModalId, useModal } from './context';
@ -33,7 +33,7 @@ export const Modals = () => {
}
}, [opened]);
if (isNilOrEmpty(opened)) {
if (!notNil(opened)) {
return null;
}
@ -49,7 +49,7 @@ export const Modals = () => {
});
};
const ModalOverflow = styled.Pressable(({ theme }) => {
const ModalOverflow = styled(Pressable)(({ theme }) => {
return {
...(Platform.OS === 'web' && ({ cursor: 'close' } as any)),
position: 'absolute',
@ -62,7 +62,7 @@ const ModalOverflow = styled.Pressable(({ theme }) => {
};
});
export const ModalContainer = styled.Pressable(({ theme }) => {
export const ModalContainer = styled(Pressable)(({ theme }) => {
return {
width: 200,
marginLeft: 'auto',
@ -76,7 +76,7 @@ export const ModalContainer = styled.Pressable(({ theme }) => {
};
});
export const ModalTitle = styled.Text(({ theme }) => {
export const ModalTitle = styled(Text)(({ theme }) => {
return {
fontSize: theme.fontSize.lg,
fontFamily: theme.fontFamily,

View file

@ -1,5 +1,6 @@
import React, { FC, useMemo, useState } from 'react';
import styled from '@emotion/native';
import { View } from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
@ -124,7 +125,7 @@ export const Puzzle: FC<PuzzleProps> = ({
);
};
const PuzzleContainer = styled.View(({ theme }) => {
const PuzzleContainer = styled(View)(({ theme }) => {
return {
position: 'relative',
borderWidth: 1,

View file

@ -4,7 +4,7 @@ import { View } from 'react-native';
import { Label } from '@procyon/components/Label';
import { RadioItem } from '@procyon/components/RadioItem';
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
import { InputElementType } from '@procyon/types/form';
import { FieldMessage } from './FieldMessage';
@ -90,7 +90,7 @@ export const RadioButton: FC<RadioButtonProps> = ({
);
};
const RadioButtonOptions = styled.View<{
const RadioButtonOptions = styled(View)<{
horizontal: RadioButtonProps['horizontal'];
}>(({ theme, horizontal }) => {
return {

View file

@ -1,7 +1,7 @@
import React, { FC, useMemo } from 'react';
import styled from '@emotion/native';
import { ChevronDownIcon } from 'lucide-react-native';
import { Platform, Pressable, StyleProp, View, ViewStyle } from 'react-native';
import { Platform, Pressable, StyleProp, Text, View, ViewStyle } from 'react-native';
import { measure, runOnJS, runOnUI, useAnimatedRef } from 'react-native-reanimated';
import { List, ListData, ListProps } from '@procyon/components/List';
@ -171,7 +171,7 @@ const DefaultInput = <Items extends ListData[]>({
return <FieldText>{getLabel ? getLabel(item) : item.label}</FieldText>;
};
export const FieldText = styled.Text<{
export const FieldText = styled(Text)<{
size?: SelectboxProps<any>['size'];
}>(({ theme, size = 'md' }) => {
return {

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react';
import styled from '@emotion/native';
import { Text } from 'react-native';
import { Text, View } from 'react-native';
import Values from 'values.js';
import { Grid, GridProps } from '@procyon/components/Grid';
@ -83,14 +83,14 @@ const TableContainer = styled(Stack)(({ theme }) => {
};
});
export const TableHead = styled.View(({ theme }) => {
export const TableHead = styled(View)(({ theme }) => {
return {
justifyContent: 'center',
padding: theme.spacing.md,
};
});
export const TableCell = styled.View(({ theme }) => {
export const TableCell = styled(View)(({ theme }) => {
return {
justifyContent: 'center',
padding: theme.spacing.md,

View file

@ -14,8 +14,8 @@ import { NativeSyntheticEvent } from 'react-native/Libraries/Types/CoreEventType
import Values from 'values.js';
import { FieldMessage } from '@procyon/components/FieldMessage';
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
import { useTheme } from '@procyon/styles/ThemeProvider';
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
import { InputElementType } from '@procyon/types/form';
import { Masked } from '@procyon/utils/imask';
@ -188,7 +188,7 @@ export const TextField: React.FC<
);
};
const TextFieldWrapper = styled.View<{
const TextFieldWrapper = styled(View)<{
color: TextFieldProps['color'];
disabled: boolean;
}>(({ theme, color, disabled }) => {
@ -200,7 +200,7 @@ const TextFieldWrapper = styled.View<{
borderRadius: theme.rounded.small,
paddingHorizontal: theme.spacing.lg,
borderWidth: 1,
borderColor: theme.palette[color!].main,
borderColor: theme.palette[color!].dark,
backgroundColor: theme.palette[color!].light,
...(color === 'secondary' && {
@ -229,7 +229,7 @@ const TextFieldInput = styled.TextInput<{
};
});
const TextFieldIconContainer = styled.View(() => {
const TextFieldIconContainer = styled(View)(() => {
return {
justifyContent: 'center',
};

View file

@ -1,7 +1,8 @@
import React, { FC } from 'react';
import styled from '@emotion/native';
import { View } from 'react-native';
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
import { notNil } from '@procyon/utils/nil';
import { Alert } from '../Alert';
import { useToaster } from './hooks';
@ -21,7 +22,7 @@ export type ToastersProps = {
export const Toasters: FC<ToastersProps> = ({ position }) => {
const { toasters } = useToaster();
if (isNilOrEmpty(toasters)) {
if (!notNil(toasters)) {
return null;
}
@ -39,7 +40,7 @@ export const Toasters: FC<ToastersProps> = ({ position }) => {
);
};
const ToastersContainer = styled.View<{
const ToastersContainer = styled(View)<{
position: ToastersProps['position'];
}>(
() => {

View file

@ -20,14 +20,10 @@
"@procyon/components": "workspace:^",
"@procyon/types": "workspace:^",
"@procyon/utils": "workspace:^",
"react-hook-form": "7.50.0"
"react-hook-form": "7.50.0",
"tiny-invariant": "1.3.3"
},
"peerDependencies": {
"@emotion/react": "^11.11.4",
"@emotion/native": "^11.11.0",
"@emotion/styled": "^11.11.5",
"yup": "1.3.3",
"clsx": "2.1.0",
"tiny-invariant": "1.3.3"
"yup": "1.3.3"
}
}

View file

@ -1,5 +1,4 @@
import React from 'react';
import styled from '@emotion/native';
import { useController, useFormContext } from 'react-hook-form';
import { Checkbox } from '@procyon/components/Checkbox';
@ -23,97 +22,79 @@ export const Field = <E extends ListData[]>({ ...props }: FieldProps<E>) => {
switch (props.component) {
case 'TEXT':
return (
<FieldWrapper>
<TextField
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
onBlur={field.onBlur}
/>
</FieldWrapper>
<TextField
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
onBlur={field.onBlur}
/>
);
case 'CHECK':
return (
<FieldWrapper>
<Checkbox
{...props}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
checked={field.value}
onChange={(e, checked) => field.onChange(checked)}
/>
</FieldWrapper>
<Checkbox
{...props}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
checked={field.value}
onChange={(e, checked) => field.onChange(checked)}
/>
);
case 'RADIO':
return (
<FieldWrapper>
<RadioButton
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}>
{props.children}
</RadioButton>
</FieldWrapper>
<RadioButton
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}>
{props.children}
</RadioButton>
);
case 'SELECT':
return (
<FieldWrapper>
<Selectbox
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
/>
</FieldWrapper>
<Selectbox
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
/>
);
case 'DATE':
return (
<FieldWrapper>
<DatePicker
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
/>
</FieldWrapper>
<DatePicker
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
/>
);
case 'TIME':
return (
<FieldWrapper>
<TimePicker
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
/>
</FieldWrapper>
<TimePicker
{...props}
value={field.value}
{...(fieldState.error && {
message: fieldState.error.message,
color: 'negative',
})}
onChange={(e, value) => field.onChange(value)}
/>
);
default:
return null;
}
};
export const FieldWrapper = styled.View(({ theme }) => {
return {
marginVertical: theme.spacing.md,
};
}) as any; // inferred type issue, IDK

View file

@ -14,8 +14,5 @@
"publishConfig": {
"directory": "dist",
"linkDirectory": false
},
"dependencies": {
"@procyon/styles": "workspace:^"
}
}

View file

@ -1,22 +0,0 @@
import { useEffect, useState } from 'react';
import { Dimensions } from 'react-native';
export function useScreenDimensions(): { height: number; width: number } {
const initialDimensions = Dimensions.get('screen');
const [width, setWidth] = useState(initialDimensions.width);
const [height, setHeight] = useState(initialDimensions.height);
const handleChange = ({ screen }) => {
setWidth(screen.width);
setHeight(screen.height);
};
useEffect(() => {
const sub = Dimensions.addEventListener('change', handleChange);
return () => {
sub.remove();
};
}, []);
return { width, height };
}

View file

@ -5,7 +5,7 @@
"author": "romanjaros <jarosr93@gmail.com>",
"license": "ISC",
"scripts": {
"clean": "rm -rf dist/",
"clean": "rm -rf dist/ && npm run build -- --clean",
"build": "tsc --b tsconfig.build.json",
"prepublish": "cp package.json dist",
"postpublish": "rm dist/package.json",
@ -14,13 +14,5 @@
"publishConfig": {
"directory": "dist",
"linkDirectory": false
},
"dependencies": {
"postcss-import": "16.0.0",
"postcss-nested": "6.0.1"
},
"peerDependencies": {
"postcss": "8.4.33",
"tailwindcss": "3.4.1"
}
}

View file

@ -1,32 +0,0 @@
import { Theme } from '@emotion/react';
import { Dimensions, StyleProp, TextStyle, ViewStyle } from 'react-native';
type StyleProps = StyleProp<ViewStyle | TextStyle>;
// Function to apply style based on dimension constraints
const applyStyleIfWithinRange = (value: number, nextValue: number, style: StyleProps) => {
const windowWidth = Dimensions.get('window').width;
if (value <= windowWidth && (nextValue >= windowWidth || value === nextValue)) {
return style;
}
return null;
};
export const mQ = (theme: Theme) => {
const brs = theme.breakpoints;
// Use Object.entries and reduce to create the 'breakpoints' object
return Object.entries(brs).reduce(
(acc, [key, value], i, entries) => {
// Get next breakpoint value, and default to the last breakpoint value in case of undefined
const nextValue = brs[entries[i + 1]?.[0]] ?? Object.values(brs).at(-1);
// Assign computed function to the respective breakpoint key in the accumulator object
acc[key] = (style: StyleProps) => applyStyleIfWithinRange(value, nextValue, style);
// Return
return acc;
},
{} as Record<keyof Theme['breakpoints'], (style: StyleProp<ViewStyle>) => object>,
);
};

View file

@ -1,3 +1,5 @@
import Values from 'values.js';
type RGB = [number, number, number];
type HSL = [number, number, number];
@ -84,3 +86,7 @@ export function getContrastColor(rgb: RGB): string {
const contrastRGB = HSLToRGB(hsl);
return contrastRGB.map((v) => v.toString(16).padStart(2, '0')).join('');
}
export const isDark = (color: string) => {
return new Values(color).getBrightness() <= 55;
};

View file

@ -14,6 +14,5 @@
"publishConfig": {
"directory": "dist",
"linkDirectory": false
},
"peerDependencies": {}
}
}

View file

@ -16,7 +16,6 @@
"linkDirectory": false
},
"dependencies": {
"@types/vanilla-masker": "1.2.4",
"imask": "7.6.1"
},
"peerDependencies": {

View file

@ -1,5 +0,0 @@
import Values from 'values.js';
export const isDark = (color: string) => {
return new Values(color).getBrightness() <= 55;
};

View file

@ -1,3 +0,0 @@
import { either, isEmpty, isNil } from 'ramda';
export const isNilOrEmpty = either(isNil, isEmpty);

View file

@ -0,0 +1,3 @@
export function notNil<TValue>(value: TValue | null | undefined): value is TValue {
return value !== null && value !== undefined;
}

7271
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,6 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { DeleteIcon, LogOutIcon } from 'lucide-react-native';
import { Text as RnText } from 'react-native';
import { Button } from '@procyon/components/Button';
import { T } from '@procyon/localization/tolgee';
@ -87,13 +86,10 @@ export const LabelAsIcon: Story = {
};
export const LabelWithIcon: Story = {
args: {},
render: (args) => (
<Button {...args}>
<LogOutIcon />
<RnText>Logout</RnText>
</Button>
),
args: {
LeftIcon: (props) => <LogOutIcon />,
},
render: (args) => <Button {...args}>Logout</Button>,
};
export const ExtraLargeSize: Story = {

View file

@ -7,7 +7,7 @@ import { Grid } from '@procyon/components/Grid';
import { Puzzle } from '@procyon/components/Puzzle';
import { RadioItem } from '@procyon/components/RadioItem';
import { Stack } from '@procyon/components/Stack';
import { Field, FieldWrapper } from '@procyon/forms/Field';
import { Field } from '@procyon/forms/Field';
import { Form } from '@procyon/forms/Form';
import { useForm } from '@procyon/forms/useForm';
@ -76,9 +76,7 @@ export const ExampleForm = () => {
<Field component="DATE" name="datePicker" label="DatePicker" />
<Field component="TIME" name="timePicker" label="TimePicker" />
</Grid>
<FieldWrapper>
<Puzzle onVerified={() => null} />
</FieldWrapper>
<Puzzle onVerified={() => null} />
<Grid cols={{ sm: 2 }} gap={10}>
<View />
<Button fullWidth onClick={formMethods.handleSubmit(onSubmit)}>