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
Some checks failed
forgejo/Procyon/procyon/pipeline/head There was a failure building this commit
This commit is contained in:
parent
deebdb261d
commit
cda0d4569f
39 changed files with 2963 additions and 4872 deletions
|
@ -18,7 +18,7 @@ import {
|
||||||
import { TolgeeChain, TolgeeProvider, useTolgee } from '@procyon/localization/tolgee';
|
import { TolgeeChain, TolgeeProvider, useTolgee } from '@procyon/localization/tolgee';
|
||||||
import { buildColorTheme } from '@procyon/styles/theme/color';
|
import { buildColorTheme } from '@procyon/styles/theme/color';
|
||||||
import { baseTheme } from '@procyon/styles/theme/base';
|
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 { ModalProvider } from '@procyon/components/Modal/context';
|
||||||
import { Modals } from '@procyon/components/Modal';
|
import { Modals } from '@procyon/components/Modal';
|
||||||
import { Theme } from '@emotion/react';
|
import { Theme } from '@emotion/react';
|
||||||
|
|
77
package.json
77
package.json
|
@ -26,77 +26,70 @@
|
||||||
"test": "jest --passWithNoTests"
|
"test": "jest --passWithNoTests"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.11.4",
|
|
||||||
"@emotion/native": "^11.11.0",
|
"@emotion/native": "^11.11.0",
|
||||||
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.5",
|
"@emotion/styled": "^11.11.5",
|
||||||
"clsx": "2.1.0",
|
|
||||||
"date-fns": "3.3.1",
|
"date-fns": "3.3.1",
|
||||||
"postcss": "8.4.33",
|
"lucide-react-native": "^0.402.0",
|
||||||
"ramda": "0.29.1",
|
"ramda": "0.29.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-native": "0.74.1",
|
"react-native": "0.74.1",
|
||||||
"react-native-advanced-ripple": "1.0.0",
|
"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-reanimated": "3.7.0",
|
||||||
"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.1.0",
|
||||||
"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": "3.3.1",
|
||||||
"yup": "1.3.3"
|
"yup": "1.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "7.23.9",
|
"@babel/core": "7.24.7",
|
||||||
"@babel/preset-env": "^7.23.9",
|
"@babel/preset-env": "^7.24.7",
|
||||||
"@babel/preset-typescript": "7.23.3",
|
"@babel/preset-typescript": "7.24.7",
|
||||||
"@storybook/addon-actions": "^8.1.5",
|
"@storybook/addon-actions": "^8.1.11",
|
||||||
"@storybook/addon-essentials": "^8.1.5",
|
"@storybook/addon-essentials": "^8.1.11",
|
||||||
"@storybook/addon-links": "^8.1.5",
|
"@storybook/addon-links": "^8.1.11",
|
||||||
"@storybook/addon-mdx-gfm": "^8.1.5",
|
"@storybook/addon-mdx-gfm": "^8.1.11",
|
||||||
"@storybook/addon-react-native-web": "0.0.23",
|
"@storybook/addon-react-native-web": "0.0.24",
|
||||||
"@storybook/addon-viewport": "^8.1.5",
|
"@storybook/addon-viewport": "^8.1.11",
|
||||||
"@storybook/addon-webpack5-compiler-babel": "^3.0.3",
|
"@storybook/addon-webpack5-compiler-babel": "^3.0.3",
|
||||||
"@storybook/blocks": "^8.1.5",
|
"@storybook/blocks": "^8.1.11",
|
||||||
"@storybook/manager-api": "^8.1.5",
|
"@storybook/manager-api": "^8.1.11",
|
||||||
"@storybook/react": "^8.1.5",
|
"@storybook/react": "^8.1.11",
|
||||||
"@storybook/react-native": "7.6.19",
|
"@storybook/react-native": "7.6.20",
|
||||||
"@storybook/react-webpack5": "^8.1.5",
|
"@storybook/react-webpack5": "^8.1.11",
|
||||||
"@storybook/types": "^8.1.5",
|
"@storybook/types": "^8.1.11",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "29.5.12",
|
||||||
"@types/mdx": "2.0.10",
|
"@types/mdx": "2.0.13",
|
||||||
"@types/node": "18.18.2",
|
"@types/node": "20.14.10",
|
||||||
"@types/ramda": "0.29.10",
|
"@types/ramda": "0.30.1",
|
||||||
"@types/react": "18.2.52",
|
"@types/react": "18.3.3",
|
||||||
"@types/react-dom": "18.2.18",
|
"@types/react-dom": "18.3.0",
|
||||||
"@types/yup": "0.29.14",
|
"@typescript-eslint/eslint-plugin": "7.15.0",
|
||||||
"@typescript-eslint/eslint-plugin": "6.20.0",
|
"@typescript-eslint/parser": "7.15.0",
|
||||||
"@typescript-eslint/parser": "6.20.0",
|
"autoprefixer": "10.4.19",
|
||||||
"autoprefixer": "10.4.17",
|
|
||||||
"babel-loader": "^9.1.3",
|
"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",
|
"cross-env": "7.0.3",
|
||||||
"eslint": "8.56.0",
|
"eslint": "8.56.0",
|
||||||
"eslint-config-prettier": "9.1.0",
|
"eslint-config-prettier": "9.1.0",
|
||||||
"eslint-plugin-import": "2.29.1",
|
"eslint-plugin-import": "2.29.1",
|
||||||
"eslint-plugin-mdx": "3.1.5",
|
"eslint-plugin-mdx": "3.1.5",
|
||||||
"eslint-plugin-react": "7.33.2",
|
"eslint-plugin-react": "7.34.3",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.2",
|
||||||
"eslint-plugin-simple-import-sort": "10.0.0",
|
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||||
"eslint-plugin-typescript-sort-keys": "3.1.0",
|
"eslint-plugin-typescript-sort-keys": "3.2.0",
|
||||||
"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",
|
||||||
"nightwatch": "3.3.5",
|
"prettier": "3.3.2",
|
||||||
"postcss-cli": "11.0.0",
|
|
||||||
"postcss-loader": "8.1.0",
|
|
||||||
"prettier": "3.2.4",
|
|
||||||
"raw-loader": "4.0.2",
|
"raw-loader": "4.0.2",
|
||||||
"storybook": "^8.1.5",
|
"storybook": "^8.1.5",
|
||||||
"tailwindcss": "3.4.1",
|
"ts-jest": "29.1.5",
|
||||||
"ts-jest": "29.1.2",
|
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typescript": "5.3.3"
|
"typescript": "5.3.3"
|
||||||
|
|
|
@ -16,12 +16,6 @@
|
||||||
"linkDirectory": false
|
"linkDirectory": false
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@procyon/auth": "workspace:^",
|
"@procyon/auth": "workspace:^"
|
||||||
"@procyon/types": "workspace:^",
|
|
||||||
"@procyon/utils": "workspace:^",
|
|
||||||
"async-mutex": "0.4.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@reduxjs/toolkit": "2.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,5 @@
|
||||||
{
|
{
|
||||||
"path": "../auth/tsconfig.build.json"
|
"path": "../auth/tsconfig.build.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "../utils/tsconfig.build.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "../types/tsconfig.build.json"
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
}
|
}
|
|
@ -20,18 +20,16 @@
|
||||||
"@procyon/localization": "workspace:^",
|
"@procyon/localization": "workspace:^",
|
||||||
"@procyon/types": "workspace:^",
|
"@procyon/types": "workspace:^",
|
||||||
"@procyon/utils": "workspace:^",
|
"@procyon/utils": "workspace:^",
|
||||||
"@procyon/styles": "workspace:^"
|
"@procyon/styles": "workspace:^",
|
||||||
|
"values.js": "^2.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@emotion/react": "^11.11.4",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/native": "^11.11.0",
|
|
||||||
"@emotion/styled": "^11.11.5",
|
"@emotion/styled": "^11.11.5",
|
||||||
"clsx": "2.1.0",
|
"@emotion/native": "^11.11.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",
|
"lucide-react-native": "^0.379.0",
|
||||||
"react-native-reanimated": "3.7.0",
|
"react-native-reanimated": "3.7.0"
|
||||||
"react-native-svg": "15.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'];
|
color: AlertProps['color'];
|
||||||
}>(({ theme, color }) => {
|
}>(({ theme, color }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { FC, ReactNode, useState } from 'react';
|
import React, { FC, ReactNode, useState } from 'react';
|
||||||
import styled from '@emotion/native';
|
import styled from '@emotion/native';
|
||||||
|
import { Theme } from '@emotion/react';
|
||||||
import { MenuIcon } from 'lucide-react-native';
|
import { MenuIcon } from 'lucide-react-native';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
|
||||||
import { Modals } from '@procyon/components/Modal/Modals';
|
import { Modals } from '@procyon/components/Modal/Modals';
|
||||||
import { Toasters } from '@procyon/components/Toaster';
|
import { Toasters } from '@procyon/components/Toaster';
|
||||||
import { ToastersProps } from '@procyon/components/Toaster/Toasters';
|
import { ToastersProps } from '@procyon/components/Toaster/Toasters';
|
||||||
import { useScreenDimensions } from '@procyon/hooks/useScreenDimensions';
|
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
|
||||||
import { mQ } from '@procyon/styles/mq';
|
|
||||||
|
|
||||||
export type AppLayoutProps = {
|
export type AppLayoutProps = {
|
||||||
Footer?: FC;
|
Footer?: FC;
|
||||||
|
@ -31,7 +31,7 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
||||||
const enabledSideNav = !!SideNav;
|
const enabledSideNav = !!SideNav;
|
||||||
const enabledTopNav = !!TopNav || !!UserNav;
|
const enabledTopNav = !!TopNav || !!UserNav;
|
||||||
|
|
||||||
useScreenDimensions();
|
const mq = useMediaQuery();
|
||||||
|
|
||||||
const [sideCollapsed, setSideCollapsed] = useState(false);
|
const [sideCollapsed, setSideCollapsed] = useState(false);
|
||||||
const [topCollapsed, setTopCollapsed] = useState(true);
|
const [topCollapsed, setTopCollapsed] = useState(true);
|
||||||
|
@ -47,10 +47,11 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
||||||
return (
|
return (
|
||||||
<AppLayoutContainer>
|
<AppLayoutContainer>
|
||||||
{enabledTopNav && (
|
{enabledTopNav && (
|
||||||
<AppLayoutTopNav onPress={toggleTop}>
|
<AppLayoutTopNav mq={mq} onPress={toggleTop}>
|
||||||
<AppLayoutTopLeftSide placeholder={!Logo}>
|
<AppLayoutTopLeftSide mq={mq} placeholder={!Logo}>
|
||||||
<AppLayoutLogo>{Logo ?? <View />}</AppLayoutLogo>
|
<AppLayoutLogo>{Logo ?? <View />}</AppLayoutLogo>
|
||||||
<AppLayoutMenuToggle
|
<AppLayoutMenuToggle
|
||||||
|
mq={mq}
|
||||||
style={{
|
style={{
|
||||||
marginBottom: 2,
|
marginBottom: 2,
|
||||||
}}
|
}}
|
||||||
|
@ -58,12 +59,14 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
||||||
/>
|
/>
|
||||||
</AppLayoutTopLeftSide>
|
</AppLayoutTopLeftSide>
|
||||||
<AppLayoutNavSection
|
<AppLayoutNavSection
|
||||||
|
mq={mq}
|
||||||
visible={!topCollapsed}
|
visible={!topCollapsed}
|
||||||
direction="row"
|
direction="row"
|
||||||
justifyContent="flex-start">
|
justifyContent="flex-start">
|
||||||
{TopNav?.map((Nav: any, i) => <Nav key={i} />)}
|
{TopNav?.map((Nav: any, i) => <Nav key={i} />)}
|
||||||
</AppLayoutNavSection>
|
</AppLayoutNavSection>
|
||||||
<AppLayoutNavSection
|
<AppLayoutNavSection
|
||||||
|
mq={mq}
|
||||||
visible={!topCollapsed}
|
visible={!topCollapsed}
|
||||||
direction="row"
|
direction="row"
|
||||||
justifyContent="flex-end">
|
justifyContent="flex-end">
|
||||||
|
@ -71,11 +74,12 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
||||||
</AppLayoutNavSection>
|
</AppLayoutNavSection>
|
||||||
</AppLayoutTopNav>
|
</AppLayoutTopNav>
|
||||||
)}
|
)}
|
||||||
<AppLayoutContent>
|
<AppLayoutContent mq={mq}>
|
||||||
{enabledSideNav && (
|
{enabledSideNav && (
|
||||||
<AppLayoutSideNav onPress={toggleSide}>
|
<AppLayoutSideNav mq={mq} onPress={toggleSide}>
|
||||||
<AppLayoutMenuToggle style={{ minWidth: 30 }} strokeWidth={1} />
|
<AppLayoutMenuToggle mq={mq} style={{ minWidth: 30 }} strokeWidth={1} />
|
||||||
<AppLayoutNavSection
|
<AppLayoutNavSection
|
||||||
|
mq={mq}
|
||||||
visible={sideCollapsed}
|
visible={sideCollapsed}
|
||||||
direction="column"
|
direction="column"
|
||||||
justifyContent="center">
|
justifyContent="center">
|
||||||
|
@ -92,25 +96,25 @@ export const AppLayout: React.FC<AppLayoutProps> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppLayoutContainer = styled.View(({ theme }) => {
|
const AppLayoutContainer = styled(View)(({ theme }) => {
|
||||||
return {
|
return {
|
||||||
backgroundColor: theme.palette.background.main,
|
backgroundColor: theme.palette.background.main,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppLayoutNavSection = styled.View<{
|
const AppLayoutNavSection = styled(View)<{
|
||||||
direction: 'row' | 'column';
|
direction: 'row' | 'column';
|
||||||
justifyContent: 'flex-start' | 'center' | 'flex-end';
|
justifyContent: 'flex-start' | 'center' | 'flex-end';
|
||||||
|
mq: keyof Theme['breakpoints'];
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
}>(({ theme, direction, visible, justifyContent }) => {
|
}>(({ theme, direction, visible, justifyContent, mq }) => {
|
||||||
const br = mQ(theme);
|
|
||||||
return {
|
return {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: direction,
|
flexDirection: direction,
|
||||||
columnGap: 4,
|
columnGap: 4,
|
||||||
rowGap: 4,
|
rowGap: 4,
|
||||||
|
|
||||||
...br.xs({
|
...(mq === 'xs' && {
|
||||||
marginTop: theme.spacing.sm,
|
marginTop: theme.spacing.sm,
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -124,34 +128,35 @@ const AppLayoutNavSection = styled.View<{
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppLayoutTopNav = styled.Pressable(({ theme }) => {
|
const AppLayoutTopNav = styled.Pressable<{ mq: keyof Theme['breakpoints'] }>(
|
||||||
const br = mQ(theme);
|
({ theme, mq }) => {
|
||||||
return {
|
return {
|
||||||
backgroundColor: theme.palette.primary.light,
|
backgroundColor: theme.palette.primary.light,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
columnGap: 4,
|
columnGap: 4,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: theme.spacing.sm,
|
padding: theme.spacing.sm,
|
||||||
|
|
||||||
...br.xs({
|
...(mq === 'xs' && {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'stretch',
|
alignItems: 'stretch',
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const AppLayoutTopLeftSide = styled.View<{
|
const AppLayoutTopLeftSide = styled(View)<{
|
||||||
|
mq: keyof Theme['breakpoints'];
|
||||||
placeholder: boolean;
|
placeholder: boolean;
|
||||||
}>(({ theme, placeholder }) => {
|
}>(({ placeholder, mq }) => {
|
||||||
const br = mQ(theme);
|
|
||||||
return {
|
return {
|
||||||
...(placeholder && {
|
...(placeholder && {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
...br.xs({
|
...(mq === 'xs' && {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
|
@ -168,33 +173,36 @@ const AppLayoutLogo = styled.Text(({ theme }) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppLayoutMenuToggle = styled(MenuIcon)(({ theme }) => {
|
const AppLayoutMenuToggle = styled(MenuIcon)<{
|
||||||
const br = mQ(theme);
|
mq: keyof Theme['breakpoints'];
|
||||||
|
}>(({ mq }) => {
|
||||||
return {
|
return {
|
||||||
display: 'none',
|
display: 'none',
|
||||||
...br.xs({
|
...(mq === 'xs' && {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppLayoutContent = styled.View(({ theme }) => {
|
const AppLayoutContent = styled(View)<{
|
||||||
const br = mQ(theme);
|
mq: keyof Theme['breakpoints'];
|
||||||
|
}>(({ theme, mq }) => {
|
||||||
return {
|
return {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
gap: 4,
|
gap: 4,
|
||||||
marginTop: theme.spacing.md,
|
marginTop: theme.spacing.md,
|
||||||
|
|
||||||
...br.xs({
|
...(mq === 'xs' && {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
marginTop: theme.spacing.sm,
|
marginTop: theme.spacing.sm,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppLayoutSideNav = styled.Pressable(({ theme }) => {
|
const AppLayoutSideNav = styled.Pressable<{
|
||||||
const br = mQ(theme);
|
mq: keyof Theme['breakpoints'];
|
||||||
|
}>(({ theme, mq }) => {
|
||||||
return {
|
return {
|
||||||
width: 150,
|
width: 150,
|
||||||
borderRadius: theme.rounded.small,
|
borderRadius: theme.rounded.small,
|
||||||
|
@ -206,7 +214,7 @@ const AppLayoutSideNav = styled.Pressable(({ theme }) => {
|
||||||
padding: theme.spacing.sm,
|
padding: theme.spacing.sm,
|
||||||
marginRight: 2,
|
marginRight: 2,
|
||||||
|
|
||||||
...br.xs({
|
...(mq === 'xs' && {
|
||||||
width: 'auto',
|
width: 'auto',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
|
@ -215,7 +223,7 @@ const AppLayoutSideNav = styled.Pressable(({ theme }) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const AppLayoutPage = styled.View(({ theme }) => {
|
const AppLayoutPage = styled(View)(({ theme }) => {
|
||||||
return {
|
return {
|
||||||
padding: theme.spacing.md,
|
padding: theme.spacing.md,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|
|
@ -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 styled, { css } from '@emotion/native';
|
||||||
|
import { LucideProps } from 'lucide-react-native';
|
||||||
import { Platform, StyleProp, TextStyle, View, ViewStyle } from 'react-native';
|
import { Platform, StyleProp, TextStyle, View, ViewStyle } from 'react-native';
|
||||||
import { useAnimatedRef } from 'react-native-reanimated';
|
import { useAnimatedRef } from 'react-native-reanimated';
|
||||||
import Values from 'values.js';
|
import Values from 'values.js';
|
||||||
|
|
||||||
import { RippleEffect } from '@procyon/components/RippleEffect';
|
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 { 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 = {
|
export type ButtonProps = {
|
||||||
|
LeftIcon?: FC<LucideProps>;
|
||||||
|
RightIcon?: FC<LucideProps>;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
color?: 'primary' | 'secondary' | 'positive' | 'negative';
|
color?: 'primary' | 'secondary' | 'positive' | 'negative';
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
@ -33,6 +37,8 @@ export const Button: React.FC<ButtonProps> = (props) => {
|
||||||
variant = 'contained',
|
variant = 'contained',
|
||||||
fullWidth,
|
fullWidth,
|
||||||
style,
|
style,
|
||||||
|
LeftIcon,
|
||||||
|
RightIcon,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const rippleAnimateRef = useAnimatedRef<View>();
|
const rippleAnimateRef = useAnimatedRef<View>();
|
||||||
|
@ -79,14 +85,18 @@ export const Button: React.FC<ButtonProps> = (props) => {
|
||||||
style?.container,
|
style?.container,
|
||||||
],
|
],
|
||||||
}}>
|
}}>
|
||||||
<ButtonText
|
<Stack direction="row" gap={1} alignItems="center">
|
||||||
variant={variant}
|
{LeftIcon && <LeftIcon />}
|
||||||
size={size}
|
<ButtonText
|
||||||
color={color}
|
variant={variant}
|
||||||
style={[style?.text]}
|
size={size}
|
||||||
disabled={disabled}>
|
color={color}
|
||||||
{children}
|
style={[style?.text]}
|
||||||
</ButtonText>
|
disabled={disabled}>
|
||||||
|
{children}
|
||||||
|
</ButtonText>
|
||||||
|
{RightIcon && <RightIcon />}
|
||||||
|
</Stack>
|
||||||
</RippleEffect>
|
</RippleEffect>
|
||||||
</ButtonContainer>
|
</ButtonContainer>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { Platform, StyleProp, View, ViewStyle } from 'react-native';
|
||||||
|
|
||||||
import { ButtonProps } from '@procyon/components/Button';
|
import { ButtonProps } from '@procyon/components/Button';
|
||||||
import { useTheme } from '@procyon/styles/ThemeProvider';
|
import { useTheme } from '@procyon/styles/ThemeProvider';
|
||||||
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
|
import { notNil } from '@procyon/utils/nil';
|
||||||
|
|
||||||
export type ButtonGroupProps = {
|
export type ButtonGroupProps = {
|
||||||
children: ReactNode[];
|
children: ReactNode[];
|
||||||
|
@ -29,7 +29,7 @@ export const ButtonGroup = forwardRef(
|
||||||
ref: MutableRefObject<View>,
|
ref: MutableRefObject<View>,
|
||||||
) => {
|
) => {
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const filteredChildren = children.filter((val) => !isNilOrEmpty(val));
|
const filteredChildren = children.filter(notNil);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { add, endOfMonth, getWeeksInMonth, startOfMonth, sub } from 'date-fns';
|
||||||
import { Grid } from '@procyon/components/Grid';
|
import { Grid } from '@procyon/components/Grid';
|
||||||
import { Stack } from '@procyon/components/Stack';
|
import { Stack } from '@procyon/components/Stack';
|
||||||
import { useTheme } from '@procyon/styles/ThemeProvider';
|
import { useTheme } from '@procyon/styles/ThemeProvider';
|
||||||
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
|
import { notNil } from '@procyon/utils/nil';
|
||||||
|
|
||||||
import { CalendarWeek } from './CalendarWeek';
|
import { CalendarWeek } from './CalendarWeek';
|
||||||
import { Controls, ControlsProps } from './Controls';
|
import { Controls, ControlsProps } from './Controls';
|
||||||
|
@ -189,7 +189,7 @@ export function Calendar({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack direction="column" gap={theme.spacing.xl}>
|
<Stack direction="column" gap={theme.spacing.xl}>
|
||||||
{!isNilOrEmpty(title) && <CalendarTitle>{title}</CalendarTitle>}
|
{notNil(title) && <CalendarTitle>{title}</CalendarTitle>}
|
||||||
<ControlsView
|
<ControlsView
|
||||||
layout={layout}
|
layout={layout}
|
||||||
onNextClick={handleClickNext}
|
onNextClick={handleClickNext}
|
||||||
|
|
|
@ -86,7 +86,7 @@ export const DateSlot: FC<DateSlotProps> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CalendarDateContainer = styled.View<{
|
const CalendarDateContainer = styled(View)<{
|
||||||
hovered: boolean;
|
hovered: boolean;
|
||||||
isOtherMonth: boolean;
|
isOtherMonth: boolean;
|
||||||
isSelected: DateSlotProps['isSelected'];
|
isSelected: DateSlotProps['isSelected'];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import styled from '@emotion/native';
|
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 { CalendarProps } from '@procyon/components/Calendar/index';
|
||||||
import { Grid } from '@procyon/components/Grid';
|
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 {
|
return {
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderColor: theme.palette.primary.dark,
|
borderColor: theme.palette.primary.dark,
|
||||||
|
@ -59,7 +59,7 @@ const CalendarWeekDaysContainer = styled.View(({ theme }) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const CalendarWeekDays = styled.View(() => {
|
const CalendarWeekDays = styled(View)(() => {
|
||||||
return {
|
return {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Animated, {
|
||||||
|
|
||||||
import { FieldMessage } from '@procyon/components/FieldMessage';
|
import { FieldMessage } from '@procyon/components/FieldMessage';
|
||||||
import { Label } from '@procyon/components/Label';
|
import { Label } from '@procyon/components/Label';
|
||||||
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
|
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
|
||||||
import { InputElementType } from '@procyon/types/form';
|
import { InputElementType } from '@procyon/types/form';
|
||||||
|
|
||||||
export type CheckboxProps<V = boolean> = Omit<
|
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'];
|
checked: CheckboxProps['checked'];
|
||||||
color: CheckboxProps['color'];
|
color: CheckboxProps['color'];
|
||||||
disabled: CheckboxProps['disabled'];
|
disabled: CheckboxProps['disabled'];
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { Children, FC, ReactNode } from 'react';
|
||||||
import { range } from 'ramda';
|
import { range } from 'ramda';
|
||||||
import { StyleProp, View, ViewStyle } from 'react-native';
|
import { StyleProp, View, ViewStyle } from 'react-native';
|
||||||
|
|
||||||
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
|
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
|
||||||
|
|
||||||
export type GridProps = {
|
export type GridProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import styled from '@emotion/native';
|
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';
|
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 {
|
return {
|
||||||
borderRadius: theme.rounded.small,
|
borderRadius: theme.rounded.small,
|
||||||
backgroundColor: theme.palette.background.main,
|
backgroundColor: theme.palette.background.main,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { ReactNode, useMemo, useState } from 'react';
|
import React, { ReactNode, useMemo, useState } from 'react';
|
||||||
import styled from '@emotion/native';
|
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 { useAnimatedRef } from 'react-native-reanimated';
|
||||||
import Values from 'values.js';
|
import Values from 'values.js';
|
||||||
|
|
||||||
import { ListData } from '@procyon/components/List';
|
import { ListData } from '@procyon/components/List';
|
||||||
import { RippleEffect } from '@procyon/components/RippleEffect';
|
import { RippleEffect } from '@procyon/components/RippleEffect';
|
||||||
import { useTheme } from '@procyon/styles/ThemeProvider';
|
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';
|
import { debounceAfter } from '@procyon/utils/debounce';
|
||||||
|
|
||||||
type CommonProps<Item extends ListData> = {
|
type CommonProps<Item extends ListData> = {
|
||||||
|
@ -125,7 +125,7 @@ const ListItemContainer = styled.Pressable<{
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ListItemView = styled.View(() => {
|
export const ListItemView = styled(View)(() => {
|
||||||
return {
|
return {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
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'];
|
color?: ListItemProps<any, any>['color'];
|
||||||
hover?: boolean;
|
hover?: boolean;
|
||||||
selected?: ListItemProps<any, any>['selected'];
|
selected?: ListItemProps<any, any>['selected'];
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import styled from '@emotion/native';
|
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 Values from 'values.js';
|
||||||
|
|
||||||
import { isNilOrEmpty } from '@procyon/utils/isNilOrEmpty';
|
import { notNil } from '@procyon/utils/nil';
|
||||||
|
|
||||||
import { ModalId, useModal } from './context';
|
import { ModalId, useModal } from './context';
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export const Modals = () => {
|
||||||
}
|
}
|
||||||
}, [opened]);
|
}, [opened]);
|
||||||
|
|
||||||
if (isNilOrEmpty(opened)) {
|
if (!notNil(opened)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ export const Modals = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModalOverflow = styled.Pressable(({ theme }) => {
|
const ModalOverflow = styled(Pressable)(({ theme }) => {
|
||||||
return {
|
return {
|
||||||
...(Platform.OS === 'web' && ({ cursor: 'close' } as any)),
|
...(Platform.OS === 'web' && ({ cursor: 'close' } as any)),
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
@ -62,7 +62,7 @@ const ModalOverflow = styled.Pressable(({ theme }) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ModalContainer = styled.Pressable(({ theme }) => {
|
export const ModalContainer = styled(Pressable)(({ theme }) => {
|
||||||
return {
|
return {
|
||||||
width: 200,
|
width: 200,
|
||||||
marginLeft: 'auto',
|
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 {
|
return {
|
||||||
fontSize: theme.fontSize.lg,
|
fontSize: theme.fontSize.lg,
|
||||||
fontFamily: theme.fontFamily,
|
fontFamily: theme.fontFamily,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { FC, useMemo, useState } from 'react';
|
import React, { FC, useMemo, useState } from 'react';
|
||||||
import styled from '@emotion/native';
|
import styled from '@emotion/native';
|
||||||
|
import { View } from 'react-native';
|
||||||
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
||||||
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
|
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 {
|
return {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { View } from 'react-native';
|
||||||
|
|
||||||
import { Label } from '@procyon/components/Label';
|
import { Label } from '@procyon/components/Label';
|
||||||
import { RadioItem } from '@procyon/components/RadioItem';
|
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 { InputElementType } from '@procyon/types/form';
|
||||||
|
|
||||||
import { FieldMessage } from './FieldMessage';
|
import { FieldMessage } from './FieldMessage';
|
||||||
|
@ -90,7 +90,7 @@ export const RadioButton: FC<RadioButtonProps> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RadioButtonOptions = styled.View<{
|
const RadioButtonOptions = styled(View)<{
|
||||||
horizontal: RadioButtonProps['horizontal'];
|
horizontal: RadioButtonProps['horizontal'];
|
||||||
}>(({ theme, horizontal }) => {
|
}>(({ theme, horizontal }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { FC, useMemo } from 'react';
|
import React, { FC, useMemo } from 'react';
|
||||||
import styled from '@emotion/native';
|
import styled from '@emotion/native';
|
||||||
import { ChevronDownIcon } from 'lucide-react-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 { measure, runOnJS, runOnUI, useAnimatedRef } from 'react-native-reanimated';
|
||||||
|
|
||||||
import { List, ListData, ListProps } from '@procyon/components/List';
|
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>;
|
return <FieldText>{getLabel ? getLabel(item) : item.label}</FieldText>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FieldText = styled.Text<{
|
export const FieldText = styled(Text)<{
|
||||||
size?: SelectboxProps<any>['size'];
|
size?: SelectboxProps<any>['size'];
|
||||||
}>(({ theme, size = 'md' }) => {
|
}>(({ theme, size = 'md' }) => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import styled from '@emotion/native';
|
import styled from '@emotion/native';
|
||||||
import { Text } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import Values from 'values.js';
|
import Values from 'values.js';
|
||||||
|
|
||||||
import { Grid, GridProps } from '@procyon/components/Grid';
|
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 {
|
return {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
padding: theme.spacing.md,
|
padding: theme.spacing.md,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const TableCell = styled.View(({ theme }) => {
|
export const TableCell = styled(View)(({ theme }) => {
|
||||||
return {
|
return {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
padding: theme.spacing.md,
|
padding: theme.spacing.md,
|
||||||
|
|
|
@ -14,8 +14,8 @@ import { NativeSyntheticEvent } from 'react-native/Libraries/Types/CoreEventType
|
||||||
import Values from 'values.js';
|
import Values from 'values.js';
|
||||||
|
|
||||||
import { FieldMessage } from '@procyon/components/FieldMessage';
|
import { FieldMessage } from '@procyon/components/FieldMessage';
|
||||||
import { useMediaQuery } from '@procyon/hooks/useMediaQuery';
|
|
||||||
import { useTheme } from '@procyon/styles/ThemeProvider';
|
import { useTheme } from '@procyon/styles/ThemeProvider';
|
||||||
|
import { useMediaQuery } from '@procyon/styles/useMediaQuery';
|
||||||
import { InputElementType } from '@procyon/types/form';
|
import { InputElementType } from '@procyon/types/form';
|
||||||
import { Masked } from '@procyon/utils/imask';
|
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'];
|
color: TextFieldProps['color'];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
}>(({ theme, color, disabled }) => {
|
}>(({ theme, color, disabled }) => {
|
||||||
|
@ -200,7 +200,7 @@ const TextFieldWrapper = styled.View<{
|
||||||
borderRadius: theme.rounded.small,
|
borderRadius: theme.rounded.small,
|
||||||
paddingHorizontal: theme.spacing.lg,
|
paddingHorizontal: theme.spacing.lg,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderColor: theme.palette[color!].main,
|
borderColor: theme.palette[color!].dark,
|
||||||
backgroundColor: theme.palette[color!].light,
|
backgroundColor: theme.palette[color!].light,
|
||||||
|
|
||||||
...(color === 'secondary' && {
|
...(color === 'secondary' && {
|
||||||
|
@ -229,7 +229,7 @@ const TextFieldInput = styled.TextInput<{
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const TextFieldIconContainer = styled.View(() => {
|
const TextFieldIconContainer = styled(View)(() => {
|
||||||
return {
|
return {
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import styled from '@emotion/native';
|
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 { Alert } from '../Alert';
|
||||||
import { useToaster } from './hooks';
|
import { useToaster } from './hooks';
|
||||||
|
@ -21,7 +22,7 @@ export type ToastersProps = {
|
||||||
export const Toasters: FC<ToastersProps> = ({ position }) => {
|
export const Toasters: FC<ToastersProps> = ({ position }) => {
|
||||||
const { toasters } = useToaster();
|
const { toasters } = useToaster();
|
||||||
|
|
||||||
if (isNilOrEmpty(toasters)) {
|
if (!notNil(toasters)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ export const Toasters: FC<ToastersProps> = ({ position }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ToastersContainer = styled.View<{
|
const ToastersContainer = styled(View)<{
|
||||||
position: ToastersProps['position'];
|
position: ToastersProps['position'];
|
||||||
}>(
|
}>(
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -20,14 +20,10 @@
|
||||||
"@procyon/components": "workspace:^",
|
"@procyon/components": "workspace:^",
|
||||||
"@procyon/types": "workspace:^",
|
"@procyon/types": "workspace:^",
|
||||||
"@procyon/utils": "workspace:^",
|
"@procyon/utils": "workspace:^",
|
||||||
"react-hook-form": "7.50.0"
|
"react-hook-form": "7.50.0",
|
||||||
|
"tiny-invariant": "1.3.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@emotion/react": "^11.11.4",
|
"yup": "1.3.3"
|
||||||
"@emotion/native": "^11.11.0",
|
|
||||||
"@emotion/styled": "^11.11.5",
|
|
||||||
"yup": "1.3.3",
|
|
||||||
"clsx": "2.1.0",
|
|
||||||
"tiny-invariant": "1.3.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from '@emotion/native';
|
|
||||||
import { useController, useFormContext } from 'react-hook-form';
|
import { useController, useFormContext } from 'react-hook-form';
|
||||||
|
|
||||||
import { Checkbox } from '@procyon/components/Checkbox';
|
import { Checkbox } from '@procyon/components/Checkbox';
|
||||||
|
@ -23,97 +22,79 @@ export const Field = <E extends ListData[]>({ ...props }: FieldProps<E>) => {
|
||||||
switch (props.component) {
|
switch (props.component) {
|
||||||
case 'TEXT':
|
case 'TEXT':
|
||||||
return (
|
return (
|
||||||
<FieldWrapper>
|
<TextField
|
||||||
<TextField
|
{...props}
|
||||||
{...props}
|
value={field.value}
|
||||||
value={field.value}
|
{...(fieldState.error && {
|
||||||
{...(fieldState.error && {
|
message: fieldState.error.message,
|
||||||
message: fieldState.error.message,
|
color: 'negative',
|
||||||
color: 'negative',
|
})}
|
||||||
})}
|
onChange={(e, value) => field.onChange(value)}
|
||||||
onChange={(e, value) => field.onChange(value)}
|
onBlur={field.onBlur}
|
||||||
onBlur={field.onBlur}
|
/>
|
||||||
/>
|
|
||||||
</FieldWrapper>
|
|
||||||
);
|
);
|
||||||
case 'CHECK':
|
case 'CHECK':
|
||||||
return (
|
return (
|
||||||
<FieldWrapper>
|
<Checkbox
|
||||||
<Checkbox
|
{...props}
|
||||||
{...props}
|
{...(fieldState.error && {
|
||||||
{...(fieldState.error && {
|
message: fieldState.error.message,
|
||||||
message: fieldState.error.message,
|
color: 'negative',
|
||||||
color: 'negative',
|
})}
|
||||||
})}
|
checked={field.value}
|
||||||
checked={field.value}
|
onChange={(e, checked) => field.onChange(checked)}
|
||||||
onChange={(e, checked) => field.onChange(checked)}
|
/>
|
||||||
/>
|
|
||||||
</FieldWrapper>
|
|
||||||
);
|
);
|
||||||
case 'RADIO':
|
case 'RADIO':
|
||||||
return (
|
return (
|
||||||
<FieldWrapper>
|
<RadioButton
|
||||||
<RadioButton
|
{...props}
|
||||||
{...props}
|
value={field.value}
|
||||||
value={field.value}
|
{...(fieldState.error && {
|
||||||
{...(fieldState.error && {
|
message: fieldState.error.message,
|
||||||
message: fieldState.error.message,
|
color: 'negative',
|
||||||
color: 'negative',
|
})}
|
||||||
})}
|
onChange={(e, value) => field.onChange(value)}>
|
||||||
onChange={(e, value) => field.onChange(value)}>
|
{props.children}
|
||||||
{props.children}
|
</RadioButton>
|
||||||
</RadioButton>
|
|
||||||
</FieldWrapper>
|
|
||||||
);
|
);
|
||||||
case 'SELECT':
|
case 'SELECT':
|
||||||
return (
|
return (
|
||||||
<FieldWrapper>
|
<Selectbox
|
||||||
<Selectbox
|
{...props}
|
||||||
{...props}
|
value={field.value}
|
||||||
value={field.value}
|
{...(fieldState.error && {
|
||||||
{...(fieldState.error && {
|
message: fieldState.error.message,
|
||||||
message: fieldState.error.message,
|
color: 'negative',
|
||||||
color: 'negative',
|
})}
|
||||||
})}
|
onChange={(e, value) => field.onChange(value)}
|
||||||
onChange={(e, value) => field.onChange(value)}
|
/>
|
||||||
/>
|
|
||||||
</FieldWrapper>
|
|
||||||
);
|
);
|
||||||
case 'DATE':
|
case 'DATE':
|
||||||
return (
|
return (
|
||||||
<FieldWrapper>
|
<DatePicker
|
||||||
<DatePicker
|
{...props}
|
||||||
{...props}
|
value={field.value}
|
||||||
value={field.value}
|
{...(fieldState.error && {
|
||||||
{...(fieldState.error && {
|
message: fieldState.error.message,
|
||||||
message: fieldState.error.message,
|
color: 'negative',
|
||||||
color: 'negative',
|
})}
|
||||||
})}
|
onChange={(e, value) => field.onChange(value)}
|
||||||
onChange={(e, value) => field.onChange(value)}
|
/>
|
||||||
/>
|
|
||||||
</FieldWrapper>
|
|
||||||
);
|
);
|
||||||
case 'TIME':
|
case 'TIME':
|
||||||
return (
|
return (
|
||||||
<FieldWrapper>
|
<TimePicker
|
||||||
<TimePicker
|
{...props}
|
||||||
{...props}
|
value={field.value}
|
||||||
value={field.value}
|
{...(fieldState.error && {
|
||||||
{...(fieldState.error && {
|
message: fieldState.error.message,
|
||||||
message: fieldState.error.message,
|
color: 'negative',
|
||||||
color: 'negative',
|
})}
|
||||||
})}
|
onChange={(e, value) => field.onChange(value)}
|
||||||
onChange={(e, value) => field.onChange(value)}
|
/>
|
||||||
/>
|
|
||||||
</FieldWrapper>
|
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FieldWrapper = styled.View(({ theme }) => {
|
|
||||||
return {
|
|
||||||
marginVertical: theme.spacing.md,
|
|
||||||
};
|
|
||||||
}) as any; // inferred type issue, IDK
|
|
||||||
|
|
|
@ -14,8 +14,5 @@
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"directory": "dist",
|
"directory": "dist",
|
||||||
"linkDirectory": false
|
"linkDirectory": false
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@procyon/styles": "workspace:^"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 };
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@
|
||||||
"author": "romanjaros <jarosr93@gmail.com>",
|
"author": "romanjaros <jarosr93@gmail.com>",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -rf dist/",
|
"clean": "rm -rf dist/ && npm run build -- --clean",
|
||||||
"build": "tsc --b tsconfig.build.json",
|
"build": "tsc --b tsconfig.build.json",
|
||||||
"prepublish": "cp package.json dist",
|
"prepublish": "cp package.json dist",
|
||||||
"postpublish": "rm dist/package.json",
|
"postpublish": "rm dist/package.json",
|
||||||
|
@ -14,13 +14,5 @@
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"directory": "dist",
|
"directory": "dist",
|
||||||
"linkDirectory": false
|
"linkDirectory": false
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"postcss-import": "16.0.0",
|
|
||||||
"postcss-nested": "6.0.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"postcss": "8.4.33",
|
|
||||||
"tailwindcss": "3.4.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import Values from 'values.js';
|
||||||
|
|
||||||
type RGB = [number, number, number];
|
type RGB = [number, number, number];
|
||||||
type HSL = [number, number, number];
|
type HSL = [number, number, number];
|
||||||
|
|
||||||
|
@ -84,3 +86,7 @@ export function getContrastColor(rgb: RGB): string {
|
||||||
const contrastRGB = HSLToRGB(hsl);
|
const contrastRGB = HSLToRGB(hsl);
|
||||||
return contrastRGB.map((v) => v.toString(16).padStart(2, '0')).join('');
|
return contrastRGB.map((v) => v.toString(16).padStart(2, '0')).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isDark = (color: string) => {
|
||||||
|
return new Values(color).getBrightness() <= 55;
|
||||||
|
};
|
|
@ -14,6 +14,5 @@
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"directory": "dist",
|
"directory": "dist",
|
||||||
"linkDirectory": false
|
"linkDirectory": false
|
||||||
},
|
}
|
||||||
"peerDependencies": {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
"linkDirectory": false
|
"linkDirectory": false
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/vanilla-masker": "1.2.4",
|
|
||||||
"imask": "7.6.1"
|
"imask": "7.6.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import Values from 'values.js';
|
|
||||||
|
|
||||||
export const isDark = (color: string) => {
|
|
||||||
return new Values(color).getBrightness() <= 55;
|
|
||||||
};
|
|
|
@ -1,3 +0,0 @@
|
||||||
import { either, isEmpty, isNil } from 'ramda';
|
|
||||||
|
|
||||||
export const isNilOrEmpty = either(isNil, isEmpty);
|
|
3
packages/utils/src/nil.ts
Normal file
3
packages/utils/src/nil.ts
Normal 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
7271
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import { DeleteIcon, LogOutIcon } from 'lucide-react-native';
|
import { DeleteIcon, LogOutIcon } from 'lucide-react-native';
|
||||||
import { Text as RnText } from 'react-native';
|
|
||||||
|
|
||||||
import { Button } from '@procyon/components/Button';
|
import { Button } from '@procyon/components/Button';
|
||||||
import { T } from '@procyon/localization/tolgee';
|
import { T } from '@procyon/localization/tolgee';
|
||||||
|
@ -87,13 +86,10 @@ export const LabelAsIcon: Story = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LabelWithIcon: Story = {
|
export const LabelWithIcon: Story = {
|
||||||
args: {},
|
args: {
|
||||||
render: (args) => (
|
LeftIcon: (props) => <LogOutIcon />,
|
||||||
<Button {...args}>
|
},
|
||||||
<LogOutIcon />
|
render: (args) => <Button {...args}>Logout</Button>,
|
||||||
<RnText>Logout</RnText>
|
|
||||||
</Button>
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ExtraLargeSize: Story = {
|
export const ExtraLargeSize: Story = {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Grid } from '@procyon/components/Grid';
|
||||||
import { Puzzle } from '@procyon/components/Puzzle';
|
import { Puzzle } from '@procyon/components/Puzzle';
|
||||||
import { RadioItem } from '@procyon/components/RadioItem';
|
import { RadioItem } from '@procyon/components/RadioItem';
|
||||||
import { Stack } from '@procyon/components/Stack';
|
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 { Form } from '@procyon/forms/Form';
|
||||||
import { useForm } from '@procyon/forms/useForm';
|
import { useForm } from '@procyon/forms/useForm';
|
||||||
|
|
||||||
|
@ -76,9 +76,7 @@ export const ExampleForm = () => {
|
||||||
<Field component="DATE" name="datePicker" label="DatePicker" />
|
<Field component="DATE" name="datePicker" label="DatePicker" />
|
||||||
<Field component="TIME" name="timePicker" label="TimePicker" />
|
<Field component="TIME" name="timePicker" label="TimePicker" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<FieldWrapper>
|
<Puzzle onVerified={() => null} />
|
||||||
<Puzzle onVerified={() => null} />
|
|
||||||
</FieldWrapper>
|
|
||||||
<Grid cols={{ sm: 2 }} gap={10}>
|
<Grid cols={{ sm: 2 }} gap={10}>
|
||||||
<View />
|
<View />
|
||||||
<Button fullWidth onClick={formMethods.handleSubmit(onSubmit)}>
|
<Button fullWidth onClick={formMethods.handleSubmit(onSubmit)}>
|
||||||
|
|
Loading…
Add table
Reference in a new issue