@nextsparkjs/theme-default 0.1.0-beta.1

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 (333) hide show
  1. package/about/business.md +49 -0
  2. package/about/features.json +302 -0
  3. package/about/team.md +79 -0
  4. package/api/ai/chat/stream/route.ts +212 -0
  5. package/api/ai/orchestrator/route.ts +226 -0
  6. package/api/ai/single-agent/route.ts +291 -0
  7. package/api/ai/usage/route.ts +122 -0
  8. package/blocks/benefits/component.tsx +100 -0
  9. package/blocks/benefits/config.ts +11 -0
  10. package/blocks/benefits/examples.ts +85 -0
  11. package/blocks/benefits/fields.ts +156 -0
  12. package/blocks/benefits/schema.ts +33 -0
  13. package/blocks/cta-section/component.tsx +100 -0
  14. package/blocks/cta-section/config.ts +11 -0
  15. package/blocks/cta-section/examples.ts +41 -0
  16. package/blocks/cta-section/fields.ts +89 -0
  17. package/blocks/cta-section/index.ts +6 -0
  18. package/blocks/cta-section/schema.ts +32 -0
  19. package/blocks/cta-section/thumbnail.png +1 -0
  20. package/blocks/faq-accordion/component.tsx +156 -0
  21. package/blocks/faq-accordion/config.ts +11 -0
  22. package/blocks/faq-accordion/examples.ts +77 -0
  23. package/blocks/faq-accordion/fields.ts +119 -0
  24. package/blocks/faq-accordion/index.ts +6 -0
  25. package/blocks/faq-accordion/schema.ts +45 -0
  26. package/blocks/features-grid/component.tsx +112 -0
  27. package/blocks/features-grid/config.ts +11 -0
  28. package/blocks/features-grid/examples.ts +63 -0
  29. package/blocks/features-grid/fields.ts +97 -0
  30. package/blocks/features-grid/index.ts +6 -0
  31. package/blocks/features-grid/schema.ts +40 -0
  32. package/blocks/features-grid/thumbnail.png +1 -0
  33. package/blocks/hero/component.tsx +100 -0
  34. package/blocks/hero/config.ts +11 -0
  35. package/blocks/hero/examples.ts +35 -0
  36. package/blocks/hero/fields.ts +60 -0
  37. package/blocks/hero/index.ts +6 -0
  38. package/blocks/hero/schema.ts +32 -0
  39. package/blocks/hero/thumbnail.png +1 -0
  40. package/blocks/hero/thumbnail.png.txt +6 -0
  41. package/blocks/hero-with-form/component.tsx +232 -0
  42. package/blocks/hero-with-form/config.ts +11 -0
  43. package/blocks/hero-with-form/examples.ts +16 -0
  44. package/blocks/hero-with-form/fields.ts +207 -0
  45. package/blocks/hero-with-form/index.ts +6 -0
  46. package/blocks/hero-with-form/schema.ts +54 -0
  47. package/blocks/jumbotron/component.tsx +136 -0
  48. package/blocks/jumbotron/config.ts +11 -0
  49. package/blocks/jumbotron/examples.ts +36 -0
  50. package/blocks/jumbotron/fields.ts +202 -0
  51. package/blocks/jumbotron/index.ts +6 -0
  52. package/blocks/jumbotron/schema.ts +55 -0
  53. package/blocks/logo-cloud/component.tsx +154 -0
  54. package/blocks/logo-cloud/config.ts +11 -0
  55. package/blocks/logo-cloud/examples.ts +34 -0
  56. package/blocks/logo-cloud/fields.ts +133 -0
  57. package/blocks/logo-cloud/index.ts +6 -0
  58. package/blocks/logo-cloud/schema.ts +46 -0
  59. package/blocks/post-content/component.tsx +197 -0
  60. package/blocks/post-content/config.ts +11 -0
  61. package/blocks/post-content/examples.ts +33 -0
  62. package/blocks/post-content/fields.ts +165 -0
  63. package/blocks/post-content/index.ts +4 -0
  64. package/blocks/post-content/schema.ts +46 -0
  65. package/blocks/pricing-table/component.tsx +154 -0
  66. package/blocks/pricing-table/config.ts +11 -0
  67. package/blocks/pricing-table/examples.ts +96 -0
  68. package/blocks/pricing-table/fields.ts +161 -0
  69. package/blocks/pricing-table/index.ts +4 -0
  70. package/blocks/pricing-table/schema.ts +50 -0
  71. package/blocks/split-content/component.tsx +135 -0
  72. package/blocks/split-content/config.ts +11 -0
  73. package/blocks/split-content/examples.ts +38 -0
  74. package/blocks/split-content/fields.ts +198 -0
  75. package/blocks/split-content/index.ts +6 -0
  76. package/blocks/split-content/schema.ts +67 -0
  77. package/blocks/stats-counter/component.tsx +124 -0
  78. package/blocks/stats-counter/config.ts +11 -0
  79. package/blocks/stats-counter/examples.ts +61 -0
  80. package/blocks/stats-counter/fields.ts +134 -0
  81. package/blocks/stats-counter/index.ts +6 -0
  82. package/blocks/stats-counter/schema.ts +47 -0
  83. package/blocks/testimonials/component.tsx +114 -0
  84. package/blocks/testimonials/config.ts +11 -0
  85. package/blocks/testimonials/examples.ts +65 -0
  86. package/blocks/testimonials/fields.ts +105 -0
  87. package/blocks/testimonials/index.ts +6 -0
  88. package/blocks/testimonials/schema.ts +41 -0
  89. package/blocks/testimonials/thumbnail.png +1 -0
  90. package/blocks/text-content/component.tsx +97 -0
  91. package/blocks/text-content/config.ts +11 -0
  92. package/blocks/text-content/examples.ts +30 -0
  93. package/blocks/text-content/fields.ts +88 -0
  94. package/blocks/text-content/index.ts +6 -0
  95. package/blocks/text-content/schema.ts +30 -0
  96. package/blocks/text-content/thumbnail.png +1 -0
  97. package/blocks/timeline/component.tsx +267 -0
  98. package/blocks/timeline/config.ts +11 -0
  99. package/blocks/timeline/examples.ts +68 -0
  100. package/blocks/timeline/fields.ts +147 -0
  101. package/blocks/timeline/index.ts +6 -0
  102. package/blocks/timeline/schema.ts +49 -0
  103. package/blocks/video-hero/component.tsx +270 -0
  104. package/blocks/video-hero/config.ts +11 -0
  105. package/blocks/video-hero/examples.ts +24 -0
  106. package/blocks/video-hero/fields.ts +98 -0
  107. package/blocks/video-hero/index.ts +6 -0
  108. package/blocks/video-hero/schema.ts +39 -0
  109. package/components/ai-chat/ChatPanel.tsx +575 -0
  110. package/components/ai-chat/ConversationItem.tsx +266 -0
  111. package/components/ai-chat/ConversationSidebar.tsx +99 -0
  112. package/components/ai-chat/MarkdownRenderer.tsx +15 -0
  113. package/components/ai-chat/Message.tsx +42 -0
  114. package/components/ai-chat/MessageInput.tsx +49 -0
  115. package/components/ai-chat/MessageList.tsx +46 -0
  116. package/components/ai-chat/TypingIndicator.tsx +11 -0
  117. package/config/app.config.ts +367 -0
  118. package/config/billing.config.ts +349 -0
  119. package/config/dashboard.config.ts +506 -0
  120. package/config/dev.config.ts +104 -0
  121. package/config/features.config.ts +203 -0
  122. package/config/flows.config.ts +129 -0
  123. package/config/permissions.config.ts +245 -0
  124. package/config/theme.config.ts +74 -0
  125. package/docs/01-overview/01-introduction.md +335 -0
  126. package/docs/01-overview/02-customization.md +671 -0
  127. package/docs/02-features/01-components.md +155 -0
  128. package/docs/02-features/02-styling.md +139 -0
  129. package/docs/02-features/03-tasks-entity.md +407 -0
  130. package/docs/03-ai/01-overview.md +211 -0
  131. package/docs/03-ai/02-customization.md +436 -0
  132. package/entities/customers/customers.config.ts +75 -0
  133. package/entities/customers/customers.fields.ts +165 -0
  134. package/entities/customers/customers.service.ts +516 -0
  135. package/entities/customers/customers.types.ts +83 -0
  136. package/entities/customers/messages/en.json +66 -0
  137. package/entities/customers/messages/es.json +66 -0
  138. package/entities/customers/migrations/001_customers_table.sql +102 -0
  139. package/entities/customers/migrations/002_customers_metas.sql +92 -0
  140. package/entities/pages/messages/en.json +41 -0
  141. package/entities/pages/messages/es.json +41 -0
  142. package/entities/pages/migrations/001_pages_table.sql +112 -0
  143. package/entities/pages/migrations/002_pages_metas.sql +56 -0
  144. package/entities/pages/migrations/003_add_status.sql +50 -0
  145. package/entities/pages/pages-management.service.ts +610 -0
  146. package/entities/pages/pages.config.ts +94 -0
  147. package/entities/pages/pages.fields.ts +101 -0
  148. package/entities/pages/pages.service.ts +290 -0
  149. package/entities/pages/pages.types.ts +124 -0
  150. package/entities/posts/components/post-header.tsx +97 -0
  151. package/entities/posts/messages/en.json +55 -0
  152. package/entities/posts/messages/es.json +55 -0
  153. package/entities/posts/migrations/001_posts_table.sql +115 -0
  154. package/entities/posts/migrations/003_add_status.sql +44 -0
  155. package/entities/posts/migrations/004_entity_taxonomy_relations.sql +129 -0
  156. package/entities/posts/migrations/006_posts_metas.sql +56 -0
  157. package/entities/posts/posts.config.ts +101 -0
  158. package/entities/posts/posts.fields.ts +116 -0
  159. package/entities/posts/posts.service.ts +376 -0
  160. package/entities/posts/posts.types.ts +74 -0
  161. package/entities/tasks/messages/en.json +204 -0
  162. package/entities/tasks/messages/es.json +204 -0
  163. package/entities/tasks/migrations/001_tasks_table.sql +105 -0
  164. package/entities/tasks/migrations/002_task_metas.sql +85 -0
  165. package/entities/tasks/migrations/sample_data.json +77 -0
  166. package/entities/tasks/tasks.config.ts +79 -0
  167. package/entities/tasks/tasks.fields.ts +196 -0
  168. package/entities/tasks/tasks.service.ts +541 -0
  169. package/entities/tasks/tasks.types.ts +56 -0
  170. package/lib/hooks/useAiChat.ts +114 -0
  171. package/lib/hooks/useConversations.ts +376 -0
  172. package/lib/hooks/useOrchestratorChat.ts +122 -0
  173. package/lib/hooks/usePersistentChat.ts +315 -0
  174. package/lib/hooks/useStreamingChat.ts +127 -0
  175. package/lib/hooks/useTokenUsage.ts +63 -0
  176. package/lib/langchain/agents/customer-assistant.md +69 -0
  177. package/lib/langchain/agents/index.ts +61 -0
  178. package/lib/langchain/agents/orchestrator.md +59 -0
  179. package/lib/langchain/agents/page-assistant.md +85 -0
  180. package/lib/langchain/agents/single-agent.md +46 -0
  181. package/lib/langchain/agents/task-assistant.md +55 -0
  182. package/lib/langchain/config.ts +45 -0
  183. package/lib/langchain/handlers/customer-handler.ts +338 -0
  184. package/lib/langchain/handlers/page-handler.ts +232 -0
  185. package/lib/langchain/handlers/task-handler.ts +323 -0
  186. package/lib/langchain/langchain.config.ts +223 -0
  187. package/lib/langchain/observability.config.ts +30 -0
  188. package/lib/langchain/orchestrator.ts +562 -0
  189. package/lib/langchain/tools/customers.ts +176 -0
  190. package/lib/langchain/tools/index.ts +10 -0
  191. package/lib/langchain/tools/orchestrator.ts +92 -0
  192. package/lib/langchain/tools/pages.ts +289 -0
  193. package/lib/langchain/tools/tasks.ts +167 -0
  194. package/lib/scheduled-actions/billing.ts +149 -0
  195. package/lib/scheduled-actions/index.ts +170 -0
  196. package/lib/scheduled-actions/webhook.ts +231 -0
  197. package/lib/selectors.ts +197 -0
  198. package/messages/de/admin.json +219 -0
  199. package/messages/de/aiUsage.json +36 -0
  200. package/messages/de/buttons.json +19 -0
  201. package/messages/de/categories.json +35 -0
  202. package/messages/de/common.json +16 -0
  203. package/messages/de/dev.json +101 -0
  204. package/messages/de/docs.json +27 -0
  205. package/messages/de/entities.json +7 -0
  206. package/messages/de/features.json +119 -0
  207. package/messages/de/footer.json +22 -0
  208. package/messages/de/home.json +57 -0
  209. package/messages/de/index.ts +39 -0
  210. package/messages/de/mobileNav.json +13 -0
  211. package/messages/de/navigation.json +8 -0
  212. package/messages/de/observability.json +74 -0
  213. package/messages/de/posts.json +54 -0
  214. package/messages/de/pricing.json +102 -0
  215. package/messages/de/support.json +9 -0
  216. package/messages/de/teams.json +8 -0
  217. package/messages/en/admin.json +219 -0
  218. package/messages/en/aiUsage.json +36 -0
  219. package/messages/en/buttons.json +19 -0
  220. package/messages/en/categories.json +35 -0
  221. package/messages/en/common.json +16 -0
  222. package/messages/en/dev.json +106 -0
  223. package/messages/en/docs.json +27 -0
  224. package/messages/en/entities.json +7 -0
  225. package/messages/en/features.json +119 -0
  226. package/messages/en/footer.json +22 -0
  227. package/messages/en/home.json +57 -0
  228. package/messages/en/index.ts +39 -0
  229. package/messages/en/mobileNav.json +13 -0
  230. package/messages/en/navigation.json +8 -0
  231. package/messages/en/observability.json +74 -0
  232. package/messages/en/posts.json +54 -0
  233. package/messages/en/pricing.json +102 -0
  234. package/messages/en/support.json +9 -0
  235. package/messages/en/teams.json +8 -0
  236. package/messages/es/admin.json +219 -0
  237. package/messages/es/aiUsage.json +36 -0
  238. package/messages/es/buttons.json +19 -0
  239. package/messages/es/categories.json +35 -0
  240. package/messages/es/common.json +16 -0
  241. package/messages/es/dev.json +101 -0
  242. package/messages/es/docs.json +27 -0
  243. package/messages/es/entities.json +7 -0
  244. package/messages/es/features.json +119 -0
  245. package/messages/es/footer.json +22 -0
  246. package/messages/es/home.json +57 -0
  247. package/messages/es/index.ts +39 -0
  248. package/messages/es/mobileNav.json +13 -0
  249. package/messages/es/navigation.json +8 -0
  250. package/messages/es/observability.json +74 -0
  251. package/messages/es/posts.json +54 -0
  252. package/messages/es/pricing.json +102 -0
  253. package/messages/es/support.json +9 -0
  254. package/messages/es/teams.json +8 -0
  255. package/messages/fr/admin.json +219 -0
  256. package/messages/fr/aiUsage.json +36 -0
  257. package/messages/fr/buttons.json +19 -0
  258. package/messages/fr/categories.json +35 -0
  259. package/messages/fr/common.json +16 -0
  260. package/messages/fr/dev.json +101 -0
  261. package/messages/fr/docs.json +27 -0
  262. package/messages/fr/entities.json +7 -0
  263. package/messages/fr/features.json +119 -0
  264. package/messages/fr/footer.json +22 -0
  265. package/messages/fr/home.json +57 -0
  266. package/messages/fr/index.ts +39 -0
  267. package/messages/fr/mobileNav.json +13 -0
  268. package/messages/fr/navigation.json +8 -0
  269. package/messages/fr/observability.json +74 -0
  270. package/messages/fr/posts.json +54 -0
  271. package/messages/fr/pricing.json +102 -0
  272. package/messages/fr/support.json +9 -0
  273. package/messages/fr/teams.json +8 -0
  274. package/messages/it/admin.json +219 -0
  275. package/messages/it/aiUsage.json +36 -0
  276. package/messages/it/buttons.json +19 -0
  277. package/messages/it/categories.json +35 -0
  278. package/messages/it/common.json +16 -0
  279. package/messages/it/dev.json +101 -0
  280. package/messages/it/docs.json +27 -0
  281. package/messages/it/entities.json +7 -0
  282. package/messages/it/features.json +119 -0
  283. package/messages/it/footer.json +22 -0
  284. package/messages/it/home.json +57 -0
  285. package/messages/it/index.ts +39 -0
  286. package/messages/it/mobileNav.json +13 -0
  287. package/messages/it/navigation.json +8 -0
  288. package/messages/it/observability.json +74 -0
  289. package/messages/it/posts.json +54 -0
  290. package/messages/it/pricing.json +102 -0
  291. package/messages/it/support.json +9 -0
  292. package/messages/it/teams.json +8 -0
  293. package/messages/pt/admin.json +219 -0
  294. package/messages/pt/aiUsage.json +36 -0
  295. package/messages/pt/buttons.json +19 -0
  296. package/messages/pt/categories.json +35 -0
  297. package/messages/pt/common.json +16 -0
  298. package/messages/pt/dev.json +101 -0
  299. package/messages/pt/docs.json +27 -0
  300. package/messages/pt/entities.json +7 -0
  301. package/messages/pt/features.json +119 -0
  302. package/messages/pt/footer.json +22 -0
  303. package/messages/pt/home.json +57 -0
  304. package/messages/pt/index.ts +39 -0
  305. package/messages/pt/mobileNav.json +13 -0
  306. package/messages/pt/navigation.json +8 -0
  307. package/messages/pt/observability.json +74 -0
  308. package/messages/pt/posts.json +54 -0
  309. package/messages/pt/pricing.json +102 -0
  310. package/messages/pt/support.json +9 -0
  311. package/messages/pt/teams.json +8 -0
  312. package/migrations/089_add_editor_team_role.sql +39 -0
  313. package/migrations/090_demo_users_teams.sql +540 -0
  314. package/migrations/091_greek_teams_billing.sql +523 -0
  315. package/migrations/092_billing_sample_data.sql +774 -0
  316. package/migrations/093_pages_sample_data.sql +1158 -0
  317. package/migrations/094_posts_sample_data.sql +278 -0
  318. package/migrations/095_tasks_sample_data.sql +440 -0
  319. package/migrations/096_customers_sample_data.sql +358 -0
  320. package/migrations/097_scheduled_actions_sample_data.sql +111 -0
  321. package/package.json +22 -0
  322. package/public/docs/desktop-layout-example.png +0 -0
  323. package/styles/components.css +11 -0
  324. package/styles/globals.css +179 -0
  325. package/templates/(public)/blog/[slug]/page.tsx +65 -0
  326. package/templates/(public)/layout.tsx +25 -0
  327. package/templates/(public)/page.tsx +200 -0
  328. package/templates/(public)/support/page.tsx +321 -0
  329. package/templates/dashboard/(main)/agent-multi/page.tsx +63 -0
  330. package/templates/dashboard/(main)/agent-single/page.tsx +142 -0
  331. package/templates/dashboard/(main)/settings/ai-usage/page.tsx +157 -0
  332. package/templates/superadmin/ai-observability/[traceId]/page.tsx +27 -0
  333. package/templates/superadmin/ai-observability/page.tsx +17 -0
