create-nextblock 0.2.78 → 0.8.0
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/bin/create-nextblock.js +740 -459
- package/package.json +1 -2
- package/scripts/sync-template.js +18 -1
- package/templates/nextblock-template/.browserslistrc +11 -0
- package/templates/nextblock-template/.swcrc +30 -30
- package/templates/nextblock-template/README.md +23 -114
- package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -28
- package/templates/nextblock-template/app/(auth-pages)/sign-in/page.tsx +50 -25
- package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +111 -56
- package/templates/nextblock-template/app/(auth-pages)/two-factor/actions.ts +91 -0
- package/templates/nextblock-template/app/(auth-pages)/two-factor/components/TwoFactorForm.tsx +118 -0
- package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -0
- package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -0
- package/templates/nextblock-template/app/[slug]/PageClientContent.tsx +48 -28
- package/templates/nextblock-template/app/[slug]/page.tsx +63 -6
- package/templates/nextblock-template/app/[slug]/page.utils.ts +374 -157
- package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -0
- package/templates/nextblock-template/app/actions/consent.ts +57 -0
- package/templates/nextblock-template/app/actions/formActions.ts +130 -11
- package/templates/nextblock-template/app/actions/languageActions.ts +31 -30
- package/templates/nextblock-template/app/actions/package-actions.ts +183 -0
- package/templates/nextblock-template/app/actions/postActions.ts +146 -48
- package/templates/nextblock-template/app/actions/twoFactorEmail.ts +21 -0
- package/templates/nextblock-template/app/actions/visualEditingActions.test.ts +179 -0
- package/templates/nextblock-template/app/actions/visualEditingActions.ts +345 -0
- package/templates/nextblock-template/app/actions.ts +67 -12
- package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -0
- package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -0
- package/templates/nextblock-template/app/api/ai/global-agent/route.ts +965 -0
- package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -0
- package/templates/nextblock-template/app/api/checkout/route.ts +146 -0
- package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -0
- package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -0
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +3413 -17
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +7830 -0
- package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +35 -0
- package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -0
- package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -0
- package/templates/nextblock-template/app/api/draft/disable/route.ts +25 -0
- package/templates/nextblock-template/app/api/draft/route.ts +93 -0
- package/templates/nextblock-template/app/api/draft/start/route.ts +77 -0
- package/templates/nextblock-template/app/api/media/library/route.ts +65 -0
- package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -0
- package/templates/nextblock-template/app/api/media/record/route.ts +160 -0
- package/templates/nextblock-template/app/api/search/route.ts +43 -0
- package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -0
- package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -0
- package/templates/nextblock-template/app/api/webhooks/freemius/route.ts +34 -0
- package/templates/nextblock-template/app/api/webhooks/stripe/route.ts +27 -0
- package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +392 -128
- package/templates/nextblock-template/app/article/[slug]/page.tsx +179 -127
- package/templates/nextblock-template/app/article/[slug]/page.utils.ts +262 -77
- package/templates/nextblock-template/app/auth/callback/route.ts +31 -58
- package/templates/nextblock-template/app/cart/page.tsx +7 -0
- package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -0
- package/templates/nextblock-template/app/checkout/page.tsx +52 -0
- package/templates/nextblock-template/app/checkout/success/actions.ts +136 -0
- package/templates/nextblock-template/app/checkout/success/page.tsx +186 -0
- package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +163 -33
- package/templates/nextblock-template/app/cms/blocks/actions.ts +424 -235
- package/templates/nextblock-template/app/cms/blocks/components/BackgroundSelector.tsx +212 -151
- package/templates/nextblock-template/app/cms/blocks/components/BlockEditorArea.tsx +41 -20
- package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +152 -19
- package/templates/nextblock-template/app/cms/blocks/components/BlockTypeCard.tsx +25 -17
- package/templates/nextblock-template/app/cms/blocks/components/BlockTypeSelector.tsx +200 -18
- package/templates/nextblock-template/app/cms/blocks/components/ColumnEditor.tsx +33 -16
- package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -0
- package/templates/nextblock-template/app/cms/blocks/components/EditableBlock.tsx +37 -18
- package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -67
- package/templates/nextblock-template/app/cms/blocks/components/SectionConfigPanel.tsx +108 -31
- package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -0
- package/templates/nextblock-template/app/cms/blocks/editors/FeaturedProductBlockEditor.tsx +31 -0
- package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +2 -2
- package/templates/nextblock-template/app/cms/blocks/editors/HeadingBlockEditor.tsx +1 -1
- package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +29 -29
- package/templates/nextblock-template/app/cms/blocks/editors/PostsGridBlockEditor.tsx +14 -18
- package/templates/nextblock-template/app/cms/blocks/editors/ProductGridBlockEditor.tsx +41 -0
- package/templates/nextblock-template/app/cms/blocks/editors/SectionBlockEditor.tsx +318 -118
- package/templates/nextblock-template/app/cms/blocks/editors/TextBlockEditor.tsx +98 -21
- package/templates/nextblock-template/app/cms/blocks/editors/VideoEmbedBlockEditor.tsx +1 -1
- package/templates/nextblock-template/app/cms/components/ContentLanguageSwitcher.tsx +27 -9
- package/templates/nextblock-template/app/cms/components/CopyContentFromLanguage.tsx +1 -1
- package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -0
- package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -0
- package/templates/nextblock-template/app/cms/components/CortexGlobalAgentChat.tsx +1507 -0
- package/templates/nextblock-template/app/cms/components/DraftStatusActions.tsx +145 -0
- package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +244 -0
- package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +38 -24
- package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -0
- package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -0
- package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -0
- package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -0
- package/templates/nextblock-template/app/cms/custom-blocks/components/BlockComposer.tsx +1522 -0
- package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -0
- package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -0
- package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -0
- package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -0
- package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -0
- package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -98
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -0
- package/templates/nextblock-template/app/cms/dashboard/page.tsx +182 -154
- package/templates/nextblock-template/app/cms/import-export/ContentTransferControls.tsx +391 -0
- package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -0
- package/templates/nextblock-template/app/cms/layout.tsx +29 -10
- package/templates/nextblock-template/app/cms/media/UploadFolderContext.tsx +22 -22
- package/templates/nextblock-template/app/cms/media/actions.ts +45 -124
- package/templates/nextblock-template/app/cms/media/components/DeleteMediaButtonClient.tsx +1 -1
- package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +26 -26
- package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -64
- package/templates/nextblock-template/app/cms/media/components/MediaPickerDialog.tsx +227 -158
- package/templates/nextblock-template/app/cms/media/components/MediaUploadForm.tsx +101 -89
- package/templates/nextblock-template/app/cms/media/page.tsx +1 -1
- package/templates/nextblock-template/app/cms/navigation/components/NavigationItemForm.tsx +2 -2
- package/templates/nextblock-template/app/cms/orders/[id]/MarkPaidButton.tsx +44 -0
- package/templates/nextblock-template/app/cms/orders/[id]/page.tsx +16 -0
- package/templates/nextblock-template/app/cms/orders/actions.ts +201 -0
- package/templates/nextblock-template/app/cms/orders/page.tsx +20 -0
- package/templates/nextblock-template/app/cms/orders/types.ts +20 -0
- package/templates/nextblock-template/app/cms/pages/[id]/edit/EditPageClient.tsx +156 -121
- package/templates/nextblock-template/app/cms/pages/[id]/edit/page.tsx +79 -26
- package/templates/nextblock-template/app/cms/pages/actions.ts +54 -38
- package/templates/nextblock-template/app/cms/pages/components/DeletePageButtonClient.tsx +1 -1
- package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +267 -116
- package/templates/nextblock-template/app/cms/pages/page.tsx +25 -18
- package/templates/nextblock-template/app/cms/payments/page.tsx +16 -0
- package/templates/nextblock-template/app/cms/posts/[id]/edit/page.tsx +132 -90
- package/templates/nextblock-template/app/cms/posts/actions.ts +71 -72
- package/templates/nextblock-template/app/cms/posts/components/DeletePostButtonClient.tsx +1 -1
- package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +256 -245
- package/templates/nextblock-template/app/cms/posts/new/page.tsx +1 -1
- package/templates/nextblock-template/app/cms/posts/page.tsx +20 -13
- package/templates/nextblock-template/app/cms/products/ClientNotionEditor.tsx +16 -0
- package/templates/nextblock-template/app/cms/products/ProductFormClientShell.tsx +56 -0
- package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +292 -0
- package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -0
- package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -0
- package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -0
- package/templates/nextblock-template/app/cms/products/new/page.tsx +143 -0
- package/templates/nextblock-template/app/cms/products/page.tsx +42 -0
- package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -0
- package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -0
- package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -0
- package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -0
- package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -0
- package/templates/nextblock-template/app/cms/revisions/RevisionHistoryButton.tsx +2 -2
- package/templates/nextblock-template/app/cms/revisions/actions.ts +285 -285
- package/templates/nextblock-template/app/cms/revisions/service.ts +19 -16
- package/templates/nextblock-template/app/cms/revisions/utils.ts +8 -3
- package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -0
- package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -0
- package/templates/nextblock-template/app/cms/settings/bot-protection/actions.ts +93 -0
- package/templates/nextblock-template/app/cms/settings/bot-protection/components/BotProtectionForm.tsx +129 -0
- package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -0
- package/templates/nextblock-template/app/cms/settings/copyright/actions.ts +1 -1
- package/templates/nextblock-template/app/cms/settings/copyright/components/CopyrightForm.tsx +2 -2
- package/templates/nextblock-template/app/cms/settings/copyright/page.tsx +1 -1
- package/templates/nextblock-template/app/cms/settings/cortex-ai/SandboxCortexAiSettingsClient.tsx +496 -0
- package/templates/nextblock-template/app/cms/settings/cortex-ai/StoredCortexAiSettingsClient.tsx +410 -0
- package/templates/nextblock-template/app/cms/settings/cortex-ai/actions.ts +248 -0
- package/templates/nextblock-template/app/cms/settings/cortex-ai/page.tsx +80 -0
- package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -0
- package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -0
- package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -0
- package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +203 -44
- package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -242
- package/templates/nextblock-template/app/cms/settings/global-css/actions.ts +65 -0
- package/templates/nextblock-template/app/cms/settings/global-css/components/GlobalCssForm.tsx +46 -0
- package/templates/nextblock-template/app/cms/settings/global-css/page.tsx +24 -0
- package/templates/nextblock-template/app/cms/settings/languages/components/DeleteLanguageButton.tsx +1 -1
- package/templates/nextblock-template/app/cms/settings/languages/components/LanguageForm.tsx +2 -2
- package/templates/nextblock-template/app/cms/settings/languages/page.tsx +1 -1
- package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
- package/templates/nextblock-template/app/cms/settings/logos/actions.ts +82 -6
- package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -0
- package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -18
- package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +20 -16
- package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -0
- package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
- package/templates/nextblock-template/app/cms/settings/logos/page.tsx +120 -82
- package/templates/nextblock-template/app/cms/settings/logos/types.ts +8 -8
- package/templates/nextblock-template/app/cms/settings/packages/activation-form.tsx +84 -0
- package/templates/nextblock-template/app/cms/settings/packages/package-card.tsx +122 -0
- package/templates/nextblock-template/app/cms/settings/packages/page.tsx +49 -0
- package/templates/nextblock-template/app/cms/settings/privacy/actions.ts +53 -0
- package/templates/nextblock-template/app/cms/settings/privacy/components/PrivacyForm.tsx +196 -0
- package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +26 -0
- package/templates/nextblock-template/app/cms/settings/security/actions.ts +251 -0
- package/templates/nextblock-template/app/cms/settings/security/components/SecurityPanel.tsx +453 -0
- package/templates/nextblock-template/app/cms/settings/security/page.tsx +13 -0
- package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -0
- package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -0
- package/templates/nextblock-template/app/cms/users/[id]/edit/page.tsx +28 -23
- package/templates/nextblock-template/app/cms/users/actions.ts +105 -40
- package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +1 -1
- package/templates/nextblock-template/app/cms/users/components/UserForm.tsx +65 -152
- package/templates/nextblock-template/app/cms/users/page.tsx +15 -10
- package/templates/nextblock-template/app/globals.css +9 -0
- package/templates/nextblock-template/app/layout.tsx +372 -120
- package/templates/nextblock-template/app/lib/seo.test.ts +52 -0
- package/templates/nextblock-template/app/lib/seo.ts +279 -0
- package/templates/nextblock-template/app/lib/site-settings.ts +87 -0
- package/templates/nextblock-template/app/lib/sitemap-utils.ts +224 -39
- package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -0
- package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -0
- package/templates/nextblock-template/app/lib/ucp/server.ts +1914 -0
- package/templates/nextblock-template/app/page.tsx +165 -73
- package/templates/nextblock-template/app/product/[slug]/page.tsx +433 -0
- package/templates/nextblock-template/app/profile/ProfileAccountSidebar.tsx +73 -0
- package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -0
- package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -0
- package/templates/nextblock-template/app/profile/account-data.ts +37 -0
- package/templates/nextblock-template/app/profile/account-links.ts +22 -0
- package/templates/nextblock-template/app/profile/account-types.ts +11 -0
- package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -0
- package/templates/nextblock-template/app/profile/orders/[id]/CustomerOrderDetailPageClient.tsx +79 -0
- package/templates/nextblock-template/app/profile/orders/[id]/page.tsx +32 -0
- package/templates/nextblock-template/app/profile/orders/page.tsx +19 -0
- package/templates/nextblock-template/app/profile/page.tsx +51 -0
- package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -0
- package/templates/nextblock-template/app/profile/password/actions.ts +59 -0
- package/templates/nextblock-template/app/profile/password/page.tsx +27 -0
- package/templates/nextblock-template/app/providers.tsx +55 -17
- package/templates/nextblock-template/app/robots.txt/route.ts +11 -1
- package/templates/nextblock-template/app/sitemap.ts +128 -0
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -0
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -0
- package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -0
- package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -0
- package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -0
- package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -0
- package/templates/nextblock-template/components/AppShell.tsx +154 -0
- package/templates/nextblock-template/components/BlockRenderer.tsx +210 -64
- package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -0
- package/templates/nextblock-template/components/CartTranslator.tsx +210 -0
- package/templates/nextblock-template/components/CurrentContentSetter.tsx +25 -0
- package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -0
- package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -0
- package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -0
- package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -0
- package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -0
- package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -0
- package/templates/nextblock-template/components/GitHubLoginButton.tsx +36 -0
- package/templates/nextblock-template/components/GlobalSearch.tsx +557 -0
- package/templates/nextblock-template/components/Header.tsx +49 -41
- package/templates/nextblock-template/components/LanguageSwitcher.tsx +55 -32
- package/templates/nextblock-template/components/ResponsiveNav.tsx +138 -43
- package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -8
- package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -55
- package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +42 -37
- package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +6 -2
- package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -0
- package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -0
- package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -84
- package/templates/nextblock-template/components/blocks/renderers/CartBlockRenderer.tsx +17 -0
- package/templates/nextblock-template/components/blocks/renderers/CheckoutBlockRenderer.tsx +19 -0
- package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +262 -8
- package/templates/nextblock-template/components/blocks/renderers/FeaturedProductBlockRenderer.tsx +22 -0
- package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +320 -37
- package/templates/nextblock-template/components/blocks/renderers/HeadingBlockRenderer.tsx +11 -8
- package/templates/nextblock-template/components/blocks/renderers/ImageBlockRenderer.tsx +12 -3
- package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +18 -13
- package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +90 -0
- package/templates/nextblock-template/components/blocks/renderers/ProductGridBlockRenderer.tsx +31 -0
- package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +424 -55
- package/templates/nextblock-template/components/blocks/renderers/SectionSlider.tsx +137 -0
- package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -0
- package/templates/nextblock-template/components/blocks/renderers/TextBlockRenderer.tsx +37 -22
- package/templates/nextblock-template/components/blocks/renderers/VideoEmbedBlockRenderer.tsx +23 -15
- package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +1 -3
- package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +1 -3
- package/templates/nextblock-template/components/blocks/types.ts +7 -6
- package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
- package/templates/nextblock-template/components/form-message.tsx +32 -26
- package/templates/nextblock-template/components/header-auth.tsx +69 -17
- package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +127 -0
- package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +59 -0
- package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -0
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -0
- package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +464 -0
- package/templates/nextblock-template/components/theme-switcher.tsx +8 -8
- package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -0
- package/templates/nextblock-template/components/visual-editing/NextblockVisualEditing.tsx +1172 -0
- package/templates/nextblock-template/context/AuthContext.tsx +23 -90
- package/templates/nextblock-template/context/CurrentContentContext.tsx +10 -4
- package/templates/nextblock-template/context/LanguageContext.tsx +16 -16
- package/templates/nextblock-template/context/language-rest-client.ts +31 -0
- package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -0
- package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -0
- package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +202 -0
- package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +252 -0
- package/templates/nextblock-template/docs/05-DEVELOPER-GUIDE.md +238 -0
- package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +125 -0
- package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -0
- package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +1319 -0
- package/templates/nextblock-template/docs/09-LIVE-DRAFT-MODE.md +104 -0
- package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -0
- package/templates/nextblock-template/docs/README.md +34 -0
- package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12507 -0
- package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -14
- package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -0
- package/templates/nextblock-template/index.d.ts +2 -0
- package/templates/nextblock-template/lib/ai-block-generation.ts +339 -0
- package/templates/nextblock-template/lib/ai-client.ts +247 -0
- package/templates/nextblock-template/lib/ai-config.ts +81 -0
- package/templates/nextblock-template/lib/ai-cortex-widget-builder.ts +125 -0
- package/templates/nextblock-template/lib/ai-global-agent-custom-block-tools.ts +363 -0
- package/templates/nextblock-template/lib/ai-global-agent-db-tools.test.ts +405 -0
- package/templates/nextblock-template/lib/ai-global-agent-db-tools.ts +1228 -0
- package/templates/nextblock-template/lib/ai-global-agent-ecommerce.ts +5 -0
- package/templates/nextblock-template/lib/ai-global-agent-tools-stats.test.ts +223 -0
- package/templates/nextblock-template/lib/ai-global-agent-tools.test.ts +2183 -0
- package/templates/nextblock-template/lib/ai-global-agent-tools.ts +4807 -0
- package/templates/nextblock-template/lib/ai-key-crypto.test.ts +70 -0
- package/templates/nextblock-template/lib/ai-key-crypto.ts +132 -0
- package/templates/nextblock-template/lib/ai-model-catalog.test.ts +49 -0
- package/templates/nextblock-template/lib/ai-model-catalog.ts +41 -0
- package/templates/nextblock-template/lib/ai-model-registry.test.ts +231 -0
- package/templates/nextblock-template/lib/ai-model-registry.ts +522 -0
- package/templates/nextblock-template/lib/auth/cookies.ts +47 -0
- package/templates/nextblock-template/lib/auth/crypto.ts +42 -0
- package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -0
- package/templates/nextblock-template/lib/auth/twoFactor.ts +167 -0
- package/templates/nextblock-template/lib/auth-redirects.ts +46 -0
- package/templates/nextblock-template/lib/blocks/FeaturedProductBlock.tsx +94 -0
- package/templates/nextblock-template/lib/blocks/ProductGridBlock.tsx +137 -0
- package/templates/nextblock-template/lib/blocks/README.md +13 -670
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +138 -56
- package/templates/nextblock-template/lib/blocks/blockTypes.ts +18 -0
- package/templates/nextblock-template/lib/blocks/ecommerce-block-schemas.ts +31 -0
- package/templates/nextblock-template/lib/cms-transfer/csv.test.ts +77 -0
- package/templates/nextblock-template/lib/cms-transfer/csv.ts +399 -0
- package/templates/nextblock-template/lib/cms-transfer/server.ts +2243 -0
- package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -0
- package/templates/nextblock-template/lib/cortex-widget-registry.test.ts +199 -0
- package/templates/nextblock-template/lib/cortex-widget-registry.ts +88 -0
- package/templates/nextblock-template/lib/cortex-widget-schema.test.tsx +237 -0
- package/templates/nextblock-template/lib/cortex-widget-schema.ts +393 -0
- package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -0
- package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -0
- package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -0
- package/templates/nextblock-template/lib/custom-block-r2-upload.ts +68 -0
- package/templates/nextblock-template/lib/custom-block-relation-registry.ts +256 -0
- package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -0
- package/templates/nextblock-template/lib/custom-block-relations.ts +279 -0
- package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -0
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -0
- package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -0
- package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -0
- package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -0
- package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -0
- package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -0
- package/templates/nextblock-template/lib/full-backup/server.ts +743 -0
- package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +45 -0
- package/templates/nextblock-template/lib/posts/readTime.ts +60 -0
- package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -0
- package/templates/nextblock-template/lib/privacy/settings.ts +103 -0
- package/templates/nextblock-template/lib/privacy/types.ts +67 -0
- package/templates/nextblock-template/lib/promotions/server.test.ts +74 -0
- package/templates/nextblock-template/lib/promotions/server.ts +741 -0
- package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -0
- package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -0
- package/templates/nextblock-template/lib/search/server.ts +585 -0
- package/templates/nextblock-template/lib/search/types.ts +27 -0
- package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -0
- package/templates/nextblock-template/lib/visual-editing/draft-content.ts +380 -0
- package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -0
- package/templates/nextblock-template/lib/visual-editing/draft-route.ts +82 -0
- package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -0
- package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -0
- package/templates/nextblock-template/lib/visual-editing/mutations.ts +190 -0
- package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -0
- package/templates/nextblock-template/lib/visual-editing/product-drafts.ts +511 -0
- package/templates/nextblock-template/lib/visual-editing/types.ts +122 -0
- package/templates/nextblock-template/lib/zod-config.ts +5 -0
- package/templates/nextblock-template/next.config.js +190 -66
- package/templates/nextblock-template/package.json +34 -30
- package/templates/nextblock-template/proxy.ts +435 -253
- package/templates/nextblock-template/public/images/NBcover.webp +0 -0
- package/templates/nextblock-template/public/images/cap.webp +0 -0
- package/templates/nextblock-template/public/images/commerce-plan.webp +0 -0
- package/templates/nextblock-template/public/images/commerce-square.webp +0 -0
- package/templates/nextblock-template/public/images/commerce-wide.webp +0 -0
- package/templates/nextblock-template/public/images/cortex-ai-square.webp +0 -0
- package/templates/nextblock-template/public/images/cortex-ai.webp +0 -0
- package/templates/nextblock-template/public/images/extensibility.webp +0 -0
- package/templates/nextblock-template/public/images/goals.webp +0 -0
- package/templates/nextblock-template/public/images/included.webp +0 -0
- package/templates/nextblock-template/public/images/nx-graph.webp +0 -0
- package/templates/nextblock-template/public/images/pants.webp +0 -0
- package/templates/nextblock-template/public/images/t-shirt.webp +0 -0
- package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -0
- package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +100 -0
- package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -0
- package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -0
- package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -0
- package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -0
- package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -0
- package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -0
- package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -0
- package/templates/nextblock-template/tailwind.config.js +1 -0
- package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -0
- package/templates/nextblock-template/tools/deploy-supabase.js +69 -71
- package/templates/nextblock-template/tsconfig.json +52 -66
- package/templates/nextblock-template/tsconfig.tsbuildinfo +1 -1
- package/templates/nextblock-template/types/jsdom.d.ts +6 -0
- package/templates/nextblock-template/app/force-styles.tsx +0 -31
- package/templates/nextblock-template/app/sitemap.xml/route.ts +0 -63
- package/templates/nextblock-template/components/blocks/renderers/HeroBlockRenderer.tsx +0 -273
- package/templates/nextblock-template/docs/How to Create a Custom Block.md +0 -149
- package/templates/nextblock-template/docs/cms-application-overview.md +0 -56
- package/templates/nextblock-template/docs/cms-architecture-overview.md +0 -73
- package/templates/nextblock-template/docs/files-structure.md +0 -426
- package/templates/nextblock-template/docs/tiptap-bundle-optimization-summary.md +0 -174
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { TestimonialBlockConfig, TestimonialBlockContent } from '../../components/blocks/TestimonialBlock';
|
|
1
|
+
import { z } from '../zod-config';
|
|
2
|
+
import { TestimonialBlockConfig, TestimonialBlockContent } from '../../components/blocks/TestimonialBlock';
|
|
3
|
+
import { ProductGridBlockSchema, ProductGridBlockContent, FeaturedProductBlockSchema, FeaturedProductBlockContent, CartBlockSchema, CartBlockContent, CheckoutBlockSchema, CheckoutBlockContent, ProductDetailsBlockSchema, ProductDetailsBlockContent } from './ecommerce-block-schemas';
|
|
4
|
+
import { availableBlockTypes, type BlockType } from './blockTypes';
|
|
5
|
+
export { availableBlockTypes, type BlockType } from './blockTypes';
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* Block Registry System
|
|
@@ -9,13 +12,7 @@ import { TestimonialBlockConfig, TestimonialBlockContent } from '../../component
|
|
|
9
12
|
* their initial content, editor components, renderer components, and Zod schemas.
|
|
10
13
|
*/
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
* Available block types - defined here as the source of truth
|
|
14
|
-
*/
|
|
15
|
-
export const availableBlockTypes = ["text", "heading", "image", "button", "posts_grid", "video_embed", "section", "hero", "form", "testimonial"] as const;
|
|
16
|
-
export type BlockType = (typeof availableBlockTypes)[number];
|
|
17
|
-
|
|
18
|
-
// --- Zod Schemas & Inferred Types ---
|
|
15
|
+
// --- Zod Schemas & Inferred Types ---
|
|
19
16
|
|
|
20
17
|
export const TextBlockSchema = z.object({
|
|
21
18
|
html_content: z.string().describe('Raw HTML content for the text block'),
|
|
@@ -98,10 +95,15 @@ const BackgroundSchema = z.object({
|
|
|
98
95
|
|
|
99
96
|
const BlockInColumnSchema = z.object({
|
|
100
97
|
block_type: z.enum(availableBlockTypes),
|
|
101
|
-
content: z.record(z.any()),
|
|
98
|
+
content: z.record(z.string(), z.any()),
|
|
102
99
|
temp_id: z.string().optional(),
|
|
103
100
|
});
|
|
104
101
|
|
|
102
|
+
const SlideSchema = z.object({
|
|
103
|
+
background: BackgroundSchema,
|
|
104
|
+
column_blocks: z.array(z.array(BlockInColumnSchema)),
|
|
105
|
+
});
|
|
106
|
+
|
|
105
107
|
export const SectionBlockSchema = z.object({
|
|
106
108
|
container_type: z.enum(['full-width', 'container', 'container-sm', 'container-lg', 'container-xl']),
|
|
107
109
|
background: BackgroundSchema,
|
|
@@ -117,11 +119,15 @@ export const SectionBlockSchema = z.object({
|
|
|
117
119
|
}),
|
|
118
120
|
vertical_alignment: z.enum(['start', 'center', 'end', 'stretch']).optional(),
|
|
119
121
|
column_blocks: z.array(z.array(BlockInColumnSchema)),
|
|
122
|
+
is_hero: z.boolean().optional(),
|
|
123
|
+
slider: z.boolean().optional(),
|
|
124
|
+
autoplay: z.boolean().optional(),
|
|
125
|
+
timeframe: z.number().optional(),
|
|
126
|
+
slides: z.array(SlideSchema).optional(),
|
|
120
127
|
});
|
|
121
128
|
export type SectionBlockContent = z.infer<typeof SectionBlockSchema>;
|
|
122
129
|
|
|
123
|
-
|
|
124
|
-
export type HeroBlockContent = z.infer<typeof HeroBlockSchema>;
|
|
130
|
+
|
|
125
131
|
|
|
126
132
|
// Form helpers
|
|
127
133
|
export const FormFieldOptionSchema = z.object({
|
|
@@ -145,6 +151,8 @@ export const FormBlockSchema = z.object({
|
|
|
145
151
|
submit_button_text: z.string(),
|
|
146
152
|
success_message: z.string(),
|
|
147
153
|
fields: z.array(FormFieldSchema),
|
|
154
|
+
botProtectionProvider: z.enum(['none', 'turnstile', 'recaptcha']).optional().default('none'),
|
|
155
|
+
botProtectionSiteKey: z.string().optional(),
|
|
148
156
|
});
|
|
149
157
|
export type FormBlockContent = z.infer<typeof FormBlockSchema>;
|
|
150
158
|
|
|
@@ -380,7 +388,12 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
380
388
|
[{ block_type: "text", content: { html_content: "<p>Column 1</p>" } }],
|
|
381
389
|
[{ block_type: "text", content: { html_content: "<p>Column 2</p>" } }],
|
|
382
390
|
[{ block_type: "text", content: { html_content: "<p>Column 3</p>" } }]
|
|
383
|
-
]
|
|
391
|
+
],
|
|
392
|
+
is_hero: false,
|
|
393
|
+
slider: false,
|
|
394
|
+
autoplay: false,
|
|
395
|
+
timeframe: 5,
|
|
396
|
+
slides: []
|
|
384
397
|
} as SectionBlockContent,
|
|
385
398
|
editorComponentFilename: "SectionBlockEditor.tsx",
|
|
386
399
|
rendererComponentFilename: "SectionBlockRenderer.tsx",
|
|
@@ -407,34 +420,6 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
407
420
|
},
|
|
408
421
|
},
|
|
409
422
|
|
|
410
|
-
hero: {
|
|
411
|
-
type: "hero",
|
|
412
|
-
label: "Hero Section",
|
|
413
|
-
icon: "LayoutTemplate",
|
|
414
|
-
initialContent: {
|
|
415
|
-
container_type: 'container',
|
|
416
|
-
background: { type: "none" },
|
|
417
|
-
responsive_columns: { mobile: 1, tablet: 1, desktop: 2 },
|
|
418
|
-
column_gap: 'lg',
|
|
419
|
-
padding: { top: 'xl', bottom: 'xl' },
|
|
420
|
-
column_blocks: [
|
|
421
|
-
[
|
|
422
|
-
{ block_type: "heading", content: { level: 1, text_content: "Hero Title" }, temp_id: `block-${Date.now()}-1` },
|
|
423
|
-
{ block_type: "text", content: { html_content: "<p>Hero description goes here. Explain the value proposition.</p>" }, temp_id: `block-${Date.now()}-2` },
|
|
424
|
-
{ block_type: "button", content: { text: "Call to Action", url: "#" }, temp_id: `block-${Date.now()}-3` },
|
|
425
|
-
],
|
|
426
|
-
[],
|
|
427
|
-
],
|
|
428
|
-
} as HeroBlockContent,
|
|
429
|
-
editorComponentFilename: "SectionBlockEditor.tsx", // Reusing section editor
|
|
430
|
-
rendererComponentFilename: "HeroBlockRenderer.tsx", // Specific renderer for hero
|
|
431
|
-
schema: HeroBlockSchema,
|
|
432
|
-
documentation: {
|
|
433
|
-
description: 'A specialized hero section for the top of a page, with prioritized images and pre-populated content.',
|
|
434
|
-
useCases: ['Main page hero/banner', 'Introductory section with a strong call to action'],
|
|
435
|
-
notes: ['This block reuses the Section editor but has a different renderer for optimized image loading.'],
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
423
|
|
|
439
424
|
form: {
|
|
440
425
|
type: "form",
|
|
@@ -445,6 +430,8 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
445
430
|
submit_button_text: "Submit",
|
|
446
431
|
success_message: "Thank you for your submission!",
|
|
447
432
|
fields: [],
|
|
433
|
+
botProtectionProvider: "none",
|
|
434
|
+
botProtectionSiteKey: "",
|
|
448
435
|
} as FormBlockContent,
|
|
449
436
|
editorComponentFilename: "FormBlockEditor.tsx",
|
|
450
437
|
rendererComponentFilename: "FormBlockRenderer.tsx",
|
|
@@ -473,6 +460,76 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
473
460
|
useCases: ['Social proof', 'Customer reviews'],
|
|
474
461
|
}
|
|
475
462
|
} as BlockDefinition<TestimonialBlockContent>,
|
|
463
|
+
|
|
464
|
+
"product_grid": {
|
|
465
|
+
type: "product_grid",
|
|
466
|
+
label: "Product Grid",
|
|
467
|
+
icon: "ShoppingBag", // Lucide icon
|
|
468
|
+
initialContent: { type: 'latest', limit: 6 } as ProductGridBlockContent,
|
|
469
|
+
editorComponentFilename: "ProductGridBlockEditor.tsx", // Assuming standard naming
|
|
470
|
+
rendererComponentFilename: "ProductGridBlockRenderer.tsx", // Assuming mapping to ProductGridBlock.tsx handled by renderer map not shown here, or we need to ensure the renderer map uses the file we created. The prompt implies creating the file in `lib/blocks` serves as the component. I will assume the system maps it.
|
|
471
|
+
schema: ProductGridBlockSchema,
|
|
472
|
+
documentation: {
|
|
473
|
+
description: 'Displays a grid of products.',
|
|
474
|
+
useCases: ['Homepage featured products', 'Category pages']
|
|
475
|
+
}
|
|
476
|
+
},
|
|
477
|
+
|
|
478
|
+
"featured_product": {
|
|
479
|
+
type: "featured_product",
|
|
480
|
+
label: "Featured Product",
|
|
481
|
+
icon: "Star",
|
|
482
|
+
initialContent: { productId: '', showBackground: false } as FeaturedProductBlockContent,
|
|
483
|
+
editorComponentFilename: "FeaturedProductBlockEditor.tsx",
|
|
484
|
+
rendererComponentFilename: "FeaturedProductBlockRenderer.tsx",
|
|
485
|
+
schema: FeaturedProductBlockSchema,
|
|
486
|
+
documentation: {
|
|
487
|
+
description: 'Highlights a specific product with a detailed view.',
|
|
488
|
+
useCases: ['Product spotlight', 'Special offers']
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
|
|
492
|
+
"cart": {
|
|
493
|
+
type: "cart",
|
|
494
|
+
label: "Cart",
|
|
495
|
+
icon: "ShoppingCart",
|
|
496
|
+
initialContent: {} as CartBlockContent,
|
|
497
|
+
editorComponentFilename: "CartBlockEditor.tsx",
|
|
498
|
+
rendererComponentFilename: "CartBlockRenderer.tsx",
|
|
499
|
+
schema: CartBlockSchema,
|
|
500
|
+
documentation: {
|
|
501
|
+
description: 'Displays the shopping cart.',
|
|
502
|
+
useCases: ['Cart page']
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
|
|
506
|
+
"checkout": {
|
|
507
|
+
type: "checkout",
|
|
508
|
+
label: "Checkout",
|
|
509
|
+
icon: "CreditCard",
|
|
510
|
+
initialContent: {} as CheckoutBlockContent,
|
|
511
|
+
editorComponentFilename: "CheckoutBlockEditor.tsx",
|
|
512
|
+
rendererComponentFilename: "CheckoutBlockRenderer.tsx",
|
|
513
|
+
schema: CheckoutBlockSchema,
|
|
514
|
+
documentation: {
|
|
515
|
+
description: 'Displays the checkout form.',
|
|
516
|
+
useCases: ['Checkout page']
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
|
|
520
|
+
"product_details": {
|
|
521
|
+
type: "product_details",
|
|
522
|
+
label: "Product Details",
|
|
523
|
+
icon: "Tag",
|
|
524
|
+
initialContent: {} as ProductDetailsBlockContent,
|
|
525
|
+
editorComponentFilename: "ProductDetailsBlockEditor.tsx",
|
|
526
|
+
rendererComponentFilename: "ProductDetailsBlockRenderer.tsx",
|
|
527
|
+
schema: ProductDetailsBlockSchema,
|
|
528
|
+
documentation: {
|
|
529
|
+
description: 'Displays product details (Title, Price, Add to Cart) using context.',
|
|
530
|
+
useCases: ['Product Template Page']
|
|
531
|
+
}
|
|
532
|
+
},
|
|
476
533
|
};
|
|
477
534
|
|
|
478
535
|
|
|
@@ -482,8 +539,11 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
482
539
|
* @param blockType - The type of block to get the definition for
|
|
483
540
|
* @returns The block definition or undefined if not found
|
|
484
541
|
*/
|
|
485
|
-
export function getBlockDefinition(blockType:
|
|
486
|
-
|
|
542
|
+
export function getBlockDefinition(blockType: string): BlockDefinition | undefined {
|
|
543
|
+
if (blockType in blockRegistry) {
|
|
544
|
+
return blockRegistry[blockType as BlockType];
|
|
545
|
+
}
|
|
546
|
+
return undefined;
|
|
487
547
|
}
|
|
488
548
|
|
|
489
549
|
/**
|
|
@@ -492,8 +552,11 @@ export function getBlockDefinition(blockType: BlockType): BlockDefinition | unde
|
|
|
492
552
|
* @param blockType - The type of block to get initial content for
|
|
493
553
|
* @returns The initial content object or undefined if block type not found
|
|
494
554
|
*/
|
|
495
|
-
export function getInitialContent(blockType:
|
|
496
|
-
|
|
555
|
+
export function getInitialContent(blockType: string): object | undefined {
|
|
556
|
+
if (blockType in blockRegistry) {
|
|
557
|
+
return blockRegistry[blockType as BlockType]?.initialContent;
|
|
558
|
+
}
|
|
559
|
+
return {};
|
|
497
560
|
}
|
|
498
561
|
|
|
499
562
|
/**
|
|
@@ -502,8 +565,14 @@ export function getInitialContent(blockType: BlockType): object | undefined {
|
|
|
502
565
|
* @param blockType - The type of block to get the label for
|
|
503
566
|
* @returns The user-friendly label or undefined if block type not found
|
|
504
567
|
*/
|
|
505
|
-
export function getBlockLabel(blockType:
|
|
506
|
-
|
|
568
|
+
export function getBlockLabel(blockType: string): string | undefined {
|
|
569
|
+
if (blockType in blockRegistry) {
|
|
570
|
+
return blockRegistry[blockType as BlockType]?.label;
|
|
571
|
+
}
|
|
572
|
+
return blockType
|
|
573
|
+
.split(/[-_]+/)
|
|
574
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
575
|
+
.join(" ");
|
|
507
576
|
}
|
|
508
577
|
|
|
509
578
|
/**
|
|
@@ -512,8 +581,8 @@ export function getBlockLabel(blockType: BlockType): string | undefined {
|
|
|
512
581
|
* @param blockType - The block type to validate
|
|
513
582
|
* @returns True if the block type exists in the registry
|
|
514
583
|
*/
|
|
515
|
-
export function isValidBlockType(blockType: string):
|
|
516
|
-
return blockType in blockRegistry;
|
|
584
|
+
export function isValidBlockType(blockType: string): boolean {
|
|
585
|
+
return blockType in blockRegistry || /^[a-z0-9_-]+$/.test(blockType);
|
|
517
586
|
}
|
|
518
587
|
|
|
519
588
|
/**
|
|
@@ -522,8 +591,11 @@ export function isValidBlockType(blockType: string): blockType is BlockType {
|
|
|
522
591
|
* @param blockType - The type of block to get the schema for
|
|
523
592
|
* @returns The Zod schema object or undefined if not found
|
|
524
593
|
*/
|
|
525
|
-
export function getBlockSchema(blockType:
|
|
526
|
-
|
|
594
|
+
export function getBlockSchema(blockType: string): z.ZodType<any> | undefined {
|
|
595
|
+
if (blockType in blockRegistry) {
|
|
596
|
+
return blockRegistry[blockType as BlockType]?.schema;
|
|
597
|
+
}
|
|
598
|
+
return z.record(z.string(), z.any());
|
|
527
599
|
}
|
|
528
600
|
|
|
529
601
|
/**
|
|
@@ -532,8 +604,13 @@ export function getBlockSchema(blockType: BlockType): z.ZodType<any> | undefined
|
|
|
532
604
|
* @param blockType - The type of block to get documentation for
|
|
533
605
|
* @returns The documentation object or undefined if not found
|
|
534
606
|
*/
|
|
535
|
-
export function getBlockDocumentation(blockType:
|
|
536
|
-
|
|
607
|
+
export function getBlockDocumentation(blockType: string): BlockDefinition['documentation'] | undefined {
|
|
608
|
+
if (blockType in blockRegistry) {
|
|
609
|
+
return blockRegistry[blockType as BlockType]?.documentation;
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
description: "Custom user-defined block layout component",
|
|
613
|
+
};
|
|
537
614
|
}
|
|
538
615
|
|
|
539
616
|
/**
|
|
@@ -549,10 +626,15 @@ export type AllBlockContent =
|
|
|
549
626
|
| ({ type: "button" } & ButtonBlockContent)
|
|
550
627
|
| ({ type: "posts_grid" } & PostsGridBlockContent)
|
|
551
628
|
| ({ type: "section" } & SectionBlockContent)
|
|
552
|
-
|
|
629
|
+
|
|
553
630
|
| ({ type: "video_embed" } & VideoEmbedBlockContent)
|
|
554
631
|
| ({ type: "form" } & FormBlockContent)
|
|
555
|
-
| ({ type: "testimonial" } & TestimonialBlockContent)
|
|
632
|
+
| ({ type: "testimonial" } & TestimonialBlockContent)
|
|
633
|
+
| ({ type: "product_grid" } & ProductGridBlockContent)
|
|
634
|
+
| ({ type: "featured_product" } & FeaturedProductBlockContent)
|
|
635
|
+
| ({ type: "cart" } & CartBlockContent)
|
|
636
|
+
| ({ type: "checkout" } & CheckoutBlockContent)
|
|
637
|
+
| ({ type: "product_details" } & ProductDetailsBlockContent);
|
|
556
638
|
|
|
557
639
|
/**
|
|
558
640
|
* Validate block content against its schema
|
|
@@ -581,7 +663,7 @@ export function validateBlockContent(
|
|
|
581
663
|
return { isValid: true, errors: [], warnings: [] };
|
|
582
664
|
} else {
|
|
583
665
|
// Format Zod errors
|
|
584
|
-
const errors = result.error.
|
|
666
|
+
const errors = result.error.issues.map(e => {
|
|
585
667
|
const path = e.path.join('.');
|
|
586
668
|
return path ? `${path}: ${e.message}` : e.message;
|
|
587
669
|
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const availableBlockTypes = [
|
|
2
|
+
"text",
|
|
3
|
+
"heading",
|
|
4
|
+
"image",
|
|
5
|
+
"button",
|
|
6
|
+
"posts_grid",
|
|
7
|
+
"video_embed",
|
|
8
|
+
"section",
|
|
9
|
+
"form",
|
|
10
|
+
"testimonial",
|
|
11
|
+
"product_grid",
|
|
12
|
+
"featured_product",
|
|
13
|
+
"cart",
|
|
14
|
+
"checkout",
|
|
15
|
+
"product_details",
|
|
16
|
+
] as const;
|
|
17
|
+
|
|
18
|
+
export type BlockType = (typeof availableBlockTypes)[number];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from '../zod-config';
|
|
2
|
+
|
|
3
|
+
// Product Grid Block Schema
|
|
4
|
+
export const ProductGridBlockSchema = z.object({
|
|
5
|
+
type: z.enum(['latest', 'category']).default('latest'),
|
|
6
|
+
categoryId: z.string().optional(),
|
|
7
|
+
limit: z.number().min(1).max(20).default(6),
|
|
8
|
+
title: z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
export type ProductGridBlockContent = z.infer<typeof ProductGridBlockSchema>;
|
|
11
|
+
|
|
12
|
+
// Featured Product Block Schema
|
|
13
|
+
export const FeaturedProductBlockSchema = z.object({
|
|
14
|
+
productId: z.string().min(1, 'Product is required'),
|
|
15
|
+
showBackground: z.boolean().default(false),
|
|
16
|
+
imagePosition: z.enum(['left', 'right']).default('left'),
|
|
17
|
+
});
|
|
18
|
+
export type FeaturedProductBlockContent = z.infer<typeof FeaturedProductBlockSchema>;
|
|
19
|
+
|
|
20
|
+
// Cart Block Schema
|
|
21
|
+
export const CartBlockSchema = z.object({});
|
|
22
|
+
export type CartBlockContent = z.infer<typeof CartBlockSchema>;
|
|
23
|
+
|
|
24
|
+
// Checkout Block Schema
|
|
25
|
+
export const CheckoutBlockSchema = z.object({});
|
|
26
|
+
export type CheckoutBlockContent = z.infer<typeof CheckoutBlockSchema>;
|
|
27
|
+
|
|
28
|
+
// Product Details Block Schema (Context Aware)
|
|
29
|
+
export const ProductDetailsBlockSchema = z.object({});
|
|
30
|
+
export type ProductDetailsBlockContent = z.infer<typeof ProductDetailsBlockSchema>;
|
|
31
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getCsvHeaders,
|
|
5
|
+
getTemplateCsv,
|
|
6
|
+
majorToMinor,
|
|
7
|
+
makeUniqueSku,
|
|
8
|
+
makeUniqueSlug,
|
|
9
|
+
minorToMajor,
|
|
10
|
+
normalizeBlocksFromFields,
|
|
11
|
+
parseCsv,
|
|
12
|
+
stringifyCsv,
|
|
13
|
+
} from "./csv";
|
|
14
|
+
|
|
15
|
+
describe("cms transfer csv helpers", () => {
|
|
16
|
+
it("builds templates with the expected content columns", () => {
|
|
17
|
+
expect(getCsvHeaders("pages")).toContain("blocks_json");
|
|
18
|
+
expect(getCsvHeaders("products")).toContain("description_html");
|
|
19
|
+
expect(getCsvHeaders("products")).toContain("description_blocks_json");
|
|
20
|
+
expect(getTemplateCsv("products")).toContain("EXAMPLE-SKU");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("round-trips JSON columns through CSV escaping", () => {
|
|
24
|
+
const csv = stringifyCsv(
|
|
25
|
+
[
|
|
26
|
+
{
|
|
27
|
+
language_code: "en",
|
|
28
|
+
title: "Landing",
|
|
29
|
+
blocks_json: JSON.stringify([
|
|
30
|
+
{ block_type: "text", content: { html_content: "<p>Hello, world</p>" }, order: 0 },
|
|
31
|
+
]),
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
["language_code", "title", "blocks_json"]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const parsed = parseCsv(csv);
|
|
38
|
+
|
|
39
|
+
expect(parsed.errors).toEqual([]);
|
|
40
|
+
expect(parsed.rows[0].blocks_json).toContain("html_content");
|
|
41
|
+
expect(JSON.parse(parsed.rows[0].blocks_json)).toHaveLength(1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("converts plain HTML into a text block fallback", () => {
|
|
45
|
+
const errors: Array<{ row: number; message: string }> = [];
|
|
46
|
+
const blocks = normalizeBlocksFromFields({
|
|
47
|
+
html: "<p>Imported description</p>",
|
|
48
|
+
languageId: 1,
|
|
49
|
+
rowNumber: 2,
|
|
50
|
+
errors,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
expect(errors).toEqual([]);
|
|
54
|
+
expect(blocks).toEqual([
|
|
55
|
+
{
|
|
56
|
+
language_id: 1,
|
|
57
|
+
block_type: "text",
|
|
58
|
+
content: { html_content: "<p>Imported description</p>" },
|
|
59
|
+
order: 0,
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("generates unique slugs and SKUs for create-new imports", () => {
|
|
65
|
+
expect(makeUniqueSlug("Example Page", new Set(["example-page"]))).toBe(
|
|
66
|
+
"example-page-copy"
|
|
67
|
+
);
|
|
68
|
+
expect(makeUniqueSku("sku-1", new Set(["SKU-1", "SKU-1-COPY"]))).toBe(
|
|
69
|
+
"SKU-1-COPY-2"
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("converts product prices between major and minor units", () => {
|
|
74
|
+
expect(majorToMinor(19.99)).toBe(1999);
|
|
75
|
+
expect(minorToMajor(1999)).toBe(19.99);
|
|
76
|
+
});
|
|
77
|
+
});
|