create-nextblock 0.16.1 → 0.16.2
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/docker-template/.dockerignore +1 -1
- package/libs/db/tsconfig.lib.json +3 -3
- package/libs/editor/tsconfig.lib.json +3 -3
- package/libs/ui/tsconfig.lib.json +3 -3
- package/libs/utils/tsconfig.json +3 -3
- package/package.json +50 -50
- package/project.json +19 -19
- package/templates/nextblock-template/.dockerignore +1 -1
- package/templates/nextblock-template/.swcrc +30 -30
- package/templates/nextblock-template/AGENTS.md +9 -9
- package/templates/nextblock-template/CLAUDE.md +1 -1
- package/templates/nextblock-template/app/(auth-pages)/layout.tsx +9 -9
- package/templates/nextblock-template/app/(auth-pages)/post-sign-in/page.tsx +27 -27
- package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -16
- package/templates/nextblock-template/app/ToasterProvider.tsx +26 -26
- package/templates/nextblock-template/app/[slug]/pageClientActions.ts +7 -7
- package/templates/nextblock-template/app/actions/contactSellerActions.test.ts +280 -280
- package/templates/nextblock-template/app/actions/contactSellerActions.ts +222 -222
- package/templates/nextblock-template/app/actions/email-retry.test.ts +62 -62
- package/templates/nextblock-template/app/actions/email.ts +241 -241
- package/templates/nextblock-template/app/actions/formActions.ts +245 -245
- package/templates/nextblock-template/app/actions/interactions.ts +489 -489
- package/templates/nextblock-template/app/actions/threadActions.ts +166 -166
- package/templates/nextblock-template/app/actions/visibilityActions.ts +210 -210
- package/templates/nextblock-template/app/api/ai/seo/alt-text/route.ts +221 -221
- package/templates/nextblock-template/app/api/ai/seo/metadata/route.ts +186 -186
- package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -29
- package/templates/nextblock-template/app/api/checkout/route.ts +162 -162
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +3092 -3092
- package/templates/nextblock-template/app/api/mcp/route.ts +415 -415
- package/templates/nextblock-template/app/api/media/record/route.ts +160 -160
- package/templates/nextblock-template/app/api/search/route.ts +43 -43
- package/templates/nextblock-template/app/api/view/route.ts +114 -114
- package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -47
- package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -47
- package/templates/nextblock-template/app/auth/callback/route.ts +31 -31
- package/templates/nextblock-template/app/cart/page.tsx +7 -7
- package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -20
- package/templates/nextblock-template/app/checkout/page.tsx +57 -57
- package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +558 -558
- package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +241 -241
- package/templates/nextblock-template/app/cms/blocks/components/MediaLibraryModal.tsx +149 -149
- package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +304 -304
- package/templates/nextblock-template/app/cms/blocks/editors/ImageBlockEditor.tsx +406 -406
- package/templates/nextblock-template/app/cms/components/ContactReminderBanner.tsx +75 -75
- package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -23
- package/templates/nextblock-template/app/cms/components/CortexAiPageContext.tsx +58 -58
- package/templates/nextblock-template/app/cms/components/FeatureImageField.tsx +254 -254
- package/templates/nextblock-template/app/cms/components/FeedbackModal.tsx +36 -36
- package/templates/nextblock-template/app/cms/components/PaymentsReminderBanner.tsx +58 -58
- package/templates/nextblock-template/app/cms/components/VisibilityBadge.tsx +62 -62
- package/templates/nextblock-template/app/cms/components/VisibilityControl.tsx +542 -542
- package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -16
- package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -16
- package/templates/nextblock-template/app/cms/dashboard/actions.ts +228 -228
- package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -200
- package/templates/nextblock-template/app/cms/inquiries/actions.ts +66 -66
- package/templates/nextblock-template/app/cms/inquiries/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/interactions/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/layout.tsx +101 -101
- package/templates/nextblock-template/app/cms/media/components/FolderNavigator.tsx +273 -273
- package/templates/nextblock-template/app/cms/media/components/FolderTree.tsx +122 -122
- package/templates/nextblock-template/app/cms/media/components/MediaGridClient.tsx +69 -69
- package/templates/nextblock-template/app/cms/messages/MessagesClient.tsx +661 -661
- package/templates/nextblock-template/app/cms/messages/actions.ts +404 -404
- package/templates/nextblock-template/app/cms/messages/loadInbox.ts +333 -333
- package/templates/nextblock-template/app/cms/messages/page.tsx +87 -87
- package/templates/nextblock-template/app/cms/messages/require-admin.ts +37 -37
- package/templates/nextblock-template/app/cms/navigation/components/NavigationMenuDnd.tsx +3 -3
- package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +649 -649
- package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +618 -618
- package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +370 -370
- package/templates/nextblock-template/app/cms/products/attributes/page.tsx +12 -12
- package/templates/nextblock-template/app/cms/products/inventory/page.tsx +13 -13
- package/templates/nextblock-template/app/cms/products/productFormData.ts +133 -133
- package/templates/nextblock-template/app/cms/products/settings/page.tsx +5 -5
- package/templates/nextblock-template/app/cms/revisions/actions.ts +332 -332
- package/templates/nextblock-template/app/cms/revisions/service.test.ts +498 -498
- package/templates/nextblock-template/app/cms/revisions/service.ts +569 -569
- package/templates/nextblock-template/app/cms/revisions/utils.ts +304 -304
- package/templates/nextblock-template/app/cms/settings/cortex-ai/CortexAiSettingsClient.tsx +948 -948
- package/templates/nextblock-template/app/cms/settings/cortex-ai/McpServerSettingsCard.tsx +628 -628
- package/templates/nextblock-template/app/cms/settings/cortex-ai/mcp-actions.ts +230 -230
- package/templates/nextblock-template/app/cms/settings/cortex-ai/require-admin.ts +34 -34
- package/templates/nextblock-template/app/cms/settings/currencies/actions.ts +331 -331
- package/templates/nextblock-template/app/cms/settings/currencies/page.tsx +494 -494
- package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +227 -227
- package/templates/nextblock-template/app/cms/settings/extra-translations/ExtraTranslationsWorkspace.tsx +767 -767
- package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +276 -276
- package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +93 -93
- package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeEditor.tsx +382 -382
- package/templates/nextblock-template/app/cms/settings/global-css/components/ThemeManager.tsx +267 -267
- package/templates/nextblock-template/app/cms/settings/global-css/page.tsx +40 -40
- package/templates/nextblock-template/app/cms/settings/global-css/theme-actions.ts +259 -259
- package/templates/nextblock-template/app/cms/settings/logos/[id]/edit/page.tsx +7 -7
- package/templates/nextblock-template/app/cms/settings/logos/components/BrandingSettingsForm.tsx +339 -339
- package/templates/nextblock-template/app/cms/settings/logos/new/page.tsx +8 -8
- package/templates/nextblock-template/app/cms/settings/seo/RedirectsCard.tsx +514 -514
- package/templates/nextblock-template/app/cms/settings/seo/RobotsCard.tsx +529 -529
- package/templates/nextblock-template/app/cms/settings/seo/SeoSettingsClient.tsx +57 -57
- package/templates/nextblock-template/app/cms/settings/seo/actions.ts +448 -448
- package/templates/nextblock-template/app/cms/settings/seo/mappers.ts +93 -93
- package/templates/nextblock-template/app/cms/settings/seo/page.tsx +46 -46
- package/templates/nextblock-template/app/cms/settings/seo/require-admin.ts +47 -47
- package/templates/nextblock-template/app/cms/settings/site-scripts/page.tsx +51 -51
- package/templates/nextblock-template/app/cms/settings/taxes/page.tsx +21 -21
- package/templates/nextblock-template/app/cms/shipping/page.tsx +20 -20
- package/templates/nextblock-template/app/cms/users/components/DeleteUserButton.tsx +12 -12
- package/templates/nextblock-template/app/layout.tsx +671 -671
- package/templates/nextblock-template/app/lib/seo.ts +319 -319
- package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -190
- package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -56
- package/templates/nextblock-template/app/product/[slug]/page.tsx +502 -502
- package/templates/nextblock-template/app/profile/ProfilePageHeader.tsx +16 -16
- package/templates/nextblock-template/app/profile/ProfilePageMissingState.tsx +9 -9
- package/templates/nextblock-template/app/profile/account-links.ts +22 -22
- package/templates/nextblock-template/app/profile/orders/CustomerOrdersPageClient.tsx +124 -124
- package/templates/nextblock-template/app/profile/orders/page.tsx +19 -19
- package/templates/nextblock-template/app/profile/password/PasswordSettingsPageClient.tsx +128 -128
- package/templates/nextblock-template/app/profile/password/actions.ts +59 -59
- package/templates/nextblock-template/app/profile/password/page.tsx +27 -27
- package/templates/nextblock-template/app/providers.tsx +96 -96
- package/templates/nextblock-template/app/robots.ts +123 -123
- package/templates/nextblock-template/app/thread/ThreadView.tsx +164 -164
- package/templates/nextblock-template/app/thread/[token]/route.ts +57 -57
- package/templates/nextblock-template/app/thread/layout.tsx +15 -15
- package/templates/nextblock-template/app/thread/page.tsx +98 -98
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -38
- package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -68
- package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -35
- package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -34
- package/templates/nextblock-template/components/BlockRenderer.tsx +312 -312
- package/templates/nextblock-template/components/CartDrawerLoader.tsx +7 -7
- package/templates/nextblock-template/components/CartTranslator.tsx +210 -210
- package/templates/nextblock-template/components/ContactSellerSection.tsx +188 -188
- package/templates/nextblock-template/components/DeferredCartDrawer.tsx +23 -23
- package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -51
- package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -68
- package/templates/nextblock-template/components/DeferredGoogleTagManager.tsx +70 -70
- package/templates/nextblock-template/components/DeferredSpeedInsights.tsx +69 -69
- package/templates/nextblock-template/components/FooterNavigation.tsx +32 -32
- package/templates/nextblock-template/components/GlobalSearch.tsx +557 -557
- package/templates/nextblock-template/components/Header.tsx +38 -38
- package/templates/nextblock-template/components/HtmlScriptExecutor.tsx +47 -47
- package/templates/nextblock-template/components/LanguageSwitcher.tsx +2 -2
- package/templates/nextblock-template/components/PostCommentsSection.tsx +378 -378
- package/templates/nextblock-template/components/ProductReviewsSection.tsx +426 -426
- package/templates/nextblock-template/components/SiteScripts.tsx +56 -56
- package/templates/nextblock-template/components/StaffReplies.tsx +102 -102
- package/templates/nextblock-template/components/blocks/PostCardSkeleton.tsx +12 -12
- package/templates/nextblock-template/components/blocks/PostsGridBlock.tsx +12 -12
- package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +48 -48
- package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +9 -9
- package/templates/nextblock-template/components/blocks/ecommerceRendererLoaders.ts +23 -23
- package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -25
- package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -92
- package/templates/nextblock-template/components/blocks/renderers/CartBlockRenderer.tsx +18 -18
- package/templates/nextblock-template/components/blocks/renderers/CheckoutBlockRenderer.tsx +20 -20
- package/templates/nextblock-template/components/blocks/renderers/FeaturedProductBlockRenderer.tsx +25 -25
- package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +385 -385
- package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +24 -24
- package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +157 -157
- package/templates/nextblock-template/components/blocks/renderers/ProductGridBlockRenderer.tsx +34 -34
- package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +612 -612
- package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -57
- package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +2 -2
- package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +2 -2
- package/templates/nextblock-template/components/blocks/types.ts +7 -7
- package/templates/nextblock-template/components/commerce/PaymentReadinessBoundary.tsx +32 -32
- package/templates/nextblock-template/components/env-var-warning.tsx +3 -3
- package/templates/nextblock-template/components/form-message.tsx +32 -32
- package/templates/nextblock-template/components/seo/GenerateMetaButton.tsx +137 -137
- package/templates/nextblock-template/components/seo/PageSeoAuditSection.tsx +244 -244
- package/templates/nextblock-template/components/seo/SeoAuditPanel.tsx +749 -749
- package/templates/nextblock-template/components/seo/SeoIssueList.tsx +195 -195
- package/templates/nextblock-template/components/seo/SeoScoreDial.tsx +144 -144
- package/templates/nextblock-template/components/seo/SocialPreview.tsx +243 -243
- package/templates/nextblock-template/components/seo/SocialPreviewDialog.tsx +110 -110
- package/templates/nextblock-template/components/submit-button.tsx +23 -23
- package/templates/nextblock-template/components/theme-icon.tsx +78 -78
- package/templates/nextblock-template/components/theme-switcher.tsx +85 -85
- package/templates/nextblock-template/context/AuthContext.tsx +23 -23
- package/templates/nextblock-template/context/ThemeCatalogContext.tsx +44 -44
- package/templates/nextblock-template/docs/01-PROJECT-OVERVIEW.md +94 -94
- package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +77 -77
- package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +372 -372
- package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +309 -309
- package/templates/nextblock-template/docs/README.md +42 -42
- package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +12506 -12506
- package/templates/nextblock-template/hooks/use-hotkeys.ts +21 -21
- package/templates/nextblock-template/hooks/useGlobalSearch.ts +101 -101
- package/templates/nextblock-template/index.d.ts +7 -7
- package/templates/nextblock-template/lib/auth-redirects.ts +46 -46
- package/templates/nextblock-template/lib/blocks/blockColors.test.ts +134 -134
- package/templates/nextblock-template/lib/blocks/blockColors.ts +175 -175
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +761 -761
- package/templates/nextblock-template/lib/blocks/inlineScriptNonce.ts +20 -20
- package/templates/nextblock-template/lib/cms/contact-reminder.ts +64 -64
- package/templates/nextblock-template/lib/cms/payments-reminder.test.ts +135 -0
- package/templates/nextblock-template/lib/cms/payments-reminder.ts +30 -23
- package/templates/nextblock-template/lib/cms/unread-messages.ts +42 -42
- package/templates/nextblock-template/lib/commerce/seller-contact.ts +162 -162
- package/templates/nextblock-template/lib/config/email-settings.ts +323 -323
- package/templates/nextblock-template/lib/config/email-tls.test.ts +57 -57
- package/templates/nextblock-template/lib/cortex-ai/alt-text-request.ts +86 -86
- package/templates/nextblock-template/lib/cortex-ai/sandbox-headers.ts +60 -60
- package/templates/nextblock-template/lib/email/placeholder-address.test.ts +59 -59
- package/templates/nextblock-template/lib/email/placeholder-address.ts +39 -39
- package/templates/nextblock-template/lib/messages/thread-reference.test.ts +70 -70
- package/templates/nextblock-template/lib/messages/thread-token.test.ts +93 -93
- package/templates/nextblock-template/lib/messages/thread-token.ts +157 -157
- package/templates/nextblock-template/lib/messages/threads.ts +579 -579
- package/templates/nextblock-template/lib/posts/readTime.ts +60 -60
- package/templates/nextblock-template/lib/publishing/viewUrl.ts +26 -26
- package/templates/nextblock-template/lib/search/types.ts +27 -27
- package/templates/nextblock-template/lib/seo/alt-text-write-back.test.ts +154 -154
- package/templates/nextblock-template/lib/seo/alt-text-write-back.ts +109 -109
- package/templates/nextblock-template/lib/seo/block-content.ts +123 -123
- package/templates/nextblock-template/lib/seo/fix-prompts.test.ts +242 -242
- package/templates/nextblock-template/lib/seo/fix-prompts.ts +204 -204
- package/templates/nextblock-template/lib/seo/page-audit-context.tsx +140 -140
- package/templates/nextblock-template/lib/seo/page-document.test.ts +350 -350
- package/templates/nextblock-template/lib/seo/page-document.ts +412 -412
- package/templates/nextblock-template/lib/seo/redirect-store.test.ts +479 -479
- package/templates/nextblock-template/lib/seo/redirect-store.ts +466 -466
- package/templates/nextblock-template/lib/seo/robots-settings-signature.test.ts +102 -102
- package/templates/nextblock-template/lib/seo/robots-settings-signature.ts +41 -41
- package/templates/nextblock-template/lib/seo/robots-txt.test.ts +370 -370
- package/templates/nextblock-template/lib/seo/robots-txt.ts +510 -510
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +177 -177
- package/templates/nextblock-template/lib/site-scripts/revisions.ts +71 -71
- package/templates/nextblock-template/lib/site-scripts/types.ts +46 -46
- package/templates/nextblock-template/lib/site-url.test.ts +89 -89
- package/templates/nextblock-template/lib/site-url.ts +102 -102
- package/templates/nextblock-template/lib/themes/buildThemeCss.ts +124 -124
- package/templates/nextblock-template/lib/themes/tokenColor.ts +31 -31
- package/templates/nextblock-template/lib/themes/tokens.ts +143 -143
- package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -105
- package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -42
- package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -143
- package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -94
- package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -81
- package/templates/nextblock-template/lib/zod-config.ts +5 -5
- package/templates/nextblock-template/next-env.d.ts +1 -2
- package/templates/nextblock-template/package.json +1 -1
- package/templates/nextblock-template/postcss.config.js +6 -6
- package/templates/nextblock-template/scripts/backup.js +115 -115
- package/templates/nextblock-template/scripts/restore.js +385 -385
- package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -112
- package/templates/nextblock-template/tailwind.config.js +25 -25
- package/templates/nextblock-template/tools/build-migrate.mjs +102 -102
- package/templates/nextblock-template/tools/configure-supabase-auth.js +282 -282
- package/templates/nextblock-template/tools/deploy-supabase.js +159 -159
- package/templates/nextblock-template/tools/lib/migrate-core.mjs +569 -569
- package/templates/nextblock-template/tools/update.mjs +1303 -1303
- package/tsconfig.base.json +3 -3
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { createContext, useContext, useMemo, type ReactNode } from "react";
|
|
4
|
-
|
|
5
|
-
/** The switcher-facing shape of a row in `site_themes`. */
|
|
6
|
-
export interface ThemeCatalogEntry {
|
|
7
|
-
slug: string;
|
|
8
|
-
name: string;
|
|
9
|
-
/** lucide-react icon name. */
|
|
10
|
-
icon: string;
|
|
11
|
-
colorScheme: "light" | "dark";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Themes are read once on the server in app/layout.tsx and handed to the client
|
|
16
|
-
* through this context, so the switcher never fetches and never hardcodes a
|
|
17
|
-
* list. Falls back to the palette shipped in libs/ui/src/styles/theme.css when
|
|
18
|
-
* the table is empty or unreachable.
|
|
19
|
-
*/
|
|
20
|
-
export const FALLBACK_THEME_CATALOG: ThemeCatalogEntry[] = [
|
|
21
|
-
{ slug: "light", name: "Light", icon: "Sun", colorScheme: "light" },
|
|
22
|
-
{ slug: "dark", name: "Dark", icon: "Moon", colorScheme: "dark" },
|
|
23
|
-
{ slug: "vibrant", name: "Vibrant", icon: "Zap", colorScheme: "dark" },
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
const ThemeCatalogContext = createContext<ThemeCatalogEntry[]>(FALLBACK_THEME_CATALOG);
|
|
27
|
-
|
|
28
|
-
export function ThemeCatalogProvider({
|
|
29
|
-
themes,
|
|
30
|
-
children,
|
|
31
|
-
}: {
|
|
32
|
-
themes?: ThemeCatalogEntry[];
|
|
33
|
-
children: ReactNode;
|
|
34
|
-
}) {
|
|
35
|
-
const value = useMemo(
|
|
36
|
-
() => (Array.isArray(themes) && themes.length > 0 ? themes : FALLBACK_THEME_CATALOG),
|
|
37
|
-
[themes],
|
|
38
|
-
);
|
|
39
|
-
return <ThemeCatalogContext.Provider value={value}>{children}</ThemeCatalogContext.Provider>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function useThemeCatalog(): ThemeCatalogEntry[] {
|
|
43
|
-
return useContext(ThemeCatalogContext);
|
|
44
|
-
}
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useMemo, type ReactNode } from "react";
|
|
4
|
+
|
|
5
|
+
/** The switcher-facing shape of a row in `site_themes`. */
|
|
6
|
+
export interface ThemeCatalogEntry {
|
|
7
|
+
slug: string;
|
|
8
|
+
name: string;
|
|
9
|
+
/** lucide-react icon name. */
|
|
10
|
+
icon: string;
|
|
11
|
+
colorScheme: "light" | "dark";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Themes are read once on the server in app/layout.tsx and handed to the client
|
|
16
|
+
* through this context, so the switcher never fetches and never hardcodes a
|
|
17
|
+
* list. Falls back to the palette shipped in libs/ui/src/styles/theme.css when
|
|
18
|
+
* the table is empty or unreachable.
|
|
19
|
+
*/
|
|
20
|
+
export const FALLBACK_THEME_CATALOG: ThemeCatalogEntry[] = [
|
|
21
|
+
{ slug: "light", name: "Light", icon: "Sun", colorScheme: "light" },
|
|
22
|
+
{ slug: "dark", name: "Dark", icon: "Moon", colorScheme: "dark" },
|
|
23
|
+
{ slug: "vibrant", name: "Vibrant", icon: "Zap", colorScheme: "dark" },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const ThemeCatalogContext = createContext<ThemeCatalogEntry[]>(FALLBACK_THEME_CATALOG);
|
|
27
|
+
|
|
28
|
+
export function ThemeCatalogProvider({
|
|
29
|
+
themes,
|
|
30
|
+
children,
|
|
31
|
+
}: {
|
|
32
|
+
themes?: ThemeCatalogEntry[];
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
}) {
|
|
35
|
+
const value = useMemo(
|
|
36
|
+
() => (Array.isArray(themes) && themes.length > 0 ? themes : FALLBACK_THEME_CATALOG),
|
|
37
|
+
[themes],
|
|
38
|
+
);
|
|
39
|
+
return <ThemeCatalogContext.Provider value={value}>{children}</ThemeCatalogContext.Provider>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function useThemeCatalog(): ThemeCatalogEntry[] {
|
|
43
|
+
return useContext(ThemeCatalogContext);
|
|
44
|
+
}
|
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
# 01 Project Overview
|
|
2
|
-
|
|
3
|
-
## What NextBlock Is
|
|
4
|
-
|
|
5
|
-
NextBlock is an Nx monorepo centered on a Next.js 16 application
|
|
6
|
-
(`apps/nextblock`) backed by Supabase. The public site, authenticated CMS,
|
|
7
|
-
shared editor, shared database helpers, shared UI primitives, and CLI scaffold
|
|
8
|
-
all live in one workspace.
|
|
9
|
-
|
|
10
|
-
The repository currently contains:
|
|
11
|
-
|
|
12
|
-
- `apps/nextblock`: the canonical application. This is the runtime source of
|
|
13
|
-
truth for the public site, CMS, checkout routes, cron routes, and auth
|
|
14
|
-
callback behavior.
|
|
15
|
-
- `apps/create-nextblock`: the CLI that copies a sanitized template from the
|
|
16
|
-
source app and rewrites it for package-based distribution.
|
|
17
|
-
- `libs/db`: Supabase clients, package activation checks, generated database
|
|
18
|
-
types, and the migration tree under `libs/db/src/supabase/migrations`.
|
|
19
|
-
- `libs/editor`: the reusable Tiptap-based editor package used by the CMS and
|
|
20
|
-
by scaffolded projects.
|
|
21
|
-
- `libs/ecommerce`: the premium commerce package that provides storefront UI,
|
|
22
|
-
checkout providers, order handling, shipping, tax, currency, and CMS pages.
|
|
23
|
-
- `libs/sdk`: the block authoring contract used for typed extensibility.
|
|
24
|
-
- `libs/ui` and `libs/utils`: shared UI components, styles, and helper
|
|
25
|
-
utilities consumed throughout the workspace.
|
|
26
|
-
|
|
27
|
-
## Runtime Model
|
|
28
|
-
|
|
29
|
-
The `apps/nextblock/app` tree is split into a few clear surfaces:
|
|
30
|
-
|
|
31
|
-
- Public routes: `app/[slug]`, `app/article/[slug]`, `app/product/*`,
|
|
32
|
-
`app/cart`, `app/checkout`, and the shared public `app/layout.tsx`.
|
|
33
|
-
- Auth routes: `app/(auth-pages)/*` plus `app/auth/callback/route.ts`.
|
|
34
|
-
- CMS routes: `app/cms/*`.
|
|
35
|
-
- Operational routes: `app/api/checkout/route.ts`,
|
|
36
|
-
`app/api/webhooks/*`, `app/api/cron/*`, `robots.txt`, and `sitemap.xml`.
|
|
37
|
-
|
|
38
|
-
The public root layout loads shared UI and editor styles, resolves cached
|
|
39
|
-
layout data from Supabase, injects the storefront cart drawer, and reads the
|
|
40
|
-
storefront currency cookie. The CMS layout checks whether the ecommerce package
|
|
41
|
-
is active so the client-side CMS shell can show or hide store navigation.
|
|
42
|
-
|
|
43
|
-
## CMS and Public Site Split
|
|
44
|
-
|
|
45
|
-
The public application and CMS are not separate projects. They share the same
|
|
46
|
-
Next.js app and database, but expose different route groups and different
|
|
47
|
-
authorization requirements:
|
|
48
|
-
|
|
49
|
-
- Public content is driven by published pages, posts, navigation, products, and
|
|
50
|
-
translations stored in Supabase.
|
|
51
|
-
- CMS routes are guarded in the client layout and expect an authenticated user
|
|
52
|
-
whose profile role is `ADMIN` or `WRITER`.
|
|
53
|
-
- Commerce CMS routes such as products, orders, shipping, taxes, and payments
|
|
54
|
-
are only meaningful when the ecommerce package is active.
|
|
55
|
-
|
|
56
|
-
## Package Activation Gating
|
|
57
|
-
|
|
58
|
-
Premium functionality is gated through `package_activations` and
|
|
59
|
-
`verifyPackageOnline()` in `libs/db/src/lib/package-validation.ts`.
|
|
60
|
-
|
|
61
|
-
Today that gate is used directly in the app for things like:
|
|
62
|
-
|
|
63
|
-
- CMS ecommerce navigation visibility.
|
|
64
|
-
- The checkout API.
|
|
65
|
-
- Premium route wrappers and CLI module activation flows.
|
|
66
|
-
|
|
67
|
-
If a package gate and the actual route behavior disagree, the route file wins.
|
|
68
|
-
|
|
69
|
-
## Nx Workspace Shape
|
|
70
|
-
|
|
71
|
-
Nx is used for project graph management, builds, linting, Vite-based library
|
|
72
|
-
output, and Next.js app targets. A few practical notes matter when navigating
|
|
73
|
-
the repo:
|
|
74
|
-
|
|
75
|
-
- `nextblock` is the main application target.
|
|
76
|
-
- Public libraries such as `db`, `editor`, `sdk`, `ui`, and `utils` are normal
|
|
77
|
-
Nx projects.
|
|
78
|
-
- `ecommerce` is an Nx library tagged `scope:premium`.
|
|
79
|
-
- The scaffold template under
|
|
80
|
-
`apps/create-nextblock/templates/nextblock-template` is intentionally copied
|
|
81
|
-
output, not a normal Nx project.
|
|
82
|
-
|
|
83
|
-
## Where to Start
|
|
84
|
-
|
|
85
|
-
- For overall architecture: read [04-DATABASE-AND-AUTH.md](./04-DATABASE-AND-AUTH.md)
|
|
86
|
-
after this file.
|
|
87
|
-
- For day-to-day setup and commands: read
|
|
88
|
-
[05-DEVELOPER-GUIDE.md](./05-DEVELOPER-GUIDE.md).
|
|
89
|
-
- For CLI behavior and template sync: read
|
|
90
|
-
[06-CLI-AND-SCAFFOLDING.md](./06-CLI-AND-SCAFFOLDING.md).
|
|
91
|
-
- For editor and block work: read
|
|
92
|
-
[03-CMS-AND-EDITOR.md](./03-CMS-AND-EDITOR.md).
|
|
93
|
-
- For commerce work: read
|
|
94
|
-
[02-ECOMMERCE-CAPABILITIES.md](./02-ECOMMERCE-CAPABILITIES.md).
|
|
1
|
+
# 01 Project Overview
|
|
2
|
+
|
|
3
|
+
## What NextBlock Is
|
|
4
|
+
|
|
5
|
+
NextBlock is an Nx monorepo centered on a Next.js 16 application
|
|
6
|
+
(`apps/nextblock`) backed by Supabase. The public site, authenticated CMS,
|
|
7
|
+
shared editor, shared database helpers, shared UI primitives, and CLI scaffold
|
|
8
|
+
all live in one workspace.
|
|
9
|
+
|
|
10
|
+
The repository currently contains:
|
|
11
|
+
|
|
12
|
+
- `apps/nextblock`: the canonical application. This is the runtime source of
|
|
13
|
+
truth for the public site, CMS, checkout routes, cron routes, and auth
|
|
14
|
+
callback behavior.
|
|
15
|
+
- `apps/create-nextblock`: the CLI that copies a sanitized template from the
|
|
16
|
+
source app and rewrites it for package-based distribution.
|
|
17
|
+
- `libs/db`: Supabase clients, package activation checks, generated database
|
|
18
|
+
types, and the migration tree under `libs/db/src/supabase/migrations`.
|
|
19
|
+
- `libs/editor`: the reusable Tiptap-based editor package used by the CMS and
|
|
20
|
+
by scaffolded projects.
|
|
21
|
+
- `libs/ecommerce`: the premium commerce package that provides storefront UI,
|
|
22
|
+
checkout providers, order handling, shipping, tax, currency, and CMS pages.
|
|
23
|
+
- `libs/sdk`: the block authoring contract used for typed extensibility.
|
|
24
|
+
- `libs/ui` and `libs/utils`: shared UI components, styles, and helper
|
|
25
|
+
utilities consumed throughout the workspace.
|
|
26
|
+
|
|
27
|
+
## Runtime Model
|
|
28
|
+
|
|
29
|
+
The `apps/nextblock/app` tree is split into a few clear surfaces:
|
|
30
|
+
|
|
31
|
+
- Public routes: `app/[slug]`, `app/article/[slug]`, `app/product/*`,
|
|
32
|
+
`app/cart`, `app/checkout`, and the shared public `app/layout.tsx`.
|
|
33
|
+
- Auth routes: `app/(auth-pages)/*` plus `app/auth/callback/route.ts`.
|
|
34
|
+
- CMS routes: `app/cms/*`.
|
|
35
|
+
- Operational routes: `app/api/checkout/route.ts`,
|
|
36
|
+
`app/api/webhooks/*`, `app/api/cron/*`, `robots.txt`, and `sitemap.xml`.
|
|
37
|
+
|
|
38
|
+
The public root layout loads shared UI and editor styles, resolves cached
|
|
39
|
+
layout data from Supabase, injects the storefront cart drawer, and reads the
|
|
40
|
+
storefront currency cookie. The CMS layout checks whether the ecommerce package
|
|
41
|
+
is active so the client-side CMS shell can show or hide store navigation.
|
|
42
|
+
|
|
43
|
+
## CMS and Public Site Split
|
|
44
|
+
|
|
45
|
+
The public application and CMS are not separate projects. They share the same
|
|
46
|
+
Next.js app and database, but expose different route groups and different
|
|
47
|
+
authorization requirements:
|
|
48
|
+
|
|
49
|
+
- Public content is driven by published pages, posts, navigation, products, and
|
|
50
|
+
translations stored in Supabase.
|
|
51
|
+
- CMS routes are guarded in the client layout and expect an authenticated user
|
|
52
|
+
whose profile role is `ADMIN` or `WRITER`.
|
|
53
|
+
- Commerce CMS routes such as products, orders, shipping, taxes, and payments
|
|
54
|
+
are only meaningful when the ecommerce package is active.
|
|
55
|
+
|
|
56
|
+
## Package Activation Gating
|
|
57
|
+
|
|
58
|
+
Premium functionality is gated through `package_activations` and
|
|
59
|
+
`verifyPackageOnline()` in `libs/db/src/lib/package-validation.ts`.
|
|
60
|
+
|
|
61
|
+
Today that gate is used directly in the app for things like:
|
|
62
|
+
|
|
63
|
+
- CMS ecommerce navigation visibility.
|
|
64
|
+
- The checkout API.
|
|
65
|
+
- Premium route wrappers and CLI module activation flows.
|
|
66
|
+
|
|
67
|
+
If a package gate and the actual route behavior disagree, the route file wins.
|
|
68
|
+
|
|
69
|
+
## Nx Workspace Shape
|
|
70
|
+
|
|
71
|
+
Nx is used for project graph management, builds, linting, Vite-based library
|
|
72
|
+
output, and Next.js app targets. A few practical notes matter when navigating
|
|
73
|
+
the repo:
|
|
74
|
+
|
|
75
|
+
- `nextblock` is the main application target.
|
|
76
|
+
- Public libraries such as `db`, `editor`, `sdk`, `ui`, and `utils` are normal
|
|
77
|
+
Nx projects.
|
|
78
|
+
- `ecommerce` is an Nx library tagged `scope:premium`.
|
|
79
|
+
- The scaffold template under
|
|
80
|
+
`apps/create-nextblock/templates/nextblock-template` is intentionally copied
|
|
81
|
+
output, not a normal Nx project.
|
|
82
|
+
|
|
83
|
+
## Where to Start
|
|
84
|
+
|
|
85
|
+
- For overall architecture: read [04-DATABASE-AND-AUTH.md](./04-DATABASE-AND-AUTH.md)
|
|
86
|
+
after this file.
|
|
87
|
+
- For day-to-day setup and commands: read
|
|
88
|
+
[05-DEVELOPER-GUIDE.md](./05-DEVELOPER-GUIDE.md).
|
|
89
|
+
- For CLI behavior and template sync: read
|
|
90
|
+
[06-CLI-AND-SCAFFOLDING.md](./06-CLI-AND-SCAFFOLDING.md).
|
|
91
|
+
- For editor and block work: read
|
|
92
|
+
[03-CMS-AND-EDITOR.md](./03-CMS-AND-EDITOR.md).
|
|
93
|
+
- For commerce work: read
|
|
94
|
+
[02-ECOMMERCE-CAPABILITIES.md](./02-ECOMMERCE-CAPABILITIES.md).
|
|
@@ -200,80 +200,80 @@ contract lives in `libs/sdk` and is documented in
|
|
|
200
200
|
|
|
201
201
|
If you are changing how blocks work inside the CMS, start here. If you are
|
|
202
202
|
designing a reusable third-party block contract, start with the SDK doc.
|
|
203
|
-
|
|
204
|
-
## Themes and Colour
|
|
205
|
-
|
|
206
|
-
### Editable site themes
|
|
207
|
-
|
|
208
|
-
Themes are rows in `site_themes`, edited at **/cms/settings/global-css**. An
|
|
209
|
-
ADMIN can recolour any theme, create new ones, duplicate, reorder, hide, set the
|
|
210
|
-
site default, and delete non-system themes.
|
|
211
|
-
|
|
212
|
-
The pipeline is:
|
|
213
|
-
|
|
214
|
-
1. `app/layout.tsx` reads the table through a cached `getCachedSiteThemes()`
|
|
215
|
-
(tag `public-layout-site-themes`).
|
|
216
|
-
2. `lib/themes/buildThemeCss.ts` renders each row to a `:root.<slug> { ... }`
|
|
217
|
-
rule, injected as a `<style id="nb-theme-tokens">` in `<head>` — before the
|
|
218
|
-
Global CSS box, so custom CSS can still override a theme.
|
|
219
|
-
3. `app/providers.tsx` feeds the slug list and default to `next-themes`, and
|
|
220
|
-
`context/ThemeCatalogContext.tsx` carries names + icons to the switcher.
|
|
221
|
-
|
|
222
|
-
`libs/ui/src/styles/theme.css` remains as the fallback palette for standalone
|
|
223
|
-
consumers of the published `@nextblock-cms/ui` package. Generated rules use
|
|
224
|
-
`:root.<slug>` (specificity 0,2,0) so they always beat that file's `.dark` /
|
|
225
|
-
`.vibrant` rules (0,1,0) regardless of stylesheet order.
|
|
226
|
-
|
|
227
|
-
### Token storage
|
|
228
|
-
|
|
229
|
-
Colour tokens are stored as **bare HSL triplets** (`"222 47% 11%"`), not hex,
|
|
230
|
-
because `libs/ui/tailwind.config.js` composes them as `hsl(var(--primary))` and
|
|
231
|
-
appends alpha as `hsl(var(--primary) / 0.5)` — only a bare triplet supports
|
|
232
|
-
that. `lib/themes/tokenColor.ts` converts to and from the hex the colour picker
|
|
233
|
-
speaks. The allowed token list lives in `lib/themes/tokens.ts`; anything not on
|
|
234
|
-
it is dropped on save, and values are shape-checked, because the result is
|
|
235
|
-
interpolated into a `<style>` tag.
|
|
236
|
-
|
|
237
|
-
Per-theme `extra_css` is emitted **nested inside** the theme rule, so authors
|
|
238
|
-
write `& h1 { ... }` and scoping is automatic. `sanitizeExtraCss()` strips `<`
|
|
239
|
-
and unbalanced `}` so it cannot escape the rule or close the style element.
|
|
240
|
-
|
|
241
|
-
### Known limitation: `dark:` utilities under custom themes
|
|
242
|
-
|
|
243
|
-
Tailwind's dark variant compiles to `.dark`, and `darkMode: ['class']` is fixed
|
|
244
|
-
at build time. A custom theme with `color_scheme: 'dark'` recolours every token
|
|
245
|
-
and sets CSS `color-scheme`, but does **not** activate `dark:` utilities — the
|
|
246
|
-
same behaviour the shipped `.vibrant` theme has always had.
|
|
247
|
-
|
|
248
|
-
It cannot be fixed by mapping the theme to two classes: `next-themes` applies
|
|
249
|
-
its value with a single `classList.add(value)`, and `DOMTokenList.add` throws
|
|
250
|
-
`InvalidCharacterError` on a string containing a space. Wiring `dark:` to a data
|
|
251
|
-
attribute would require a pre-hydration script mirroring next-themes' own.
|
|
252
|
-
|
|
253
|
-
Verify the database → CSS path without booting the app:
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
npm run verify:site-themes
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### Block text colour
|
|
260
|
-
|
|
261
|
-
`apps/nextblock/lib/blocks/blockColors.ts` is the single source of truth for
|
|
262
|
-
block text colour, shared by `HeadingBlockRenderer`, `EditableBlock` and
|
|
263
|
-
`ColumnEditor` so the CMS preview cannot drift from the live page.
|
|
264
|
-
|
|
265
|
-
A stored value is either a **theme token** keyword (`"primary"` — follows the
|
|
266
|
-
theme) or a **literal CSS colour** (`"#FF8800"` — fixed). Tokens render as a
|
|
267
|
-
static Tailwind class; literals render as an inline `style`. `resolveTextColor()`
|
|
268
|
-
returns `{ className?, style? }` and falls back to `{}` for anything it does not
|
|
269
|
-
recognise, so a hand-edited value degrades to the inherited colour instead of
|
|
270
|
-
emitting a bogus class.
|
|
271
|
-
|
|
272
|
-
Class names here are written as **complete literals**. Tailwind v4 ignores the
|
|
273
|
-
`safelist` key in the legacy JS config — `libs/ui/tailwind.config.js` still
|
|
274
|
-
carries one, but v4 never reads it, so a class exists only if the scanner finds
|
|
275
|
-
the whole string in a source file.
|
|
276
|
-
|
|
277
|
-
The editor control is `ColorField` from `libs/ui`, which offers the theme tokens
|
|
278
|
-
and a custom picker (hex, alpha, screen eyedropper, recent colours) with a live
|
|
279
|
-
WCAG contrast badge measured against the section background.
|
|
203
|
+
|
|
204
|
+
## Themes and Colour
|
|
205
|
+
|
|
206
|
+
### Editable site themes
|
|
207
|
+
|
|
208
|
+
Themes are rows in `site_themes`, edited at **/cms/settings/global-css**. An
|
|
209
|
+
ADMIN can recolour any theme, create new ones, duplicate, reorder, hide, set the
|
|
210
|
+
site default, and delete non-system themes.
|
|
211
|
+
|
|
212
|
+
The pipeline is:
|
|
213
|
+
|
|
214
|
+
1. `app/layout.tsx` reads the table through a cached `getCachedSiteThemes()`
|
|
215
|
+
(tag `public-layout-site-themes`).
|
|
216
|
+
2. `lib/themes/buildThemeCss.ts` renders each row to a `:root.<slug> { ... }`
|
|
217
|
+
rule, injected as a `<style id="nb-theme-tokens">` in `<head>` — before the
|
|
218
|
+
Global CSS box, so custom CSS can still override a theme.
|
|
219
|
+
3. `app/providers.tsx` feeds the slug list and default to `next-themes`, and
|
|
220
|
+
`context/ThemeCatalogContext.tsx` carries names + icons to the switcher.
|
|
221
|
+
|
|
222
|
+
`libs/ui/src/styles/theme.css` remains as the fallback palette for standalone
|
|
223
|
+
consumers of the published `@nextblock-cms/ui` package. Generated rules use
|
|
224
|
+
`:root.<slug>` (specificity 0,2,0) so they always beat that file's `.dark` /
|
|
225
|
+
`.vibrant` rules (0,1,0) regardless of stylesheet order.
|
|
226
|
+
|
|
227
|
+
### Token storage
|
|
228
|
+
|
|
229
|
+
Colour tokens are stored as **bare HSL triplets** (`"222 47% 11%"`), not hex,
|
|
230
|
+
because `libs/ui/tailwind.config.js` composes them as `hsl(var(--primary))` and
|
|
231
|
+
appends alpha as `hsl(var(--primary) / 0.5)` — only a bare triplet supports
|
|
232
|
+
that. `lib/themes/tokenColor.ts` converts to and from the hex the colour picker
|
|
233
|
+
speaks. The allowed token list lives in `lib/themes/tokens.ts`; anything not on
|
|
234
|
+
it is dropped on save, and values are shape-checked, because the result is
|
|
235
|
+
interpolated into a `<style>` tag.
|
|
236
|
+
|
|
237
|
+
Per-theme `extra_css` is emitted **nested inside** the theme rule, so authors
|
|
238
|
+
write `& h1 { ... }` and scoping is automatic. `sanitizeExtraCss()` strips `<`
|
|
239
|
+
and unbalanced `}` so it cannot escape the rule or close the style element.
|
|
240
|
+
|
|
241
|
+
### Known limitation: `dark:` utilities under custom themes
|
|
242
|
+
|
|
243
|
+
Tailwind's dark variant compiles to `.dark`, and `darkMode: ['class']` is fixed
|
|
244
|
+
at build time. A custom theme with `color_scheme: 'dark'` recolours every token
|
|
245
|
+
and sets CSS `color-scheme`, but does **not** activate `dark:` utilities — the
|
|
246
|
+
same behaviour the shipped `.vibrant` theme has always had.
|
|
247
|
+
|
|
248
|
+
It cannot be fixed by mapping the theme to two classes: `next-themes` applies
|
|
249
|
+
its value with a single `classList.add(value)`, and `DOMTokenList.add` throws
|
|
250
|
+
`InvalidCharacterError` on a string containing a space. Wiring `dark:` to a data
|
|
251
|
+
attribute would require a pre-hydration script mirroring next-themes' own.
|
|
252
|
+
|
|
253
|
+
Verify the database → CSS path without booting the app:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
npm run verify:site-themes
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Block text colour
|
|
260
|
+
|
|
261
|
+
`apps/nextblock/lib/blocks/blockColors.ts` is the single source of truth for
|
|
262
|
+
block text colour, shared by `HeadingBlockRenderer`, `EditableBlock` and
|
|
263
|
+
`ColumnEditor` so the CMS preview cannot drift from the live page.
|
|
264
|
+
|
|
265
|
+
A stored value is either a **theme token** keyword (`"primary"` — follows the
|
|
266
|
+
theme) or a **literal CSS colour** (`"#FF8800"` — fixed). Tokens render as a
|
|
267
|
+
static Tailwind class; literals render as an inline `style`. `resolveTextColor()`
|
|
268
|
+
returns `{ className?, style? }` and falls back to `{}` for anything it does not
|
|
269
|
+
recognise, so a hand-edited value degrades to the inherited colour instead of
|
|
270
|
+
emitting a bogus class.
|
|
271
|
+
|
|
272
|
+
Class names here are written as **complete literals**. Tailwind v4 ignores the
|
|
273
|
+
`safelist` key in the legacy JS config — `libs/ui/tailwind.config.js` still
|
|
274
|
+
carries one, but v4 never reads it, so a class exists only if the scanner finds
|
|
275
|
+
the whole string in a source file.
|
|
276
|
+
|
|
277
|
+
The editor control is `ColorField` from `libs/ui`, which offers the theme tokens
|
|
278
|
+
and a custom picker (hex, alpha, screen eyedropper, recent colours) with a live
|
|
279
|
+
WCAG contrast badge measured against the section background.
|