@canmingir/link 1.2.0 → 1.2.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canmingir/link",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -0,0 +1,88 @@
1
+ import Box from "@mui/material/Box";
2
+ import Breadcrumbs from "@mui/material/Breadcrumbs";
3
+ import Link from "@mui/material/Link";
4
+ import LinkItem from "./link-item";
5
+ import PropTypes from "prop-types";
6
+ import Stack from "@mui/material/Stack";
7
+ import Typography from "@mui/material/Typography";
8
+
9
+ export default function CustomBreadcrumbs({
10
+ links,
11
+ action,
12
+ heading,
13
+ moreLink,
14
+ activeLast,
15
+ sx,
16
+ ...other
17
+ }) {
18
+ const lastLink = links[links.length - 1].name;
19
+
20
+ return (
21
+ <Box sx={{ ...sx }}>
22
+ <Stack direction="row" alignItems="center">
23
+ <Box sx={{ flexGrow: 1 }}>
24
+ {heading && (
25
+ <Typography variant="h4" gutterBottom>
26
+ {heading}
27
+ </Typography>
28
+ )}
29
+
30
+ {!!links.length && (
31
+ <Breadcrumbs separator={<Separator />} {...other}>
32
+ {links.map((link) => (
33
+ <LinkItem
34
+ key={link.name || ""}
35
+ link={link}
36
+ activeLast={activeLast}
37
+ disabled={link.name === lastLink}
38
+ />
39
+ ))}
40
+ </Breadcrumbs>
41
+ )}
42
+ </Box>
43
+
44
+ {action && <Box sx={{ flexShrink: 0 }}> {action} </Box>}
45
+ </Stack>
46
+
47
+ {!!moreLink && (
48
+ <Box sx={{ mt: 2 }}>
49
+ {moreLink.map((href) => (
50
+ <Link
51
+ key={href}
52
+ href={href}
53
+ variant="body2"
54
+ target="_blank"
55
+ rel="noopener"
56
+ sx={{ display: "table" }}
57
+ >
58
+ {href}
59
+ </Link>
60
+ ))}
61
+ </Box>
62
+ )}
63
+ </Box>
64
+ );
65
+ }
66
+
67
+ CustomBreadcrumbs.propTypes = {
68
+ sx: PropTypes.object,
69
+ action: PropTypes.node,
70
+ links: PropTypes.array,
71
+ heading: PropTypes.string,
72
+ moreLink: PropTypes.array,
73
+ activeLast: PropTypes.bool,
74
+ };
75
+
76
+ function Separator() {
77
+ return (
78
+ <Box
79
+ component="span"
80
+ sx={{
81
+ width: 4,
82
+ height: 4,
83
+ borderRadius: "50%",
84
+ bgcolor: "text.disabled",
85
+ }}
86
+ />
87
+ );
88
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./CustomBreadcrumbs";
@@ -0,0 +1,58 @@
1
+ import Box from "@mui/material/Box";
2
+ import Link from "@mui/material/Link";
3
+ import PropTypes from "prop-types";
4
+ import { RouterLink } from "../../routes/components/router-link";
5
+
6
+ export default function BreadcrumbsLink({ link, activeLast, disabled }) {
7
+ const styles = {
8
+ typography: "body2",
9
+ alignItems: "center",
10
+ color: "text.primary",
11
+ display: "inline-flex",
12
+ ...(disabled &&
13
+ !activeLast && {
14
+ cursor: "default",
15
+ pointerEvents: "none",
16
+ color: "text.disabled",
17
+ }),
18
+ };
19
+
20
+ const renderContent = (
21
+ <>
22
+ {link.icon && (
23
+ <Box
24
+ component="span"
25
+ sx={{
26
+ mr: 1,
27
+ display: "inherit",
28
+ "& svg": { width: 20, height: 20 },
29
+ }}
30
+ >
31
+ {link.icon}
32
+ </Box>
33
+ )}
34
+
35
+ {link.name}
36
+ </>
37
+ );
38
+
39
+ if (link.href) {
40
+ return (
41
+ <Link component={RouterLink} href={link.href} sx={styles}>
42
+ {renderContent}
43
+ </Link>
44
+ );
45
+ }
46
+
47
+ return <Box sx={styles}> {renderContent} </Box>;
48
+ }
49
+
50
+ BreadcrumbsLink.propTypes = {
51
+ activeLast: PropTypes.bool,
52
+ disabled: PropTypes.bool,
53
+ link: PropTypes.shape({
54
+ href: PropTypes.string,
55
+ icon: PropTypes.node,
56
+ name: PropTypes.string,
57
+ }),
58
+ };
@@ -0,0 +1,46 @@
1
+ import Popover from "@mui/material/Popover";
2
+ import React from "react";
3
+ import { StyledArrow } from "./styles";
4
+ import { getPosition } from "./utils";
5
+ import { menuItemClasses } from "@mui/material/MenuItem";
6
+
7
+ export default function CustomPopover({
8
+ open,
9
+ children,
10
+ arrow = "top-right",
11
+ hiddenArrow,
12
+ sx,
13
+ ...other
14
+ }) {
15
+ const { style, anchorOrigin, transformOrigin } = getPosition(arrow);
16
+
17
+ return (
18
+ <Popover
19
+ open={Boolean(open)}
20
+ anchorEl={open}
21
+ anchorOrigin={anchorOrigin}
22
+ transformOrigin={transformOrigin}
23
+ slotProps={{
24
+ paper: {
25
+ sx: {
26
+ width: "auto",
27
+ overflow: "inherit",
28
+ ...style,
29
+ [`& .${menuItemClasses.root}`]: {
30
+ "& svg": {
31
+ mr: 2,
32
+ flexShrink: 0,
33
+ },
34
+ },
35
+ ...sx,
36
+ },
37
+ },
38
+ }}
39
+ {...other}
40
+ >
41
+ {!hiddenArrow && <StyledArrow arrow={arrow} />}
42
+
43
+ {children}
44
+ </Popover>
45
+ );
46
+ }
@@ -0,0 +1,3 @@
1
+ export { default } from "./CustomPopover";
2
+
3
+ export { default as usePopover } from "./usePopover";
@@ -0,0 +1,82 @@
1
+ import { alpha, styled } from "@mui/material/styles";
2
+
3
+ import { bgBlur } from "../../theme/css";
4
+
5
+ export const StyledArrow = styled("span")(({ arrow, theme }) => {
6
+ const SIZE = 14;
7
+
8
+ const POSITION = -(SIZE / 2) + 0.5;
9
+
10
+ const topStyle = {
11
+ top: POSITION,
12
+ transform: "rotate(135deg)",
13
+ };
14
+
15
+ const bottomStyle = {
16
+ bottom: POSITION,
17
+ transform: "rotate(-45deg)",
18
+ };
19
+
20
+ const leftStyle = {
21
+ left: POSITION,
22
+ transform: "rotate(45deg)",
23
+ };
24
+
25
+ const rightStyle = {
26
+ right: POSITION,
27
+ transform: "rotate(-135deg)",
28
+ };
29
+
30
+ return {
31
+ width: SIZE,
32
+ height: SIZE,
33
+ position: "absolute",
34
+ borderBottomLeftRadius: SIZE / 4,
35
+ clipPath: "polygon(0% 0%, 100% 100%, 0% 100%)",
36
+ border: `solid 1px ${alpha(
37
+ theme.palette.mode === "light"
38
+ ? theme.palette.grey[500]
39
+ : theme.palette.common.black,
40
+ 0.12
41
+ )}`,
42
+ ...bgBlur({
43
+ color: theme.palette.background.paper,
44
+ }),
45
+ // Top
46
+ ...(arrow === "top-left" && { ...topStyle, left: 20 }),
47
+ ...(arrow === "top-center" && {
48
+ ...topStyle,
49
+ left: 0,
50
+ right: 0,
51
+ margin: "auto",
52
+ }),
53
+ ...(arrow === "top-right" && { ...topStyle, right: 20 }),
54
+ // Bottom
55
+ ...(arrow === "bottom-left" && { ...bottomStyle, left: 20 }),
56
+ ...(arrow === "bottom-center" && {
57
+ ...bottomStyle,
58
+ left: 0,
59
+ right: 0,
60
+ margin: "auto",
61
+ }),
62
+ ...(arrow === "bottom-right" && { ...bottomStyle, right: 20 }),
63
+ // Left
64
+ ...(arrow === "left-top" && { ...leftStyle, top: 20 }),
65
+ ...(arrow === "left-center" && {
66
+ ...leftStyle,
67
+ top: 0,
68
+ bottom: 0,
69
+ margin: "auto",
70
+ }),
71
+ ...(arrow === "left-bottom" && { ...leftStyle, bottom: 20 }),
72
+ // Right
73
+ ...(arrow === "right-top" && { ...rightStyle, top: 20 }),
74
+ ...(arrow === "right-center" && {
75
+ ...rightStyle,
76
+ top: 0,
77
+ bottom: 0,
78
+ margin: "auto",
79
+ }),
80
+ ...(arrow === "right-bottom" && { ...rightStyle, bottom: 20 }),
81
+ };
82
+ });
@@ -0,0 +1,20 @@
1
+ import { useCallback, useState } from "react";
2
+
3
+ export default function usePopover() {
4
+ const [open, setOpen] = useState(null);
5
+
6
+ const onOpen = useCallback((event) => {
7
+ setOpen(event.currentTarget);
8
+ }, []);
9
+
10
+ const onClose = useCallback(() => {
11
+ setOpen(null);
12
+ }, []);
13
+
14
+ return {
15
+ open,
16
+ onOpen,
17
+ onClose,
18
+ setOpen,
19
+ };
20
+ }
@@ -0,0 +1,100 @@
1
+ export function getPosition(arrow) {
2
+ let props;
3
+
4
+ switch (arrow) {
5
+ case "top-left":
6
+ props = {
7
+ style: { ml: -0.75 },
8
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
9
+ transformOrigin: { vertical: "top", horizontal: "left" },
10
+ };
11
+ break;
12
+ case "top-center":
13
+ props = {
14
+ style: {},
15
+ anchorOrigin: { vertical: "bottom", horizontal: "center" },
16
+ transformOrigin: { vertical: "top", horizontal: "center" },
17
+ };
18
+ break;
19
+ case "top-right":
20
+ props = {
21
+ style: { ml: 0.75 },
22
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
23
+ transformOrigin: { vertical: "top", horizontal: "right" },
24
+ };
25
+ break;
26
+ case "bottom-left":
27
+ props = {
28
+ style: { ml: -0.75 },
29
+ anchorOrigin: { vertical: "top", horizontal: "left" },
30
+ transformOrigin: { vertical: "bottom", horizontal: "left" },
31
+ };
32
+ break;
33
+ case "bottom-center":
34
+ props = {
35
+ style: {},
36
+ anchorOrigin: { vertical: "top", horizontal: "center" },
37
+ transformOrigin: { vertical: "bottom", horizontal: "center" },
38
+ };
39
+ break;
40
+ case "bottom-right":
41
+ props = {
42
+ style: { ml: 0.75 },
43
+ anchorOrigin: { vertical: "top", horizontal: "right" },
44
+ transformOrigin: { vertical: "bottom", horizontal: "right" },
45
+ };
46
+ break;
47
+ case "left-top":
48
+ props = {
49
+ style: { mt: -0.75 },
50
+ anchorOrigin: { vertical: "top", horizontal: "right" },
51
+ transformOrigin: { vertical: "top", horizontal: "left" },
52
+ };
53
+ break;
54
+ case "left-center":
55
+ props = {
56
+ style: {},
57
+ anchorOrigin: { vertical: "center", horizontal: "right" },
58
+ transformOrigin: { vertical: "center", horizontal: "left" },
59
+ };
60
+ break;
61
+ case "left-bottom":
62
+ props = {
63
+ style: { mt: 0.75 },
64
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
65
+ transformOrigin: { vertical: "bottom", horizontal: "left" },
66
+ };
67
+ break;
68
+ case "right-top":
69
+ props = {
70
+ style: { mt: -0.75 },
71
+ anchorOrigin: { vertical: "top", horizontal: "left" },
72
+ transformOrigin: { vertical: "top", horizontal: "right" },
73
+ };
74
+ break;
75
+ case "right-center":
76
+ props = {
77
+ style: {},
78
+ anchorOrigin: { vertical: "center", horizontal: "left" },
79
+ transformOrigin: { vertical: "center", horizontal: "right" },
80
+ };
81
+ break;
82
+ case "right-bottom":
83
+ props = {
84
+ style: { mt: 0.75 },
85
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
86
+ transformOrigin: { vertical: "bottom", horizontal: "right" },
87
+ };
88
+ break;
89
+
90
+ // top-right
91
+ default:
92
+ props = {
93
+ style: { ml: 0.75 },
94
+ anchorOrigin: { vertical: "bottom", horizontal: "right" },
95
+ transformOrigin: { vertical: "top", horizontal: "right" },
96
+ };
97
+ }
98
+
99
+ return props;
100
+ }
@@ -0,0 +1,16 @@
1
+ import { FormProvider as Form } from "react-hook-form";
2
+ import PropTypes from "prop-types";
3
+
4
+ export default function FormProvider({ children, onSubmit, methods }) {
5
+ return (
6
+ <Form {...methods}>
7
+ <form onSubmit={onSubmit}>{children}</form>
8
+ </Form>
9
+ );
10
+ }
11
+
12
+ FormProvider.propTypes = {
13
+ children: PropTypes.node,
14
+ methods: PropTypes.object,
15
+ onSubmit: PropTypes.func,
16
+ };
@@ -0,0 +1 @@
1
+ export { default } from "./FormProvider";
@@ -0,0 +1,116 @@
1
+ import { alpha, useTheme } from "@mui/material/styles";
2
+
3
+ import Box from "@mui/material/Box";
4
+ import { LazyLoadImage } from "react-lazy-load-image-component";
5
+ import React from "react";
6
+ import { forwardRef } from "react";
7
+ import { getRatio } from "./utils";
8
+
9
+ const Image = forwardRef(
10
+ (
11
+ {
12
+ ratio,
13
+ overlay,
14
+ disabledEffect = false,
15
+ alt,
16
+ src,
17
+ afterLoad,
18
+ delayTime,
19
+ threshold,
20
+ beforeLoad,
21
+ delayMethod,
22
+ placeholder,
23
+ wrapperProps,
24
+ scrollPosition,
25
+ effect = "blur",
26
+ visibleByDefault,
27
+ wrapperClassName,
28
+ useIntersectionObserver,
29
+ sx,
30
+ ...other
31
+ },
32
+ ref
33
+ ) => {
34
+ const theme = useTheme();
35
+
36
+ const overlayStyles = !!overlay && {
37
+ "&:before": {
38
+ content: "''",
39
+ top: 0,
40
+ left: 0,
41
+ width: 1,
42
+ height: 1,
43
+ zIndex: 1,
44
+ position: "absolute",
45
+ background: overlay || alpha(theme.palette.grey[900], 0.48),
46
+ },
47
+ };
48
+
49
+ const content = (
50
+ <Box
51
+ component={LazyLoadImage}
52
+ alt={alt}
53
+ src={src}
54
+ afterLoad={afterLoad}
55
+ delayTime={delayTime}
56
+ threshold={threshold}
57
+ beforeLoad={beforeLoad}
58
+ delayMethod={delayMethod}
59
+ placeholder={placeholder}
60
+ wrapperProps={wrapperProps}
61
+ scrollPosition={scrollPosition}
62
+ visibleByDefault={visibleByDefault}
63
+ effect={disabledEffect ? undefined : effect}
64
+ useIntersectionObserver={useIntersectionObserver}
65
+ wrapperClassName={wrapperClassName || "component-image-wrapper"}
66
+ placeholderSrc={
67
+ disabledEffect ? "/assets/transparent.png" : "/assets/placeholder.svg"
68
+ }
69
+ sx={{
70
+ width: 1,
71
+ height: 1,
72
+ objectFit: "cover",
73
+ verticalAlign: "bottom",
74
+ ...(!!ratio && {
75
+ top: 0,
76
+ left: 0,
77
+ position: "absolute",
78
+ }),
79
+ }}
80
+ />
81
+ );
82
+
83
+ return (
84
+ <Box
85
+ ref={ref}
86
+ component="span"
87
+ className="component-image"
88
+ sx={{
89
+ overflow: "hidden",
90
+ position: "relative",
91
+ verticalAlign: "bottom",
92
+ display: "inline-block",
93
+ ...(!!ratio && {
94
+ width: 1,
95
+ }),
96
+ "& span.component-image-wrapper": {
97
+ width: 1,
98
+ height: 1,
99
+ verticalAlign: "bottom",
100
+ backgroundSize: "cover !important",
101
+ ...(!!ratio && {
102
+ pt: getRatio(ratio),
103
+ }),
104
+ },
105
+ ...overlayStyles,
106
+ ...sx,
107
+ }}
108
+ {...other}
109
+ >
110
+ {content}
111
+ </Box>
112
+ );
113
+ }
114
+ );
115
+
116
+ export default Image;
@@ -0,0 +1 @@
1
+ export { default } from "./Image";
@@ -0,0 +1,15 @@
1
+ // ----------------------------------------------------------------------
2
+
3
+ export function getRatio(ratio = "1/1") {
4
+ return {
5
+ "4/3": "calc(100% / 4 * 3)",
6
+ "3/4": "calc(100% / 3 * 4)",
7
+ "6/4": "calc(100% / 6 * 4)",
8
+ "4/6": "calc(100% / 4 * 6)",
9
+ "16/9": "calc(100% / 16 * 9)",
10
+ "9/16": "calc(100% / 9 * 16)",
11
+ "21/9": "calc(100% / 21 * 9)",
12
+ "9/21": "calc(100% / 9 * 21)",
13
+ "1/1": "100%",
14
+ }[ratio];
15
+ }
@@ -0,0 +1,51 @@
1
+ import Box from "@mui/material/Box";
2
+ import React from "react";
3
+ import { StyledLabel } from "./styles";
4
+ import { forwardRef } from "react";
5
+ import { useTheme } from "@mui/material/styles";
6
+
7
+ const Label = forwardRef(
8
+ (
9
+ {
10
+ children,
11
+ color = "default",
12
+ variant = "soft",
13
+ startIcon,
14
+ endIcon,
15
+ sx,
16
+ ...other
17
+ },
18
+ ref
19
+ ) => {
20
+ const theme = useTheme();
21
+
22
+ const iconStyles = {
23
+ width: 16,
24
+ height: 16,
25
+ "& svg, img": { width: 1, height: 1, objectFit: "cover" },
26
+ };
27
+
28
+ return (
29
+ <StyledLabel
30
+ ref={ref}
31
+ component="span"
32
+ ownerState={{ color, variant }}
33
+ sx={{
34
+ ...(startIcon && { pl: 0.75 }),
35
+ ...(endIcon && { pr: 0.75 }),
36
+ ...sx,
37
+ }}
38
+ theme={theme}
39
+ {...other}
40
+ >
41
+ {startIcon && <Box sx={{ mr: 0.75, ...iconStyles }}> {startIcon} </Box>}
42
+
43
+ {children}
44
+
45
+ {endIcon && <Box sx={{ ml: 0.75, ...iconStyles }}> {endIcon} </Box>}
46
+ </StyledLabel>
47
+ );
48
+ }
49
+ );
50
+
51
+ export default Label;
@@ -0,0 +1 @@
1
+ export { default } from "./label";
@@ -0,0 +1,76 @@
1
+ import { alpha, styled } from "@mui/material/styles";
2
+
3
+ import Box from "@mui/material/Box";
4
+
5
+ export const StyledLabel = styled(Box)(({ theme, ownerState }) => {
6
+ const lightMode = theme.palette.mode === "light";
7
+
8
+ const filledVariant = ownerState.variant === "filled";
9
+
10
+ const outlinedVariant = ownerState.variant === "outlined";
11
+
12
+ const softVariant = ownerState.variant === "soft";
13
+
14
+ const defaultStyle = {
15
+ ...(ownerState.color === "default" && {
16
+ // FILLED
17
+ ...(filledVariant && {
18
+ color: lightMode ? theme.palette.common.white : theme.palette.grey[800],
19
+ backgroundColor: theme.palette.text.primary,
20
+ }),
21
+ // OUTLINED
22
+ ...(outlinedVariant && {
23
+ backgroundColor: "transparent",
24
+ color: theme.palette.text.primary,
25
+ border: `2px solid ${theme.palette.text.primary}`,
26
+ }),
27
+ // SOFT
28
+ ...(softVariant && {
29
+ color: theme.palette.text.secondary,
30
+ backgroundColor: alpha(theme.palette.grey[500], 0.16),
31
+ }),
32
+ }),
33
+ };
34
+
35
+ const colorStyle = {
36
+ ...(ownerState.color !== "default" && {
37
+ // FILLED
38
+ ...(filledVariant && {
39
+ color: theme.palette[ownerState.color].contrastText,
40
+ backgroundColor: theme.palette[ownerState.color].main,
41
+ }),
42
+ // OUTLINED
43
+ ...(outlinedVariant && {
44
+ backgroundColor: "transparent",
45
+ color: theme.palette[ownerState.color].main,
46
+ border: `2px solid ${theme.palette[ownerState.color].main}`,
47
+ }),
48
+ // SOFT
49
+ ...(softVariant && {
50
+ color: theme.palette[ownerState.color][lightMode ? "dark" : "light"],
51
+ backgroundColor: alpha(theme.palette[ownerState.color].main, 0.16),
52
+ }),
53
+ }),
54
+ };
55
+
56
+ return {
57
+ height: 24,
58
+ minWidth: 24,
59
+ lineHeight: 0,
60
+ borderRadius: 6,
61
+ cursor: "default",
62
+ alignItems: "center",
63
+ whiteSpace: "nowrap",
64
+ display: "inline-flex",
65
+ justifyContent: "center",
66
+ textTransform: "capitalize",
67
+ padding: theme.spacing(0, 0.75),
68
+ fontSize: theme.typography.pxToRem(12),
69
+ fontWeight: theme.typography.fontWeightBold,
70
+ transition: theme.transitions.create("all", {
71
+ duration: theme.transitions.duration.shorter,
72
+ }),
73
+ ...defaultStyle,
74
+ ...colorStyle,
75
+ };
76
+ });
@@ -0,0 +1,39 @@
1
+ import { Controller, useFormContext } from "react-hook-form";
2
+
3
+ import PropTypes from "prop-types";
4
+ import TextField from "@mui/material/TextField";
5
+
6
+ export default function RHFTextField({ name, helperText, type, ...other }) {
7
+ const { control } = useFormContext();
8
+
9
+ return (
10
+ <Controller
11
+ name={name}
12
+ control={control}
13
+ render={({ field, fieldState: { error } }) => (
14
+ <TextField
15
+ {...field}
16
+ fullWidth
17
+ type={type}
18
+ value={type === "number" && field.value === 0 ? "" : field.value}
19
+ onChange={(event) => {
20
+ if (type === "number") {
21
+ field.onChange(Number(event.target.value));
22
+ } else {
23
+ field.onChange(event.target.value);
24
+ }
25
+ }}
26
+ error={!!error}
27
+ helperText={error ? error?.message : helperText}
28
+ {...other}
29
+ />
30
+ )}
31
+ />
32
+ );
33
+ }
34
+
35
+ RHFTextField.propTypes = {
36
+ helperText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
37
+ name: PropTypes.string,
38
+ type: PropTypes.string,
39
+ };
@@ -0,0 +1 @@
1
+ export { default } from "./RHFTextfield";
@@ -0,0 +1,39 @@
1
+ import Box from "@mui/material/Box";
2
+ import React from "react";
3
+ import { forwardRef } from "react";
4
+
5
+ import { StyledRootScrollbar, StyledScrollbar } from "./styles";
6
+
7
+ const Scrollbar = forwardRef(({ children, sx, ...other }, ref) => {
8
+ const userAgent =
9
+ typeof navigator === "undefined" ? "SSR" : navigator.userAgent;
10
+ const mobile =
11
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
12
+ userAgent
13
+ );
14
+
15
+ if (mobile) {
16
+ return (
17
+ <Box ref={ref} sx={{ overflow: "auto", ...sx }} {...other}>
18
+ {children}
19
+ </Box>
20
+ );
21
+ }
22
+
23
+ return (
24
+ <StyledRootScrollbar>
25
+ <StyledScrollbar
26
+ scrollableNodeProps={{
27
+ ref,
28
+ }}
29
+ clickOnTrack={false}
30
+ sx={sx}
31
+ {...other}
32
+ >
33
+ {children}
34
+ </StyledScrollbar>
35
+ </StyledRootScrollbar>
36
+ );
37
+ });
38
+
39
+ export default Scrollbar;
@@ -0,0 +1 @@
1
+ export { default } from "./scrollbar";
@@ -0,0 +1,27 @@
1
+ import SimpleBar from "simplebar-react";
2
+
3
+ import { alpha, styled } from "@mui/material/styles";
4
+
5
+ // ----------------------------------------------------------------------
6
+
7
+ export const StyledRootScrollbar = styled("div")(() => ({
8
+ flexGrow: 1,
9
+ height: "100%",
10
+ overflow: "hidden",
11
+ }));
12
+
13
+ export const StyledScrollbar = styled(SimpleBar)(({ theme }) => ({
14
+ maxHeight: "100%",
15
+
16
+ "& .simplebar-scrollbar": {
17
+ "&:before": {
18
+ backgroundColor: alpha(theme.palette.grey[600], 0.48),
19
+ },
20
+ "&.simplebar-visible:before": {
21
+ opacity: 1,
22
+ },
23
+ },
24
+ "& .simplebar-mask": {
25
+ zIndex: "inherit",
26
+ },
27
+ }));
@@ -0,0 +1,29 @@
1
+ import Paper from "@mui/material/Paper";
2
+ import Typography from "@mui/material/Typography";
3
+
4
+ export default function SearchNotFound({ query, sx, ...other }) {
5
+ return query ? (
6
+ <Paper
7
+ sx={{
8
+ bgcolor: "unset",
9
+ textAlign: "center",
10
+ ...sx,
11
+ }}
12
+ {...other}
13
+ >
14
+ <Typography variant="h6" gutterBottom>
15
+ Not Found
16
+ </Typography>
17
+
18
+ <Typography variant="body2">
19
+ No results found for &nbsp;
20
+ <strong>&quot;{query}&quot;</strong>.
21
+ <br /> Try checking for typos or using complete words.
22
+ </Typography>
23
+ </Paper>
24
+ ) : (
25
+ <Typography variant="body2" sx={sx}>
26
+ Please enter keywords
27
+ </Typography>
28
+ );
29
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./SearchNotFound";
@@ -0,0 +1,87 @@
1
+ import Box from "@mui/material/Box";
2
+ import Checkbox from "@mui/material/Checkbox";
3
+ import PropTypes from "prop-types";
4
+ import TableCell from "@mui/material/TableCell";
5
+ import TableHead from "@mui/material/TableHead";
6
+ import TableRow from "@mui/material/TableRow";
7
+ import TableSortLabel from "@mui/material/TableSortLabel";
8
+
9
+ const visuallyHidden = {
10
+ border: 0,
11
+ margin: -1,
12
+ padding: 0,
13
+ width: "1px",
14
+ height: "1px",
15
+ overflow: "hidden",
16
+ position: "absolute",
17
+ whiteSpace: "nowrap",
18
+ clip: "rect(0 0 0 0)",
19
+ };
20
+
21
+ export default function TableHeadCustom({
22
+ order,
23
+ orderBy,
24
+ rowCount = 0,
25
+ headLabel,
26
+ numSelected = 0,
27
+ onSort,
28
+ onSelectAllRows,
29
+ sx,
30
+ }) {
31
+ return (
32
+ <TableHead sx={sx}>
33
+ <TableRow>
34
+ {onSelectAllRows && (
35
+ <TableCell padding="checkbox">
36
+ <Checkbox
37
+ indeterminate={!!numSelected && numSelected < rowCount}
38
+ checked={!!rowCount && numSelected === rowCount}
39
+ onChange={(event) => onSelectAllRows(event.target.checked)}
40
+ />
41
+ </TableCell>
42
+ )}
43
+
44
+ {headLabel.map((headCell) => (
45
+ <TableCell
46
+ key={headCell.id}
47
+ align={headCell.align || "left"}
48
+ sortDirection={orderBy === headCell.id ? order : false}
49
+ sx={{ width: headCell.width, minWidth: headCell.minWidth }}
50
+ >
51
+ {onSort ? (
52
+ <TableSortLabel
53
+ hideSortIcon
54
+ active={orderBy === headCell.id}
55
+ direction={orderBy === headCell.id ? order : "asc"}
56
+ onClick={() => onSort(headCell.id)}
57
+ >
58
+ {headCell.label}
59
+
60
+ {orderBy === headCell.id ? (
61
+ <Box sx={{ ...visuallyHidden }}>
62
+ {order === "desc"
63
+ ? "sorted descending"
64
+ : "sorted ascending"}
65
+ </Box>
66
+ ) : null}
67
+ </TableSortLabel>
68
+ ) : (
69
+ headCell.label
70
+ )}
71
+ </TableCell>
72
+ ))}
73
+ </TableRow>
74
+ </TableHead>
75
+ );
76
+ }
77
+
78
+ TableHeadCustom.propTypes = {
79
+ sx: PropTypes.object,
80
+ onSort: PropTypes.func,
81
+ orderBy: PropTypes.string,
82
+ headLabel: PropTypes.array,
83
+ rowCount: PropTypes.number,
84
+ numSelected: PropTypes.number,
85
+ onSelectAllRows: PropTypes.func,
86
+ order: PropTypes.oneOf(["asc", "desc"]),
87
+ };
@@ -0,0 +1 @@
1
+ export { default } from "./TableHeadCustom";
@@ -0,0 +1,72 @@
1
+ import Checkbox from "@mui/material/Checkbox";
2
+ import PropTypes from "prop-types";
3
+ import Stack from "@mui/material/Stack";
4
+ import Typography from "@mui/material/Typography";
5
+
6
+ export default function TableSelectedAction({
7
+ dense,
8
+ action,
9
+ rowCount,
10
+ numSelected,
11
+ onSelectAllRows,
12
+ sx,
13
+ ...other
14
+ }) {
15
+ if (!numSelected) {
16
+ return null;
17
+ }
18
+
19
+ return (
20
+ <Stack
21
+ direction="row"
22
+ alignItems="center"
23
+ sx={{
24
+ pl: 1,
25
+ pr: 2,
26
+ top: 0,
27
+ left: 0,
28
+ width: 1,
29
+ zIndex: 9,
30
+ height: 58,
31
+ position: "absolute",
32
+ bgcolor: "primary.lighter",
33
+ ...(dense && {
34
+ height: 38,
35
+ }),
36
+ ...sx,
37
+ }}
38
+ {...other}
39
+ >
40
+ <Checkbox
41
+ indeterminate={!!numSelected && numSelected < rowCount}
42
+ checked={!!rowCount && numSelected === rowCount}
43
+ onChange={(event) => onSelectAllRows(event.target.checked)}
44
+ />
45
+
46
+ <Typography
47
+ variant="subtitle2"
48
+ sx={{
49
+ ml: 2,
50
+ flexGrow: 1,
51
+ color: "primary.main",
52
+ ...(dense && {
53
+ ml: 3,
54
+ }),
55
+ }}
56
+ >
57
+ {numSelected} selected
58
+ </Typography>
59
+
60
+ {action && action}
61
+ </Stack>
62
+ );
63
+ }
64
+
65
+ TableSelectedAction.propTypes = {
66
+ action: PropTypes.node,
67
+ dense: PropTypes.bool,
68
+ numSelected: PropTypes.number,
69
+ onSelectAllRows: PropTypes.func,
70
+ rowCount: PropTypes.number,
71
+ sx: PropTypes.object,
72
+ };
@@ -0,0 +1 @@
1
+ export { default } from "./TableSelectedAction";
package/src/lib/index.js CHANGED
@@ -8,3 +8,16 @@ export { default as SparkleInput } from "./SparkleInput/SparkleInput";
8
8
  export { default as StepComponent } from "./StepComponent/StepComponent";
9
9
  export { default as SvgColor } from "./SvgColor";
10
10
  export { default as ProjectWizard } from "./ProjectWizard";
11
+ export { default as CustomPopover } from "./CustomPopover/CustomPopover";
12
+ export { default as usePopover } from "./CustomPopover/usePopover";
13
+ export { default as Image } from "./Image/Image";
14
+ export { default as Label } from "./Label/Label";
15
+ export { default as Scrollbar } from "./Scrollbar/Scrollbar";
16
+ export { default as SearchNotFound } from "./SearchNotFound/SearchNotFound";
17
+ export { default as CustomBreadcrumbs } from "./CustomBreadcrumbs/CustomBreadcrumbs";
18
+ export { default as FormProvider } from "./FormProvider/FormProvider";
19
+ export { default as RHFTextField } from "./RHFTextfield/RHFTextfield";
20
+ export { default as TableHeadCustom } from "./TableHeadCustom/TableHeadCustom";
21
+ export { default as TableSelectedAction } from "./TableSelectedAction/TableSelectedAction";
22
+ export { default as useTable } from "./useTable/useTable";
23
+ export { default as useChart } from "./useChart/useChart";
@@ -0,0 +1,179 @@
1
+ import { alpha, useTheme } from "@mui/material/styles";
2
+
3
+ import merge from "lodash/merge";
4
+ import { useResponsive } from "src/hooks/use-responsive";
5
+
6
+ export default function useChart(options) {
7
+ const theme = useTheme();
8
+
9
+ const smUp = useResponsive("up", "sm");
10
+
11
+ const LABEL_TOTAL = {
12
+ show: true,
13
+ label: "Total",
14
+ color: theme.palette.text.secondary,
15
+ fontSize: theme.typography.subtitle2.fontSize,
16
+ fontWeight: theme.typography.subtitle2.fontWeight,
17
+ lineHeight: theme.typography.subtitle2.lineHeight,
18
+ };
19
+
20
+ const LABEL_VALUE = {
21
+ offsetY: 8,
22
+ color: theme.palette.text.primary,
23
+ fontSize: theme.typography.h3.fontSize,
24
+ fontWeight: theme.typography.h3.fontWeight,
25
+ lineHeight: theme.typography.h3.lineHeight,
26
+ };
27
+
28
+ const baseOptions = {
29
+ colors: [
30
+ theme.palette.primary.main,
31
+ theme.palette.warning.main,
32
+ theme.palette.info.main,
33
+ theme.palette.error.main,
34
+ theme.palette.success.main,
35
+ theme.palette.warning.dark,
36
+ theme.palette.success.darker,
37
+ theme.palette.info.dark,
38
+ theme.palette.info.darker,
39
+ ],
40
+
41
+ chart: {
42
+ toolbar: { show: false },
43
+ zoom: { enabled: false },
44
+ foreColor: theme.palette.text.disabled,
45
+ fontFamily: theme.typography.fontFamily,
46
+ },
47
+
48
+ states: {
49
+ hover: {
50
+ filter: {
51
+ type: "lighten",
52
+ value: 0.04,
53
+ },
54
+ },
55
+ active: {
56
+ filter: {
57
+ type: "darken",
58
+ value: 0.88,
59
+ },
60
+ },
61
+ },
62
+ fill: {
63
+ opacity: 1,
64
+ gradient: {
65
+ type: "vertical",
66
+ shadeIntensity: 0,
67
+ opacityFrom: 0.4,
68
+ opacityTo: 0,
69
+ stops: [0, 100],
70
+ },
71
+ },
72
+ dataLabels: {
73
+ enabled: false,
74
+ },
75
+ stroke: {
76
+ width: 3,
77
+ curve: "smooth",
78
+ lineCap: "round",
79
+ },
80
+ grid: {
81
+ strokeDashArray: 3,
82
+ borderColor: theme.palette.divider,
83
+ xaxis: {
84
+ lines: {
85
+ show: false,
86
+ },
87
+ },
88
+ },
89
+ xaxis: {
90
+ axisBorder: { show: false },
91
+ axisTicks: { show: false },
92
+ },
93
+ markers: {
94
+ size: 0,
95
+ strokeColors: theme.palette.background.paper,
96
+ },
97
+ tooltip: {
98
+ theme: false,
99
+ x: {
100
+ show: true,
101
+ },
102
+ },
103
+ legend: {
104
+ show: true,
105
+ fontSize: 13,
106
+ position: "top",
107
+ horizontalAlign: "right",
108
+ markers: {
109
+ radius: 12,
110
+ },
111
+ fontWeight: 500,
112
+ itemMargin: {
113
+ horizontal: 8,
114
+ },
115
+ labels: {
116
+ colors: theme.palette.text.primary,
117
+ },
118
+ },
119
+ plotOptions: {
120
+ bar: {
121
+ borderRadius: smUp ? 3 : 1,
122
+ columnWidth: "28%",
123
+ borderRadiusApplication: "end",
124
+ borderRadiusWhenStacked: "last",
125
+ },
126
+ pie: {
127
+ donut: {
128
+ labels: {
129
+ show: true,
130
+ value: LABEL_VALUE,
131
+ total: LABEL_TOTAL,
132
+ },
133
+ },
134
+ },
135
+
136
+ radialBar: {
137
+ track: {
138
+ strokeWidth: "100%",
139
+ background: alpha(theme.palette.grey[500], 0.16),
140
+ },
141
+ dataLabels: {
142
+ value: LABEL_VALUE,
143
+ total: LABEL_TOTAL,
144
+ },
145
+ },
146
+ radar: {
147
+ polygons: {
148
+ fill: { colors: ["transparent"] },
149
+ strokeColors: theme.palette.divider,
150
+ connectorColors: theme.palette.divider,
151
+ },
152
+ },
153
+ polarArea: {
154
+ rings: {
155
+ strokeColor: theme.palette.divider,
156
+ },
157
+ spokes: {
158
+ connectorColors: theme.palette.divider,
159
+ },
160
+ },
161
+ },
162
+ responsive: [
163
+ {
164
+ breakpoint: theme.breakpoints.values.sm,
165
+ options: {
166
+ plotOptions: { bar: { columnWidth: "40%" } },
167
+ },
168
+ },
169
+ {
170
+ breakpoint: theme.breakpoints.values.md,
171
+ options: {
172
+ plotOptions: { bar: { columnWidth: "32%" } },
173
+ },
174
+ },
175
+ ],
176
+ };
177
+
178
+ return merge(baseOptions, options);
179
+ }
@@ -0,0 +1,121 @@
1
+ import { useCallback, useState } from "react";
2
+
3
+ export default function useTable(props) {
4
+ const [dense, setDense] = useState(!!props?.defaultDense);
5
+
6
+ const [page, setPage] = useState(props?.defaultCurrentPage || 0);
7
+
8
+ const [orderBy, setOrderBy] = useState(props?.defaultOrderBy || "name");
9
+
10
+ const [rowsPerPage, setRowsPerPage] = useState(
11
+ props?.defaultRowsPerPage || 5
12
+ );
13
+
14
+ const [order, setOrder] = useState(props?.defaultOrder || "asc");
15
+
16
+ const [selected, setSelected] = useState(props?.defaultSelected || []);
17
+
18
+ const onSort = useCallback(
19
+ (id) => {
20
+ const isAsc = orderBy === id && order === "asc";
21
+ if (id !== "") {
22
+ setOrder(isAsc ? "desc" : "asc");
23
+ setOrderBy(id);
24
+ }
25
+ },
26
+ [order, orderBy]
27
+ );
28
+
29
+ const onSelectRow = useCallback(
30
+ (inputValue) => {
31
+ const newSelected = selected.includes(inputValue)
32
+ ? selected.filter((value) => value !== inputValue)
33
+ : [...selected, inputValue];
34
+
35
+ setSelected(newSelected);
36
+ },
37
+ [selected]
38
+ );
39
+
40
+ const onChangeRowsPerPage = useCallback((event) => {
41
+ setPage(0);
42
+ setRowsPerPage(parseInt(event.target.value, 10));
43
+ }, []);
44
+
45
+ const onChangeDense = useCallback((event) => {
46
+ setDense(event.target.checked);
47
+ }, []);
48
+
49
+ const onSelectAllRows = useCallback((checked, inputValue) => {
50
+ if (checked) {
51
+ setSelected(inputValue);
52
+ return;
53
+ }
54
+ setSelected([]);
55
+ }, []);
56
+
57
+ const onChangePage = useCallback((event, newPage) => {
58
+ setPage(newPage);
59
+ }, []);
60
+
61
+ const onResetPage = useCallback(() => {
62
+ setPage(0);
63
+ }, []);
64
+
65
+ const onUpdatePageDeleteRow = useCallback(
66
+ (totalRowsInPage) => {
67
+ setSelected([]);
68
+ if (page) {
69
+ if (totalRowsInPage < 2) {
70
+ setPage(page - 1);
71
+ }
72
+ }
73
+ },
74
+ [page]
75
+ );
76
+
77
+ const onUpdatePageDeleteRows = useCallback(
78
+ ({ totalRows, totalRowsInPage, totalRowsFiltered }) => {
79
+ const totalSelected = selected.length;
80
+
81
+ setSelected([]);
82
+
83
+ if (page) {
84
+ if (totalSelected === totalRowsInPage) {
85
+ setPage(page - 1);
86
+ } else if (totalSelected === totalRowsFiltered) {
87
+ setPage(0);
88
+ } else if (totalSelected > totalRowsInPage) {
89
+ const newPage =
90
+ Math.ceil((totalRows - totalSelected) / rowsPerPage) - 1;
91
+ setPage(newPage);
92
+ }
93
+ }
94
+ },
95
+ [page, rowsPerPage, selected.length]
96
+ );
97
+
98
+ return {
99
+ dense,
100
+ order,
101
+ page,
102
+ orderBy,
103
+ rowsPerPage,
104
+ selected,
105
+ onSelectRow,
106
+ onSelectAllRows,
107
+ onSort,
108
+ onChangePage,
109
+ onChangeDense,
110
+ onResetPage,
111
+ onChangeRowsPerPage,
112
+ onUpdatePageDeleteRow,
113
+ onUpdatePageDeleteRows,
114
+ setPage,
115
+ setDense,
116
+ setOrder,
117
+ setOrderBy,
118
+ setSelected,
119
+ setRowsPerPage,
120
+ };
121
+ }