foundry-component-library 0.1.6 → 0.1.8

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.
@@ -1,6 +1,7 @@
1
1
  import Container from "../Container";
2
2
  import styles from "./styles.module.scss";
3
3
  import { NextLink } from "../../types";
4
+ import WavyText from "../TextAnimations/WavyText";
4
5
 
5
6
  const AgencyNumbers = ({
6
7
  heading,
@@ -19,12 +20,7 @@ const AgencyNumbers = ({
19
20
  <Container>
20
21
  <div className={styles.wrapper}>
21
22
  <div className={styles.headingWrapper}>
22
- {heading && (
23
- <div
24
- className={styles.heading}
25
- dangerouslySetInnerHTML={{ __html: heading }}
26
- />
27
- )}
23
+ {heading && <WavyText className={styles.heading} text={heading} />}
28
24
  {Link && (
29
25
  <Link
30
26
  className={`${styles.button} ${styles.desktop}`}
@@ -4,6 +4,7 @@ import styles from "./styles.module.scss";
4
4
  import Container from "../Container";
5
5
  import { NextImage } from "../../types";
6
6
  import useDrag from "../../hooks/useDrag";
7
+ import WavyText from "../TextAnimations/WavyText";
7
8
 
8
9
  const Awards = ({
9
10
  heading,
@@ -29,7 +30,7 @@ const Awards = ({
29
30
  return (
30
31
  <div className={styles.awards}>
31
32
  <Container>
32
- {heading && <div className={styles.heading}>{heading}</div>}
33
+ {heading && <WavyText className={styles.heading} text={heading} />}
33
34
  </Container>
34
35
  <Container noMobilePadding>
35
36
  <div
@@ -5,6 +5,7 @@ import styles from "./styles.module.scss";
5
5
  import Container from "../Container";
6
6
  import { Case, NextImage } from "../../types";
7
7
  import useDrag from "../../hooks/useDrag";
8
+ import WavyText from "../TextAnimations/WavyText";
8
9
 
9
10
  const CaseStudyTeaser = ({
10
11
  heading,
@@ -32,8 +33,10 @@ const CaseStudyTeaser = ({
32
33
  return (
33
34
  <div className={styles.caseStudyTeaser}>
34
35
  <Container>
35
- <div ref={headingRef} className={styles.heading}>
36
- {heading}
36
+ <div ref={headingRef}>
37
+ <WavyText className={styles.heading} text={heading}>
38
+ {heading}
39
+ </WavyText>
37
40
  </div>
38
41
  </Container>
39
42
 
@@ -2,6 +2,8 @@ import styles from "./styles.module.scss";
2
2
  import Container from "../Container";
3
3
  import { translate } from "../../utils";
4
4
  import { NextLink } from "../../types";
5
+ import WavyText from "../TextAnimations/WavyText";
6
+ import FadeInText from "../TextAnimations/FadeInText";
5
7
 
6
8
  const ContactTeaser = ({
7
9
  heading,
@@ -23,11 +25,12 @@ const ContactTeaser = ({
23
25
  <Container>
24
26
  <div className={styles.wrapper}>
25
27
  {heading && (
26
- <div className={`${styles.heading} ${!text ? styles.margin : ""}`}>
27
- {heading}
28
- </div>
28
+ <WavyText
29
+ className={`${styles.heading} ${!text ? styles.margin : ""}`}
30
+ text={heading}
31
+ />
29
32
  )}
30
- {text && <div className={styles.text}>{text}</div>}
33
+ {text && <FadeInText className={styles.text} text={text} />}
31
34
  <Link href={buttonHref} className={styles.button}>
32
35
  {translate(buttonText)}
33
36
  </Link>
@@ -1,26 +1,29 @@
1
1
  "use client";
2
- import { useState } from "react";
2
+ import { useState, useEffect } from "react";
3
3
  import styles from "./styles.module.scss";
4
4
  import Container from "../Container";
5
5
  import Dropdown from "./Dropdown";
6
6
  import { NextImage } from "../../types";
7
+ import { motion, AnimatePresence } from "motion/react";
8
+
9
+ type Brand = {
10
+ data?: {
11
+ title?: string;
12
+ featured?: boolean;
13
+ image?: {
14
+ sourceUrl: string;
15
+ };
16
+ };
17
+ service?: string[];
18
+ industry?: string[];
19
+ };
7
20
 
8
21
  const Logos = ({
9
22
  brands = [],
10
23
  withoutFilters,
11
24
  Image,
12
25
  }: {
13
- brands: {
14
- data?: {
15
- title?: string;
16
- featured?: boolean;
17
- image?: {
18
- sourceUrl: string;
19
- };
20
- };
21
- service?: string[];
22
- industry?: string[];
23
- }[];
26
+ brands: Brand[];
24
27
  withoutFilters?: boolean;
25
28
  Image: NextImage;
26
29
  }) => {
@@ -30,34 +33,43 @@ const Logos = ({
30
33
  });
31
34
  const services: Set<string> = new Set();
32
35
  const industries: Set<string> = new Set();
36
+ const [brandsToShow, setBrandsToShow] = useState<Brand[]>([]);
33
37
 
34
38
  brands.forEach((brand) => {
35
39
  brand.service?.forEach((service) => services.add(service));
36
40
  brand.industry?.forEach((industry) => industries.add(industry));
37
41
  });
38
42
 
39
- let brandsToShow = brands.filter((brand) => {
40
- if (selected.category === "featured" && brand.data?.featured) {
41
- return true;
42
- }
43
- if (
44
- selected.category === "service" &&
45
- brand.service?.includes(selected.tag)
46
- ) {
47
- return true;
48
- }
49
- if (
50
- selected.category === "industry" &&
51
- brand.industry?.includes(selected.tag)
52
- ) {
53
- return true;
54
- }
55
- return false;
56
- });
43
+ useEffect(() => {
44
+ setBrandsToShow([]);
57
45
 
58
- if (withoutFilters) {
59
- brandsToShow = brands;
60
- }
46
+ setTimeout(() => {
47
+ setBrandsToShow(
48
+ brands.filter((brand) => {
49
+ if (selected.category === "featured" && brand.data?.featured) {
50
+ return true;
51
+ }
52
+ if (
53
+ selected.category === "service" &&
54
+ brand.service?.includes(selected.tag)
55
+ ) {
56
+ return true;
57
+ }
58
+ if (
59
+ selected.category === "industry" &&
60
+ brand.industry?.includes(selected.tag)
61
+ ) {
62
+ return true;
63
+ }
64
+ return false;
65
+ })
66
+ );
67
+ }, 400);
68
+
69
+ if (withoutFilters) {
70
+ setBrandsToShow(brands);
71
+ }
72
+ }, [selected]);
61
73
 
62
74
  return (
63
75
  <Container>
@@ -90,20 +102,30 @@ const Logos = ({
90
102
  )}
91
103
 
92
104
  <div className={styles.logos}>
93
- {brandsToShow.map((brand, i) => {
94
- const { data } = brand;
95
- if (!data?.image) return;
105
+ <AnimatePresence>
106
+ {brandsToShow.map((brand, i) => {
107
+ const { data } = brand;
108
+ if (!data?.image) return;
96
109
 
97
- return (
98
- <div key={data?.title || "" + i} className={styles.image}>
99
- <Image
100
- src={data?.image?.sourceUrl || ""}
101
- alt={data?.title || ""}
102
- fill
103
- />
104
- </div>
105
- );
106
- })}
110
+ return (
111
+ <motion.div
112
+ key={data?.title || "" + i}
113
+ className={styles.image}
114
+ initial={{ opacity: 0, y: -10 }}
115
+ animate={{ opacity: 1, y: 0 }}
116
+ exit={{ opacity: 0, y: 10 }}
117
+ transition={{ duration: 0.4 }}
118
+ layout
119
+ >
120
+ <Image
121
+ src={data?.image?.sourceUrl || ""}
122
+ alt={data?.title || ""}
123
+ fill
124
+ />
125
+ </motion.div>
126
+ );
127
+ })}
128
+ </AnimatePresence>
107
129
  </div>
108
130
  </Container>
109
131
  );
@@ -4,7 +4,10 @@ import styles from "./styles.module.scss";
4
4
  import Container from "../Container";
5
5
  import { NextImage, NextLink, PostPreview } from "../../types";
6
6
  import Arrow from "../../assets/svg/arrow.svg";
7
- import useDrag from "../../hooks/useDrag";
7
+ import { motion } from "framer-motion";
8
+ import WavyText from "../TextAnimations/WavyText";
9
+ import FadeInText from "../TextAnimations/FadeInText";
10
+ import PopInText from "../TextAnimations/PopInText";
8
11
 
9
12
  const NewsTeaser = ({
10
13
  caption,
@@ -21,9 +24,8 @@ const NewsTeaser = ({
21
24
  Link: NextLink;
22
25
  Image: NextImage;
23
26
  }) => {
24
- const sectionRef = useRef(null);
25
- const { handleMouseDown, handleMouseMove, handleMouseUp, dragStyle } =
26
- useDrag(sectionRef);
27
+ const wrapperRef = useRef(null);
28
+ const dragStarted = useRef(false);
27
29
 
28
30
  if (!posts) return;
29
31
 
@@ -32,52 +34,77 @@ const NewsTeaser = ({
32
34
  <Container noMobilePadding>
33
35
  <div className={styles.wrapper}>
34
36
  <div className={styles.texts}>
35
- <div className={styles.caption}>{caption}</div>
36
- <div className={styles.heading}>{heading}</div>
37
- <div className={styles.text}>{text}</div>
37
+ <PopInText className={styles.caption} text={caption} />
38
+ <WavyText className={styles.heading} text={heading} />
39
+ <FadeInText className={styles.text} text={text} />
40
+ {/* <div className={styles.text}>{text}</div> */}
38
41
  <Link className={`${styles.button} ${styles.desktop}`} href="/news">
39
42
  Explore
40
43
  </Link>
41
44
  </div>
42
- <div
43
- ref={sectionRef}
44
- className={styles.items}
45
- onMouseDown={handleMouseDown}
46
- onMouseMove={handleMouseMove}
47
- onMouseUp={handleMouseUp}
48
- onMouseLeave={handleMouseUp}
49
- style={dragStyle as React.CSSProperties}
50
- >
51
- {posts.map((post) => {
52
- const { id, title, uri, CustomFieldsPosts: customFields } = post;
45
+ <div ref={wrapperRef} className={styles.newsWrapper}>
46
+ <motion.div
47
+ className={styles.items}
48
+ drag="x"
49
+ dragConstraints={wrapperRef}
50
+ onDragStart={() => (dragStarted.current = true)}
51
+ onDragEnd={() => {
52
+ setTimeout(() => {
53
+ dragStarted.current = false;
54
+ }, 0);
55
+ }}
56
+ >
57
+ {posts.map((post) => {
58
+ const {
59
+ id,
60
+ title,
61
+ uri,
62
+ CustomFieldsPosts: customFields,
63
+ } = post;
53
64
 
54
- return (
55
- <div key={id} className={styles.item}>
56
- <div className={styles.image}>
57
- {customFields.thumbnailImage && (
58
- <Image
59
- src={customFields.thumbnailImage?.sourceUrl}
60
- width={260}
61
- height={220}
62
- alt={title}
63
- />
64
- )}
65
- </div>
66
- <div className={styles.itemTexts}>
67
- <div>
68
- <div className={styles.title}>{title}</div>
69
- <div className={styles.excerpt}>
70
- {customFields.excerpt}
65
+ return (
66
+ <motion.div
67
+ key={id}
68
+ className={styles.item}
69
+ whileHover={{
70
+ y: -10,
71
+ }}
72
+ >
73
+ <div className={styles.image}>
74
+ {customFields.thumbnailImage && (
75
+ <Image
76
+ src={customFields.thumbnailImage?.sourceUrl}
77
+ width={260}
78
+ height={220}
79
+ alt={title}
80
+ />
81
+ )}
82
+ </div>
83
+ <div className={styles.itemTexts}>
84
+ <div>
85
+ <div className={styles.title}>{title}</div>
86
+ <div className={styles.excerpt}>
87
+ {customFields.excerpt}
88
+ </div>
71
89
  </div>
90
+ <Link
91
+ className={styles.more}
92
+ href={`news${uri}`}
93
+ onClick={(e) => {
94
+ if (dragStarted.current) {
95
+ e.preventDefault();
96
+ e.stopPropagation();
97
+ }
98
+ }}
99
+ >
100
+ Read More
101
+ <Arrow />
102
+ </Link>
72
103
  </div>
73
- <Link className={styles.more} href={`news${uri}`}>
74
- Read More
75
- <Arrow />
76
- </Link>
77
- </div>
78
- </div>
79
- );
80
- })}
104
+ </motion.div>
105
+ );
106
+ })}
107
+ </motion.div>
81
108
  </div>
82
109
  <Link className={`${styles.button} ${styles.mobile}`} href="/news">
83
110
  Explore News
@@ -3,6 +3,7 @@
3
3
  .newsTeaser {
4
4
  padding: 64px 0;
5
5
  color: $color-brown;
6
+ overflow: hidden;
6
7
 
7
8
  @media #{$QUERY-sm} {
8
9
  padding: 32px 0;
@@ -65,8 +66,13 @@
65
66
  }
66
67
  }
67
68
 
69
+ .itemsWrapper {
70
+ width: 100%;
71
+ // overflow-x: scroll;
72
+ }
73
+
68
74
  .items {
69
- display: flex;
75
+ display: inline-flex;
70
76
  gap: 20px;
71
77
  }
72
78
 
@@ -3,6 +3,8 @@ import Offices from "../contact/Offices";
3
3
  import styles from "./styles.module.scss";
4
4
  import Container from "../Container";
5
5
  import { NextImage, NextLink, OfficeDetails } from "../../types";
6
+ import PopInText from "../TextAnimations/PopInText";
7
+ import WavyText from "../TextAnimations/WavyText";
6
8
 
7
9
  const OfficesTeaser = ({
8
10
  details,
@@ -16,10 +18,11 @@ const OfficesTeaser = ({
16
18
  <Container noMobilePadding>
17
19
  <div className={styles.officesTeaser}>
18
20
  <div className={styles.texts}>
19
- <div className={styles.caption}>Our Offices</div>
20
- <div
21
+ <PopInText className={styles.caption} text="Our Offices" />
22
+ <WavyText
21
23
  className={styles.heading}
22
- >{`We operate all\nover the world`}</div>
24
+ text={`We operate all\nover the world`}
25
+ />
23
26
  </div>
24
27
 
25
28
  <div className={styles.offices}>
@@ -2,32 +2,52 @@ import { MouseEventHandler } from "react";
2
2
  import styles from "./styles.module.scss";
3
3
  import Plus from "../../assets/svg/plus.svg";
4
4
  import { NextLink } from "../../types";
5
+ import { motion } from "framer-motion";
5
6
 
6
7
  const Tile = ({
7
8
  text,
8
9
  background,
9
10
  href,
11
+ i,
10
12
  onClick,
11
13
  Link,
12
14
  }: {
13
15
  text: string;
14
16
  background: "pink" | "yellow" | "brown" | "blue";
15
17
  href: string;
18
+ i: number;
16
19
  onClick?: MouseEventHandler<HTMLAnchorElement>;
17
20
  Link: NextLink;
18
21
  }) => {
19
22
  return (
20
- <Link
21
- className={`${styles.tile} ${styles[background]}`}
22
- href={href}
23
- onClick={onClick}
24
- draggable="false"
23
+ <motion.div
24
+ className={styles.tileWrapper}
25
+ whileHover={{
26
+ scale: 1.08,
27
+ rotate: i % 2 === 0 ? -3 : 3,
28
+ boxShadow: "0px 10px 20px rgba(0,0,0,0.2)",
29
+ y: [0, Math.random() * 12 - 6, 0],
30
+ transition: {
31
+ y: {
32
+ duration: 2,
33
+ repeat: Infinity,
34
+ ease: "easeInOut",
35
+ },
36
+ },
37
+ }}
25
38
  >
26
- <div className={styles.text}>{text}</div>
27
- <div>
28
- <Plus />
29
- </div>
30
- </Link>
39
+ <Link
40
+ href={href}
41
+ onClick={onClick}
42
+ draggable="false"
43
+ className={`${styles.tile} ${styles[background]}`}
44
+ >
45
+ <div className={styles.text}>{text}</div>
46
+ <div>
47
+ <Plus />
48
+ </div>
49
+ </Link>
50
+ </motion.div>
31
51
  );
32
52
  };
33
53
 
@@ -4,8 +4,8 @@ import Container from "../Container";
4
4
  import styles from "./styles.module.scss";
5
5
  import TextSection from "../TextSection";
6
6
  import Tile from "./Tile";
7
- import useDrag from "../../hooks/useDrag";
8
7
  import { NextLink } from "../../types";
8
+ import { motion } from "framer-motion";
9
9
 
10
10
  const ServiceHubsTeaser = ({
11
11
  caption,
@@ -24,45 +24,49 @@ const ServiceHubsTeaser = ({
24
24
  }[];
25
25
  Link: NextLink;
26
26
  }) => {
27
- const sectionRef = useRef(null);
28
- const {
29
- handleMouseDown,
30
- handleMouseMove,
31
- handleMouseUp,
32
- preventedClick,
33
- dragStyle,
34
- } = useDrag(sectionRef);
27
+ const wrapperRef = useRef(null);
28
+ const dragStarted = useRef(false);
35
29
 
36
30
  return (
37
31
  <div className={styles.benefits}>
38
32
  <TextSection caption={caption} heading={heading} text={text} isSmall />
39
33
  <Container noMobilePadding>
40
- <div
41
- ref={sectionRef}
42
- className={styles.tiles}
43
- onMouseDown={handleMouseDown}
44
- onMouseMove={handleMouseMove}
45
- onMouseUp={handleMouseUp}
46
- onMouseLeave={handleMouseUp}
47
- style={dragStyle as React.CSSProperties}
48
- >
49
- {tiles.map((tile, i) => {
50
- let background: "pink" | "yellow" | "brown" | "blue" = "pink";
51
- if (i % 4 === 1) background = "yellow";
52
- if (i % 4 === 2) background = "brown";
53
- if (i % 4 === 3) background = "blue";
34
+ <div className={styles.wrapper} ref={wrapperRef}>
35
+ <motion.div
36
+ className={styles.tiles}
37
+ drag="x"
38
+ dragConstraints={wrapperRef}
39
+ onDragStart={() => (dragStarted.current = true)}
40
+ onDragEnd={() => {
41
+ setTimeout(() => {
42
+ dragStarted.current = false;
43
+ }, 0);
44
+ }}
45
+ >
46
+ {tiles.map((tile, i) => {
47
+ let background: "pink" | "yellow" | "brown" | "blue" = "pink";
48
+ if (i % 4 === 1) background = "yellow";
49
+ if (i % 4 === 2) background = "brown";
50
+ if (i % 4 === 3) background = "blue";
54
51
 
55
- return (
56
- <Tile
57
- key={tile.id}
58
- text={tile.title}
59
- background={background}
60
- href={tile.uri}
61
- onClick={preventedClick}
62
- Link={Link}
63
- />
64
- );
65
- })}
52
+ return (
53
+ <Tile
54
+ key={tile.id}
55
+ text={tile.title}
56
+ background={background}
57
+ href={tile.uri}
58
+ i={i}
59
+ Link={Link}
60
+ onClick={(e) => {
61
+ if (dragStarted.current) {
62
+ e.preventDefault();
63
+ e.stopPropagation();
64
+ }
65
+ }}
66
+ />
67
+ );
68
+ })}
69
+ </motion.div>
66
70
  </div>
67
71
  </Container>
68
72
  </div>
@@ -1,7 +1,16 @@
1
1
  @use "../variables" as *;
2
2
 
3
+ .benefits {
4
+ overflow: hidden;
5
+ }
6
+
7
+ .wrapper {
8
+ width: 100%;
9
+ // overflow-x: scroll;
10
+ }
11
+
3
12
  .tiles {
4
- display: flex;
13
+ display: inline-flex;
5
14
  gap: 16px;
6
15
  padding-bottom: 64px;
7
16
 
@@ -10,23 +19,16 @@
10
19
  }
11
20
  }
12
21
 
13
- .tile {
14
- flex-shrink: 0;
15
- white-space: pre-wrap;
16
- padding: 16px;
17
- display: flex;
18
- flex-direction: column;
19
- align-items: center;
20
- justify-content: center;
21
- text-align: center;
22
+ .tileWrapper {
23
+ z-index: 0;
24
+ position: relative;
22
25
  width: 360px;
23
26
  max-width: 100%;
24
27
  height: 411px;
25
- box-sizing: border-box;
26
- background-color: $color-pink;
27
- color: $color-brown;
28
- font-size: 34px;
29
- font-family: $font-secondary;
28
+
29
+ &:hover {
30
+ z-index: 1;
31
+ }
30
32
 
31
33
  @media screen and (max-width: $screen-sm) {
32
34
  max-width: 80%;
@@ -44,6 +46,24 @@
44
46
  margin-right: 20px;
45
47
  }
46
48
  }
49
+ }
50
+
51
+ .tile {
52
+ flex-shrink: 0;
53
+ white-space: pre-wrap;
54
+ padding: 16px;
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: center;
58
+ justify-content: center;
59
+ text-align: center;
60
+ box-sizing: border-box;
61
+ background-color: $color-pink;
62
+ color: $color-brown;
63
+ font-size: 34px;
64
+ font-family: $font-secondary;
65
+ width: 100%;
66
+ height: 100%;
47
67
 
48
68
  &.yellow {
49
69
  background-color: $color-yellow;
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { FC } from "react";
3
+ import { motion, Variants, HTMLMotionProps } from "framer-motion";
4
+
5
+ interface Props extends HTMLMotionProps<"div"> {
6
+ text: string;
7
+ delay?: number;
8
+ duration?: number;
9
+ }
10
+
11
+ const FadeInText: FC<Props> = ({
12
+ text,
13
+ delay = 0,
14
+ duration = 0.3,
15
+ ...props
16
+ }: Props) => {
17
+ const container: Variants = {
18
+ hidden: {
19
+ opacity: 0,
20
+ y: 10,
21
+ },
22
+ visible: {
23
+ opacity: 1,
24
+ y: 0,
25
+ },
26
+ };
27
+
28
+ return (
29
+ <motion.div
30
+ variants={container}
31
+ initial="hidden"
32
+ whileInView="visible"
33
+ viewport={{ once: true, margin: "0px 0px -10% 0px" }}
34
+ transition={{
35
+ delay: delay,
36
+ duration: duration,
37
+ }}
38
+ {...props}
39
+ >
40
+ {text}
41
+ </motion.div>
42
+ );
43
+ };
44
+
45
+ export default FadeInText;
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { FC } from "react";
3
+ import { motion, HTMLMotionProps } from "framer-motion";
4
+
5
+ interface Props extends HTMLMotionProps<"div"> {
6
+ text: string;
7
+ delay?: number;
8
+ duration?: number;
9
+ }
10
+
11
+ const PopInText: FC<Props> = ({
12
+ text,
13
+ delay = 0,
14
+ duration = 0.3,
15
+ ...props
16
+ }: Props) => {
17
+ return (
18
+ <div>
19
+ <motion.span
20
+ initial={{ opacity: 0, scale: 0.8 }}
21
+ whileInView={{ opacity: 1, scale: 1 }}
22
+ transition={{ type: "spring", duration: duration, delay: delay }}
23
+ viewport={{ once: true, margin: "0px 0px -10% 0px" }}
24
+ {...props}
25
+ style={{ display: "inline-block" }}
26
+ >
27
+ {text}
28
+ </motion.span>
29
+ </div>
30
+ );
31
+ };
32
+
33
+ export default PopInText;
@@ -0,0 +1,88 @@
1
+ "use client";
2
+ import { FC } from "react";
3
+ import { motion, Variants, HTMLMotionProps } from "framer-motion";
4
+
5
+ interface Props extends HTMLMotionProps<"div"> {
6
+ text: string;
7
+ delay?: number;
8
+ duration?: number;
9
+ }
10
+
11
+ const WavyText: FC<Props> = ({
12
+ text,
13
+ delay = 0,
14
+ duration = 0.05,
15
+ ...props
16
+ }: Props) => {
17
+ const container: Variants = {
18
+ hidden: {
19
+ opacity: 0,
20
+ },
21
+ visible: (i: number = 1) => ({
22
+ opacity: 1,
23
+ transition: { staggerChildren: duration, delayChildren: i * delay },
24
+ }),
25
+ };
26
+
27
+ const child: Variants = {
28
+ visible: {
29
+ opacity: 1,
30
+ y: 0,
31
+ transition: {
32
+ type: "spring",
33
+ damping: 12,
34
+ stiffness: 200,
35
+ },
36
+ },
37
+ hidden: {
38
+ opacity: 0,
39
+ y: 20,
40
+ transition: {
41
+ type: "spring",
42
+ damping: 12,
43
+ stiffness: 200,
44
+ },
45
+ },
46
+ };
47
+
48
+ const words = text.split(/([ \n])/);
49
+
50
+ return (
51
+ <motion.div
52
+ // style={{ display: "flex", flexWrap: "wrap", overflow: "hidden" }}
53
+ variants={container}
54
+ initial="hidden"
55
+ whileInView="visible"
56
+ viewport={{ once: true, margin: "0px 0px -10% 0px" }}
57
+ {...props}
58
+ >
59
+ {words.map((word, i) => {
60
+ let sign = word;
61
+
62
+ if (word === " ") {
63
+ sign = "\u00A0";
64
+ }
65
+
66
+ if (word === "\n") {
67
+ return <br key={Math.random()} />;
68
+ }
69
+
70
+ if (word.includes("<em>")) {
71
+ return <em key={word + i}>{word.replace(/<[^>]*>/g, "")}</em>;
72
+ }
73
+
74
+ return (
75
+ <motion.span
76
+ key={word + i}
77
+ variants={child}
78
+ style={{ display: "inline-block" }}
79
+ >
80
+ {sign}
81
+ </motion.span>
82
+ );
83
+ })}
84
+ </motion.div>
85
+ );
86
+ };
87
+
88
+ export default WavyText;
@@ -1,5 +1,9 @@
1
+ "use client";
1
2
  import styles from "./styles.module.scss";
2
3
  import Container from "../Container";
4
+ import PopInText from "../TextAnimations/PopInText";
5
+ import WavyText from "../TextAnimations/WavyText";
6
+ import FadeInText from "../TextAnimations/FadeInText";
3
7
 
4
8
  const TextSection = ({
5
9
  caption,
@@ -24,14 +28,15 @@ const TextSection = ({
24
28
  return (
25
29
  <Container>
26
30
  <div className={`${styles.section} ${alignStyle} ${themeStyle}`}>
27
- {caption && <div className={styles.caption}>{caption}</div>}
31
+ {caption && <PopInText className={styles.caption} text={caption} />}
28
32
  {heading && (
29
- <div className={`${styles.heading} ${isSmall ? styles.small : ""}`}>
30
- {heading}
31
- </div>
33
+ <WavyText
34
+ className={`${styles.heading} ${isSmall ? styles.small : ""}`}
35
+ text={heading}
36
+ />
32
37
  )}
33
38
  {subheading && <div className={styles.subheading}>{subheading}</div>}
34
- {text && <div className={styles.text}>{text}</div>}
39
+ {text && <FadeInText className={styles.text} text={text} />}
35
40
  </div>
36
41
  </Container>
37
42
  );
@@ -0,0 +1,129 @@
1
+ "use client";
2
+ import { Dispatch, SetStateAction } from "react";
3
+ import styles from "./styles.module.scss";
4
+ import { motion } from "framer-motion";
5
+
6
+ const Mask = ({
7
+ isAnimated,
8
+ setIsAnimated,
9
+ }: {
10
+ isAnimated: boolean;
11
+ setIsAnimated: Dispatch<SetStateAction<boolean>>;
12
+ }) => {
13
+ return (
14
+ <>
15
+ {!isAnimated && (
16
+ <div className={styles.mask}>
17
+ <motion.svg
18
+ key="modal"
19
+ initial={{ opacity: 1, scale: 1 }}
20
+ whileInView={{
21
+ scale: 12,
22
+ opacity: [1, 1, 0],
23
+ transition: {
24
+ duration: 0.5,
25
+ // ease: "linear",
26
+ ease: [1, 0, 0, 1],
27
+ delay: 1,
28
+ },
29
+ }}
30
+ onAnimationComplete={() => {
31
+ setIsAnimated(true);
32
+ }}
33
+ // viewBox="0 0 415 110"
34
+ fill="none"
35
+ xmlns="http://www.w3.org/2000/svg"
36
+ >
37
+ {/* Define the mask */}
38
+ <mask id="circle-mask">
39
+ <rect width="100%" height="100%" fill="white" />
40
+ <motion.g>
41
+ <path
42
+ d="M51.3664 80.0738C52.3787 80.0738 53.2626 80.4516 54.0181 81.2146C54.7735 81.9701 55.1588 82.8539 55.1588 83.8663C55.1588 84.8786 54.7735 85.7624 54.0181 86.5179C53.2551 87.2809 52.3787 87.6587 51.3664 87.6587H4.7924C3.7121 87.6587 2.80555 87.2809 2.08031 86.5179C1.35507 85.7624 1 84.8786 1 83.8663C1 82.8539 1.36262 81.9701 2.08031 81.2146C2.79799 80.4516 3.70454 80.0738 4.7924 80.0738H24.2908V30.2438H4.7924C3.7121 30.2438 2.80555 29.8812 2.08031 29.1635C1.35507 28.4458 1 27.5393 1 26.4514C1 25.4466 1.36262 24.5552 2.08031 23.7997C2.79799 23.0367 3.70454 22.659 4.7924 22.659H24.2908V4.78485C24.2908 3.78009 24.6534 2.88865 25.3711 2.13319C26.0888 1.37773 26.9953 1 28.0832 1H51.374C52.3863 1 53.2702 1.37773 54.0256 2.13319C54.7811 2.8962 55.1664 3.78009 55.1664 4.78485C55.1664 5.86516 54.7811 6.77171 54.0256 7.49695C53.2626 8.22219 52.3863 8.57726 51.374 8.57726H31.8756V22.659H51.374C52.3863 22.659 53.2702 23.0367 54.0256 23.7997C54.7811 24.5552 55.1664 25.4391 55.1664 26.4514C55.1664 27.5317 54.7811 28.4383 54.0256 29.1635C53.2626 29.8887 52.3863 30.2438 51.374 30.2438H31.8756V80.0738H51.374H51.3664Z"
43
+ fill="black"
44
+ />
45
+ <path
46
+ d="M66.5364 87.6601C65.4561 87.6601 64.5495 87.2823 63.8243 86.5193C63.099 85.7639 62.744 84.88 62.744 83.8677V26.4528C62.744 25.448 63.1066 24.5566 63.8243 23.8012C64.542 23.0381 65.4485 22.6604 66.5364 22.6604H113.11C114.123 22.6604 115.007 23.0381 115.762 23.8012C116.518 24.5566 116.903 25.4405 116.903 26.4528V83.8677C116.903 84.88 116.518 85.7639 115.762 86.5193C114.999 87.2823 114.123 87.6601 113.11 87.6601H66.5364ZM70.3288 60.5769C70.3288 64.12 71.1976 67.3684 72.9276 70.3298C74.6576 73.2912 77.007 75.6558 79.9684 77.4236C82.9298 79.1989 86.2161 80.0752 89.8272 80.0752C93.4383 80.0752 96.7094 79.1914 99.633 77.4236C102.557 75.6558 104.899 73.2912 106.674 70.3298C108.442 67.3684 109.326 64.12 109.326 60.5769V49.7436C109.326 46.1325 108.442 42.8614 106.674 39.9377C104.899 37.0141 102.557 34.6722 99.633 32.8969C96.7094 31.1291 93.4383 30.2452 89.8272 30.2452C86.2161 30.2452 82.9298 31.1291 79.9684 32.8969C77.007 34.6722 74.6576 37.0141 72.9276 39.9377C71.1976 42.8614 70.3288 46.1325 70.3288 49.7436V60.5769Z"
47
+ fill="black"
48
+ />
49
+ <path
50
+ d="M151.562 87.6601C146.576 87.6601 142.044 86.4362 137.964 83.981C133.885 81.5257 130.613 78.2546 128.158 74.1751C125.703 70.0956 124.479 65.5629 124.479 60.5769V26.4528C124.479 25.448 124.857 24.5566 125.62 23.8012C126.375 23.0381 127.259 22.6604 128.271 22.6604C129.352 22.6604 130.258 23.0381 130.976 23.8012C131.701 24.5566 132.056 25.4405 132.056 26.4528V60.5769C132.056 64.12 132.94 67.3684 134.708 70.3298C136.476 73.2912 138.84 75.6558 141.802 77.4236C144.763 79.1989 148.012 80.0752 151.555 80.0752C155.166 80.0752 158.445 79.1914 161.413 77.4236C164.375 75.6558 166.717 73.2912 168.454 70.3298C170.184 67.3684 171.053 64.12 171.053 60.5769V26.4528C171.053 25.448 171.438 24.5566 172.194 23.8012C172.957 23.0381 173.833 22.6604 174.846 22.6604C175.926 22.6604 176.832 23.0381 177.558 23.8012C178.275 24.5566 178.638 25.4405 178.638 26.4528V60.5769C178.638 65.5629 177.429 70.0956 175.004 74.1751C172.587 78.2546 169.316 81.5257 165.198 83.981C161.081 86.4362 156.533 87.6601 151.555 87.6601H151.562Z"
51
+ fill="black"
52
+ />
53
+ <path
54
+ d="M186.328 87.6584C185.316 87.6584 184.432 87.2958 183.677 86.5781C182.914 85.8604 182.536 84.9916 182.536 83.9793C182.536 82.899 182.914 81.9698 183.677 81.2143C184.432 80.4513 185.354 80.0736 186.442 80.0736C187.235 80.0736 187.907 79.7865 188.443 79.2048C188.987 78.6307 189.259 77.981 189.259 77.2558V43.245C189.259 39.4904 190.181 36.0606 192.024 32.9557C193.868 29.8507 196.315 27.3577 199.39 25.4842C202.457 23.6106 205.872 22.6663 209.627 22.6663C213.381 22.6663 216.796 23.6031 219.863 25.4842C222.93 27.3577 225.385 29.8507 227.229 32.9557C229.072 36.0606 229.994 39.4904 229.994 43.245V77.2558C229.994 77.981 230.266 78.6307 230.81 79.2048C231.354 79.7865 232.018 80.0736 232.812 80.0736C233.892 80.0736 234.814 80.4513 235.577 81.2143C236.332 81.9698 236.717 82.8915 236.717 83.9793C236.717 84.9916 236.332 85.8529 235.577 86.5781C234.814 87.3034 233.937 87.6584 232.925 87.6584H219.493C218.481 87.6584 217.597 87.2958 216.841 86.5781C216.078 85.8604 215.7 84.9916 215.7 83.9793C215.7 82.899 216.078 81.9698 216.841 81.2143C217.597 80.4513 218.481 80.0736 219.493 80.0736C220.286 80.0736 220.966 79.7865 221.548 79.2048C222.122 78.6307 222.416 77.981 222.416 77.2558V43.0259C222.416 40.6387 221.857 38.4781 220.739 36.529C219.614 34.5799 218.103 33.0236 216.184 31.8678C214.273 30.7119 212.127 30.1378 209.74 30.1378C207.353 30.1378 205.192 30.7195 203.235 31.8678C201.286 33.0236 199.738 34.5799 198.582 36.529C197.426 38.4781 196.852 40.6387 196.852 43.0259V77.2558C196.852 77.981 197.139 78.6307 197.721 79.2048C198.295 79.7865 198.982 80.0736 199.775 80.0736C200.78 80.0736 201.672 80.4513 202.427 81.2143C203.182 81.9698 203.568 82.8915 203.568 83.9793C203.568 84.9916 203.182 85.8529 202.427 86.5781C201.664 87.3034 200.78 87.6584 199.775 87.6584H186.328Z"
55
+ fill="black"
56
+ />
57
+ <path
58
+ d="M273.086 87.6599C268.607 87.6599 264.406 86.8138 260.463 85.1141C256.527 83.4218 253.082 81.0875 250.12 78.1336C247.159 75.1722 244.832 71.7198 243.132 67.7838C241.433 63.8479 240.587 59.6475 240.587 55.1677C240.587 50.6878 241.44 46.4875 243.132 42.544C244.832 38.608 247.159 35.1631 250.12 32.1942C253.082 29.2403 256.527 26.906 260.463 25.2137C264.399 23.514 268.607 22.6678 273.086 22.6678H287.168V4.7937C287.168 3.78894 287.546 2.8975 288.309 2.14204C289.072 1.38658 289.948 1.00885 290.961 1.00885C291.965 1.00885 292.857 1.38658 293.612 2.14204C294.375 2.90505 294.753 3.78894 294.753 4.7937V83.8676C294.753 84.8799 294.375 85.7637 293.612 86.5192C292.857 87.2822 291.973 87.6599 290.961 87.6599H273.086ZM248.171 55.1677C248.171 59.572 249.237 63.6666 251.367 67.459C253.497 71.2514 256.436 74.3034 260.191 76.6151C263.945 78.9268 268.244 80.0827 273.079 80.0827H287.161V30.2526H273.079C268.531 30.2526 264.361 31.3707 260.568 33.6069C256.776 35.8506 253.762 38.8422 251.526 42.5968C249.282 46.3515 248.171 50.5443 248.171 55.1601V55.1677Z"
59
+ fill="black"
60
+ />
61
+ <path
62
+ d="M355.302 81.1615C356.095 81.8792 356.495 82.7857 356.495 83.8736C356.495 84.9539 356.102 85.8906 355.302 86.6914C354.584 87.4091 353.753 87.7717 352.816 87.7717C352.741 87.7717 352.431 87.7566 351.895 87.7188C351.351 87.6811 350.724 87.3034 349.998 86.5781L320.966 57.5458H309.921V83.8736C309.921 84.8859 309.536 85.7698 308.781 86.5252C308.025 87.2807 307.141 87.666 306.129 87.666C305.049 87.666 304.142 87.2882 303.417 86.5252C302.692 85.7698 302.336 84.8859 302.336 83.8736V26.4587C302.336 25.454 302.699 24.5625 303.417 23.8071C304.134 23.044 305.041 22.6663 306.129 22.6663H339.059C342.232 22.6663 345.141 23.4444 347.777 24.9931C350.414 26.5494 352.522 28.642 354.116 31.2785C355.702 33.9151 356.495 36.8538 356.495 40.1023C356.495 43.2828 355.702 46.2064 354.116 48.8732C352.522 51.5475 350.414 53.6628 347.777 55.2115C345.141 56.7601 342.232 57.5383 339.059 57.5383H331.694L355.309 81.1539L355.302 81.1615ZM309.921 40.1098C309.921 42.7842 310.873 45.0883 312.792 47.045C314.703 48.994 316.992 49.9686 319.674 49.9686H339.059C341.802 49.9686 344.128 48.994 346.047 47.045C347.959 45.0959 348.918 42.7464 348.918 40.0041C348.918 37.2618 347.943 34.9501 345.994 33.069C344.045 31.1954 341.696 30.2511 338.954 30.2511H319.674C317 30.2511 314.711 31.2105 312.792 33.1219C310.873 35.0407 309.921 37.3675 309.921 40.1098Z"
63
+ fill="black"
64
+ />
65
+ <path
66
+ d="M364.178 109C363.098 109 362.191 108.622 361.466 107.859C360.741 107.104 360.386 106.22 360.386 105.208C360.386 104.195 360.748 103.311 361.466 102.556C362.184 101.793 363.09 101.415 364.178 101.415H392.447C395.114 101.415 397.554 100.766 399.76 99.4661C401.959 98.1667 403.711 96.4141 405.018 94.2081C406.318 92.0022 406.967 89.562 406.967 86.8953V85.052L361.149 28.725C360.643 28.0073 360.386 27.2065 360.386 26.3377C360.386 26.1942 360.424 25.8316 360.492 25.2574C360.567 24.6757 360.998 24.0638 361.791 23.4141C362.441 22.84 363.196 22.5529 364.065 22.5529C364.208 22.5529 364.586 22.5907 365.206 22.6586C365.818 22.7342 366.452 23.1648 367.102 23.958L391.579 54.1764C392.878 55.7628 394.14 56.7072 395.371 56.9942C396.602 57.2813 397.539 57.4249 398.189 57.4249C399.194 57.4249 400.372 57.1906 401.709 56.7223C403.047 56.2539 404.255 55.2945 405.343 53.8515C406.423 52.4086 406.967 50.6786 406.967 48.654V26.3377C406.967 25.333 407.33 24.4415 408.048 23.6861C408.765 22.9231 409.71 22.5453 410.866 22.5453C411.87 22.5453 412.739 22.9382 413.464 23.7389C414.182 24.5322 414.545 25.4387 414.545 26.4435V86.8877C414.545 90.9294 413.547 94.6312 411.568 97.9854C409.581 101.347 406.914 104.014 403.553 106.001C400.191 107.988 396.459 108.977 392.342 108.977H364.178V109Z"
67
+ fill="black"
68
+ />
69
+ <path
70
+ d="M51.3664 80.0738C52.3787 80.0738 53.2626 80.4516 54.0181 81.2146C54.7735 81.9701 55.1588 82.8539 55.1588 83.8663C55.1588 84.8786 54.7735 85.7624 54.0181 86.5179C53.2551 87.2809 52.3787 87.6587 51.3664 87.6587H4.7924C3.7121 87.6587 2.80555 87.2809 2.08031 86.5179C1.35507 85.7624 1 84.8786 1 83.8663C1 82.8539 1.36262 81.9701 2.08031 81.2146C2.79799 80.4516 3.70454 80.0738 4.7924 80.0738H24.2908V30.2438H4.7924C3.7121 30.2438 2.80555 29.8812 2.08031 29.1635C1.35507 28.4458 1 27.5393 1 26.4514C1 25.4466 1.36262 24.5552 2.08031 23.7997C2.79799 23.0367 3.70454 22.659 4.7924 22.659H24.2908V4.78485C24.2908 3.78009 24.6534 2.88865 25.3711 2.13319C26.0888 1.37773 26.9953 1 28.0832 1H51.374C52.3863 1 53.2702 1.37773 54.0256 2.13319C54.7811 2.8962 55.1664 3.78009 55.1664 4.78485C55.1664 5.86516 54.7811 6.77171 54.0256 7.49695C53.2626 8.22219 52.3863 8.57726 51.374 8.57726H31.8756V22.659H51.374C52.3863 22.659 53.2702 23.0367 54.0256 23.7997C54.7811 24.5552 55.1664 25.4391 55.1664 26.4514C55.1664 27.5317 54.7811 28.4383 54.0256 29.1635C53.2626 29.8887 52.3863 30.2438 51.374 30.2438H31.8756V80.0738H51.374H51.3664Z"
71
+ stroke="white"
72
+ strokeWidth="0.488"
73
+ strokeMiterlimit="10"
74
+ />
75
+ <path
76
+ d="M66.5364 87.6601C65.4561 87.6601 64.5495 87.2823 63.8243 86.5193C63.099 85.7639 62.744 84.88 62.744 83.8677V26.4528C62.744 25.448 63.1066 24.5566 63.8243 23.8012C64.542 23.0381 65.4485 22.6604 66.5364 22.6604H113.11C114.123 22.6604 115.007 23.0381 115.762 23.8012C116.518 24.5566 116.903 25.4405 116.903 26.4528V83.8677C116.903 84.88 116.518 85.7639 115.762 86.5193C114.999 87.2823 114.123 87.6601 113.11 87.6601H66.5364ZM70.3288 60.5769C70.3288 64.12 71.1976 67.3684 72.9276 70.3298C74.6576 73.2912 77.007 75.6558 79.9684 77.4236C82.9298 79.1989 86.2161 80.0752 89.8272 80.0752C93.4383 80.0752 96.7094 79.1914 99.633 77.4236C102.557 75.6558 104.899 73.2912 106.674 70.3298C108.442 67.3684 109.326 64.12 109.326 60.5769V49.7436C109.326 46.1325 108.442 42.8614 106.674 39.9377C104.899 37.0141 102.557 34.6722 99.633 32.8969C96.7094 31.1291 93.4383 30.2452 89.8272 30.2452C86.2161 30.2452 82.9298 31.1291 79.9684 32.8969C77.007 34.6722 74.6576 37.0141 72.9276 39.9377C71.1976 42.8614 70.3288 46.1325 70.3288 49.7436V60.5769Z"
77
+ stroke="white"
78
+ strokeWidth="0.488"
79
+ strokeMiterlimit="10"
80
+ />
81
+ <path
82
+ d="M151.562 87.6601C146.576 87.6601 142.044 86.4362 137.964 83.981C133.885 81.5257 130.613 78.2546 128.158 74.1751C125.703 70.0956 124.479 65.5629 124.479 60.5769V26.4528C124.479 25.448 124.857 24.5566 125.62 23.8012C126.375 23.0381 127.259 22.6604 128.271 22.6604C129.352 22.6604 130.258 23.0381 130.976 23.8012C131.701 24.5566 132.056 25.4405 132.056 26.4528V60.5769C132.056 64.12 132.94 67.3684 134.708 70.3298C136.476 73.2912 138.84 75.6558 141.802 77.4236C144.763 79.1989 148.012 80.0752 151.555 80.0752C155.166 80.0752 158.445 79.1914 161.413 77.4236C164.375 75.6558 166.717 73.2912 168.454 70.3298C170.184 67.3684 171.053 64.12 171.053 60.5769V26.4528C171.053 25.448 171.438 24.5566 172.194 23.8012C172.957 23.0381 173.833 22.6604 174.846 22.6604C175.926 22.6604 176.832 23.0381 177.558 23.8012C178.275 24.5566 178.638 25.4405 178.638 26.4528V60.5769C178.638 65.5629 177.429 70.0956 175.004 74.1751C172.587 78.2546 169.316 81.5257 165.198 83.981C161.081 86.4362 156.533 87.6601 151.555 87.6601H151.562Z"
83
+ stroke="white"
84
+ strokeWidth="0.488"
85
+ strokeMiterlimit="10"
86
+ />
87
+ <path
88
+ d="M186.328 87.6584C185.316 87.6584 184.432 87.2958 183.677 86.5781C182.914 85.8604 182.536 84.9916 182.536 83.9793C182.536 82.899 182.914 81.9698 183.677 81.2143C184.432 80.4513 185.354 80.0736 186.442 80.0736C187.235 80.0736 187.907 79.7865 188.443 79.2048C188.987 78.6307 189.259 77.981 189.259 77.2558V43.245C189.259 39.4904 190.181 36.0606 192.024 32.9557C193.868 29.8507 196.315 27.3577 199.39 25.4842C202.457 23.6106 205.872 22.6663 209.627 22.6663C213.381 22.6663 216.796 23.6031 219.863 25.4842C222.93 27.3577 225.385 29.8507 227.229 32.9557C229.072 36.0606 229.994 39.4904 229.994 43.245V77.2558C229.994 77.981 230.266 78.6307 230.81 79.2048C231.354 79.7865 232.018 80.0736 232.812 80.0736C233.892 80.0736 234.814 80.4513 235.577 81.2143C236.332 81.9698 236.717 82.8915 236.717 83.9793C236.717 84.9916 236.332 85.8529 235.577 86.5781C234.814 87.3034 233.937 87.6584 232.925 87.6584H219.493C218.481 87.6584 217.597 87.2958 216.841 86.5781C216.078 85.8604 215.7 84.9916 215.7 83.9793C215.7 82.899 216.078 81.9698 216.841 81.2143C217.597 80.4513 218.481 80.0736 219.493 80.0736C220.286 80.0736 220.966 79.7865 221.548 79.2048C222.122 78.6307 222.416 77.981 222.416 77.2558V43.0259C222.416 40.6387 221.857 38.4781 220.739 36.529C219.614 34.5799 218.103 33.0236 216.184 31.8678C214.273 30.7119 212.127 30.1378 209.74 30.1378C207.353 30.1378 205.192 30.7195 203.235 31.8678C201.286 33.0236 199.738 34.5799 198.582 36.529C197.426 38.4781 196.852 40.6387 196.852 43.0259V77.2558C196.852 77.981 197.139 78.6307 197.721 79.2048C198.295 79.7865 198.982 80.0736 199.775 80.0736C200.78 80.0736 201.672 80.4513 202.427 81.2143C203.182 81.9698 203.568 82.8915 203.568 83.9793C203.568 84.9916 203.182 85.8529 202.427 86.5781C201.664 87.3034 200.78 87.6584 199.775 87.6584H186.328Z"
89
+ stroke="white"
90
+ strokeWidth="0.488"
91
+ strokeMiterlimit="10"
92
+ />
93
+ <path
94
+ d="M273.086 87.6599C268.607 87.6599 264.406 86.8138 260.463 85.1141C256.527 83.4218 253.082 81.0875 250.12 78.1336C247.159 75.1722 244.832 71.7198 243.132 67.7838C241.433 63.8479 240.587 59.6475 240.587 55.1677C240.587 50.6878 241.44 46.4875 243.132 42.544C244.832 38.608 247.159 35.1631 250.12 32.1942C253.082 29.2403 256.527 26.906 260.463 25.2137C264.399 23.514 268.607 22.6678 273.086 22.6678H287.168V4.7937C287.168 3.78894 287.546 2.8975 288.309 2.14204C289.072 1.38658 289.948 1.00885 290.961 1.00885C291.965 1.00885 292.857 1.38658 293.612 2.14204C294.375 2.90505 294.753 3.78894 294.753 4.7937V83.8676C294.753 84.8799 294.375 85.7637 293.612 86.5192C292.857 87.2822 291.973 87.6599 290.961 87.6599H273.086ZM248.171 55.1677C248.171 59.572 249.237 63.6666 251.367 67.459C253.497 71.2514 256.436 74.3034 260.191 76.6151C263.945 78.9268 268.244 80.0827 273.079 80.0827H287.161V30.2526H273.079C268.531 30.2526 264.361 31.3707 260.568 33.6069C256.776 35.8506 253.762 38.8422 251.526 42.5968C249.282 46.3515 248.171 50.5443 248.171 55.1601V55.1677Z"
95
+ stroke="white"
96
+ strokeWidth="0.488"
97
+ strokeMiterlimit="10"
98
+ />
99
+ <path
100
+ d="M355.302 81.1615C356.095 81.8792 356.495 82.7857 356.495 83.8736C356.495 84.9539 356.102 85.8906 355.302 86.6914C354.584 87.4091 353.753 87.7717 352.816 87.7717C352.741 87.7717 352.431 87.7566 351.895 87.7188C351.351 87.6811 350.724 87.3034 349.998 86.5781L320.966 57.5458H309.921V83.8736C309.921 84.8859 309.536 85.7698 308.781 86.5252C308.025 87.2807 307.141 87.666 306.129 87.666C305.049 87.666 304.142 87.2882 303.417 86.5252C302.692 85.7698 302.336 84.8859 302.336 83.8736V26.4587C302.336 25.454 302.699 24.5625 303.417 23.8071C304.134 23.044 305.041 22.6663 306.129 22.6663H339.059C342.232 22.6663 345.141 23.4444 347.777 24.9931C350.414 26.5494 352.522 28.642 354.116 31.2785C355.702 33.9151 356.495 36.8538 356.495 40.1023C356.495 43.2828 355.702 46.2064 354.116 48.8732C352.522 51.5475 350.414 53.6628 347.777 55.2115C345.141 56.7601 342.232 57.5383 339.059 57.5383H331.694L355.309 81.1539L355.302 81.1615ZM309.921 40.1098C309.921 42.7842 310.873 45.0883 312.792 47.045C314.703 48.994 316.992 49.9686 319.674 49.9686H339.059C341.802 49.9686 344.128 48.994 346.047 47.045C347.959 45.0959 348.918 42.7464 348.918 40.0041C348.918 37.2618 347.943 34.9501 345.994 33.069C344.045 31.1954 341.696 30.2511 338.954 30.2511H319.674C317 30.2511 314.711 31.2105 312.792 33.1219C310.873 35.0407 309.921 37.3675 309.921 40.1098Z"
101
+ stroke="white"
102
+ strokeWidth="0.488"
103
+ strokeMiterlimit="10"
104
+ />
105
+ <path
106
+ d="M364.178 109C363.098 109 362.191 108.622 361.466 107.859C360.741 107.104 360.386 106.22 360.386 105.208C360.386 104.195 360.748 103.311 361.466 102.556C362.184 101.793 363.09 101.415 364.178 101.415H392.447C395.114 101.415 397.554 100.766 399.76 99.4661C401.959 98.1667 403.711 96.4141 405.018 94.2081C406.318 92.0022 406.967 89.562 406.967 86.8953V85.052L361.149 28.725C360.643 28.0073 360.386 27.2065 360.386 26.3377C360.386 26.1942 360.424 25.8316 360.492 25.2574C360.567 24.6757 360.998 24.0638 361.791 23.4141C362.441 22.84 363.196 22.5529 364.065 22.5529C364.208 22.5529 364.586 22.5907 365.206 22.6586C365.818 22.7342 366.452 23.1648 367.102 23.958L391.579 54.1764C392.878 55.7628 394.14 56.7072 395.371 56.9942C396.602 57.2813 397.539 57.4249 398.189 57.4249C399.194 57.4249 400.372 57.1906 401.709 56.7223C403.047 56.2539 404.255 55.2945 405.343 53.8515C406.423 52.4086 406.967 50.6786 406.967 48.654V26.3377C406.967 25.333 407.33 24.4415 408.048 23.6861C408.765 22.9231 409.71 22.5453 410.866 22.5453C411.87 22.5453 412.739 22.9382 413.464 23.7389C414.182 24.5322 414.545 25.4387 414.545 26.4435V86.8877C414.545 90.9294 413.547 94.6312 411.568 97.9854C409.581 101.347 406.914 104.014 403.553 106.001C400.191 107.988 396.459 108.977 392.342 108.977H364.178V109Z"
107
+ stroke="white"
108
+ strokeWidth="0.488"
109
+ strokeMiterlimit="10"
110
+ />
111
+ </motion.g>
112
+ </mask>
113
+
114
+ <rect
115
+ x="0"
116
+ y="0"
117
+ width="100%"
118
+ height="100%"
119
+ fill="white"
120
+ mask="url(#circle-mask)"
121
+ />
122
+ </motion.svg>
123
+ </div>
124
+ )}
125
+ </>
126
+ );
127
+ };
128
+
129
+ export default Mask;
@@ -5,11 +5,13 @@ import styles from "./styles.module.scss";
5
5
  import Mute from "../../assets/svg/mute.svg";
6
6
  import Muted from "../../assets/svg/muted.svg";
7
7
  import PlayButton from "../../assets/svg/play-button.svg";
8
+ import Mask from "./Mask";
8
9
 
9
10
  function VideoTeaser({ url }: { url: string }) {
10
11
  const [playing, setPlaying] = useState(false);
11
12
  const [hasWindow, setHasWindow] = useState(false);
12
13
  const [isMuted, setIsMuted] = useState(true);
14
+ const [isAnimated, setIsAnimated] = useState(false);
13
15
 
14
16
  useEffect(() => {
15
17
  if (typeof window !== "undefined") {
@@ -30,12 +32,15 @@ function VideoTeaser({ url }: { url: string }) {
30
32
  playing ? styles.playing : ""
31
33
  }`}
32
34
  >
35
+ <Mask isAnimated={isAnimated} setIsAnimated={setIsAnimated} />
33
36
  <button className={styles.btnMute} onClick={() => setIsMuted(!isMuted)}>
34
37
  {isMuted ? <Muted /> : <Mute />}
35
38
  </button>
36
39
  <div className={styles.video} onClick={handleClick}>
37
40
  <div
38
- className={`${styles.playButton} ${playing ? styles.playing : ""}`}
41
+ className={`${styles.playButton} ${playing ? styles.playing : ""} ${
42
+ isAnimated ? styles.isAnimated : ""
43
+ }`}
39
44
  >
40
45
  <PlayButton />
41
46
  </div>
@@ -6,11 +6,13 @@
6
6
  background-position: center;
7
7
  width: 100%;
8
8
  height: 790px;
9
+ max-height: calc(100vh - 75px);
9
10
  text-align: center;
10
11
  box-sizing: border-box;
11
12
  display: flex;
12
13
  align-items: center;
13
14
  position: relative;
15
+ overflow: hidden;
14
16
 
15
17
  @media #{$QUERY-md} {
16
18
  padding: 100px 50px;
@@ -64,6 +66,12 @@
64
66
  align-items: center;
65
67
  justify-content: center;
66
68
  cursor: pointer;
69
+ transition: opacity 0.3s;
70
+ opacity: 0;
71
+
72
+ &.isAnimated {
73
+ opacity: 1;
74
+ }
67
75
 
68
76
  &.playing {
69
77
  opacity: 0;
@@ -91,3 +99,21 @@
91
99
  height: 100%;
92
100
  }
93
101
  }
102
+
103
+ .mask {
104
+ position: absolute;
105
+ top: 0;
106
+ left: 0;
107
+ width: 100%;
108
+ height: 100%;
109
+ z-index: 5;
110
+
111
+ svg {
112
+ width: 100%;
113
+ height: 100%;
114
+ }
115
+
116
+ path {
117
+ transform: translate(34.5%, 39.5%);
118
+ }
119
+ }
@@ -1,6 +1,9 @@
1
- import { useState, useEffect } from "react";
1
+ import { useState, useEffect, RefObject } from "react";
2
2
 
3
- export const useOnScreen = (ref: any, rootMargin = "0px") => {
3
+ export const useOnScreen = (
4
+ ref: RefObject<null | HTMLElement>,
5
+ rootMargin = "0px"
6
+ ) => {
4
7
  // State and setter for storing whether element is visible
5
8
  const [isIntersecting, setIntersecting] = useState(false);
6
9
  useEffect(() => {
@@ -20,7 +23,9 @@ export const useOnScreen = (ref: any, rootMargin = "0px") => {
20
23
  observer.observe(currentElement);
21
24
  }
22
25
  return () => {
23
- observer.unobserve(currentElement);
26
+ if (currentElement) {
27
+ observer.unobserve(currentElement);
28
+ }
24
29
  };
25
30
  }, []); // Empty array ensures that effect is only run on mount and unmount
26
31
  return isIntersecting;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foundry-component-library",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",