@hellobetterdigitalnz/selwynui 0.0.1-46 → 0.0.1-48

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.
Files changed (30) hide show
  1. package/dist/Components/DataDisplay/ContentBlock/ContentBlockProps.d.ts +3 -0
  2. package/dist/Components/DataDisplay/DetailsCard/DetailsCardProps.d.ts +0 -1
  3. package/dist/Components/DataDisplay/ListBlock/ListBlockProps.d.ts +1 -1
  4. package/dist/Components/DataDisplay/Media/Media.d.ts +0 -0
  5. package/dist/Components/DataDisplay/Media/MediaProps.d.ts +0 -0
  6. package/dist/Components/Shared/ElementHolder/ElementHolderProps.d.ts +1 -1
  7. package/dist/index.cjs.js +4 -8
  8. package/dist/index.cjs.js.map +1 -1
  9. package/dist/index.es.js +3509 -3484
  10. package/dist/index.es.js.map +1 -1
  11. package/dist/selwynui.css +1 -1
  12. package/package.json +1 -1
  13. package/src/Components/DataDisplay/ChatItenaryBlock/ChatItenaryBlock.stories.tsx +1 -1
  14. package/src/Components/DataDisplay/ChatItenaryBlock/chatItenaryBlock.module.scss +17 -17
  15. package/src/Components/DataDisplay/ContentBlock/ContentBlock.stories.tsx +3 -3
  16. package/src/Components/DataDisplay/ContentBlock/ContentBlock.tsx +12 -2
  17. package/src/Components/DataDisplay/ContentBlock/ContentBlockProps.tsx +3 -0
  18. package/src/Components/DataDisplay/ContentBlock/contentBlock.module.scss +45 -30
  19. package/src/Components/DataDisplay/DetailsCard/DetailsCard.tsx +2 -3
  20. package/src/Components/DataDisplay/DetailsCard/DetailsCardProps.tsx +0 -1
  21. package/src/Components/DataDisplay/KPIBlock/kpiBlock.module.scss +5 -3
  22. package/src/Components/DataDisplay/ListBlock/ListBlock.tsx +88 -60
  23. package/src/Components/DataDisplay/ListBlock/ListBlockProps.tsx +1 -1
  24. package/src/Components/DataDisplay/Media/Media.tsx +0 -0
  25. package/src/Components/DataDisplay/Media/MediaProps.tsx +0 -0
  26. package/src/Components/DataDisplay/TestimonyCard/TestimonyCard.stories.tsx +1 -1
  27. package/src/Components/DataDisplay/TestimonyCard/TestimonyCard.tsx +59 -63
  28. package/src/Components/DataDisplay/TestimonyCard/testimonyCard.module.scss +92 -53
  29. package/src/Components/Shared/ElementHolder/ElementHolderProps.tsx +1 -1
  30. package/src/Components/Shared/ElementHolder/elementHolder.module.scss +1 -0
@@ -21,7 +21,7 @@
21
21
 
