@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.
- package/about/business.md +49 -0
- package/about/features.json +302 -0
- package/about/team.md +79 -0
- package/api/ai/chat/stream/route.ts +212 -0
- package/api/ai/orchestrator/route.ts +226 -0
- package/api/ai/single-agent/route.ts +291 -0
- package/api/ai/usage/route.ts +122 -0
- package/blocks/benefits/component.tsx +100 -0
- package/blocks/benefits/config.ts +11 -0
- package/blocks/benefits/examples.ts +85 -0
- package/blocks/benefits/fields.ts +156 -0
- package/blocks/benefits/schema.ts +33 -0
- package/blocks/cta-section/component.tsx +100 -0
- package/blocks/cta-section/config.ts +11 -0
- package/blocks/cta-section/examples.ts +41 -0
- package/blocks/cta-section/fields.ts +89 -0
- package/blocks/cta-section/index.ts +6 -0
- package/blocks/cta-section/schema.ts +32 -0
- package/blocks/cta-section/thumbnail.png +1 -0
- package/blocks/faq-accordion/component.tsx +156 -0
- package/blocks/faq-accordion/config.ts +11 -0
- package/blocks/faq-accordion/examples.ts +77 -0
- package/blocks/faq-accordion/fields.ts +119 -0
- package/blocks/faq-accordion/index.ts +6 -0
- package/blocks/faq-accordion/schema.ts +45 -0
- package/blocks/features-grid/component.tsx +112 -0
- package/blocks/features-grid/config.ts +11 -0
- package/blocks/features-grid/examples.ts +63 -0
- package/blocks/features-grid/fields.ts +97 -0
- package/blocks/features-grid/index.ts +6 -0
- package/blocks/features-grid/schema.ts +40 -0
- package/blocks/features-grid/thumbnail.png +1 -0
- package/blocks/hero/component.tsx +100 -0
- package/blocks/hero/config.ts +11 -0
- package/blocks/hero/examples.ts +35 -0
- package/blocks/hero/fields.ts +60 -0
- package/blocks/hero/index.ts +6 -0
- package/blocks/hero/schema.ts +32 -0
- package/blocks/hero/thumbnail.png +1 -0
- package/blocks/hero/thumbnail.png.txt +6 -0
- package/blocks/hero-with-form/component.tsx +232 -0
- package/blocks/hero-with-form/config.ts +11 -0
- package/blocks/hero-with-form/examples.ts +16 -0
- package/blocks/hero-with-form/fields.ts +207 -0
- package/blocks/hero-with-form/index.ts +6 -0
- package/blocks/hero-with-form/schema.ts +54 -0
- package/blocks/jumbotron/component.tsx +136 -0
- package/blocks/jumbotron/config.ts +11 -0
- package/blocks/jumbotron/examples.ts +36 -0
- package/blocks/jumbotron/fields.ts +202 -0
- package/blocks/jumbotron/index.ts +6 -0
- package/blocks/jumbotron/schema.ts +55 -0
- package/blocks/logo-cloud/component.tsx +154 -0
- package/blocks/logo-cloud/config.ts +11 -0
- package/blocks/logo-cloud/examples.ts +34 -0
- package/blocks/logo-cloud/fields.ts +133 -0
- package/blocks/logo-cloud/index.ts +6 -0
- package/blocks/logo-cloud/schema.ts +46 -0
- package/blocks/post-content/component.tsx +197 -0
- package/blocks/post-content/config.ts +11 -0
- package/blocks/post-content/examples.ts +33 -0
- package/blocks/post-content/fields.ts +165 -0
- package/blocks/post-content/index.ts +4 -0
- package/blocks/post-content/schema.ts +46 -0
- package/blocks/pricing-table/component.tsx +154 -0
- package/blocks/pricing-table/config.ts +11 -0
- package/blocks/pricing-table/examples.ts +96 -0
- package/blocks/pricing-table/fields.ts +161 -0
- package/blocks/pricing-table/index.ts +4 -0
- package/blocks/pricing-table/schema.ts +50 -0
- package/blocks/split-content/component.tsx +135 -0
- package/blocks/split-content/config.ts +11 -0
- package/blocks/split-content/examples.ts +38 -0
- package/blocks/split-content/fields.ts +198 -0
- package/blocks/split-content/index.ts +6 -0
- package/blocks/split-content/schema.ts +67 -0
- package/blocks/stats-counter/component.tsx +124 -0
- package/blocks/stats-counter/config.ts +11 -0
- package/blocks/stats-counter/examples.ts +61 -0
- package/blocks/stats-counter/fields.ts +134 -0
- package/blocks/stats-counter/index.ts +6 -0
- package/blocks/stats-counter/schema.ts +47 -0
- package/blocks/testimonials/component.tsx +114 -0
- package/blocks/testimonials/config.ts +11 -0
- package/blocks/testimonials/examples.ts +65 -0
- package/blocks/testimonials/fields.ts +105 -0
- package/blocks/testimonials/index.ts +6 -0
- package/blocks/testimonials/schema.ts +41 -0
- package/blocks/testimonials/thumbnail.png +1 -0
- package/blocks/text-content/component.tsx +97 -0
- package/blocks/text-content/config.ts +11 -0
- package/blocks/text-content/examples.ts +30 -0
- package/blocks/text-content/fields.ts +88 -0
- package/blocks/text-content/index.ts +6 -0
- package/blocks/text-content/schema.ts +30 -0
- package/blocks/text-content/thumbnail.png +1 -0
- package/blocks/timeline/component.tsx +267 -0
- package/blocks/timeline/config.ts +11 -0
- package/blocks/timeline/examples.ts +68 -0
- package/blocks/timeline/fields.ts +147 -0
- package/blocks/timeline/index.ts +6 -0
- package/blocks/timeline/schema.ts +49 -0
- package/blocks/video-hero/component.tsx +270 -0
- package/blocks/video-hero/config.ts +11 -0
- package/blocks/video-hero/examples.ts +24 -0
- package/blocks/video-hero/fields.ts +98 -0
- package/blocks/video-hero/index.ts +6 -0
- package/blocks/video-hero/schema.ts +39 -0
- package/components/ai-chat/ChatPanel.tsx +575 -0
- package/components/ai-chat/ConversationItem.tsx +266 -0
- package/components/ai-chat/ConversationSidebar.tsx +99 -0
- package/components/ai-chat/MarkdownRenderer.tsx +15 -0
- package/components/ai-chat/Message.tsx +42 -0
- package/components/ai-chat/MessageInput.tsx +49 -0
- package/components/ai-chat/MessageList.tsx +46 -0
- package/components/ai-chat/TypingIndicator.tsx +11 -0
- package/config/app.config.ts +367 -0
- package/config/billing.config.ts +349 -0
- package/config/dashboard.config.ts +506 -0
- package/config/dev.config.ts +104 -0
- package/config/features.config.ts +203 -0
- package/config/flows.config.ts +129 -0
- package/config/permissions.config.ts +245 -0
- package/config/theme.config.ts +74 -0
- package/docs/01-overview/01-introduction.md +335 -0
- package/docs/01-overview/02-customization.md +671 -0
- package/docs/02-features/01-components.md +155 -0
- package/docs/02-features/02-styling.md +139 -0
- package/docs/02-features/03-tasks-entity.md +407 -0
- package/docs/03-ai/01-overview.md +211 -0
- package/docs/03-ai/02-customization.md +436 -0
- package/entities/customers/customers.config.ts +75 -0
- package/entities/customers/customers.fields.ts +165 -0
- package/entities/customers/customers.service.ts +516 -0
- package/entities/customers/customers.types.ts +83 -0
- package/entities/customers/messages/en.json +66 -0
- package/entities/customers/messages/es.json +66 -0
- package/entities/customers/migrations/001_customers_table.sql +102 -0
- package/entities/customers/migrations/002_customers_metas.sql +92 -0
- package/entities/pages/messages/en.json +41 -0
- package/entities/pages/messages/es.json +41 -0
- package/entities/pages/migrations/001_pages_table.sql +112 -0
- package/entities/pages/migrations/002_pages_metas.sql +56 -0
- package/entities/pages/migrations/003_add_status.sql +50 -0
- package/entities/pages/pages-management.service.ts +610 -0
- package/entities/pages/pages.config.ts +94 -0
- package/entities/pages/pages.fields.ts +101 -0
- package/entities/pages/pages.service.ts +290 -0
- package/entities/pages/pages.types.ts +124 -0
- package/entities/posts/components/post-header.tsx +97 -0
- package/entities/posts/messages/en.json +55 -0
- package/entities/posts/messages/es.json +55 -0
- package/entities/posts/migrations/001_posts_table.sql +115 -0
- package/entities/posts/migrations/003_add_status.sql +44 -0
- package/entities/posts/migrations/004_entity_taxonomy_relations.sql +129 -0
- package/entities/posts/migrations/006_posts_metas.sql +56 -0
- package/entities/posts/posts.config.ts +101 -0
- package/entities/posts/posts.fields.ts +116 -0
- package/entities/posts/posts.service.ts +376 -0
- package/entities/posts/posts.types.ts +74 -0
- package/entities/tasks/messages/en.json +204 -0
- package/entities/tasks/messages/es.json +204 -0
- package/entities/tasks/migrations/001_tasks_table.sql +105 -0
- package/entities/tasks/migrations/002_task_metas.sql +85 -0
- package/entities/tasks/migrations/sample_data.json +77 -0
- package/entities/tasks/tasks.config.ts +79 -0
- package/entities/tasks/tasks.fields.ts +196 -0
- package/entities/tasks/tasks.service.ts +541 -0
- package/entities/tasks/tasks.types.ts +56 -0
- package/lib/hooks/useAiChat.ts +114 -0
- package/lib/hooks/useConversations.ts +376 -0
- package/lib/hooks/useOrchestratorChat.ts +122 -0
- package/lib/hooks/usePersistentChat.ts +315 -0
- package/lib/hooks/useStreamingChat.ts +127 -0
- package/lib/hooks/useTokenUsage.ts +63 -0
- package/lib/langchain/agents/customer-assistant.md +69 -0
- package/lib/langchain/agents/index.ts +61 -0
- package/lib/langchain/agents/orchestrator.md +59 -0
- package/lib/langchain/agents/page-assistant.md +85 -0
- package/lib/langchain/agents/single-agent.md +46 -0
- package/lib/langchain/agents/task-assistant.md +55 -0
- package/lib/langchain/config.ts +45 -0
- package/lib/langchain/handlers/customer-handler.ts +338 -0
- package/lib/langchain/handlers/page-handler.ts +232 -0
- package/lib/langchain/handlers/task-handler.ts +323 -0
- package/lib/langchain/langchain.config.ts +223 -0
- package/lib/langchain/observability.config.ts +30 -0
- package/lib/langchain/orchestrator.ts +562 -0
- package/lib/langchain/tools/customers.ts +176 -0
- package/lib/langchain/tools/index.ts +10 -0
- package/lib/langchain/tools/orchestrator.ts +92 -0
- package/lib/langchain/tools/pages.ts +289 -0
- package/lib/langchain/tools/tasks.ts +167 -0
- package/lib/scheduled-actions/billing.ts +149 -0
- package/lib/scheduled-actions/index.ts +170 -0
- package/lib/scheduled-actions/webhook.ts +231 -0
- package/lib/selectors.ts +197 -0
- package/messages/de/admin.json +219 -0
- package/messages/de/aiUsage.json +36 -0
- package/messages/de/buttons.json +19 -0
- package/messages/de/categories.json +35 -0
- package/messages/de/common.json +16 -0
- package/messages/de/dev.json +101 -0
- package/messages/de/docs.json +27 -0
- package/messages/de/entities.json +7 -0
- package/messages/de/features.json +119 -0
- package/messages/de/footer.json +22 -0
- package/messages/de/home.json +57 -0
- package/messages/de/index.ts +39 -0
- package/messages/de/mobileNav.json +13 -0
- package/messages/de/navigation.json +8 -0
- package/messages/de/observability.json +74 -0
- package/messages/de/posts.json +54 -0
- package/messages/de/pricing.json +102 -0
- package/messages/de/support.json +9 -0
- package/messages/de/teams.json +8 -0
- package/messages/en/admin.json +219 -0
- package/messages/en/aiUsage.json +36 -0
- package/messages/en/buttons.json +19 -0
- package/messages/en/categories.json +35 -0
- package/messages/en/common.json +16 -0
- package/messages/en/dev.json +106 -0
- package/messages/en/docs.json +27 -0
- package/messages/en/entities.json +7 -0
- package/messages/en/features.json +119 -0
- package/messages/en/footer.json +22 -0
- package/messages/en/home.json +57 -0
- package/messages/en/index.ts +39 -0
- package/messages/en/mobileNav.json +13 -0
- package/messages/en/navigation.json +8 -0
- package/messages/en/observability.json +74 -0
- package/messages/en/posts.json +54 -0
- package/messages/en/pricing.json +102 -0
- package/messages/en/support.json +9 -0
- package/messages/en/teams.json +8 -0
- package/messages/es/admin.json +219 -0
- package/messages/es/aiUsage.json +36 -0
- package/messages/es/buttons.json +19 -0
- package/messages/es/categories.json +35 -0
- package/messages/es/common.json +16 -0
- package/messages/es/dev.json +101 -0
- package/messages/es/docs.json +27 -0
- package/messages/es/entities.json +7 -0
- package/messages/es/features.json +119 -0
- package/messages/es/footer.json +22 -0
- package/messages/es/home.json +57 -0
- package/messages/es/index.ts +39 -0
- package/messages/es/mobileNav.json +13 -0
- package/messages/es/navigation.json +8 -0
- package/messages/es/observability.json +74 -0
- package/messages/es/posts.json +54 -0
- package/messages/es/pricing.json +102 -0
- package/messages/es/support.json +9 -0
- package/messages/es/teams.json +8 -0
- package/messages/fr/admin.json +219 -0
- package/messages/fr/aiUsage.json +36 -0
- package/messages/fr/buttons.json +19 -0
- package/messages/fr/categories.json +35 -0
- package/messages/fr/common.json +16 -0
- package/messages/fr/dev.json +101 -0
- package/messages/fr/docs.json +27 -0
- package/messages/fr/entities.json +7 -0
- package/messages/fr/features.json +119 -0
- package/messages/fr/footer.json +22 -0
- package/messages/fr/home.json +57 -0
- package/messages/fr/index.ts +39 -0
- package/messages/fr/mobileNav.json +13 -0
- package/messages/fr/navigation.json +8 -0
- package/messages/fr/observability.json +74 -0
- package/messages/fr/posts.json +54 -0
- package/messages/fr/pricing.json +102 -0
- package/messages/fr/support.json +9 -0
- package/messages/fr/teams.json +8 -0
- package/messages/it/admin.json +219 -0
- package/messages/it/aiUsage.json +36 -0
- package/messages/it/buttons.json +19 -0
- package/messages/it/categories.json +35 -0
- package/messages/it/common.json +16 -0
- package/messages/it/dev.json +101 -0
- package/messages/it/docs.json +27 -0
- package/messages/it/entities.json +7 -0
- package/messages/it/features.json +119 -0
- package/messages/it/footer.json +22 -0
- package/messages/it/home.json +57 -0
- package/messages/it/index.ts +39 -0
- package/messages/it/mobileNav.json +13 -0
- package/messages/it/navigation.json +8 -0
- package/messages/it/observability.json +74 -0
- package/messages/it/posts.json +54 -0
- package/messages/it/pricing.json +102 -0
- package/messages/it/support.json +9 -0
- package/messages/it/teams.json +8 -0
- package/messages/pt/admin.json +219 -0
- package/messages/pt/aiUsage.json +36 -0
- package/messages/pt/buttons.json +19 -0
- package/messages/pt/categories.json +35 -0
- package/messages/pt/common.json +16 -0
- package/messages/pt/dev.json +101 -0
- package/messages/pt/docs.json +27 -0
- package/messages/pt/entities.json +7 -0
- package/messages/pt/features.json +119 -0
- package/messages/pt/footer.json +22 -0
- package/messages/pt/home.json +57 -0
- package/messages/pt/index.ts +39 -0
- package/messages/pt/mobileNav.json +13 -0
- package/messages/pt/navigation.json +8 -0
- package/messages/pt/observability.json +74 -0
- package/messages/pt/posts.json +54 -0
- package/messages/pt/pricing.json +102 -0
- package/messages/pt/support.json +9 -0
- package/messages/pt/teams.json +8 -0
- package/migrations/089_add_editor_team_role.sql +39 -0
- package/migrations/090_demo_users_teams.sql +540 -0
- package/migrations/091_greek_teams_billing.sql +523 -0
- package/migrations/092_billing_sample_data.sql +774 -0
- package/migrations/093_pages_sample_data.sql +1158 -0
- package/migrations/094_posts_sample_data.sql +278 -0
- package/migrations/095_tasks_sample_data.sql +440 -0
- package/migrations/096_customers_sample_data.sql +358 -0
- package/migrations/097_scheduled_actions_sample_data.sql +111 -0
- package/package.json +22 -0
- package/public/docs/desktop-layout-example.png +0 -0
- package/styles/components.css +11 -0
- package/styles/globals.css +179 -0
- package/templates/(public)/blog/[slug]/page.tsx +65 -0
- package/templates/(public)/layout.tsx +25 -0
- package/templates/(public)/page.tsx +200 -0
- package/templates/(public)/support/page.tsx +321 -0
- package/templates/dashboard/(main)/agent-multi/page.tsx +63 -0
- package/templates/dashboard/(main)/agent-single/page.tsx +142 -0
- package/templates/dashboard/(main)/settings/ai-usage/page.tsx +157 -0
- package/templates/superadmin/ai-observability/[traceId]/page.tsx +27 -0
- 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,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
|
+
]
|