@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,61 @@
1
+ import type { BlockExample } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const examples: BlockExample[] = [
4
+ {
5
+ name: 'Light Background',
6
+ description: 'Stats counter with light background',
7
+ props: {
8
+ title: 'Trusted by Thousands',
9
+ content: 'Join a growing community of successful businesses',
10
+ backgroundColor: 'gray-50',
11
+ stats: [
12
+ {
13
+ value: '10,000+',
14
+ label: 'Active Users',
15
+ description: 'Growing daily',
16
+ },
17
+ {
18
+ value: '99.9%',
19
+ label: 'Uptime',
20
+ description: 'Reliable service',
21
+ },
22
+ {
23
+ value: '50M+',
24
+ label: 'API Requests',
25
+ description: 'Processed monthly',
26
+ },
27
+ {
28
+ value: '4.9/5',
29
+ label: 'Customer Rating',
30
+ description: 'From 2,000+ reviews',
31
+ },
32
+ ],
33
+ },
34
+ },
35
+ {
36
+ name: 'Dark Background',
37
+ description: 'Stats counter with dark background',
38
+ props: {
39
+ title: 'The Numbers Speak',
40
+ content: 'Real results from real customers',
41
+ backgroundColor: 'gray-900',
42
+ stats: [
43
+ {
44
+ value: '$2.5M+',
45
+ label: 'Revenue Generated',
46
+ description: 'For our customers',
47
+ },
48
+ {
49
+ value: '150+',
50
+ label: 'Countries',
51
+ description: 'Worldwide reach',
52
+ },
53
+ {
54
+ value: '24/7',
55
+ label: 'Support',
56
+ description: 'Always available',
57
+ },
58
+ ],
59
+ },
60
+ },
61
+ ]
@@ -0,0 +1,134 @@
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
+ * Stats Counter Block Field Definitions
10
+ *
11
+ * Organized into 3 tabs:
12
+ * - Content: title, content, cta (from base) + stats array
13
+ * - Design: backgroundColor (from base) + columns, variant, size
14
+ * - Advanced: className, id (from base)
15
+ */
16
+
17
+ // Stats-specific content fields
18
+ const statsContentFields: FieldDefinition[] = [
19
+ {
20
+ name: 'stats',
21
+ label: 'Statistics',
22
+ type: 'array',
23
+ tab: 'content',
24
+ required: true,
25
+ description: 'List of statistics to display',
26
+ helpText: 'Add up to 8 statistics with values and labels',
27
+ minItems: 1,
28
+ maxItems: 8,
29
+ itemFields: [
30
+ {
31
+ name: 'value',
32
+ label: 'Value',
33
+ type: 'text',
34
+ tab: 'content',
35
+ required: true,
36
+ placeholder: '10,000+',
37
+ helpText: 'The number or metric value (e.g., "10,000+", "99%", "$1M+")',
38
+ },
39
+ {
40
+ name: 'label',
41
+ label: 'Label',
42
+ type: 'text',
43
+ tab: 'content',
44
+ required: true,
45
+ placeholder: 'Happy Customers',
46
+ helpText: 'Description of the statistic',
47
+ maxLength: 100,
48
+ },
49
+ {
50
+ name: 'prefix',
51
+ label: 'Prefix',
52
+ type: 'text',
53
+ tab: 'content',
54
+ required: false,
55
+ placeholder: '$',
56
+ helpText: 'Optional prefix (e.g., "$", "+")',
57
+ },
58
+ {
59
+ name: 'suffix',
60
+ label: 'Suffix',
61
+ type: 'text',
62
+ tab: 'content',
63
+ required: false,
64
+ placeholder: '+',
65
+ helpText: 'Optional suffix (e.g., "%", "+", "K")',
66
+ },
67
+ ],
68
+ },
69
+ ]
70
+
71
+ // Stats-specific design fields
72
+ const statsDesignFields: FieldDefinition[] = [
73
+ {
74
+ name: 'columns',
75
+ label: 'Grid Columns',
76
+ type: 'select',
77
+ tab: 'design',
78
+ required: false,
79
+ default: '4',
80
+ description: 'Number of columns in the grid layout',
81
+ options: [
82
+ { label: '2 Columns', value: '2' },
83
+ { label: '3 Columns', value: '3' },
84
+ { label: '4 Columns', value: '4' },
85
+ ],
86
+ },
87
+ {
88
+ name: 'variant',
89
+ label: 'Style Variant',
90
+ type: 'select',
91
+ tab: 'design',
92
+ required: false,
93
+ default: 'default',
94
+ description: 'Visual style of the statistics',
95
+ options: [
96
+ { label: 'Default', value: 'default' },
97
+ { label: 'Cards (with background)', value: 'cards' },
98
+ { label: 'Minimal (text only)', value: 'minimal' },
99
+ ],
100
+ },
101
+ {
102
+ name: 'size',
103
+ label: 'Number Size',
104
+ type: 'select',
105
+ tab: 'design',
106
+ required: false,
107
+ default: 'md',
108
+ description: 'Size of the statistic numbers',
109
+ options: [
110
+ { label: 'Small', value: 'sm' },
111
+ { label: 'Medium', value: 'md' },
112
+ { label: 'Large', value: 'lg' },
113
+ ],
114
+ },
115
+ ]
116
+
117
+ /**
118
+ * Complete field definitions organized by tab
119
+ */
120
+ export const fieldDefinitions: FieldDefinition[] = [
121
+ // Content tab: base fields + stats-specific
122
+ ...baseContentFields,
123
+ ...statsContentFields,
124
+
125
+ // Design tab: base fields + stats-specific
126
+ ...baseDesignFields,
127
+ ...statsDesignFields,
128
+
129
+ // Advanced tab: base fields only
130
+ ...baseAdvancedFields,
131
+ ]
132
+
133
+ // Alias for compatibility
134
+ 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 { StatsCounterBlock as Component } from './component'
5
+
6
+ export type { StatsCounterBlockProps } from './schema'
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod'
2
+ import { baseBlockSchema } from '@nextsparkjs/core/types/blocks'
3
+
4
+ /**
5
+ * Stat Item Schema
6
+ * Individual statistic with value, label, and optional prefix/suffix
7
+ */
8
+ const statItemSchema = z.object({
9
+ value: z.string().min(1, 'Value is required'),
10
+ label: z.string().min(1, 'Label is required').max(100),
11
+ prefix: z.string().optional(),
12
+ suffix: z.string().optional(),
13
+ })
14
+
15
+ export type StatItem = z.infer<typeof statItemSchema>
16
+
17
+ /**
18
+ * Stats Counter Block Schema
19
+ *
20
+ * Extends base schema with:
21
+ * - stats: Array of statistics (value, label, prefix, suffix)
22
+ * - columns: Grid layout option (2, 3, 4 columns)
23
+ * - variant: Visual style (default, cards, minimal)
24
+ * - size: Number size (sm, md, lg)
25
+ *
26
+ * Note: Uses base schema title, content, cta, backgroundColor, className, id
27
+ * The `title` field serves as optional section title
28
+ * The `content` field serves as optional section description/subtitle
29
+ */
30
+ export const statsCounterSpecificSchema = z.object({
31
+ // Content: array of stat items
32
+ stats: z.array(statItemSchema)
33
+ .min(1, 'At least one statistic is required')
34
+ .max(8, 'Maximum 8 statistics allowed'),
35
+
36
+ // Design: visual appearance
37
+ columns: z.enum(['2', '3', '4']).default('4'),
38
+ variant: z.enum(['default', 'cards', 'minimal']).default('default'),
39
+ size: z.enum(['sm', 'md', 'lg']).default('md'),
40
+ })
41
+
42
+ /**
43
+ * Complete Stats Counter Block Schema
44
+ */
45
+ export const schema = baseBlockSchema.merge(statsCounterSpecificSchema)
46
+
47
+ export type StatsCounterBlockProps = z.infer<typeof schema>
@@ -0,0 +1,114 @@
1
+ import React from 'react'
2
+ import { Quote } from 'lucide-react'
3
+ import { Avatar, AvatarFallback, AvatarImage } from '@nextsparkjs/core/components/ui/avatar'
4
+ import { cn } from '@nextsparkjs/core/lib/utils'
5
+ import { buildSectionClasses } from '@nextsparkjs/core/types/blocks'
6
+ import { sel } from '../../lib/selectors'
7
+ import type { TestimonialsBlockProps, TestimonialItem } from './schema'
8
+
9
+ /**
10
+ * Testimonials Block Component
11
+ *
12
+ * Props from 3-tab structure:
13
+ * - Content: title, content, cta, items
14
+ * - Design: backgroundColor, columns
15
+ * - Advanced: className, id
16
+ */
17
+ export function TestimonialsBlock({
18
+ // Base content props
19
+ title,
20
+ content,
21
+ cta,
22
+ // Testimonials-specific content
23
+ items,
24
+ // Base design props
25
+ backgroundColor = 'gray-50',
26
+ // Testimonials-specific design
27
+ columns = '3',
28
+ // Base advanced props
29
+ className,
30
+ id,
31
+ }: TestimonialsBlockProps) {
32
+ // Build column classes based on columns prop
33
+ const columnClasses: Record<string, string> = {
34
+ '2': 'md:grid-cols-2',
35
+ '3': 'md:grid-cols-2 lg:grid-cols-3',
36
+ }
37
+
38
+ // Build section classes with background and custom className
39
+ const sectionClasses = buildSectionClasses(
40
+ 'py-16 px-4 md:py-24',
41
+ { backgroundColor, className }
42
+ )
43
+
44
+ // Ensure items is always an array
45
+ const safeItems = Array.isArray(items) ? items : []
46
+
47
+ return (
48
+ <section id={id} className={sectionClasses} data-cy={sel('blocks.testimonials.container')}>
49
+ <div className="container mx-auto max-w-6xl">
50
+ {/* Section Header */}
51
+ {(title || content) && (
52
+ <div className="mb-12 text-center">
53
+ {title && (
54
+ <h2 className="mb-4 text-4xl font-bold md:text-5xl">
55
+ {title}
56
+ </h2>
57
+ )}
58
+ {content && (
59
+ <p className="mx-auto max-w-2xl text-lg text-muted-foreground">
60
+ {content}
61
+ </p>
62
+ )}
63
+ </div>
64
+ )}
65
+
66
+ {/* Testimonials Grid */}
67
+ <div className={cn('grid gap-8', columnClasses[columns] || columnClasses['3'])}>
68
+ {safeItems.map((item: TestimonialItem, index: number) => (
69
+ <div
70
+ key={index}
71
+ className="flex flex-col p-6 rounded-lg border bg-card"
72
+ >
73
+ <Quote className="h-8 w-8 text-primary mb-4" />
74
+
75
+ <blockquote className="mb-6 text-lg flex-grow">
76
+ "{item.quote}"
77
+ </blockquote>
78
+
79
+ <div className="flex items-center gap-3">
80
+ <Avatar>
81
+ <AvatarImage src={item.avatar} alt={item.author} />
82
+ <AvatarFallback>
83
+ {item.author.split(' ').map((n: string) => n[0]).join('')}
84
+ </AvatarFallback>
85
+ </Avatar>
86
+
87
+ <div>
88
+ <div className="font-semibold">{item.author}</div>
89
+ {item.role && (
90
+ <div className="text-sm text-muted-foreground">{item.role}</div>
91
+ )}
92
+ </div>
93
+ </div>
94
+ </div>
95
+ ))}
96
+ </div>
97
+
98
+ {/* Optional CTA */}
99
+ {cta && (
100
+ <div className="mt-12 text-center">
101
+ <a
102
+ href={cta.link}
103
+ target={cta.target}
104
+ rel={cta.target === '_blank' ? 'noopener noreferrer' : undefined}
105
+ 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"
106
+ >
107
+ {cta.text}
108
+ </a>
109
+ </div>
110
+ )}
111
+ </div>
112
+ </section>
113
+ )
114
+ }
@@ -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: 'testimonials',
5
+ name: 'Testimonials',
6
+ description: 'Display customer testimonials with quotes, authors, and avatars',
7
+ category: 'testimonials',
8
+ icon: 'Quote',
9
+ thumbnail: '/theme/blocks/testimonials/thumbnail.png',
10
+ scope: ['pages']
11
+ }
@@ -0,0 +1,65 @@
1
+ import type { BlockExample } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const examples: BlockExample[] = [
4
+ {
5
+ name: 'Grid',
6
+ description: 'Testimonials in grid layout',
7
+ props: {
8
+ title: 'What Our Customers Say',
9
+ content: 'Hear from teams who transformed their workflow',
10
+ backgroundColor: 'white',
11
+ layout: 'grid',
12
+ showImages: true,
13
+ testimonials: [
14
+ {
15
+ quote: 'This platform completely changed how we work. The automation features alone save us 10+ hours per week.',
16
+ author: 'Sarah Johnson',
17
+ role: 'VP of Operations',
18
+ company: 'TechCorp',
19
+ image: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400',
20
+ },
21
+ {
22
+ quote: 'Best investment we made this year. The ROI was clear within the first month of use.',
23
+ author: 'Michael Chen',
24
+ role: 'CTO',
25
+ company: 'StartupXYZ',
26
+ image: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400',
27
+ },
28
+ {
29
+ quote: 'The support team is incredible. They helped us migrate all our data seamlessly.',
30
+ author: 'Emily Rodriguez',
31
+ role: 'Product Manager',
32
+ company: 'InnovateLabs',
33
+ image: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400',
34
+ },
35
+ ],
36
+ },
37
+ },
38
+ {
39
+ name: 'Carousel',
40
+ description: 'Testimonials in carousel format',
41
+ props: {
42
+ title: 'Customer Success Stories',
43
+ backgroundColor: 'gray-50',
44
+ layout: 'carousel',
45
+ showImages: true,
46
+ autoplay: true,
47
+ testimonials: [
48
+ {
49
+ quote: 'We tried several platforms before finding this one. It is exactly what we needed - powerful yet simple to use.',
50
+ author: 'David Park',
51
+ role: 'CEO',
52
+ company: 'GrowthCo',
53
+ image: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=400',
54
+ },
55
+ {
56
+ quote: 'The analytics dashboard gives us insights we never had before. Game changer for our team.',
57
+ author: 'Lisa Thompson',
58
+ role: 'Marketing Director',
59
+ company: 'BrandBuilder',
60
+ image: 'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?w=400',
61
+ },
62
+ ],
63
+ },
64
+ },
65
+ ]
@@ -0,0 +1,105 @@
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
+ * Testimonials Block Field Definitions
10
+ *
11
+ * Organized into 3 tabs:
12
+ * - Content: title, description, cta (from base) + items array
13
+ * - Design: backgroundColor (from base) + columns
14
+ * - Advanced: className, id (from base)
15
+ */
16
+
17
+ // Testimonials-specific content fields
18
+ const testimonialsContentFields: FieldDefinition[] = [
19
+ {
20
+ name: 'items',
21
+ label: 'Testimonials',
22
+ type: 'array',
23
+ tab: 'content',
24
+ required: true,
25
+ description: 'Customer testimonials to display',
26
+ helpText: 'Add up to 6 testimonials',
27
+ minItems: 1,
28
+ maxItems: 6,
29
+ itemFields: [
30
+ {
31
+ name: 'quote',
32
+ label: 'Quote',
33
+ type: 'textarea',
34
+ tab: 'content',
35
+ required: true,
36
+ placeholder: 'This product changed my life...',
37
+ maxLength: 500,
38
+ rows: 3,
39
+ },
40
+ {
41
+ name: 'author',
42
+ label: 'Author Name',
43
+ type: 'text',
44
+ tab: 'content',
45
+ required: true,
46
+ placeholder: 'John Doe',
47
+ maxLength: 100,
48
+ },
49
+ {
50
+ name: 'role',
51
+ label: 'Role/Title',
52
+ type: 'text',
53
+ tab: 'content',
54
+ required: false,
55
+ placeholder: 'CEO at Company',
56
+ maxLength: 100,
57
+ },
58
+ {
59
+ name: 'avatar',
60
+ label: 'Avatar Image',
61
+ type: 'image',
62
+ tab: 'content',
63
+ required: false,
64
+ description: 'Profile picture of the person',
65
+ helpText: 'Recommended size: 100x100px',
66
+ },
67
+ ],
68
+ },
69
+ ]
70
+
71
+ // Testimonials-specific design fields
72
+ const testimonialsDesignFields: FieldDefinition[] = [
73
+ {
74
+ name: 'columns',
75
+ label: 'Grid Columns',
76
+ type: 'select',
77
+ tab: 'design',
78
+ required: false,
79
+ default: '3',
80
+ description: 'Number of columns in the grid layout',
81
+ options: [
82
+ { label: '2 Columns', value: '2' },
83
+ { label: '3 Columns', value: '3' },
84
+ ],
85
+ },
86
+ ]
87
+
88
+ /**
89
+ * Complete field definitions organized by tab
90
+ */
91
+ export const fieldDefinitions: FieldDefinition[] = [
92
+ // Content tab: base fields + testimonials-specific
93
+ ...baseContentFields,
94
+ ...testimonialsContentFields,
95
+
96
+ // Design tab: base fields + testimonials-specific
97
+ ...baseDesignFields,
98
+ ...testimonialsDesignFields,
99
+
100
+ // Advanced tab: base fields only
101
+ ...baseAdvancedFields,
102
+ ]
103
+
104
+ // Alias for compatibility
105
+ 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 { TestimonialsBlock as Component } from './component'
5
+
6
+ export type { TestimonialsBlockProps } from './schema'
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod'
2
+ import { baseBlockSchema } from '@nextsparkjs/core/types/blocks'
3
+
4
+ /**
5
+ * Testimonial Item Schema
6
+ * Individual testimonial entry
7
+ */
8
+ const testimonialItemSchema = z.object({
9
+ quote: z.string().min(1, 'Quote is required').max(500),
10
+ author: z.string().min(1, 'Author name is required').max(100),
11
+ role: z.string().max(100).optional(),
12
+ avatar: z.string().url('Must be a valid URL').optional(),
13
+ })
14
+
15
+ export type TestimonialItem = z.infer<typeof testimonialItemSchema>
16
+
17
+ /**
18
+ * Testimonials Block Schema
19
+ *
20
+ * Extends base schema with:
21
+ * - items: Array of testimonial items
22
+ * - columns: Grid layout option (2, 3 columns)
23
+ *
24
+ * Note: Uses base schema title, description, cta, backgroundColor, className, id
25
+ */
26
+ export const testimonialsSpecificSchema = z.object({
27
+ // Content: array of testimonials
28
+ items: z.array(testimonialItemSchema)
29
+ .min(1, 'At least one testimonial is required')
30
+ .max(6, 'Maximum 6 testimonials allowed'),
31
+
32
+ // Design: column layout
33
+ columns: z.enum(['2', '3']).default('3'),
34
+ })
35
+
36
+ /**
37
+ * Complete Testimonials Block Schema
38
+ */
39
+ export const schema = baseBlockSchema.merge(testimonialsSpecificSchema)
40
+
41
+ export type TestimonialsBlockProps = z.infer<typeof schema>
@@ -0,0 +1 @@
1
+ Placeholder