@nextsparkjs/theme-default 0.1.0-beta.1 → 0.1.0-beta.101
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/LICENSE +21 -0
- package/api/ai/chat/stream/route.ts +4 -1
- package/api/ai/orchestrator/route.ts +10 -3
- package/api/ai/single-agent/route.ts +10 -3
- package/api/ai/usage/route.ts +4 -1
- package/blocks/benefits/component.tsx +4 -4
- package/blocks/cta-section/component.tsx +4 -4
- package/blocks/faq-accordion/component.tsx +2 -2
- package/blocks/features-grid/component.tsx +5 -5
- package/blocks/hero/component.tsx +2 -2
- package/blocks/hero/fields.ts +1 -1
- package/blocks/hero-with-form/component.tsx +7 -7
- package/blocks/hero-with-form/fields.ts +1 -1
- package/blocks/jumbotron/component.tsx +7 -7
- package/blocks/jumbotron/fields.ts +1 -1
- package/blocks/logo-cloud/component.tsx +6 -6
- package/blocks/logo-cloud/fields.ts +1 -1
- package/blocks/post-content/component.tsx +2 -2
- package/blocks/pricing-table/component.tsx +5 -5
- package/blocks/split-content/component.tsx +5 -5
- package/blocks/split-content/fields.ts +1 -1
- package/blocks/stats-counter/component.tsx +9 -9
- package/blocks/testimonials/component.tsx +4 -4
- package/blocks/testimonials/fields.ts +1 -1
- package/blocks/text-content/component.tsx +12 -10
- package/blocks/timeline/component.tsx +12 -12
- package/blocks/video-hero/component.tsx +7 -7
- package/blocks/video-hero/fields.ts +1 -1
- package/components/ai-chat/ChatPanel.tsx +7 -7
- package/components/ai-chat/Message.tsx +2 -2
- package/components/ai-chat/MessageInput.tsx +3 -3
- package/components/ai-chat/MessageList.tsx +3 -3
- package/components/ai-chat/TypingIndicator.tsx +2 -2
- package/config/app.config.ts +75 -62
- package/config/dashboard.config.ts +14 -0
- package/config/features.config.ts +10 -0
- package/config/permissions.config.ts +26 -1
- package/docs/{01-overview → public/01-overview}/01-introduction.md +5 -0
- package/docs/{01-overview → public/01-overview}/02-customization.md +5 -0
- package/docs/{02-features → public/02-features}/03-tasks-entity.md +5 -0
- package/docs/{03-ai → public/03-ai}/01-overview.md +5 -0
- package/docs/{03-ai → public/03-ai}/02-customization.md +5 -0
- package/docs/superadmin/01-setup/01-configuration.md +79 -0
- package/docs/superadmin/01-setup/02-deployment.md +82 -0
- package/docs/superadmin/02-management/01-users.md +83 -0
- package/docs/superadmin/03-integrations/01-langchain.md +139 -0
- package/entities/customers/api/docs.md +107 -0
- package/entities/customers/api/presets.ts +80 -0
- package/entities/pages/api/docs.md +114 -0
- package/entities/pages/api/presets.ts +72 -0
- package/entities/posts/api/docs.md +120 -0
- package/entities/posts/api/presets.ts +74 -0
- package/entities/tasks/api/docs.md +126 -0
- package/entities/tasks/api/presets.ts +84 -0
- package/lib/selectors.ts +7 -4
- package/messages/de/admin.json +45 -0
- package/messages/en/admin.json +56 -0
- package/messages/en/navigation.json +2 -1
- package/messages/es/admin.json +56 -0
- package/messages/es/navigation.json +2 -1
- package/messages/fr/admin.json +45 -0
- package/messages/it/admin.json +45 -0
- package/messages/pt/admin.json +45 -0
- package/migrations/090_demo_users_teams.sql +11 -11
- package/migrations/091_greek_teams_billing.sql +15 -15
- package/migrations/093_pages_sample_data.sql +7 -7
- package/migrations/098_patterns_sample_data.sql +234 -0
- package/package.json +8 -3
- package/styles/globals.css +42 -0
- package/templates/(public)/blog/[slug]/page.tsx +1 -1
- package/templates/(public)/page.tsx +1 -1
- package/tests/cypress/e2e/_utils/devtools/access.bdd.md +262 -0
- package/tests/cypress/e2e/_utils/devtools/access.cy.ts +171 -0
- package/tests/cypress/e2e/_utils/devtools/navigation.bdd.md +261 -0
- package/tests/cypress/e2e/_utils/devtools/navigation.cy.ts +157 -0
- package/tests/cypress/e2e/_utils/devtools/pages.bdd.md +303 -0
- package/tests/cypress/e2e/_utils/devtools/pages.cy.ts +184 -0
- package/tests/cypress/e2e/_utils/docs/README.md +215 -0
- package/tests/cypress/e2e/_utils/selectors/auth.bdd.md +354 -0
- package/tests/cypress/e2e/_utils/selectors/auth.cy.ts +310 -0
- package/tests/cypress/e2e/_utils/selectors/billing.bdd.md +276 -0
- package/tests/cypress/e2e/_utils/selectors/billing.cy.ts +182 -0
- package/tests/cypress/e2e/_utils/selectors/block-editor.bdd.md +615 -0
- package/tests/cypress/e2e/_utils/selectors/block-editor.cy.ts +783 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-container.cy.ts +52 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-mobile.bdd.md +205 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-mobile.cy.ts +137 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-navigation.bdd.md +147 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-navigation.cy.ts +114 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-sidebar.bdd.md +76 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-sidebar.cy.ts +68 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-topnav.bdd.md +326 -0
- package/tests/cypress/e2e/_utils/selectors/dashboard-topnav.cy.ts +177 -0
- package/tests/cypress/e2e/_utils/selectors/devtools.bdd.md +306 -0
- package/tests/cypress/e2e/_utils/selectors/devtools.cy.ts +273 -0
- package/tests/cypress/e2e/_utils/selectors/global-search.bdd.md +115 -0
- package/tests/cypress/e2e/_utils/selectors/global-search.cy.ts +93 -0
- package/tests/cypress/e2e/_utils/selectors/patterns.bdd.md +388 -0
- package/tests/cypress/e2e/_utils/selectors/patterns.cy.ts +559 -0
- package/tests/cypress/e2e/_utils/selectors/public.cy.ts +112 -0
- package/tests/cypress/e2e/_utils/selectors/settings-api-keys.bdd.md +266 -0
- package/tests/cypress/e2e/_utils/selectors/settings-api-keys.cy.ts +233 -0
- package/tests/cypress/e2e/_utils/selectors/settings-billing.bdd.md +78 -0
- package/tests/cypress/e2e/_utils/selectors/settings-billing.cy.ts +108 -0
- package/tests/cypress/e2e/_utils/selectors/settings-layout.bdd.md +129 -0
- package/tests/cypress/e2e/_utils/selectors/settings-layout.cy.ts +115 -0
- package/tests/cypress/e2e/_utils/selectors/settings-password.bdd.md +82 -0
- package/tests/cypress/e2e/_utils/selectors/settings-password.cy.ts +74 -0
- package/tests/cypress/e2e/_utils/selectors/settings-profile.bdd.md +77 -0
- package/tests/cypress/e2e/_utils/selectors/settings-profile.cy.ts +79 -0
- package/tests/cypress/e2e/_utils/selectors/settings-teams.bdd.md +130 -0
- package/tests/cypress/e2e/_utils/selectors/settings-teams.cy.ts +86 -0
- package/tests/cypress/e2e/_utils/selectors/superadmin.bdd.md +261 -0
- package/tests/cypress/e2e/_utils/selectors/superadmin.cy.ts +193 -0
- package/tests/cypress/e2e/_utils/selectors/tasks.bdd.md +593 -0
- package/tests/cypress/e2e/_utils/selectors/tasks.cy.ts +864 -0
- package/tests/cypress/e2e/_utils/selectors/taxonomies.cy.ts +126 -0
- package/tests/cypress/e2e/_utils/selectors/teams.bdd.md +278 -0
- package/tests/cypress/e2e/_utils/selectors/teams.cy.ts +195 -0
- package/tests/cypress/e2e/_utils/superadmin/all-teams.bdd.md +261 -0
- package/tests/cypress/e2e/_utils/superadmin/all-teams.cy.ts +177 -0
- package/tests/cypress/e2e/_utils/superadmin/all-users.bdd.md +406 -0
- package/tests/cypress/e2e/_utils/superadmin/all-users.cy.ts +294 -0
- package/tests/cypress/e2e/_utils/superadmin/dashboard.bdd.md +235 -0
- package/tests/cypress/e2e/_utils/superadmin/dashboard.cy.ts +149 -0
- package/tests/cypress/e2e/_utils/superadmin/subscriptions-overview.bdd.md +290 -0
- package/tests/cypress/e2e/_utils/superadmin/subscriptions-overview.cy.ts +194 -0
- package/tests/cypress/e2e/ai/ai-usage.cy.ts +209 -0
- package/tests/cypress/e2e/ai/chat-api.cy.ts +119 -0
- package/tests/cypress/e2e/ai/guardrails.cy.ts +332 -0
- package/tests/cypress/e2e/api/_core/billing/BillingAPIController.js +319 -0
- package/tests/cypress/e2e/api/_core/billing/check-action.cy.ts +326 -0
- package/tests/cypress/e2e/api/_core/billing/checkout.cy.ts +358 -0
- package/tests/cypress/e2e/api/_core/billing/lifecycle.cy.ts +423 -0
- package/tests/cypress/e2e/api/_core/billing/plans/README.md +345 -0
- package/tests/cypress/e2e/api/_core/billing/plans/business.cy.ts +412 -0
- package/tests/cypress/e2e/api/_core/billing/plans/downgrade.cy.ts +510 -0
- package/tests/cypress/e2e/api/_core/billing/plans/fixtures/billing-plans.json +163 -0
- package/tests/cypress/e2e/api/_core/billing/plans/free.cy.ts +500 -0
- package/tests/cypress/e2e/api/_core/billing/plans/pro.cy.ts +497 -0
- package/tests/cypress/e2e/api/_core/billing/plans/starter.cy.ts +342 -0
- package/tests/cypress/e2e/api/_core/billing/portal.cy.ts +313 -0
- package/tests/cypress/e2e/api/_core/devtools/registries.bdd.md +300 -0
- package/tests/cypress/e2e/api/_core/devtools/registries.cy.ts +368 -0
- package/tests/cypress/e2e/api/_core/scheduled-actions/cron-endpoint.bdd.md +375 -0
- package/tests/cypress/e2e/api/_core/scheduled-actions/cron-endpoint.cy.ts +346 -0
- package/tests/cypress/e2e/api/_core/scheduled-actions/devtools-endpoint.bdd.md +451 -0
- package/tests/cypress/e2e/api/_core/scheduled-actions/devtools-endpoint.cy.ts +447 -0
- package/tests/cypress/e2e/api/_core/scheduled-actions/scheduling.bdd.md +649 -0
- package/tests/cypress/e2e/api/_core/scheduled-actions/scheduling.cy.ts +333 -0
- package/tests/cypress/e2e/api/_core/security/security-headers.cy.ts +601 -0
- package/tests/cypress/e2e/api/_core/settings/api-keys.crud.cy.ts +923 -0
- package/tests/cypress/e2e/api/_core/teams/teams-security.cy.ts +415 -0
- package/tests/cypress/e2e/api/_core/users/users-crud.cy.ts +469 -0
- package/tests/cypress/e2e/api/_core/users/users-metas.cy.ts +913 -0
- package/tests/cypress/e2e/api/_core/users/users-security.cy.ts +375 -0
- package/tests/cypress/e2e/api/entities/customers/customers-crud.cy.ts +648 -0
- package/tests/cypress/e2e/api/entities/customers/customers-metas.cy.ts +839 -0
- package/tests/cypress/e2e/api/entities/media/media-crud.cy.ts +600 -0
- package/tests/cypress/e2e/api/entities/media/media-role-permissions.cy.ts +617 -0
- package/tests/cypress/e2e/api/entities/media/media-team-isolation.cy.ts +464 -0
- package/tests/cypress/e2e/api/entities/pages/blocks-scope.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/pages/pages-crud.cy.ts +425 -0
- package/tests/cypress/e2e/api/entities/pages/pages-status.cy.ts +335 -0
- package/tests/cypress/e2e/api/entities/posts/post-categories-crud.cy.ts +610 -0
- package/tests/cypress/e2e/api/entities/posts/posts-crud.cy.ts +709 -0
- package/tests/cypress/e2e/api/entities/posts/posts-status.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/tasks/tasks-crud.cy.ts +602 -0
- package/tests/cypress/e2e/api/entities/tasks/tasks-metas.cy.ts +878 -0
- package/tests/cypress/e2e/patterns/patterns-in-pages.cy.ts +367 -0
- package/tests/cypress/e2e/uat/_core/auth/app-roles/developer-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/_core/auth/app-roles/developer-login.cy.ts +144 -0
- package/tests/cypress/e2e/uat/_core/auth/app-roles/superadmin-login.bdd.md +118 -0
- package/tests/cypress/e2e/uat/_core/auth/app-roles/superadmin-login.cy.ts +84 -0
- package/tests/cypress/e2e/uat/_core/auth/custom-roles/editor-login.bdd.md +288 -0
- package/tests/cypress/e2e/uat/_core/auth/custom-roles/editor-login.cy.ts +188 -0
- package/tests/cypress/e2e/uat/_core/auth/login-logout.bdd.md +160 -0
- package/tests/cypress/e2e/uat/_core/auth/login-logout.cy.ts +116 -0
- package/tests/cypress/e2e/uat/_core/auth/password-reset.bdd.md +289 -0
- package/tests/cypress/e2e/uat/_core/auth/password-reset.cy.ts +200 -0
- package/tests/cypress/e2e/uat/_core/auth/registration-control-invitation.cy.ts +176 -0
- package/tests/cypress/e2e/uat/_core/auth/registration-control-open.cy.ts +131 -0
- package/tests/cypress/e2e/uat/_core/auth/registration-control.cy.ts +140 -0
- package/tests/cypress/e2e/uat/_core/auth/team-roles/admin-login.bdd.md +225 -0
- package/tests/cypress/e2e/uat/_core/auth/team-roles/admin-login.cy.ts +148 -0
- package/tests/cypress/e2e/uat/_core/auth/team-roles/member-login.bdd.md +251 -0
- package/tests/cypress/e2e/uat/_core/auth/team-roles/member-login.cy.ts +163 -0
- package/tests/cypress/e2e/uat/_core/auth/team-roles/owner-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/_core/auth/team-roles/owner-login.cy.ts +141 -0
- package/tests/cypress/e2e/uat/_core/billing/extended.bdd.md +273 -0
- package/tests/cypress/e2e/uat/_core/billing/extended.cy.ts +209 -0
- package/tests/cypress/e2e/uat/_core/billing/feature-gates.bdd.md +407 -0
- package/tests/cypress/e2e/uat/_core/billing/feature-gates.cy.ts +307 -0
- package/tests/cypress/e2e/uat/_core/billing/page.bdd.md +329 -0
- package/tests/cypress/e2e/uat/_core/billing/page.cy.ts +250 -0
- package/tests/cypress/e2e/uat/_core/billing/status.bdd.md +190 -0
- package/tests/cypress/e2e/uat/_core/billing/status.cy.ts +145 -0
- package/tests/cypress/e2e/uat/_core/billing/team-switch.bdd.md +156 -0
- package/tests/cypress/e2e/uat/_core/billing/team-switch.cy.ts +122 -0
- package/tests/cypress/e2e/uat/_core/billing/usage.bdd.md +218 -0
- package/tests/cypress/e2e/uat/_core/billing/usage.cy.ts +176 -0
- package/tests/cypress/e2e/uat/_core/blocks/hero.bdd.md +124 -0
- package/tests/cypress/e2e/uat/_core/blocks/hero.cy.ts +56 -0
- package/tests/cypress/e2e/uat/_core/devtools/api-tester.cy.ts +390 -0
- package/tests/cypress/e2e/uat/_core/performance/suspense-loading.cy.ts +134 -0
- package/tests/cypress/e2e/uat/_core/scheduled-actions/devtools-ui.bdd.md +736 -0
- package/tests/cypress/e2e/uat/_core/scheduled-actions/devtools-ui.cy.ts +740 -0
- package/tests/cypress/e2e/uat/_core/teams/inline-edit.cy.ts +278 -0
- package/tests/cypress/e2e/uat/_core/teams/roles-matrix.bdd.md +553 -0
- package/tests/cypress/e2e/uat/_core/teams/roles-matrix.cy.ts +185 -0
- package/tests/cypress/e2e/uat/_core/teams/switcher.bdd.md +1151 -0
- package/tests/cypress/e2e/uat/_core/teams/switcher.cy.ts +497 -0
- package/tests/cypress/e2e/uat/_core/teams/team-switcher.md +198 -0
- package/tests/cypress/e2e/uat/entities/customers/member.bdd.md +275 -0
- package/tests/cypress/e2e/uat/entities/customers/member.cy.ts +122 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.bdd.md +243 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.bdd.md +476 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.cy.ts +486 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.bdd.md +460 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.cy.ts +301 -0
- package/tests/cypress/e2e/uat/entities/pages/list.bdd.md +432 -0
- package/tests/cypress/e2e/uat/entities/pages/list.cy.ts +273 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.bdd.md +696 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.cy.ts +340 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.bdd.md +161 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.cy.ts +104 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.bdd.md +375 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.cy.ts +241 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.bdd.md +429 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.cy.ts +257 -0
- package/tests/cypress/e2e/uat/entities/posts/list.bdd.md +340 -0
- package/tests/cypress/e2e/uat/entities/posts/list.cy.ts +177 -0
- package/tests/cypress/e2e/uat/entities/posts/public.bdd.md +614 -0
- package/tests/cypress/e2e/uat/entities/posts/public.cy.ts +249 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.bdd.md +222 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.bdd.md +419 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.cy.ts +191 -0
- package/tests/cypress/e2e/uat/features/roles/editor-role.bdd.md +552 -0
- package/tests/cypress/e2e/uat/features/roles/editor-role.cy.ts +210 -0
- package/tests/cypress/e2e/uat/features/roles/member-restrictions.bdd.md +450 -0
- package/tests/cypress/e2e/uat/features/roles/member-restrictions.cy.ts +189 -0
- package/tests/cypress/e2e/uat/features/roles/owner-full-crud.bdd.md +530 -0
- package/tests/cypress/e2e/uat/features/roles/owner-full-crud.cy.ts +247 -0
- package/tests/cypress/fixtures/blocks.json +218 -0
- package/tests/cypress/fixtures/entities.json +87 -0
- package/tests/cypress/fixtures/page-builder.json +21 -0
- package/tests/cypress/src/components/CategoriesPOM.ts +382 -0
- package/tests/cypress/src/components/CustomersPOM.ts +439 -0
- package/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
- package/tests/cypress/src/components/EntityForm.ts +375 -0
- package/tests/cypress/src/components/EntityList.ts +389 -0
- package/tests/cypress/src/components/PageBuilderPOM.ts +710 -0
- package/tests/cypress/src/components/PostEditorPOM.ts +370 -0
- package/tests/cypress/src/components/PostsListPOM.ts +223 -0
- package/tests/cypress/src/components/PublicPagePOM.ts +447 -0
- package/tests/cypress/src/components/PublicPostPOM.ts +146 -0
- package/tests/cypress/src/components/TasksPOM.ts +272 -0
- package/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
- package/tests/cypress/src/components/index.ts +21 -0
- package/tests/cypress/src/controllers/ApiKeysAPIController.js +178 -0
- package/tests/cypress/src/controllers/BaseAPIController.js +317 -0
- package/tests/cypress/src/controllers/CustomerAPIController.js +251 -0
- package/tests/cypress/src/controllers/MediaAPIController.js +231 -0
- package/tests/cypress/src/controllers/PagesAPIController.js +226 -0
- package/tests/cypress/src/controllers/PostsAPIController.js +250 -0
- package/tests/cypress/src/controllers/TaskAPIController.js +240 -0
- package/tests/cypress/src/controllers/UsersAPIController.js +242 -0
- package/tests/cypress/src/controllers/index.js +25 -0
- package/tests/cypress/src/core/AuthPOM.ts +450 -0
- package/tests/cypress/src/core/BasePOM.ts +33 -0
- package/tests/cypress/src/core/BlockEditorBasePOM.ts +874 -0
- package/tests/cypress/src/core/DashboardEntityPOM.ts +41 -0
- package/tests/cypress/src/core/index.ts +14 -0
- package/tests/cypress/src/entities/CustomersPOM.ts +172 -0
- package/tests/cypress/src/entities/PagesPOM.ts +137 -0
- package/tests/cypress/src/entities/PatternsPOM.ts +329 -0
- package/tests/cypress/src/entities/PostsPOM.ts +137 -0
- package/tests/cypress/src/entities/TasksPOM.ts +246 -0
- package/tests/cypress/src/entities/index.ts +16 -0
- package/tests/cypress/src/features/BillingPOM.ts +385 -0
- package/tests/cypress/src/features/DashboardPOM.ts +271 -0
- package/tests/cypress/src/features/DevtoolsPOM.ts +750 -0
- package/tests/cypress/src/features/PageBuilderPOM.ts +283 -0
- package/tests/cypress/src/features/PostEditorPOM.ts +313 -0
- package/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
- package/tests/cypress/src/features/SettingsPOM.ts +707 -0
- package/tests/cypress/src/features/SuperadminPOM.ts +851 -0
- package/tests/cypress/src/features/SuperadminTeamRolesPOM.ts +285 -0
- package/tests/cypress/src/features/index.ts +28 -0
- package/tests/cypress/src/helpers/ApiInterceptor.ts +20 -0
- package/tests/cypress/src/index.ts +101 -0
- package/tests/cypress/src/pages/dashboard/Dashboard.js +677 -0
- package/tests/cypress/src/pages/dashboard/DashboardPage.js +43 -0
- package/tests/cypress/src/pages/dashboard/DashboardStats.js +546 -0
- package/tests/cypress/src/pages/dashboard/index.js +6 -0
- package/tests/cypress/src/pages/index.js +5 -0
- package/tests/cypress/src/pages/public/FeaturesPage.js +28 -0
- package/tests/cypress/src/pages/public/LandingPage.js +69 -0
- package/tests/cypress/src/pages/public/PricingPage.js +33 -0
- package/tests/cypress/src/pages/public/index.js +6 -0
- package/tests/cypress/src/selectors.ts +46 -0
- package/tests/cypress/src/session-helpers.ts +518 -0
- package/tests/cypress/support/doc-commands.ts +260 -0
- package/tests/cypress/support/e2e.ts +90 -0
- package/tests/cypress.config.ts +178 -0
- package/tests/jest/__mocks__/@nextsparkjs/core/components/ui/badge.js +16 -0
- package/tests/jest/__mocks__/@nextsparkjs/core/lib/db.js +11 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +160 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/theme-registry.ts +68 -0
- package/tests/jest/__mocks__/jose.js +22 -0
- package/tests/jest/__mocks__/next/image.js +15 -0
- package/tests/jest/__mocks__/next-server.js +56 -0
- package/tests/jest/components/post-header.test.tsx +377 -0
- package/tests/jest/jest.config.cjs +154 -0
- package/tests/jest/langchain/COVERAGE.md +372 -0
- package/tests/jest/langchain/guardrails.test.ts +465 -0
- package/tests/jest/langchain/streaming.test.ts +370 -0
- package/tests/jest/langchain/token-tracker.test.ts +455 -0
- package/tests/jest/langchain/tracer-callbacks.test.ts +881 -0
- package/tests/jest/langchain/tracer.test.ts +823 -0
- package/tests/jest/services/tasks.service.test.ts +707 -0
- package/tests/jest/setup.ts +170 -0
- package/tests/jest/tsconfig.jest.json +6 -0
- package/tests/jest/validation/categories.test.ts +429 -0
- package/tests/jest/validation/posts.test.ts +546 -0
- package/tests/tsconfig.json +21 -0
- /package/docs/{02-features → public/02-features}/01-components.md +0 -0
- /package/docs/{02-features → public/02-features}/02-styling.md +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 NextSpark
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
import { NextRequest } from 'next/server'
|
|
27
27
|
import { z } from 'zod'
|
|
28
28
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
29
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
29
30
|
import { streamChat } from '@/plugins/langchain/lib/agent-factory'
|
|
30
31
|
import { createSSEEncoder } from '@/plugins/langchain/lib/streaming'
|
|
31
32
|
import { loadSystemPrompt } from '@/themes/default/lib/langchain/agents'
|
|
@@ -46,7 +47,7 @@ const StreamChatRequestSchema = z.object({
|
|
|
46
47
|
/**
|
|
47
48
|
* POST - Stream chat response
|
|
48
49
|
*/
|
|
49
|
-
|
|
50
|
+
const postHandler = async (request: NextRequest) => {
|
|
50
51
|
try {
|
|
51
52
|
// 1. Authentication
|
|
52
53
|
const authResult = await authenticateRequest(request)
|
|
@@ -210,3 +211,5 @@ export async function POST(request: NextRequest) {
|
|
|
210
211
|
) as any
|
|
211
212
|
}
|
|
212
213
|
}
|
|
214
|
+
|
|
215
|
+
export const POST = withRateLimitTier(postHandler, 'write')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
4
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
4
5
|
import { processMessage } from '@/themes/default/lib/langchain/orchestrator'
|
|
5
6
|
import { dbMemoryStore } from '@/plugins/langchain/lib/db-memory-store'
|
|
6
7
|
import type { ChatMessage } from '@/plugins/langchain/types/langchain.types'
|
|
@@ -52,7 +53,7 @@ function convertToApiMessages(
|
|
|
52
53
|
* - Sub-agents: task-assistant, customer-assistant, page-assistant
|
|
53
54
|
* - Handles ambiguous requests by asking for clarification
|
|
54
55
|
*/
|
|
55
|
-
|
|
56
|
+
const postHandler = async (req: NextRequest) => {
|
|
56
57
|
try {
|
|
57
58
|
// 1. Dual authentication (API key or session)
|
|
58
59
|
const authResult = await authenticateRequest(req)
|
|
@@ -118,10 +119,12 @@ export async function POST(req: NextRequest) {
|
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
export const POST = withRateLimitTier(postHandler, 'write')
|
|
123
|
+
|
|
121
124
|
/**
|
|
122
125
|
* GET - Retrieve conversation history
|
|
123
126
|
*/
|
|
124
|
-
|
|
127
|
+
const getHandler = async (req: NextRequest) => {
|
|
125
128
|
const { searchParams } = new URL(req.url)
|
|
126
129
|
const sessionId = searchParams.get('sessionId')
|
|
127
130
|
|
|
@@ -187,10 +190,12 @@ export async function GET(req: NextRequest) {
|
|
|
187
190
|
}
|
|
188
191
|
}
|
|
189
192
|
|
|
193
|
+
export const GET = withRateLimitTier(getHandler, 'read')
|
|
194
|
+
|
|
190
195
|
/**
|
|
191
196
|
* DELETE - Clear conversation
|
|
192
197
|
*/
|
|
193
|
-
|
|
198
|
+
const deleteHandler = async (req: NextRequest) => {
|
|
194
199
|
const authResult = await authenticateRequest(req)
|
|
195
200
|
if (!authResult.success || !authResult.user) {
|
|
196
201
|
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
|
|
@@ -224,3 +229,5 @@ export async function DELETE(req: NextRequest) {
|
|
|
224
229
|
return NextResponse.json({ success: false, error: 'Failed to clear' }, { status: 500 })
|
|
225
230
|
}
|
|
226
231
|
}
|
|
232
|
+
|
|
233
|
+
export const DELETE = withRateLimitTier(deleteHandler, 'write')
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { NextRequest, NextResponse } from 'next/server'
|
|
15
15
|
import { z } from 'zod'
|
|
16
16
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
17
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
17
18
|
import { createAgent } from '@/plugins/langchain/lib/agent-factory'
|
|
18
19
|
import {
|
|
19
20
|
dbMemoryStore,
|
|
@@ -74,7 +75,7 @@ function convertToApiMessages(
|
|
|
74
75
|
/**
|
|
75
76
|
* POST - Send message to single agent
|
|
76
77
|
*/
|
|
77
|
-
|
|
78
|
+
const postHandler = async (req: NextRequest) => {
|
|
78
79
|
try {
|
|
79
80
|
// 1. Authentication
|
|
80
81
|
const authResult = await authenticateRequest(req)
|
|
@@ -181,10 +182,12 @@ export async function POST(req: NextRequest) {
|
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
184
|
|
|
185
|
+
export const POST = withRateLimitTier(postHandler, 'write')
|
|
186
|
+
|
|
184
187
|
/**
|
|
185
188
|
* GET - Retrieve conversation history
|
|
186
189
|
*/
|
|
187
|
-
|
|
190
|
+
const getHandler = async (req: NextRequest) => {
|
|
188
191
|
const { searchParams } = new URL(req.url)
|
|
189
192
|
const sessionId = searchParams.get('sessionId')
|
|
190
193
|
|
|
@@ -252,10 +255,12 @@ export async function GET(req: NextRequest) {
|
|
|
252
255
|
}
|
|
253
256
|
}
|
|
254
257
|
|
|
258
|
+
export const GET = withRateLimitTier(getHandler, 'read')
|
|
259
|
+
|
|
255
260
|
/**
|
|
256
261
|
* DELETE - Clear conversation
|
|
257
262
|
*/
|
|
258
|
-
|
|
263
|
+
const deleteHandler = async (req: NextRequest) => {
|
|
259
264
|
const authResult = await authenticateRequest(req)
|
|
260
265
|
if (!authResult.success || !authResult.user) {
|
|
261
266
|
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 })
|
|
@@ -289,3 +294,5 @@ export async function DELETE(req: NextRequest) {
|
|
|
289
294
|
return NextResponse.json({ success: false, error: 'Failed to clear' }, { status: 500 })
|
|
290
295
|
}
|
|
291
296
|
}
|
|
297
|
+
|
|
298
|
+
export const DELETE = withRateLimitTier(deleteHandler, 'write')
|
package/api/ai/usage/route.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { NextRequest, NextResponse } from 'next/server'
|
|
22
22
|
import { authenticateRequest } from '@nextsparkjs/core/lib/api/auth/dual-auth'
|
|
23
|
+
import { withRateLimitTier } from '@nextsparkjs/core/lib/api/rate-limit'
|
|
23
24
|
import { tokenTracker } from '@/plugins/langchain/lib/token-tracker'
|
|
24
25
|
import { queryOne } from '@nextsparkjs/core/lib/db'
|
|
25
26
|
|
|
@@ -28,7 +29,7 @@ type Period = 'today' | '7d' | '30d' | 'all'
|
|
|
28
29
|
/**
|
|
29
30
|
* GET - Retrieve token usage statistics
|
|
30
31
|
*/
|
|
31
|
-
|
|
32
|
+
const getHandler = async (request: NextRequest) => {
|
|
32
33
|
try {
|
|
33
34
|
// 1. Authentication
|
|
34
35
|
const authResult = await authenticateRequest(request)
|
|
@@ -120,3 +121,5 @@ export async function GET(request: NextRequest) {
|
|
|
120
121
|
)
|
|
121
122
|
}
|
|
122
123
|
}
|
|
124
|
+
|
|
125
|
+
export const GET = withRateLimitTier(getHandler, 'read')
|
|
@@ -23,9 +23,9 @@ export function BenefitsBlock({
|
|
|
23
23
|
const bgClasses = getBackgroundClasses(backgroundColor)
|
|
24
24
|
|
|
25
25
|
const gridCols = {
|
|
26
|
-
'2': 'md:grid-cols-2',
|
|
27
|
-
'3': 'md:grid-cols-3',
|
|
28
|
-
'4': 'md:grid-cols-2 lg:grid-cols-4',
|
|
26
|
+
'2': '@md:grid-cols-2',
|
|
27
|
+
'3': '@md:grid-cols-3',
|
|
28
|
+
'4': '@md:grid-cols-2 @lg:grid-cols-4',
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const cardStyles = {
|
|
@@ -49,7 +49,7 @@ export function BenefitsBlock({
|
|
|
49
49
|
{(sectionTitle || sectionSubtitle) && (
|
|
50
50
|
<div className="text-center mb-12">
|
|
51
51
|
{sectionTitle && (
|
|
52
|
-
<h2 className="text-3xl md:text-4xl font-bold mb-4">
|
|
52
|
+
<h2 className="text-3xl @md:text-4xl font-bold mb-4">
|
|
53
53
|
{sectionTitle}
|
|
54
54
|
</h2>
|
|
55
55
|
)}
|
|
@@ -48,7 +48,7 @@ export function CTASectionBlock({
|
|
|
48
48
|
|
|
49
49
|
// Build section classes with background and custom className
|
|
50
50
|
const sectionClasses = buildSectionClasses(
|
|
51
|
-
'py-16 px-4 md:py-24',
|
|
51
|
+
'py-16 px-4 @md:py-24',
|
|
52
52
|
{ backgroundColor, className }
|
|
53
53
|
)
|
|
54
54
|
|
|
@@ -56,15 +56,15 @@ export function CTASectionBlock({
|
|
|
56
56
|
<section id={id} className={sectionClasses} data-cy={sel('blocks.ctaSection.container')}>
|
|
57
57
|
<div className="container mx-auto max-w-4xl text-center">
|
|
58
58
|
{title && (
|
|
59
|
-
<h2 className="mb-4 text-4xl font-bold md:text-5xl">{title}</h2>
|
|
59
|
+
<h2 className="mb-4 text-4xl font-bold @md:text-5xl">{title}</h2>
|
|
60
60
|
)}
|
|
61
61
|
|
|
62
62
|
{displayContent && (
|
|
63
|
-
<p className="mb-8 text-lg md:text-xl opacity-90">{displayContent}</p>
|
|
63
|
+
<p className="mb-8 text-lg @md:text-xl opacity-90">{displayContent}</p>
|
|
64
64
|
)}
|
|
65
65
|
|
|
66
66
|
{(primaryCta || secondaryButton) && (
|
|
67
|
-
<div className="flex flex-col gap-4 sm:flex-row sm:justify-center">
|
|
67
|
+
<div className="flex flex-col gap-4 @sm:flex-row @sm:justify-center">
|
|
68
68
|
{primaryCta && (
|
|
69
69
|
<Button asChild size="lg">
|
|
70
70
|
<a
|
|
@@ -44,7 +44,7 @@ export function FaqAccordionBlock({
|
|
|
44
44
|
|
|
45
45
|
// Build section classes with background and custom className
|
|
46
46
|
const sectionClasses = buildSectionClasses(
|
|
47
|
-
'py-16 px-4 md:py-24',
|
|
47
|
+
'py-16 px-4 @md:py-24',
|
|
48
48
|
{ backgroundColor, className }
|
|
49
49
|
)
|
|
50
50
|
|
|
@@ -80,7 +80,7 @@ export function FaqAccordionBlock({
|
|
|
80
80
|
{(title || subtitle) && (
|
|
81
81
|
<div className="mb-12 text-center">
|
|
82
82
|
{title && (
|
|
83
|
-
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
|
83
|
+
<h2 className="mb-4 text-4xl font-bold @md:text-5xl">
|
|
84
84
|
{title}
|
|
85
85
|
</h2>
|
|
86
86
|
)}
|
|
@@ -42,14 +42,14 @@ export function FeaturesGridBlock({
|
|
|
42
42
|
|
|
43
43
|
// Build column classes based on columns prop
|
|
44
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',
|
|
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
48
|
}
|
|
49
49
|
|
|
50
50
|
// Build section classes with background and custom className
|
|
51
51
|
const sectionClasses = buildSectionClasses(
|
|
52
|
-
'py-16 px-4 md:py-24',
|
|
52
|
+
'py-16 px-4 @md:py-24',
|
|
53
53
|
{ backgroundColor, className }
|
|
54
54
|
)
|
|
55
55
|
|
|
@@ -60,7 +60,7 @@ export function FeaturesGridBlock({
|
|
|
60
60
|
{(title || displayContent) && (
|
|
61
61
|
<div className="mb-12 text-center">
|
|
62
62
|
{title && (
|
|
63
|
-
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
|
63
|
+
<h2 className="mb-4 text-4xl font-bold @md:text-5xl">
|
|
64
64
|
{title}
|
|
65
65
|
</h2>
|
|
66
66
|
)}
|
|
@@ -72,13 +72,13 @@ export function HeroBlock({
|
|
|
72
72
|
{/* Content */}
|
|
73
73
|
<div className="container relative z-10 mx-auto max-w-4xl text-center">
|
|
74
74
|
{title && (
|
|
75
|
-
<h1 className="mb-6 text-5xl font-bold leading-tight md:text-6xl lg:text-7xl">
|
|
75
|
+
<h1 className="mb-6 text-5xl font-bold leading-tight @md:text-6xl @lg:text-7xl">
|
|
76
76
|
{title}
|
|
77
77
|
</h1>
|
|
78
78
|
)}
|
|
79
79
|
|
|
80
80
|
{displayContent && (
|
|
81
|
-
<p className="mb-8 text-xl md:text-2xl opacity-90">
|
|
81
|
+
<p className="mb-8 text-xl @md:text-2xl opacity-90">
|
|
82
82
|
{displayContent}
|
|
83
83
|
</p>
|
|
84
84
|
)}
|
package/blocks/hero/fields.ts
CHANGED
|
@@ -21,7 +21,7 @@ const heroDesignFields: FieldDefinition[] = [
|
|
|
21
21
|
{
|
|
22
22
|
name: 'backgroundImage',
|
|
23
23
|
label: 'Background Image',
|
|
24
|
-
type: '
|
|
24
|
+
type: 'media-library',
|
|
25
25
|
tab: 'design',
|
|
26
26
|
required: false,
|
|
27
27
|
helpText: 'Optional background image (recommended: 1920x1080px minimum)',
|
|
@@ -88,26 +88,26 @@ export function HeroWithFormBlock({
|
|
|
88
88
|
</div>
|
|
89
89
|
|
|
90
90
|
{/* Content Container */}
|
|
91
|
-
<div className="container relative z-10 mx-auto px-4 py-12 lg:py-0">
|
|
92
|
-
<div className="grid lg:grid-cols-2 gap-8 lg:gap-16 min-h-screen items-center">
|
|
91
|
+
<div className="container relative z-10 mx-auto px-4 py-12 @lg:py-0">
|
|
92
|
+
<div className="grid @lg:grid-cols-2 gap-8 @lg:gap-16 min-h-screen items-center">
|
|
93
93
|
|
|
94
94
|
{/* Left: Title/Subtitle - vertically centered, bottom aligned on mobile */}
|
|
95
|
-
<div className="text-white order-2 lg:order-1 flex flex-col justify-end lg:justify-center pb-8 lg:pb-0">
|
|
95
|
+
<div className="text-white order-2 @lg:order-1 flex flex-col justify-end @lg:justify-center pb-8 @lg:pb-0">
|
|
96
96
|
{title && (
|
|
97
|
-
<h1 className="text-4xl lg:text-5xl xl:text-6xl font-bold italic mb-4 leading-tight">
|
|
97
|
+
<h1 className="text-4xl @lg:text-5xl @xl:text-6xl font-bold italic mb-4 leading-tight">
|
|
98
98
|
{title}
|
|
99
99
|
</h1>
|
|
100
100
|
)}
|
|
101
101
|
{subtitle && (
|
|
102
|
-
<p className="text-lg lg:text-xl xl:text-2xl opacity-90 max-w-lg">
|
|
102
|
+
<p className="text-lg @lg:text-xl @xl:text-2xl opacity-90 max-w-lg">
|
|
103
103
|
{subtitle}
|
|
104
104
|
</p>
|
|
105
105
|
)}
|
|
106
106
|
</div>
|
|
107
107
|
|
|
108
108
|
{/* Right: Form Card - centered vertically */}
|
|
109
|
-
<div className="order-1 lg:order-2 flex justify-center lg:justify-end items-start lg:items-center pt-8 lg:pt-0">
|
|
110
|
-
<div className="bg-white rounded-lg shadow-2xl p-6 sm:p-8 w-full max-w-md">
|
|
109
|
+
<div className="order-1 @lg:order-2 flex justify-center @lg:justify-end items-start @lg:items-center pt-8 @lg:pt-0">
|
|
110
|
+
<div className="bg-white rounded-lg shadow-2xl p-6 @sm:p-8 w-full max-w-md">
|
|
111
111
|
{/* Form Header */}
|
|
112
112
|
{formTitle && (
|
|
113
113
|
<h2 className="text-xl font-bold text-center text-primary mb-2">
|
|
@@ -34,7 +34,7 @@ const heroWithFormContentFields: FieldDefinition[] = [
|
|
|
34
34
|
{
|
|
35
35
|
name: 'backgroundImage',
|
|
36
36
|
label: 'Background Image',
|
|
37
|
-
type: '
|
|
37
|
+
type: 'media-library',
|
|
38
38
|
tab: 'content',
|
|
39
39
|
required: true,
|
|
40
40
|
helpText: 'Full-width background image (recommended: 1920x1080px minimum)',
|
|
@@ -46,16 +46,16 @@ export function JumbotronBlock({
|
|
|
46
46
|
}[align]
|
|
47
47
|
|
|
48
48
|
const ctaJustifyClasses = {
|
|
49
|
-
center: 'sm:justify-center',
|
|
50
|
-
left: 'sm:justify-start',
|
|
51
|
-
right: 'sm:justify-end',
|
|
49
|
+
center: '@sm:justify-center',
|
|
50
|
+
left: '@sm:justify-start',
|
|
51
|
+
right: '@sm:justify-end',
|
|
52
52
|
}[align]
|
|
53
53
|
|
|
54
54
|
// Build section classes with fullscreen or standard padding
|
|
55
55
|
const sectionClasses = buildSectionClasses(
|
|
56
56
|
cn(
|
|
57
57
|
'relative flex overflow-hidden px-4',
|
|
58
|
-
fullscreen ? 'min-h-screen' : 'py-16 md:py-24',
|
|
58
|
+
fullscreen ? 'min-h-screen' : 'py-16 @md:py-24',
|
|
59
59
|
alignmentClasses,
|
|
60
60
|
textColor === 'light' ? 'text-white' : 'text-gray-900'
|
|
61
61
|
),
|
|
@@ -81,20 +81,20 @@ export function JumbotronBlock({
|
|
|
81
81
|
{/* Content */}
|
|
82
82
|
<div className={cn('container relative z-10 max-w-4xl', contentAlignmentClasses)}>
|
|
83
83
|
{title && (
|
|
84
|
-
<h1 className="mb-6 text-5xl font-bold leading-tight md:text-6xl lg:text-7xl">
|
|
84
|
+
<h1 className="mb-6 text-5xl font-bold leading-tight @md:text-6xl @lg:text-7xl">
|
|
85
85
|
{title}
|
|
86
86
|
</h1>
|
|
87
87
|
)}
|
|
88
88
|
|
|
89
89
|
{subtitle && (
|
|
90
|
-
<p className="mb-8 text-xl md:text-2xl opacity-90">
|
|
90
|
+
<p className="mb-8 text-xl @md:text-2xl opacity-90">
|
|
91
91
|
{subtitle}
|
|
92
92
|
</p>
|
|
93
93
|
)}
|
|
94
94
|
|
|
95
95
|
{/* CTAs - automatically center based on count */}
|
|
96
96
|
{(primaryCta || secondaryCta) && (
|
|
97
|
-
<div className={cn('flex flex-col gap-4 sm:flex-row', ctaJustifyClasses)}>
|
|
97
|
+
<div className={cn('flex flex-col gap-4 @sm:flex-row', ctaJustifyClasses)}>
|
|
98
98
|
{primaryCta && primaryCta.text && (
|
|
99
99
|
<Button
|
|
100
100
|
asChild
|
|
@@ -148,7 +148,7 @@ const jumbotronDesignFields: FieldDefinition[] = [
|
|
|
148
148
|
{
|
|
149
149
|
name: 'backgroundImage',
|
|
150
150
|
label: 'Background Image',
|
|
151
|
-
type: '
|
|
151
|
+
type: 'media-library',
|
|
152
152
|
tab: 'design',
|
|
153
153
|
required: false,
|
|
154
154
|
helpText: 'Optional background image (recommended: 1920x1080px minimum)',
|
|
@@ -43,10 +43,10 @@ export function LogoCloudBlock({
|
|
|
43
43
|
|
|
44
44
|
// Build column classes for grid layout
|
|
45
45
|
const columnClasses: Record<string, string> = {
|
|
46
|
-
'3': 'grid-cols-2 sm:grid-cols-3',
|
|
47
|
-
'4': 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-4',
|
|
48
|
-
'5': 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-5',
|
|
49
|
-
'6': 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-6',
|
|
46
|
+
'3': 'grid-cols-2 @sm:grid-cols-3',
|
|
47
|
+
'4': 'grid-cols-2 @sm:grid-cols-3 @lg:grid-cols-4',
|
|
48
|
+
'5': 'grid-cols-2 @sm:grid-cols-3 @lg:grid-cols-5',
|
|
49
|
+
'6': 'grid-cols-2 @sm:grid-cols-3 @lg:grid-cols-6',
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// Build size classes for logo containers
|
|
@@ -66,7 +66,7 @@ export function LogoCloudBlock({
|
|
|
66
66
|
|
|
67
67
|
// Build section classes with background and custom className
|
|
68
68
|
const sectionClasses = buildSectionClasses(
|
|
69
|
-
'py-12 px-4 md:py-16',
|
|
69
|
+
'py-12 px-4 @md:py-16',
|
|
70
70
|
{ backgroundColor, className }
|
|
71
71
|
)
|
|
72
72
|
|
|
@@ -77,7 +77,7 @@ export function LogoCloudBlock({
|
|
|
77
77
|
{(title || content) && (
|
|
78
78
|
<div className="mb-10 text-center">
|
|
79
79
|
{title && (
|
|
80
|
-
<h2 className="mb-3 text-2xl font-semibold md:text-3xl">
|
|
80
|
+
<h2 className="mb-3 text-2xl font-semibold @md:text-3xl">
|
|
81
81
|
{title}
|
|
82
82
|
</h2>
|
|
83
83
|
)}
|
|
@@ -79,7 +79,7 @@ export function PostContentBlock({
|
|
|
79
79
|
|
|
80
80
|
// Build section classes with background
|
|
81
81
|
const sectionClasses = buildSectionClasses(
|
|
82
|
-
'py-16 px-4 md:py-24',
|
|
82
|
+
'py-16 px-4 @md:py-24',
|
|
83
83
|
{ backgroundColor, className }
|
|
84
84
|
)
|
|
85
85
|
|
|
@@ -119,7 +119,7 @@ export function PostContentBlock({
|
|
|
119
119
|
{/* Optional Section Title */}
|
|
120
120
|
{title && (
|
|
121
121
|
<div className={cn('mb-12 text-center', maxWidthClasses[maxWidth], 'mx-auto')}>
|
|
122
|
-
<h2 className="text-4xl font-bold md:text-5xl lg:text-6xl tracking-tight">
|
|
122
|
+
<h2 className="text-4xl font-bold @md:text-5xl @lg:text-6xl tracking-tight">
|
|
123
123
|
{title}
|
|
124
124
|
</h2>
|
|
125
125
|
</div>
|
|
@@ -38,14 +38,14 @@ export function PricingTableBlock({
|
|
|
38
38
|
|
|
39
39
|
// Build column classes based on columns prop
|
|
40
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',
|
|
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
44
|
}
|
|
45
45
|
|
|
46
46
|
// Build section classes with background and custom className
|
|
47
47
|
const sectionClasses = buildSectionClasses(
|
|
48
|
-
'py-16 px-4 md:py-24',
|
|
48
|
+
'py-16 px-4 @md:py-24',
|
|
49
49
|
{ backgroundColor, className }
|
|
50
50
|
)
|
|
51
51
|
|
|
@@ -59,7 +59,7 @@ export function PricingTableBlock({
|
|
|
59
59
|
{(title || content) && (
|
|
60
60
|
<div className="mb-12 text-center">
|
|
61
61
|
{title && (
|
|
62
|
-
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
|
62
|
+
<h2 className="mb-4 text-4xl font-bold @md:text-5xl">
|
|
63
63
|
{title}
|
|
64
64
|
</h2>
|
|
65
65
|
)}
|
|
@@ -38,7 +38,7 @@ export function SplitContentBlock({
|
|
|
38
38
|
|
|
39
39
|
// Build section classes with background and custom className
|
|
40
40
|
const sectionClasses = buildSectionClasses(
|
|
41
|
-
'py-16 px-4 md:py-24',
|
|
41
|
+
'py-16 px-4 @md:py-24',
|
|
42
42
|
{ backgroundColor, className }
|
|
43
43
|
)
|
|
44
44
|
|
|
@@ -57,13 +57,13 @@ export function SplitContentBlock({
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// Grid order classes based on image position
|
|
60
|
-
const imageOrderClass = imagePosition === 'right' ? 'lg:order-2' : 'lg:order-1'
|
|
61
|
-
const contentOrderClass = imagePosition === 'right' ? 'lg:order-1' : 'lg:order-2'
|
|
60
|
+
const imageOrderClass = imagePosition === 'right' ? '@lg:order-2' : '@lg:order-1'
|
|
61
|
+
const contentOrderClass = imagePosition === 'right' ? '@lg:order-1' : '@lg:order-2'
|
|
62
62
|
|
|
63
63
|
return (
|
|
64
64
|
<section id={id} className={sectionClasses} data-cy={sel('blocks.splitContent.container')}>
|
|
65
65
|
<div className="container mx-auto max-w-7xl">
|
|
66
|
-
<div className={cn('grid gap-8 lg:grid-cols-2 lg:gap-12', alignmentClasses[verticalAlign as 'top' | 'center' | 'bottom'])}>
|
|
66
|
+
<div className={cn('grid gap-8 @lg:grid-cols-2 @lg:gap-12', alignmentClasses[verticalAlign as 'top' | 'center' | 'bottom'])}>
|
|
67
67
|
{/* Image Column */}
|
|
68
68
|
<div className={cn('relative', imageOrderClass)}>
|
|
69
69
|
<div className="relative aspect-[4/3] w-full overflow-hidden">
|
|
@@ -86,7 +86,7 @@ export function SplitContentBlock({
|
|
|
86
86
|
)}
|
|
87
87
|
|
|
88
88
|
{title && (
|
|
89
|
-
<h2 className="mb-4 text-3xl font-bold md:text-4xl lg:text-5xl">
|
|
89
|
+
<h2 className="mb-4 text-3xl font-bold @md:text-4xl @lg:text-5xl">
|
|
90
90
|
{title}
|
|
91
91
|
</h2>
|
|
92
92
|
)}
|
|
@@ -34,16 +34,16 @@ export function StatsCounterBlock({
|
|
|
34
34
|
|
|
35
35
|
// Build column classes based on columns prop
|
|
36
36
|
const columnClasses: Record<string, string> = {
|
|
37
|
-
'2': 'sm:grid-cols-2',
|
|
38
|
-
'3': 'sm:grid-cols-2 lg:grid-cols-3',
|
|
39
|
-
'4': 'sm:grid-cols-2 lg:grid-cols-4',
|
|
37
|
+
'2': '@sm:grid-cols-2',
|
|
38
|
+
'3': '@sm:grid-cols-2 @lg:grid-cols-3',
|
|
39
|
+
'4': '@sm:grid-cols-2 @lg:grid-cols-4',
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// Size classes for numbers
|
|
43
43
|
const sizeClasses: Record<string, string> = {
|
|
44
|
-
sm: 'text-3xl md:text-4xl',
|
|
45
|
-
md: 'text-4xl md:text-5xl',
|
|
46
|
-
lg: 'text-5xl md:text-6xl lg:text-7xl',
|
|
44
|
+
sm: 'text-3xl @md:text-4xl',
|
|
45
|
+
md: 'text-4xl @md:text-5xl',
|
|
46
|
+
lg: 'text-5xl @md:text-6xl @lg:text-7xl',
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Variant-specific stat item classes
|
|
@@ -62,7 +62,7 @@ export function StatsCounterBlock({
|
|
|
62
62
|
|
|
63
63
|
// Build section classes with background and custom className
|
|
64
64
|
const sectionClasses = buildSectionClasses(
|
|
65
|
-
'py-16 px-4 md:py-24',
|
|
65
|
+
'py-16 px-4 @md:py-24',
|
|
66
66
|
{ backgroundColor, className }
|
|
67
67
|
)
|
|
68
68
|
|
|
@@ -73,7 +73,7 @@ export function StatsCounterBlock({
|
|
|
73
73
|
{(title || content) && (
|
|
74
74
|
<div className="mb-12 text-center">
|
|
75
75
|
{title && (
|
|
76
|
-
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
|
76
|
+
<h2 className="mb-4 text-4xl font-bold @md:text-5xl">
|
|
77
77
|
{title}
|
|
78
78
|
</h2>
|
|
79
79
|
)}
|
|
@@ -98,7 +98,7 @@ export function StatsCounterBlock({
|
|
|
98
98
|
<span className="text-primary">{stat.suffix}</span>
|
|
99
99
|
)}
|
|
100
100
|
</div>
|
|
101
|
-
<div className="text-sm md:text-base text-muted-foreground font-medium">
|
|
101
|
+
<div className="text-sm @md:text-base text-muted-foreground font-medium">
|
|
102
102
|
{stat.label}
|
|
103
103
|
</div>
|
|
104
104
|
</div>
|
|
@@ -31,13 +31,13 @@ export function TestimonialsBlock({
|
|
|
31
31
|
}: TestimonialsBlockProps) {
|
|
32
32
|
// Build column classes based on columns prop
|
|
33
33
|
const columnClasses: Record<string, string> = {
|
|
34
|
-
'2': 'md:grid-cols-2',
|
|
35
|
-
'3': 'md:grid-cols-2 lg:grid-cols-3',
|
|
34
|
+
'2': '@md:grid-cols-2',
|
|
35
|
+
'3': '@md:grid-cols-2 @lg:grid-cols-3',
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Build section classes with background and custom className
|
|
39
39
|
const sectionClasses = buildSectionClasses(
|
|
40
|
-
'py-16 px-4 md:py-24',
|
|
40
|
+
'py-16 px-4 @md:py-24',
|
|
41
41
|
{ backgroundColor, className }
|
|
42
42
|
)
|
|
43
43
|
|
|
@@ -51,7 +51,7 @@ export function TestimonialsBlock({
|
|
|
51
51
|
{(title || content) && (
|
|
52
52
|
<div className="mb-12 text-center">
|
|
53
53
|
{title && (
|
|
54
|
-
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
|
54
|
+
<h2 className="mb-4 text-4xl font-bold @md:text-5xl">
|
|
55
55
|
{title}
|
|
56
56
|
</h2>
|
|
57
57
|
)}
|