@@ -0,0 +1,156 @@
1
+ 'use client'
2
+
3
+ import React from 'react'
4
+ import { cn } from '@nextsparkjs/core/lib/utils'
5
+ import { buildSectionClasses } from '@nextsparkjs/core/types/blocks'
6
+ import { sel } from '../../lib/selectors'
7
+ import {
8
+ Accordion,
9
+ AccordionContent,
10
+ AccordionItem,
11
+ AccordionTrigger,
12
+ } from '@nextsparkjs/core/components/ui/accordion'
13
+ import type { FaqAccordionBlockProps, FaqItem } from './schema'
14
+
15
+ /**
16
+ * FAQ Accordion Block Component
17
+ *
18
+ * Props from 3-tab structure:
19
+ * - Content: title, subtitle, items
20
+ * - Design: backgroundColor, allowMultiple, defaultOpenFirst, variant
21
+ * - Advanced: className, id
22
+ */
23
+ export function FaqAccordionBlock({
24
+ // Base content props
25
+ title,
26
+ // FAQ-specific content
27
+ subtitle,
28
+ items,
29
+ // Base design props
30
+ backgroundColor,
31
+ // FAQ-specific design
32
+ allowMultiple = false,
33
+ defaultOpenFirst = true,
34
+ variant = 'default',
35
+ // Base advanced props
36
+ className,
37
+ id,
38
+ }: FaqAccordionBlockProps) {
39
+ // Safe fallback for items array
40
+ const safeItems = items ?? []
41
+
42
+ // Determine default value for accordion
43
+ const defaultValue = defaultOpenFirst && safeItems.length > 0 ? 'item-0' : undefined
44
+
45
+ // Build section classes with background and custom className
46
+ const sectionClasses = buildSectionClasses(
47
+ 'py-16 px-4 md:py-24',
48
+ { backgroundColor, className }
49
+ )
50
+
51
+ // Variant-specific classes for accordion container
52
+ const accordionContainerClasses = cn({
53
+ // Default: clean minimal style
54
+ 'space-y-0': variant === 'default',
55
+ // Bordered: contained with border
56
+ 'border rounded-lg overflow-hidden': variant === 'bordered',
57
+ // Separated: gaps between items
58
+ 'space-y-4': variant === 'separated',
59
+ })
60
+
61
+ // Variant-specific classes for accordion items
62
+ const getItemClasses = () => {
63
+ if (variant === 'bordered') {
64
+ return cn(
65
+ 'border-b last:border-b-0',
66
+ 'px-6'
67
+ )
68
+ }
69
+ if (variant === 'separated') {
70
+ return 'border rounded-lg px-6 bg-card'
71
+ }
72
+ // Default variant
73
+ return ''
74
+ }
75
+
76
+ return (
77
+ <section id={id} className={sectionClasses} data-cy={sel('blocks.faqAccordion.container')}>
78
+ <div className="container mx-auto max-w-4xl">
79
+ {/* Section Header */}
80
+ {(title || subtitle) && (
81
+ <div className="mb-12 text-center">
82
+ {title && (
83
+ <h2 className="mb-4 text-4xl font-bold md:text-5xl">
84
+ {title}
85
+ </h2>
86
+ )}
87
+ {subtitle && (
88
+ <p className="mx-auto max-w-2xl text-lg text-muted-foreground">
89
+ {subtitle}
90
+ </p>
91
+ )}
92
+ </div>
93
+ )}
94
+
95
+ {/* FAQ Accordion - Render different types based on allowMultiple */}
96
+ {allowMultiple ? (
97
+ <Accordion
98
+ type="multiple"
99
+ className={accordionContainerClasses}
100
+ >
101
+ {safeItems.map((item: FaqItem, index: number) => (
102
+ <AccordionItem
103
+ key={index}
104
+ value={`item-${index}`}
105
+ className={getItemClasses()}
106
+ data-cy={sel('blocks.faqAccordion.item', { index: String(index) })}
107
+ >
108
+ <AccordionTrigger
109
+ className="text-base font-semibold hover:no-underline"
110
+ data-cy={sel('blocks.faqAccordion.question', { index: String(index) })}
111
+ >
112
+ {item.question}
113
+ </AccordionTrigger>
114
+ <AccordionContent
115
+ className="text-muted-foreground whitespace-pre-wrap"
116
+ data-cy={sel('blocks.faqAccordion.answer', { index: String(index) })}
117
+ >
118
+ {item.answer}
119
+ </AccordionContent>
120
+ </AccordionItem>
121
+ ))}
122
+ </Accordion>
123
+ ) : (
124
+ <Accordion
125
+ type="single"
126
+ defaultValue={defaultValue}
127
+ collapsible
128
+ className={accordionContainerClasses}
129
+ >
130
+ {safeItems.map((item: FaqItem, index: number) => (
131
+ <AccordionItem
132
+ key={index}
133
+ value={`item-${index}`}
134
+ className={getItemClasses()}
135
+ data-cy={sel('blocks.faqAccordion.item', { index: String(index) })}
136
+ >
137
+ <AccordionTrigger
138
+ className="text-base font-semibold hover:no-underline"
139
+ data-cy={sel('blocks.faqAccordion.question', { index: String(index) })}
140
+ >
141
+ {item.question}
142
+ </AccordionTrigger>
143
+ <AccordionContent
144
+ className="text-muted-foreground whitespace-pre-wrap"
145
+ data-cy={sel('blocks.faqAccordion.answer', { index: String(index) })}
146
+ >
147
+ {item.answer}
148
+ </AccordionContent>
149
+ </AccordionItem>
150
+ ))}
151
+ </Accordion>
152
+ )}
153
+ </div>
154
+ </section>
155
+ )
156
+ }
@@ -0,0 +1,11 @@
1
+ import type { BlockConfig } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const config: Omit<BlockConfig, 'schema' | 'fieldDefinitions' | 'Component' | 'examples'> = {
4
+ slug: 'faq-accordion',
5
+ name: 'FAQ Accordion',
6
+ description: 'A frequently asked questions section with expandable/collapsible accordion items',
7
+ category: 'faq',
8
+ icon: 'HelpCircle',
9
+ thumbnail: '/theme/blocks/faq-accordion/thumbnail.png',
10
+ scope: ['pages']
11
+ }
@@ -0,0 +1,77 @@
1
+ import type { BlockExample } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const examples: BlockExample[] = [
4
+ {
5
+ name: 'Default',
6
+ description: 'Standard FAQ accordion',
7
+ props: {
8
+ title: 'Frequently Asked Questions',
9
+ subtitle: 'Find answers to common questions about our platform',
10
+ backgroundColor: 'white',
11
+ variant: 'default',
12
+ allowMultiple: false,
13
+ defaultOpenFirst: true,
14
+ items: [
15
+ {
16
+ question: 'How does the free trial work?',
17
+ answer: 'Start with our 14-day free trial with full access to all features. No credit card required. Cancel anytime.',
18
+ },
19
+ {
20
+ question: 'Can I upgrade or downgrade my plan?',
21
+ answer: 'Yes, you can change your plan at any time. Changes take effect immediately and we prorate billing automatically.',
22
+ },
23
+ {
24
+ question: 'What kind of support do you offer?',
25
+ answer: 'All plans include email support. Premium plans include priority support with 24/7 availability and dedicated account managers.',
26
+ },
27
+ ],
28
+ },
29
+ },
30
+ {
31
+ name: 'Bordered',
32
+ description: 'FAQ with bordered cards',
33
+ props: {
34
+ title: 'Common Questions',
35
+ backgroundColor: 'gray-50',
36
+ variant: 'bordered',
37
+ allowMultiple: true,
38
+ defaultOpenFirst: true,
39
+ items: [
40
+ {
41
+ question: 'Is my data secure?',
42
+ answer: 'We use industry-standard encryption and are SOC 2 Type II certified. Your data is stored in secure, redundant data centers.',
43
+ },
44
+ {
45
+ question: 'Do you offer team pricing?',
46
+ answer: 'Yes, we have special pricing for teams of 10 or more. Contact our sales team for a custom quote.',
47
+ },
48
+ ],
49
+ },
50
+ },
51
+ {
52
+ name: 'Separated',
53
+ description: 'FAQ with separated items',
54
+ props: {
55
+ title: 'Need Help?',
56
+ subtitle: 'Browse our most asked questions',
57
+ backgroundColor: 'white',
58
+ variant: 'separated',
59
+ allowMultiple: true,
60
+ defaultOpenFirst: false,
61
+ items: [
62
+ {
63
+ question: 'How do I get started?',
64
+ answer: 'Sign up for a free account, complete the onboarding wizard, and start inviting your team members.',
65
+ },
66
+ {
67
+ question: 'Can I import my existing data?',
68
+ answer: 'Yes, we support importing from CSV, Excel, and most major platforms. Our team can help with larger migrations.',
69
+ },
70
+ {
71
+ question: 'What payment methods do you accept?',
72
+ answer: 'We accept all major credit cards, PayPal, and wire transfers for annual plans.',
73
+ },
74
+ ],
75
+ },
76
+ },
77
+ ]
@@ -0,0 +1,119 @@
1
+ import type { FieldDefinition } from '@nextsparkjs/core/types/blocks'
2
+ import {
3
+ baseContentFields,
4
+ baseDesignFields,
5
+ baseAdvancedFields,
6
+ } from '@nextsparkjs/core/types/blocks'
7
+
8
+ /**
9
+ * FAQ Accordion Block Field Definitions
10
+ *
11
+ * Organized into 3 tabs:
12
+ * - Content: title (from base) + subtitle + items array
13
+ * - Design: backgroundColor (from base) + allowMultiple + defaultOpenFirst + variant
14
+ * - Advanced: className, id (from base)
15
+ */
16
+
17
+ // FAQ-specific content fields
18
+ const faqContentFields: FieldDefinition[] = [
19
+ {
20
+ name: 'subtitle',
21
+ label: 'Section Description',
22
+ type: 'textarea',
23
+ tab: 'content',
24
+ required: false,
25
+ placeholder: 'Find answers to commonly asked questions about our service...',
26
+ helpText: 'Optional description displayed below the title',
27
+ rows: 3,
28
+ },
29
+ {
30
+ name: 'items',
31
+ label: 'FAQ Items',
32
+ type: 'array',
33
+ tab: 'content',
34
+ required: true,
35
+ description: 'List of frequently asked questions and their answers',
36
+ helpText: 'Add up to 20 FAQ items',
37
+ minItems: 1,
38
+ maxItems: 20,
39
+ itemFields: [
40
+ {
41
+ name: 'question',
42
+ label: 'Question',
43
+ type: 'text',
44
+ tab: 'content',
45
+ required: true,
46
+ placeholder: 'What is your return policy?',
47
+ helpText: 'The question users are asking',
48
+ maxLength: 200,
49
+ },
50
+ {
51
+ name: 'answer',
52
+ label: 'Answer',
53
+ type: 'textarea',
54
+ tab: 'content',
55
+ required: true,
56
+ placeholder: 'Our return policy allows you to return items within 30 days...',
57
+ helpText: 'The answer to the question (supports basic formatting)',
58
+ maxLength: 1000,
59
+ rows: 4,
60
+ },
61
+ ],
62
+ },
63
+ ]
64
+
65
+ // FAQ-specific design fields
66
+ const faqDesignFields: FieldDefinition[] = [
67
+ {
68
+ name: 'allowMultiple',
69
+ label: 'Allow Multiple Open',
70
+ type: 'checkbox',
71
+ tab: 'design',
72
+ required: false,
73
+ default: false,
74
+ description: 'Allow multiple accordion items to be open at the same time',
75
+ helpText: 'When disabled, opening one item will close others',
76
+ },
77
+ {
78
+ name: 'defaultOpenFirst',
79
+ label: 'First Item Open by Default',
80
+ type: 'checkbox',
81
+ tab: 'design',
82
+ required: false,
83
+ default: true,
84
+ description: 'Automatically open the first FAQ item when the page loads',
85
+ },
86
+ {
87
+ name: 'variant',
88
+ label: 'Visual Style',
89
+ type: 'select',
90
+ tab: 'design',
91
+ required: false,
92
+ default: 'default',
93
+ description: 'Choose the visual style variant for the accordion',
94
+ options: [
95
+ { label: 'Default', value: 'default' },
96
+ { label: 'Bordered', value: 'bordered' },
97
+ { label: 'Separated', value: 'separated' },
98
+ ],
99
+ },
100
+ ]
101
+
102
+ /**
103
+ * Complete field definitions organized by tab
104
+ */
105
+ export const fieldDefinitions: FieldDefinition[] = [
106
+ // Content tab: base fields + FAQ-specific
107
+ ...baseContentFields,
108
+ ...faqContentFields,
109
+
110
+ // Design tab: base fields + FAQ-specific
111
+ ...baseDesignFields,
112
+ ...faqDesignFields,
113
+
114
+ // Advanced tab: base fields only
115
+ ...baseAdvancedFields,
116
+ ]
117
+
118
+ // Alias for compatibility
119
+ export const fields = fieldDefinitions
@@ -0,0 +1,6 @@
1
+ export { config } from './config'
2
+ export { schema } from './schema'
3
+ export { fields } from './fields'
4
+ export { FaqAccordionBlock as Component } from './component'
5
+
6
+ export type { FaqAccordionBlockProps } from './schema'
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod'
2
+ import { baseBlockSchema } from '@nextsparkjs/core/types/blocks'
3
+
4
+ /**
5
+ * FAQ Item Schema
6
+ * Individual question-answer pair in the accordion
7
+ */
8
+ const faqItemSchema = z.object({
9
+ question: z.string().min(1, 'Question is required').max(200),
10
+ answer: z.string().min(1, 'Answer is required').max(1000),
11
+ })
12
+
13
+ export type FaqItem = z.infer<typeof faqItemSchema>
14
+
15
+ /**
16
+ * FAQ Accordion Block Schema
17
+ *
18
+ * Extends base schema with:
19
+ * - subtitle: Section description
20
+ * - items: Array of FAQ items (question, answer)
21
+ * - allowMultiple: Allow multiple items open at once
22
+ * - defaultOpenFirst: First item open by default
23
+ * - variant: Visual style variant
24
+ *
25
+ * Note: Uses base schema title, backgroundColor, className, id
26
+ */
27
+ export const faqAccordionSpecificSchema = z.object({
28
+ // Content: subtitle and FAQ items
29
+ subtitle: z.string().optional(),
30
+ items: z.array(faqItemSchema)
31
+ .min(1, 'At least one FAQ item is required')
32
+ .max(20, 'Maximum 20 FAQ items allowed'),
33
+
34
+ // Design: accordion behavior and styling
35
+ allowMultiple: z.boolean().default(false),
36
+ defaultOpenFirst: z.boolean().default(true),
37
+ variant: z.enum(['default', 'bordered', 'separated']).default('default'),
38
+ })
39
+
40
+ /**
41
+ * Complete FAQ Accordion Block Schema
42
+ */
43
+ export const schema = baseBlockSchema.merge(faqAccordionSpecificSchema)
44
+
45
+ export type FaqAccordionBlockProps = z.infer<typeof schema>
@@ -0,0 +1,112 @@
1
+ import React from 'react'
2
+ import * as Icons from 'lucide-react'
3
+ import { cn } from '@nextsparkjs/core/lib/utils'
4
+ import { buildSectionClasses } from '@nextsparkjs/core/types/blocks'
5
+ import { sel } from '../../lib/selectors'
6
+ import type { FeaturesGridBlockProps, FeatureItem } from './schema'
7
+
8
+ /**
9
+ * Features Grid Block Component
10
+ *
11
+ * Props from 3-tab structure:
12
+ * - Content: title, content, cta, items
13
+ * - Design: backgroundColor, columns
14
+ * - Advanced: className, id
15
+ */
16
+ export function FeaturesGridBlock({
17
+ // Base content props
18
+ title,
19
+ content,
20
+ cta,
21
+ // Features-specific content
22
+ items,
23
+ // Base design props
24
+ backgroundColor,
25
+ // Features-specific design
26
+ columns = '3',
27
+ // Base advanced props
28
+ className,
29
+ id,
30
+ // Legacy props for backward compatibility
31
+ ...legacyProps
32
+ }: FeaturesGridBlockProps & { features?: FeatureItem[]; description?: string }) {
33
+ // Handle legacy 'features' prop for backward compatibility
34
+ const safeItems = Array.isArray(items)
35
+ ? items
36
+ : Array.isArray((legacyProps as { features?: FeatureItem[] }).features)
37
+ ? (legacyProps as { features: FeatureItem[] }).features
38
+ : []
39
+
40
+ // Handle legacy description prop
41
+ const displayContent = content || (legacyProps as { description?: string }).description
42
+
43
+ // Build column classes based on columns prop
44
+ const columnClasses: Record<string, string> = {
45
+ '2': 'sm:grid-cols-2',
46
+ '3': 'sm:grid-cols-2 lg:grid-cols-3',
47
+ '4': 'sm:grid-cols-2 lg:grid-cols-4',
48
+ }
49
+
50
+ // Build section classes with background and custom className
51
+ const sectionClasses = buildSectionClasses(
52
+ 'py-16 px-4 md:py-24',
53
+ { backgroundColor, className }
54
+ )
55
+
56
+ return (
57
+ <section id={id} className={sectionClasses} data-cy={sel('blocks.featuresGrid.container')}>
58
+ <div className="container mx-auto max-w-6xl">
59
+ {/* Section Header */}
60
+ {(title || displayContent) && (
61
+ <div className="mb-12 text-center">
62
+ {title && (
63
+ <h2 className="mb-4 text-4xl font-bold md:text-5xl">
64
+ {title}
65
+ </h2>
66
+ )}
67
+ {displayContent && (
68
+ <p className="mx-auto max-w-2xl text-lg text-muted-foreground">
69
+ {displayContent}
70
+ </p>
71
+ )}
72
+ </div>
73
+ )}
74
+
75
+ {/* Features Grid */}
76
+ <div className={cn('grid gap-8', columnClasses[columns] || columnClasses['3'])}>
77
+ {safeItems.map((item, index) => {
78
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
+ const IconComponent = (Icons as any)[item.icon] || Icons.Circle
80
+
81
+ return (
82
+ <div
83
+ key={index}
84
+ className="flex flex-col items-center text-center p-6 rounded-lg border bg-card"
85
+ >
86
+ <div className="mb-4 rounded-full bg-primary/10 p-4">
87
+ <IconComponent className="h-8 w-8 text-primary" />
88
+ </div>
89
+ <h3 className="mb-2 text-xl font-semibold">{item.title}</h3>
90
+ <p className="text-muted-foreground">{item.description}</p>
91
+ </div>
92
+ )
93
+ })}
94
+ </div>
95
+
96
+ {/* Optional CTA */}
97
+ {cta && (
98
+ <div className="mt-12 text-center">
99
+ <a
100
+ href={cta.link}
101
+ target={cta.target}
102
+ rel={cta.target === '_blank' ? 'noopener noreferrer' : undefined}
103
+ className="inline-flex items-center justify-center rounded-md bg-primary px-8 py-3 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors"
104
+ >
105
+ {cta.text}
106
+ </a>
107
+ </div>
108
+ )}
109
+ </div>
110
+ </section>
111
+ )
112
+ }
@@ -0,0 +1,11 @@
1
+ import type { BlockConfig } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const config: Omit<BlockConfig, 'schema' | 'fieldDefinitions' | 'Component' | 'examples'> = {
4
+ slug: 'features-grid',
5
+ name: 'Features Grid',
6
+ description: 'Grid layout displaying multiple features with icons, titles, and descriptions',
7
+ category: 'content',
8
+ icon: 'Grid',
9
+ thumbnail: '/theme/blocks/features-grid/thumbnail.png',
10
+ scope: ['pages']
11
+ }
@@ -0,0 +1,63 @@
1
+ import type { BlockExample } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const examples: BlockExample[] = [
4
+ {
5
+ name: '3 Columns',
6
+ description: 'Feature grid with 3 columns',
7
+ props: {
8
+ title: 'Everything You Need',
9
+ content: 'Powerful features to help you build, launch, and grow your business',
10
+ backgroundColor: 'white',
11
+ columns: '3',
12
+ features: [
13
+ {
14
+ title: 'Team Collaboration',
15
+ description: 'Work together in real-time with your entire team',
16
+ icon: 'Users',
17
+ },
18
+ {
19
+ title: 'Advanced Analytics',
20
+ description: 'Track performance with detailed insights and reports',
21
+ icon: 'BarChart',
22
+ },
23
+ {
24
+ title: 'Automation',
25
+ description: 'Automate workflows and save hours every week',
26
+ icon: 'Zap',
27
+ },
28
+ ],
29
+ },
30
+ },
31
+ {
32
+ name: '4 Columns',
33
+ description: 'Feature grid with 4 columns',
34
+ props: {
35
+ title: 'Complete Feature Set',
36
+ content: 'All the tools you need in one platform',
37
+ backgroundColor: 'gray-50',
38
+ columns: '4',
39
+ features: [
40
+ {
41
+ title: 'Secure Storage',
42
+ description: 'Enterprise-grade encryption for all your files',
43
+ icon: 'Lock',
44
+ },
45
+ {
46
+ title: 'API Access',
47
+ description: 'Build custom integrations with our REST API',
48
+ icon: 'Code',
49
+ },
50
+ {
51
+ title: '24/7 Support',
52
+ description: 'Get help whenever you need it',
53
+ icon: 'MessageCircle',
54
+ },
55
+ {
56
+ title: 'Custom Domains',
57
+ description: 'Use your own domain for branding',
58
+ icon: 'Globe',
59
+ },
60
+ ],
61
+ },
62
+ },
63
+ ]