@bettercms-ai/ui 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Video-1CG9bFXZ.d.ts → Video-DRC_fPjV.d.ts} +15 -9
- package/dist/blocks.d.ts +1 -1
- package/dist/blocks.js +28 -9
- package/dist/blocks.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +80 -16
- package/dist/index.js.map +1 -1
- package/dist/registry.js +47 -9
- package/dist/registry.js.map +1 -1
- package/dist/renderer.d.ts +5 -2
- package/dist/renderer.js +80 -16
- package/dist/renderer.js.map +1 -1
- package/dist/resolve.d.ts +34 -1
- package/dist/resolve.js +65 -0
- package/dist/resolve.js.map +1 -1
- package/dist/tokens.d.ts +90 -0
- package/dist/tokens.js +66 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +7 -2
|
@@ -2,31 +2,37 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { HeadingProps, TextProps, PortableTextDocument, ImageProps, ButtonProps, SpacerProps, ColumnsProps, ContentBlock, VideoProps } from '@bettercms-ai/types';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/** Preview-only attributes understood by the BetterCMS visual editor. */
|
|
6
|
+
type BcmsBindingProps = {
|
|
7
|
+
"data-bcms-field"?: string;
|
|
8
|
+
"data-bcms-kind"?: "text" | "richtext" | "image";
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
interface HeadingBlockProps extends HeadingProps, BcmsBindingProps {
|
|
6
12
|
className?: string;
|
|
7
13
|
align?: "left" | "center" | "right";
|
|
8
14
|
}
|
|
9
|
-
declare function Heading({ text, level, align, className, }: HeadingBlockProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
declare function Heading({ text, level, align, className, "data-bcms-field": field, "data-bcms-kind": kind, }: HeadingBlockProps): react_jsx_runtime.JSX.Element;
|
|
10
16
|
|
|
11
|
-
interface TextBlockProps extends TextProps {
|
|
17
|
+
interface TextBlockProps extends TextProps, BcmsBindingProps {
|
|
12
18
|
className?: string;
|
|
13
19
|
align?: "left" | "center" | "right";
|
|
14
20
|
/** Portable Text source. WINS over `html`, which is the derived cache. */
|
|
15
21
|
content?: PortableTextDocument;
|
|
16
22
|
}
|
|
17
|
-
declare function Text({ html, content, align, className }: TextBlockProps): react_jsx_runtime.JSX.Element;
|
|
23
|
+
declare function Text({ html, content, align, className, "data-bcms-field": field, "data-bcms-kind": kind, }: TextBlockProps): react_jsx_runtime.JSX.Element;
|
|
18
24
|
|
|
19
|
-
interface ImageBlockProps extends ImageProps {
|
|
25
|
+
interface ImageBlockProps extends ImageProps, BcmsBindingProps {
|
|
20
26
|
className?: string;
|
|
21
27
|
sizes?: string;
|
|
22
28
|
}
|
|
23
|
-
declare function Image({ src, alt, width, height, caption, className, sizes, }: ImageBlockProps): react_jsx_runtime.JSX.Element;
|
|
29
|
+
declare function Image({ src, alt, width, height, caption, className, sizes, "data-bcms-field": field, "data-bcms-kind": kind, }: ImageBlockProps): react_jsx_runtime.JSX.Element;
|
|
24
30
|
|
|
25
|
-
interface ButtonBlockProps extends ButtonProps {
|
|
31
|
+
interface ButtonBlockProps extends ButtonProps, BcmsBindingProps {
|
|
26
32
|
className?: string;
|
|
27
33
|
align?: "left" | "center" | "right";
|
|
28
34
|
}
|
|
29
|
-
declare function Button({ text, href, variant, align, className, }: ButtonBlockProps): react_jsx_runtime.JSX.Element;
|
|
35
|
+
declare function Button({ text, href, variant, align, className, "data-bcms-field": field, "data-bcms-kind": kind, }: ButtonBlockProps): react_jsx_runtime.JSX.Element;
|
|
30
36
|
|
|
31
37
|
interface SpacerBlockProps extends SpacerProps {
|
|
32
38
|
className?: string;
|
|
@@ -44,4 +50,4 @@ interface VideoBlockProps extends VideoProps {
|
|
|
44
50
|
}
|
|
45
51
|
declare function Video({ url, poster, autoplay, loop, className, }: VideoBlockProps): react_jsx_runtime.JSX.Element;
|
|
46
52
|
|
|
47
|
-
export {
|
|
53
|
+
export { type BcmsBindingProps as B, Columns as C, Heading as H, Image as I, Spacer as S, Text as T, Video as V, Button as a };
|
package/dist/blocks.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a as Button, C as Columns, H as Heading, I as Image, S as Spacer, T as Text, V as Video } from './Video-DRC_fPjV.js';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import { SectionProps, ContentBlock, NavbarProps, FooterProps, SliderProps, TabsProps, ComponentProps, FormProps } from '@bettercms-ai/types';
|
|
4
4
|
import React from 'react';
|
package/dist/blocks.js
CHANGED
|
@@ -6,7 +6,9 @@ function Heading({
|
|
|
6
6
|
text,
|
|
7
7
|
level = 2,
|
|
8
8
|
align = "left",
|
|
9
|
-
className = ""
|
|
9
|
+
className = "",
|
|
10
|
+
"data-bcms-field": field,
|
|
11
|
+
"data-bcms-kind": kind
|
|
10
12
|
}) {
|
|
11
13
|
const alignClass = {
|
|
12
14
|
left: "text-left",
|
|
@@ -16,13 +18,13 @@ function Heading({
|
|
|
16
18
|
const classNames = `font-heading font-bold tracking-tight text-foreground ${alignClass} ${className}`;
|
|
17
19
|
switch (level) {
|
|
18
20
|
case 1:
|
|
19
|
-
return /* @__PURE__ */ jsx("h1", { className: classNames, children: text });
|
|
21
|
+
return /* @__PURE__ */ jsx("h1", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
20
22
|
case 2:
|
|
21
|
-
return /* @__PURE__ */ jsx("h2", { className: classNames, children: text });
|
|
23
|
+
return /* @__PURE__ */ jsx("h2", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
22
24
|
case 3:
|
|
23
|
-
return /* @__PURE__ */ jsx("h3", { className: classNames, children: text });
|
|
25
|
+
return /* @__PURE__ */ jsx("h3", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
24
26
|
default:
|
|
25
|
-
return /* @__PURE__ */ jsx("h2", { className: classNames, children: text });
|
|
27
|
+
return /* @__PURE__ */ jsx("h2", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -68,7 +70,14 @@ function PortableText({ doc }) {
|
|
|
68
70
|
|
|
69
71
|
// src/blocks/Text.tsx
|
|
70
72
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
71
|
-
function Text({
|
|
73
|
+
function Text({
|
|
74
|
+
html,
|
|
75
|
+
content,
|
|
76
|
+
align = "left",
|
|
77
|
+
className = "",
|
|
78
|
+
"data-bcms-field": field,
|
|
79
|
+
"data-bcms-kind": kind
|
|
80
|
+
}) {
|
|
72
81
|
const alignClass = {
|
|
73
82
|
left: "text-left",
|
|
74
83
|
center: "text-center",
|
|
@@ -82,6 +91,8 @@ function Text({ html, content, align = "left", className = "" }) {
|
|
|
82
91
|
"div",
|
|
83
92
|
{
|
|
84
93
|
className: cls,
|
|
94
|
+
"data-bcms-field": field,
|
|
95
|
+
"data-bcms-kind": kind,
|
|
85
96
|
dangerouslySetInnerHTML: { __html: html }
|
|
86
97
|
}
|
|
87
98
|
);
|
|
@@ -103,7 +114,9 @@ function Image({
|
|
|
103
114
|
height,
|
|
104
115
|
caption,
|
|
105
116
|
className = "",
|
|
106
|
-
sizes
|
|
117
|
+
sizes,
|
|
118
|
+
"data-bcms-field": field,
|
|
119
|
+
"data-bcms-kind": kind
|
|
107
120
|
}) {
|
|
108
121
|
return /* @__PURE__ */ jsxs("figure", { className: cn("w-full", className), children: [
|
|
109
122
|
/* @__PURE__ */ jsx4(
|
|
@@ -114,6 +127,8 @@ function Image({
|
|
|
114
127
|
width,
|
|
115
128
|
height,
|
|
116
129
|
sizes,
|
|
130
|
+
"data-bcms-field": field,
|
|
131
|
+
"data-bcms-kind": kind,
|
|
117
132
|
className: "w-full h-auto rounded-md object-cover",
|
|
118
133
|
loading: "lazy"
|
|
119
134
|
}
|
|
@@ -129,7 +144,9 @@ function Button({
|
|
|
129
144
|
href,
|
|
130
145
|
variant = "primary",
|
|
131
146
|
align = "left",
|
|
132
|
-
className = ""
|
|
147
|
+
className = "",
|
|
148
|
+
"data-bcms-field": field,
|
|
149
|
+
"data-bcms-kind": kind
|
|
133
150
|
}) {
|
|
134
151
|
const baseStyles = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50";
|
|
135
152
|
const variantStyles = {
|
|
@@ -145,6 +162,8 @@ function Button({
|
|
|
145
162
|
"a",
|
|
146
163
|
{
|
|
147
164
|
href,
|
|
165
|
+
"data-bcms-field": field,
|
|
166
|
+
"data-bcms-kind": kind,
|
|
148
167
|
className: cn(baseStyles, variantStyles[variant], alignClass, "px-4 py-2", className),
|
|
149
168
|
children: text
|
|
150
169
|
}
|
|
@@ -352,7 +371,7 @@ function Tabs({ tabs, className = "", renderBlock }) {
|
|
|
352
371
|
}
|
|
353
372
|
|
|
354
373
|
// src/blocks/Placeholders.tsx
|
|
355
|
-
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
374
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
356
375
|
var box = "rounded border border-dashed border-neutral-300 bg-neutral-50 p-4 text-sm text-neutral-500";
|
|
357
376
|
function ComponentInstance({
|
|
358
377
|
componentId,
|
package/dist/blocks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/blocks/Heading.tsx","../src/blocks/portableText.tsx","../src/blocks/Text.tsx","../src/lib/utils.ts","../src/blocks/Image.tsx","../src/blocks/Button.tsx","../src/blocks/Spacer.tsx","../src/blocks/Columns.tsx","../src/blocks/Video.tsx","../src/blocks/Section.tsx","../src/blocks/Navbar.tsx","../src/blocks/Footer.tsx","../src/blocks/Slider.tsx","../src/blocks/Tabs.tsx","../src/blocks/Placeholders.tsx"],"sourcesContent":["import type { HeadingProps } from \"@bettercms-ai/types\";\n\ninterface HeadingBlockProps extends HeadingProps {\n className?: string;\n align?: \"left\" | \"center\" | \"right\";\n}\n\nexport function Heading({\n text,\n level = 2,\n align = \"left\",\n className = \"\",\n}: HeadingBlockProps) {\n const alignClass = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n }[align];\n\n const classNames = `font-heading font-bold tracking-tight text-foreground ${alignClass} ${className}`;\n\n switch (level) {\n case 1:\n return <h1 className={classNames}>{text}</h1>;\n case 2:\n return <h2 className={classNames}>{text}</h2>;\n case 3:\n return <h3 className={classNames}>{text}</h3>;\n default:\n return <h2 className={classNames}>{text}</h2>;\n }\n}\n","import React from \"react\";\nimport type { PortableTextDocument, PortableTextNode } from \"@bettercms-ai/types\";\n\n/**\n * Portable Text → React.\n *\n * React rather than an HTML string, deliberately: React escapes text children by default, so\n * author data cannot become markup here at all. The `dangerouslySetInnerHTML` path that the\n * `html` cache still uses has to be trusted; this one does not.\n *\n * Unknown marks and unknown styles are DROPPED, never passed through. A colour mark carries a\n * token NAME (`color:brand-accent`) which becomes a class the consuming site styles — so it is\n * theme-aware and survives a rebrand, which a baked hex does not.\n */\n\nconst MARK_TAGS: Record<string, keyof React.JSX.IntrinsicElements> = {\n strong: \"strong\",\n em: \"em\",\n underline: \"u\",\n \"strike-through\": \"s\",\n code: \"code\",\n};\n\nconst BLOCK_TAGS: Record<string, keyof React.JSX.IntrinsicElements> = {\n normal: \"p\",\n h1: \"h1\",\n h2: \"h2\",\n h3: \"h3\",\n h4: \"h4\",\n h5: \"h5\",\n h6: \"h6\",\n blockquote: \"blockquote\",\n};\n\nfunction Span({ node, index }: { node: PortableTextNode; index: number }) {\n const marks = node.marks ?? [];\n const colour = marks.find((m) => m.startsWith(\"color:\"))?.slice(\"color:\".length);\n\n // Text is a React child, so it is escaped by construction.\n let out: React.ReactNode = node.text ?? \"\";\n for (const m of marks) {\n const Tag = MARK_TAGS[m];\n if (Tag) out = <Tag>{out}</Tag>;\n }\n if (colour && /^[a-z0-9-]+$/i.test(colour)) {\n out = <span className={`bcms-color-${colour}`}>{out}</span>;\n }\n return <React.Fragment key={node._key ?? index}>{out}</React.Fragment>;\n}\n\nexport function PortableText({ doc }: { doc: PortableTextDocument }) {\n return (\n <>\n {doc.content.map((block, i) => {\n const Tag = BLOCK_TAGS[block.style ?? \"normal\"] ?? \"p\";\n return (\n <Tag key={block._key ?? i}>\n {(block.children ?? []).map((c, j) => (\n <Span key={c._key ?? j} node={c} index={j} />\n ))}\n </Tag>\n );\n })}\n </>\n );\n}\n","import type { PortableTextDocument, TextProps } from \"@bettercms-ai/types\";\nimport { PortableText } from \"./portableText\";\n\ninterface TextBlockProps extends TextProps {\n className?: string;\n align?: \"left\" | \"center\" | \"right\";\n /** Portable Text source. WINS over `html`, which is the derived cache. */\n content?: PortableTextDocument;\n}\n\nexport function Text({ html, content, align = \"left\", className = \"\" }: TextBlockProps) {\n const alignClass = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n }[align];\n\n const cls = `text-muted-foreground leading-relaxed ${alignClass} ${className}`;\n\n // `content` wins when present — it is the source of truth and renders through React, which\n // escapes by construction. `html` remains the fallback so every block authored before\n // Portable Text existed renders exactly as it always did.\n if (content && content.content.length > 0) {\n return (\n <div className={cls}>\n <PortableText doc={content} />\n </div>\n );\n }\n\n return (\n <div\n className={cls}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { ImageProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\ninterface ImageBlockProps extends ImageProps {\n className?: string;\n sizes?: string;\n}\n\nexport function Image({\n src,\n alt,\n width,\n height,\n caption,\n className = \"\",\n sizes,\n}: ImageBlockProps) {\n return (\n <figure className={cn(\"w-full\", className)}>\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n sizes={sizes}\n className=\"w-full h-auto rounded-md object-cover\"\n loading=\"lazy\"\n />\n {caption && (\n <figcaption className=\"mt-2 text-sm text-muted-foreground text-center italic\">\n {caption}\n </figcaption>\n )}\n </figure>\n );\n}\n","import type { ButtonProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\ninterface ButtonBlockProps extends ButtonProps {\n className?: string;\n align?: \"left\" | \"center\" | \"right\";\n}\n\nexport function Button({\n text,\n href,\n variant = \"primary\",\n align = \"left\",\n className = \"\",\n}: ButtonBlockProps) {\n const baseStyles =\n \"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\";\n\n const variantStyles = {\n primary:\n \"bg-primary text-primary-foreground shadow hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n };\n\n const alignClass = {\n left: \"justify-start\",\n center: \"justify-center\",\n right: \"justify-end\",\n }[align];\n\n return (\n <a\n href={href}\n className={cn(baseStyles, variantStyles[variant], alignClass, \"px-4 py-2\", className)}\n >\n {text}\n </a>\n );\n}\n","import type { SpacerProps } from \"@bettercms-ai/types\";\n\ninterface SpacerBlockProps extends SpacerProps {\n className?: string;\n}\n\nexport function Spacer({ height = 32, className = \"\" }: SpacerBlockProps) {\n return (\n <div\n className={`w-full border border-dashed border-muted-foreground/20 rounded flex items-center justify-center ${className}`}\n style={{ height: `${height}px` }}\n aria-hidden=\"true\"\n >\n <span className=\"text-xs text-muted-foreground/40 select-none\">\n {height}px\n </span>\n </div>\n );\n}\n","import type { ColumnsProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React from \"react\";\n\ninterface ColumnsBlockProps extends ColumnsProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Columns({\n columns,\n gap = 16,\n className = \"\",\n renderBlock,\n}: ColumnsBlockProps) {\n return (\n <div\n className={cn(\"grid w-full\", className)}\n style={{\n gridTemplateColumns: `repeat(${columns.length}, minmax(0, 1fr))`,\n gap: `${gap}px`,\n }}\n >\n {columns.map((columnBlocks, colIndex) => (\n <div key={colIndex} className=\"flex flex-col gap-4 min-w-0\">\n {columnBlocks.map((block) => (\n <span key={block.id}>\n {renderBlock ? renderBlock(block) : null}\n </span>\n ))}\n </div>\n ))}\n </div>\n );\n}\n","import type { VideoProps } from \"@bettercms-ai/types\";\nimport { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\n\ninterface VideoBlockProps extends VideoProps {\n className?: string;\n}\n\nfunction getEmbedUrl(url: string): { embedUrl: string; provider: \"youtube\" | \"vimeo\" | \"unknown\" } {\n // YouTube\n const ytMatch = url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/\n );\n if (ytMatch) {\n return {\n embedUrl: `https://www.youtube.com/embed/${ytMatch[1]}`,\n provider: \"youtube\",\n };\n }\n\n // Vimeo\n const vimeoMatch = url.match(/vimeo\\.com\\/(\\d+)/);\n if (vimeoMatch) {\n return {\n embedUrl: `https://player.vimeo.com/video/${vimeoMatch[1]}`,\n provider: \"vimeo\",\n };\n }\n\n return { embedUrl: url, provider: \"unknown\" };\n}\n\nexport function Video({\n url,\n poster,\n autoplay = false,\n loop = false,\n className = \"\",\n}: VideoBlockProps) {\n const [isLoaded, setIsLoaded] = useState(false);\n const { embedUrl, provider } = getEmbedUrl(url);\n\n // If not a recognized embed, render a native video tag\n if (provider === \"unknown\") {\n return (\n <video\n src={url}\n poster={poster}\n autoPlay={autoplay}\n loop={loop}\n controls\n className={className}\n playsInline\n />\n );\n }\n\n return (\n <div className={cn(\"w-full overflow-hidden rounded-md bg-black aspect-video\", className)}>\n {!isLoaded && poster && (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={poster}\n alt=\"Video thumbnail\"\n className=\"w-full h-full object-cover absolute inset-0\"\n />\n )}\n <iframe\n src={`${embedUrl}?autoplay=${autoplay ? 1 : 0}&loop=${loop ? 1 : 0}&mute=${autoplay ? 1 : 0}`}\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n loading=\"lazy\"\n onLoad={() => setIsLoaded(true)}\n className=\"w-full h-full\"\n />\n </div>\n );\n}\n","import type { SectionProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React from \"react\";\n\ninterface SectionBlockProps extends SectionProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Section({\n children,\n background,\n paddingY,\n maxWidth,\n className = \"\",\n renderBlock,\n}: SectionBlockProps) {\n const inner = (children ?? []).map((block) => (\n <span key={block.id}>{renderBlock ? renderBlock(block) : null}</span>\n ));\n return (\n <section\n className={cn(\"w-full\", className)}\n style={{ background, paddingTop: paddingY, paddingBottom: paddingY }}\n >\n {maxWidth ? <div style={{ maxWidth, marginInline: \"auto\" }}>{inner}</div> : inner}\n </section>\n );\n}\n","import type { NavbarProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\ninterface NavbarBlockProps extends NavbarProps {\n className?: string;\n}\n\nexport function Navbar({ logo, links, cta, className = \"\" }: NavbarBlockProps) {\n return (\n <nav className={cn(\"flex items-center gap-6 py-4\", className)}>\n {logo?.src ? (\n <a href={logo.href ?? \"/\"} className=\"shrink-0\">\n <img src={logo.src} alt={logo.alt} className=\"h-8 w-auto\" />\n </a>\n ) : null}\n <div className=\"flex flex-1 gap-5\">\n {(links ?? []).map((l, i) => (\n <a key={i} href={l.href} className=\"text-inherit no-underline\">\n {l.label}\n </a>\n ))}\n </div>\n {cta ? (\n <a\n href={cta.href}\n className=\"rounded-lg bg-black px-4 py-2 font-semibold text-white no-underline\"\n >\n {cta.text}\n </a>\n ) : null}\n </nav>\n );\n}\n","import type { FooterProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\ninterface FooterBlockProps extends FooterProps {\n className?: string;\n}\n\nexport function Footer({ columns, copyright, className = \"\" }: FooterBlockProps) {\n return (\n <footer className={cn(\"mt-12 border-t pt-8\", className)}>\n <div className=\"flex flex-wrap gap-12\">\n {(columns ?? []).map((col, i) => (\n <div key={i} className=\"flex flex-col gap-1.5\">\n {col.heading ? <h4 className=\"mb-2 font-semibold\">{col.heading}</h4> : null}\n {(col.links ?? []).map((l, j) => (\n <a key={j} href={l.href} className=\"text-neutral-500 no-underline\">\n {l.label}\n </a>\n ))}\n </div>\n ))}\n </div>\n {copyright ? <p className=\"mt-6 text-sm text-neutral-500\">{copyright}</p> : null}\n </footer>\n );\n}\n","\"use client\";\n\nimport type { SliderProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React, { useState } from \"react\";\n\ninterface SliderBlockProps extends SliderProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Slider({ slides, className = \"\", renderBlock }: SliderBlockProps) {\n const [i, setI] = useState(0);\n const list = slides ?? [];\n const go = (n: number) => setI((n + list.length) % (list.length || 1));\n const btn =\n \"absolute top-1/2 -translate-y-1/2 flex h-9 w-9 items-center justify-center rounded-full border-0 bg-black/50 text-white cursor-pointer\";\n return (\n <div className={cn(\"relative w-full\", className)}>\n {list.map((s, idx) => (\n <div key={s.id} hidden={idx !== i} className=\"flex flex-col gap-4\">\n {(s.children ?? []).map((b) => (\n <span key={b.id}>{renderBlock ? renderBlock(b) : null}</span>\n ))}\n </div>\n ))}\n <button type=\"button\" aria-label=\"Previous\" onClick={() => go(i - 1)} className={cn(btn, \"left-2\")}>\n ‹\n </button>\n <button type=\"button\" aria-label=\"Next\" onClick={() => go(i + 1)} className={cn(btn, \"right-2\")}>\n ›\n </button>\n </div>\n );\n}\n","\"use client\";\n\nimport type { TabsProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React, { useState } from \"react\";\n\ninterface TabsBlockProps extends TabsProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Tabs({ tabs, className = \"\", renderBlock }: TabsBlockProps) {\n const [active, setActive] = useState(0);\n const list = tabs ?? [];\n return (\n <div className={cn(\"w-full\", className)}>\n <div role=\"tablist\" className=\"mb-4 flex gap-1 border-b\">\n {list.map((t, idx) => (\n <button\n key={t.id}\n role=\"tab\"\n type=\"button\"\n aria-selected={idx === active}\n onClick={() => setActive(idx)}\n className={cn(\n \"cursor-pointer border-b-2 border-transparent bg-transparent px-4 py-2\",\n idx === active && \"border-black font-semibold\",\n )}\n >\n {t.label}\n </button>\n ))}\n </div>\n {list.map((t, idx) => (\n <div key={t.id} role=\"tabpanel\" hidden={idx !== active} className=\"flex flex-col gap-4\">\n {(t.children ?? []).map((b) => (\n <span key={b.id}>{renderBlock ? renderBlock(b) : null}</span>\n ))}\n </div>\n ))}\n </div>\n );\n}\n","import type { ComponentProps as BcmsComponentProps, FormProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\nconst box =\n \"rounded border border-dashed border-neutral-300 bg-neutral-50 p-4 text-sm text-neutral-500\";\n\n/**\n * Builder-preview placeholder for a `component` instance. Live instance resolution\n * (definition lookup + override merge) happens server-side in the delivery renderer\n * and in the page-builder, which pass a resolver — the standalone library preview\n * just shows what's referenced.\n */\nexport function ComponentInstance({\n componentId,\n className = \"\",\n}: BcmsComponentProps & { className?: string }) {\n return (\n <div className={cn(box, className)}>\n Component instance: <code>{componentId}</code>\n </div>\n );\n}\n\n/** Builder-preview placeholder for a `form` block (rendered live by @bettercms-ai/next). */\nexport function FormPlaceholder({ formId, className = \"\" }: FormProps & { className?: string }) {\n return (\n <div className={cn(box, className)}>\n Form: <code>{formId}</code>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsxs","useState","jsx","jsxs","useState","jsx","jsxs","jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/blocks/Heading.tsx","../src/blocks/portableText.tsx","../src/blocks/Text.tsx","../src/lib/utils.ts","../src/blocks/Image.tsx","../src/blocks/Button.tsx","../src/blocks/Spacer.tsx","../src/blocks/Columns.tsx","../src/blocks/Video.tsx","../src/blocks/Section.tsx","../src/blocks/Navbar.tsx","../src/blocks/Footer.tsx","../src/blocks/Slider.tsx","../src/blocks/Tabs.tsx","../src/blocks/Placeholders.tsx"],"sourcesContent":["import type { HeadingProps } from \"@bettercms-ai/types\";\nimport type { BcmsBindingProps } from \"../binding\";\n\ninterface HeadingBlockProps extends HeadingProps, BcmsBindingProps {\n className?: string;\n align?: \"left\" | \"center\" | \"right\";\n}\n\nexport function Heading({\n text,\n level = 2,\n align = \"left\",\n className = \"\",\n \"data-bcms-field\": field,\n \"data-bcms-kind\": kind,\n}: HeadingBlockProps) {\n const alignClass = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n }[align];\n\n const classNames = `font-heading font-bold tracking-tight text-foreground ${alignClass} ${className}`;\n\n switch (level) {\n case 1:\n return <h1 className={classNames} data-bcms-field={field} data-bcms-kind={kind}>{text}</h1>;\n case 2:\n return <h2 className={classNames} data-bcms-field={field} data-bcms-kind={kind}>{text}</h2>;\n case 3:\n return <h3 className={classNames} data-bcms-field={field} data-bcms-kind={kind}>{text}</h3>;\n default:\n return <h2 className={classNames} data-bcms-field={field} data-bcms-kind={kind}>{text}</h2>;\n }\n}\n","import React from \"react\";\nimport type { PortableTextDocument, PortableTextNode } from \"@bettercms-ai/types\";\n\n/**\n * Portable Text → React.\n *\n * React rather than an HTML string, deliberately: React escapes text children by default, so\n * author data cannot become markup here at all. The `dangerouslySetInnerHTML` path that the\n * `html` cache still uses has to be trusted; this one does not.\n *\n * Unknown marks and unknown styles are DROPPED, never passed through. A colour mark carries a\n * token NAME (`color:brand-accent`) which becomes a class the consuming site styles — so it is\n * theme-aware and survives a rebrand, which a baked hex does not.\n */\n\nconst MARK_TAGS: Record<string, keyof React.JSX.IntrinsicElements> = {\n strong: \"strong\",\n em: \"em\",\n underline: \"u\",\n \"strike-through\": \"s\",\n code: \"code\",\n};\n\nconst BLOCK_TAGS: Record<string, keyof React.JSX.IntrinsicElements> = {\n normal: \"p\",\n h1: \"h1\",\n h2: \"h2\",\n h3: \"h3\",\n h4: \"h4\",\n h5: \"h5\",\n h6: \"h6\",\n blockquote: \"blockquote\",\n};\n\nfunction Span({ node, index }: { node: PortableTextNode; index: number }) {\n const marks = node.marks ?? [];\n const colour = marks.find((m) => m.startsWith(\"color:\"))?.slice(\"color:\".length);\n\n // Text is a React child, so it is escaped by construction.\n let out: React.ReactNode = node.text ?? \"\";\n for (const m of marks) {\n const Tag = MARK_TAGS[m];\n if (Tag) out = <Tag>{out}</Tag>;\n }\n if (colour && /^[a-z0-9-]+$/i.test(colour)) {\n out = <span className={`bcms-color-${colour}`}>{out}</span>;\n }\n return <React.Fragment key={node._key ?? index}>{out}</React.Fragment>;\n}\n\nexport function PortableText({ doc }: { doc: PortableTextDocument }) {\n return (\n <>\n {doc.content.map((block, i) => {\n const Tag = BLOCK_TAGS[block.style ?? \"normal\"] ?? \"p\";\n return (\n <Tag key={block._key ?? i}>\n {(block.children ?? []).map((c, j) => (\n <Span key={c._key ?? j} node={c} index={j} />\n ))}\n </Tag>\n );\n })}\n </>\n );\n}\n","import type { PortableTextDocument, TextProps } from \"@bettercms-ai/types\";\nimport { PortableText } from \"./portableText\";\nimport type { BcmsBindingProps } from \"../binding\";\n\ninterface TextBlockProps extends TextProps, BcmsBindingProps {\n className?: string;\n align?: \"left\" | \"center\" | \"right\";\n /** Portable Text source. WINS over `html`, which is the derived cache. */\n content?: PortableTextDocument;\n}\n\nexport function Text({\n html,\n content,\n align = \"left\",\n className = \"\",\n \"data-bcms-field\": field,\n \"data-bcms-kind\": kind,\n}: TextBlockProps) {\n const alignClass = {\n left: \"text-left\",\n center: \"text-center\",\n right: \"text-right\",\n }[align];\n\n const cls = `text-muted-foreground leading-relaxed ${alignClass} ${className}`;\n\n // `content` wins when present — it is the source of truth and renders through React, which\n // escapes by construction. `html` remains the fallback so every block authored before\n // Portable Text existed renders exactly as it always did.\n if (content && content.content.length > 0) {\n return (\n <div className={cls}>\n <PortableText doc={content} />\n </div>\n );\n }\n\n return (\n <div\n className={cls}\n data-bcms-field={field}\n data-bcms-kind={kind}\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: html }}\n />\n );\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import type { ImageProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport type { BcmsBindingProps } from \"../binding\";\n\ninterface ImageBlockProps extends ImageProps, BcmsBindingProps {\n className?: string;\n sizes?: string;\n}\n\nexport function Image({\n src,\n alt,\n width,\n height,\n caption,\n className = \"\",\n sizes,\n \"data-bcms-field\": field,\n \"data-bcms-kind\": kind,\n}: ImageBlockProps) {\n return (\n <figure className={cn(\"w-full\", className)}>\n <img\n src={src}\n alt={alt}\n width={width}\n height={height}\n sizes={sizes}\n data-bcms-field={field}\n data-bcms-kind={kind}\n className=\"w-full h-auto rounded-md object-cover\"\n loading=\"lazy\"\n />\n {caption && (\n <figcaption className=\"mt-2 text-sm text-muted-foreground text-center italic\">\n {caption}\n </figcaption>\n )}\n </figure>\n );\n}\n","import type { ButtonProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport type { BcmsBindingProps } from \"../binding\";\n\ninterface ButtonBlockProps extends ButtonProps, BcmsBindingProps {\n className?: string;\n align?: \"left\" | \"center\" | \"right\";\n}\n\nexport function Button({\n text,\n href,\n variant = \"primary\",\n align = \"left\",\n className = \"\",\n \"data-bcms-field\": field,\n \"data-bcms-kind\": kind,\n}: ButtonBlockProps) {\n const baseStyles =\n \"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50\";\n\n const variantStyles = {\n primary:\n \"bg-primary text-primary-foreground shadow hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80\",\n };\n\n const alignClass = {\n left: \"justify-start\",\n center: \"justify-center\",\n right: \"justify-end\",\n }[align];\n\n return (\n <a\n href={href}\n data-bcms-field={field}\n data-bcms-kind={kind}\n className={cn(baseStyles, variantStyles[variant], alignClass, \"px-4 py-2\", className)}\n >\n {text}\n </a>\n );\n}\n","import type { SpacerProps } from \"@bettercms-ai/types\";\n\ninterface SpacerBlockProps extends SpacerProps {\n className?: string;\n}\n\nexport function Spacer({ height = 32, className = \"\" }: SpacerBlockProps) {\n return (\n <div\n className={`w-full border border-dashed border-muted-foreground/20 rounded flex items-center justify-center ${className}`}\n style={{ height: `${height}px` }}\n aria-hidden=\"true\"\n >\n <span className=\"text-xs text-muted-foreground/40 select-none\">\n {height}px\n </span>\n </div>\n );\n}\n","import type { ColumnsProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React from \"react\";\n\ninterface ColumnsBlockProps extends ColumnsProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Columns({\n columns,\n gap = 16,\n className = \"\",\n renderBlock,\n}: ColumnsBlockProps) {\n return (\n <div\n className={cn(\"grid w-full\", className)}\n style={{\n gridTemplateColumns: `repeat(${columns.length}, minmax(0, 1fr))`,\n gap: `${gap}px`,\n }}\n >\n {columns.map((columnBlocks, colIndex) => (\n <div key={colIndex} className=\"flex flex-col gap-4 min-w-0\">\n {columnBlocks.map((block) => (\n <span key={block.id}>\n {renderBlock ? renderBlock(block) : null}\n </span>\n ))}\n </div>\n ))}\n </div>\n );\n}\n","import type { VideoProps } from \"@bettercms-ai/types\";\nimport { useState } from \"react\";\nimport { cn } from \"../lib/utils\";\n\ninterface VideoBlockProps extends VideoProps {\n className?: string;\n}\n\nfunction getEmbedUrl(url: string): { embedUrl: string; provider: \"youtube\" | \"vimeo\" | \"unknown\" } {\n // YouTube\n const ytMatch = url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/\n );\n if (ytMatch) {\n return {\n embedUrl: `https://www.youtube.com/embed/${ytMatch[1]}`,\n provider: \"youtube\",\n };\n }\n\n // Vimeo\n const vimeoMatch = url.match(/vimeo\\.com\\/(\\d+)/);\n if (vimeoMatch) {\n return {\n embedUrl: `https://player.vimeo.com/video/${vimeoMatch[1]}`,\n provider: \"vimeo\",\n };\n }\n\n return { embedUrl: url, provider: \"unknown\" };\n}\n\nexport function Video({\n url,\n poster,\n autoplay = false,\n loop = false,\n className = \"\",\n}: VideoBlockProps) {\n const [isLoaded, setIsLoaded] = useState(false);\n const { embedUrl, provider } = getEmbedUrl(url);\n\n // If not a recognized embed, render a native video tag\n if (provider === \"unknown\") {\n return (\n <video\n src={url}\n poster={poster}\n autoPlay={autoplay}\n loop={loop}\n controls\n className={className}\n playsInline\n />\n );\n }\n\n return (\n <div className={cn(\"w-full overflow-hidden rounded-md bg-black aspect-video\", className)}>\n {!isLoaded && poster && (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={poster}\n alt=\"Video thumbnail\"\n className=\"w-full h-full object-cover absolute inset-0\"\n />\n )}\n <iframe\n src={`${embedUrl}?autoplay=${autoplay ? 1 : 0}&loop=${loop ? 1 : 0}&mute=${autoplay ? 1 : 0}`}\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n allowFullScreen\n loading=\"lazy\"\n onLoad={() => setIsLoaded(true)}\n className=\"w-full h-full\"\n />\n </div>\n );\n}\n","import type { SectionProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React from \"react\";\n\ninterface SectionBlockProps extends SectionProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Section({\n children,\n background,\n paddingY,\n maxWidth,\n className = \"\",\n renderBlock,\n}: SectionBlockProps) {\n const inner = (children ?? []).map((block) => (\n <span key={block.id}>{renderBlock ? renderBlock(block) : null}</span>\n ));\n return (\n <section\n className={cn(\"w-full\", className)}\n style={{ background, paddingTop: paddingY, paddingBottom: paddingY }}\n >\n {maxWidth ? <div style={{ maxWidth, marginInline: \"auto\" }}>{inner}</div> : inner}\n </section>\n );\n}\n","import type { NavbarProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\ninterface NavbarBlockProps extends NavbarProps {\n className?: string;\n}\n\nexport function Navbar({ logo, links, cta, className = \"\" }: NavbarBlockProps) {\n return (\n <nav className={cn(\"flex items-center gap-6 py-4\", className)}>\n {logo?.src ? (\n <a href={logo.href ?? \"/\"} className=\"shrink-0\">\n <img src={logo.src} alt={logo.alt} className=\"h-8 w-auto\" />\n </a>\n ) : null}\n <div className=\"flex flex-1 gap-5\">\n {(links ?? []).map((l, i) => (\n <a key={i} href={l.href} className=\"text-inherit no-underline\">\n {l.label}\n </a>\n ))}\n </div>\n {cta ? (\n <a\n href={cta.href}\n className=\"rounded-lg bg-black px-4 py-2 font-semibold text-white no-underline\"\n >\n {cta.text}\n </a>\n ) : null}\n </nav>\n );\n}\n","import type { FooterProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\ninterface FooterBlockProps extends FooterProps {\n className?: string;\n}\n\nexport function Footer({ columns, copyright, className = \"\" }: FooterBlockProps) {\n return (\n <footer className={cn(\"mt-12 border-t pt-8\", className)}>\n <div className=\"flex flex-wrap gap-12\">\n {(columns ?? []).map((col, i) => (\n <div key={i} className=\"flex flex-col gap-1.5\">\n {col.heading ? <h4 className=\"mb-2 font-semibold\">{col.heading}</h4> : null}\n {(col.links ?? []).map((l, j) => (\n <a key={j} href={l.href} className=\"text-neutral-500 no-underline\">\n {l.label}\n </a>\n ))}\n </div>\n ))}\n </div>\n {copyright ? <p className=\"mt-6 text-sm text-neutral-500\">{copyright}</p> : null}\n </footer>\n );\n}\n","\"use client\";\n\nimport type { SliderProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React, { useState } from \"react\";\n\ninterface SliderBlockProps extends SliderProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Slider({ slides, className = \"\", renderBlock }: SliderBlockProps) {\n const [i, setI] = useState(0);\n const list = slides ?? [];\n const go = (n: number) => setI((n + list.length) % (list.length || 1));\n const btn =\n \"absolute top-1/2 -translate-y-1/2 flex h-9 w-9 items-center justify-center rounded-full border-0 bg-black/50 text-white cursor-pointer\";\n return (\n <div className={cn(\"relative w-full\", className)}>\n {list.map((s, idx) => (\n <div key={s.id} hidden={idx !== i} className=\"flex flex-col gap-4\">\n {(s.children ?? []).map((b) => (\n <span key={b.id}>{renderBlock ? renderBlock(b) : null}</span>\n ))}\n </div>\n ))}\n <button type=\"button\" aria-label=\"Previous\" onClick={() => go(i - 1)} className={cn(btn, \"left-2\")}>\n ‹\n </button>\n <button type=\"button\" aria-label=\"Next\" onClick={() => go(i + 1)} className={cn(btn, \"right-2\")}>\n ›\n </button>\n </div>\n );\n}\n","\"use client\";\n\nimport type { TabsProps, ContentBlock } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\nimport React, { useState } from \"react\";\n\ninterface TabsBlockProps extends TabsProps {\n className?: string;\n renderBlock?: (block: ContentBlock) => React.ReactNode;\n}\n\nexport function Tabs({ tabs, className = \"\", renderBlock }: TabsBlockProps) {\n const [active, setActive] = useState(0);\n const list = tabs ?? [];\n return (\n <div className={cn(\"w-full\", className)}>\n <div role=\"tablist\" className=\"mb-4 flex gap-1 border-b\">\n {list.map((t, idx) => (\n <button\n key={t.id}\n role=\"tab\"\n type=\"button\"\n aria-selected={idx === active}\n onClick={() => setActive(idx)}\n className={cn(\n \"cursor-pointer border-b-2 border-transparent bg-transparent px-4 py-2\",\n idx === active && \"border-black font-semibold\",\n )}\n >\n {t.label}\n </button>\n ))}\n </div>\n {list.map((t, idx) => (\n <div key={t.id} role=\"tabpanel\" hidden={idx !== active} className=\"flex flex-col gap-4\">\n {(t.children ?? []).map((b) => (\n <span key={b.id}>{renderBlock ? renderBlock(b) : null}</span>\n ))}\n </div>\n ))}\n </div>\n );\n}\n","import type { ComponentProps as BcmsComponentProps, FormProps, CollectionProps } from \"@bettercms-ai/types\";\nimport { cn } from \"../lib/utils\";\n\nconst box =\n \"rounded border border-dashed border-neutral-300 bg-neutral-50 p-4 text-sm text-neutral-500\";\n\n/**\n * Builder-preview placeholder for a `component` instance. Live instance resolution\n * (definition lookup + override merge) happens server-side in the delivery renderer\n * and in the page-builder, which pass a resolver — the standalone library preview\n * just shows what's referenced.\n */\nexport function ComponentInstance({\n componentId,\n className = \"\",\n}: BcmsComponentProps & { className?: string }) {\n return (\n <div className={cn(box, className)}>\n Component instance: <code>{componentId}</code>\n </div>\n );\n}\n\n/** Builder-preview placeholder for a `form` block (rendered live by @bettercms-ai/next). */\nexport function FormPlaceholder({ formId, className = \"\" }: FormProps & { className?: string }) {\n return (\n <div className={cn(box, className)}>\n Form: <code>{formId}</code>\n </div>\n );\n}\n\n/**\n * Builder-preview placeholder for a `collection` block.\n *\n * The builder canvas has no entries to list — the list is fetched per request by the site\n * renderer, deliberately, so that a published snapshot can never bake in a stale set of\n * posts. A placeholder is therefore the honest render here, not a limitation.\n */\nexport function CollectionPlaceholder({\n cardComponentId,\n className = \"\",\n}: CollectionProps & { className?: string }) {\n return (\n <div className={cn(box, className)}>\n Collection: entries of this page\n {cardComponentId ? <> as <code>{cardComponentId}</code></> : <> (default card)</>}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsx","jsxs","jsx","jsxs","useState","jsx","jsxs","useState","jsx","jsxs","Fragment","jsx","jsxs"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as Button, C as Columns, H as Heading, I as Image, S as Spacer, T as Text, V as Video } from './Video-
|
|
1
|
+
export { B as BcmsBindingProps, a as Button, C as Columns, H as Heading, I as Image, S as Spacer, T as Text, V as Video } from './Video-DRC_fPjV.js';
|
|
2
2
|
export { BLOCK_REGISTRY, BLOCK_TYPES, BlockRegistryEntry } from './registry.js';
|
|
3
3
|
export { BlockRenderer, BlocksRenderer } from './renderer.js';
|
|
4
4
|
import { ClassValue } from 'clsx';
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,9 @@ function Heading({
|
|
|
6
6
|
text,
|
|
7
7
|
level = 2,
|
|
8
8
|
align = "left",
|
|
9
|
-
className = ""
|
|
9
|
+
className = "",
|
|
10
|
+
"data-bcms-field": field,
|
|
11
|
+
"data-bcms-kind": kind
|
|
10
12
|
}) {
|
|
11
13
|
const alignClass = {
|
|
12
14
|
left: "text-left",
|
|
@@ -16,13 +18,13 @@ function Heading({
|
|
|
16
18
|
const classNames = `font-heading font-bold tracking-tight text-foreground ${alignClass} ${className}`;
|
|
17
19
|
switch (level) {
|
|
18
20
|
case 1:
|
|
19
|
-
return /* @__PURE__ */ jsx("h1", { className: classNames, children: text });
|
|
21
|
+
return /* @__PURE__ */ jsx("h1", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
20
22
|
case 2:
|
|
21
|
-
return /* @__PURE__ */ jsx("h2", { className: classNames, children: text });
|
|
23
|
+
return /* @__PURE__ */ jsx("h2", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
22
24
|
case 3:
|
|
23
|
-
return /* @__PURE__ */ jsx("h3", { className: classNames, children: text });
|
|
25
|
+
return /* @__PURE__ */ jsx("h3", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
24
26
|
default:
|
|
25
|
-
return /* @__PURE__ */ jsx("h2", { className: classNames, children: text });
|
|
27
|
+
return /* @__PURE__ */ jsx("h2", { className: classNames, "data-bcms-field": field, "data-bcms-kind": kind, children: text });
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -68,7 +70,14 @@ function PortableText({ doc }) {
|
|
|
68
70
|
|
|
69
71
|
// src/blocks/Text.tsx
|
|
70
72
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
71
|
-
function Text({
|
|
73
|
+
function Text({
|
|
74
|
+
html,
|
|
75
|
+
content,
|
|
76
|
+
align = "left",
|
|
77
|
+
className = "",
|
|
78
|
+
"data-bcms-field": field,
|
|
79
|
+
"data-bcms-kind": kind
|
|
80
|
+
}) {
|
|
72
81
|
const alignClass = {
|
|
73
82
|
left: "text-left",
|
|
74
83
|
center: "text-center",
|
|
@@ -82,6 +91,8 @@ function Text({ html, content, align = "left", className = "" }) {
|
|
|
82
91
|
"div",
|
|
83
92
|
{
|
|
84
93
|
className: cls,
|
|
94
|
+
"data-bcms-field": field,
|
|
95
|
+
"data-bcms-kind": kind,
|
|
85
96
|
dangerouslySetInnerHTML: { __html: html }
|
|
86
97
|
}
|
|
87
98
|
);
|
|
@@ -103,7 +114,9 @@ function Image({
|
|
|
103
114
|
height,
|
|
104
115
|
caption,
|
|
105
116
|
className = "",
|
|
106
|
-
sizes
|
|
117
|
+
sizes,
|
|
118
|
+
"data-bcms-field": field,
|
|
119
|
+
"data-bcms-kind": kind
|
|
107
120
|
}) {
|
|
108
121
|
return /* @__PURE__ */ jsxs("figure", { className: cn("w-full", className), children: [
|
|
109
122
|
/* @__PURE__ */ jsx4(
|
|
@@ -114,6 +127,8 @@ function Image({
|
|
|
114
127
|
width,
|
|
115
128
|
height,
|
|
116
129
|
sizes,
|
|
130
|
+
"data-bcms-field": field,
|
|
131
|
+
"data-bcms-kind": kind,
|
|
117
132
|
className: "w-full h-auto rounded-md object-cover",
|
|
118
133
|
loading: "lazy"
|
|
119
134
|
}
|
|
@@ -129,7 +144,9 @@ function Button({
|
|
|
129
144
|
href,
|
|
130
145
|
variant = "primary",
|
|
131
146
|
align = "left",
|
|
132
|
-
className = ""
|
|
147
|
+
className = "",
|
|
148
|
+
"data-bcms-field": field,
|
|
149
|
+
"data-bcms-kind": kind
|
|
133
150
|
}) {
|
|
134
151
|
const baseStyles = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50";
|
|
135
152
|
const variantStyles = {
|
|
@@ -145,6 +162,8 @@ function Button({
|
|
|
145
162
|
"a",
|
|
146
163
|
{
|
|
147
164
|
href,
|
|
165
|
+
"data-bcms-field": field,
|
|
166
|
+
"data-bcms-kind": kind,
|
|
148
167
|
className: cn(baseStyles, variantStyles[variant], alignClass, "px-4 py-2", className),
|
|
149
168
|
children: text
|
|
150
169
|
}
|
|
@@ -352,7 +371,7 @@ function Tabs({ tabs, className = "", renderBlock }) {
|
|
|
352
371
|
}
|
|
353
372
|
|
|
354
373
|
// src/blocks/Placeholders.tsx
|
|
355
|
-
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
374
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
356
375
|
var box = "rounded border border-dashed border-neutral-300 bg-neutral-50 p-4 text-sm text-neutral-500";
|
|
357
376
|
function ComponentInstance({
|
|
358
377
|
componentId,
|
|
@@ -369,9 +388,28 @@ function FormPlaceholder({ formId, className = "" }) {
|
|
|
369
388
|
/* @__PURE__ */ jsx14("code", { children: formId })
|
|
370
389
|
] });
|
|
371
390
|
}
|
|
391
|
+
function CollectionPlaceholder({
|
|
392
|
+
cardComponentId,
|
|
393
|
+
className = ""
|
|
394
|
+
}) {
|
|
395
|
+
return /* @__PURE__ */ jsxs8("div", { className: cn(box, className), children: [
|
|
396
|
+
"Collection: entries of this page",
|
|
397
|
+
cardComponentId ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
398
|
+
" as ",
|
|
399
|
+
/* @__PURE__ */ jsx14("code", { children: cardComponentId })
|
|
400
|
+
] }) : /* @__PURE__ */ jsx14(Fragment2, { children: " (default card)" })
|
|
401
|
+
] });
|
|
402
|
+
}
|
|
372
403
|
|
|
373
404
|
// src/registry.ts
|
|
374
405
|
var BLOCK_REGISTRY = {
|
|
406
|
+
// The entries of the page this block sits on. No preview here by design: the list is
|
|
407
|
+
// fetched per request by the site renderer, so the builder has nothing to show.
|
|
408
|
+
collection: {
|
|
409
|
+
component: CollectionPlaceholder,
|
|
410
|
+
label: "Collection",
|
|
411
|
+
icon: "list"
|
|
412
|
+
},
|
|
375
413
|
heading: {
|
|
376
414
|
component: Heading,
|
|
377
415
|
label: "Heading",
|
|
@@ -463,7 +501,22 @@ function blockStyleToReactStyle(style) {
|
|
|
463
501
|
import "react";
|
|
464
502
|
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
465
503
|
var CONTAINER_TYPES = /* @__PURE__ */ new Set(["columns", "section", "slider", "tabs"]);
|
|
466
|
-
function
|
|
504
|
+
function bindingProps(block, annotate) {
|
|
505
|
+
if (!annotate || !block.id) return {};
|
|
506
|
+
switch (block.type) {
|
|
507
|
+
case "heading":
|
|
508
|
+
case "button":
|
|
509
|
+
return { "data-bcms-field": `${block.id}__text`, "data-bcms-kind": "text" };
|
|
510
|
+
case "text":
|
|
511
|
+
case "richtext":
|
|
512
|
+
return { "data-bcms-field": `${block.id}__html`, "data-bcms-kind": "richtext" };
|
|
513
|
+
case "image":
|
|
514
|
+
return { "data-bcms-field": `${block.id}__src`, "data-bcms-kind": "image" };
|
|
515
|
+
default:
|
|
516
|
+
return {};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
function resolveBlock(block, className, annotate = false) {
|
|
467
520
|
const entry = BLOCK_REGISTRY[block.type];
|
|
468
521
|
if (!entry) {
|
|
469
522
|
return /* @__PURE__ */ jsxs9(
|
|
@@ -479,13 +532,14 @@ function resolveBlock(block, className) {
|
|
|
479
532
|
}
|
|
480
533
|
const Component = entry.component;
|
|
481
534
|
const blockStyle = blockStyleToReactStyle(block.style);
|
|
482
|
-
const el = /* @__PURE__ */ jsx15(Component, { ...block.props, className });
|
|
535
|
+
const el = /* @__PURE__ */ jsx15(Component, { ...block.props, className, ...bindingProps(block, annotate) });
|
|
483
536
|
return blockStyle ? /* @__PURE__ */ jsx15("div", { style: blockStyle, children: el }) : el;
|
|
484
537
|
}
|
|
485
538
|
function BlockRenderer({
|
|
486
539
|
block,
|
|
487
540
|
className = "",
|
|
488
|
-
renderBlock
|
|
541
|
+
renderBlock,
|
|
542
|
+
annotate = false
|
|
489
543
|
}) {
|
|
490
544
|
const entry = BLOCK_REGISTRY[block.type];
|
|
491
545
|
if (!entry) {
|
|
@@ -501,22 +555,32 @@ function BlockRenderer({
|
|
|
501
555
|
);
|
|
502
556
|
}
|
|
503
557
|
const Component = entry.component;
|
|
504
|
-
const containerProps = CONTAINER_TYPES.has(block.type) ? { renderBlock: renderBlock ?? resolveBlock } : {};
|
|
558
|
+
const containerProps = CONTAINER_TYPES.has(block.type) ? { renderBlock: renderBlock ?? ((child) => resolveBlock(child, void 0, annotate)) } : {};
|
|
505
559
|
const blockStyle = blockStyleToReactStyle(block.style);
|
|
506
|
-
const el = /* @__PURE__ */ jsx15(
|
|
560
|
+
const el = /* @__PURE__ */ jsx15(
|
|
561
|
+
Component,
|
|
562
|
+
{
|
|
563
|
+
...block.props,
|
|
564
|
+
className,
|
|
565
|
+
...containerProps,
|
|
566
|
+
...bindingProps(block, annotate)
|
|
567
|
+
}
|
|
568
|
+
);
|
|
507
569
|
return blockStyle ? /* @__PURE__ */ jsx15("div", { style: blockStyle, children: el }) : el;
|
|
508
570
|
}
|
|
509
571
|
function BlocksRenderer({
|
|
510
572
|
blocks,
|
|
511
573
|
className = "",
|
|
512
|
-
renderBlock
|
|
574
|
+
renderBlock,
|
|
575
|
+
annotate = false
|
|
513
576
|
}) {
|
|
514
577
|
if (blocks.length === 0) return null;
|
|
515
578
|
return /* @__PURE__ */ jsx15("div", { className, children: blocks.map((block) => /* @__PURE__ */ jsx15(
|
|
516
579
|
BlockRenderer,
|
|
517
580
|
{
|
|
518
581
|
block,
|
|
519
|
-
renderBlock
|
|
582
|
+
renderBlock,
|
|
583
|
+
annotate
|
|
520
584
|
},
|
|
521
585
|
block.id
|
|
522
586
|
)) });
|