@campxdev/react-blueprint 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -3
- package/src/components/DataDisplay/DataTable/DataTable.stories.tsx +54 -0
- package/src/components/DataDisplay/DataTable/DataTable.tsx +31 -0
- package/src/components/Input/Button/Button.stories.tsx +5 -0
- package/src/components/Input/Button/Button.tsx +8 -1
- package/src/components/Input/Button/ButtonLoader.css +24 -0
- package/src/components/Input/SingleSelect/SingleSelect.tsx +8 -0
- package/src/components/Input/components/FetchingOptionsLoader.tsx +10 -0
- package/src/components/Layout/LayoutWrapper/LayoutWrapper.tsx +3 -5
- package/src/components/Layout/SideNavigation/SideNavigation.tsx +8 -13
- package/src/components/Layout/SideNavigation/styles/styles.tsx +3 -0
- package/src/components/Layout/Spinner/Spinner.css +32 -0
- package/src/components/Layout/Spinner/Spinner.stories.tsx +20 -0
- package/src/components/Layout/Spinner/Spinner.tsx +5 -0
- package/src/store/activeStore.ts +5 -0
- package/src/themes/commonTheme.ts +3 -3
- package/.env +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@campxdev/react-blueprint",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"main": "./export.ts",
|
|
5
5
|
"private": false,
|
|
6
6
|
"dependencies": {
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"@emotion/styled": "^11.11.5",
|
|
9
9
|
"@mui/icons-material": "^5.14.11",
|
|
10
10
|
"@mui/material": "^5.14.11",
|
|
11
|
+
"@mui/x-data-grid": "^7.5.1",
|
|
11
12
|
"@testing-library/jest-dom": "^5.14.1",
|
|
12
13
|
"@testing-library/react": "^13.0.0",
|
|
13
14
|
"@testing-library/user-event": "^13.2.1",
|
|
14
15
|
"@types/jest": "^27.0.1",
|
|
15
16
|
"@types/node": "^16.7.13",
|
|
16
|
-
"react-error-boundary": "^3.1.4",
|
|
17
17
|
"@types/react": "^18.0.0",
|
|
18
18
|
"@types/react-dom": "^18.0.0",
|
|
19
19
|
"axios": "^1.7.2",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"pullstate": "^1.24.0",
|
|
22
22
|
"react": "^18.3.1",
|
|
23
23
|
"react-dom": "^18.3.1",
|
|
24
|
+
"react-error-boundary": "^3.1.4",
|
|
24
25
|
"react-router-dom": "^6.4.2",
|
|
25
26
|
"react-scripts": "5.0.1",
|
|
26
27
|
"typescript": "^5.3.3",
|
|
@@ -55,7 +56,6 @@
|
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
57
58
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
|
58
|
-
"@types/js-cookie": "^3.0.5",
|
|
59
59
|
"@chromatic-com/storybook": "^1.4.0",
|
|
60
60
|
"@storybook/addon-essentials": "^8.1.4",
|
|
61
61
|
"@storybook/addon-interactions": "^8.1.4",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"@storybook/react": "^8.1.4",
|
|
68
68
|
"@storybook/react-webpack5": "^8.1.4",
|
|
69
69
|
"@storybook/test": "^8.1.4",
|
|
70
|
+
"@types/js-cookie": "^3.0.5",
|
|
70
71
|
"eslint-plugin-storybook": "^0.8.0",
|
|
71
72
|
"prop-types": "^15.8.1",
|
|
72
73
|
"storybook": "^8.1.4",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import DataTable from "./DataTable"; // Make sure the path to your component is correct
|
|
4
|
+
import { GridColDef } from "@mui/x-data-grid";
|
|
5
|
+
|
|
6
|
+
const columns: GridColDef[] = [
|
|
7
|
+
{ field: "id", headerName: "ID", width: 70 },
|
|
8
|
+
{ field: "firstName", headerName: "First name", width: 130 },
|
|
9
|
+
{ field: "lastName", headerName: "Last name", width: 130 },
|
|
10
|
+
{ field: "age", headerName: "Age", type: "number", width: 90 },
|
|
11
|
+
{
|
|
12
|
+
field: "fullName",
|
|
13
|
+
headerName: "Full name",
|
|
14
|
+
description: "This column has a value getter and is not sortable.",
|
|
15
|
+
sortable: false,
|
|
16
|
+
width: 160,
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const rows = [
|
|
21
|
+
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
|
|
22
|
+
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
|
|
23
|
+
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
|
|
24
|
+
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
|
|
25
|
+
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
|
|
26
|
+
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
|
|
27
|
+
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
|
|
28
|
+
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
|
|
29
|
+
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
// Define the default export with Meta type including the component type
|
|
33
|
+
const meta: Meta<typeof DataTable> = {
|
|
34
|
+
title: "DataDisplay/DataTable",
|
|
35
|
+
component: DataTable,
|
|
36
|
+
parameters: {
|
|
37
|
+
controls: {
|
|
38
|
+
include: ["rows", "columns"], // Specify the controls you want to include
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default meta;
|
|
44
|
+
const Template: StoryObj<typeof DataTable> = {
|
|
45
|
+
render: (args) => <DataTable {...args} />,
|
|
46
|
+
args: {
|
|
47
|
+
columns,
|
|
48
|
+
rows,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const Default: StoryObj<typeof DataTable> = {
|
|
53
|
+
...Template,
|
|
54
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { DataGrid, GridColDef, GridRowsProp } from "@mui/x-data-grid";
|
|
3
|
+
|
|
4
|
+
interface DataTableProps {
|
|
5
|
+
columns: GridColDef[];
|
|
6
|
+
rows: GridRowsProp;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function DataTable({ columns, rows }: DataTableProps) {
|
|
10
|
+
return (
|
|
11
|
+
<div style={{ height: 400, width: "100%" }}>
|
|
12
|
+
<DataGrid
|
|
13
|
+
rows={rows}
|
|
14
|
+
columns={columns}
|
|
15
|
+
initialState={{
|
|
16
|
+
pagination: {
|
|
17
|
+
paginationModel: { page: 0, pageSize: 5 },
|
|
18
|
+
},
|
|
19
|
+
}}
|
|
20
|
+
pageSizeOptions={[5, 10]}
|
|
21
|
+
checkboxSelection
|
|
22
|
+
onPaginationMetaChange={(params) => {
|
|
23
|
+
console.log(params);
|
|
24
|
+
}}
|
|
25
|
+
onPaginationModelChange={(params) => {
|
|
26
|
+
console.log(params);
|
|
27
|
+
}}
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -2,9 +2,16 @@ import {
|
|
|
2
2
|
Button as MuiButton,
|
|
3
3
|
ButtonProps as MuiButtonProps,
|
|
4
4
|
} from "@mui/material";
|
|
5
|
+
import "./ButtonLoader.css";
|
|
5
6
|
|
|
6
|
-
export type ButtonProps = {} & MuiButtonProps;
|
|
7
|
+
export type ButtonProps = { loading: boolean } & MuiButtonProps;
|
|
7
8
|
|
|
8
9
|
export const Button = (props: ButtonProps) => {
|
|
10
|
+
if (props.loading)
|
|
11
|
+
return (
|
|
12
|
+
<MuiButton {...props} onClick={() => {}}>
|
|
13
|
+
<div className="buttonLoader"></div>
|
|
14
|
+
</MuiButton>
|
|
15
|
+
);
|
|
9
16
|
return <MuiButton {...props} />;
|
|
10
17
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* HTML: <div class="buttonLoader"></div> */
|
|
2
|
+
.buttonLoader {
|
|
3
|
+
max-height: 40px;
|
|
4
|
+
padding: 5px 30px;
|
|
5
|
+
aspect-ratio: 2.5;
|
|
6
|
+
--_g: no-repeat radial-gradient(farthest-side,#000 90%,#0000);
|
|
7
|
+
background: var(--_g), var(--_g), var(--_g), var(--_g);
|
|
8
|
+
background-size: 20% 50%;
|
|
9
|
+
animation: l44 1s infinite linear alternate;
|
|
10
|
+
scale:0.5;
|
|
11
|
+
}
|
|
12
|
+
@keyframes l44 {
|
|
13
|
+
0%,
|
|
14
|
+
5% {background-position: calc(0*100%/3) 50% ,calc(1*100%/3) 50% ,calc(2*100%/3) 50% ,calc(3*100%/3) 50% }
|
|
15
|
+
12.5% {background-position: calc(0*100%/3) 0 ,calc(1*100%/3) 50% ,calc(2*100%/3) 50% ,calc(3*100%/3) 50% }
|
|
16
|
+
25% {background-position: calc(0*100%/3) 0 ,calc(1*100%/3) 0 ,calc(2*100%/3) 50% ,calc(3*100%/3) 50% }
|
|
17
|
+
37.5% {background-position: calc(0*100%/3) 100%,calc(1*100%/3) 0 ,calc(2*100%/3) 0 ,calc(3*100%/3) 50% }
|
|
18
|
+
50% {background-position: calc(0*100%/3) 100%,calc(1*100%/3) 100%,calc(2*100%/3) 0 ,calc(3*100%/3) 0 }
|
|
19
|
+
62.5% {background-position: calc(0*100%/3) 50% ,calc(1*100%/3) 100%,calc(2*100%/3) 100%,calc(3*100%/3) 0 }
|
|
20
|
+
75% {background-position: calc(0*100%/3) 50% ,calc(1*100%/3) 50% ,calc(2*100%/3) 100%,calc(3*100%/3) 100%}
|
|
21
|
+
87.5% {background-position: calc(0*100%/3) 50% ,calc(1*100%/3) 50% ,calc(2*100%/3) 50% ,calc(3*100%/3) 100%}
|
|
22
|
+
95%,
|
|
23
|
+
100% {background-position: calc(0*100%/3) 50% ,calc(1*100%/3) 50% ,calc(2*100%/3) 50% ,calc(3*100%/3) 50% }
|
|
24
|
+
}
|
|
@@ -2,12 +2,14 @@ import {
|
|
|
2
2
|
Box,
|
|
3
3
|
CircularProgress,
|
|
4
4
|
Autocomplete as MuiAutocomplete,
|
|
5
|
+
Paper,
|
|
5
6
|
TextField,
|
|
6
7
|
} from "@mui/material";
|
|
7
8
|
import axios from "axios";
|
|
8
9
|
import { useReducer } from "react";
|
|
9
10
|
import { campxAxios } from "../../../utils/campxAxios";
|
|
10
11
|
import { Typography } from "../../Typography/Typography";
|
|
12
|
+
import { FetchingOptionsLoader } from "../components/FetchingOptionsLoader";
|
|
11
13
|
import { OptionContainer } from "../styles";
|
|
12
14
|
|
|
13
15
|
function sleep(duration: number): Promise<void> {
|
|
@@ -182,6 +184,12 @@ export const SingleSelect = ({
|
|
|
182
184
|
}}
|
|
183
185
|
/>
|
|
184
186
|
)}
|
|
187
|
+
PaperComponent={(props) => (
|
|
188
|
+
<Paper {...props}>
|
|
189
|
+
{props.children}
|
|
190
|
+
<FetchingOptionsLoader loading={loadingInternalOptions} />
|
|
191
|
+
</Paper>
|
|
192
|
+
)}
|
|
185
193
|
renderOption={(props, option: any) => {
|
|
186
194
|
return (
|
|
187
195
|
<Box component="li" {...props}>
|
|
@@ -3,6 +3,7 @@ import { IconButton, Toolbar, Typography } from "@mui/material";
|
|
|
3
3
|
import MenuIcon from "@mui/icons-material/Menu";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import { LeftIcon, RightIcon } from "../../../assets/images/icons";
|
|
6
|
+
import { activeStore } from "../../../store/activeStore";
|
|
6
7
|
import { SideNavigation } from "../SideNavigation/SideNavigation";
|
|
7
8
|
import {
|
|
8
9
|
StyledLayoutContainer,
|
|
@@ -26,14 +27,12 @@ export const LayoutWrapper = ({
|
|
|
26
27
|
);
|
|
27
28
|
const [isHovered, setIsHovered] = useState<boolean>(false);
|
|
28
29
|
|
|
29
|
-
const
|
|
30
|
+
const { active } = activeStore.useState((s) => s);
|
|
30
31
|
|
|
31
32
|
const handleDrawer = () => {
|
|
32
33
|
setOpen(!open);
|
|
33
34
|
};
|
|
34
35
|
|
|
35
|
-
console.log(active, menu[active].name);
|
|
36
|
-
|
|
37
36
|
return (
|
|
38
37
|
<StyledLayoutContainer>
|
|
39
38
|
<StyledMainContainer>
|
|
@@ -44,7 +43,7 @@ export const LayoutWrapper = ({
|
|
|
44
43
|
aria-label="open drawer"
|
|
45
44
|
onClick={handleDrawer}
|
|
46
45
|
edge="start"
|
|
47
|
-
sx={{ mr: 0.5 }}
|
|
46
|
+
sx={{ mr: 0.5, padding: "6px", marginLeft: "0px" }}
|
|
48
47
|
onMouseEnter={() => setIsHovered(true)}
|
|
49
48
|
onMouseLeave={() => setIsHovered(false)}
|
|
50
49
|
>
|
|
@@ -67,7 +66,6 @@ export const LayoutWrapper = ({
|
|
|
67
66
|
children={children}
|
|
68
67
|
open={open}
|
|
69
68
|
handleDrawer={handleDrawer}
|
|
70
|
-
setActive={setActive}
|
|
71
69
|
/>
|
|
72
70
|
</StyledMainContainer>
|
|
73
71
|
</StyledLayoutContainer>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ListItemIcon, Stack } from "@mui/material";
|
|
2
2
|
import { useMatch, useResolvedPath } from "react-router-dom";
|
|
3
3
|
import { HomeIcon } from "../../../assets/images/icons";
|
|
4
|
+
import { activeStore } from "../../../store/activeStore";
|
|
4
5
|
import { Typography } from "../../Typography/Typography";
|
|
5
6
|
import {
|
|
6
7
|
Main,
|
|
@@ -16,7 +17,6 @@ export interface SideNavigationProps {
|
|
|
16
17
|
children: React.ReactNode;
|
|
17
18
|
open?: any;
|
|
18
19
|
handleDrawer?: any;
|
|
19
|
-
setActive: any;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export interface MenuItemProps {
|
|
@@ -28,7 +28,6 @@ export interface MenuItemProps {
|
|
|
28
28
|
iconType: string;
|
|
29
29
|
};
|
|
30
30
|
index: number;
|
|
31
|
-
setActive: any;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export const SideNavigation = ({
|
|
@@ -36,7 +35,6 @@ export const SideNavigation = ({
|
|
|
36
35
|
children,
|
|
37
36
|
open,
|
|
38
37
|
handleDrawer,
|
|
39
|
-
setActive,
|
|
40
38
|
}: SideNavigationProps) => {
|
|
41
39
|
return (
|
|
42
40
|
<Stack gap="20px" direction={"row"}>
|
|
@@ -48,12 +46,7 @@ export const SideNavigation = ({
|
|
|
48
46
|
>
|
|
49
47
|
<StyledList>
|
|
50
48
|
{menu?.map((item: any, index: number) => (
|
|
51
|
-
<MenuItem
|
|
52
|
-
menuItem={item}
|
|
53
|
-
index={index}
|
|
54
|
-
key={index}
|
|
55
|
-
setActive={setActive}
|
|
56
|
-
/>
|
|
49
|
+
<MenuItem menuItem={item} index={index} key={index} />
|
|
57
50
|
))}
|
|
58
51
|
</StyledList>
|
|
59
52
|
</StyledDrawer>
|
|
@@ -62,7 +55,7 @@ export const SideNavigation = ({
|
|
|
62
55
|
);
|
|
63
56
|
};
|
|
64
57
|
|
|
65
|
-
const MenuItem = ({ menuItem, index
|
|
58
|
+
const MenuItem = ({ menuItem, index }: MenuItemProps) => {
|
|
66
59
|
const { path, icon: Icon, name, permissionKey, iconType } = menuItem;
|
|
67
60
|
|
|
68
61
|
let resolved = useResolvedPath(path);
|
|
@@ -73,14 +66,16 @@ const MenuItem = ({ menuItem, index, setActive }: MenuItemProps) => {
|
|
|
73
66
|
|
|
74
67
|
// if (!hasAccess) return null
|
|
75
68
|
|
|
76
|
-
console.log(index, "path");
|
|
77
|
-
|
|
78
69
|
return (
|
|
79
70
|
<StyledListItem key={path} disablePadding match={match}>
|
|
80
71
|
<StyledLinkButton
|
|
81
72
|
to={path}
|
|
82
73
|
style={{ width: "100%" }}
|
|
83
|
-
onClick={() =>
|
|
74
|
+
onClick={() =>
|
|
75
|
+
activeStore.update((s) => {
|
|
76
|
+
s.active = index;
|
|
77
|
+
})
|
|
78
|
+
}
|
|
84
79
|
>
|
|
85
80
|
<StyledListItemButton>
|
|
86
81
|
<ListItemIcon
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.spinner {
|
|
2
|
+
width: 40px;
|
|
3
|
+
height: 40px;
|
|
4
|
+
border-radius: 50%;
|
|
5
|
+
position: relative;
|
|
6
|
+
animation: rotate 1s linear infinite;
|
|
7
|
+
scale: 0.5;
|
|
8
|
+
}
|
|
9
|
+
.spinner::before , .spinner::after {
|
|
10
|
+
content: "";
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
position: absolute;
|
|
13
|
+
inset: 0px;
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
border: 5px solid #7D60D9;
|
|
16
|
+
animation: prixClipFix 1.5s linear infinite ;
|
|
17
|
+
}
|
|
18
|
+
.spinner::after{
|
|
19
|
+
transform: rotate3d(90, 90, 0, 180deg );
|
|
20
|
+
border-color: #FF3D00;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@keyframes rotate {
|
|
24
|
+
0% {transform: rotate(0deg)}
|
|
25
|
+
100% {transform: rotate(360deg)}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@keyframes prixClipFix {
|
|
29
|
+
0% {clip-path:polygon(50% 50%,0 0,0 0,0 0,0 0,0 0)}
|
|
30
|
+
50% {clip-path:polygon(50% 50%,0 0,100% 0,100% 0,100% 0,100% 0)}
|
|
31
|
+
75%, 100% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,100% 100%,100% 100%)}
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Import React and other necessary elements
|
|
2
|
+
import { Meta } from "@storybook/react";
|
|
3
|
+
|
|
4
|
+
// Make sure your TextField import is correct
|
|
5
|
+
|
|
6
|
+
import { Spinner } from "./Spinner";
|
|
7
|
+
|
|
8
|
+
// Define the default export with Meta type including the component type
|
|
9
|
+
export default {
|
|
10
|
+
title: "Layout/Spinner",
|
|
11
|
+
component: Spinner,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
argTypes: {},
|
|
14
|
+
} as Meta<typeof Spinner>;
|
|
15
|
+
|
|
16
|
+
// Define stories directly as objects with render function
|
|
17
|
+
export const Primary = {
|
|
18
|
+
render: (args: any) => <Spinner {...args} />,
|
|
19
|
+
args: {},
|
|
20
|
+
};
|
|
@@ -76,9 +76,9 @@ export const getCommonTheme = (mode: Theme) => {
|
|
|
76
76
|
"& li": {
|
|
77
77
|
borderBottom: "1212121A",
|
|
78
78
|
minHeight: "55px",
|
|
79
|
-
":hover": {
|
|
80
|
-
|
|
81
|
-
},
|
|
79
|
+
// ":hover": {
|
|
80
|
+
// backgroundColor: "rgba(0, 0, 0, 0.025)",
|
|
81
|
+
// },
|
|
82
82
|
},
|
|
83
83
|
"& > :last-child": {
|
|
84
84
|
borderBottom: "none",
|
package/.env
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
REACT_APP_API_HOST=http://localhost:3000
|