@sprintup-cms/sdk 1.0.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.
@@ -0,0 +1,292 @@
1
+ import React from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+
4
+ /* @sprintup-cms/sdk — https://forgecms.io */
5
+
6
+ function getData(block) {
7
+ return block.data ?? block.content ?? {};
8
+ }
9
+ function HeadingBlock({ block }) {
10
+ const d = getData(block);
11
+ const text = d.text || d.heading || d.title || "";
12
+ const level = Number(d.level) || 2;
13
+ const cls = {
14
+ 1: "text-4xl font-bold tracking-tight",
15
+ 2: "text-2xl font-bold mt-8",
16
+ 3: "text-xl font-semibold mt-6",
17
+ 4: "text-lg font-medium mt-4"
18
+ }[level] ?? "text-2xl font-bold";
19
+ return React.createElement(`h${level}`, { className: cls }, text);
20
+ }
21
+ function TextBlock({ block }) {
22
+ const d = getData(block);
23
+ return /* @__PURE__ */ jsx("p", { className: "text-base leading-relaxed text-muted-foreground", children: d.text || d.content || "" });
24
+ }
25
+ function RichTextBlock({ block }) {
26
+ const d = getData(block);
27
+ const html = d.content || d.richtext || d.text || "";
28
+ if (!html) return null;
29
+ return /* @__PURE__ */ jsx(
30
+ "div",
31
+ {
32
+ className: "prose prose-neutral dark:prose-invert max-w-none",
33
+ dangerouslySetInnerHTML: { __html: html }
34
+ }
35
+ );
36
+ }
37
+ function ImageBlock({ block }) {
38
+ const d = getData(block);
39
+ const src = d.src || d.url || d.image || "";
40
+ if (!src) return null;
41
+ return /* @__PURE__ */ jsxs("figure", { className: "my-6", children: [
42
+ /* @__PURE__ */ jsx("img", { src, alt: d.alt || "", className: "w-full rounded-lg border object-cover" }),
43
+ d.caption && /* @__PURE__ */ jsx("figcaption", { className: "mt-2 text-sm text-muted-foreground text-center", children: d.caption })
44
+ ] });
45
+ }
46
+ function HeroBlock({ block }) {
47
+ const d = getData(block);
48
+ return /* @__PURE__ */ jsx("section", { className: "py-12 md:py-20", children: /* @__PURE__ */ jsxs("div", { className: "max-w-3xl", children: [
49
+ d.badge && /* @__PURE__ */ jsx("span", { className: "inline-block px-3 py-1 text-xs font-semibold rounded-full bg-secondary text-secondary-foreground mb-4", children: d.badge }),
50
+ /* @__PURE__ */ jsx("h1", { className: "text-4xl md:text-5xl font-bold tracking-tight mb-4 text-balance", children: d.title }),
51
+ d.subtitle && /* @__PURE__ */ jsx("p", { className: "text-xl text-muted-foreground mb-8", children: d.subtitle }),
52
+ (d.primaryButton || d.cta) && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 flex-wrap", children: [
53
+ (d.primaryButton || d.cta) && /* @__PURE__ */ jsx(
54
+ "a",
55
+ {
56
+ href: d.primaryUrl || d.ctaUrl || "#",
57
+ className: "inline-flex items-center px-6 py-3 rounded-lg bg-primary text-primary-foreground font-semibold hover:opacity-90 transition-opacity",
58
+ children: d.primaryButton || d.cta
59
+ }
60
+ ),
61
+ d.secondaryButton && /* @__PURE__ */ jsx(
62
+ "a",
63
+ {
64
+ href: d.secondaryUrl || "#",
65
+ className: "inline-flex items-center px-6 py-3 rounded-lg border border-border font-semibold hover:bg-muted transition-colors",
66
+ children: d.secondaryButton
67
+ }
68
+ )
69
+ ] })
70
+ ] }) });
71
+ }
72
+ function CTABlock({ block }) {
73
+ const d = getData(block);
74
+ return /* @__PURE__ */ jsxs("section", { className: "py-12 px-8 rounded-xl bg-primary text-primary-foreground text-center", children: [
75
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl md:text-3xl font-bold mb-4", children: d.title }),
76
+ d.subtitle && /* @__PURE__ */ jsx("p", { className: "text-primary-foreground/80 mb-6 max-w-2xl mx-auto", children: d.subtitle }),
77
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-center flex-wrap", children: [
78
+ d.primaryButton && /* @__PURE__ */ jsx(
79
+ "a",
80
+ {
81
+ href: d.primaryUrl || "#",
82
+ className: "px-6 py-3 rounded-lg bg-background text-foreground font-semibold hover:opacity-90 transition-opacity",
83
+ children: d.primaryButton
84
+ }
85
+ ),
86
+ d.secondaryButton && /* @__PURE__ */ jsx(
87
+ "a",
88
+ {
89
+ href: d.secondaryUrl || "#",
90
+ className: "px-6 py-3 rounded-lg border border-primary-foreground/20 text-primary-foreground font-semibold hover:bg-primary-foreground/10 transition-colors",
91
+ children: d.secondaryButton
92
+ }
93
+ )
94
+ ] })
95
+ ] });
96
+ }
97
+ function FAQBlock({ block }) {
98
+ const d = getData(block);
99
+ const items = d.items || [];
100
+ return /* @__PURE__ */ jsxs("section", { className: "py-8", children: [
101
+ d.title && /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-6", children: d.title }),
102
+ /* @__PURE__ */ jsx("div", { className: "space-y-4", children: items.map((item, i) => /* @__PURE__ */ jsxs("details", { className: "group border border-border rounded-lg", children: [
103
+ /* @__PURE__ */ jsxs("summary", { className: "flex items-center justify-between p-4 cursor-pointer font-medium select-none", children: [
104
+ item.question,
105
+ /* @__PURE__ */ jsx("span", { className: "transition-transform group-open:rotate-45 text-lg leading-none", children: "+" })
106
+ ] }),
107
+ /* @__PURE__ */ jsx("div", { className: "px-4 pb-4 text-muted-foreground", children: item.answer })
108
+ ] }, i)) })
109
+ ] });
110
+ }
111
+ function StatsBlock({ block }) {
112
+ const d = getData(block);
113
+ const items = d.items || d.stats || [];
114
+ return /* @__PURE__ */ jsxs("section", { className: "py-8", children: [
115
+ d.title && /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-6 text-center", children: d.title }),
116
+ /* @__PURE__ */ jsx("div", { className: `grid gap-6 grid-cols-2 md:grid-cols-${Math.min(items.length, 4)}`, children: items.map((s, i) => /* @__PURE__ */ jsxs("div", { className: "text-center p-6 rounded-lg border bg-card", children: [
117
+ /* @__PURE__ */ jsx("div", { className: "text-3xl font-bold text-primary", children: s.value }),
118
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mt-1", children: s.label })
119
+ ] }, i)) })
120
+ ] });
121
+ }
122
+ function TestimonialBlock({ block }) {
123
+ const d = getData(block);
124
+ return /* @__PURE__ */ jsxs("div", { className: "border border-border rounded-xl p-6 bg-card", children: [
125
+ /* @__PURE__ */ jsxs("blockquote", { className: "text-lg italic mb-4 text-foreground", children: [
126
+ '"',
127
+ d.quote,
128
+ '"'
129
+ ] }),
130
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
131
+ d.avatar && /* @__PURE__ */ jsx("img", { src: d.avatar, alt: "", className: "w-10 h-10 rounded-full object-cover" }),
132
+ /* @__PURE__ */ jsxs("div", { children: [
133
+ /* @__PURE__ */ jsx("div", { className: "font-semibold", children: d.author }),
134
+ d.role && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: d.role })
135
+ ] })
136
+ ] })
137
+ ] });
138
+ }
139
+ function QuoteBlock({ block }) {
140
+ const d = getData(block);
141
+ return /* @__PURE__ */ jsxs("blockquote", { className: "border-l-4 border-primary pl-6 py-2 italic text-lg", children: [
142
+ d.text,
143
+ d.author && /* @__PURE__ */ jsxs("footer", { className: "mt-2 text-sm text-muted-foreground not-italic", children: [
144
+ "\u2014 ",
145
+ d.author
146
+ ] })
147
+ ] });
148
+ }
149
+ function AlertBlock({ block }) {
150
+ const d = getData(block);
151
+ const colors = {
152
+ info: "bg-blue-50 border-blue-200 text-blue-800 dark:bg-blue-950 dark:border-blue-800 dark:text-blue-200",
153
+ success: "bg-green-50 border-green-200 text-green-800 dark:bg-green-950 dark:border-green-800 dark:text-green-200",
154
+ warning: "bg-yellow-50 border-yellow-200 text-yellow-800 dark:bg-yellow-950 dark:border-yellow-800 dark:text-yellow-200",
155
+ error: "bg-red-50 border-red-200 text-red-800 dark:bg-red-950 dark:border-red-800 dark:text-red-200"
156
+ };
157
+ const variant = d.variant || d.type || "info";
158
+ return /* @__PURE__ */ jsxs("div", { className: `p-4 rounded-lg border ${colors[variant] ?? colors.info}`, children: [
159
+ d.title && /* @__PURE__ */ jsx("div", { className: "font-semibold mb-1", children: d.title }),
160
+ /* @__PURE__ */ jsx("p", { children: d.message || d.text || "" })
161
+ ] });
162
+ }
163
+ function DividerBlock() {
164
+ return /* @__PURE__ */ jsx("hr", { className: "my-8 border-border" });
165
+ }
166
+ function SpacerBlock({ block }) {
167
+ const d = getData(block);
168
+ const sizes = { sm: "h-4", md: "h-8", lg: "h-16", xl: "h-24" };
169
+ return /* @__PURE__ */ jsx("div", { className: sizes[d.size] ?? "h-8" });
170
+ }
171
+ function VideoBlock({ block }) {
172
+ const d = getData(block);
173
+ const url = d.url || d.embed || "";
174
+ if (!url) return null;
175
+ const embedUrl = url.replace("youtube.com/watch?v=", "youtube.com/embed/").replace("youtu.be/", "youtube.com/embed/").replace("vimeo.com/", "player.vimeo.com/video/");
176
+ return /* @__PURE__ */ jsx("div", { className: "aspect-video rounded-lg overflow-hidden border bg-muted", children: /* @__PURE__ */ jsx("iframe", { src: embedUrl, allow: "autoplay; fullscreen", allowFullScreen: true, className: "w-full h-full", title: d.title || "Video" }) });
177
+ }
178
+ function SectionBlock({ block, pageType }) {
179
+ const d = getData(block);
180
+ const section = pageType?.sections.find((s) => s.name === block.type);
181
+ if (section) {
182
+ const filledFields = section.fields.filter((f) => d[f.name] !== void 0 && d[f.name] !== "" && d[f.name] !== null);
183
+ if (filledFields.length === 0) return null;
184
+ return /* @__PURE__ */ jsx("section", { className: "py-4 space-y-4 border-b border-border last:border-0", children: filledFields.map((field) => {
185
+ const value = d[field.name];
186
+ if (!value && value !== 0 && value !== false) return null;
187
+ if (field.fieldType === "richtext") {
188
+ return /* @__PURE__ */ jsxs("div", { children: [
189
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1", children: field.label }),
190
+ /* @__PURE__ */ jsx("div", { className: "prose prose-neutral dark:prose-invert max-w-none text-sm", dangerouslySetInnerHTML: { __html: String(value) } })
191
+ ] }, field.id);
192
+ }
193
+ if (field.fieldType === "image") {
194
+ return /* @__PURE__ */ jsx("figure", { children: /* @__PURE__ */ jsx("img", { src: String(value), alt: field.label, className: "rounded-lg border max-h-96 object-cover" }) }, field.id);
195
+ }
196
+ if (field.fieldType === "boolean") {
197
+ return /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
198
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
199
+ field.label,
200
+ ":"
201
+ ] }),
202
+ " ",
203
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: value ? "Yes" : "No" })
204
+ ] }, field.id);
205
+ }
206
+ if (field.fieldType === "url") {
207
+ return /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
208
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
209
+ field.label,
210
+ ":"
211
+ ] }),
212
+ " ",
213
+ /* @__PURE__ */ jsx("a", { href: String(value), className: "text-primary underline underline-offset-2 break-all", children: String(value) })
214
+ ] }, field.id);
215
+ }
216
+ return /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
217
+ /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
218
+ field.label,
219
+ ":"
220
+ ] }),
221
+ " ",
222
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: String(value) })
223
+ ] }, field.id);
224
+ }) });
225
+ }
226
+ const entries = Object.entries(d).filter(([, v]) => v !== "" && v !== null && v !== void 0);
227
+ if (entries.length === 0) return null;
228
+ return /* @__PURE__ */ jsxs("section", { className: "py-4 space-y-2 border-b border-border last:border-0", children: [
229
+ block.label && /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm text-muted-foreground uppercase tracking-wide", children: block.label }),
230
+ entries.map(([key, value]) => /* @__PURE__ */ jsxs("p", { className: "text-sm", children: [
231
+ /* @__PURE__ */ jsxs("span", { className: "font-medium capitalize", children: [
232
+ key.replace(/_/g, " "),
233
+ ":"
234
+ ] }),
235
+ " ",
236
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: String(value) })
237
+ ] }, key))
238
+ ] });
239
+ }
240
+ var BUILT_IN = {
241
+ heading: (b) => /* @__PURE__ */ jsx(HeadingBlock, { block: b }),
242
+ text: (b) => /* @__PURE__ */ jsx(TextBlock, { block: b }),
243
+ richtext: (b) => /* @__PURE__ */ jsx(RichTextBlock, { block: b }),
244
+ image: (b) => /* @__PURE__ */ jsx(ImageBlock, { block: b }),
245
+ hero: (b) => /* @__PURE__ */ jsx(HeroBlock, { block: b }),
246
+ "hero-section": (b) => /* @__PURE__ */ jsx(HeroBlock, { block: b }),
247
+ cta: (b) => /* @__PURE__ */ jsx(CTABlock, { block: b }),
248
+ faq: (b) => /* @__PURE__ */ jsx(FAQBlock, { block: b }),
249
+ stats: (b) => /* @__PURE__ */ jsx(StatsBlock, { block: b }),
250
+ testimonial: (b) => /* @__PURE__ */ jsx(TestimonialBlock, { block: b }),
251
+ quote: (b) => /* @__PURE__ */ jsx(QuoteBlock, { block: b }),
252
+ alert: (b) => /* @__PURE__ */ jsx(AlertBlock, { block: b }),
253
+ divider: () => /* @__PURE__ */ jsx(DividerBlock, {}),
254
+ spacer: (b) => /* @__PURE__ */ jsx(SpacerBlock, { block: b }),
255
+ video: (b) => /* @__PURE__ */ jsx(VideoBlock, { block: b })
256
+ };
257
+ function CMSBlocks({ blocks, pageType, className = "", custom = {} }) {
258
+ if (!blocks?.length) return null;
259
+ return /* @__PURE__ */ jsx("div", { className: `space-y-8 ${className}`, children: blocks.map((block) => {
260
+ if (custom[block.type]) return /* @__PURE__ */ jsx(React.Fragment, { children: custom[block.type](block) }, block.id);
261
+ if (BUILT_IN[block.type]) return /* @__PURE__ */ jsx(React.Fragment, { children: BUILT_IN[block.type](block, pageType) }, block.id);
262
+ return /* @__PURE__ */ jsx(SectionBlock, { block, pageType }, block.id);
263
+ }) });
264
+ }
265
+ function CMSPreviewBanner({ isPreview, status, slug, exitUrl = "/api/cms-preview/exit" }) {
266
+ if (!isPreview) return null;
267
+ return /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-50 flex items-center justify-between px-4 py-2.5 bg-amber-500 text-white text-sm font-medium shadow", children: [
268
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
269
+ /* @__PURE__ */ jsxs("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: [
270
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" }),
271
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" })
272
+ ] }),
273
+ /* @__PURE__ */ jsx("span", { children: "Draft Preview" }),
274
+ status && /* @__PURE__ */ jsxs(Fragment, { children: [
275
+ /* @__PURE__ */ jsx("span", { className: "opacity-60", children: "\xB7" }),
276
+ /* @__PURE__ */ jsx("span", { className: "opacity-75 capitalize", children: status })
277
+ ] }),
278
+ slug && /* @__PURE__ */ jsxs(Fragment, { children: [
279
+ /* @__PURE__ */ jsx("span", { className: "opacity-60", children: "\xB7" }),
280
+ /* @__PURE__ */ jsxs("span", { className: "opacity-75 font-normal", children: [
281
+ "/",
282
+ slug
283
+ ] })
284
+ ] })
285
+ ] }),
286
+ /* @__PURE__ */ jsx("a", { href: exitUrl, className: "px-3 py-1 rounded bg-white/20 hover:bg-white/30 transition-colors text-xs", children: "Exit Preview" })
287
+ ] });
288
+ }
289
+
290
+ export { CMSBlocks, CMSPreviewBanner };
291
+ //# sourceMappingURL=index.js.map
292
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/blocks.tsx","../../src/react/preview-banner.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"index.js","sourcesContent":["'use client'\n\nimport React from 'react'\nimport type { CMSBlock, CMSPageType } from '../client'\n\nexport interface CMSBlocksProps {\n blocks: CMSBlock[]\n pageType?: CMSPageType | null\n className?: string\n /**\n * Custom block renderers — extend or override built-in blocks.\n * @example\n * <CMSBlocks blocks={blocks} custom={{ 'my-hero': (block) => <MyHero {...block.data} /> }} />\n */\n custom?: Record<string, (block: CMSBlock) => React.ReactNode>\n}\n\n/**\n * Resolves block data from either `data` (v1.1+) or legacy `content` field.\n */\nfunction getData(block: CMSBlock): Record<string, any> {\n return block.data ?? block.content ?? {}\n}\n\n// ── Built-in block renderers ──────────────────────────────────────────────────\n\nfunction HeadingBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const text = d.text || d.heading || d.title || ''\n const level = Number(d.level) || 2\n const cls = {\n 1: 'text-4xl font-bold tracking-tight',\n 2: 'text-2xl font-bold mt-8',\n 3: 'text-xl font-semibold mt-6',\n 4: 'text-lg font-medium mt-4',\n }[level] ?? 'text-2xl font-bold'\n return React.createElement(`h${level}`, { className: cls }, text)\n}\n\nfunction TextBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n return <p className=\"text-base leading-relaxed text-muted-foreground\">{d.text || d.content || ''}</p>\n}\n\nfunction RichTextBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const html = d.content || d.richtext || d.text || ''\n if (!html) return null\n return (\n <div\n className=\"prose prose-neutral dark:prose-invert max-w-none\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n )\n}\n\nfunction ImageBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const src = d.src || d.url || d.image || ''\n if (!src) return null\n return (\n <figure className=\"my-6\">\n <img src={src} alt={d.alt || ''} className=\"w-full rounded-lg border object-cover\" />\n {d.caption && (\n <figcaption className=\"mt-2 text-sm text-muted-foreground text-center\">{d.caption}</figcaption>\n )}\n </figure>\n )\n}\n\nfunction HeroBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n return (\n <section className=\"py-12 md:py-20\">\n <div className=\"max-w-3xl\">\n {d.badge && (\n <span className=\"inline-block px-3 py-1 text-xs font-semibold rounded-full bg-secondary text-secondary-foreground mb-4\">\n {d.badge}\n </span>\n )}\n <h1 className=\"text-4xl md:text-5xl font-bold tracking-tight mb-4 text-balance\">{d.title}</h1>\n {d.subtitle && <p className=\"text-xl text-muted-foreground mb-8\">{d.subtitle}</p>}\n {(d.primaryButton || d.cta) && (\n <div className=\"flex gap-4 flex-wrap\">\n {(d.primaryButton || d.cta) && (\n <a href={d.primaryUrl || d.ctaUrl || '#'}\n className=\"inline-flex items-center px-6 py-3 rounded-lg bg-primary text-primary-foreground font-semibold hover:opacity-90 transition-opacity\">\n {d.primaryButton || d.cta}\n </a>\n )}\n {d.secondaryButton && (\n <a href={d.secondaryUrl || '#'}\n className=\"inline-flex items-center px-6 py-3 rounded-lg border border-border font-semibold hover:bg-muted transition-colors\">\n {d.secondaryButton}\n </a>\n )}\n </div>\n )}\n </div>\n </section>\n )\n}\n\nfunction CTABlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n return (\n <section className=\"py-12 px-8 rounded-xl bg-primary text-primary-foreground text-center\">\n <h2 className=\"text-2xl md:text-3xl font-bold mb-4\">{d.title}</h2>\n {d.subtitle && <p className=\"text-primary-foreground/80 mb-6 max-w-2xl mx-auto\">{d.subtitle}</p>}\n <div className=\"flex gap-4 justify-center flex-wrap\">\n {d.primaryButton && (\n <a href={d.primaryUrl || '#'}\n className=\"px-6 py-3 rounded-lg bg-background text-foreground font-semibold hover:opacity-90 transition-opacity\">\n {d.primaryButton}\n </a>\n )}\n {d.secondaryButton && (\n <a href={d.secondaryUrl || '#'}\n className=\"px-6 py-3 rounded-lg border border-primary-foreground/20 text-primary-foreground font-semibold hover:bg-primary-foreground/10 transition-colors\">\n {d.secondaryButton}\n </a>\n )}\n </div>\n </section>\n )\n}\n\nfunction FAQBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const items: { question: string; answer: string }[] = d.items || []\n return (\n <section className=\"py-8\">\n {d.title && <h2 className=\"text-2xl font-bold mb-6\">{d.title}</h2>}\n <div className=\"space-y-4\">\n {items.map((item, i) => (\n <details key={i} className=\"group border border-border rounded-lg\">\n <summary className=\"flex items-center justify-between p-4 cursor-pointer font-medium select-none\">\n {item.question}\n <span className=\"transition-transform group-open:rotate-45 text-lg leading-none\">+</span>\n </summary>\n <div className=\"px-4 pb-4 text-muted-foreground\">{item.answer}</div>\n </details>\n ))}\n </div>\n </section>\n )\n}\n\nfunction StatsBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const items: { value: string; label: string }[] = d.items || d.stats || []\n return (\n <section className=\"py-8\">\n {d.title && <h2 className=\"text-2xl font-bold mb-6 text-center\">{d.title}</h2>}\n <div className={`grid gap-6 grid-cols-2 md:grid-cols-${Math.min(items.length, 4)}`}>\n {items.map((s, i) => (\n <div key={i} className=\"text-center p-6 rounded-lg border bg-card\">\n <div className=\"text-3xl font-bold text-primary\">{s.value}</div>\n <div className=\"text-sm text-muted-foreground mt-1\">{s.label}</div>\n </div>\n ))}\n </div>\n </section>\n )\n}\n\nfunction TestimonialBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n return (\n <div className=\"border border-border rounded-xl p-6 bg-card\">\n <blockquote className=\"text-lg italic mb-4 text-foreground\">\"{d.quote}\"</blockquote>\n <div className=\"flex items-center gap-3\">\n {d.avatar && <img src={d.avatar} alt=\"\" className=\"w-10 h-10 rounded-full object-cover\" />}\n <div>\n <div className=\"font-semibold\">{d.author}</div>\n {d.role && <div className=\"text-sm text-muted-foreground\">{d.role}</div>}\n </div>\n </div>\n </div>\n )\n}\n\nfunction QuoteBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n return (\n <blockquote className=\"border-l-4 border-primary pl-6 py-2 italic text-lg\">\n {d.text}\n {d.author && <footer className=\"mt-2 text-sm text-muted-foreground not-italic\">— {d.author}</footer>}\n </blockquote>\n )\n}\n\nfunction AlertBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const colors: Record<string, string> = {\n info: 'bg-blue-50 border-blue-200 text-blue-800 dark:bg-blue-950 dark:border-blue-800 dark:text-blue-200',\n success: 'bg-green-50 border-green-200 text-green-800 dark:bg-green-950 dark:border-green-800 dark:text-green-200',\n warning: 'bg-yellow-50 border-yellow-200 text-yellow-800 dark:bg-yellow-950 dark:border-yellow-800 dark:text-yellow-200',\n error: 'bg-red-50 border-red-200 text-red-800 dark:bg-red-950 dark:border-red-800 dark:text-red-200',\n }\n const variant = d.variant || d.type || 'info'\n return (\n <div className={`p-4 rounded-lg border ${colors[variant] ?? colors.info}`}>\n {d.title && <div className=\"font-semibold mb-1\">{d.title}</div>}\n <p>{d.message || d.text || ''}</p>\n </div>\n )\n}\n\nfunction DividerBlock() {\n return <hr className=\"my-8 border-border\" />\n}\n\nfunction SpacerBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const sizes: Record<string, string> = { sm: 'h-4', md: 'h-8', lg: 'h-16', xl: 'h-24' }\n return <div className={sizes[d.size] ?? 'h-8'} />\n}\n\nfunction VideoBlock({ block }: { block: CMSBlock }) {\n const d = getData(block)\n const url = d.url || d.embed || ''\n if (!url) return null\n // Convert YouTube/Vimeo watch URLs to embed URLs\n const embedUrl = url\n .replace('youtube.com/watch?v=', 'youtube.com/embed/')\n .replace('youtu.be/', 'youtube.com/embed/')\n .replace('vimeo.com/', 'player.vimeo.com/video/')\n return (\n <div className=\"aspect-video rounded-lg overflow-hidden border bg-muted\">\n <iframe src={embedUrl} allow=\"autoplay; fullscreen\" allowFullScreen className=\"w-full h-full\" title={d.title || 'Video'} />\n </div>\n )\n}\n\n// ── Section block (structured page type sections) ─────────────────────────────\n\nfunction SectionBlock({ block, pageType }: { block: CMSBlock; pageType?: CMSPageType | null }) {\n const d = getData(block)\n const section = pageType?.sections.find(s => s.name === block.type)\n\n // If we have schema info, render labelled fields\n if (section) {\n const filledFields = section.fields.filter(f => d[f.name] !== undefined && d[f.name] !== '' && d[f.name] !== null)\n if (filledFields.length === 0) return null\n return (\n <section className=\"py-4 space-y-4 border-b border-border last:border-0\">\n {filledFields.map(field => {\n const value = d[field.name]\n if (!value && value !== 0 && value !== false) return null\n if (field.fieldType === 'richtext') {\n return (\n <div key={field.id}>\n <p className=\"text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-1\">{field.label}</p>\n <div className=\"prose prose-neutral dark:prose-invert max-w-none text-sm\" dangerouslySetInnerHTML={{ __html: String(value) }} />\n </div>\n )\n }\n if (field.fieldType === 'image') {\n return (\n <figure key={field.id}>\n <img src={String(value)} alt={field.label} className=\"rounded-lg border max-h-96 object-cover\" />\n </figure>\n )\n }\n if (field.fieldType === 'boolean') {\n return (\n <p key={field.id} className=\"text-sm\">\n <span className=\"font-medium\">{field.label}:</span>{' '}\n <span className=\"text-muted-foreground\">{value ? 'Yes' : 'No'}</span>\n </p>\n )\n }\n if (field.fieldType === 'url') {\n return (\n <p key={field.id} className=\"text-sm\">\n <span className=\"font-medium\">{field.label}:</span>{' '}\n <a href={String(value)} className=\"text-primary underline underline-offset-2 break-all\">{String(value)}</a>\n </p>\n )\n }\n return (\n <p key={field.id} className=\"text-sm\">\n <span className=\"font-medium\">{field.label}:</span>{' '}\n <span className=\"text-muted-foreground\">{String(value)}</span>\n </p>\n )\n })}\n </section>\n )\n }\n\n // No schema — render raw data as simple key/value pairs\n const entries = Object.entries(d).filter(([, v]) => v !== '' && v !== null && v !== undefined)\n if (entries.length === 0) return null\n return (\n <section className=\"py-4 space-y-2 border-b border-border last:border-0\">\n {block.label && <h3 className=\"font-semibold text-sm text-muted-foreground uppercase tracking-wide\">{block.label}</h3>}\n {entries.map(([key, value]) => (\n <p key={key} className=\"text-sm\">\n <span className=\"font-medium capitalize\">{key.replace(/_/g, ' ')}:</span>{' '}\n <span className=\"text-muted-foreground\">{String(value)}</span>\n </p>\n ))}\n </section>\n )\n}\n\n// ── Main component ────────────────────────────────────────────────────────────\n\nconst BUILT_IN: Record<string, (block: CMSBlock, pageType?: CMSPageType | null) => React.ReactNode> = {\n heading: (b) => <HeadingBlock block={b} />,\n text: (b) => <TextBlock block={b} />,\n richtext: (b) => <RichTextBlock block={b} />,\n image: (b) => <ImageBlock block={b} />,\n hero: (b) => <HeroBlock block={b} />,\n 'hero-section': (b) => <HeroBlock block={b} />,\n cta: (b) => <CTABlock block={b} />,\n faq: (b) => <FAQBlock block={b} />,\n stats: (b) => <StatsBlock block={b} />,\n testimonial: (b) => <TestimonialBlock block={b} />,\n quote: (b) => <QuoteBlock block={b} />,\n alert: (b) => <AlertBlock block={b} />,\n divider: () => <DividerBlock />,\n spacer: (b) => <SpacerBlock block={b} />,\n video: (b) => <VideoBlock block={b} />,\n}\n\nexport function CMSBlocks({ blocks, pageType, className = '', custom = {} }: CMSBlocksProps) {\n if (!blocks?.length) return null\n\n return (\n <div className={`space-y-8 ${className}`}>\n {blocks.map(block => {\n // 1. Custom renderer takes priority\n if (custom[block.type]) return <React.Fragment key={block.id}>{custom[block.type](block)}</React.Fragment>\n // 2. Built-in renderer\n if (BUILT_IN[block.type]) return <React.Fragment key={block.id}>{BUILT_IN[block.type](block, pageType)}</React.Fragment>\n // 3. Structured section block (from page type sections)\n return <SectionBlock key={block.id} block={block} pageType={pageType} />\n })}\n </div>\n )\n}\n","'use client'\n\nimport React from 'react'\n\nexport interface CMSPreviewBannerProps {\n isPreview: boolean\n status?: string\n slug?: string\n /** URL for the exit preview link. Defaults to /api/cms-preview/exit */\n exitUrl?: string\n}\n\nexport function CMSPreviewBanner({ isPreview, status, slug, exitUrl = '/api/cms-preview/exit' }: CMSPreviewBannerProps) {\n if (!isPreview) return null\n return (\n <div className=\"sticky top-0 z-50 flex items-center justify-between px-4 py-2.5 bg-amber-500 text-white text-sm font-medium shadow\">\n <div className=\"flex items-center gap-2\">\n <svg className=\"w-4 h-4 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\" />\n </svg>\n <span>Draft Preview</span>\n {status && <><span className=\"opacity-60\">·</span><span className=\"opacity-75 capitalize\">{status}</span></>}\n {slug && <><span className=\"opacity-60\">·</span><span className=\"opacity-75 font-normal\">/{slug}</span></>}\n </div>\n <a href={exitUrl} className=\"px-3 py-1 rounded bg-white/20 hover:bg-white/30 transition-colors text-xs\">\n Exit Preview\n </a>\n </div>\n )\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@sprintup-cms/sdk",
3
+ "version": "1.0.0",
4
+ "description": "Official SDK for SprintUp Forge CMS — typed API client, Next.js helpers, and React block renderer",
5
+ "author": "SprintUp <hello@sprintup.io>",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "cms", "headless", "nextjs", "school", "sprintup", "forge"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/sprintup-io/forge-cms"
13
+ },
14
+ "homepage": "https://forgecms.io",
15
+ "sideEffects": false,
16
+ "type": "module",
17
+ "exports": {
18
+ ".": {
19
+ "import": "./dist/client.js",
20
+ "require": "./dist/client.cjs",
21
+ "types": "./dist/client.d.ts"
22
+ },
23
+ "./next": {
24
+ "import": "./dist/next/index.js",
25
+ "require": "./dist/next/index.cjs",
26
+ "types": "./dist/next/index.d.ts"
27
+ },
28
+ "./react": {
29
+ "import": "./dist/react/index.js",
30
+ "require": "./dist/react/index.cjs",
31
+ "types": "./dist/react/index.d.ts"
32
+ }
33
+ },
34
+ "main": "./dist/client.cjs",
35
+ "module": "./dist/client.js",
36
+ "types": "./dist/client.d.ts",
37
+ "files": [
38
+ "dist",
39
+ "README.md",
40
+ "CHANGELOG.md"
41
+ ],
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "dev": "tsup --watch",
45
+ "lint": "tsc --noEmit",
46
+ "prepublishOnly": "npm run lint && npm run build",
47
+ "release": "npm run build && npm publish --access public",
48
+ "release:dry": "npm run build && npm publish --dry-run --access public"
49
+ },
50
+ "peerDependencies": {
51
+ "next": ">=14.0.0",
52
+ "react": ">=18.0.0",
53
+ "react-dom": ">=18.0.0"
54
+ },
55
+ "peerDependenciesMeta": {
56
+ "next": { "optional": true },
57
+ "react": { "optional": true },
58
+ "react-dom": { "optional": true }
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^22.0.0",
62
+ "@types/react": "^18.0.0",
63
+ "next": "^15.0.0",
64
+ "react": "^18.0.0",
65
+ "tsup": "^8.0.0",
66
+ "typescript": "^5.0.0"
67
+ }
68
+ }