@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.
Files changed (88) hide show
  1. package/README.md +97 -0
  2. package/dist/client/blogClient.d.ts +31 -0
  3. package/dist/client/blogClient.js +129 -0
  4. package/dist/client/blogClient.js.map +1 -0
  5. package/dist/components/BlogList.d.ts +24 -0
  6. package/dist/components/BlogList.js +60 -0
  7. package/dist/components/BlogList.js.map +1 -0
  8. package/dist/components/BlogPost.d.ts +25 -0
  9. package/dist/components/BlogPost.js +53 -0
  10. package/dist/components/BlogPost.js.map +1 -0
  11. package/dist/components/JsonLd.d.ts +6 -0
  12. package/dist/components/JsonLd.js +15 -0
  13. package/dist/components/JsonLd.js.map +1 -0
  14. package/dist/config.d.ts +16 -0
  15. package/dist/config.js +32 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/index.d.ts +9 -0
  18. package/dist/index.js +31 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/lib/format.d.ts +2 -0
  21. package/dist/lib/format.js +10 -0
  22. package/dist/lib/format.js.map +1 -0
  23. package/dist/render/BlockRenderer.d.ts +9 -0
  24. package/dist/render/BlockRenderer.js +80 -0
  25. package/dist/render/BlockRenderer.js.map +1 -0
  26. package/dist/render/RichText.d.ts +5 -0
  27. package/dist/render/RichText.js +12 -0
  28. package/dist/render/RichText.js.map +1 -0
  29. package/dist/render/blockStyle.d.ts +8 -0
  30. package/dist/render/blockStyle.js +33 -0
  31. package/dist/render/blockStyle.js.map +1 -0
  32. package/dist/render/blocks/AccordionBlock.d.ts +4 -0
  33. package/dist/render/blocks/AccordionBlock.js +39 -0
  34. package/dist/render/blocks/AccordionBlock.js.map +1 -0
  35. package/dist/render/blocks/AlertBlock.d.ts +4 -0
  36. package/dist/render/blocks/AlertBlock.js +11 -0
  37. package/dist/render/blocks/AlertBlock.js.map +1 -0
  38. package/dist/render/blocks/ButtonBlock.d.ts +4 -0
  39. package/dist/render/blocks/ButtonBlock.js +17 -0
  40. package/dist/render/blocks/ButtonBlock.js.map +1 -0
  41. package/dist/render/blocks/CodeBlock.d.ts +4 -0
  42. package/dist/render/blocks/CodeBlock.js +16 -0
  43. package/dist/render/blocks/CodeBlock.js.map +1 -0
  44. package/dist/render/blocks/ColumnsBlock.d.ts +4 -0
  45. package/dist/render/blocks/ColumnsBlock.js +19 -0
  46. package/dist/render/blocks/ColumnsBlock.js.map +1 -0
  47. package/dist/render/blocks/DividerBlock.d.ts +4 -0
  48. package/dist/render/blocks/DividerBlock.js +19 -0
  49. package/dist/render/blocks/DividerBlock.js.map +1 -0
  50. package/dist/render/blocks/EmbedBlock.d.ts +4 -0
  51. package/dist/render/blocks/EmbedBlock.js +26 -0
  52. package/dist/render/blocks/EmbedBlock.js.map +1 -0
  53. package/dist/render/blocks/GalleryBlock.d.ts +4 -0
  54. package/dist/render/blocks/GalleryBlock.js +15 -0
  55. package/dist/render/blocks/GalleryBlock.js.map +1 -0
  56. package/dist/render/blocks/HeadingBlock.d.ts +5 -0
  57. package/dist/render/blocks/HeadingBlock.js +10 -0
  58. package/dist/render/blocks/HeadingBlock.js.map +1 -0
  59. package/dist/render/blocks/ImageBlock.d.ts +4 -0
  60. package/dist/render/blocks/ImageBlock.js +33 -0
  61. package/dist/render/blocks/ImageBlock.js.map +1 -0
  62. package/dist/render/blocks/ListBlock.d.ts +5 -0
  63. package/dist/render/blocks/ListBlock.js +16 -0
  64. package/dist/render/blocks/ListBlock.js.map +1 -0
  65. package/dist/render/blocks/QuoteBlock.d.ts +4 -0
  66. package/dist/render/blocks/QuoteBlock.js +15 -0
  67. package/dist/render/blocks/QuoteBlock.js.map +1 -0
  68. package/dist/render/blocks/SpacerBlock.d.ts +4 -0
  69. package/dist/render/blocks/SpacerBlock.js +8 -0
  70. package/dist/render/blocks/SpacerBlock.js.map +1 -0
  71. package/dist/render/blocks/TableBlock.d.ts +4 -0
  72. package/dist/render/blocks/TableBlock.js +18 -0
  73. package/dist/render/blocks/TableBlock.js.map +1 -0
  74. package/dist/render/blocks/TabsBlock.d.ts +4 -0
  75. package/dist/render/blocks/TabsBlock.js +29 -0
  76. package/dist/render/blocks/TabsBlock.js.map +1 -0
  77. package/dist/render/blocks/TextBlock.d.ts +4 -0
  78. package/dist/render/blocks/TextBlock.js +12 -0
  79. package/dist/render/blocks/TextBlock.js.map +1 -0
  80. package/dist/render/blocks/VideoBlock.d.ts +4 -0
  81. package/dist/render/blocks/VideoBlock.js +63 -0
  82. package/dist/render/blocks/VideoBlock.js.map +1 -0
  83. package/dist/seo/index.d.ts +46 -0
  84. package/dist/seo/index.js +87 -0
  85. package/dist/seo/index.js.map +1 -0
  86. package/dist/styles.css +174 -0
  87. package/dist/types/blog.d.ts +260 -0
  88. 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,5 @@