22
22
  &.itinerary {
23
23
  padding: 48px 0 76px;
24
- border-top: 1px solid var(--color-taste);
24
+ border-top: 1px solid var(--color-text);
25
25
 
26
26
  @media (max-width: 834px) {
27
27
  padding: 24px 0 48px;
@@ -79,7 +79,7 @@
79
79
  font-size: var(--font-size-h3);
80
80
  font-weight: var(--font-weight-body-regular);
81
81
  line-height: 1;
82
- color: var(--color-taste);
82
+ color: var(--color-text);
83
83
 
84
84
  @media (max-width: 834px) {
85
85
  font-size: var(--font-size-h4);
@@ -94,7 +94,7 @@
94
94
  font-weight: var(--font-weight-h5);
95
95
  letter-spacing: -3.6px;
96
96
  line-height: 1;
97
- color: var(--color-taste);
97
+ color: var(--color-text);
98
98
  }
99
99
 
100
100
  .subtitle {
@@ -102,7 +102,7 @@
102
102
  line-height: var(--line-height-h6);
103
103
  margin: 0 0 70px 0;
104
104
  letter-spacing: -0.56px;
105
- color: var(--color-taste);
105
+ color: var(--color-text);
106
106
 
107
107
  @media (max-width: 834px) {
108
108
  font-size: var(--font-size-body-regular);
@@ -137,7 +137,7 @@
137
137
  .inputBox {
138
138
  background: var(--bg-modal-color);
139
139
  border-radius: var(--tw-8, 32px);
140
- border: 2px solid var(--color-taste);
140
+ border: 2px solid var(--color-text);
141
141
  padding: 24px 24px 24px 24px;
142
142
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
143
143
  width: 100%;
@@ -160,7 +160,7 @@
160
160
  font-size: 18px;
161
161
  resize: none;
162
162
  font-family: inherit;
163
- color: var(--header-bg);
163
+ color: var(--color-bg);
164
164
  margin-bottom: 16px;
165
165
 
166
166
  @media (max-width: 834px) {
@@ -168,7 +168,7 @@
168
168
  }
169
169
 
170
170
  &::placeholder {
171
- color: var(--header-bg);
171
+ color: var(--color-bg);
172
172
 
173
173
  @media (max-width: 834px) {
174
174
  font-size: var(--font-size-body-sm);
@@ -254,7 +254,7 @@
254
254
  padding: 0;
255
255
 
256
256
  svg {
257
- color: var(--color-taste);
257
+ color: var(--color-text);
258
258
  width: 20px;
259
259
  height: 20px;
260
260
  }
@@ -282,7 +282,7 @@
282
282
 
283
283
  &.itinerary {
284
284
  padding: 48px 0 0;
285
- border-top: 1px solid var(--color-taste);
285
+ border-top: 1px solid var(--color-text);
286
286
  flex: 1;
287
287
  display: flex;
288
288
  flex-direction: column;
@@ -378,7 +378,7 @@
378
378
  font-weight: var(--font-weight-bold);
379
379
  line-height: var(--line-height-h3);
380
380
  letter-spacing: -1.92px;
381
- color: var(--header-bg);
381
+ color: var(--color-bg);
382
382
  margin: 0 0 62px 0;
383
383
 
384
384
  @media (max-width: 834px) {
@@ -399,7 +399,7 @@
399
399
  font-size: var(--font-size-label);
400
400
  line-height: var(--line-height-body-regular);
401
401
  font-weight: var(--font-weight-h4);
402
- color: var(--header-bg);
402
+ color: var(--color-bg);
403
403
  background: var(--color-sand);
404
404
  border-radius: 24px;
405
405
 
@@ -428,7 +428,7 @@
428
428
  font-size: 16px;
429
429
  line-height: var(--line-height-body-regular);
430
430
  font-weight: var(--font-weight-h4);
431
- color: var(--header-bg);
431
+ color: var(--color-bg);
432
432
 
433
433
  @media (max-width: 834px) {
434
434
  font-size: var(--font-size-body-sm);
@@ -573,7 +573,7 @@
573
573
  min-height: 162px;
574
574
  background: var(--bg-modal-color);
575
575
  border-radius: 12px;
576
- border: 2px solid var(--color-taste);
576
+ border: 2px solid var(--color-text);
577
577
  margin: 0;
578
578
  width: 100%;
579
579
  box-sizing: border-box;
@@ -723,7 +723,7 @@
723
723
  padding: 0;
724
724
 
725
725
  svg {
726
- color: var(--color-taste);
726
+ color: var(--color-text);
727
727
  width: 20px;
728
728
  height: 20px;
729
729
  }
@@ -737,7 +737,7 @@
737
737
  .fixedInputBox {
738
738
  background: var(--bg-modal-color);
739
739
  border-radius: var(--tw-8, 32px);
740
- border: 2px solid var(--color-taste);
740
+ border: 2px solid var(--color-text);
741
741
  padding: 24px 24px 24px 24px;
742
742
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
743
743
  width: 100%;
@@ -759,7 +759,7 @@
759
759
  font-size: 18px;
760
760
  resize: none;
761
761
  font-family: inherit;
762
- color: var(--header-bg);
762
+ color: var(--color-bg);
763
763
  margin-bottom: 16px;
764
764
 
765
765
  @media (max-width: 834px) {
@@ -767,7 +767,7 @@
767
767
  }
768
768
 
769
769
  &::placeholder {
770
- color: var(--header-bg);
770
+ color: var(--color-bg);
771
771
 
772
772
  @media (max-width: 834px) {
773
773
  font-size: var(--font-size-body-sm);
@@ -21,10 +21,10 @@ const ContentBlockTemplate: Story = {
21
21
  render: () => {
22
22
  return (
23
23
  <>
24
- <ElementHolder paddingTop="sm" paddingBottom="sm" pillar="participate" level="primary">
25
- <ContentBlock>
24
+ <ElementHolder paddingTop={'lg'} paddingBottom={"lg"} pillar="visit" level="light">
25
+ <ContentBlock spacingTop={"lg"}>
26
26
  <h3>Privacy policy</h3>
27
- <h6>Lorem ipsum dolor sit amet, consectetur adipiscing elit</h6>
27
+ <h5>Lorem ipsum dolor sit amet, consectetur adipiscing elit</h5>
28
28
  <p>
29
29
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor <strong>incididunt</strong> ut labore et
30
30
  dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
@@ -2,15 +2,25 @@ import ContentBlockProps from "./ContentBlockProps.tsx";
2
2
  import styles from './contentBlock.module.scss';
3
3
  import Container from "../../Shared/Container/Container.tsx";
4
4
  import LargeHeroIcon from "../../Layout/HeroBanner/LargeHeroIcon.tsx";
5
+ import cslx from "clsx";
5
6
 
6
7
  const ContentBlock = (props: ContentBlockProps) => {
7
8
  const {
8
9
  children,
9
- pillar = 'visit'
10
+ pillar = 'visit',
11
+ spacingTop = 'none',
10
12
  } = props;
11
13
 
14
+ const className = cslx(
15
+ styles.contentBlock ,
16
+ `${pillar}`,
17
+ {
18
+ [styles[`contentBlock--pt-${spacingTop}`]]: spacingTop,
19
+ },
20
+ );
21
+
12
22
  return (
13
- <div className={`${styles.contentBlock} ${pillar ? `${pillar}` : ""}`}>
23
+ <div className={className}>
14
24
  <Container>
15
25
  <div className={`typography ${styles.contentBlockWrapper}` }>
16
26
  {children}
@@ -3,6 +3,9 @@ import {ReactNode} from "react";
3
3
  interface ContentBlockProps {
4
4
  children: ReactNode;
5
5
  pillar?: 'visit' | 'live' | 'business' | 'participate' | 'taste' | 'main';
6
+ watermark?: boolean;
7
+ spacingTop?: "none" | "xsm" |"sm" | "md" | "lg" ;
8
+ spacingBottom?: "none" | "xsm" |"sm" | "md" | "lg" | "xl";
6
9
  }
7
10
 
8
11
  export default ContentBlockProps;
@@ -1,59 +1,74 @@
1
1
  .contentBlock {
2
+ position: relative;
3
+
4
+ &Inner {
5
+ //position: relative;
6
+ z-index: 1;
7
+ }
8
+
9
+
10
+ &--pt-none {
11
+ .heroSvg{
12
+ top:0;
13
+ }
14
+ }
15
+
16
+ &--pt-xsm {
17
+ .heroSvg {
18
+ top: -72px;
19
+ }
20
+ }
21
+
22
+ &--pt-sm {
23
+ .heroSvg {
24
+ top: -90px;
25
+ }
26
+ }
27
+
28
+ &--pt-md {
29
+ .heroSvg {
30
+ top: -120px;
31
+ }
32
+ }
33
+
34
+ &--pt-lg {
35
+ .heroSvg {
36
+ top: -144px;
37
+ }
38
+ }
39
+
2
40
 
3
41
  @media (max-width: 834px) {
4
- padding: 64px 0;
5
42
  width: 100%;
6
43
  }
7
44
 
8
45
  @media (max-width: 480px) {
9
- padding: 48px 0;
10
46
  width: 100%;
11
47
  }
48
+
12
49
  }
13
50
 
14
51
  .contentBlockWrapper {
15
52
  max-width: 910px;
16
- }
17
-
18
- .pillarIcon {
19
- position: absolute;
20
- right: 0;
21
- bottom: 0;
22
- pointer-events: none;
23
- z-index: 1;
53
+ font-family: var(--font);
24
54
 
25
- @media (max-width: 1200px) {
26
- right: -100px;
27
- display: none;
55
+ h1,h2,h3,h4,h5,h6{
56
+ margin-bottom: 24px ;
57
+ font-weight: 400;
28
58
  }
29
59
 
30
- @media (max-width: 900px) {
31
- display: none;
32
- }
33
60
 
34
- svg {
35
- height: 577px;
36
- width: 639px;
37
61
 
38
- @media (max-width: 1400px) {
39
- height: 450px;
40
- width: 500px;
41
- }
42
-
43
- @media (max-width: 1200px) {
44
- height: 350px;
45
- width: 400px;
46
- }
47
- }
48
62
  }
49
63
 
50
64
  .heroSvg {
51
65
  position: absolute;
52
66
  z-index: 5;
53
67
  top: 0;
54
- right: 0;
55
68
  height: 340px;
56
69
  pointer-events: none;
70
+ opacity: 0.2;
71
+ right: -240px;
57
72
 
58
73
  @media (max-width: 1024px) {
59
74
  display: none;
@@ -11,7 +11,6 @@ const DetailsCard = (props: DetailsCardProps) => {
11
11
  image = '',
12
12
  variation= 'long',
13
13
  link = {},
14
- category = 'all',
15
14
  pillar = 'visit'
16
15
  } = props;
17
16
 
@@ -22,12 +21,12 @@ const DetailsCard = (props: DetailsCardProps) => {
22
21
  "detailsCard",
23
22
  ];
24
23
 
25
- if(variation==='short') {
24
+ if(variation === 'short') {
26
25
  classes.push(styles.detailsCardShort)
27
26
  }
28
27
 
29
28
 
30
- return <div className={cx(classes)} id={category}>
29
+ return <div className={cx(classes)}>
31
30
  <a href={link?.href} target={link.target} rel={link.rel} className={`${styles.cardWrap} ${styles.detailsCardWithLink}`}>
32
31
  <div className={styles.cardImage}>
33
32
  {image && <img src={image} alt={title} />}
@@ -12,7 +12,6 @@ interface DetailsCardProps {
12
12
  pillar?: 'visit' | 'live' | 'business' | 'participate' | 'taste'
13
13
  image?:string,
14
14
  variation?: "long" | "short";
15
- category?: 'all' | 'adventure' | 'ski' | 'nature',
16
15
  }
17
16
 
18
17
  export default DetailsCardProps;
@@ -9,8 +9,8 @@
9
9
  }
10
10
 
11
11
  .header {
12
- flex: 0 0 40%;
13
- margin-right: 90px;
12
+ flex: 0 0 35%;
13
+ margin-right: 50px;
14
14
 
15
15
  @media (max-width: 1200px) {
16
16
  margin-right: 60px;
@@ -28,7 +28,7 @@
28
28
  font-weight: var(--font-weight-h5);
29
29
  letter-spacing: -1.92px;
30
30
  line-height: 1;
31
- margin-bottom: 48px;
31
+ margin-bottom: 59px;
32
32
 
33
33
  @media (max-width: 900px) {
34
34
  font-size: var(--font-size-h5);
@@ -56,6 +56,7 @@
56
56
  .stats {
57
57
  width: 60%;
58
58
  display: flex;
59
+ align-items: center;
59
60
  flex-direction: column;
60
61
  gap: 48px;
61
62
 
@@ -70,6 +71,7 @@
70
71
 
71
72
  .statItem {
72
73
  display: flex;
74
+ align-items: flex-start;
73
75
  padding-bottom: 48px;
74
76
  border-bottom: 1px solid;
75
77
 
@@ -1,4 +1,4 @@
1
- import ListBlockProps from './ListBlockProps.tsx';
1
+ import ListBlockProps from './ListBlockProps.tsx';
2
2
  import styles from "./listBlock.module.scss";
3
3
  import cslx from "clsx";
4
4
  import Container from "../../Shared/Container/Container";
@@ -6,86 +6,114 @@ import DetailsCard from "../DetailsCard/DetailsCard";
6
6
  import { CaretDown } from "../../Icons";
7
7
  import { useState } from "react";
8
8
 
9
- const ListBlock = (props:ListBlockProps) => {
10
- const {
11
- title = '',
12
- description = '',
13
- cards = [],
14
- filters = [],
9
+ // Helpers
10
+ const slugify = (str: string) =>
11
+ str.toLowerCase().trim().replace(/\s+/g, "-");
12
+
13
+ const formatCategory = (str: string) =>
14
+ str
15
+ .split(" ")
16
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
17
+ .join(" ");
18
+
19
+ const ListBlock = (props: ListBlockProps) => {
20
+ const {
21
+ title = '',
22
+ description = '',
23
+ cards = [],
15
24
  action
16
- } = props
25
+ } = props;
17
26
 
18
- const [activeFilter, setActiveFilter] = useState("all");
19
27
 
20
- const filterCards = (category: string | undefined) => {
21
- if (!category) return activeFilter === "all";
22
- if (activeFilter === "all") return true;
23
- return category.toLowerCase() === activeFilter;
24
- };
28
+ const uniqueCategories = Array.from(
29
+ new Set(cards.map(c => c.category?.toLowerCase()).filter(Boolean))
30
+ );
31
+
32
+ const dynamicFilters = [...uniqueCategories];
33
+ const [activeFilter, setActiveFilter] = useState<string | null>(null);
25
34
 
35
+ const filterCards = (category?: string) => {
36
+ if (!category) return false;
37
+ if (!activeFilter) return true;
38
+ return slugify(category) === activeFilter;
39
+ };
26
40
 
27
41
  const classes = [styles.pathway, "pathway"];
28
42
 
29
43
  return (
30
44
  <div>
31
45
  <Container>
32
- <div className={cslx(classes)}>
33
- <div className={styles.pathwayTitle}><h3>{title}</h3></div>
46
+ <div className={cslx(classes)}>
47
+ {title && <div className={styles.pathwayTitle}><h3>{title}</h3></div>}
48
+
49
+ {(description || action) && (
34
50
  <div className={styles.pathwayDescription}>
35
- <p>{description}</p>
36
- {action && <div className={styles.action}>
37
- {action}
38
- </div>}
51
+ {description && <p>{description}</p>}
52
+ {action && <div className={styles.action}>{action}</div>}
39
53
  </div>
54
+ )}
40
55
 
41
- {filters && filters.length > 0 && (<div className={`${styles.pathwayFilters} ${styles.pathwayFilterDesktop}`}>
56
+ {/* Desktop Filters */}
57
+ {dynamicFilters.length > 0 && (
58
+ <div className={`${styles.pathwayFilters} ${styles.pathwayFilterDesktop}`}>
42
59
  <ul>
43
- {filters.map((cat) => (
44
- <li
45
- key={cat}
46
- className={activeFilter === cat ? styles.active : ""}
47
- onClick={() => setActiveFilter(cat)}
48
- >
49
- <span>{cat === "all" ? "All Attractions" : cat.charAt(0).toUpperCase() + cat.slice(1)}</span>
50
- </li>
51
- ))}
60
+ <li
61
+ key="all"
62
+ className={!activeFilter ? styles.active : ""}
63
+ onClick={() => setActiveFilter(null)}
64
+ >
65
+ <span>All</span>
66
+ </li>
67
+ {dynamicFilters.map(cat => {
68
+ const value = slugify(cat!);
69
+ const label = formatCategory(cat!);
70
+ return (
71
+ <li
72
+ key={value}
73
+ className={activeFilter === value ? styles.active : ""}
74
+ onClick={() => setActiveFilter(value)}
75
+ >
76
+ <span>{label}</span>
77
+ </li>
78
+ );
79
+ })}
52
80
  </ul>
53
- </div>)}
81
+ </div>
82
+ )}
54
83
 
55
- {filters && filters.length > 0 && (<div className={`${styles.pathwayFilters} ${styles.pathwayFilterMobile}`}>
56
- <select onChange={(e) => setActiveFilter(e.target.value.toLowerCase())}>
57
- {filters.map((cat) => (
58
- <option key={cat} value={cat}>
59
- {cat === "all" ? "All Attractions" : cat.charAt(0).toUpperCase() + cat.slice(1)}
60
- </option>
61
- ))}
84
+ {/* Mobile Filters */}
85
+ {dynamicFilters.length > 0 && (
86
+ <div className={`${styles.pathwayFilters} ${styles.pathwayFilterMobile}`}>
87
+ <select
88
+ onChange={(e) => setActiveFilter(e.target.value || null)}
89
+ value={activeFilter || ""}
90
+ >
91
+ <option value="">All</option>
92
+ {dynamicFilters.map(cat => {
93
+ const value = slugify(cat!);
94
+ const label = formatCategory(cat!);
95
+ return (
96
+ <option key={value} value={value}>
97
+ {label}
98
+ </option>
99
+ );
100
+ })}
62
101
  </select>
63
102
  <CaretDown />
64
- </div>)}
103
+ </div>
104
+ )}
65
105
 
66
- {/* Cards */}
67
- <div className={styles.pathwayCards}>
68
- <div className={styles.pathwayCardsWrap}>
69
- {filters && filters.length > 0 ? (
70
- <>
71
- {cards.filter((c) => filterCards(c.category)).map((card, idx) => (
72
- <div key={idx} className={styles.pathwayCard}>
73
- <DetailsCard {...card} variation={"short"} />
74
- </div>
75
- ))}
76
- </>
77
- ) : (
78
- <>
79
- {cards.map((card, idx) => (
80
- <div key={idx} className={styles.pathwayCard}>
81
- <DetailsCard {...card} variation={"short"} />
82
- </div>
83
- ))}
84
- </>
85
- )}
86
- </div>
106
+ {/* Cards */}
107
+ <div className={styles.pathwayCards}>
108
+ <div className={styles.pathwayCardsWrap}>
109
+ {cards.filter(c => filterCards(c.category)).map((card, idx) => (
110
+ <div key={idx} className={styles.pathwayCard}>
111
+ <DetailsCard {...card} variation="short" />
112
+ </div>
113
+ ))}
87
114
  </div>
88
115
  </div>
116
+ </div>
89
117
  </Container>
90
118
  </div>
91
119
  );
@@ -13,7 +13,7 @@ export interface Card {
13
13
  pillar?: 'visit' | 'live' | 'business' | 'participate' | 'taste'
14
14
  image?:string,
15
15
  variation?: "long" | "short";
16
- category?: 'all' | 'adventure' | 'ski' | 'nature',
16
+ category?: string | undefined,
17
17
  }
18
18
 
19
19
  interface ListBlockProps {
File without changes
@@ -21,7 +21,7 @@ const TestimonyCardTemplate: Story = {
21
21
  render: () => {
22
22
  return (
23
23
  <>
24
- <ElementHolder paddingTop="sm" paddingBottom="sm" pillar="visit" level="primary">
24
+ <ElementHolder paddingTop="sm" paddingBottom="sm" pillar="business" level="primary">
25
25
  <TestimonyCard
26
26
  testimonies={[
27
27
  {