@levo-so/blocks 0.1.54 → 0.1.59

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 (117) hide show
  1. package/package.json +2 -2
  2. package/src/blocks/about-us/about-us-1.schema.ts +14 -0
  3. package/src/blocks/about-us/about-us-1.tsx +4 -2
  4. package/src/blocks/about-us/about-us-2.schema.ts +48 -0
  5. package/src/blocks/about-us/about-us-2.tsx +6 -0
  6. package/src/blocks/blogs/blog-listing-1.schema.ts +10 -0
  7. package/src/blocks/blogs/blog-listing-2.schema.ts +42 -162
  8. package/src/blocks/blogs/blog-listing-2.tsx +7 -0
  9. package/src/blocks/blogs/blog-listing-3.schema.ts +9 -0
  10. package/src/blocks/blogs/blog-post-1.schema.ts +7 -1
  11. package/src/blocks/blogs/blog-post-1.tsx +1 -1
  12. package/src/blocks/blogs/blog-post-2.schema.ts +464 -28
  13. package/src/blocks/blogs/blog-post-2.tsx +6 -13
  14. package/src/blocks/blogs/blog-post-3.schema.ts +42 -0
  15. package/src/blocks/blogs/blog-post-3.tsx +4 -1
  16. package/src/blocks/calendar/calendar-1.schema.ts +537 -0
  17. package/src/blocks/calendar/calendar-1.tsx +145 -0
  18. package/src/blocks/cards/cards-10.schema.ts +52 -4
  19. package/src/blocks/cards/cards-10.tsx +13 -1
  20. package/src/blocks/cards/cards-14.schema.ts +532 -0
  21. package/src/blocks/cards/cards-14.tsx +54 -0
  22. package/src/blocks/cards/cards-15.schema.ts +277 -0
  23. package/src/blocks/cards/cards-15.tsx +40 -0
  24. package/src/blocks/cards/cards-6.schema.ts +46 -0
  25. package/src/blocks/cards/cards-6.tsx +27 -1
  26. package/src/blocks/cards/cards-7.tsx +2 -0
  27. package/src/blocks/carousel/carousel-2.schema.ts +1128 -0
  28. package/src/blocks/carousel/carousel-2.tsx +159 -0
  29. package/src/blocks/content/content-5.schema.ts +112 -6
  30. package/src/blocks/content/content-5.tsx +19 -3
  31. package/src/blocks/content/content-6.schema.ts +16 -3
  32. package/src/blocks/content/content-6.tsx +1 -0
  33. package/src/blocks/content/content-8.schema.ts +125 -0
  34. package/src/blocks/content/content-8.tsx +27 -0
  35. package/src/blocks/content/content-9.schema.ts +2729 -0
  36. package/src/blocks/content/content-9.tsx +91 -0
  37. package/src/blocks/cta/cta-2.schema.ts +46 -4
  38. package/src/blocks/cta/cta-2.tsx +9 -1
  39. package/src/blocks/embed/embed-1.schema.ts +100 -0
  40. package/src/blocks/event/ClientOnly.tsx +27 -0
  41. package/src/blocks/event/event-details.tsx +10 -3
  42. package/src/blocks/event/event-listing-3.tsx +9 -2
  43. package/src/blocks/event/event-listing-4.tsx +11 -2
  44. package/src/blocks/event/event-listing.tsx +11 -4
  45. package/src/blocks/faq/faq-1.schema.ts +58 -1
  46. package/src/blocks/faq/faq-1.tsx +18 -1
  47. package/src/blocks/faq/faq-2.tsx +2 -1
  48. package/src/blocks/faq/faq-3.schema.ts +6 -1
  49. package/src/blocks/faq/faq-3.tsx +1 -0
  50. package/src/blocks/features/features-1/features-1.schema.ts +2 -0
  51. package/src/blocks/features/features-1/variants/index.ts +2 -0
  52. package/src/blocks/features/features-1/variants/stylized-cards-v3.ts +451 -0
  53. package/src/blocks/features/features-4.schema.ts +358 -20
  54. package/src/blocks/features/features-4.tsx +3 -1
  55. package/src/blocks/features/features-6.tsx +2 -0
  56. package/src/blocks/filter-listing/filter-listing-1.schema.ts +614 -0
  57. package/src/blocks/filter-listing/filter-listing-1.tsx +128 -0
  58. package/src/blocks/footer/footer-6.schema.ts +2 -2
  59. package/src/blocks/hero/hero-11.schema.ts +849 -0
  60. package/src/blocks/hero/hero-11.tsx +59 -0
  61. package/src/blocks/hero/hero-12.schema.ts +712 -0
  62. package/src/blocks/hero/hero-12.tsx +76 -0
  63. package/src/blocks/hero/hero-13.schema.ts +238 -0
  64. package/src/blocks/hero/hero-13.tsx +31 -0
  65. package/src/blocks/hero/hero-4.tsx +2 -0
  66. package/src/blocks/hero/hero-5.tsx +2 -0
  67. package/src/blocks/hero/hero-7.tsx +2 -1
  68. package/src/blocks/hero/hero-8.tsx +2 -0
  69. package/src/blocks/hero/hero-9.schema.ts +5 -0
  70. package/src/blocks/hero/hero-9.tsx +2 -0
  71. package/src/blocks/index.ts +27 -0
  72. package/src/blocks/navbar/navbar-1.schema.ts +6 -6
  73. package/src/blocks/navbar/navbar-1.tsx +6 -7
  74. package/src/blocks/navbar/navbar-2.schema.ts +9 -9
  75. package/src/blocks/navbar/navbar-2.tsx +7 -8
  76. package/src/blocks/navbar/navbar-3.schema.ts +9 -9
  77. package/src/blocks/navbar/navbar-3.tsx +139 -114
  78. package/src/blocks/polling/polling-1.schema.ts +134 -0
  79. package/src/blocks/polling/polling-1.tsx +466 -0
  80. package/src/blocks/products/products-listing-2.schema.ts +596 -0
  81. package/src/blocks/products/products-listing-2.tsx +56 -0
  82. package/src/blocks/products/products-listing-3.schema.ts +818 -0
  83. package/src/blocks/products/products-listing-3.tsx +125 -0
  84. package/src/blocks/profile/profile-2.schema.ts +505 -0
  85. package/src/blocks/profile/profile-2.tsx +64 -0
  86. package/src/blocks/profile/profile-3.schema.ts +867 -0
  87. package/src/blocks/profile/profile-3.tsx +98 -0
  88. package/src/blocks/services/service-1.schema.ts +1743 -0
  89. package/src/blocks/services/service-1.tsx +139 -0
  90. package/src/blocks/services/service-2.schema.ts +433 -0
  91. package/src/blocks/services/service-2.tsx +98 -0
  92. package/src/blocks/services/service-3.schema.ts +631 -0
  93. package/src/blocks/services/service-3.tsx +135 -0
  94. package/src/blocks/tabs/tab-1.schema.ts +831 -0
  95. package/src/blocks/tabs/tab-1.tsx +126 -0
  96. package/src/blocks/tabs/tab-2.schema.ts +767 -0
  97. package/src/blocks/tabs/tab-2.tsx +60 -0
  98. package/src/blocks/team/team-3.schema.ts +5 -1
  99. package/src/blocks/team/team-3.tsx +7 -0
  100. package/src/blocks/team/team-4.schema.ts +17 -13
  101. package/src/blocks/team/team-4.tsx +4 -1
  102. package/src/blocks/team/team-5.schema.ts +369 -0
  103. package/src/blocks/team/team-5.tsx +38 -0
  104. package/src/blocks/testimonial/testimonial-1.tsx +0 -1
  105. package/src/blocks/testimonial/testimonial-2.tsx +2 -1
  106. package/src/blocks/testimonial/testimonial-3.tsx +2 -0
  107. package/src/blocks/testimonial/testimonial-4.tsx +2 -1
  108. package/src/blocks/testimonial/testimonial-5.tsx +2 -0
  109. package/src/blocks/testimonial/testimonial-6.tsx +2 -1
  110. package/src/blocks/testimonial/testimonial-7.schema.ts +438 -0
  111. package/src/blocks/testimonial/testimonial-7.tsx +125 -0
  112. package/src/blocks/timeline/timeline-1.schema.ts +741 -0
  113. package/src/blocks/timeline/timeline-1.tsx +52 -0
  114. package/src/blocks/users/edit-profile.schema.ts +294 -0
  115. package/src/blocks/users/edit-profile.tsx +184 -0
  116. package/src/schemas/blocks.ts +64 -12
  117. package/src/schemas/categories.ts +36 -0
