@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,165 @@
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
+ * Post Content Block Field Definitions
10
+ *
11
+ * Organized into 3 tabs:
12
+ * - Content: title, cta (from base) + content (rich-text, replaces base content)
13
+ * - Design: backgroundColor (from base) + editorial typography options
14
+ * - Advanced: className, id (from base)
15
+ *
16
+ * Note: The `content` field is overridden with a rich-text version for editorial content
17
+ */
18
+
19
+ // Filter out base content field (we'll replace it with rich-text version)
20
+ const baseContentFieldsWithoutContent = baseContentFields.filter(
21
+ (field) => field.name !== 'content'
22
+ )
23
+
24
+ // Post-content-specific content fields (rich-text content)
25
+ const postContentFields: FieldDefinition[] = [
26
+ {
27
+ name: 'content',
28
+ label: 'Article Content',
29
+ type: 'rich-text',
30
+ tab: 'content',
31
+ required: true,
32
+ placeholder: 'Write your article content here...',
33
+ helpText: 'Main article body with rich text formatting support',
34
+ },
35
+ ]
36
+
37
+ // Post-content-specific design fields (editorial styling)
38
+ const postDesignFields: FieldDefinition[] = [
39
+ // Drop cap section
40
+ {
41
+ name: 'showDropCap',
42
+ label: 'Show Drop Cap',
43
+ type: 'checkbox',
44
+ tab: 'design',
45
+ required: false,
46
+ default: false,
47
+ helpText: 'Display a decorative large first letter',
48
+ },
49
+ {
50
+ name: 'dropCapStyle',
51
+ label: 'Drop Cap Style',
52
+ type: 'select',
53
+ tab: 'design',
54
+ required: false,
55
+ default: 'serif',
56
+ helpText: 'Visual style for the drop cap',
57
+ options: [
58
+ { label: 'Serif (Classic)', value: 'serif' },
59
+ { label: 'Sans-Serif (Modern)', value: 'sans-serif' },
60
+ { label: 'Decorative', value: 'decorative' },
61
+ ],
62
+ },
63
+
64
+ // Typography section
65
+ {
66
+ name: 'maxWidth',
67
+ label: 'Reading Width',
68
+ type: 'select',
69
+ tab: 'design',
70
+ required: false,
71
+ default: 'narrow',
72
+ helpText: 'Optimal reading width for long-form content',
73
+ options: [
74
+ { label: 'Narrow (680px) - Optimal for reading', value: 'narrow' },
75
+ { label: 'Medium (768px)', value: 'medium' },
76
+ { label: 'Wide (900px)', value: 'wide' },
77
+ ],
78
+ },
79
+ {
80
+ name: 'fontSize',
81
+ label: 'Base Font Size',
82
+ type: 'select',
83
+ tab: 'design',
84
+ required: false,
85
+ default: 'medium',
86
+ helpText: 'Base font size for article text',
87
+ options: [
88
+ { label: 'Small (16px)', value: 'small' },
89
+ { label: 'Medium (18px) - Recommended', value: 'medium' },
90
+ { label: 'Large (20px)', value: 'large' },
91
+ ],
92
+ },
93
+ {
94
+ name: 'lineHeight',
95
+ label: 'Line Spacing',
96
+ type: 'select',
97
+ tab: 'design',
98
+ required: false,
99
+ default: 'relaxed',
100
+ helpText: 'Vertical spacing between lines',
101
+ options: [
102
+ { label: 'Compact (1.6)', value: 'compact' },
103
+ { label: 'Normal (1.7)', value: 'normal' },
104
+ { label: 'Relaxed (1.8) - Recommended', value: 'relaxed' },
105
+ ],
106
+ },
107
+ {
108
+ name: 'paragraphSpacing',
109
+ label: 'Paragraph Spacing',
110
+ type: 'select',
111
+ tab: 'design',
112
+ required: false,
113
+ default: 'normal',
114
+ helpText: 'Vertical spacing between paragraphs',
115
+ options: [
116
+ { label: 'Tight', value: 'tight' },
117
+ { label: 'Normal', value: 'normal' },
118
+ { label: 'Loose', value: 'loose' },
119
+ ],
120
+ },
121
+
122
+ // Dividers section
123
+ {
124
+ name: 'showDividers',
125
+ label: 'Show Section Dividers',
126
+ type: 'checkbox',
127
+ tab: 'design',
128
+ required: false,
129
+ default: false,
130
+ helpText: 'Display subtle dividers between content sections',
131
+ },
132
+ {
133
+ name: 'dividerStyle',
134
+ label: 'Divider Style',
135
+ type: 'select',
136
+ tab: 'design',
137
+ required: false,
138
+ default: 'line',
139
+ helpText: 'Visual style for section dividers',
140
+ options: [
141
+ { label: 'Line', value: 'line' },
142
+ { label: 'Dots (•••)', value: 'dots' },
143
+ { label: 'Asterisks (***)', value: 'asterisks' },
144
+ ],
145
+ },
146
+ ]
147
+
148
+ /**
149
+ * Complete field definitions organized by tab
150
+ */
151
+ export const fieldDefinitions: FieldDefinition[] = [
152
+ // Content tab: base fields (without content) + rich-text content
153
+ ...baseContentFieldsWithoutContent,
154
+ ...postContentFields,
155
+
156
+ // Design tab: base fields + editorial-specific
157
+ ...baseDesignFields,
158
+ ...postDesignFields,
159
+
160
+ // Advanced tab: base fields only (ALWAYS last)
161
+ ...baseAdvancedFields,
162
+ ]
163
+
164
+ // Alias for compatibility
165
+ export const fields = fieldDefinitions
@@ -0,0 +1,4 @@
1
+ export { config } from './config'
2
+ export { fieldDefinitions, fields } from './fields'
3
+ export { schema, type PostContentBlockProps } from './schema'
4
+ export { PostContentBlock } from './component'
@@ -0,0 +1,46 @@
1
+ import { z } from 'zod'
2
+ import { baseBlockSchema } from '@nextsparkjs/core/types/blocks'
3
+
4
+ /**
5
+ * Post Content Block Schema
6
+ *
7
+ * Extends base schema with editorial-focused fields:
8
+ * - content: Main article content (overrides base content with required)
9
+ * - showDropCap: Display decorative drop cap on first letter
10
+ * - dropCapStyle: Style variant for the drop cap
11
+ * - maxWidth: Reading width control for optimal typography
12
+ * - fontSize: Base font size for content
13
+ * - lineHeight: Line spacing for readability
14
+ * - paragraphSpacing: Vertical spacing between paragraphs
15
+ * - showDividers: Show subtle section dividers
16
+ * - dividerStyle: Visual style for dividers
17
+ *
18
+ * Note: Uses base schema title, cta, backgroundColor, className, id
19
+ * The `content` field is overridden to be required and serves as the main article body
20
+ */
21
+ export const postContentSpecificSchema = z.object({
22
+ // Content: rich text body (overrides base optional content)
23
+ content: z.string().min(1, 'Content is required'),
24
+
25
+ // Design: drop cap styling
26
+ showDropCap: z.boolean().default(false),
27
+ dropCapStyle: z.enum(['serif', 'sans-serif', 'decorative']).default('serif'),
28
+
29
+ // Design: layout and typography
30
+ maxWidth: z.enum(['narrow', 'medium', 'wide']).default('narrow'),
31
+ fontSize: z.enum(['small', 'medium', 'large']).default('medium'),
32
+ lineHeight: z.enum(['compact', 'normal', 'relaxed']).default('relaxed'),
33
+ paragraphSpacing: z.enum(['tight', 'normal', 'loose']).default('normal'),
34
+
35
+ // Design: section dividers
36
+ showDividers: z.boolean().default(false),
37
+ dividerStyle: z.enum(['line', 'dots', 'asterisks']).default('line'),
38
+ })
39
+
40
+ /**
41
+ * Complete Post Content Block Schema
42
+ * Note: postContentSpecificSchema.content overrides baseBlockSchema.content
43
+ */
44
+ export const schema = baseBlockSchema.merge(postContentSpecificSchema)
45
+
46
+ export type PostContentBlockProps = z.infer<typeof schema>
@@ -0,0 +1,154 @@
1
+ import React from 'react'
2
+ import { Button } from '@nextsparkjs/core/components/ui/button'
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@nextsparkjs/core/components/ui/card'
4
+ import { Check } from 'lucide-react'
5
+ import { cn } from '@nextsparkjs/core/lib/utils'
6
+ import { buildSectionClasses } from '@nextsparkjs/core/types/blocks'
7
+ import { sel } from '../../lib/selectors'
8
+ import type { PricingTableBlockProps, PlanItem } from './schema'
9
+
10
+ /**
11
+ * Pricing Table Block Component
12
+ *
13
+ * Props from 3-tab structure:
14
+ * - Content: title, content, plans
15
+ * - Design: backgroundColor, columns, highlightPopular
16
+ * - Advanced: className, id
17
+ */
18
+ export function PricingTableBlock({
19
+ // Base content props
20
+ title,
21
+ content,
22
+ // Pricing-specific content
23
+ plans,
24
+ // Base design props
25
+ backgroundColor,
26
+ // Pricing-specific design
27
+ columns = '3',
28
+ highlightPopular = true,
29
+ // Base advanced props
30
+ className,
31
+ id,
32
+ }: PricingTableBlockProps) {
33
+ // Parse features from newline-separated string
34
+ const parseFeatures = (features?: string): string[] => {
35
+ if (!features) return []
36
+ return features.split('\n').map(f => f.trim()).filter(Boolean)
37
+ }
38
+
39
+ // Build column classes based on columns prop
40
+ const columnClasses: Record<string, string> = {
41
+ '2': 'sm:grid-cols-2',
42
+ '3': 'sm:grid-cols-2 lg:grid-cols-3',
43
+ '4': 'sm:grid-cols-2 lg:grid-cols-4',
44
+ }
45
+
46
+ // Build section classes with background and custom className
47
+ const sectionClasses = buildSectionClasses(
48
+ 'py-16 px-4 md:py-24',
49
+ { backgroundColor, className }
50
+ )
51
+
52
+ // Safe plans array (fallback to empty array)
53
+ const safePlans = Array.isArray(plans) ? plans : []
54
+
55
+ return (
56
+ <section id={id} className={sectionClasses} data-cy={sel('blocks.pricingTable.container')}>
57
+ <div className="container mx-auto max-w-7xl">
58
+ {/* Section Header */}
59
+ {(title || content) && (
60
+ <div className="mb-12 text-center">
61
+ {title && (
62
+ <h2 className="mb-4 text-4xl font-bold md:text-5xl">
63
+ {title}
64
+ </h2>
65
+ )}
66
+ {content && (
67
+ <p className="mx-auto max-w-2xl text-lg text-muted-foreground">
68
+ {content}
69
+ </p>
70
+ )}
71
+ </div>
72
+ )}
73
+
74
+ {/* Pricing Plans Grid */}
75
+ <div className={cn('grid gap-8', columnClasses[columns] || columnClasses['3'])}>
76
+ {safePlans.map((plan: PlanItem, index: number) => {
77
+ const features = parseFeatures(plan.features)
78
+ const isHighlighted = highlightPopular && plan.isPopular
79
+
80
+ return (
81
+ <Card
82
+ key={index}
83
+ className={cn(
84
+ 'relative flex flex-col',
85
+ isHighlighted && 'border-primary shadow-lg scale-105',
86
+ plan.isDisabled && 'opacity-60'
87
+ )}
88
+ data-cy={sel('blocks.pricingTable.plan', { index: String(index) })}
89
+ >
90
+ {/* Popular Badge */}
91
+ {isHighlighted && (
92
+ <div className="absolute -top-3 left-1/2 -translate-x-1/2">
93
+ <span className="bg-primary text-primary-foreground text-xs font-semibold px-3 py-1 rounded-full">
94
+ Popular
95
+ </span>
96
+ </div>
97
+ )}
98
+
99
+ {/* Card Header */}
100
+ <CardHeader className="text-center pb-8">
101
+ <CardTitle className="text-2xl mb-2">{plan.name}</CardTitle>
102
+ <div className="flex items-baseline justify-center gap-1">
103
+ <span className="text-4xl font-bold">{plan.price}</span>
104
+ {plan.period && (
105
+ <span className="text-muted-foreground">{plan.period}</span>
106
+ )}
107
+ </div>
108
+ {plan.description && (
109
+ <CardDescription className="mt-2">{plan.description}</CardDescription>
110
+ )}
111
+ </CardHeader>
112
+
113
+ {/* Card Content */}
114
+ <CardContent className="flex-1 flex flex-col">
115
+ {/* Features List */}
116
+ {features.length > 0 && (
117
+ <ul className="space-y-3 mb-6 flex-1" data-cy={sel('blocks.pricingTable.features')}>
118
+ {features.map((feature: string, i: number) => (
119
+ <li key={i} className="flex items-start gap-2">
120
+ <Check className="h-5 w-5 text-primary shrink-0 mt-0.5" />
121
+ <span className="text-sm text-muted-foreground">{feature}</span>
122
+ </li>
123
+ ))}
124
+ </ul>
125
+ )}
126
+
127
+ {/* CTA Button */}
128
+ {plan.ctaText && plan.ctaUrl && (
129
+ <Button
130
+ asChild
131
+ className="w-full"
132
+ variant={isHighlighted ? 'default' : 'outline'}
133
+ disabled={plan.isDisabled}
134
+ data-cy={sel('blocks.pricingTable.cta', { index: String(index) })}
135
+ >
136
+ <a href={plan.ctaUrl}>{plan.ctaText}</a>
137
+ </Button>
138
+ )}
139
+
140
+ {/* Disabled State Message */}
141
+ {plan.isDisabled && !plan.ctaText && (
142
+ <div className="text-center text-sm text-muted-foreground">
143
+ Coming Soon
144
+ </div>
145
+ )}
146
+ </CardContent>
147
+ </Card>
148
+ )
149
+ })}
150
+ </div>
151
+ </div>
152
+ </section>
153
+ )
154
+ }
@@ -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: 'pricing-table',
5
+ name: 'Pricing Table',
6
+ description: 'A pricing comparison table showing different plans with features list, price, CTA button, and optional "Popular" badge',
7
+ category: 'pricing',
8
+ icon: 'DollarSign',
9
+ thumbnail: '/theme/blocks/pricing-table/thumbnail.png',
10
+ scope: ['pages']
11
+ }
@@ -0,0 +1,96 @@
1
+ import type { BlockExample } from '@nextsparkjs/core/types/blocks'
2
+
3
+ export const examples: BlockExample[] = [
4
+ {
5
+ name: 'Standard',
6
+ description: 'Three-tier pricing without highlight',
7
+ props: {
8
+ title: 'Simple, Transparent Pricing',
9
+ content: 'Choose the plan that fits your needs. All plans include 14-day free trial.',
10
+ backgroundColor: 'white',
11
+ columns: '3',
12
+ highlightPopular: false,
13
+ plans: [
14
+ {
15
+ name: 'Starter',
16
+ price: '$29',
17
+ period: 'per month',
18
+ description: 'Perfect for small teams',
19
+ features: 'Up to 5 team members\n10GB storage\nEmail support\nBasic analytics',
20
+ ctaText: 'Start Free Trial',
21
+ ctaUrl: '/signup?plan=starter',
22
+ isPopular: false,
23
+ isDisabled: false,
24
+ },
25
+ {
26
+ name: 'Professional',
27
+ price: '$99',
28
+ period: 'per month',
29
+ description: 'For growing businesses',
30
+ features: 'Up to 25 team members\n100GB storage\nPriority support\nAdvanced analytics\nCustom integrations',
31
+ ctaText: 'Start Free Trial',
32
+ ctaUrl: '/signup?plan=pro',
33
+ isPopular: false,
34
+ isDisabled: false,
35
+ },
36
+ {
37
+ name: 'Enterprise',
38
+ price: 'Custom',
39
+ period: '',
40
+ description: 'For large organizations',
41
+ features: 'Unlimited team members\nUnlimited storage\n24/7 dedicated support\nCustom analytics\nAPI access\nSSO & SAML',
42
+ ctaText: 'Contact Sales',
43
+ ctaUrl: '/contact',
44
+ isPopular: false,
45
+ isDisabled: false,
46
+ },
47
+ ],
48
+ },
49
+ },
50
+ {
51
+ name: 'With Highlight',
52
+ description: 'Pricing with highlighted popular plan',
53
+ props: {
54
+ title: 'Pricing That Grows With You',
55
+ content: 'Start free, upgrade when you need more',
56
+ backgroundColor: 'gray-50',
57
+ columns: '3',
58
+ highlightPopular: true,
59
+ plans: [
60
+ {
61
+ name: 'Basic',
62
+ price: '$0',
63
+ period: 'forever free',
64
+ description: 'Get started at no cost',
65
+ features: 'Up to 3 team members\n5GB storage\nCommunity support\nBasic features',
66
+ ctaText: 'Get Started',
67
+ ctaUrl: '/signup?plan=basic',
68
+ isPopular: false,
69
+ isDisabled: false,
70
+ },
71
+ {
72
+ name: 'Pro',
73
+ price: '$49',
74
+ period: 'per month',
75
+ description: 'Most popular choice',
76
+ features: 'Up to 15 team members\n50GB storage\nPriority support\nAll features\nAdvanced analytics\nIntegrations',
77
+ ctaText: 'Start Free Trial',
78
+ ctaUrl: '/signup?plan=pro',
79
+ isPopular: true,
80
+ isDisabled: false,
81
+ },
82
+ {
83
+ name: 'Business',
84
+ price: '$199',
85
+ period: 'per month',
86
+ description: 'For serious teams',
87
+ features: 'Unlimited team members\n500GB storage\n24/7 support\nAll Pro features\nCustom workflows\nDedicated manager',
88
+ ctaText: 'Start Free Trial',
89
+ ctaUrl: '/signup?plan=business',
90
+ isPopular: false,
91
+ isDisabled: false,
92
+ },
93
+ ],
94
+ },
95
+ },
96
+ ]
@@ -0,0 +1,161 @@
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
+ * Pricing Table Block Field Definitions
10
+ *
11
+ * Organized into 3 tabs:
12
+ * - Content: title, content (from base) + plans array
13
+ * - Design: backgroundColor (from base) + columns + highlightPopular
14
+ * - Advanced: className, id (from base)
15
+ */
16
+
17
+ // Pricing-specific content fields
18
+ const pricingContentFields: FieldDefinition[] = [
19
+ {
20
+ name: 'plans',
21
+ label: 'Pricing Plans',
22
+ type: 'array',
23
+ tab: 'content',
24
+ required: true,
25
+ description: 'List of pricing plans to display',
26
+ helpText: 'Add up to 4 pricing plans with features and CTA',
27
+ minItems: 1,
28
+ maxItems: 4,
29
+ itemFields: [
30
+ {
31
+ name: 'name',
32
+ label: 'Plan Name',
33
+ type: 'text',
34
+ tab: 'content',
35
+ required: true,
36
+ placeholder: 'Starter',
37
+ maxLength: 50,
38
+ },
39
+ {
40
+ name: 'price',
41
+ label: 'Price',
42
+ type: 'text',
43
+ tab: 'content',
44
+ required: true,
45
+ placeholder: '$29',
46
+ maxLength: 50,
47
+ helpText: 'Price display (e.g., "$29", "Free", "$99")',
48
+ },
49
+ {
50
+ name: 'period',
51
+ label: 'Billing Period',
52
+ type: 'text',
53
+ tab: 'content',
54
+ required: false,
55
+ placeholder: '/month',
56
+ maxLength: 50,
57
+ helpText: 'Billing period (e.g., "/month", "/year", "one-time")',
58
+ },
59
+ {
60
+ name: 'description',
61
+ label: 'Plan Description',
62
+ type: 'text',
63
+ tab: 'content',
64
+ required: false,
65
+ placeholder: 'Perfect for getting started',
66
+ maxLength: 200,
67
+ },
68
+ {
69
+ name: 'features',
70
+ label: 'Features (one per line)',
71
+ type: 'textarea',
72
+ tab: 'content',
73
+ required: false,
74
+ placeholder: 'Unlimited projects\n24/7 support\nAPI access',
75
+ rows: 4,
76
+ helpText: 'Enter each feature on a new line',
77
+ },
78
+ {
79
+ name: 'ctaText',
80
+ label: 'Button Text',
81
+ type: 'text',
82
+ tab: 'content',
83
+ required: false,
84
+ placeholder: 'Get Started',
85
+ maxLength: 50,
86
+ },
87
+ {
88
+ name: 'ctaUrl',
89
+ label: 'Button Link',
90
+ type: 'url',
91
+ tab: 'content',
92
+ required: false,
93
+ placeholder: '/signup',
94
+ },
95
+ {
96
+ name: 'isPopular',
97
+ label: 'Mark as "Popular"',
98
+ type: 'checkbox',
99
+ tab: 'content',
100
+ required: false,
101
+ default: false,
102
+ helpText: 'Show "Popular" badge on this plan',
103
+ },
104
+ {
105
+ name: 'isDisabled',
106
+ label: 'Disable this plan',
107
+ type: 'checkbox',
108
+ tab: 'content',
109
+ required: false,
110
+ default: false,
111
+ helpText: 'Gray out this plan (coming soon, unavailable)',
112
+ },
113
+ ],
114
+ },
115
+ ]
116
+
117
+ // Pricing-specific design fields
118
+ const pricingDesignFields: FieldDefinition[] = [
119
+ {
120
+ name: 'columns',
121
+ label: 'Grid Columns',
122
+ type: 'select',
123
+ tab: 'design',
124
+ required: false,
125
+ default: '3',
126
+ description: 'Number of columns in the pricing table',
127
+ options: [
128
+ { label: '2 Columns', value: '2' },
129
+ { label: '3 Columns', value: '3' },
130
+ { label: '4 Columns', value: '4' },
131
+ ],
132
+ },
133
+ {
134
+ name: 'highlightPopular',
135
+ label: 'Highlight Popular Plan',
136
+ type: 'checkbox',
137
+ tab: 'design',
138
+ required: false,
139
+ default: true,
140
+ description: 'Add border and shadow to popular plan',
141
+ },
142
+ ]
143
+
144
+ /**
145
+ * Complete field definitions organized by tab
146
+ */
147
+ export const fieldDefinitions: FieldDefinition[] = [
148
+ // Content tab: base fields + pricing-specific
149
+ ...baseContentFields,
150
+ ...pricingContentFields,
151
+
152
+ // Design tab: base fields + pricing-specific
153
+ ...baseDesignFields,
154
+ ...pricingDesignFields,
155
+
156
+ // Advanced tab: base fields only
157
+ ...baseAdvancedFields,
158
+ ]
159
+
160
+ // Alias for compatibility
161
+ export const fields = fieldDefinitions
@@ -0,0 +1,4 @@
1
+ export { config } from './config'
2
+ export { fieldDefinitions, fields } from './fields'
3
+ export { schema, type PricingTableBlockProps, type PlanItem } from './schema'
4
+ export { PricingTableBlock } from './component'