1
+ export declare function RichText({ html, className, as: Tag, }: {
2
+ html: string;
3
+ className?: string;
4
+ as?: 'div' | 'span';
5
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { AccordionBlockContent } from '../../types/blog';
2
+ export default function AccordionBlock({ content }: {
3
+ content: AccordionBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { AlertBlockContent } from '../../types/blog';
2
+ export default function AlertBlock({ content }: {
3
+ content: AlertBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { ButtonBlockContent } from '../../types/blog';
2
+ export default function ButtonBlock({ content }: {
3
+ content: ButtonBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { CodeBlockContent } from '../../types/blog';
2
+ export default function CodeBlock({ content }: {
3
+ content: CodeBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { ColumnsBlockContent } from '../../types/blog';
2
+ export default function ColumnsBlock({ content }: {
3
+ content: ColumnsBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { DividerBlockContent } from '../../types/blog';
2
+ export default function DividerBlock({ content }: {
3
+ content: DividerBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { EmbedBlockContent } from '../../types/blog';
2
+ export default function EmbedBlock({ content }: {
3
+ content: EmbedBlockContent;
4
+ }): import("react").JSX.Element | null;
@@ -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,4 @@
1
+ import { GalleryBlockContent } from '../../types/blog';
2
+ export default function GalleryBlock({ content }: {
3
+ content: GalleryBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,5 @@
1
+ import { JSX } from 'react';
2
+ import { HeadingBlockContent } from '../../types/blog';
3
+ export default function HeadingBlock({ content }: {
4
+ content: HeadingBlockContent;
5
+ }): JSX.Element;
@@ -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,4 @@
1
+ import { ImageBlockContent } from '../../types/blog';
2
+ export default function ImageBlock({ content }: {
3
+ content: ImageBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,5 @@
1
+ import { JSX } from 'react';
2
+ import { ListBlockContent } from '../../types/blog';
3
+ export default function ListBlock({ content }: {
4
+ content: ListBlockContent;
5
+ }): JSX.Element;
@@ -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,4 @@
1
+ import { QuoteBlockContent } from '../../types/blog';
2
+ export default function QuoteBlock({ content }: {
3
+ content: QuoteBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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,4 @@
1
+ import { SpacerBlockContent } from '../../types/blog';
2
+ export default function SpacerBlock({ content }: {
3
+ content: SpacerBlockContent;
4
+ }): import("react").JSX.Element;
@@ -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;"}
@@ -0,0 +1,4 @@
1
+ import { TableBlockContent } from '../../types/blog';
2
+ export default function TableBlock({ content }: {
3
+ content: TableBlockContent;
4
+ }): import("react").JSX.Element;