@@ -0,0 +1,91 @@
1
+ import {
2
+ type ILevoBlockBaseProps,
3
+ Heading,
4
+ Image,
5
+ Typography,
6
+ Container,
7
+ Section,
8
+ Box,
9
+ AccordionRoot,
10
+ AccordionItem,
11
+ AccordionTrigger,
12
+ AccordionContent,
13
+ Icon,
14
+ } from "@levo-so/studio";
15
+
16
+ import type { IContent9Content } from "./content-9.schema";
17
+
18
+ const Content9: React.FC<ILevoBlockBaseProps<IContent9Content>> = ({
19
+ content,
20
+ }) => (
21
+ <Section elementKey="layout">
22
+ <Container elementKey="container">
23
+ <Heading elementKey="title" />
24
+
25
+ <Box elementKey="accordions_container">
26
+ <AccordionRoot
27
+ type="single"
28
+ elementKey="sections_levoGroup"
29
+ data-levo_group
30
+ defaultValue={`item-0`}
31
+ >
32
+ {(content.sections ?? []).map((_, index) => (
33
+ <AccordionItem
34
+ value={`item-${index}`}
35
+ key={index}
36
+ elementKey={`sections.${index}.wrapper`}
37
+ data-levo_group_item
38
+ >
39
+ <AccordionTrigger elementKey={`sections.${index}.trigger`}>
40
+ <Box elementKey={`sections.${index}.headerContainer`}>
41
+ <Box elementKey={`sections.${index}.iconLabelContainer`}>
42
+ <Icon elementKey={`sections.${index}.icon`} />
43
+ <Typography elementKey={`sections.${index}.label`} />
44
+ </Box>
45
+ <Typography elementKey={`sections.${index}.title`} />
46
+ </Box>
47
+ </AccordionTrigger>
48
+ <AccordionContent elementKey={`sections.${index}.content`}>
49
+ <Box elementKey={`sections.${index}.container`}>
50
+ <Box
51
+ elementKey={`sections.${index}.cards_levoGroup`}
52
+ data-levo_group
53
+ >
54
+ {(content.sections?.[index]?.cards ?? []).map(
55
+ (_, cardIndex) => (
56
+ <Box
57
+ key={cardIndex}
58
+ data-levo_group_item
59
+ elementKey={`sections.${index}.cards.${cardIndex}.card`}
60
+ >
61
+ <Box
62
+ elementKey={`sections.${index}.cards.${cardIndex}.label_container`}
63
+ >
64
+ <Box
65
+ elementKey={`sections.${index}.cards.${cardIndex}.label_divider`}
66
+ />
67
+ <Typography
68
+ elementKey={`sections.${index}.cards.${cardIndex}.label`}
69
+ />
70
+ </Box>
71
+ <Typography
72
+ elementKey={`sections.${index}.cards.${cardIndex}.title`}
73
+ />
74
+ <Typography
75
+ elementKey={`sections.${index}.cards.${cardIndex}.description`}
76
+ />
77
+ </Box>
78
+ ),
79
+ )}
80
+ </Box>
81
+ </Box>
82
+ </AccordionContent>
83
+ </AccordionItem>
84
+ ))}
85
+ </AccordionRoot>
86
+ </Box>
87
+ </Container>
88
+ </Section>
89
+ );
90
+
91
+ export default Content9;
@@ -59,7 +59,14 @@ const DEFAULT_CONTENT = {
59
59
  title: "Your Transformation Starts Today",
60
60
  description:
61
61
  "No more guesswork. No more excuses. Just real, proven training that delivers results built around you.",
62
- ctaButton: "Book Your First Class",
62
+ buttons: [
63
+ {
64
+ text: "Book Your First Class",
65
+ },
66
+ {
67
+ text: "Learn More",
68
+ },
69
+ ],
63
70
  };
