@yourdash/uikit 1.0.1 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. package/components/box/box.module.scss +1 -1
  2. package/components/box/box.tsx +3 -3
  3. package/components/button/button.module.scss +3 -3
  4. package/components/button/button.tsx +2 -1
  5. package/components/buttonLink/buttonLink.module.scss +5 -1
  6. package/components/buttonLink/buttonLink.tsx +13 -12
  7. package/components/buttonWithIcon/buttonWithIcon.module.scss +56 -0
  8. package/components/buttonWithIcon/buttonWithIcon.tsx +36 -0
  9. package/components/card/card.module.scss +6 -6
  10. package/components/card/card.tsx +23 -20
  11. package/components/container/container.module.scss +20 -0
  12. package/components/container/container.tsx +22 -0
  13. package/components/contextMenu/contextMenu.tsx +1 -1
  14. package/components/contextMenu/contextMenuRoot.module.scss +1 -1
  15. package/components/contextMenu/contextMenuRoot.tsx +83 -83
  16. package/components/flex/flex.module.scss +31 -19
  17. package/components/flex/flex.tsx +23 -2
  18. package/components/heading/heading.module.scss +1 -1
  19. package/components/heading/heading.tsx +1 -1
  20. package/components/icon/icon.tsx +1 -1
  21. package/components/iconButton/iconButton.module.scss +1 -1
  22. package/components/iconButton/iconButton.tsx +3 -3
  23. package/components/image/image.module.scss +72 -1
  24. package/components/image/image.tsx +65 -10
  25. package/components/link/link.module.scss +1 -1
  26. package/components/link/link.tsx +1 -1
  27. package/components/progressBar/progressBar.module.scss +25 -0
  28. package/components/progressBar/progressBar.tsx +21 -0
  29. package/components/redirect/redirect.tsx +1 -1
  30. package/components/separator/separator.module.scss +9 -4
  31. package/components/separator/separator.tsx +3 -3
  32. package/components/spinner/spinner.module.scss +1 -6
  33. package/components/spinner/spinner.tsx +1 -1
  34. package/components/subtext/subtext.module.scss +1 -1
  35. package/components/subtext/subtext.tsx +1 -1
  36. package/components/tag/tag.module.scss +13 -0
  37. package/components/tag/tag.tsx +21 -0
  38. package/components/text/text.module.scss +1 -1
  39. package/components/text/text.tsx +1 -1
  40. package/components/textButton/textButton.module.scss +1 -1
  41. package/components/textButton/textButton.tsx +1 -1
  42. package/components/textInput/textInput.module.scss +1 -1
  43. package/components/textInput/textInput.tsx +40 -10
  44. package/components/toast/toast.module.scss +71 -31
  45. package/components/toast/toast.ts +12 -0
  46. package/components/toast/toastAction.ts +12 -0
  47. package/components/toast/toastContext.ts +5 -3
  48. package/components/toast/toasts.tsx +99 -0
  49. package/core/decrementLevel.tsx +13 -13
  50. package/core/incrementLevel.tsx +1 -1
  51. package/core/level.tsx +1 -1
  52. package/core/remToPx.ts +8 -0
  53. package/core/root.tsx +26 -32
  54. package/core/toast.ts +18 -17
  55. package/imports.d.ts +81 -0
  56. package/package.json +9 -40
  57. package/theme/defaultTheme.module.scss +16 -4
  58. package/theme/themeValues.scss +8 -5
  59. package/tsconfig.json +19 -9
  60. package/utilityComponent/hasBeenShown/hasBeenShown.tsx +47 -0
  61. package/utilityComponent/onInView/onInView.tsx +83 -0
  62. package/views/carousel/carousel.module.scss +77 -0
  63. package/views/carousel/carousel.tsx +138 -0
  64. package/views/header/header.module.scss +16 -0
  65. package/views/header/header.tsx +28 -0
  66. package/views/infiniteScroll/infiniteScroll.module.scss +26 -0
  67. package/views/infiniteScroll/infiniteScroll.tsx +90 -0
  68. package/views/navBar/components/navImage/navImage.module.scss +7 -0
  69. package/views/navBar/components/navImage/navImage.tsx +15 -0
  70. package/views/navBar/components/navTitle/navTitle.tsx +13 -0
  71. package/views/navBar/navBar.module.scss +22 -0
  72. package/views/navBar/navBar.tsx +37 -0
  73. package/views/onBoarding/onBoarding.module.scss +84 -0
  74. package/views/onBoarding/onBoarding.tsx +138 -0
  75. package/views/panAndZoom/panAndZoom.tsx +121 -114
  76. package/views/sidebar/Sidebar.module.scss +49 -0
  77. package/views/sidebar/Sidebar.tsx +30 -0
  78. package/views/sidebar/SidebarContainer.module.scss +22 -0
  79. package/views/sidebar/SidebarContainer.tsx +38 -0
  80. package/views/sidebar/SidebarContext.tsx +15 -0
  81. package/views/sidebar/SidebarToggleButton.tsx +25 -0
  82. package/components/toast/toast.tsx +0 -65
