@campxdev/react-blueprint 0.1.42 → 0.1.43

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,9 +1,10 @@
1
1
  {
2
2
  "name": "@campxdev/react-blueprint",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "main": "./export.ts",
5
5
  "private": false,
6
6
  "dependencies": {
7
+ "@campxdev/campx-web-utils": "^0.1.3",
7
8
  "@emotion/react": "^11.11.4",
8
9
  "@emotion/styled": "^11.11.5",
9
10
  "@mui/icons-material": "^5.15.20",
@@ -11,9 +12,6 @@
11
12
  "@mui/x-data-grid": "^7.5.1",
12
13
  "@storybook/addon-backgrounds": "^8.1.5",
13
14
  "@storybook/addon-designs": "^8.0.2",
14
- "axios": "^1.7.2",
15
- "framer-motion": "^11.2.9",
16
- "js-cookie": "^3.0.5",
17
15
  "@testing-library/jest-dom": "^5.14.1",
18
16
  "@testing-library/react": "^13.0.0",
19
17
  "@testing-library/user-event": "^13.2.1",
@@ -22,11 +20,15 @@
22
20
  "@types/react": "^18.0.0",
23
21
  "@types/react-dom": "^18.3.0",
24
22
  "@types/react-router-dom": "^5.3.3",
23
+ "axios": "^1.7.2",
24
+ "framer-motion": "^11.2.9",
25
+ "js-cookie": "^3.0.5",
25
26
  "lodash": "^4.17.21",
26
27
  "pullstate": "^1.24.0",
27
28
  "react": "^18.3.1",
28
29
  "react-dom": "^18.3.1",
29
30
  "react-error-boundary": "^3.1.4",
31
+ "react-joyride": "^2.8.2",
30
32
  "react-router-dom": "^6.24.0",
31
33
  "react-scripts": "^5.0.1",
32
34
  "storybook-dark-mode": "^4.0.1",
@@ -0,0 +1,68 @@
1
+ export const ToursIcon = () => {
2
+ return (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ width="118"
6
+ height="118"
7
+ viewBox="0 0 118 118"
8
+ >
9
+ <defs>
10
+ <filter
11
+ id="Rectangle_24558"
12
+ x="0"
13
+ y="0"
14
+ width="118"
15
+ height="118"
16
+ filterUnits="userSpaceOnUse"
17
+ >
18
+ <feOffset dx="6" dy="6" />
19
+ <feGaussianBlur stdDeviation="8" result="blur" />
20
+ <feFlood flood-opacity="0.059" />
21
+ <feComposite operator="in" in2="blur" />
22
+ <feComposite in="SourceGraphic" />
23
+ </filter>
24
+ </defs>
25
+ <g
26
+ id="Group_9777"
27
+ data-name="Group 9777"
28
+ transform="translate(-1822 -982)"
29
+ >
30
+ <g
31
+ id="Group_9776"
32
+ data-name="Group 9776"
33
+ transform="translate(1840 1000)"
34
+ >
35
+ <g
36
+ transform="matrix(1, 0, 0, 1, -18, -18)"
37
+ filter="url(#Rectangle_24558)"
38
+ >
39
+ <rect
40
+ id="Rectangle_24558-2"
41
+ data-name="Rectangle 24558"
42
+ width="70"
43
+ height="70"
44
+ rx="35"
45
+ transform="translate(18 18)"
46
+ fill="#fff"
47
+ />
48
+ </g>
49
+ <rect
50
+ id="Rectangle_24559"
51
+ data-name="Rectangle 24559"
52
+ width="54"
53
+ height="54"
54
+ rx="27"
55
+ transform="translate(8 8)"
56
+ fill="#d0d0e3"
57
+ />
58
+ </g>
59
+ <path
60
+ id="sun"
61
+ d="M4.914,11.712a.971.971,0,0,0-.971-.971H2.971a.971.971,0,0,0,0,1.942h.971A.971.971,0,0,0,4.914,11.712Zm.622,4.856-.69.69a.968.968,0,0,0,1.369,1.369l.69-.69a.971.971,0,0,0-1.369-1.369ZM11.712,4.914a.971.971,0,0,0,.971-.971V2.971a.971.971,0,0,0-1.942,0v.971A.971.971,0,0,0,11.712,4.914Zm5.5,2.273a.971.971,0,0,0,.68-.282l.69-.69a.971.971,0,1,0-1.369-1.369l-.641.69a.967.967,0,0,0,.641,1.651ZM5.555,6.9A.968.968,0,0,0,6.924,5.535l-.69-.69A.975.975,0,0,0,4.846,6.215Zm14.9,3.836h-.971a.971.971,0,0,0,0,1.942h.971a.971.971,0,0,0,0-1.942Zm-2.564,5.827a.971.971,0,0,0-1.321,1.321l.69.69a.968.968,0,1,0,1.369-1.369ZM11.712,6.37a5.342,5.342,0,1,0,5.342,5.342A5.342,5.342,0,0,0,11.712,6.37Zm0,8.741a3.4,3.4,0,1,1,3.4-3.4,3.4,3.4,0,0,1-3.4,3.4Zm0,3.4a.971.971,0,0,0-.971.971v.971a.971.971,0,0,0,1.942,0v-.971A.971.971,0,0,0,11.712,18.51Z"
62
+ transform="translate(1863.288 1023.288)"
63
+ fill="#323167"
64
+ />
65
+ </g>
66
+ </svg>
67
+ );
68
+ };
@@ -33,6 +33,7 @@ import { ProductFeaturesIcon } from "./IconComponents/ProductFeaturesIcon";
33
33
  import { ProfileIcon } from "./IconComponents/ProfileIcon";
34
34
  import { RightIcon } from "./IconComponents/RightIcon";
35
35
  import { TicketsIcon } from "./IconComponents/TicketsIcon";
36
+ import { ToursIcon } from "./IconComponents/ToursIcon";
36
37
  import { UnCheckedCheckboxIcon } from "./IconComponents/UncheckCheckBoxIcon";
37
38
  import { UnCheckedRadioIcon } from "./IconComponents/UncheckedRadioIcon";
38
39
  import { Union4Icon } from "./IconComponents/Union4Icon";
@@ -78,4 +79,5 @@ export const Icons = {
78
79
  ExamxIcon,
79
80
  Union4Icon,
80
81
  XIcon,
82
+ ToursIcon,
81
83
  };
@@ -0,0 +1,113 @@
1
+ import { axios } from "@campxdev/campx-web-utils";
2
+ import { IconButton } from "@mui/material";
3
+ import { ReactNode, useEffect, useState, useCallback } from "react";
4
+ import ReactJoyride, { Step, CallBackProps, ACTIONS } from "react-joyride";
5
+ import { ToursIcon } from "../../Assets/Icons/IconComponents/ToursIcon";
6
+ import { Tooltip } from "../Tooltip/Tooltip";
7
+ import { Typography } from "../../DataDisplay/Typography/Typography";
8
+
9
+ export interface TutorialProps {
10
+ steps: Step[];
11
+ children?: ReactNode;
12
+ tourName: string;
13
+ iconPosition?: "left" | "right";
14
+ }
15
+
16
+ export const Tutorial = ({
17
+ steps,
18
+ children,
19
+ tourName,
20
+ iconPosition = "right",
21
+ }: TutorialProps) => {
22
+ const [run, setRun] = useState(false);
23
+ const userTours = localStorage.getItem("userTours") || "[]";
24
+
25
+ const startTour = useCallback(() => {
26
+ setRun(true);
27
+ }, []);
28
+
29
+ useEffect(() => {
30
+ if (userTours && !userTours.includes(tourName)) {
31
+ startTour();
32
+ }
33
+ }, [userTours, tourName, startTour]);
34
+
35
+ const handleJoyrideCallback = (data: CallBackProps) => {
36
+ const { action, status } = data;
37
+
38
+ if (action === ACTIONS.RESET) {
39
+ setRun(false);
40
+ completeTour().catch((err) => {
41
+ console.error("Failed to mark tour as complete:", err);
42
+ });
43
+ }
44
+ };
45
+
46
+ const completeTour = async () => {
47
+ try {
48
+ if (!userTours.includes(tourName)) {
49
+ localStorage.setItem(
50
+ "userTours",
51
+ JSON.stringify([...JSON.parse(userTours), tourName])
52
+ );
53
+ }
54
+ await axios.post("/square/tours/complete", { tourName });
55
+ } catch (error) {
56
+ console.error("Error completing the tour:", error);
57
+ }
58
+ };
59
+
60
+ return (
61
+ <div style={{ textAlign: iconPosition }}>
62
+ <Tooltip
63
+ title={<Typography variant="body1">Start Tour</Typography>}
64
+ placement="left"
65
+ >
66
+ <IconButton
67
+ onClick={startTour}
68
+ style={{ cursor: "pointer" }}
69
+ aria-label={`Start ${tourName} tour`}
70
+ >
71
+ <ToursIcon />
72
+ </IconButton>
73
+ </Tooltip>
74
+
75
+ <ReactJoyride
76
+ callback={handleJoyrideCallback}
77
+ steps={steps}
78
+ continuous={true}
79
+ run={run}
80
+ showSkipButton={true}
81
+ locale={{
82
+ last: "Finish",
83
+ next: "Next",
84
+ skip: "Skip",
85
+ back: "Previous",
86
+ }}
87
+ styles={{
88
+ buttonNext: {
89
+ backgroundColor: "#D27D2D",
90
+ color: "white",
91
+ height: "28px",
92
+ width: "100px",
93
+ padding: "0px",
94
+ fontFamily: "Roboto, sans-serif",
95
+ },
96
+ buttonBack: {
97
+ backgroundColor: "transparent",
98
+ color: "black",
99
+ borderRadius: "4px",
100
+ height: "28px",
101
+ width: "100px",
102
+ gap: "10px",
103
+ marginLeft: "5px",
104
+ padding: "0px",
105
+ border: "1px solid black",
106
+ fontFamily: "Roboto, sans-serif",
107
+ },
108
+ }}
109
+ />
110
+ {children}
111
+ </div>
112
+ );
113
+ };
@@ -1,2 +1,3 @@
1
1
  export * from "./Spinner/Spinner";
2
2
  export * from "./Tooltip/Tooltip";
3
+ export * from "./Tutorial/Tutorial";
@@ -0,0 +1,56 @@
1
+ import { Meta, StoryObj } from "@storybook/react";
2
+ import { Tutorial } from "../../components/Feedback/Tutorial/Tutorial";
3
+
4
+ export default {
5
+ title: "Feedback/Tutorial",
6
+ component: Tutorial,
7
+ parameters: {
8
+ controls: {
9
+ exclude: ["children"],
10
+ },
11
+ },
12
+ argTypes: {
13
+ iconPosition: {
14
+ control: { type: "radio" },
15
+ options: ["left", "right"],
16
+ defaultValue: "right",
17
+ },
18
+ tourName: { control: "text" },
19
+ steps: { control: "object" },
20
+ },
21
+ } as Meta<typeof Tutorial>;
22
+
23
+ export const PrimaryTutorial: StoryObj<typeof Tutorial> = {
24
+ render: (args) => (
25
+ <div>
26
+ {/* Placeholder elements for the tutorial */}
27
+ <div
28
+ className="tutorial-target"
29
+ style={{ margin: "20px", border: "2px solid blue", padding: "10px" }}
30
+ >
31
+ Target 1: This element is the first target of the tutorial.
32
+ </div>
33
+ <div
34
+ className="next-target"
35
+ style={{ margin: "20px", border: "2px solid green", padding: "10px" }}
36
+ >
37
+ Target 2: This element is the next target of the tutorial.
38
+ </div>
39
+
40
+ <Tutorial {...args} />
41
+ </div>
42
+ ),
43
+ args: {
44
+ tourName: "Active Batches",
45
+ steps: [
46
+ {
47
+ target: ".tutorial-target",
48
+ content: "This is my first step",
49
+ },
50
+ {
51
+ target: ".next-target",
52
+ content: "This is the next step",
53
+ },
54
+ ],
55
+ },
56
+ };
@@ -187,8 +187,7 @@ export const getCommonTheme = (mode: Theme) => {
187
187
  styleOverrides: {
188
188
  tooltip: {
189
189
  backgroundColor: ColorTokens.surface.paperBackground,
190
- padding: "20px 30px",
191
- minWidth: "300px",
190
+ padding: "20px 20px",
192
191
  boxShadow: `0px 2px 5px ${ColorTokens.secondary.main}`,
193
192
  border: `1px solid ${ColorTokens.secondary.main}`,
194
193
  },