64
71
 
65
72
  export type ICta2Content = typeof DEFAULT_CONTENT;
@@ -103,10 +110,19 @@ export const Cta2: IBlock = {
103
110
  label: "Description",
104
111
  field_interface: "TypographyWidget",
105
112
  },
113
+
106
114
  {
107
- key: "ctaButton",
108
- label: "CTA Button",
109
- field_interface: "ButtonWidget",
115
+ key: "buttons",
116
+ label: "Buttons",
117
+ kind: "group",
118
+ field_interface: "BoxWidget",
119
+ fields: [
120
+ {
121
+ key: "text",
122
+ label: "Button",
123
+ field_interface: "ButtonWidget",
124
+ },
125
+ ],
110
126
  },
111
127
  {
112
128
  key: "rightImage",
@@ -203,6 +219,32 @@ export const Cta2: IBlock = {
203
219
  "margin-bottom": "lg",
204
220
  "text-color": "text-2",
205
221
  },
222
+ buttons_levoGroup: {
223
+ display: "flex",
224
+ "flex-direction": "row",
225
+ "column-gap": "base",
226
+ "align-items": "center",
227
+ mobile: {
228
+ "flex-direction": "column",
229
+ "row-gap": "sm",
230
+ },
231
+ },
232
+ buttons: [
233
+ {
234
+ text: {
235
+ selectedVariants: {
236
+ Button_Variants: "Primary",
237
+ },
238
+ },
239
+ },
240
+ {
241
+ text: {
242
+ selectedVariants: {
243
+ Button_Variants: "Secondary",
244
+ },
245
+ },
246
+ },
247
+ ],
206
248
  },
