create-nextblock 0.15.5 → 0.15.9
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/package.json +50 -26
- package/templates/nextblock-template/app/ToasterProvider.tsx +26 -17
- package/templates/nextblock-template/app/actions/contactSellerActions.test.ts +280 -0
- package/templates/nextblock-template/app/actions/contactSellerActions.ts +222 -0
- package/templates/nextblock-template/app/actions/email-retry.test.ts +62 -0
- package/templates/nextblock-template/app/actions/email.ts +241 -110
- package/templates/nextblock-template/app/actions/formActions.ts +245 -116
- package/templates/nextblock-template/app/actions/interactions.ts +489 -396
- package/templates/nextblock-template/app/actions/threadActions.ts +166 -0
- package/templates/nextblock-template/app/api/checkout/route.ts +162 -146
- package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +14 -0
- package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +664 -1
- package/templates/nextblock-template/app/checkout/page.tsx +57 -52
- package/templates/nextblock-template/app/cms/CmsClientLayout.tsx +552 -529
- package/templates/nextblock-template/app/cms/blocks/editors/FormBlockEditor.tsx +304 -181
- package/templates/nextblock-template/app/cms/components/ContactReminderBanner.tsx +75 -0
- package/templates/nextblock-template/app/cms/components/PaymentsReminderBanner.tsx +58 -0
- package/templates/nextblock-template/app/cms/components/VisibilityControl.tsx +542 -528
- package/templates/nextblock-template/app/cms/inquiries/actions.ts +66 -0
- package/templates/nextblock-template/app/cms/inquiries/page.tsx +12 -0
- package/templates/nextblock-template/app/cms/interactions/page.tsx +12 -51
- package/templates/nextblock-template/app/cms/layout.tsx +101 -73
- package/templates/nextblock-template/app/cms/messages/MessagesClient.tsx +661 -0
- package/templates/nextblock-template/app/cms/messages/actions.ts +404 -0
- package/templates/nextblock-template/app/cms/messages/loadInbox.ts +333 -0
- package/templates/nextblock-template/app/cms/messages/page.tsx +87 -0
- package/templates/nextblock-template/app/cms/messages/require-admin.ts +37 -0
- package/templates/nextblock-template/app/cms/products/[id]/edit/page.tsx +370 -362
- package/templates/nextblock-template/app/cms/revisions/service.ts +20 -0
- package/templates/nextblock-template/app/cms/settings/email/components/EmailForm.tsx +227 -185
- package/templates/nextblock-template/app/layout.tsx +671 -667
- package/templates/nextblock-template/app/lib/seo.ts +319 -311
- package/templates/nextblock-template/app/product/[slug]/page.tsx +502 -482
- package/templates/nextblock-template/app/providers.tsx +96 -96
- package/templates/nextblock-template/app/thread/ThreadView.tsx +164 -0
- package/templates/nextblock-template/app/thread/[token]/route.ts +57 -0
- package/templates/nextblock-template/app/thread/layout.tsx +15 -0
- package/templates/nextblock-template/app/thread/page.tsx +98 -0
- package/templates/nextblock-template/components/BlockRenderer.tsx +312 -296
- package/templates/nextblock-template/components/ContactSellerSection.tsx +188 -0
- package/templates/nextblock-template/components/PostCommentsSection.tsx +378 -369
- package/templates/nextblock-template/components/ProductReviewsSection.tsx +426 -419
- package/templates/nextblock-template/components/StaffReplies.tsx +102 -0
- package/templates/nextblock-template/components/blocks/renderers/CartBlockRenderer.tsx +18 -17
- package/templates/nextblock-template/components/blocks/renderers/CheckoutBlockRenderer.tsx +20 -19
- package/templates/nextblock-template/components/blocks/renderers/FeaturedProductBlockRenderer.tsx +25 -22
- package/templates/nextblock-template/components/blocks/renderers/FormBlockRenderer.tsx +385 -381
- package/templates/nextblock-template/components/blocks/renderers/ProductDetailsBlockRenderer.tsx +157 -92
- package/templates/nextblock-template/components/blocks/renderers/ProductGridBlockRenderer.tsx +34 -31
- package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +612 -600
- package/templates/nextblock-template/components/commerce/PaymentReadinessBoundary.tsx +32 -0
- package/templates/nextblock-template/docs/05-DEVELOPER-GUIDE.md +25 -19
- package/templates/nextblock-template/docs/06-CLI-AND-SCAFFOLDING.md +1 -1
- package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +2 -2
- package/templates/nextblock-template/docs/12-VERCEL-DEPLOYMENT.md +32 -9
- package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +309 -0
- package/templates/nextblock-template/docs/README.md +42 -41
- package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +540 -542
- package/templates/nextblock-template/docs/assets/lighthouse-scores.png +0 -0
- package/templates/nextblock-template/lib/blocks/blockColors.test.ts +22 -2
- package/templates/nextblock-template/lib/blocks/blockColors.ts +44 -1
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +761 -753
- package/templates/nextblock-template/lib/cms/contact-reminder.ts +64 -0
- package/templates/nextblock-template/lib/cms/payments-reminder.ts +98 -0
- package/templates/nextblock-template/lib/cms/unread-messages.ts +42 -0
- package/templates/nextblock-template/lib/commerce/seller-contact.ts +162 -0
- package/templates/nextblock-template/lib/config/email-settings.ts +323 -254
- package/templates/nextblock-template/lib/config/email-tls.test.ts +57 -0
- package/templates/nextblock-template/lib/email/placeholder-address.test.ts +59 -0
- package/templates/nextblock-template/lib/email/placeholder-address.ts +39 -0
- package/templates/nextblock-template/lib/messages/thread-reference.test.ts +70 -0
- package/templates/nextblock-template/lib/messages/thread-token.test.ts +93 -0
- package/templates/nextblock-template/lib/messages/thread-token.ts +157 -0
- package/templates/nextblock-template/lib/messages/threads.ts +579 -0
- package/templates/nextblock-template/lib/setup/migrations-bundle.ts +20 -0
- package/templates/nextblock-template/lib/site-url.test.ts +89 -0
- package/templates/nextblock-template/lib/site-url.ts +102 -48
- package/templates/nextblock-template/package.json +14 -1
- package/templates/nextblock-template/public/assets/nextblock-banner.jpg +0 -0
|
Binary file
|
|
@@ -39,12 +39,26 @@ describe('resolveTextColor', () => {
|
|
|
39
39
|
expect(resolveTextColor(undefined)).toEqual({});
|
|
40
40
|
expect(resolveTextColor(null)).toEqual({});
|
|
41
41
|
expect(resolveTextColor('')).toEqual({});
|
|
42
|
-
expect(resolveTextColor('
|
|
42
|
+
expect(resolveTextColor('notacolour')).toEqual({});
|
|
43
43
|
expect(resolveTextColor('javascript:alert(1)')).toEqual({});
|
|
44
44
|
expect(resolveTextColor('url(https://evil.test/x.png)')).toEqual({});
|
|
45
|
+
// A valid name with anything appended is not a name — this is the injection case,
|
|
46
|
+
// and it must stay rejected even though `red` on its own is now accepted.
|
|
45
47
|
expect(resolveTextColor('red; background: url(x)')).toEqual({});
|
|
46
48
|
});
|
|
47
49
|
|
|
50
|
+
it('accepts CSS named colours, which seeded and AI-authored content actually uses', () => {
|
|
51
|
+
// The seeded contact-page heading is `textColor: "white"`. It matched neither a
|
|
52
|
+
// token nor the hex/rgb/hsl pattern, so it resolved to {} and the white-on-dark hero
|
|
53
|
+
// rendered dark-on-dark with nothing reporting a problem.
|
|
54
|
+
expect(resolveTextColor('white')).toEqual({ style: { color: 'white' } });
|
|
55
|
+
expect(resolveTextColor('Black')).toEqual({ style: { color: 'Black' } });
|
|
56
|
+
expect(resolveTextColor(' transparent ')).toEqual({ style: { color: 'transparent' } });
|
|
57
|
+
|
|
58
|
+
// Still distinguishable from a theme token, which resolves to a class instead.
|
|
59
|
+
expect(resolveTextColor('accent')).toEqual({ className: 'text-accent' });
|
|
60
|
+
});
|
|
61
|
+
|
|
48
62
|
it('never emits an interpolated class name', () => {
|
|
49
63
|
for (const token of TEXT_COLOR_TOKENS) {
|
|
50
64
|
const { className } = resolveTextColor(token);
|
|
@@ -73,7 +87,11 @@ describe('guards', () => {
|
|
|
73
87
|
expect(isTextColorToken('accent')).toBe(true);
|
|
74
88
|
expect(isTextColorToken('#FFF')).toBe(false);
|
|
75
89
|
expect(isCustomCssColor('#FFF')).toBe(true);
|
|
90
|
+
expect(isCustomCssColor('white')).toBe(true);
|
|
91
|
+
// A theme token is not a literal colour: the two share one field and are told apart
|
|
92
|
+
// only here, so this must keep answering false.
|
|
76
93
|
expect(isCustomCssColor('accent')).toBe(false);
|
|
94
|
+
expect(isCustomCssColor('notacolour')).toBe(false);
|
|
77
95
|
});
|
|
78
96
|
});
|
|
79
97
|
|
|
@@ -103,7 +121,9 @@ describe('HeadingBlockSchema.textColor', () => {
|
|
|
103
121
|
});
|
|
104
122
|
|
|
105
123
|
it('rejects values that are neither a token nor a colour', () => {
|
|
106
|
-
|
|
124
|
+
// 'red' was in this list only because named colours used to be rejected wholesale.
|
|
125
|
+
// It is a real colour and is now accepted; the genuinely invalid values stay here.
|
|
126
|
+
for (const bad of ['nonsense', 'url(x)', 'red; background: url(x)', '']) {
|
|
107
127
|
expect(HeadingBlockSchema.safeParse({ ...base, textColor: bad }).success).toBe(false);
|
|
108
128
|
}
|
|
109
129
|
});
|
|
@@ -82,12 +82,55 @@ export const TEXT_COLOR_TOKEN_OPTIONS = TEXT_COLOR_TOKENS.map((token) => ({
|
|
|
82
82
|
export const CSS_COLOR_PATTERN =
|
|
83
83
|
/^(#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})|rgba?\([^)]+\)|hsla?\([^)]+\))$/i;
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* CSS named colours, which the picker never emits but hand-authored and AI-authored
|
|
87
|
+
* content does.
|
|
88
|
+
*
|
|
89
|
+
* The seeded contact page sets `textColor: "white"` on its heading. That is perfectly
|
|
90
|
+
* valid CSS, but it matched neither a theme token nor the literal pattern above, so
|
|
91
|
+
* `resolveTextColor` returned `{}` and the heading quietly inherited the dark default —
|
|
92
|
+
* a white-on-dark hero rendering dark-on-dark, with nothing anywhere reporting a problem.
|
|
93
|
+
*
|
|
94
|
+
* Spelled out as a set rather than folded into the pattern as `[a-z]+`, because
|
|
95
|
+
* `isCustomCssColor` has to keep answering false for a theme token like `accent`: the
|
|
96
|
+
* two are stored in the same field and told apart only by these predicates.
|
|
97
|
+
*/
|
|
98
|
+
const CSS_NAMED_COLORS = new Set(
|
|
99
|
+
(
|
|
100
|
+
'aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue ' +
|
|
101
|
+
'blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk ' +
|
|
102
|
+
'crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki ' +
|
|
103
|
+
'darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen ' +
|
|
104
|
+
'darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue ' +
|
|
105
|
+
'dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite ' +
|
|
106
|
+
'gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki ' +
|
|
107
|
+
'lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan ' +
|
|
108
|
+
'lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen ' +
|
|
109
|
+
'lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen ' +
|
|
110
|
+
'magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen ' +
|
|
111
|
+
'mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream ' +
|
|
112
|
+
'mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid ' +
|
|
113
|
+
'palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum ' +
|
|
114
|
+
'powderblue purple rebeccapurple red rosybrown royalblue saddlebrown salmon sandybrown ' +
|
|
115
|
+
'seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen ' +
|
|
116
|
+
'steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow ' +
|
|
117
|
+
'yellowgreen transparent currentcolor'
|
|
118
|
+
).split(' ')
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
export function isCssNamedColor(value: unknown): value is string {
|
|
122
|
+
return typeof value === 'string' && CSS_NAMED_COLORS.has(value.trim().toLowerCase());
|
|
123
|
+
}
|
|
124
|
+
|
|
85
125
|
export function isTextColorToken(value: unknown): value is TextColorToken {
|
|
86
126
|
return typeof value === 'string' && (TEXT_COLOR_TOKENS as readonly string[]).includes(value);
|
|
87
127
|
}
|
|
88
128
|
|
|
89
129
|
export function isCustomCssColor(value: unknown): value is string {
|
|
90
|
-
return
|
|
130
|
+
return (
|
|
131
|
+
(typeof value === 'string' && CSS_COLOR_PATTERN.test(value.trim())) ||
|
|
132
|
+
isCssNamedColor(value)
|
|
133
|
+
);
|
|
91
134
|
}
|
|
92
135
|
|
|
93
136
|
export interface ResolvedTextColor {
|