@@ -0,0 +1,77 @@
1
+ @use "@yourdash/uikit/theme/themeValues" as *;
2
+
3
+ .containerComponent {
4
+ display: flex;
5
+ flex-direction: row;
6
+ max-width: 100%;
7
+ height: 24rem;
8
+ position: relative;
9
+ padding: 0;
10
+ overflow: hidden;
11
+ }
12
+
13
+ .component {
14
+ display: flex;
15
+ align-items: center;
16
+ max-width: 100%;
17
+ height: 24rem;
18
+ gap: 0.5rem;
19
+ padding: var(#{$theme+$padding});
20
+ flex-direction: row;
21
+ overflow-x: auto;
22
+ scroll-snap-type: x mandatory;
23
+ scroll-snap-stop: always;
24
+ scrollbar-width: none;
25
+ padding-bottom: 2.5rem;
26
+
27
+ &::-webkit-scrollbar {
28
+ display: none;
29
+ }
30
+ }
31
+
32
+ .page {
33
+ display: flex;
34
+ width: 80%;
35
+ height: 100%;
36
+ flex-shrink: 0;
37
+ scroll-snap-align: center;
38
+
39
+ &:first-of-type {
40
+ margin-left: calc(20% + var(#{$theme+$gap}));
41
+ }
42
+
43
+ &:last-of-type {
44
+ margin-right: calc(20% + var(#{$theme+$gap}));
45
+ }
46
+ }
47
+
48
+ .controls {
49
+ position: absolute;
50
+ bottom: 0;
51
+ left: 50%;
52
+ transform: translateX(-50%);
53
+ display: flex;
54
+ flex-direction: row;
55
+ gap: var(#{$theme+$gap});
56
+ }
57
+
58
+ .indicator {
59
+ display: flex;
60
+ flex-direction: row;
61
+ gap: var(#{$theme+$gap});
62
+ padding: calc(var(#{$theme+$padding}) / 2);
63
+ border-radius: var(#{$theme+$radius});
64
+
65
+ .pageIndicator {
66
+ background-color: var(#{$theme+$color});
67
+ padding: 0.5rem;
68
+ border-radius: var(#{$theme+$radius});
69
+ transition: var(#{$theme+$transition});
70
+ position: relative;
71
+
72
+ &.selected {
73
+ padding-right: 1.5rem;
74
+ padding-left: 1.5rem;
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,138 @@
1
+ import page from "@yourdash/web/src/deprecatedLogin/Page.tsx";
2
+ import React, { useEffect, useRef, useState } from "react";
3
+ import Card from "../../components/card/card.tsx";
4
+ import Container from "../../components/container/container.tsx";
5
+ import { UKIcon } from "../../components/icon/iconDictionary.ts";
6
+ import IconButton from "../../components/iconButton/iconButton.tsx";
7
+ import styles from "./carousel.module.scss";
8
+ import clippy from "@yourdash/shared/web/helpers/clippy.ts";
9
+
10
+ const Carousel: React.FC<{
11
+ items: { element: React.ReactElement; id: string }[];
12
+ className?: string;
13
+ }> = ({ items, className }) => {
14
+ const scrollRef = useRef<HTMLDivElement>(null);
15
+ const [currentPage, setCurrentPage] = useState<number>(0);
16
+
17
+ useEffect(() => {
18
+ const scrollElement = scrollRef.current;
19
+
20
+ if (!scrollElement) return;
21
+
22
+ console.log(Array.from(scrollElement.children));
23
+
24
+ let timer: Timer;
25
+ let listener = () => {
26
+ clearTimeout(timer);
27
+ timer = setTimeout(function () {
28
+ Array.from(scrollElement.children).forEach((ele: Element, index: number) => {
29
+ if (
30
+ Math.abs(
31
+ ele.getBoundingClientRect().left +
32
+ ele.getBoundingClientRect().width / 2 -
33
+ (scrollElement.getBoundingClientRect().left + scrollElement.getBoundingClientRect().width / 2),
34
+ ) <
35
+ ele.getBoundingClientRect().width / 2
36
+ ) {
37
+ setCurrentPage(index);
38
+ return;
39
+ }
40
+ });
41
+ }, 25);
42
+ };
43
+
44
+ scrollElement.addEventListener("scroll", listener);
45
+
46
+ return () => {
47
+ scrollElement.removeEventListener("scroll", listener);
48
+ clearTimeout(timer);
49
+ };
50
+ }, []);
51
+
52
+ return (
53
+ <Container className={clippy(styles.containerComponent, className)}>
54
+ <div
55
+ className={styles.component}
56
+ ref={scrollRef}
57
+ >
58
+ {items.map((child) => {
59
+ return (
60
+ <div
61
+ key={child.id}
62
+ className={styles.page}
63
+ >
64
+ {child.element}
65
+ </div>
66
+ );
67
+ })}
68
+ </div>
69
+ <div className={styles.controls}>
70
+ <IconButton
71
+ accessibleLabel={"previous page"}
72
+ icon={UKIcon.ChevronLeft}
73
+ className={styles.pageControl}
74
+ onClick={() => {
75
+ const scrollElement = scrollRef.current;
76
+
77
+ if (!scrollElement) {
78
+ return;
79
+ }
80
+
81
+ const carouselTargetPage = scrollElement.children[currentPage - 1] as HTMLDivElement;
82
+
83
+ if (!carouselTargetPage) {
84
+ return;
85
+ }
86
+
87
+ carouselTargetPage.scrollIntoView({ behavior: "smooth" });
88
+ }}
89
+ />
90
+ <Card className={styles.indicator}>
91
+ {items.map((page, index) => {
92
+ return (
93
+ <button
94
+ key={page.id}
95
+ className={clippy(styles.pageIndicator, index === currentPage && styles.selected)}
96
+ onClick={() => {
97
+ const scrollElement = scrollRef.current;
98
+
99
+ if (!scrollElement) {
100
+ return;
101
+ }
102
+
103
+ scrollElement.scrollIntoView({ behavior: "smooth" });
104
+
105
+ const carouselTargetPage = scrollElement.children[index] as HTMLDivElement;
106
+
107
+ carouselTargetPage.scrollIntoView({ behavior: "smooth" });
108
+ }}
109
+ />
110
+ );
111
+ })}
112
+ </Card>
113
+ <IconButton
114
+ accessibleLabel={"next page"}
115
+ icon={UKIcon.ChevronRight}
116
+ className={styles.pageControl}
117
+ onClick={() => {
118
+ const scrollElement = scrollRef.current;
119
+
120
+ if (!scrollElement) {
121
+ return;
122
+ }
123
+
124
+ const carouselTargetPage = scrollElement.children[currentPage + 1] as HTMLDivElement;
125
+
126
+ if (!carouselTargetPage) {
127
+ return;
128
+ }
129
+
130
+ carouselTargetPage.scrollIntoView({ behavior: "smooth" });
131
+ }}
132
+ />
133
+ </div>
134
+ </Container>
135
+ );
136
+ };
137
+
138
+ export default Carousel;
@@ -0,0 +1,16 @@
1
+ /*!
2
+ * Copyright ©2024 Ewsgit <https://ewsgit.uk> and YourDash <https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ @use "@yourdash/uikit/theme/themeValues" as *;
7
+
8
+ .view {
9
+ width: 100%;
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ padding: var(#{$theme+$padding});
14
+ padding-top: calc(var(#{$theme+$padding}) * 4);
15
+ padding-bottom: calc(var(#{$theme+$padding}) * 4);
16
+ }
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit <https://ewsgit.uk> and YourDash <https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ import React from "react";
7
+ import Heading from "../../components/heading/heading.tsx";
8
+ import styles from "./header.module.scss";
9
+
10
+ const Header: React.FC<{ backgroundImage?: string; heading: string }> = ({ backgroundImage, heading }) => {
11
+ return (
12
+ <>
13
+ <div
14
+ className={styles.view}
15
+ style={
16
+ backgroundImage ? { backgroundImage: backgroundImage } : { backgroundImage: "linear-gradient(-45deg, #ff8093aa, #ffd264aa)" }
17
+ }
18
+ >
19
+ <Heading
20
+ level={1}
21
+ text={heading}
22
+ />
23
+ </div>
24
+ </>
25
+ );
26
+ };
27
+
28
+ export default Header;
@@ -0,0 +1,26 @@
1
+ /*!
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ @use "@yourdash/uikit/theme/themeValues" as *;
7
+
8
+ .component {
9
+ display: flex;
10
+ flex-direction: column;
11
+ width: 100%;
12
+ height: 100%;
13
+ gap: 1rem;
14
+ align-items: center;
15
+ }
16
+
17
+ .items {
18
+ height: 100%;
19
+ }
20
+
21
+ .endOfItems {
22
+ text-align: center;
23
+ padding: var(#{$theme+$padding});
24
+ gap: var(#{$theme+$gap});
25
+ width: calc(100% - calc(var(#{$theme+$padding}) * 2));
26
+ }
@@ -0,0 +1,90 @@
1
+ /*
2
+ * Copyright ©2024 Ewsgit<https://ewsgit.uk> and YourDash<https://yourdash.ewsgit.uk> contributors.
3
+ * YourDash is licensed under the MIT License. (https://mit.ewsgit.uk)
4
+ */
5
+
6
+ import clippy from "@yourdash/shared/web/helpers/clippy.ts";
7
+ import React, { useEffect, useState } from "react";
8
+ import Heading from "../../components/heading/heading.tsx";
9
+ import Separator from "../../components/separator/separator.tsx";
10
+ import Text from "../../components/text/text.tsx";
11
+ import styles from "./infiniteScroll.module.scss";
12
+
13
+ const InfiniteScroll: React.FC<{
14
+ children: React.ReactNode | React.ReactNode[];
15
+ fetchNextPage: (nextPageNumber: number) => Promise<{ hasAnotherPage?: boolean }>;
16
+ containerClassName?: string;
17
+ className?: string;
18
+ resetState?: string;
19
+ }> = ({ children, fetchNextPage, containerClassName, className, resetState }) => {
20
+ const endOfItemsRef = React.useRef<HTMLDivElement>(null);
21
+ const lastFetchedPage = React.useRef<number>(-1);
22
+ const [isLoading, setIsLoading] = useState<boolean>(false);
23
+ const [isLastPage, setIsLastPage] = useState<boolean>(false);
24
+
25
+ useEffect(() => {
26
+ lastFetchedPage.current = -1;
27
+ setIsLoading(false);
28
+ setIsLastPage(false);
29
+ fetchNextPageWrapper();
30
+ }, [resetState]);
31
+
32
+ async function fetchNextPageWrapper() {
33
+ if (isLoading) return;
34
+ setIsLoading(true);
35
+ const { hasAnotherPage } = await fetchNextPage(lastFetchedPage.current + 1);
36
+ lastFetchedPage.current++;
37
+ setIsLoading(false);
38
+ setIsLastPage(hasAnotherPage || false);
39
+ }
40
+
41
+ useEffect(() => {
42
+ if (!endOfItemsRef.current) return;
43
+
44
+ const element: HTMLDivElement = endOfItemsRef.current;
45
+
46
+ const observer = new IntersectionObserver((elem) => {
47
+ console.log("observer update");
48
+ const isVisible = elem[0].isIntersecting;
49
+
50
+ if (isVisible) fetchNextPageWrapper();
51
+ });
52
+
53
+ observer.observe(element);
54
+ }, []);
55
+
56
+ // TODO: Use interaction observer to detect when the last item is shown on the screen and fetch the next page
57
+
58
+ return (
59
+ <div className={clippy(containerClassName, styles.component)}>
60
+ {/* @ts-ignore */}
61
+ {children?.length > 0 ? (
62
+ <div className={clippy(className, styles.items)}>{children}</div>
63
+ ) : (
64
+ <div className={"text-center"}>
65
+ <Heading
66
+ level={1}
67
+ text={"Whoops."}
68
+ />
69
+ <Separator direction={"column"} />
70
+ <Text text={"It looks like nothing could be found..."} />
71
+ </div>
72
+ )}
73
+ <div
74
+ ref={endOfItemsRef}
75
+ className={styles.endOfItems}
76
+ >
77
+ {isLoading && <Text text={"Loading more content"} />}
78
+ <Separator direction={"column"} />
79
+ {isLastPage && (
80
+ <Text
81
+ text={"No more items to load"}
82
+ className={styles.endOfItems}
83
+ />
84
+ )}
85
+ </div>
86
+ </div>
87
+ );
88
+ };
89
+
90
+ export default InfiniteScroll;
@@ -0,0 +1,7 @@
1
+ @use "@yourdash/uikit/theme/themeValues" as *;
2
+
3
+ .component {
4
+ height: calc(var(--nav-height) - var(#{$theme+$padding}));
5
+ aspect-ratio: 1 / 1;
6
+ border-radius: 0;
7
+ }
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import Image from "../../../../components/image/image.tsx";
3
+ import styles from "./navImage.module.scss";
4
+
5
+ const NavImage: React.FC<{ src: string }> = ({ src }) => {
6
+ return (
7
+ <Image
8
+ accessibleLabel=""
9
+ src={src}
10
+ className={styles.component}
11
+ />
12
+ );
13
+ };
14
+
15
+ export default NavImage;
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import Heading from "../../../../components/heading/heading.tsx";
3
+
4
+ const NavTitle: React.FC<{ title: string }> = ({ title }) => {
5
+ return (
6
+ <Heading
7
+ text={title}
8
+ level={2}
9
+ />
10
+ );
11
+ };
12
+
13
+ export default NavTitle;
@@ -0,0 +1,22 @@
1
+ @use "@yourdash/uikit/theme/themeValues" as *;
2
+
3
+ .component {
4
+ --nav-height: calc(2rem + var(#{$theme+$padding}));
5
+
6
+ width: 100%;
7
+ height: calc(var(--nav-height) + calc(var(#{$theme+$padding}) * 2));
8
+ border-top: 0;
9
+ border-left: 0;
10
+ border-right: 0;
11
+ padding: var(#{$theme+$padding});
12
+ display: grid;
13
+ grid-template-columns: auto 1fr auto;
14
+ justify-content: center;
15
+ align-items: center;
16
+ }
17
+
18
+ .segment {
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ }
@@ -0,0 +1,37 @@
1
+ import React from "react";
2
+ import Box from "../../components/box/box.tsx";
3
+ import styles from "./navBar.module.scss";
4
+ import Flex from "../../components/flex/flex.tsx";
5
+ import clippy from "@yourdash/shared/web/helpers/clippy.ts";
6
+
7
+ const NavBar: React.FC<{
8
+ leftSection?: React.ReactElement | React.ReactElement[];
9
+ centerSection?: React.ReactElement | React.ReactElement[];
10
+ rightSection?: React.ReactElement | React.ReactElement[];
11
+ className?: string;
12
+ }> = ({ leftSection, centerSection, rightSection, className }) => {
13
+ return (
14
+ <Box className={clippy(styles.component, className)}>
15
+ <Flex
16
+ className={styles.segment}
17
+ direction="row"
18
+ >
19
+ {leftSection}
20
+ </Flex>
21
+ <Flex
22
+ className={styles.segment}
23
+ direction="row"
24
+ >
25
+ {centerSection}
26
+ </Flex>
27
+ <Flex
28
+ className={styles.segment}
29
+ direction="row"
30
+ >
31
+ {rightSection}
32
+ </Flex>
33
+ </Box>
34
+ );
35
+ };
36
+
37
+ export default NavBar;
@@ -0,0 +1,84 @@
1
+ @use "@yourdash/uikit/theme/themeValues" as *;
2
+
3
+ .page {
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ flex-direction: column;
8
+ width: 100%;
9
+ height: 100%;
10
+ position: relative;
11
+ animation: fadeIn 1s 0s cubic-bezier(0.215, 0.610, 0.355, 1);
12
+
13
+ &::before {
14
+ content: "";
15
+ //noinspection CssUnknownTarget
16
+ background-image: url("/assets/productLogos/yourdash.svg");
17
+ background-size: 20rem;
18
+ background-repeat: repeat;
19
+ width: 1000rem;
20
+ height: 1000rem;
21
+ position: absolute;
22
+ filter: blur(0.25rem) grayscale(1);
23
+ opacity: 0.1;
24
+ transform: rotate(-45deg);
25
+ z-index: -1;
26
+ }
27
+
28
+ @keyframes fadeIn {
29
+ from {
30
+ transform: translateY(2.5rem);
31
+ opacity: 0;
32
+ }
33
+ to {
34
+ transform: translateY(0);
35
+ opacity: 1;
36
+ }
37
+ }
38
+ }
39
+
40
+ .card {
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ flex-direction: column;
45
+ gap: calc(var(#{$theme+$gap}) * 2);
46
+ padding: 2rem;
47
+ position: relative;
48
+ transition: var(--transition);
49
+ }
50
+
51
+ .cardContainer {
52
+ box-shadow: #00000088 0 0 4rem;
53
+ }
54
+
55
+ .goBackButton {
56
+ position: absolute;
57
+ top: var(#{$theme+$padding});
58
+ left: var(#{$theme+$padding});
59
+ }
60
+
61
+ .headerImage {
62
+ height: 16rem;
63
+ }
64
+
65
+ .header {
66
+ line-height: 1;
67
+ text-align: center;
68
+ }
69
+
70
+ .body {
71
+ text-align: center;
72
+ }
73
+
74
+ .actions {
75
+ }
76
+
77
+ .action {
78
+ }
79
+
80
+ .actionWithoutIcon {
81
+ }
82
+
83
+ .actionWithIcon {
84
+ }
@@ -0,0 +1,138 @@
1
+ import * as React from "react";
2
+ import Card from "../../components/card/card.tsx";
3
+ import { UKIcon } from "../../components/icon/iconDictionary.ts";
4
+ import IconButton from "../../components/iconButton/iconButton.tsx";
5
+ import Image from "../../components/image/image.tsx";
6
+ import Heading from "../../components/heading/heading.tsx";
7
+ import Text from "../../components/text/text.tsx";
8
+ import ButtonWithIcon from "../../components/buttonWithIcon/buttonWithIcon.tsx";
9
+ import Button from "../../components/button/button.tsx";
10
+ import { Outlet } from "react-router";
11
+ import styles from "./onBoarding.module.scss";
12
+ import Flex from "../../components/flex/flex.tsx";
13
+ import clippy from "@yourdash/shared/web/helpers/clippy.ts";
14
+
15
+ const OnBoarding: React.FC<{
16
+ meta: { id: string };
17
+ pages: {
18
+ headerImage: string;
19
+ header: string;
20
+ body: string;
21
+ actions: { label: string; icon?: UKIcon; onClick: () => void; changeTo?: "next" | "previous" | "remain" | "completed" }[];
22
+ allowGoBack?: boolean;
23
+ }[];
24
+ }> = ({ pages, meta }) => {
25
+ const [currentPage, setCurrentPage] = React.useState<number>(0);
26
+ const page = pages[currentPage];
27
+
28
+ if (localStorage.getItem(`yourdash-application-visited-${meta.id}`) || currentPage > pages.length - 1) {
29
+ localStorage.setItem(`yourdash-application-visited-${meta.id}`, "true");
30
+
31
+ return <Outlet />;
32
+ }
33
+
34
+ return (
35
+ <div className={styles.page}>
36
+ <Card
37
+ className={styles.card}
38
+ containerClassName={styles.cardContainer}
39
+ >
40
+ {page.allowGoBack && (
41
+ <IconButton
42
+ className={clippy(styles.goBackButton, "animate__animated animate__fadeInDown")}
43
+ accessibleLabel="Go back to the last page"
44
+ icon={UKIcon.ChevronLeft}
45
+ onClick={() => {
46
+ setCurrentPage(currentPage - 1);
47
+ }}
48
+ />
49
+ )}
50
+ <Image
51
+ className={styles.headerImage}
52
+ src={page.headerImage}
53
+ accessibleLabel=""
54
+ />
55
+ <Heading
56
+ className={styles.header}
57
+ text={page.header}
58
+ />
59
+ <Text
60
+ className={styles.body}
61
+ text={page.body}
62
+ />
63
+ <Flex
64
+ className={styles.actions}
65
+ direction="row"
66
+ >
67
+ {page.actions.map((action) => {
68
+ if (action.icon) {
69
+ return (
70
+ <>
71
+ <ButtonWithIcon
72
+ key={action.label}
73
+ className={clippy(styles.action, styles.actionWithIcon, "animate__animated animate__fadeInUp")}
74
+ text={action.label}
75
+ icon={action.icon}
76
+ onClick={() => {
77
+ action.onClick();
78
+ if (action.changeTo) {
79
+ switch (action.changeTo) {
80
+ case "next":
81
+ setCurrentPage(currentPage + 1);
82
+ break;
83
+ case "previous":
84
+ if (currentPage > 0) setCurrentPage(currentPage - 1);
85
+ break;
86
+ case "remain":
87
+ break;
88
+ case "completed":
89
+ setCurrentPage(pages.length + 1);
90
+ break;
91
+ default:
92
+ break;
93
+ }
94
+ }
95
+ }}
96
+ />
97
+ </>
98
+ );
99
+ }
100
+
101
+ return (
102
+ <>
103
+ <Button
104
+ key={action.icon}
105
+ className={clippy(styles.action, styles.actionWithoutIcon, "animate__animated animate__fadeInUp")}
106
+ text={action.label}
107
+ onClick={() => {
108
+ action.onClick();
109
+
110
+ if (action.changeTo) {
111
+ switch (action.changeTo) {
112
+ case "next":
113
+ setCurrentPage(currentPage + 1);
114
+ break;
115
+ case "previous":
116
+ if (currentPage > 0) setCurrentPage(currentPage - 1);
117
+ break;
118
+ case "remain":
119
+ break;
120
+ case "completed":
121
+ setCurrentPage(pages.length + 1);
122
+ break;
123
+ default:
124
+ break;
125
+ }
126
+ }
127
+ }}
128
+ />
129
+ </>
130
+ );
131
+ })}
132
+ </Flex>
133
+ </Card>
134
+ </div>
135
+ );
136
+ };
137
+
138
+ export default OnBoarding;