207
249
  },
208
250
  ],
@@ -18,7 +18,15 @@ const Cta2: React.FC<ILevoBlockBaseProps<ICta2Content>> = ({ content }) => (
18
18
  <Box elementKey="contentContainer">
19
19
  <Heading elementKey="title" />
20
20
  <Typography elementKey="description" />
21
- <Button elementKey="ctaButton" />
21
+ <Box elementKey="buttons_levoGroup" data-levo_group>
22
+ {(content?.buttons ?? []).map((_: any, index: number) => (
23
+ <Button
24
+ key={index}
25
+ data-levo_group_item
26
+ elementKey={`buttons.${index}.text`}
27
+ />
28
+ ))}
29
+ </Box>
22
30
  </Box>
23
31
  <Image elementKey="rightImage" alt="Right fitness image" />
24
32
  </Container>
@@ -9,6 +9,21 @@ const DEFAULT_CONTENT = {
9
9
  description: "We've got something special to share with you. Take a look!",
10
10
  embed: "",
11
11
  };
12
+ const DEFAULT_CONTENT_2 = {
13
+ layout: null,
14
+ container: null,
15
+ contentWrapper: null,
16
+ title: "Visit Our Store",
17
+ description:
18
+ "<p>Experience wellness in person — explore our full range of CBD &amp; THC and find the right balance for your lifestyle.</p>",
19
+ ctas: [
20
+ {
21
+ cta: "Get Direction",
22
+ },
23
+ ],
24
+ embed:
25
+ '<iframe\n src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3153.019266284122!2d-122.41941568468298!3d37.77492977975937!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8085808b5f4d3f7d%3A0x9e1bfb7b9e8e6b!2sSan%20Francisco%2C%20CA%2C%20USA!5e0!3m2!1sen!2sin!4v1697030400000!5m2!1sen!2sin"\n width="100%"\n height="100%"\n style="border:0;"\n allowfullscreen=""\n loading="lazy"\n referrerpolicy="no-referrer-when-downgrade"\n></iframe>\n',
26
+ };
12
27
 
13
28
  export type IEmbed1Content = typeof DEFAULT_CONTENT;
14
29
 
@@ -149,5 +164,90 @@ export const Embed1: IBlock = {
149
164
  content: DEFAULT_CONTENT,
150
165
  config: {},
151
166
  },
167
+ {
168
+ key: "variant-1",
169
+ title: "Variant 1",
170
+ styles: {
171
+ layout: {
172
+ "padding-left": "8xl",
173
+ "padding-right": "8xl",
174
+ "padding-top": "8xl",
175
+ "padding-bottom": "8xl",
176
+ tablet: {
177
+ "padding-left": "4xl",
178
+ "padding-right": "4xl",
179
+ "padding-top": "4xl",
180
+ "padding-bottom": "4xl",
181
+ },
182
+ mobile: {
183
+ "padding-left": "lg",
184
+ "padding-right": "lg",
185
+ "padding-top": "lg",
186
+ "padding-bottom": "lg",
187
+ },
188
+ },
189
+ container: {
190
+ display: "flex",
191
+ "justify-content": "space-between",
192
+ tablet: {
193
+ "flex-direction": "column",
194
+ "column-gap": "none",
195
+ "row-gap": "xl",
196
+ "padding-top": "xl",
197
+ },
198
+ mobile: {
199
+ "row-gap": "base",
200
+ "padding-top": "base",
201
+ },
202
+ "max-width": "auto",
203
+ "background-color": "background-3",
204
+ },
205
+ embed: {
206
+ width: "50%",
207
+ height: "400px",
208
+ tablet: {
209
+ width: "100%",
210
+ height: "300px",
211
+ },
212
+ mobile: {
213
+ height: "250px",
214
+ },
215
+ },
216
+ contentWrapper: {
217
+ display: "flex",
218
+ "flex-direction": "column",
219
+ "align-items": "start",
220
+ "justify-content": "center",
221
+ "row-gap": "base",
222
+ "padding-left": "none",
223
+ tablet: {
224
+ "padding-left": "xl",
225
+ "padding-right": "xl",
226
+ },
227
+ mobile: {
228
+ "padding-left": "base",
229
+ "padding-right": "base",
230
+ },
231
+ "max-width": "400px",
232
+ },
233
+ textWrapper: {
234
+ display: "flex",
235
+ "flex-direction": "column",
236
+ "row-gap": "4xs",
237
+ },
238
+ title: {
239
+ "font-size": "4xl",
240
+ mobile: {
241
+ "font-size": "2xl",
242
+ },
243
+ },
244
+ description: {
245
+ "line-height": 1.625,
246
+ },
247
+ },
248
+
249
+ content: DEFAULT_CONTENT_2,
250
+ config: {},
251
+ },
152
252
  ],
