create-nextblock 0.2.36 → 0.2.38
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 +30 -30
- package/templates/nextblock-template/app/cms/blocks/components/BlockEditorArea.tsx +1 -1
- package/templates/nextblock-template/app/cms/blocks/components/SectionConfigPanel.tsx +19 -1
- package/templates/nextblock-template/app/cms/blocks/editors/SectionBlockEditor.tsx +2 -0
- package/templates/nextblock-template/app/force-styles.tsx +31 -0
- package/templates/nextblock-template/app/globals.css +10 -432
- package/templates/nextblock-template/app/layout.tsx +0 -3
- package/templates/nextblock-template/components/ResponsiveNav.tsx +5 -1
- package/templates/nextblock-template/components/blocks/renderers/HeroBlockRenderer.tsx +10 -1
- package/templates/nextblock-template/components/blocks/renderers/SectionBlockRenderer.tsx +10 -1
- package/templates/nextblock-template/lib/blocks/blockRegistry.ts +13 -0
- package/templates/nextblock-template/package.json +54 -54
- package/templates/nextblock-template/public/images/NBcover.webp +0 -0
- package/templates/nextblock-template/tailwind.config.js +1 -1
- package/templates/nextblock-template/tsconfig.json +3 -2
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "create-nextblock",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"create-nextblock": "./bin/create-nextblock.js"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
-
"sync-template": "node ./scripts/sync-template.js",
|
|
12
|
-
"prepack": "npm run sync-template"
|
|
13
|
-
},
|
|
14
|
-
"keywords": [],
|
|
15
|
-
"author": "",
|
|
16
|
-
"license": "ISC",
|
|
17
|
-
"type": "module",
|
|
18
|
-
"dependencies": {
|
|
19
|
-
"@clack/prompts": "^0.8.1",
|
|
20
|
-
"@nextblock-cms/db": "latest",
|
|
21
|
-
"chalk": "^5.6.2",
|
|
22
|
-
"commander": "^14.0.1",
|
|
23
|
-
"execa": "^9.3.0",
|
|
24
|
-
"fs-extra": "^11.3.2",
|
|
25
|
-
"inquirer": "^12.10.0",
|
|
26
|
-
"open": "^10.1.0",
|
|
27
|
-
"ora": "^8.0.1",
|
|
28
|
-
"picocolors": "^1.1.1"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "create-nextblock",
|
|
3
|
+
"version": "0.2.38",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-nextblock": "./bin/create-nextblock.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"sync-template": "node ./scripts/sync-template.js",
|
|
12
|
+
"prepack": "npm run sync-template"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [],
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "ISC",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@clack/prompts": "^0.8.1",
|
|
20
|
+
"@nextblock-cms/db": "latest",
|
|
21
|
+
"chalk": "^5.6.2",
|
|
22
|
+
"commander": "^14.0.1",
|
|
23
|
+
"execa": "^9.3.0",
|
|
24
|
+
"fs-extra": "^11.3.2",
|
|
25
|
+
"inquirer": "^12.10.0",
|
|
26
|
+
"open": "^10.1.0",
|
|
27
|
+
"ora": "^8.0.1",
|
|
28
|
+
"picocolors": "^1.1.1"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -104,7 +104,7 @@ export default function BlockEditorArea({ parentId, parentType, initialBlocks, l
|
|
|
104
104
|
lastSavedBlocks.current = blocks;
|
|
105
105
|
} else {
|
|
106
106
|
// On failure, revert the UI to the last known good state
|
|
107
|
-
alert(
|
|
107
|
+
alert(`Failed to save changes: ${result.error}. Reverting.`);
|
|
108
108
|
setBlocks(lastSavedBlocks.current);
|
|
109
109
|
}
|
|
110
110
|
}, [parentId, parentType, blocks]);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// app/cms/blocks/components/SectionConfigPanel.tsx
|
|
2
1
|
"use client";
|
|
3
2
|
|
|
4
3
|
import React from 'react';
|
|
@@ -112,6 +111,25 @@ export default function SectionConfigPanel({ content, onChange }: SectionConfigP
|
|
|
112
111
|
</SelectContent>
|
|
113
112
|
</Select>
|
|
114
113
|
</div>
|
|
114
|
+
|
|
115
|
+
{/* Vertical Alignment */}
|
|
116
|
+
<div className="space-y-2">
|
|
117
|
+
<Label htmlFor="vertical-alignment">Vertical Alignment</Label>
|
|
118
|
+
<Select
|
|
119
|
+
value={content.vertical_alignment || 'start'}
|
|
120
|
+
onValueChange={(value: any) => onChange({ ...content, vertical_alignment: value })}
|
|
121
|
+
>
|
|
122
|
+
<SelectTrigger id="vertical-alignment">
|
|
123
|
+
<SelectValue placeholder="Select alignment" />
|
|
124
|
+
</SelectTrigger>
|
|
125
|
+
<SelectContent>
|
|
126
|
+
<SelectItem value="start">Top</SelectItem>
|
|
127
|
+
<SelectItem value="center">Center</SelectItem>
|
|
128
|
+
<SelectItem value="end">Bottom</SelectItem>
|
|
129
|
+
<SelectItem value="stretch">Stretch</SelectItem>
|
|
130
|
+
</SelectContent>
|
|
131
|
+
</Select>
|
|
132
|
+
</div>
|
|
115
133
|
</div>
|
|
116
134
|
|
|
117
135
|
{/* Background Configuration */}
|
|
@@ -52,6 +52,7 @@ export default function SectionBlockEditor({
|
|
|
52
52
|
responsive_columns: { mobile: 1, tablet: 2, desktop: 3 },
|
|
53
53
|
column_gap: "md",
|
|
54
54
|
padding: { top: "md", bottom: "md" },
|
|
55
|
+
vertical_alignment: "start",
|
|
55
56
|
column_blocks: [],
|
|
56
57
|
};
|
|
57
58
|
|
|
@@ -62,6 +63,7 @@ export default function SectionBlockEditor({
|
|
|
62
63
|
content.responsive_columns ?? defaults.responsive_columns,
|
|
63
64
|
column_gap: content.column_gap ?? defaults.column_gap,
|
|
64
65
|
padding: content.padding ?? defaults.padding,
|
|
66
|
+
vertical_alignment: content.vertical_alignment ?? defaults.vertical_alignment,
|
|
65
67
|
column_blocks: content.column_blocks ?? defaults.column_blocks,
|
|
66
68
|
};
|
|
67
69
|
}, [content]);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This component is never rendered but ensures that specific Tailwind classes
|
|
5
|
+
* used in the database seeds (SQL files) are generated in the CSS bundle.
|
|
6
|
+
*
|
|
7
|
+
* We are using this as a fallback because Tailwind's scanning of SQL files
|
|
8
|
+
* in the libs directory is proving unreliable on Windows.
|
|
9
|
+
*/
|
|
10
|
+
export default function ForceStyles() {
|
|
11
|
+
return (
|
|
12
|
+
<div className="hidden">
|
|
13
|
+
{/* Spacing & Layout */}
|
|
14
|
+
<div className="mt-10 p-8 p-10 p-12 gap-4"></div>
|
|
15
|
+
<div className="grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-8"></div>
|
|
16
|
+
|
|
17
|
+
{/* Text colors used in blocks */}
|
|
18
|
+
<div className="text-slate-200 text-slate-300 text-slate-400 text-slate-600 text-slate-900"></div>
|
|
19
|
+
<div className="dark:text-slate-200 dark:text-slate-400 dark:text-white"></div>
|
|
20
|
+
<div className="text-sm font-semibold text-center text-white"></div>
|
|
21
|
+
|
|
22
|
+
{/* Backgrounds and Borders */}
|
|
23
|
+
<div className="bg-white/5 bg-white/10 border-white/10 border-white/20"></div>
|
|
24
|
+
<div className="bg-slate-50 hover:bg-slate-100 dark:bg-white/5 dark:hover:bg-white/10"></div>
|
|
25
|
+
|
|
26
|
+
{/* Gradients */}
|
|
27
|
+
<div className="bg-gradient-to-r bg-gradient-to-br from-blue-400 to-cyan-400"></div>
|
|
28
|
+
<div className="from-blue-500/10 to-purple-500/10"></div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -1,436 +1,14 @@
|
|
|
1
|
-
@config "../../../../tailwind.config.js";
|
|
2
|
-
@import
|
|
3
|
-
@import
|
|
4
|
-
@import
|
|
5
|
-
/*─────────────────────────────────────────────────────────────────────────────
|
|
6
|
-
globals.css — complete rewrite
|
|
7
|
-
─────────────────────────────────────────────────────────────────────────────*/
|
|
8
|
-
/*─────────────────────────────────────────────────────────────────────────────
|
|
9
|
-
1. Critical CSS Resets (formerly in <style id="critical-css">)
|
|
10
|
-
─────────────────────────────────────────────────────────────────────────────*/
|
|
11
|
-
@layer base {
|
|
12
|
-
*, ::before, ::after {
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
border-width: 0;
|
|
15
|
-
border-style: solid;
|
|
16
|
-
border-color: hsl(var(--border));
|
|
17
|
-
}
|
|
18
|
-
::before, ::after {
|
|
19
|
-
--tw-content: "";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
html, :host {
|
|
23
|
-
line-height: 1.5;
|
|
24
|
-
-webkit-text-size-adjust: 100%;
|
|
25
|
-
-moz-tab-size: 4;
|
|
26
|
-
tab-size: 4;
|
|
27
|
-
font-family:
|
|
28
|
-
ui-sans-serif,
|
|
29
|
-
system-ui,
|
|
30
|
-
sans-serif,
|
|
31
|
-
"Apple Color Emoji",
|
|
32
|
-
"Segoe UI Emoji",
|
|
33
|
-
"Segoe UI Symbol",
|
|
34
|
-
"Noto Color Emoji";
|
|
35
|
-
font-feature-settings: normal;
|
|
36
|
-
font-variation-settings: normal;
|
|
37
|
-
-webkit-tap-highlight-color: transparent;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
body {
|
|
41
|
-
margin: 0;
|
|
42
|
-
line-height: inherit;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
hr {
|
|
46
|
-
height: 0;
|
|
47
|
-
color: inherit;
|
|
48
|
-
border-top-width: 1px;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
abbr:where([title]) {
|
|
52
|
-
-webkit-text-decoration: underline dotted;
|
|
53
|
-
text-decoration: underline dotted;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
h1, h2, h3, h4, h5, h6 {
|
|
57
|
-
font-size: inherit;
|
|
58
|
-
font-weight: inherit;
|
|
59
|
-
margin: 0;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
a {
|
|
63
|
-
color: inherit;
|
|
64
|
-
text-decoration: inherit;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
b, strong {
|
|
68
|
-
font-weight: bolder;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
code, kbd, pre, samp {
|
|
72
|
-
font-family:
|
|
73
|
-
ui-monospace,
|
|
74
|
-
SFMono-Regular,
|
|
75
|
-
Menlo,
|
|
76
|
-
Monaco,
|
|
77
|
-
Consolas,
|
|
78
|
-
"Liberation Mono",
|
|
79
|
-
"Courier New",
|
|
80
|
-
monospace;
|
|
81
|
-
font-feature-settings: normal;
|
|
82
|
-
font-variation-settings: normal;
|
|
83
|
-
font-size: 1em;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
small {
|
|
87
|
-
font-size: 80%;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
sub, sup {
|
|
91
|
-
font-size: 75%;
|
|
92
|
-
line-height: 0;
|
|
93
|
-
position: relative;
|
|
94
|
-
vertical-align: baseline;
|
|
95
|
-
}
|
|
96
|
-
sub { bottom: -0.25em; }
|
|
97
|
-
sup { top: -0.5em; }
|
|
98
|
-
|
|
99
|
-
table {
|
|
100
|
-
text-indent: 0;
|
|
101
|
-
border-color: inherit;
|
|
102
|
-
border-collapse: collapse;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
button,
|
|
106
|
-
input,
|
|
107
|
-
optgroup,
|
|
108
|
-
select,
|
|
109
|
-
textarea {
|
|
110
|
-
font-family: inherit;
|
|
111
|
-
font-feature-settings: inherit;
|
|
112
|
-
font-variation-settings: inherit;
|
|
113
|
-
font-size: 100%;
|
|
114
|
-
font-weight: inherit;
|
|
115
|
-
line-height: inherit;
|
|
116
|
-
letter-spacing: inherit;
|
|
117
|
-
color: inherit;
|
|
118
|
-
margin: 0;
|
|
119
|
-
padding: 0;
|
|
120
|
-
}
|
|
121
|
-
button, select {
|
|
122
|
-
text-transform: none;
|
|
123
|
-
}
|
|
124
|
-
button,
|
|
125
|
-
input[type="button"],
|
|
126
|
-
input[type="reset"],
|
|
127
|
-
input[type="submit"] {
|
|
128
|
-
-webkit-appearance: button;
|
|
129
|
-
background-color: transparent;
|
|
130
|
-
background-image: none;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
:-moz-focusring { outline: auto; }
|
|
134
|
-
:-moz-ui-invalid { box-shadow: none; }
|
|
135
|
-
progress { vertical-align: baseline; }
|
|
136
|
-
::-webkit-inner-spin-button,
|
|
137
|
-
::-webkit-outer-spin-button {
|
|
138
|
-
height: auto;
|
|
139
|
-
}
|
|
140
|
-
[type="search"] {
|
|
141
|
-
-webkit-appearance: textfield;
|
|
142
|
-
outline-offset: -2px;
|
|
143
|
-
}
|
|
144
|
-
::-webkit-search-decoration {
|
|
145
|
-
-webkit-appearance: none;
|
|
146
|
-
}
|
|
147
|
-
::-webkit-file-upload-button {
|
|
148
|
-
-webkit-appearance: button;
|
|
149
|
-
font: inherit;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
summary { display: list-item; }
|
|
153
|
-
blockquote, dd, dl, figure, p, pre { margin: 0; }
|
|
154
|
-
fieldset { margin: 0; padding: 0; }
|
|
155
|
-
legend { padding: 0; }
|
|
156
|
-
menu, ol, ul { list-style: none; margin: 0; padding: 0; }
|
|
157
|
-
dialog { padding: 0; }
|
|
158
|
-
textarea { resize: vertical; }
|
|
159
|
-
|
|
160
|
-
input::-moz-placeholder,
|
|
161
|
-
textarea::-moz-placeholder {
|
|
162
|
-
opacity: 1;
|
|
163
|
-
color: hsl(var(--muted-foreground));
|
|
164
|
-
}
|
|
165
|
-
input::placeholder,
|
|
166
|
-
textarea::placeholder {
|
|
167
|
-
opacity: 1;
|
|
168
|
-
color: hsl(var(--muted-foreground));
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
[role="button"], button { cursor: pointer; }
|
|
172
|
-
:disabled { cursor: default; }
|
|
173
|
-
|
|
174
|
-
audio,
|
|
175
|
-
canvas,
|
|
176
|
-
embed,
|
|
177
|
-
iframe,
|
|
178
|
-
img,
|
|
179
|
-
object,
|
|
180
|
-
svg,
|
|
181
|
-
video {
|
|
182
|
-
display: block;
|
|
183
|
-
vertical-align: middle;
|
|
184
|
-
}
|
|
185
|
-
img, video {
|
|
186
|
-
max-width: 100%;
|
|
187
|
-
height: auto;
|
|
188
|
-
}
|
|
189
|
-
[hidden] { display: none; }
|
|
190
|
-
|
|
191
|
-
/*───────────────────────────────────────────────────────────────────────────
|
|
192
|
-
2. Project-specific base styles (Tailwind-powered)
|
|
193
|
-
───────────────────────────────────────────────────────────────────────────*/
|
|
194
|
-
/* Apply your border color everywhere */
|
|
195
|
-
* {
|
|
196
|
-
border-color: hsl(var(--border));
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/* Body background & text */
|
|
200
|
-
body {
|
|
201
|
-
background-color: hsl(var(--background));
|
|
202
|
-
color: hsl(var(--foreground));
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/* Semantic headings */
|
|
206
|
-
ul,
|
|
207
|
-
ol {
|
|
208
|
-
padding-left: 1.5rem;
|
|
209
|
-
margin-bottom: 1rem;
|
|
210
|
-
}
|
|
211
|
-
li {
|
|
212
|
-
margin-bottom: 0.25rem;
|
|
213
|
-
}
|
|
214
|
-
blockquote {
|
|
215
|
-
padding: 1rem;
|
|
216
|
-
font-style: italic;
|
|
217
|
-
border-left-width: 4px;
|
|
218
|
-
border-left-style: solid;
|
|
219
|
-
border-left-color: hsl(var(--border));
|
|
220
|
-
background-color: hsl(var(--muted));
|
|
221
|
-
color: hsl(var(--muted-foreground));
|
|
222
|
-
margin-bottom: 1rem;
|
|
223
|
-
}
|
|
224
|
-
code {
|
|
225
|
-
background-color: hsl(var(--muted));
|
|
226
|
-
color: hsl(var(--muted-foreground));
|
|
227
|
-
padding: 0.25rem 0.25rem;
|
|
228
|
-
padding-top: 0.125rem;
|
|
229
|
-
padding-bottom: 0.125rem;
|
|
230
|
-
border-radius: 0.125rem;
|
|
231
|
-
font-family:
|
|
232
|
-
ui-monospace,
|
|
233
|
-
SFMono-Regular,
|
|
234
|
-
Menlo,
|
|
235
|
-
Monaco,
|
|
236
|
-
Consolas,
|
|
237
|
-
'Liberation Mono',
|
|
238
|
-
'Courier New',
|
|
239
|
-
monospace;
|
|
240
|
-
font-size: 0.875rem;
|
|
241
|
-
line-height: 1.25rem;
|
|
242
|
-
}
|
|
243
|
-
pre {
|
|
244
|
-
background-color: hsl(var(--muted));
|
|
245
|
-
padding: 1rem;
|
|
246
|
-
border-radius: 0.375rem;
|
|
247
|
-
overflow-x: auto;
|
|
248
|
-
margin-bottom: 1rem;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
table {
|
|
252
|
-
width: 100%;
|
|
253
|
-
border-collapse: collapse;
|
|
254
|
-
margin-bottom: 1rem;
|
|
255
|
-
}
|
|
256
|
-
thead {
|
|
257
|
-
background-color: hsl(var(--muted));
|
|
258
|
-
}
|
|
259
|
-
th,
|
|
260
|
-
td {
|
|
261
|
-
border: 1px solid hsl(var(--border));
|
|
262
|
-
padding: 0.5rem;
|
|
263
|
-
text-align: left;
|
|
264
|
-
}
|
|
265
|
-
th {
|
|
266
|
-
font-weight: 600;
|
|
267
|
-
}
|
|
268
|
-
hr {
|
|
269
|
-
border-top: 1px solid hsl(var(--border));
|
|
270
|
-
margin: 2rem 0;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/* Image alignment preserved from editor output */
|
|
275
|
-
@layer components {
|
|
276
|
-
img[data-align='left'] {
|
|
277
|
-
display: block;
|
|
278
|
-
margin-left: 0;
|
|
279
|
-
margin-right: auto;
|
|
280
|
-
}
|
|
281
|
-
img[data-align='right'] {
|
|
282
|
-
display: block;
|
|
283
|
-
margin-left: auto;
|
|
284
|
-
margin-right: 0;
|
|
285
|
-
}
|
|
286
|
-
img[data-align='center'] {
|
|
287
|
-
display: block;
|
|
288
|
-
margin-left: auto;
|
|
289
|
-
margin-right: auto;
|
|
290
|
-
}
|
|
291
|
-
}
|
|
1
|
+
@config "../../../../tailwind.config.js";
|
|
2
|
+
@import 'tailwindcss/preflight';
|
|
3
|
+
@import 'tailwindcss/theme';
|
|
4
|
+
@import 'tailwindcss/utilities';
|
|
292
5
|
|
|
293
6
|
/*─────────────────────────────────────────────────────────────────────────────
|
|
294
|
-
|
|
7
|
+
globals.css — modularized
|
|
295
8
|
─────────────────────────────────────────────────────────────────────────────*/
|
|
296
|
-
:root {
|
|
297
|
-
--background: 220 20% 98%;
|
|
298
|
-
--foreground: 215 30% 15%;
|
|
299
|
-
--card: 0 0% 100%;
|
|
300
|
-
--card-foreground: 215 30% 15%;
|
|
301
|
-
--popover: 0 0% 100%;
|
|
302
|
-
--popover-foreground: 215 30% 15%;
|
|
303
9
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
--muted: 220 30% 94%;
|
|
311
|
-
--muted-foreground: 215 25% 45%;
|
|
312
|
-
|
|
313
|
-
--accent: 190 70% 50%;
|
|
314
|
-
--accent-foreground: 210 40% 98%;
|
|
315
|
-
|
|
316
|
-
--destructive: 0 70% 42%;
|
|
317
|
-
--destructive-foreground: 0 0% 98%;
|
|
318
|
-
|
|
319
|
-
--warning: 38 92% 50%;
|
|
320
|
-
--warning-foreground: 48 96% 98%;
|
|
321
|
-
|
|
322
|
-
--border: 220 20% 88%;
|
|
323
|
-
--input: 220 20% 88%;
|
|
324
|
-
--ring: 200 80% 60%;
|
|
325
|
-
|
|
326
|
-
--radius: 0.5rem;
|
|
327
|
-
|
|
328
|
-
--chart-1: 217 70% 50%;
|
|
329
|
-
--chart-2: 190 60% 45%;
|
|
330
|
-
--chart-3: 215 35% 40%;
|
|
331
|
-
--chart-4: 220 15% 70%;
|
|
332
|
-
--chart-5: 200 50% 65%;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.dark {
|
|
336
|
-
--background: 220 25% 10%;
|
|
337
|
-
--foreground: 220 15% 90%;
|
|
338
|
-
--card: 220 20% 14%;
|
|
339
|
-
--card-foreground: 220 15% 90%;
|
|
340
|
-
--popover: 220 20% 14%;
|
|
341
|
-
--popover-foreground: 220 15% 90%;
|
|
342
|
-
|
|
343
|
-
--primary: 210 90% 65%;
|
|
344
|
-
--primary-foreground: 220 20% 10%;
|
|
345
|
-
|
|
346
|
-
--secondary: 215 50% 45%;
|
|
347
|
-
--secondary-foreground: 220 15% 90%;
|
|
348
|
-
|
|
349
|
-
--muted: 220 15% 18%;
|
|
350
|
-
--muted-foreground: 220 10% 65%;
|
|
351
|
-
|
|
352
|
-
--accent: 195 80% 55%;
|
|
353
|
-
--accent-foreground: 220 25% 10%;
|
|
354
|
-
|
|
355
|
-
--destructive: 0 65% 42%;
|
|
356
|
-
--destructive-foreground: 0 0% 98%;
|
|
357
|
-
|
|
358
|
-
--warning: 38 92% 50%;
|
|
359
|
-
--warning-foreground: 48 96% 98%;
|
|
360
|
-
|
|
361
|
-
--border: 220 15% 25%;
|
|
362
|
-
--input: 220 15% 25%;
|
|
363
|
-
--ring: 195 90% 60%;
|
|
364
|
-
|
|
365
|
-
--chart-1: 210 80% 60%;
|
|
366
|
-
--chart-2: 195 70% 50%;
|
|
367
|
-
--chart-3: 215 40% 50%;
|
|
368
|
-
--chart-4: 220 10% 55%;
|
|
369
|
-
--chart-5: 200 60% 70%;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/*─────────────────────────────────────────────────────────────────────────────
|
|
373
|
-
4. Explicit heading sizes & spacing
|
|
374
|
-
─────────────────────────────────────────────────────────────────────────────*/
|
|
375
|
-
h1 {
|
|
376
|
-
font-size: 3.5rem;
|
|
377
|
-
line-height: 1;
|
|
378
|
-
font-weight: 700;
|
|
379
|
-
margin: 1.5rem 0 1rem;
|
|
380
|
-
}
|
|
381
|
-
h2 {
|
|
382
|
-
font-size: 2.5rem;
|
|
383
|
-
line-height: 1;
|
|
384
|
-
font-weight: 700;
|
|
385
|
-
margin: 1.25rem 0 0.75rem;
|
|
386
|
-
}
|
|
387
|
-
h3 {
|
|
388
|
-
font-size: 2.25rem;
|
|
389
|
-
line-height: 2.5rem;
|
|
390
|
-
font-weight: 700;
|
|
391
|
-
margin: 1rem 0 0.75rem;
|
|
392
|
-
}
|
|
393
|
-
h4 {
|
|
394
|
-
font-size: 1.5rem;
|
|
395
|
-
line-height: 2rem;
|
|
396
|
-
font-weight: 700;
|
|
397
|
-
margin: 0.75rem 0 0.5rem;
|
|
398
|
-
}
|
|
399
|
-
h5 {
|
|
400
|
-
font-size: 1.25rem;
|
|
401
|
-
line-height: 1.75rem;
|
|
402
|
-
font-weight: 600;
|
|
403
|
-
margin: 0.5rem 0 0.5rem;
|
|
404
|
-
}
|
|
405
|
-
h6 {
|
|
406
|
-
font-size: 1.125rem;
|
|
407
|
-
line-height: 1.75rem;
|
|
408
|
-
font-weight: 600;
|
|
409
|
-
margin: 0.5rem 0 0.5rem;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/*─────────────────────────────────────────────────────────────────────────────
|
|
413
|
-
5. Shimmer loading animation
|
|
414
|
-
─────────────────────────────────────────────────────────────────────────────*/
|
|
415
|
-
@keyframes shimmer {
|
|
416
|
-
100% {
|
|
417
|
-
transform: translateX(100%);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
.shimmer::before {
|
|
421
|
-
content: '';
|
|
422
|
-
position: absolute;
|
|
423
|
-
top: 0;
|
|
424
|
-
left: 0;
|
|
425
|
-
right: 0;
|
|
426
|
-
bottom: 0;
|
|
427
|
-
transform: translateX(-100%);
|
|
428
|
-
background-image: linear-gradient(
|
|
429
|
-
90deg,
|
|
430
|
-
rgba(255, 255, 255, 0) 0,
|
|
431
|
-
rgba(255, 255, 255, 0.2) 20%,
|
|
432
|
-
rgba(255, 255, 255, 0.5) 60%,
|
|
433
|
-
rgba(255, 255, 255, 0)
|
|
434
|
-
);
|
|
435
|
-
animation: shimmer 2s infinite;
|
|
436
|
-
}
|
|
10
|
+
@import './base.css';
|
|
11
|
+
@import './components.css';
|
|
12
|
+
@import './theme.css';
|
|
13
|
+
@import './typography.css';
|
|
14
|
+
@import './animations.css';
|
|
@@ -147,13 +147,10 @@ export default async function RootLayout({
|
|
|
147
147
|
<title>{metadata.title as string}</title>
|
|
148
148
|
<meta name="description" content={metadata.description as string} />
|
|
149
149
|
<link rel="preconnect" href="https://ppcppwsfnrptznvbxnsz.supabase.co" />
|
|
150
|
-
<link rel="preconnect" href="https://pub-a31e3f1a87d144898aeb489a8221f92e.r2.dev" crossOrigin="anonymous" />
|
|
151
150
|
<link rel="dns-prefetch" href="https://ppcppwsfnrptznvbxnsz.supabase.co" />
|
|
152
|
-
<link rel="dns-prefetch" href="https://pub-a31e3f1a87d144898aeb489a8221f92e.r2.dev" />
|
|
153
151
|
<link rel="dns-prefetch" href="https://aws-0-us-east-1.pooler.supabase.com" />
|
|
154
152
|
<link rel="dns-prefetch" href="https://db.ppcppwsfnrptznvbxnsz.supabase.co" />
|
|
155
153
|
<link rel="dns-prefetch" href="https://realtime.supabase.com" />
|
|
156
|
-
<link rel="preload" as="image" href="https://pub-a31e3f1a87d144898aeb489a8221f92e.r2.dev/hero-bg.jpg" fetchPriority="high" />
|
|
157
154
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
158
155
|
</head>
|
|
159
156
|
<body className="bg-background text-foreground min-h-screen flex flex-col">
|
|
@@ -261,7 +261,11 @@ export default function ResponsiveNav({
|
|
|
261
261
|
>
|
|
262
262
|
{logo && logo.media ? (
|
|
263
263
|
<Image
|
|
264
|
-
src={
|
|
264
|
+
src={
|
|
265
|
+
logo.media.object_key.startsWith('/') || logo.media.object_key.startsWith('http')
|
|
266
|
+
? logo.media.object_key
|
|
267
|
+
: `${R2_BASE_URL}/${logo.media.object_key}`
|
|
268
|
+
}
|
|
265
269
|
alt={logo.media.alt_text || siteTitle || 'Nextblock'}
|
|
266
270
|
width={logo.media.width || 100}
|
|
267
271
|
height={logo.media.height || 32}
|
|
@@ -68,6 +68,14 @@ const paddingClasses = {
|
|
|
68
68
|
xl: 'py-12'
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
// Vertical alignment classes
|
|
72
|
+
const verticalAlignmentClasses = {
|
|
73
|
+
start: 'items-start',
|
|
74
|
+
center: 'items-center',
|
|
75
|
+
end: 'items-end',
|
|
76
|
+
stretch: 'items-stretch'
|
|
77
|
+
};
|
|
78
|
+
|
|
71
79
|
// Background style generator
|
|
72
80
|
function generateBackgroundStyles(background: SectionBlockContent['background']) {
|
|
73
81
|
const styles: React.CSSProperties = {};
|
|
@@ -207,6 +215,7 @@ const HeroBlockRenderer: React.FC<SectionBlockRendererProps> = ({
|
|
|
207
215
|
const gapClass = gapClasses[content.column_gap] || gapClasses.md;
|
|
208
216
|
const paddingTopClass = paddingClasses[content.padding.top] || paddingClasses.md;
|
|
209
217
|
const paddingBottomClass = paddingClasses[content.padding.bottom] || paddingClasses.md;
|
|
218
|
+
const alignmentClass = content.vertical_alignment ? verticalAlignmentClasses[content.vertical_alignment] : 'items-start';
|
|
210
219
|
|
|
211
220
|
const imageProps = backgroundImage?.blur_data_url
|
|
212
221
|
? {
|
|
@@ -243,7 +252,7 @@ const HeroBlockRenderer: React.FC<SectionBlockRendererProps> = ({
|
|
|
243
252
|
/>
|
|
244
253
|
)}
|
|
245
254
|
<div className={`${containerClass} relative`}>
|
|
246
|
-
<div className={`grid ${gridClass} ${gapClass}`}>
|
|
255
|
+
<div className={`grid ${gridClass} ${gapClass} ${alignmentClass}`}>
|
|
247
256
|
{content.column_blocks.map((columnBlocks, columnIndex) => (
|
|
248
257
|
<div key={`column-${columnIndex}`} className="min-h-0 space-y-4">
|
|
249
258
|
{(Array.isArray(columnBlocks) ? columnBlocks : []).map((block, blockIndex) => (
|
|
@@ -46,6 +46,14 @@ const paddingClasses = {
|
|
|
46
46
|
xl: 'py-12'
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
// Vertical alignment classes
|
|
50
|
+
const verticalAlignmentClasses = {
|
|
51
|
+
start: 'items-start',
|
|
52
|
+
center: 'items-center',
|
|
53
|
+
end: 'items-end',
|
|
54
|
+
stretch: 'items-stretch'
|
|
55
|
+
};
|
|
56
|
+
|
|
49
57
|
// Background style generator
|
|
50
58
|
function generateBackgroundStyles(background: SectionBlockContent['background']) {
|
|
51
59
|
const styles: React.CSSProperties = {};
|
|
@@ -161,6 +169,7 @@ const SectionBlockRenderer: React.FC<SectionBlockRendererProps> = ({
|
|
|
161
169
|
const gapClass = gapClasses[content.column_gap] || gapClasses.md;
|
|
162
170
|
const paddingTopClass = paddingClasses[content.padding.top] || paddingClasses.md;
|
|
163
171
|
const paddingBottomClass = paddingClasses[content.padding.bottom] || paddingClasses.md;
|
|
172
|
+
const alignmentClass = content.vertical_alignment ? verticalAlignmentClasses[content.vertical_alignment] : 'items-start';
|
|
164
173
|
|
|
165
174
|
return (
|
|
166
175
|
<section
|
|
@@ -168,7 +177,7 @@ const SectionBlockRenderer: React.FC<SectionBlockRendererProps> = ({
|
|
|
168
177
|
style={styles}
|
|
169
178
|
>
|
|
170
179
|
<div className={containerClass}>
|
|
171
|
-
<div className={`grid ${gridClass} ${gapClass}`}>
|
|
180
|
+
<div className={`grid ${gridClass} ${gapClass} ${alignmentClass}`}>
|
|
172
181
|
{content.column_blocks.map((columnBlocks, columnIndex) => (
|
|
173
182
|
<div key={`column-${columnIndex}`} className="min-h-0 space-y-4">
|
|
174
183
|
{(Array.isArray(columnBlocks) ? columnBlocks : []).map((block, blockIndex) => (
|
|
@@ -146,6 +146,8 @@ export interface SectionBlockContent {
|
|
|
146
146
|
top: 'none' | 'sm' | 'md' | 'lg' | 'xl';
|
|
147
147
|
bottom: 'none' | 'sm' | 'md' | 'lg' | 'xl';
|
|
148
148
|
};
|
|
149
|
+
/** Vertical alignment of columns */
|
|
150
|
+
vertical_alignment?: 'start' | 'center' | 'end' | 'stretch';
|
|
149
151
|
/** Array of blocks within columns - 2D array where each index represents a column */
|
|
150
152
|
column_blocks: Array<Array<{
|
|
151
153
|
block_type: BlockType;
|
|
@@ -621,6 +623,7 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
621
623
|
background: { type: "none" },
|
|
622
624
|
responsive_columns: { mobile: 1, tablet: 2, desktop: 3 },
|
|
623
625
|
column_gap: "md",
|
|
626
|
+
vertical_alignment: "start",
|
|
624
627
|
padding: { top: "md", bottom: "md" },
|
|
625
628
|
column_blocks: [
|
|
626
629
|
[{ block_type: "text", content: { html_content: "<p>Column 1</p>" } }],
|
|
@@ -669,6 +672,16 @@ export const blockRegistry: Record<BlockType, BlockDefinition> = {
|
|
|
669
672
|
description: 'Section padding configuration',
|
|
670
673
|
default: { top: 'md', bottom: 'md' },
|
|
671
674
|
},
|
|
675
|
+
vertical_alignment: {
|
|
676
|
+
type: 'union',
|
|
677
|
+
required: false,
|
|
678
|
+
description: 'Vertical alignment of columns',
|
|
679
|
+
default: 'start',
|
|
680
|
+
unionValues: ['start', 'center', 'end', 'stretch'] as const,
|
|
681
|
+
constraints: {
|
|
682
|
+
enum: ['start', 'center', 'end', 'stretch'] as const,
|
|
683
|
+
},
|
|
684
|
+
},
|
|
672
685
|
column_blocks: {
|
|
673
686
|
type: 'array',
|
|
674
687
|
required: true,
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@nextblock-cms/template",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"private": true,
|
|
5
|
-
"scripts": {
|
|
6
|
-
"dev": "next dev",
|
|
7
|
-
"build": "next build",
|
|
8
|
-
"start": "next start",
|
|
9
|
-
"lint": "next lint"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"@aws-sdk/client-s3": "^3.920.0",
|
|
13
|
-
"@aws-sdk/s3-request-presigner": "^3.920.0",
|
|
14
|
-
"@dnd-kit/core": "^6.3.1",
|
|
15
|
-
"@dnd-kit/sortable": "^10.0.0",
|
|
16
|
-
"@dnd-kit/utilities": "^3.2.2",
|
|
17
|
-
"@supabase/ssr": "^0.6.1",
|
|
18
|
-
"@supabase/supabase-js": "^2.47.2",
|
|
19
|
-
"@tiptap/react": "^3.3.0",
|
|
20
|
-
"date-fns": "^3.6.0",
|
|
21
|
-
"dotenv": "^16.5.0",
|
|
22
|
-
"fast-json-patch": "^3.1.1",
|
|
23
|
-
"html-react-parser": "^5.2.6",
|
|
24
|
-
"js-cookie": "^3.0.5",
|
|
25
|
-
"lodash.debounce": "^4.0.8",
|
|
26
|
-
"lucide-react": "^0.534.0",
|
|
27
|
-
"next": "^15.5.4",
|
|
28
|
-
"nodemailer": "^7.0.4",
|
|
29
|
-
"plaiceholder": "^3.0.0",
|
|
30
|
-
"react": "19.0.0",
|
|
31
|
-
"react-dom": "19.0.0",
|
|
32
|
-
"react-hot-toast": "^2.4.1",
|
|
33
|
-
"sharp": "^0.34.2",
|
|
34
|
-
"uuid": "^10.0.0",
|
|
35
|
-
"zod": "^3.25.76",
|
|
36
|
-
"@nextblock-cms/ui": "workspace:*",
|
|
37
|
-
"@nextblock-cms/utils": "workspace:*",
|
|
38
|
-
"@nextblock-cms/db": "workspace:*",
|
|
39
|
-
"@nextblock-cms/editor": "workspace:*",
|
|
40
|
-
"@nextblock-cms/sdk": "workspace:*"
|
|
41
|
-
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@types/node": "22.10.2",
|
|
44
|
-
"@types/react": "^19.0.0",
|
|
45
|
-
"@types/react-dom": "19.0.2",
|
|
46
|
-
"autoprefixer": "^10.4.13",
|
|
47
|
-
"eslint": "^9.8.0",
|
|
48
|
-
"eslint-config-next": "^15.5.4",
|
|
49
|
-
"postcss": "^8.4.38",
|
|
50
|
-
"tailwindcss": "^3.4.3",
|
|
51
|
-
"typescript": "~5.8.2",
|
|
52
|
-
"typescript-eslint": "^8.0.0"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@nextblock-cms/template",
|
|
3
|
+
"version": "0.2.16",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@aws-sdk/client-s3": "^3.920.0",
|
|
13
|
+
"@aws-sdk/s3-request-presigner": "^3.920.0",
|
|
14
|
+
"@dnd-kit/core": "^6.3.1",
|
|
15
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
16
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
17
|
+
"@supabase/ssr": "^0.6.1",
|
|
18
|
+
"@supabase/supabase-js": "^2.47.2",
|
|
19
|
+
"@tiptap/react": "^3.3.0",
|
|
20
|
+
"date-fns": "^3.6.0",
|
|
21
|
+
"dotenv": "^16.5.0",
|
|
22
|
+
"fast-json-patch": "^3.1.1",
|
|
23
|
+
"html-react-parser": "^5.2.6",
|
|
24
|
+
"js-cookie": "^3.0.5",
|
|
25
|
+
"lodash.debounce": "^4.0.8",
|
|
26
|
+
"lucide-react": "^0.534.0",
|
|
27
|
+
"next": "^15.5.4",
|
|
28
|
+
"nodemailer": "^7.0.4",
|
|
29
|
+
"plaiceholder": "^3.0.0",
|
|
30
|
+
"react": "19.0.0",
|
|
31
|
+
"react-dom": "19.0.0",
|
|
32
|
+
"react-hot-toast": "^2.4.1",
|
|
33
|
+
"sharp": "^0.34.2",
|
|
34
|
+
"uuid": "^10.0.0",
|
|
35
|
+
"zod": "^3.25.76",
|
|
36
|
+
"@nextblock-cms/ui": "workspace:*",
|
|
37
|
+
"@nextblock-cms/utils": "workspace:*",
|
|
38
|
+
"@nextblock-cms/db": "workspace:*",
|
|
39
|
+
"@nextblock-cms/editor": "workspace:*",
|
|
40
|
+
"@nextblock-cms/sdk": "workspace:*"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "22.10.2",
|
|
44
|
+
"@types/react": "^19.0.0",
|
|
45
|
+
"@types/react-dom": "19.0.2",
|
|
46
|
+
"autoprefixer": "^10.4.13",
|
|
47
|
+
"eslint": "^9.8.0",
|
|
48
|
+
"eslint-config-next": "^15.5.4",
|
|
49
|
+
"postcss": "^8.4.38",
|
|
50
|
+
"tailwindcss": "^3.4.3",
|
|
51
|
+
"typescript": "~5.8.2",
|
|
52
|
+
"typescript-eslint": "^8.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
Binary file
|
|
@@ -14,7 +14,7 @@ module.exports = {
|
|
|
14
14
|
const libsDir = join(__dirname, '../../libs');
|
|
15
15
|
if (existsSync(libsDir)) {
|
|
16
16
|
projectGlobs.push(
|
|
17
|
-
join(libsDir, '**/*.{ts,tsx,js,jsx,md,mdx,html}')
|
|
17
|
+
join(libsDir, '**/*.{ts,tsx,js,jsx,md,mdx,html,sql}')
|
|
18
18
|
);
|
|
19
19
|
}
|
|
20
20
|
return projectGlobs;
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"**/*.jsx",
|
|
38
38
|
"next-env.d.ts",
|
|
39
39
|
".next/types/**/*.ts",
|
|
40
|
-
"../../dist/apps/nextblock/.next/types/**/*.ts"
|
|
40
|
+
"../../dist/apps/nextblock/.next/types/**/*.ts",
|
|
41
|
+
"../../tailwind.config.js"
|
|
41
42
|
],
|
|
42
43
|
"exclude": [
|
|
43
44
|
"node_modules",
|
|
@@ -59,4 +60,4 @@
|
|
|
59
60
|
"path": "../../libs/utils/tsconfig.json"
|
|
60
61
|
}
|
|
61
62
|
]
|
|
62
|
-
}
|
|
63
|
+
}
|