@gosalesdeal/blog 0.1.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/README.md +97 -0
- package/dist/client/blogClient.d.ts +31 -0
- package/dist/client/blogClient.js +129 -0
- package/dist/client/blogClient.js.map +1 -0
- package/dist/components/BlogList.d.ts +24 -0
- package/dist/components/BlogList.js +60 -0
- package/dist/components/BlogList.js.map +1 -0
- package/dist/components/BlogPost.d.ts +25 -0
- package/dist/components/BlogPost.js +53 -0
- package/dist/components/BlogPost.js.map +1 -0
- package/dist/components/JsonLd.d.ts +6 -0
- package/dist/components/JsonLd.js +15 -0
- package/dist/components/JsonLd.js.map +1 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.js +32 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/format.d.ts +2 -0
- package/dist/lib/format.js +10 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/render/BlockRenderer.d.ts +9 -0
- package/dist/render/BlockRenderer.js +80 -0
- package/dist/render/BlockRenderer.js.map +1 -0
- package/dist/render/RichText.d.ts +5 -0
- package/dist/render/RichText.js +12 -0
- package/dist/render/RichText.js.map +1 -0
- package/dist/render/blockStyle.d.ts +8 -0
- package/dist/render/blockStyle.js +33 -0
- package/dist/render/blockStyle.js.map +1 -0
- package/dist/render/blocks/AccordionBlock.d.ts +4 -0
- package/dist/render/blocks/AccordionBlock.js +39 -0
- package/dist/render/blocks/AccordionBlock.js.map +1 -0
- package/dist/render/blocks/AlertBlock.d.ts +4 -0
- package/dist/render/blocks/AlertBlock.js +11 -0
- package/dist/render/blocks/AlertBlock.js.map +1 -0
- package/dist/render/blocks/ButtonBlock.d.ts +4 -0
- package/dist/render/blocks/ButtonBlock.js +17 -0
- package/dist/render/blocks/ButtonBlock.js.map +1 -0
- package/dist/render/blocks/CodeBlock.d.ts +4 -0
- package/dist/render/blocks/CodeBlock.js +16 -0
- package/dist/render/blocks/CodeBlock.js.map +1 -0
- package/dist/render/blocks/ColumnsBlock.d.ts +4 -0
- package/dist/render/blocks/ColumnsBlock.js +19 -0
- package/dist/render/blocks/ColumnsBlock.js.map +1 -0
- package/dist/render/blocks/DividerBlock.d.ts +4 -0
- package/dist/render/blocks/DividerBlock.js +19 -0
- package/dist/render/blocks/DividerBlock.js.map +1 -0
- package/dist/render/blocks/EmbedBlock.d.ts +4 -0
- package/dist/render/blocks/EmbedBlock.js +26 -0
- package/dist/render/blocks/EmbedBlock.js.map +1 -0
- package/dist/render/blocks/GalleryBlock.d.ts +4 -0
- package/dist/render/blocks/GalleryBlock.js +15 -0
- package/dist/render/blocks/GalleryBlock.js.map +1 -0
- package/dist/render/blocks/HeadingBlock.d.ts +5 -0
- package/dist/render/blocks/HeadingBlock.js +10 -0
- package/dist/render/blocks/HeadingBlock.js.map +1 -0
- package/dist/render/blocks/ImageBlock.d.ts +4 -0
- package/dist/render/blocks/ImageBlock.js +33 -0
- package/dist/render/blocks/ImageBlock.js.map +1 -0
- package/dist/render/blocks/ListBlock.d.ts +5 -0
- package/dist/render/blocks/ListBlock.js +16 -0
- package/dist/render/blocks/ListBlock.js.map +1 -0
- package/dist/render/blocks/QuoteBlock.d.ts +4 -0
- package/dist/render/blocks/QuoteBlock.js +15 -0
- package/dist/render/blocks/QuoteBlock.js.map +1 -0
- package/dist/render/blocks/SpacerBlock.d.ts +4 -0
- package/dist/render/blocks/SpacerBlock.js +8 -0
- package/dist/render/blocks/SpacerBlock.js.map +1 -0
- package/dist/render/blocks/TableBlock.d.ts +4 -0
- package/dist/render/blocks/TableBlock.js +18 -0
- package/dist/render/blocks/TableBlock.js.map +1 -0
- package/dist/render/blocks/TabsBlock.d.ts +4 -0
- package/dist/render/blocks/TabsBlock.js +29 -0
- package/dist/render/blocks/TabsBlock.js.map +1 -0
- package/dist/render/blocks/TextBlock.d.ts +4 -0
- package/dist/render/blocks/TextBlock.js +12 -0
- package/dist/render/blocks/TextBlock.js.map +1 -0
- package/dist/render/blocks/VideoBlock.d.ts +4 -0
- package/dist/render/blocks/VideoBlock.js +63 -0
- package/dist/render/blocks/VideoBlock.js.map +1 -0
- package/dist/seo/index.d.ts +46 -0
- package/dist/seo/index.js +87 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/styles.css +174 -0
- package/dist/types/blog.d.ts +260 -0
- package/package.json +68 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ContentBlock } from '../types/blog';
|
|
3
|
+
export interface BlockRendererProps {
|
|
4
|
+
block: ContentBlock;
|
|
5
|
+
}
|
|
6
|
+
/** Renders one content block wrapped with its layout settings. */
|
|
7
|
+
export declare function BlockRenderer({ block }: BlockRendererProps): import("react").JSX.Element;
|
|
8
|
+
/** Renders an ordered list of content blocks (used by posts and columns). */
|
|
9
|
+
export declare function renderBlocks(blocks: ContentBlock[]): ReactNode;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { animationClass, blockSettingsToStyle } from "./blockStyle.js";
|
|
3
|
+
import TextBlock from "./blocks/TextBlock.js";
|
|
4
|
+
import HeadingBlock from "./blocks/HeadingBlock.js";
|
|
5
|
+
import ImageBlock from "./blocks/ImageBlock.js";
|
|
6
|
+
import VideoBlock from "./blocks/VideoBlock.js";
|
|
7
|
+
import DividerBlock from "./blocks/DividerBlock.js";
|
|
8
|
+
import SpacerBlock from "./blocks/SpacerBlock.js";
|
|
9
|
+
import QuoteBlock from "./blocks/QuoteBlock.js";
|
|
10
|
+
import CodeBlock from "./blocks/CodeBlock.js";
|
|
11
|
+
import ListBlock from "./blocks/ListBlock.js";
|
|
12
|
+
import ButtonBlock from "./blocks/ButtonBlock.js";
|
|
13
|
+
import EmbedBlock from "./blocks/EmbedBlock.js";
|
|
14
|
+
import GalleryBlock from "./blocks/GalleryBlock.js";
|
|
15
|
+
import TableBlock from "./blocks/TableBlock.js";
|
|
16
|
+
import AlertBlock from "./blocks/AlertBlock.js";
|
|
17
|
+
import ColumnsBlock from "./blocks/ColumnsBlock.js";
|
|
18
|
+
import AccordionBlock from "./blocks/AccordionBlock.js";
|
|
19
|
+
import TabsBlock from "./blocks/TabsBlock.js";
|
|
20
|
+
function renderBlockContent(block) {
|
|
21
|
+
switch (block.type) {
|
|
22
|
+
case "text":
|
|
23
|
+
return /* @__PURE__ */ jsx(TextBlock, { content: block.content });
|
|
24
|
+
case "heading":
|
|
25
|
+
return /* @__PURE__ */ jsx(HeadingBlock, { content: block.content });
|
|
26
|
+
case "image":
|
|
27
|
+
return /* @__PURE__ */ jsx(ImageBlock, { content: block.content });
|
|
28
|
+
case "video":
|
|
29
|
+
return /* @__PURE__ */ jsx(VideoBlock, { content: block.content });
|
|
30
|
+
case "divider":
|
|
31
|
+
return /* @__PURE__ */ jsx(DividerBlock, { content: block.content });
|
|
32
|
+
case "spacer":
|
|
33
|
+
return /* @__PURE__ */ jsx(SpacerBlock, { content: block.content });
|
|
34
|
+
case "quote":
|
|
35
|
+
return /* @__PURE__ */ jsx(QuoteBlock, { content: block.content });
|
|
36
|
+
case "code":
|
|
37
|
+
return /* @__PURE__ */ jsx(CodeBlock, { content: block.content });
|
|
38
|
+
case "list":
|
|
39
|
+
return /* @__PURE__ */ jsx(ListBlock, { content: block.content });
|
|
40
|
+
case "button":
|
|
41
|
+
return /* @__PURE__ */ jsx(ButtonBlock, { content: block.content });
|
|
42
|
+
case "embed":
|
|
43
|
+
return /* @__PURE__ */ jsx(EmbedBlock, { content: block.content });
|
|
44
|
+
case "gallery":
|
|
45
|
+
return /* @__PURE__ */ jsx(GalleryBlock, { content: block.content });
|
|
46
|
+
case "table":
|
|
47
|
+
return /* @__PURE__ */ jsx(TableBlock, { content: block.content });
|
|
48
|
+
case "alert":
|
|
49
|
+
return /* @__PURE__ */ jsx(AlertBlock, { content: block.content });
|
|
50
|
+
case "accordion":
|
|
51
|
+
return /* @__PURE__ */ jsx(AccordionBlock, { content: block.content });
|
|
52
|
+
case "tabs":
|
|
53
|
+
return /* @__PURE__ */ jsx(TabsBlock, { content: block.content });
|
|
54
|
+
case "columns":
|
|
55
|
+
return /* @__PURE__ */ jsx(ColumnsBlock, { content: block.content });
|
|
56
|
+
default:
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function BlockRenderer({ block }) {
|
|
61
|
+
const className = `ggblog-block ggblog-block-${block.type} ${animationClass(block.settings)}`.trim();
|
|
62
|
+
return /* @__PURE__ */ jsx(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
className,
|
|
66
|
+
style: blockSettingsToStyle(block.settings),
|
|
67
|
+
"data-block-type": block.type,
|
|
68
|
+
"data-block-id": block.id,
|
|
69
|
+
children: renderBlockContent(block)
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
function renderBlocks(blocks) {
|
|
74
|
+
return blocks.map((block) => /* @__PURE__ */ jsx(BlockRenderer, { block }, block.id));
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
BlockRenderer,
|
|
78
|
+
renderBlocks
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=BlockRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BlockRenderer.js","sources":["../../src/render/BlockRenderer.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type {\n ContentBlock,\n TextBlockContent,\n HeadingBlockContent,\n ImageBlockContent,\n VideoBlockContent,\n QuoteBlockContent,\n CodeBlockContent,\n ListBlockContent,\n ButtonBlockContent,\n EmbedBlockContent,\n GalleryBlockContent,\n TableBlockContent,\n AccordionBlockContent,\n TabsBlockContent,\n AlertBlockContent,\n ColumnsBlockContent,\n SpacerBlockContent,\n DividerBlockContent,\n} from '../types/blog';\nimport { blockSettingsToStyle, animationClass } from './blockStyle';\nimport TextBlock from './blocks/TextBlock';\nimport HeadingBlock from './blocks/HeadingBlock';\nimport ImageBlock from './blocks/ImageBlock';\nimport VideoBlock from './blocks/VideoBlock';\nimport DividerBlock from './blocks/DividerBlock';\nimport SpacerBlock from './blocks/SpacerBlock';\nimport QuoteBlock from './blocks/QuoteBlock';\nimport CodeBlock from './blocks/CodeBlock';\nimport ListBlock from './blocks/ListBlock';\nimport ButtonBlock from './blocks/ButtonBlock';\nimport EmbedBlock from './blocks/EmbedBlock';\nimport GalleryBlock from './blocks/GalleryBlock';\nimport TableBlock from './blocks/TableBlock';\nimport AlertBlock from './blocks/AlertBlock';\nimport ColumnsBlock from './blocks/ColumnsBlock';\nimport AccordionBlock from './blocks/AccordionBlock';\nimport TabsBlock from './blocks/TabsBlock';\n\n/** Maps a single block to its read-only renderer. */\nfunction renderBlockContent(block: ContentBlock): ReactNode {\n switch (block.type) {\n case 'text':\n return <TextBlock content={block.content as TextBlockContent} />;\n case 'heading':\n return <HeadingBlock content={block.content as HeadingBlockContent} />;\n case 'image':\n return <ImageBlock content={block.content as ImageBlockContent} />;\n case 'video':\n return <VideoBlock content={block.content as VideoBlockContent} />;\n case 'divider':\n return <DividerBlock content={block.content as DividerBlockContent} />;\n case 'spacer':\n return <SpacerBlock content={block.content as SpacerBlockContent} />;\n case 'quote':\n return <QuoteBlock content={block.content as QuoteBlockContent} />;\n case 'code':\n return <CodeBlock content={block.content as CodeBlockContent} />;\n case 'list':\n return <ListBlock content={block.content as ListBlockContent} />;\n case 'button':\n return <ButtonBlock content={block.content as ButtonBlockContent} />;\n case 'embed':\n return <EmbedBlock content={block.content as EmbedBlockContent} />;\n case 'gallery':\n return <GalleryBlock content={block.content as GalleryBlockContent} />;\n case 'table':\n return <TableBlock content={block.content as TableBlockContent} />;\n case 'alert':\n return <AlertBlock content={block.content as AlertBlockContent} />;\n case 'accordion':\n return <AccordionBlock content={block.content as AccordionBlockContent} />;\n case 'tabs':\n return <TabsBlock content={block.content as TabsBlockContent} />;\n case 'columns':\n return <ColumnsBlock content={block.content as ColumnsBlockContent} />;\n default:\n return null;\n }\n}\n\nexport interface BlockRendererProps {\n block: ContentBlock;\n}\n\n/** Renders one content block wrapped with its layout settings. */\nexport function BlockRenderer({ block }: BlockRendererProps) {\n const className = `ggblog-block ggblog-block-${block.type} ${animationClass(block.settings)}`.trim();\n return (\n <div\n className={className}\n style={blockSettingsToStyle(block.settings)}\n data-block-type={block.type}\n data-block-id={block.id}\n >\n {renderBlockContent(block)}\n </div>\n );\n}\n\n/** Renders an ordered list of content blocks (used by posts and columns). */\nexport function renderBlocks(blocks: ContentBlock[]): ReactNode {\n return blocks.map((block) => <BlockRenderer key={block.id} block={block} />);\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAyCA,SAAS,mBAAmB,OAAgC;AAC1D,UAAQ,MAAM,MAAA;AAAA,IACZ,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,SAAS,MAAM,QAAA,CAA+B;AAAA,IACpE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,aAAA,EAAY,SAAS,MAAM,QAAA,CAA+B;AAAA,IACpE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,YAAA,EAAW,SAAS,MAAM,QAAA,CAA8B;AAAA,IAClE,KAAK;AACH,aAAO,oBAAC,gBAAA,EAAe,SAAS,MAAM,QAAA,CAAkC;AAAA,IAC1E,KAAK;AACH,aAAO,oBAAC,WAAA,EAAU,SAAS,MAAM,QAAA,CAA6B;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,cAAA,EAAa,SAAS,MAAM,QAAA,CAAgC;AAAA,IACtE;AACE,aAAO;AAAA,EAAA;AAEb;AAOO,SAAS,cAAc,EAAE,SAA6B;AAC3D,QAAM,YAAY,6BAA6B,MAAM,IAAI,IAAI,eAAe,MAAM,QAAQ,CAAC,GAAG,KAAA;AAC9F,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,OAAO,qBAAqB,MAAM,QAAQ;AAAA,MAC1C,mBAAiB,MAAM;AAAA,MACvB,iBAAe,MAAM;AAAA,MAEpB,6BAAmB,KAAK;AAAA,IAAA;AAAA,EAAA;AAG/B;AAGO,SAAS,aAAa,QAAmC;AAC9D,SAAO,OAAO,IAAI,CAAC,8BAAW,eAAA,EAA6B,MAAA,GAAV,MAAM,EAAkB,CAAE;AAC7E;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
function RichText({
|
|
3
|
+
html,
|
|
4
|
+
className,
|
|
5
|
+
as: Tag = "div"
|
|
6
|
+
}) {
|
|
7
|
+
return /* @__PURE__ */ jsx(Tag, { className, dangerouslySetInnerHTML: { __html: html ?? "" } });
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
RichText
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=RichText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RichText.js","sources":["../../src/render/RichText.tsx"],"sourcesContent":["// Renders trusted CMS HTML. Blog block content is authored in the GoEnterprise\n// CMS and treated as trusted; if your authors are untrusted, sanitize upstream\n// or pass already-sanitized HTML.\nexport function RichText({\n html,\n className,\n as: Tag = 'div',\n}: {\n html: string;\n className?: string;\n as?: 'div' | 'span';\n}) {\n return <Tag className={className} dangerouslySetInnerHTML={{ __html: html ?? '' }} />;\n}\n"],"names":[],"mappings":";AAGO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA,IAAI,MAAM;AACZ,GAIG;AACD,SAAO,oBAAC,OAAI,WAAsB,yBAAyB,EAAE,QAAQ,QAAQ,MAAM;AACrF;"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { BlockSettings } from '../types/blog';
|
|
3
|
+
/**
|
|
4
|
+
* Convert a block's authoring settings into inline CSS. Mirrors the field
|
|
5
|
+
* handling of the authoring app's renderer so output matches the editor.
|
|
6
|
+
*/
|
|
7
|
+
export declare function blockSettingsToStyle(settings?: BlockSettings): CSSProperties;
|
|
8
|
+
export declare function animationClass(settings?: BlockSettings): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function blockSettingsToStyle(settings) {
|
|
2
|
+
if (!settings) return {};
|
|
3
|
+
const style = {};
|
|
4
|
+
if (settings.margin) {
|
|
5
|
+
const m = settings.margin;
|
|
6
|
+
style.margin = `${m.top}px ${m.right}px ${m.bottom}px ${m.left}px`;
|
|
7
|
+
}
|
|
8
|
+
if (settings.padding) {
|
|
9
|
+
const p = settings.padding;
|
|
10
|
+
style.padding = `${p.top}px ${p.right}px ${p.bottom}px ${p.left}px`;
|
|
11
|
+
}
|
|
12
|
+
if (settings.alignment) style.textAlign = settings.alignment;
|
|
13
|
+
if (settings.backgroundColor) style.backgroundColor = settings.backgroundColor;
|
|
14
|
+
if (settings.borderRadius != null) style.borderRadius = `${settings.borderRadius}px`;
|
|
15
|
+
if (settings.border) {
|
|
16
|
+
const b = settings.border;
|
|
17
|
+
style.border = `${b.width}px ${b.style} ${b.color}`;
|
|
18
|
+
}
|
|
19
|
+
if (settings.fontSize != null) style.fontSize = `${settings.fontSize}px`;
|
|
20
|
+
if (settings.fontWeight) style.fontWeight = settings.fontWeight;
|
|
21
|
+
if (settings.color) style.color = settings.color;
|
|
22
|
+
if (settings.lineHeight != null) style.lineHeight = settings.lineHeight;
|
|
23
|
+
if (settings.letterSpacing != null) style.letterSpacing = `${settings.letterSpacing}px`;
|
|
24
|
+
return style;
|
|
25
|
+
}
|
|
26
|
+
function animationClass(settings) {
|
|
27
|
+
return settings?.animation ? `ggblog-animate-${settings.animation.type}` : "";
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
animationClass,
|
|
31
|
+
blockSettingsToStyle
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=blockStyle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blockStyle.js","sources":["../../src/render/blockStyle.ts"],"sourcesContent":["import type { CSSProperties } from 'react';\nimport type { BlockSettings } from '../types/blog';\n\n/**\n * Convert a block's authoring settings into inline CSS. Mirrors the field\n * handling of the authoring app's renderer so output matches the editor.\n */\nexport function blockSettingsToStyle(settings?: BlockSettings): CSSProperties {\n if (!settings) return {};\n const style: CSSProperties = {};\n\n if (settings.margin) {\n const m = settings.margin;\n style.margin = `${m.top}px ${m.right}px ${m.bottom}px ${m.left}px`;\n }\n if (settings.padding) {\n const p = settings.padding;\n style.padding = `${p.top}px ${p.right}px ${p.bottom}px ${p.left}px`;\n }\n if (settings.alignment) style.textAlign = settings.alignment;\n if (settings.backgroundColor) style.backgroundColor = settings.backgroundColor;\n if (settings.borderRadius != null) style.borderRadius = `${settings.borderRadius}px`;\n if (settings.border) {\n const b = settings.border;\n style.border = `${b.width}px ${b.style} ${b.color}`;\n }\n if (settings.fontSize != null) style.fontSize = `${settings.fontSize}px`;\n if (settings.fontWeight) style.fontWeight = settings.fontWeight;\n if (settings.color) style.color = settings.color;\n if (settings.lineHeight != null) style.lineHeight = settings.lineHeight;\n if (settings.letterSpacing != null) style.letterSpacing = `${settings.letterSpacing}px`;\n\n return style;\n}\n\nexport function animationClass(settings?: BlockSettings): string {\n return settings?.animation ? `ggblog-animate-${settings.animation.type}` : '';\n}\n"],"names":[],"mappings":"AAOO,SAAS,qBAAqB,UAAyC;AAC5E,MAAI,CAAC,SAAU,QAAO,CAAA;AACtB,QAAM,QAAuB,CAAA;AAE7B,MAAI,SAAS,QAAQ;AACnB,UAAM,IAAI,SAAS;AACnB,UAAM,SAAS,GAAG,EAAE,GAAG,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,IAAI;AAAA,EAChE;AACA,MAAI,SAAS,SAAS;AACpB,UAAM,IAAI,SAAS;AACnB,UAAM,UAAU,GAAG,EAAE,GAAG,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,EAAE,IAAI;AAAA,EACjE;AACA,MAAI,SAAS,UAAW,OAAM,YAAY,SAAS;AACnD,MAAI,SAAS,gBAAiB,OAAM,kBAAkB,SAAS;AAC/D,MAAI,SAAS,gBAAgB,YAAY,eAAe,GAAG,SAAS,YAAY;AAChF,MAAI,SAAS,QAAQ;AACnB,UAAM,IAAI,SAAS;AACnB,UAAM,SAAS,GAAG,EAAE,KAAK,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK;AAAA,EACnD;AACA,MAAI,SAAS,YAAY,YAAY,WAAW,GAAG,SAAS,QAAQ;AACpE,MAAI,SAAS,WAAY,OAAM,aAAa,SAAS;AACrD,MAAI,SAAS,MAAO,OAAM,QAAQ,SAAS;AAC3C,MAAI,SAAS,cAAc,KAAM,OAAM,aAAa,SAAS;AAC7D,MAAI,SAAS,iBAAiB,YAAY,gBAAgB,GAAG,SAAS,aAAa;AAEnF,SAAO;AACT;AAEO,SAAS,eAAe,UAAkC;AAC/D,SAAO,UAAU,YAAY,kBAAkB,SAAS,UAAU,IAAI,KAAK;AAC7E;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { RichText } from "../RichText.js";
|
|
5
|
+
function AccordionBlock({ content }) {
|
|
6
|
+
const items = content.items ?? [];
|
|
7
|
+
const [open, setOpen] = useState(
|
|
8
|
+
() => items.filter((item) => item.defaultOpen).map((item) => item.id)
|
|
9
|
+
);
|
|
10
|
+
const toggle = (id) => {
|
|
11
|
+
setOpen((prev) => {
|
|
12
|
+
if (prev.includes(id)) return prev.filter((x) => x !== id);
|
|
13
|
+
return content.allowMultiple ? [...prev, id] : [id];
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
return /* @__PURE__ */ jsx("div", { className: `ggblog-accordion ggblog-accordion-${content.style ?? "default"}`, children: items.map((item) => {
|
|
17
|
+
const isOpen = open.includes(item.id);
|
|
18
|
+
return /* @__PURE__ */ jsxs("div", { className: "ggblog-accordion-item", children: [
|
|
19
|
+
/* @__PURE__ */ jsxs(
|
|
20
|
+
"button",
|
|
21
|
+
{
|
|
22
|
+
type: "button",
|
|
23
|
+
className: "ggblog-accordion-trigger",
|
|
24
|
+
"aria-expanded": isOpen,
|
|
25
|
+
onClick: () => toggle(item.id),
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsx("span", { children: item.title }),
|
|
28
|
+
/* @__PURE__ */ jsx("span", { className: "ggblog-accordion-icon", "aria-hidden": "true", children: isOpen ? "−" : "+" })
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
),
|
|
32
|
+
isOpen ? /* @__PURE__ */ jsx("div", { className: "ggblog-accordion-panel", children: /* @__PURE__ */ jsx(RichText, { html: item.content }) }) : null
|
|
33
|
+
] }, item.id);
|
|
34
|
+
}) });
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
AccordionBlock as default
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=AccordionBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccordionBlock.js","sources":["../../../src/render/blocks/AccordionBlock.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport type { AccordionBlockContent } from '../../types/blog';\nimport { RichText } from '../RichText';\n\nexport default function AccordionBlock({ content }: { content: AccordionBlockContent }) {\n const items = content.items ?? [];\n const [open, setOpen] = useState<string[]>(() =>\n items.filter((item) => item.defaultOpen).map((item) => item.id),\n );\n\n const toggle = (id: string) => {\n setOpen((prev) => {\n if (prev.includes(id)) return prev.filter((x) => x !== id);\n return content.allowMultiple ? [...prev, id] : [id];\n });\n };\n\n return (\n <div className={`ggblog-accordion ggblog-accordion-${content.style ?? 'default'}`}>\n {items.map((item) => {\n const isOpen = open.includes(item.id);\n return (\n <div key={item.id} className=\"ggblog-accordion-item\">\n <button\n type=\"button\"\n className=\"ggblog-accordion-trigger\"\n aria-expanded={isOpen}\n onClick={() => toggle(item.id)}\n >\n <span>{item.title}</span>\n <span className=\"ggblog-accordion-icon\" aria-hidden=\"true\">\n {isOpen ? '−' : '+'}\n </span>\n </button>\n {isOpen ? (\n <div className=\"ggblog-accordion-panel\">\n <RichText html={item.content} />\n </div>\n ) : null}\n </div>\n );\n })}\n </div>\n );\n}\n"],"names":[],"mappings":";;;;AAMA,SAAwB,eAAe,EAAE,WAA+C;AACtF,QAAM,QAAQ,QAAQ,SAAS,CAAA;AAC/B,QAAM,CAAC,MAAM,OAAO,IAAI;AAAA,IAAmB,MACzC,MAAM,OAAO,CAAC,SAAS,KAAK,WAAW,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,EAAA;AAGhE,QAAM,SAAS,CAAC,OAAe;AAC7B,YAAQ,CAAC,SAAS;AAChB,UAAI,KAAK,SAAS,EAAE,EAAG,QAAO,KAAK,OAAO,CAAC,MAAM,MAAM,EAAE;AACzD,aAAO,QAAQ,gBAAgB,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE;AAAA,IACpD,CAAC;AAAA,EACH;AAEA,SACE,oBAAC,OAAA,EAAI,WAAW,qCAAqC,QAAQ,SAAS,SAAS,IAC5E,UAAA,MAAM,IAAI,CAAC,SAAS;AACnB,UAAM,SAAS,KAAK,SAAS,KAAK,EAAE;AACpC,WACE,qBAAC,OAAA,EAAkB,WAAU,yBAC3B,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,iBAAe;AAAA,UACf,SAAS,MAAM,OAAO,KAAK,EAAE;AAAA,UAE7B,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAM,eAAK,MAAA,CAAM;AAAA,YAClB,oBAAC,UAAK,WAAU,yBAAwB,eAAY,QACjD,UAAA,SAAS,MAAM,IAAA,CAClB;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAED,SACC,oBAAC,OAAA,EAAI,WAAU,0BACb,UAAA,oBAAC,UAAA,EAAS,MAAM,KAAK,QAAA,CAAS,EAAA,CAChC,IACE;AAAA,IAAA,EAAA,GAhBI,KAAK,EAiBf;AAAA,EAEJ,CAAC,EAAA,CACH;AAEJ;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function AlertBlock({ content }) {
|
|
3
|
+
return /* @__PURE__ */ jsxs("div", { className: `ggblog-alert ggblog-alert-${content.type ?? "info"}`, role: "note", children: [
|
|
4
|
+
content.title ? /* @__PURE__ */ jsx("div", { className: "ggblog-alert-title", children: content.title }) : null,
|
|
5
|
+
/* @__PURE__ */ jsx("div", { className: "ggblog-alert-text", children: content.text })
|
|
6
|
+
] });
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
AlertBlock as default
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=AlertBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlertBlock.js","sources":["../../../src/render/blocks/AlertBlock.tsx"],"sourcesContent":["import type { AlertBlockContent } from '../../types/blog';\n\nexport default function AlertBlock({ content }: { content: AlertBlockContent }) {\n return (\n <div className={`ggblog-alert ggblog-alert-${content.type ?? 'info'}`} role=\"note\">\n {content.title ? <div className=\"ggblog-alert-title\">{content.title}</div> : null}\n <div className=\"ggblog-alert-text\">{content.text}</div>\n </div>\n );\n}\n"],"names":[],"mappings":";AAEA,SAAwB,WAAW,EAAE,WAA2C;AAC9E,SACE,qBAAC,SAAI,WAAW,6BAA6B,QAAQ,QAAQ,MAAM,IAAI,MAAK,QACzE,UAAA;AAAA,IAAA,QAAQ,QAAQ,oBAAC,OAAA,EAAI,WAAU,sBAAsB,UAAA,QAAQ,OAAM,IAAS;AAAA,IAC7E,oBAAC,OAAA,EAAI,WAAU,qBAAqB,kBAAQ,KAAA,CAAK;AAAA,EAAA,GACnD;AAEJ;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
function ButtonBlock({ content }) {
|
|
3
|
+
return /* @__PURE__ */ jsx(
|
|
4
|
+
"a",
|
|
5
|
+
{
|
|
6
|
+
className: `ggblog-button ggblog-button-${content.style ?? "primary"} ggblog-button-${content.size ?? "medium"}`,
|
|
7
|
+
href: content.url,
|
|
8
|
+
target: content.openInNewTab ? "_blank" : void 0,
|
|
9
|
+
rel: content.openInNewTab ? "noopener noreferrer" : void 0,
|
|
10
|
+
children: content.text
|
|
11
|
+
}
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
ButtonBlock as default
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=ButtonBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ButtonBlock.js","sources":["../../../src/render/blocks/ButtonBlock.tsx"],"sourcesContent":["import type { ButtonBlockContent } from '../../types/blog';\n\nexport default function ButtonBlock({ content }: { content: ButtonBlockContent }) {\n return (\n <a\n className={`ggblog-button ggblog-button-${content.style ?? 'primary'} ggblog-button-${content.size ?? 'medium'}`}\n href={content.url}\n target={content.openInNewTab ? '_blank' : undefined}\n rel={content.openInNewTab ? 'noopener noreferrer' : undefined}\n >\n {content.text}\n </a>\n );\n}\n"],"names":[],"mappings":";AAEA,SAAwB,YAAY,EAAE,WAA4C;AAChF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,+BAA+B,QAAQ,SAAS,SAAS,kBAAkB,QAAQ,QAAQ,QAAQ;AAAA,MAC9G,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ,eAAe,WAAW;AAAA,MAC1C,KAAK,QAAQ,eAAe,wBAAwB;AAAA,MAEnD,UAAA,QAAQ;AAAA,IAAA;AAAA,EAAA;AAGf;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function CodeBlock({ content }) {
|
|
3
|
+
const code = content.code ?? "";
|
|
4
|
+
return /* @__PURE__ */ jsxs("div", { className: `ggblog-code ggblog-code-${content.theme ?? "dark"}`, children: [
|
|
5
|
+
content.filename ? /* @__PURE__ */ jsx("div", { className: "ggblog-code-filename", children: content.filename }) : null,
|
|
6
|
+
/* @__PURE__ */ jsx("pre", { className: "ggblog-code-pre", children: /* @__PURE__ */ jsx("code", { className: content.language ? `language-${content.language}` : void 0, children: content.showLineNumbers ? code.split("\n").map((line, i) => /* @__PURE__ */ jsxs("span", { className: "ggblog-code-line", children: [
|
|
7
|
+
/* @__PURE__ */ jsx("span", { className: "ggblog-code-ln", "aria-hidden": "true", children: i + 1 }),
|
|
8
|
+
line,
|
|
9
|
+
"\n"
|
|
10
|
+
] }, i)) : code }) })
|
|
11
|
+
] });
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
CodeBlock as default
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=CodeBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeBlock.js","sources":["../../../src/render/blocks/CodeBlock.tsx"],"sourcesContent":["import type { CodeBlockContent } from '../../types/blog';\n\nexport default function CodeBlock({ content }: { content: CodeBlockContent }) {\n const code = content.code ?? '';\n return (\n <div className={`ggblog-code ggblog-code-${content.theme ?? 'dark'}`}>\n {content.filename ? <div className=\"ggblog-code-filename\">{content.filename}</div> : null}\n <pre className=\"ggblog-code-pre\">\n <code className={content.language ? `language-${content.language}` : undefined}>\n {content.showLineNumbers\n ? code.split('\\n').map((line, i) => (\n <span key={i} className=\"ggblog-code-line\">\n <span className=\"ggblog-code-ln\" aria-hidden=\"true\">\n {i + 1}\n </span>\n {line}\n {'\\n'}\n </span>\n ))\n : code}\n </code>\n </pre>\n </div>\n );\n}\n"],"names":[],"mappings":";AAEA,SAAwB,UAAU,EAAE,WAA0C;AAC5E,QAAM,OAAO,QAAQ,QAAQ;AAC7B,8BACG,OAAA,EAAI,WAAW,2BAA2B,QAAQ,SAAS,MAAM,IAC/D,UAAA;AAAA,IAAA,QAAQ,WAAW,oBAAC,OAAA,EAAI,WAAU,wBAAwB,UAAA,QAAQ,UAAS,IAAS;AAAA,IACrF,oBAAC,OAAA,EAAI,WAAU,mBACb,UAAA,oBAAC,QAAA,EAAK,WAAW,QAAQ,WAAW,YAAY,QAAQ,QAAQ,KAAK,QAClE,UAAA,QAAQ,kBACL,KAAK,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,MAC1B,qBAAC,QAAA,EAAa,WAAU,oBACtB,UAAA;AAAA,MAAA,oBAAC,UAAK,WAAU,kBAAiB,eAAY,QAC1C,cAAI,GACP;AAAA,MACC;AAAA,MACA;AAAA,IAAA,EAAA,GALQ,CAMX,CACD,IACD,KAAA,CACN,EAAA,CACF;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { renderBlocks } from "../BlockRenderer.js";
|
|
3
|
+
function ColumnsBlock({ content }) {
|
|
4
|
+
const gap = content.gap ?? 16;
|
|
5
|
+
const alignItems = content.verticalAlign === "center" ? "center" : content.verticalAlign === "bottom" ? "flex-end" : "flex-start";
|
|
6
|
+
return /* @__PURE__ */ jsx("div", { className: "ggblog-columns", style: { display: "flex", gap: `${gap}px`, alignItems, flexWrap: "wrap" }, children: (content.columns ?? []).map((column) => /* @__PURE__ */ jsx(
|
|
7
|
+
"div",
|
|
8
|
+
{
|
|
9
|
+
className: "ggblog-column",
|
|
10
|
+
style: { flex: `1 1 ${column.width}%`, minWidth: 0 },
|
|
11
|
+
children: renderBlocks(column.blocks ?? [])
|
|
12
|
+
},
|
|
13
|
+
column.id
|
|
14
|
+
)) });
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
ColumnsBlock as default
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=ColumnsBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColumnsBlock.js","sources":["../../../src/render/blocks/ColumnsBlock.tsx"],"sourcesContent":["import type { ColumnsBlockContent } from '../../types/blog';\nimport { renderBlocks } from '../BlockRenderer';\n\nexport default function ColumnsBlock({ content }: { content: ColumnsBlockContent }) {\n const gap = content.gap ?? 16;\n const alignItems =\n content.verticalAlign === 'center'\n ? 'center'\n : content.verticalAlign === 'bottom'\n ? 'flex-end'\n : 'flex-start';\n\n return (\n <div className=\"ggblog-columns\" style={{ display: 'flex', gap: `${gap}px`, alignItems, flexWrap: 'wrap' }}>\n {(content.columns ?? []).map((column) => (\n <div\n key={column.id}\n className=\"ggblog-column\"\n style={{ flex: `1 1 ${column.width}%`, minWidth: 0 }}\n >\n {renderBlocks(column.blocks ?? [])}\n </div>\n ))}\n </div>\n );\n}\n"],"names":[],"mappings":";;AAGA,SAAwB,aAAa,EAAE,WAA6C;AAClF,QAAM,MAAM,QAAQ,OAAO;AAC3B,QAAM,aACJ,QAAQ,kBAAkB,WACtB,WACA,QAAQ,kBAAkB,WACxB,aACA;AAER,SACE,oBAAC,SAAI,WAAU,kBAAiB,OAAO,EAAE,SAAS,QAAQ,KAAK,GAAG,GAAG,MAAM,YAAY,UAAU,UAC7F,WAAA,QAAQ,WAAW,CAAA,GAAI,IAAI,CAAC,WAC5B;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,WAAU;AAAA,MACV,OAAO,EAAE,MAAM,OAAO,OAAO,KAAK,KAAK,UAAU,EAAA;AAAA,MAEhD,UAAA,aAAa,OAAO,UAAU,CAAA,CAAE;AAAA,IAAA;AAAA,IAJ5B,OAAO;AAAA,EAAA,CAMf,GACH;AAEJ;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
function DividerBlock({ content }) {
|
|
3
|
+
return /* @__PURE__ */ jsx(
|
|
4
|
+
"hr",
|
|
5
|
+
{
|
|
6
|
+
className: "ggblog-divider",
|
|
7
|
+
style: {
|
|
8
|
+
borderTopStyle: content.style ?? "solid",
|
|
9
|
+
borderTopColor: content.color,
|
|
10
|
+
borderTopWidth: content.thickness != null ? `${content.thickness}px` : void 0,
|
|
11
|
+
width: content.width != null ? `${content.width}%` : void 0
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
DividerBlock as default
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=DividerBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DividerBlock.js","sources":["../../../src/render/blocks/DividerBlock.tsx"],"sourcesContent":["import type { DividerBlockContent } from '../../types/blog';\n\nexport default function DividerBlock({ content }: { content: DividerBlockContent }) {\n return (\n <hr\n className=\"ggblog-divider\"\n style={{\n borderTopStyle: content.style ?? 'solid',\n borderTopColor: content.color,\n borderTopWidth: content.thickness != null ? `${content.thickness}px` : undefined,\n width: content.width != null ? `${content.width}%` : undefined,\n }}\n />\n );\n}\n"],"names":[],"mappings":";AAEA,SAAwB,aAAa,EAAE,WAA6C;AAClF,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,OAAO;AAAA,QACL,gBAAgB,QAAQ,SAAS;AAAA,QACjC,gBAAgB,QAAQ;AAAA,QACxB,gBAAgB,QAAQ,aAAa,OAAO,GAAG,QAAQ,SAAS,OAAO;AAAA,QACvE,OAAO,QAAQ,SAAS,OAAO,GAAG,QAAQ,KAAK,MAAM;AAAA,MAAA;AAAA,IACvD;AAAA,EAAA;AAGN;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { RichText } from "../RichText.js";
|
|
3
|
+
function EmbedBlock({ content }) {
|
|
4
|
+
if (content.html) {
|
|
5
|
+
return /* @__PURE__ */ jsx("div", { className: "ggblog-embed", children: /* @__PURE__ */ jsx(RichText, { html: content.html }) });
|
|
6
|
+
}
|
|
7
|
+
if (content.url) {
|
|
8
|
+
return /* @__PURE__ */ jsx("div", { className: "ggblog-embed", children: /* @__PURE__ */ jsx(
|
|
9
|
+
"iframe",
|
|
10
|
+
{
|
|
11
|
+
className: "ggblog-embed-frame",
|
|
12
|
+
src: content.url,
|
|
13
|
+
title: content.provider ?? "Embedded content",
|
|
14
|
+
width: content.width ?? "100%",
|
|
15
|
+
height: content.height ?? 400,
|
|
16
|
+
loading: "lazy",
|
|
17
|
+
allowFullScreen: true
|
|
18
|
+
}
|
|
19
|
+
) });
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
EmbedBlock as default
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=EmbedBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmbedBlock.js","sources":["../../../src/render/blocks/EmbedBlock.tsx"],"sourcesContent":["import type { EmbedBlockContent } from '../../types/blog';\nimport { RichText } from '../RichText';\n\nexport default function EmbedBlock({ content }: { content: EmbedBlockContent }) {\n if (content.html) {\n return (\n <div className=\"ggblog-embed\">\n <RichText html={content.html} />\n </div>\n );\n }\n if (content.url) {\n return (\n <div className=\"ggblog-embed\">\n <iframe\n className=\"ggblog-embed-frame\"\n src={content.url}\n title={content.provider ?? 'Embedded content'}\n width={content.width ?? '100%'}\n height={content.height ?? 400}\n loading=\"lazy\"\n allowFullScreen\n />\n </div>\n );\n }\n return null;\n}\n"],"names":[],"mappings":";;AAGA,SAAwB,WAAW,EAAE,WAA2C;AAC9E,MAAI,QAAQ,MAAM;AAChB,WACE,oBAAC,SAAI,WAAU,gBACb,8BAAC,UAAA,EAAS,MAAM,QAAQ,KAAA,CAAM,EAAA,CAChC;AAAA,EAEJ;AACA,MAAI,QAAQ,KAAK;AACf,WACE,oBAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ,YAAY;AAAA,QAC3B,OAAO,QAAQ,SAAS;AAAA,QACxB,QAAQ,QAAQ,UAAU;AAAA,QAC1B,SAAQ;AAAA,QACR,iBAAe;AAAA,MAAA;AAAA,IAAA,GAEnB;AAAA,EAEJ;AACA,SAAO;AACT;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function GalleryBlock({ content }) {
|
|
3
|
+
const columns = content.columns ?? 3;
|
|
4
|
+
const gap = content.gap ?? 8;
|
|
5
|
+
const masonry = content.layout === "masonry";
|
|
6
|
+
const style = masonry ? { columnCount: columns, columnGap: `${gap}px` } : { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: `${gap}px` };
|
|
7
|
+
return /* @__PURE__ */ jsx("div", { className: `ggblog-gallery ${masonry ? "ggblog-gallery-masonry" : "ggblog-gallery-grid"}`, style, children: (content.images ?? []).map((image) => /* @__PURE__ */ jsxs("figure", { className: "ggblog-gallery-item", children: [
|
|
8
|
+
/* @__PURE__ */ jsx("img", { src: image.url, alt: image.alt ?? "", loading: "lazy" }),
|
|
9
|
+
image.caption ? /* @__PURE__ */ jsx("figcaption", { children: image.caption }) : null
|
|
10
|
+
] }, image.id)) });
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
GalleryBlock as default
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=GalleryBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GalleryBlock.js","sources":["../../../src/render/blocks/GalleryBlock.tsx"],"sourcesContent":["import type { CSSProperties } from 'react';\nimport type { GalleryBlockContent } from '../../types/blog';\n\n// Renders grid / masonry / justified layouts. 'carousel' falls back to a grid\n// in this server-only renderer (no client runtime is shipped for galleries).\nexport default function GalleryBlock({ content }: { content: GalleryBlockContent }) {\n const columns = content.columns ?? 3;\n const gap = content.gap ?? 8;\n const masonry = content.layout === 'masonry';\n\n const style: CSSProperties = masonry\n ? { columnCount: columns, columnGap: `${gap}px` }\n : { display: 'grid', gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: `${gap}px` };\n\n return (\n <div className={`ggblog-gallery ${masonry ? 'ggblog-gallery-masonry' : 'ggblog-gallery-grid'}`} style={style}>\n {(content.images ?? []).map((image) => (\n <figure key={image.id} className=\"ggblog-gallery-item\">\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={image.url} alt={image.alt ?? ''} loading=\"lazy\" />\n {image.caption ? <figcaption>{image.caption}</figcaption> : null}\n </figure>\n ))}\n </div>\n );\n}\n"],"names":[],"mappings":";AAKA,SAAwB,aAAa,EAAE,WAA6C;AAClF,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,MAAM,QAAQ,OAAO;AAC3B,QAAM,UAAU,QAAQ,WAAW;AAEnC,QAAM,QAAuB,UACzB,EAAE,aAAa,SAAS,WAAW,GAAG,GAAG,SACzC,EAAE,SAAS,QAAQ,qBAAqB,UAAU,OAAO,UAAU,KAAK,GAAG,GAAG,KAAA;AAElF,6BACG,OAAA,EAAI,WAAW,kBAAkB,UAAU,2BAA2B,qBAAqB,IAAI,OAC5F,mBAAQ,UAAU,IAAI,IAAI,CAAC,UAC3B,qBAAC,UAAA,EAAsB,WAAU,uBAE/B,UAAA;AAAA,IAAA,oBAAC,OAAA,EAAI,KAAK,MAAM,KAAK,KAAK,MAAM,OAAO,IAAI,SAAQ,OAAA,CAAO;AAAA,IACzD,MAAM,UAAU,oBAAC,cAAA,EAAY,UAAA,MAAM,SAAQ,IAAgB;AAAA,EAAA,EAAA,GAHjD,MAAM,EAInB,CACD,GACH;AAEJ;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
function HeadingBlock({ content }) {
|
|
3
|
+
const level = content.level ?? 2;
|
|
4
|
+
const Tag = `h${level}`;
|
|
5
|
+
return /* @__PURE__ */ jsx(Tag, { id: content.anchor, className: `ggblog-heading ggblog-heading-${level}`, children: content.text });
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
HeadingBlock as default
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=HeadingBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeadingBlock.js","sources":["../../../src/render/blocks/HeadingBlock.tsx"],"sourcesContent":["import type { JSX } from 'react';\nimport type { HeadingBlockContent } from '../../types/blog';\n\nexport default function HeadingBlock({ content }: { content: HeadingBlockContent }) {\n const level = content.level ?? 2;\n const Tag = `h${level}` as keyof JSX.IntrinsicElements;\n return (\n <Tag id={content.anchor} className={`ggblog-heading ggblog-heading-${level}`}>\n {content.text}\n </Tag>\n );\n}\n"],"names":[],"mappings":";AAGA,SAAwB,aAAa,EAAE,WAA6C;AAClF,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,MAAM,IAAI,KAAK;AACrB,SACE,oBAAC,KAAA,EAAI,IAAI,QAAQ,QAAQ,WAAW,iCAAiC,KAAK,IACvE,UAAA,QAAQ,KAAA,CACX;AAEJ;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function ImageBlock({ content }) {
|
|
3
|
+
const img = (
|
|
4
|
+
// eslint-disable-next-line @next/next/no-img-element -- framework-agnostic package
|
|
5
|
+
/* @__PURE__ */ jsx(
|
|
6
|
+
"img",
|
|
7
|
+
{
|
|
8
|
+
className: "ggblog-image",
|
|
9
|
+
src: content.url,
|
|
10
|
+
alt: content.alt ?? "",
|
|
11
|
+
width: content.width,
|
|
12
|
+
height: content.height,
|
|
13
|
+
loading: "lazy"
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
);
|
|
17
|
+
return /* @__PURE__ */ jsxs("figure", { className: "ggblog-figure", children: [
|
|
18
|
+
content.link ? /* @__PURE__ */ jsx(
|
|
19
|
+
"a",
|
|
20
|
+
{
|
|
21
|
+
href: content.link,
|
|
22
|
+
target: content.openInNewTab ? "_blank" : void 0,
|
|
23
|
+
rel: content.openInNewTab ? "noopener noreferrer" : void 0,
|
|
24
|
+
children: img
|
|
25
|
+
}
|
|
26
|
+
) : img,
|
|
27
|
+
content.caption ? /* @__PURE__ */ jsx("figcaption", { className: "ggblog-caption", children: content.caption }) : null
|
|
28
|
+
] });
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
ImageBlock as default
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=ImageBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageBlock.js","sources":["../../../src/render/blocks/ImageBlock.tsx"],"sourcesContent":["import type { ImageBlockContent } from '../../types/blog';\n\nexport default function ImageBlock({ content }: { content: ImageBlockContent }) {\n const img = (\n // eslint-disable-next-line @next/next/no-img-element -- framework-agnostic package\n <img\n className=\"ggblog-image\"\n src={content.url}\n alt={content.alt ?? ''}\n width={content.width}\n height={content.height}\n loading=\"lazy\"\n />\n );\n return (\n <figure className=\"ggblog-figure\">\n {content.link ? (\n <a\n href={content.link}\n target={content.openInNewTab ? '_blank' : undefined}\n rel={content.openInNewTab ? 'noopener noreferrer' : undefined}\n >\n {img}\n </a>\n ) : (\n img\n )}\n {content.caption ? <figcaption className=\"ggblog-caption\">{content.caption}</figcaption> : null}\n </figure>\n );\n}\n"],"names":[],"mappings":";AAEA,SAAwB,WAAW,EAAE,WAA2C;AAC9E,QAAM;AAAA;AAAA,IAEJ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ,OAAO;AAAA,QACpB,OAAO,QAAQ;AAAA,QACf,QAAQ,QAAQ;AAAA,QAChB,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA;AAGZ,SACE,qBAAC,UAAA,EAAO,WAAU,iBACf,UAAA;AAAA,IAAA,QAAQ,OACP;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAM,QAAQ;AAAA,QACd,QAAQ,QAAQ,eAAe,WAAW;AAAA,QAC1C,KAAK,QAAQ,eAAe,wBAAwB;AAAA,QAEnD,UAAA;AAAA,MAAA;AAAA,IAAA,IAGH;AAAA,IAED,QAAQ,UAAU,oBAAC,cAAA,EAAW,WAAU,kBAAkB,UAAA,QAAQ,SAAQ,IAAgB;AAAA,EAAA,GAC7F;AAEJ;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
function ListBlock({ content }) {
|
|
3
|
+
const items = content.items ?? [];
|
|
4
|
+
if (content.type === "checklist") {
|
|
5
|
+
return /* @__PURE__ */ jsx("ul", { className: "ggblog-list ggblog-checklist", children: items.map((item) => /* @__PURE__ */ jsxs("li", { className: "ggblog-checklist-item", children: [
|
|
6
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: !!item.checked, readOnly: true }),
|
|
7
|
+
/* @__PURE__ */ jsx("span", { children: item.text })
|
|
8
|
+
] }, item.id)) });
|
|
9
|
+
}
|
|
10
|
+
const Tag = content.type === "ordered" ? "ol" : "ul";
|
|
11
|
+
return /* @__PURE__ */ jsx(Tag, { className: `ggblog-list ggblog-list-${content.style ?? "default"}`, children: items.map((item) => /* @__PURE__ */ jsx("li", { children: item.text }, item.id)) });
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
ListBlock as default
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=ListBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListBlock.js","sources":["../../../src/render/blocks/ListBlock.tsx"],"sourcesContent":["import type { JSX } from 'react';\nimport type { ListBlockContent } from '../../types/blog';\n\nexport default function ListBlock({ content }: { content: ListBlockContent }) {\n const items = content.items ?? [];\n\n if (content.type === 'checklist') {\n return (\n <ul className=\"ggblog-list ggblog-checklist\">\n {items.map((item) => (\n <li key={item.id} className=\"ggblog-checklist-item\">\n <input type=\"checkbox\" checked={!!item.checked} readOnly />\n <span>{item.text}</span>\n </li>\n ))}\n </ul>\n );\n }\n\n const Tag = (content.type === 'ordered' ? 'ol' : 'ul') as keyof JSX.IntrinsicElements;\n return (\n <Tag className={`ggblog-list ggblog-list-${content.style ?? 'default'}`}>\n {items.map((item) => (\n <li key={item.id}>{item.text}</li>\n ))}\n </Tag>\n );\n}\n"],"names":[],"mappings":";AAGA,SAAwB,UAAU,EAAE,WAA0C;AAC5E,QAAM,QAAQ,QAAQ,SAAS,CAAA;AAE/B,MAAI,QAAQ,SAAS,aAAa;AAChC,WACE,oBAAC,MAAA,EAAG,WAAU,gCACX,UAAA,MAAM,IAAI,CAAC,SACV,qBAAC,MAAA,EAAiB,WAAU,yBAC1B,UAAA;AAAA,MAAA,oBAAC,SAAA,EAAM,MAAK,YAAW,SAAS,CAAC,CAAC,KAAK,SAAS,UAAQ,KAAA,CAAC;AAAA,MACzD,oBAAC,QAAA,EAAM,UAAA,KAAK,KAAA,CAAK;AAAA,IAAA,EAAA,GAFV,KAAK,EAGd,CACD,GACH;AAAA,EAEJ;AAEA,QAAM,MAAO,QAAQ,SAAS,YAAY,OAAO;AACjD,6BACG,KAAA,EAAI,WAAW,2BAA2B,QAAQ,SAAS,SAAS,IAClE,UAAA,MAAM,IAAI,CAAC,6BACT,MAAA,EAAkB,UAAA,KAAK,QAAf,KAAK,EAAe,CAC9B,EAAA,CACH;AAEJ;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function QuoteBlock({ content }) {
|
|
3
|
+
const hasMeta = content.author || content.source;
|
|
4
|
+
return /* @__PURE__ */ jsxs("blockquote", { className: `ggblog-quote ggblog-quote-${content.style ?? "default"}`, children: [
|
|
5
|
+
/* @__PURE__ */ jsx("p", { className: "ggblog-quote-text", children: content.text }),
|
|
6
|
+
hasMeta ? /* @__PURE__ */ jsxs("footer", { className: "ggblog-quote-meta", children: [
|
|
7
|
+
content.author ? /* @__PURE__ */ jsx("span", { className: "ggblog-quote-author", children: content.author }) : null,
|
|
8
|
+
content.source ? content.sourceUrl ? /* @__PURE__ */ jsx("a", { className: "ggblog-quote-source", href: content.sourceUrl, children: content.source }) : /* @__PURE__ */ jsx("span", { className: "ggblog-quote-source", children: content.source }) : null
|
|
9
|
+
] }) : null
|
|
10
|
+
] });
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
QuoteBlock as default
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=QuoteBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuoteBlock.js","sources":["../../../src/render/blocks/QuoteBlock.tsx"],"sourcesContent":["import type { QuoteBlockContent } from '../../types/blog';\n\nexport default function QuoteBlock({ content }: { content: QuoteBlockContent }) {\n const hasMeta = content.author || content.source;\n return (\n <blockquote className={`ggblog-quote ggblog-quote-${content.style ?? 'default'}`}>\n <p className=\"ggblog-quote-text\">{content.text}</p>\n {hasMeta ? (\n <footer className=\"ggblog-quote-meta\">\n {content.author ? <span className=\"ggblog-quote-author\">{content.author}</span> : null}\n {content.source ? (\n content.sourceUrl ? (\n <a className=\"ggblog-quote-source\" href={content.sourceUrl}>\n {content.source}\n </a>\n ) : (\n <span className=\"ggblog-quote-source\">{content.source}</span>\n )\n ) : null}\n </footer>\n ) : null}\n </blockquote>\n );\n}\n"],"names":[],"mappings":";AAEA,SAAwB,WAAW,EAAE,WAA2C;AAC9E,QAAM,UAAU,QAAQ,UAAU,QAAQ;AAC1C,8BACG,cAAA,EAAW,WAAW,6BAA6B,QAAQ,SAAS,SAAS,IAC5E,UAAA;AAAA,IAAA,oBAAC,KAAA,EAAE,WAAU,qBAAqB,UAAA,QAAQ,MAAK;AAAA,IAC9C,UACC,qBAAC,UAAA,EAAO,WAAU,qBACf,UAAA;AAAA,MAAA,QAAQ,SAAS,oBAAC,QAAA,EAAK,WAAU,uBAAuB,UAAA,QAAQ,QAAO,IAAU;AAAA,MACjF,QAAQ,SACP,QAAQ,gCACL,KAAA,EAAE,WAAU,uBAAsB,MAAM,QAAQ,WAC9C,UAAA,QAAQ,OAAA,CACX,IAEA,oBAAC,QAAA,EAAK,WAAU,uBAAuB,UAAA,QAAQ,QAAO,IAEtD;AAAA,IAAA,EAAA,CACN,IACE;AAAA,EAAA,GACN;AAEJ;"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
function SpacerBlock({ content }) {
|
|
3
|
+
return /* @__PURE__ */ jsx("div", { className: "ggblog-spacer", style: { height: `${content.height ?? 0}px` }, "aria-hidden": "true" });
|
|
4
|
+
}
|
|
5
|
+
export {
|
|
6
|
+
SpacerBlock as default
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=SpacerBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpacerBlock.js","sources":["../../../src/render/blocks/SpacerBlock.tsx"],"sourcesContent":["import type { SpacerBlockContent } from '../../types/blog';\n\nexport default function SpacerBlock({ content }: { content: SpacerBlockContent }) {\n return <div className=\"ggblog-spacer\" style={{ height: `${content.height ?? 0}px` }} aria-hidden=\"true\" />;\n}\n"],"names":[],"mappings":";AAEA,SAAwB,YAAY,EAAE,WAA4C;AAChF,SAAO,oBAAC,OAAA,EAAI,WAAU,iBAAgB,OAAO,EAAE,QAAQ,GAAG,QAAQ,UAAU,CAAC,KAAA,GAAQ,eAAY,QAAO;AAC1G;"}
|