153
253
  };
@@ -0,0 +1,27 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ interface IClientOnlyProps {
4
+ children: React.ReactNode;
5
+ fallback?: React.ReactNode;
6
+ }
7
+
8
+ /**
9
+ * Component that renders its children on the client side only to prevent hydration mismatches.
10
+ * Useful for content that differs between server and client (e.g., dates with timezone, localStorage-dependent content).
11
+ */
12
+ export const ClientOnly: React.FC<IClientOnlyProps> = ({
13
+ children,
14
+ fallback = null,
15
+ }) => {
16
+ const [mounted, setMounted] = useState(false);
17
+
18
+ useEffect(() => {
19
+ setMounted(true);
20
+ }, []);
21
+
22
+ if (!mounted) {
23
+ return <>{fallback}</>;
24
+ }
25
+
26
+ return children;
27
+ };
@@ -12,6 +12,7 @@ import {
12
12
  import dayjs from "dayjs";
13
13
 
14
14
  import type { IEventDetailsContent } from "./event-details.schema";
15
+ import { ClientOnly } from "./ClientOnly";
15
16
 
16
17
  const EventDetails: React.FC<ILevoBlockBaseProps<IEventDetailsContent>> = ({
17
18
  content,
@@ -32,19 +33,25 @@ const EventDetails: React.FC<ILevoBlockBaseProps<IEventDetailsContent>> = ({
32
33
  <Box elementKey="start-date-wrapper">
33
34
  <Icon elementKey="date-icon" />
34
35
  <Typography elementKey="starts_at">
35
- {dayjs(content?.starts_at).format("MMM D, YYYY")}
36
+ <ClientOnly>
37
+ {dayjs(content?.starts_at).format("MMM D, YYYY")}
38
+ </ClientOnly>
36
39
  </Typography>
37
40
  </Box>
38
41
  <Box elementKey="end-date-wrapper">
39
42
  <Icon elementKey="end-date-icon" />
40
43
  <Typography elementKey="ends_at">
41
- {dayjs(content?.ends_at).format("MMM D, YYYY")}
44
+ <ClientOnly>
45
+ {dayjs(content?.ends_at).format("MMM D, YYYY")}
46
+ </ClientOnly>
42
47
  </Typography>
43
48
  </Box>
44
49
  <Box elementKey="time-wrapper">
45
50
  <Icon elementKey="time-icon" />
46
51
  <Typography elementKey="time-range">
47
- {`${dayjs(content?.starts_at).format("hh:mm A")} - ${dayjs(content?.ends_at).format("hh:mm A")}`}
52
+ <ClientOnly>
53
+ {`${dayjs(content?.starts_at).format("hh:mm A")} - ${dayjs(content?.ends_at).format("hh:mm A")}`}
54
+ </ClientOnly>
48
55
  </Typography>
49
56
  </Box>
50
57
  <Box elementKey="kind-wrapper">
@@ -13,6 +13,7 @@ import {
13
13
  } from "@levo-so/studio";
14
14
 
15
15
  import type { IEventListing3 } from "./event-listing-3.schema";
16
+ import { ClientOnly } from "./ClientOnly";
16
17
 
17
18
  const EventListing3: React.FC<ILevoBlockBaseProps<IEventListing3>> = () => {
18
19
  const { data, query, setQuery, meta } = useContentEngine("events");
@@ -43,7 +44,11 @@ const EventListing3: React.FC<ILevoBlockBaseProps<IEventListing3>> = () => {
43
44
  <Typography
44
45
  elementKey={`events.${index}.publishedAt-header`}
45
46
  >
46
- {dayjs(item?.starts_at).format("MMM D, YYYY")}
47
+ <ClientOnly>
48
+ {dayjs(item?.["publishedAt-header"]).format(
49
+ "MMM D, YYYY",
50
+ )}
51
+ </ClientOnly>
47
52
  </Typography>
48
53
  </Box>
49
54
 
@@ -57,7 +62,9 @@ const EventListing3: React.FC<ILevoBlockBaseProps<IEventListing3>> = () => {
57
62
  <Typography elementKey={`events.${index}.title`} />
58
63
  <Typography elementKey={`events.${index}.description`} />
59
64
  <Typography elementKey={`events.${index}.publishedAt`}>
60
- {dayjs(item?.starts_at).format("MMM D, YYYY")}
65
+ <ClientOnly>
66
+ {dayjs(item?.publishedAt).format("MMM D, YYYY")}
67
+ </ClientOnly>
61
68
  </Typography>
62
69
 
63
70
  <Button elementKey={`events.${index}.cta`} />
@@ -13,6 +13,7 @@ import {
13
13
  import dayjs from "dayjs";
14
14
 
15
15
  import type { IEventListing4 } from "./event-listing-4.schema";
16
+ import { ClientOnly } from "./ClientOnly";
16
17
 
17
18
  const EventListing4: React.FC<ILevoBlockBaseProps<IEventListing4>> = () => {
18
19
  const { data, query, setQuery, meta } = useContentEngine("events");
@@ -46,7 +47,11 @@ const EventListing4: React.FC<ILevoBlockBaseProps<IEventListing4>> = () => {
46
47
  <Typography
47
48
  elementKey={`events.${index}.publishedAt-header`}
48
49
  >
49
- {dayjs(item?.starts_at).format("MMM D, YYYY")}
50
+ <ClientOnly>
51
+ {dayjs(item?.["publishedAt-header"]).format(
52
+ "MMM D, YYYY",
53
+ )}
54
+ </ClientOnly>
50
55
  </Typography>
51
56
  <Typography elementKey={`events.${index}.role-text`} />
52
57
  </Box>
@@ -56,7 +61,11 @@ const EventListing4: React.FC<ILevoBlockBaseProps<IEventListing4>> = () => {
56
61
  elementKey={`events.${index}.event-end-date-icon`}
57
62
  />
58
63
  <Typography elementKey={`events.${index}.event-end-date`}>
59
- {dayjs(item?.ends_at).format("MMM D, YYYY")}
64
+ <ClientOnly>
65
+ {dayjs(item?.["event-end-date"]).format(
66
+ "MMM D, YYYY",
67
+ )}
68
+ </ClientOnly>
60
69
  </Typography>
61
70
  <Typography elementKey={`events.${index}.company-text`} />
62
71
  </Box>
@@ -13,6 +13,7 @@ import {
13
13
  } from "@levo-so/studio";
14
14
 
15
15
  import type { IEventListing } from "./event-listing.schema";
16
+ import { ClientOnly } from "./ClientOnly";
16
17
 
17
18
  const EventListing: React.FC<ILevoBlockBaseProps<IEventListing>> = () => {
18
19
  const { data, query, setQuery, meta } = useContentEngine("events");
@@ -36,8 +37,8 @@ const EventListing: React.FC<ILevoBlockBaseProps<IEventListing>> = () => {
36
37
  elementKey={`events.${index}.eventWrapper`}
37
38
  >
38
39
  <Image
39
- height="60px"
40
- width="120px"
40
+ height={200}
41
+ width={360}
41
42
  elementKey={`events.${index}.image`}
42
43
  alt="event poster"
43
44
  />
@@ -50,7 +51,11 @@ const EventListing: React.FC<ILevoBlockBaseProps<IEventListing>> = () => {
50
51
  <Typography
51
52
  elementKey={`events.${index}.publishedAt-header`}
52
53
  >
53
- {dayjs(item?.starts_at).format("MMM D, YYYY")}
54
+ <ClientOnly>
55
+ {dayjs(item?.["publishedAt-header"]).format(
56
+ "MMM D, YYYY",
57
+ )}
58
+ </ClientOnly>
54
59
  </Typography>
55
60
  </Box>
56
61
  </Box>
@@ -58,7 +63,9 @@ const EventListing: React.FC<ILevoBlockBaseProps<IEventListing>> = () => {
58
63
  <Typography elementKey={`events.${index}.title`} />
59
64
  <Typography elementKey={`events.${index}.description`} />
60
65
  <Typography elementKey={`events.${index}.publishedAt`}>
61
- {dayjs(item?.starts_at).format("MMM D, YYYY")}
66
+ <ClientOnly>
67
+ {dayjs(item?.publishedAt).format("MMM D, YYYY")}
68
+ </ClientOnly>
62
69
  </Typography>
63
70
  </Box>
64
71
  </Box>
@@ -33,6 +33,7 @@ const DEFAULT_CONTENT = {
33
33
  question: "How do I initiate a legal consultation with your team?",
34
34
  answer:
35
35
  "Simply reach out through our contact page, and our team will promptly schedule a confidential consultation to address your legal concerns",
36
+ features: [],
36
37
  },
37
38
  {
38
39
  wrapper: null,
@@ -43,6 +44,7 @@ const DEFAULT_CONTENT = {
43
44
  question: "What areas of law does your firm specialize in?",
44
45
  answer:
45
46
  "Simply reach out through our contact page, and our team will promptly schedule a confidential consultation to address your legal concerns",
47
+ features: [],
46
48
  },
47
49
  {
48
50
  wrapper: null,
@@ -53,6 +55,7 @@ const DEFAULT_CONTENT = {
53
55
  question: "How does your fee structure work?",
54
56
  answer:
55
57
  "Simply reach out through our contact page, and our team will promptly schedule a confidential consultation to address your legal concerns",
58
+ features: [],
56
59
  },
57
60
  {
58
61
  wrapper: null,
@@ -63,6 +66,7 @@ const DEFAULT_CONTENT = {
63
66
  question: "What sets your legal team apart from others?",
64
67
  answer:
65
68
  "Simply reach out through our contact page, and our team will promptly schedule a confidential consultation to address your legal concerns",
69
+ features: [],
66
70
  },
67
71
  ],
68
72
 
@@ -212,6 +216,30 @@ export const Faq1: IBlock = {
212
216
  max_characters: 220,
213
217
  },
214
218
  },
219
+
220
+ {
221
+ key: "features",
222
+ label: "Features",
223
+ kind: "group",
224
+ field_interface: "BoxWidget",
225
+ fields: [
226
+ {
227
+ key: "wrapper",
228
+ label: "Wrapper",
229
+ field_interface: "BoxWidget",
230
+ },
231
+ {
232
+ key: "icon",
233
+ label: "Icon",
234
+ field_interface: "IconWidget",
235
+ },
236
+ {
237
+ key: "label",
238
+ label: "Label",
239
+ field_interface: "TypographyWidget",
240
+ },
241
+ ],
242
+ },
215
243
  ],
216
244
  hint: {
217
245
  prompt_description:
@@ -225,7 +253,6 @@ export const Faq1: IBlock = {
225
253
  label: "CTA",
226
254
  field_interface: "ButtonWidget",
227
255
  },
228
-
229
256
  {
230
257
  key: "faq_image",
231
258
  label: "Faq Image",
@@ -341,6 +368,36 @@ export const Faq1: IBlock = {
341
368
  "align-items": "center",
342
369
  "column-gap": "base",
343
370
  },
371
+ features_list: {
372
+ display: "flex",
373
+ "flex-direction": "row",
374
+ "column-gap": "lg",
375
+ "margin-top": "base",
376
+ "flex-wrap": "wrap",
377
+ },
378
+ features: [
379
+ {
380
+ wrapper: {
381
+ display: "flex",
382
+ "align-items": "center",
383
+ "column-gap": "xs",
384
+ "background-color": "background-2",
385
+ "padding-left": "sm",
386
+ "padding-right": "sm",
387
+ "padding-top": "2xs",
388
+ "padding-bottom": "2xs",
389
+ "border-radius": "md",
390
+ },
391
+ icon: {
392
+ width: "16px",
393
+ height: "16px",
394
+ },
395
+ label: {
396
+ "font-size": "sm",
397
+ color: "text-2",
398
+ },
399
+ },
400
+ ],
344
401
  };
345
402
  }),
346
403
  },
@@ -31,7 +31,7 @@ const Faq1: React.FC<ILevoBlockBaseProps<IFaq1Content>> = ({ content }) => (
31
31
  data-levo_group
32
32
  defaultValue={`item-0`}
33
33
  >
34
- {(content.faqs ?? []).map((_, index) => (
34
+ {(content.faqs ?? []).map((item: any, index) => (
35
35
  <AccordionItem
36
36
  value={`item-${index}`}
37
37
  key={index}
@@ -46,6 +46,23 @@ const Faq1: React.FC<ILevoBlockBaseProps<IFaq1Content>> = ({ content }) => (
46
46
  </AccordionTrigger>
47
47
  <AccordionContent elementKey={`faqs.${index}.content`}>
48
48
  <Typography elementKey={`faqs.${index}.answer`} />
49
+ <Box elementKey={`faqs.${index}.features`}>
50
+ {(item.features ?? []).map(
51
+ (feature: any, featureIndex: number) => (
52
+ <Box
53
+ key={featureIndex}
54
+ elementKey={`faqs.${index}.features.${featureIndex}.wrapper`}
55
+ >
56
+ <Icon
57
+ elementKey={`faqs.${index}.features.${featureIndex}.icon`}
58
+ />
59
+ <Typography
60
+ elementKey={`faqs.${index}.features.${featureIndex}.label`}
61
+ />
62
+ </Box>
63
+ ),
64
+ )}
65
+ </Box>
49
66
  </AccordionContent>
50
67
  </AccordionItem>
51
68
  ))}
@@ -1,9 +1,10 @@
1
+ "use client";
2
+
1
3
  import React, { useState } from "react";
2
4
  import {
3
5
  type ILevoBlockBaseProps,
4
6
  Heading,
5
7
  Icon,
6
- Image,
7
8
  Typography,
8
9
  Container,
9
10
  Section,
@@ -12,7 +12,7 @@ const DEFAULT_CONTENT = {
12
12
 
13
13
  // main content wrapper with accordion and image in row
14
14
  main_content_container: null,
15
-
15
+ header_cta: "Contact Us",
16
16
  // accordions wrapper
17
17
  accordions_container: null,
18
18
 
@@ -137,6 +137,11 @@ export const Faq3: IBlock = {
137
137
  max_characters: 120,
138
138
  },
139
139
  },
140
+ {
141
+ key: "header_cta",
142
+ label: "Header CTA",
143
+ field_interface: "ButtonWidget",
144
+ },
140
145
  {
141
146
  key: "main_content_container",
142
147
  label: "Main Content Container",
@@ -21,6 +21,7 @@ const Faq3: React.FC<ILevoBlockBaseProps<IFaq3Content>> = ({ content }) => (
21
21
  <Box elementKey="header_container">
22
22
  <Heading elementKey="title" />
23
23
  <Typography elementKey="description" />
24
+ <Button elementKey="header_cta" />
24
25
  </Box>
25
26
 
26
27
  <Box elementKey="main_content_container">
@@ -5,6 +5,7 @@ import {
5
5
  defaultFeatures1Variant,
6
6
  stylizedCardsV1Features1Variant,
7
7
  stylizedCardsV2Features1Variant,
8
+ stylizedCardsV3Features1Variant,
8
9
  } from "./variants";
9
10
 
10
11
  export type IFeatures1Content = typeof DEFAULT_CONTENT;
@@ -161,5 +162,6 @@ export const Features1: IBlock = {
161
162
  defaultFeatures1Variant,
162
163
  stylizedCardsV1Features1Variant,
163
164
  stylizedCardsV2Features1Variant,
165
+ stylizedCardsV3Features1Variant,
164
166
  ],
165
167
  };
@@ -1,10 +1,12 @@
1
1
  import { stylizedCardsV1Features1Variant } from "./stylized-cards-v1";
2
2
  import { stylizedCardsV2Features1Variant } from "./stylized-cards-v2";
3
+ import { stylizedCardsV3Features1Variant } from "./stylized-cards-v3";
3
4
  import { defaultFeatures1Variant, DEFAULT_CONTENT } from "./default";
4
5
 
5
6
  export {
6
7
  stylizedCardsV1Features1Variant,
7
8
  stylizedCardsV2Features1Variant,
9
+ stylizedCardsV3Features1Variant,
8
10
  defaultFeatures1Variant,
9
11
  DEFAULT_CONTENT,
10
12
  };