@json-render/image 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/LICENSE +201 -0
- package/README.md +167 -0
- package/dist/catalog.d.mts +265 -0
- package/dist/catalog.d.ts +265 -0
- package/dist/catalog.js +207 -0
- package/dist/catalog.js.map +1 -0
- package/dist/catalog.mjs +7 -0
- package/dist/catalog.mjs.map +1 -0
- package/dist/chunk-A67OT34V.mjs +41 -0
- package/dist/chunk-A67OT34V.mjs.map +1 -0
- package/dist/chunk-KQSKKHJA.mjs +348 -0
- package/dist/chunk-KQSKKHJA.mjs.map +1 -0
- package/dist/chunk-PMEELRVP.mjs +183 -0
- package/dist/chunk-PMEELRVP.mjs.map +1 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +600 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +19 -0
- package/dist/index.mjs.map +1 -0
- package/dist/render-DyXCSaYW.d.mts +40 -0
- package/dist/render-DyXCSaYW.d.ts +40 -0
- package/dist/render.d.mts +4 -0
- package/dist/render.d.ts +4 -0
- package/dist/render.js +380 -0
- package/dist/render.js.map +1 -0
- package/dist/render.mjs +11 -0
- package/dist/render.mjs.map +1 -0
- package/dist/server.d.mts +53 -0
- package/dist/server.d.ts +53 -0
- package/dist/server.js +248 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +11 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +85 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
renderToPng: () => renderToPng,
|
|
34
|
+
renderToSvg: () => renderToSvg,
|
|
35
|
+
schema: () => schema,
|
|
36
|
+
standardComponentDefinitions: () => standardComponentDefinitions,
|
|
37
|
+
standardComponents: () => standardComponents
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
40
|
+
|
|
41
|
+
// src/schema.ts
|
|
42
|
+
var import_core = require("@json-render/core");
|
|
43
|
+
var schema = (0, import_core.defineSchema)(
|
|
44
|
+
(s) => ({
|
|
45
|
+
spec: s.object({
|
|
46
|
+
root: s.string(),
|
|
47
|
+
elements: s.record(
|
|
48
|
+
s.object({
|
|
49
|
+
type: s.ref("catalog.components"),
|
|
50
|
+
props: s.propsOf("catalog.components"),
|
|
51
|
+
children: s.array(s.string()),
|
|
52
|
+
visible: s.any()
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
}),
|
|
56
|
+
catalog: s.object({
|
|
57
|
+
components: s.map({
|
|
58
|
+
props: s.zod(),
|
|
59
|
+
slots: s.array(s.string()),
|
|
60
|
+
description: s.string(),
|
|
61
|
+
example: s.any()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
}),
|
|
65
|
+
{
|
|
66
|
+
defaultRules: [
|
|
67
|
+
"The root element MUST be a Frame component. It defines the image dimensions (width, height) and background.",
|
|
68
|
+
"Frame width and height determine the output image size. Common sizes: 1200x630 (OG image), 1080x1080 (social square), 1920x1080 (banner).",
|
|
69
|
+
"Use Row for horizontal layouts and Column for vertical layouts. Both support gap, align, and justify props.",
|
|
70
|
+
"All text content must use Heading or Text components. Raw strings are not supported.",
|
|
71
|
+
"Image src must be a fully qualified URL. For placeholder images, use https://picsum.photos/{width}/{height}?random={n}.",
|
|
72
|
+
"Satori renders a subset of CSS: flexbox layout, borders, backgrounds, text styling. Absolute positioning is supported via position/top/left/right/bottom.",
|
|
73
|
+
"CRITICAL INTEGRITY CHECK: Before outputting ANY element that references children, you MUST have already output (or will output) each child as its own element. If an element has children: ['a', 'b'], then elements 'a' and 'b' MUST exist."
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// src/components/standard.tsx
|
|
79
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
80
|
+
var headingSizes = {
|
|
81
|
+
h1: 48,
|
|
82
|
+
h2: 36,
|
|
83
|
+
h3: 28,
|
|
84
|
+
h4: 22
|
|
85
|
+
};
|
|
86
|
+
var headingWeights = {
|
|
87
|
+
h1: 700,
|
|
88
|
+
h2: 700,
|
|
89
|
+
h3: 600,
|
|
90
|
+
h4: 600
|
|
91
|
+
};
|
|
92
|
+
function cleanStyle(raw) {
|
|
93
|
+
const out = {};
|
|
94
|
+
for (const k in raw) {
|
|
95
|
+
if (raw[k] !== void 0 && raw[k] !== null) {
|
|
96
|
+
out[k] = raw[k];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
function FrameComponent({
|
|
102
|
+
element,
|
|
103
|
+
children
|
|
104
|
+
}) {
|
|
105
|
+
const p = element.props;
|
|
106
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
107
|
+
"div",
|
|
108
|
+
{
|
|
109
|
+
style: cleanStyle({
|
|
110
|
+
display: p.display ?? "flex",
|
|
111
|
+
flexDirection: p.flexDirection ?? "column",
|
|
112
|
+
width: p.width,
|
|
113
|
+
height: p.height,
|
|
114
|
+
backgroundColor: p.backgroundColor ?? "white",
|
|
115
|
+
padding: p.padding,
|
|
116
|
+
alignItems: p.alignItems,
|
|
117
|
+
justifyContent: p.justifyContent
|
|
118
|
+
}),
|
|
119
|
+
children
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
function BoxComponent({
|
|
124
|
+
element,
|
|
125
|
+
children
|
|
126
|
+
}) {
|
|
127
|
+
const p = element.props;
|
|
128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
129
|
+
"div",
|
|
130
|
+
{
|
|
131
|
+
style: cleanStyle({
|
|
132
|
+
display: "flex",
|
|
133
|
+
flexDirection: p.flexDirection ?? "column",
|
|
134
|
+
padding: p.padding,
|
|
135
|
+
paddingTop: p.paddingTop,
|
|
136
|
+
paddingBottom: p.paddingBottom,
|
|
137
|
+
paddingLeft: p.paddingLeft,
|
|
138
|
+
paddingRight: p.paddingRight,
|
|
139
|
+
margin: p.margin,
|
|
140
|
+
backgroundColor: p.backgroundColor,
|
|
141
|
+
borderWidth: p.borderWidth,
|
|
142
|
+
borderColor: p.borderColor,
|
|
143
|
+
borderRadius: p.borderRadius,
|
|
144
|
+
borderStyle: p.borderWidth ? "solid" : void 0,
|
|
145
|
+
flex: p.flex,
|
|
146
|
+
width: p.width,
|
|
147
|
+
height: p.height,
|
|
148
|
+
alignItems: p.alignItems,
|
|
149
|
+
justifyContent: p.justifyContent,
|
|
150
|
+
position: p.position,
|
|
151
|
+
top: p.top,
|
|
152
|
+
left: p.left,
|
|
153
|
+
right: p.right,
|
|
154
|
+
bottom: p.bottom,
|
|
155
|
+
overflow: p.overflow
|
|
156
|
+
}),
|
|
157
|
+
children
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
function RowComponent({
|
|
162
|
+
element,
|
|
163
|
+
children
|
|
164
|
+
}) {
|
|
165
|
+
const p = element.props;
|
|
166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
style: cleanStyle({
|
|
170
|
+
display: "flex",
|
|
171
|
+
flexDirection: "row",
|
|
172
|
+
gap: p.gap,
|
|
173
|
+
alignItems: p.alignItems,
|
|
174
|
+
justifyContent: p.justifyContent,
|
|
175
|
+
padding: p.padding,
|
|
176
|
+
flex: p.flex,
|
|
177
|
+
flexWrap: p.wrap ? "wrap" : void 0
|
|
178
|
+
}),
|
|
179
|
+
children
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
function ColumnComponent({
|
|
184
|
+
element,
|
|
185
|
+
children
|
|
186
|
+
}) {
|
|
187
|
+
const p = element.props;
|
|
188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
189
|
+
"div",
|
|
190
|
+
{
|
|
191
|
+
style: cleanStyle({
|
|
192
|
+
display: "flex",
|
|
193
|
+
flexDirection: "column",
|
|
194
|
+
gap: p.gap,
|
|
195
|
+
alignItems: p.alignItems,
|
|
196
|
+
justifyContent: p.justifyContent,
|
|
197
|
+
padding: p.padding,
|
|
198
|
+
flex: p.flex
|
|
199
|
+
}),
|
|
200
|
+
children
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
function HeadingComponent({
|
|
205
|
+
element
|
|
206
|
+
}) {
|
|
207
|
+
const p = element.props;
|
|
208
|
+
const level = p.level ?? "h2";
|
|
209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
210
|
+
"div",
|
|
211
|
+
{
|
|
212
|
+
style: cleanStyle({
|
|
213
|
+
display: "flex",
|
|
214
|
+
fontSize: headingSizes[level] ?? 36,
|
|
215
|
+
fontWeight: headingWeights[level] ?? 700,
|
|
216
|
+
color: p.color ?? "black",
|
|
217
|
+
textAlign: p.align ?? "left",
|
|
218
|
+
letterSpacing: p.letterSpacing,
|
|
219
|
+
lineHeight: p.lineHeight ?? 1.2
|
|
220
|
+
}),
|
|
221
|
+
children: p.text
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
function TextComponent({
|
|
226
|
+
element
|
|
227
|
+
}) {
|
|
228
|
+
const p = element.props;
|
|
229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
230
|
+
"div",
|
|
231
|
+
{
|
|
232
|
+
style: cleanStyle({
|
|
233
|
+
display: "flex",
|
|
234
|
+
fontSize: p.fontSize ?? 16,
|
|
235
|
+
color: p.color ?? "black",
|
|
236
|
+
textAlign: p.align ?? "left",
|
|
237
|
+
fontWeight: p.fontWeight === "bold" ? 700 : 400,
|
|
238
|
+
fontStyle: p.fontStyle ?? "normal",
|
|
239
|
+
lineHeight: p.lineHeight ?? 1.4,
|
|
240
|
+
letterSpacing: p.letterSpacing,
|
|
241
|
+
textDecoration: p.textDecoration
|
|
242
|
+
}),
|
|
243
|
+
children: p.text
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
function ImageComponent({
|
|
248
|
+
element
|
|
249
|
+
}) {
|
|
250
|
+
const p = element.props;
|
|
251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
252
|
+
"img",
|
|
253
|
+
{
|
|
254
|
+
src: p.src,
|
|
255
|
+
width: p.width ?? void 0,
|
|
256
|
+
height: p.height ?? void 0,
|
|
257
|
+
style: cleanStyle({
|
|
258
|
+
borderRadius: p.borderRadius,
|
|
259
|
+
objectFit: p.objectFit ?? "contain"
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
function DividerComponent({
|
|
265
|
+
element
|
|
266
|
+
}) {
|
|
267
|
+
const p = element.props;
|
|
268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
269
|
+
"div",
|
|
270
|
+
{
|
|
271
|
+
style: {
|
|
272
|
+
display: "flex",
|
|
273
|
+
width: "100%",
|
|
274
|
+
borderBottom: `${p.thickness ?? 1}px solid ${p.color ?? "#e5e7eb"}`,
|
|
275
|
+
marginTop: p.marginTop ?? 8,
|
|
276
|
+
marginBottom: p.marginBottom ?? 8
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
function SpacerComponent({
|
|
282
|
+
element
|
|
283
|
+
}) {
|
|
284
|
+
const p = element.props;
|
|
285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", height: p.height ?? 20 } });
|
|
286
|
+
}
|
|
287
|
+
var standardComponents = {
|
|
288
|
+
Frame: FrameComponent,
|
|
289
|
+
Box: BoxComponent,
|
|
290
|
+
Row: RowComponent,
|
|
291
|
+
Column: ColumnComponent,
|
|
292
|
+
Heading: HeadingComponent,
|
|
293
|
+
Text: TextComponent,
|
|
294
|
+
Image: ImageComponent,
|
|
295
|
+
Divider: DividerComponent,
|
|
296
|
+
Spacer: SpacerComponent
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// src/render.tsx
|
|
300
|
+
var import_satori = __toESM(require("satori"));
|
|
301
|
+
var import_core2 = require("@json-render/core");
|
|
302
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
303
|
+
var noopEmit = () => {
|
|
304
|
+
};
|
|
305
|
+
function renderElement(elementKey, spec, registry, stateModel, repeatItem, repeatIndex, repeatBasePath) {
|
|
306
|
+
const element = spec.elements[elementKey];
|
|
307
|
+
if (!element) return null;
|
|
308
|
+
const ctx = {
|
|
309
|
+
stateModel,
|
|
310
|
+
repeatItem,
|
|
311
|
+
repeatIndex,
|
|
312
|
+
repeatBasePath
|
|
313
|
+
};
|
|
314
|
+
if (element.visible !== void 0) {
|
|
315
|
+
if (!(0, import_core2.evaluateVisibility)(element.visible, ctx)) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const resolvedProps = (0, import_core2.resolveElementProps)(
|
|
320
|
+
element.props,
|
|
321
|
+
ctx
|
|
322
|
+
);
|
|
323
|
+
const resolvedElement = { ...element, props: resolvedProps };
|
|
324
|
+
const Component = registry[resolvedElement.type];
|
|
325
|
+
if (!Component) return null;
|
|
326
|
+
if (resolvedElement.repeat) {
|
|
327
|
+
const items = (0, import_core2.getByPath)(stateModel, resolvedElement.repeat.statePath) ?? [];
|
|
328
|
+
const fragments = items.map((item, index) => {
|
|
329
|
+
const key = resolvedElement.repeat.key && typeof item === "object" && item !== null ? String(
|
|
330
|
+
item[resolvedElement.repeat.key] ?? index
|
|
331
|
+
) : String(index);
|
|
332
|
+
const childPath = `${resolvedElement.repeat.statePath}/${index}`;
|
|
333
|
+
const children2 = resolvedElement.children?.map(
|
|
334
|
+
(childKey) => renderElement(
|
|
335
|
+
childKey,
|
|
336
|
+
spec,
|
|
337
|
+
registry,
|
|
338
|
+
stateModel,
|
|
339
|
+
item,
|
|
340
|
+
index,
|
|
341
|
+
childPath
|
|
342
|
+
)
|
|
343
|
+
);
|
|
344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { element: resolvedElement, emit: noopEmit, children: children2 }, key);
|
|
345
|
+
});
|
|
346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fragments });
|
|
347
|
+
}
|
|
348
|
+
const children = resolvedElement.children?.map(
|
|
349
|
+
(childKey) => renderElement(
|
|
350
|
+
childKey,
|
|
351
|
+
spec,
|
|
352
|
+
registry,
|
|
353
|
+
stateModel,
|
|
354
|
+
repeatItem,
|
|
355
|
+
repeatIndex,
|
|
356
|
+
repeatBasePath
|
|
357
|
+
)
|
|
358
|
+
);
|
|
359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Component, { element: resolvedElement, emit: noopEmit, children: children && children.length > 0 ? children : void 0 }, elementKey);
|
|
360
|
+
}
|
|
361
|
+
function getDimensions(spec, options = {}) {
|
|
362
|
+
if (options.width && options.height) {
|
|
363
|
+
return { width: options.width, height: options.height };
|
|
364
|
+
}
|
|
365
|
+
const rootElement = spec.elements[spec.root];
|
|
366
|
+
const props = rootElement?.props;
|
|
367
|
+
return {
|
|
368
|
+
width: options.width ?? props?.width ?? 1200,
|
|
369
|
+
height: options.height ?? props?.height ?? 630
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
function buildTree(spec, options = {}) {
|
|
373
|
+
const {
|
|
374
|
+
registry: customRegistry,
|
|
375
|
+
includeStandard = true,
|
|
376
|
+
state = {}
|
|
377
|
+
} = options;
|
|
378
|
+
const mergedState = {
|
|
379
|
+
...spec.state,
|
|
380
|
+
...state
|
|
381
|
+
};
|
|
382
|
+
const registry = {
|
|
383
|
+
...includeStandard ? standardComponents : {},
|
|
384
|
+
...customRegistry
|
|
385
|
+
};
|
|
386
|
+
const root = renderElement(spec.root, spec, registry, mergedState);
|
|
387
|
+
return root ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {});
|
|
388
|
+
}
|
|
389
|
+
async function renderToSvg(spec, options = {}) {
|
|
390
|
+
const tree = buildTree(spec, options);
|
|
391
|
+
const { width, height } = getDimensions(spec, options);
|
|
392
|
+
return (0, import_satori.default)(tree, {
|
|
393
|
+
width,
|
|
394
|
+
height,
|
|
395
|
+
fonts: options.fonts ?? []
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
async function renderToPng(spec, options = {}) {
|
|
399
|
+
const svg = await renderToSvg(spec, options);
|
|
400
|
+
let Resvg;
|
|
401
|
+
try {
|
|
402
|
+
const mod = await import("@resvg/resvg-js");
|
|
403
|
+
Resvg = mod.Resvg;
|
|
404
|
+
} catch {
|
|
405
|
+
throw new Error(
|
|
406
|
+
"@resvg/resvg-js is required for PNG output. Install it with: npm install @resvg/resvg-js"
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
const resvg = new Resvg(svg);
|
|
410
|
+
const pngData = resvg.render();
|
|
411
|
+
return pngData.asPng();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/catalog.ts
|
|
415
|
+
var import_zod = require("zod");
|
|
416
|
+
var standardComponentDefinitions = {
|
|
417
|
+
// ==========================================================================
|
|
418
|
+
// Root
|
|
419
|
+
// ==========================================================================
|
|
420
|
+
Frame: {
|
|
421
|
+
props: import_zod.z.object({
|
|
422
|
+
width: import_zod.z.number(),
|
|
423
|
+
height: import_zod.z.number(),
|
|
424
|
+
backgroundColor: import_zod.z.string().nullable(),
|
|
425
|
+
padding: import_zod.z.number().nullable(),
|
|
426
|
+
display: import_zod.z.enum(["flex", "none"]).nullable(),
|
|
427
|
+
flexDirection: import_zod.z.enum(["row", "column"]).nullable(),
|
|
428
|
+
alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
|
|
429
|
+
justifyContent: import_zod.z.enum([
|
|
430
|
+
"flex-start",
|
|
431
|
+
"center",
|
|
432
|
+
"flex-end",
|
|
433
|
+
"space-between",
|
|
434
|
+
"space-around"
|
|
435
|
+
]).nullable()
|
|
436
|
+
}),
|
|
437
|
+
slots: ["default"],
|
|
438
|
+
description: "Root image container. Defines the output image dimensions and background. Must be the root element.",
|
|
439
|
+
example: { width: 1200, height: 630, backgroundColor: "#ffffff" }
|
|
440
|
+
},
|
|
441
|
+
// ==========================================================================
|
|
442
|
+
// Layout Components
|
|
443
|
+
// ==========================================================================
|
|
444
|
+
Box: {
|
|
445
|
+
props: import_zod.z.object({
|
|
446
|
+
padding: import_zod.z.number().nullable(),
|
|
447
|
+
paddingTop: import_zod.z.number().nullable(),
|
|
448
|
+
paddingBottom: import_zod.z.number().nullable(),
|
|
449
|
+
paddingLeft: import_zod.z.number().nullable(),
|
|
450
|
+
paddingRight: import_zod.z.number().nullable(),
|
|
451
|
+
margin: import_zod.z.number().nullable(),
|
|
452
|
+
backgroundColor: import_zod.z.string().nullable(),
|
|
453
|
+
borderWidth: import_zod.z.number().nullable(),
|
|
454
|
+
borderColor: import_zod.z.string().nullable(),
|
|
455
|
+
borderRadius: import_zod.z.number().nullable(),
|
|
456
|
+
flex: import_zod.z.number().nullable(),
|
|
457
|
+
width: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
|
|
458
|
+
height: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
|
|
459
|
+
alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
|
|
460
|
+
justifyContent: import_zod.z.enum([
|
|
461
|
+
"flex-start",
|
|
462
|
+
"center",
|
|
463
|
+
"flex-end",
|
|
464
|
+
"space-between",
|
|
465
|
+
"space-around"
|
|
466
|
+
]).nullable(),
|
|
467
|
+
flexDirection: import_zod.z.enum(["row", "column"]).nullable(),
|
|
468
|
+
position: import_zod.z.enum(["relative", "absolute"]).nullable(),
|
|
469
|
+
top: import_zod.z.number().nullable(),
|
|
470
|
+
left: import_zod.z.number().nullable(),
|
|
471
|
+
right: import_zod.z.number().nullable(),
|
|
472
|
+
bottom: import_zod.z.number().nullable(),
|
|
473
|
+
overflow: import_zod.z.enum(["visible", "hidden"]).nullable()
|
|
474
|
+
}),
|
|
475
|
+
slots: ["default"],
|
|
476
|
+
description: "Generic container with padding, margin, background, border, and flex alignment. Supports absolute positioning.",
|
|
477
|
+
example: {
|
|
478
|
+
padding: 20,
|
|
479
|
+
backgroundColor: "#f9f9f9",
|
|
480
|
+
borderRadius: 8,
|
|
481
|
+
alignItems: "center"
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
Row: {
|
|
485
|
+
props: import_zod.z.object({
|
|
486
|
+
gap: import_zod.z.number().nullable(),
|
|
487
|
+
alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
|
|
488
|
+
justifyContent: import_zod.z.enum([
|
|
489
|
+
"flex-start",
|
|
490
|
+
"center",
|
|
491
|
+
"flex-end",
|
|
492
|
+
"space-between",
|
|
493
|
+
"space-around"
|
|
494
|
+
]).nullable(),
|
|
495
|
+
padding: import_zod.z.number().nullable(),
|
|
496
|
+
flex: import_zod.z.number().nullable(),
|
|
497
|
+
wrap: import_zod.z.boolean().nullable()
|
|
498
|
+
}),
|
|
499
|
+
slots: ["default"],
|
|
500
|
+
description: "Horizontal flex layout. Use for placing elements side by side.",
|
|
501
|
+
example: { gap: 10, alignItems: "center" }
|
|
502
|
+
},
|
|
503
|
+
Column: {
|
|
504
|
+
props: import_zod.z.object({
|
|
505
|
+
gap: import_zod.z.number().nullable(),
|
|
506
|
+
alignItems: import_zod.z.enum(["flex-start", "center", "flex-end", "stretch"]).nullable(),
|
|
507
|
+
justifyContent: import_zod.z.enum([
|
|
508
|
+
"flex-start",
|
|
509
|
+
"center",
|
|
510
|
+
"flex-end",
|
|
511
|
+
"space-between",
|
|
512
|
+
"space-around"
|
|
513
|
+
]).nullable(),
|
|
514
|
+
padding: import_zod.z.number().nullable(),
|
|
515
|
+
flex: import_zod.z.number().nullable()
|
|
516
|
+
}),
|
|
517
|
+
slots: ["default"],
|
|
518
|
+
description: "Vertical flex layout. Use for stacking elements top to bottom.",
|
|
519
|
+
example: { gap: 8, padding: 10 }
|
|
520
|
+
},
|
|
521
|
+
// ==========================================================================
|
|
522
|
+
// Content Components
|
|
523
|
+
// ==========================================================================
|
|
524
|
+
Heading: {
|
|
525
|
+
props: import_zod.z.object({
|
|
526
|
+
text: import_zod.z.string(),
|
|
527
|
+
level: import_zod.z.enum(["h1", "h2", "h3", "h4"]).nullable(),
|
|
528
|
+
color: import_zod.z.string().nullable(),
|
|
529
|
+
align: import_zod.z.enum(["left", "center", "right"]).nullable(),
|
|
530
|
+
letterSpacing: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
|
|
531
|
+
lineHeight: import_zod.z.number().nullable()
|
|
532
|
+
}),
|
|
533
|
+
slots: [],
|
|
534
|
+
description: "Heading text at various levels. h1 is largest, h4 is smallest.",
|
|
535
|
+
example: { text: "Hello World", level: "h1", color: "#000000" }
|
|
536
|
+
},
|
|
537
|
+
Text: {
|
|
538
|
+
props: import_zod.z.object({
|
|
539
|
+
text: import_zod.z.string(),
|
|
540
|
+
fontSize: import_zod.z.number().nullable(),
|
|
541
|
+
color: import_zod.z.string().nullable(),
|
|
542
|
+
align: import_zod.z.enum(["left", "center", "right"]).nullable(),
|
|
543
|
+
fontWeight: import_zod.z.enum(["normal", "bold"]).nullable(),
|
|
544
|
+
fontStyle: import_zod.z.enum(["normal", "italic"]).nullable(),
|
|
545
|
+
lineHeight: import_zod.z.number().nullable(),
|
|
546
|
+
letterSpacing: import_zod.z.union([import_zod.z.number(), import_zod.z.string()]).nullable(),
|
|
547
|
+
textDecoration: import_zod.z.enum(["none", "underline", "line-through"]).nullable()
|
|
548
|
+
}),
|
|
549
|
+
slots: [],
|
|
550
|
+
description: "Body text with configurable size, color, weight, and alignment.",
|
|
551
|
+
example: { text: "Some content here.", fontSize: 16, color: "#333333" }
|
|
552
|
+
},
|
|
553
|
+
Image: {
|
|
554
|
+
props: import_zod.z.object({
|
|
555
|
+
src: import_zod.z.string(),
|
|
556
|
+
width: import_zod.z.number().nullable(),
|
|
557
|
+
height: import_zod.z.number().nullable(),
|
|
558
|
+
borderRadius: import_zod.z.number().nullable(),
|
|
559
|
+
objectFit: import_zod.z.enum(["contain", "cover", "fill", "none"]).nullable()
|
|
560
|
+
}),
|
|
561
|
+
slots: [],
|
|
562
|
+
description: "Image from a URL. Specify width and/or height to control size. For placeholder images use https://picsum.photos/{width}/{height}?random={n}.",
|
|
563
|
+
example: {
|
|
564
|
+
src: "https://picsum.photos/400/300?random=1",
|
|
565
|
+
width: 400,
|
|
566
|
+
height: 300
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
// ==========================================================================
|
|
570
|
+
// Decorative Components
|
|
571
|
+
// ==========================================================================
|
|
572
|
+
Divider: {
|
|
573
|
+
props: import_zod.z.object({
|
|
574
|
+
color: import_zod.z.string().nullable(),
|
|
575
|
+
thickness: import_zod.z.number().nullable(),
|
|
576
|
+
marginTop: import_zod.z.number().nullable(),
|
|
577
|
+
marginBottom: import_zod.z.number().nullable()
|
|
578
|
+
}),
|
|
579
|
+
slots: [],
|
|
580
|
+
description: "Horizontal line separator between content sections.",
|
|
581
|
+
example: { color: "#e5e7eb", thickness: 1 }
|
|
582
|
+
},
|
|
583
|
+
Spacer: {
|
|
584
|
+
props: import_zod.z.object({
|
|
585
|
+
height: import_zod.z.number().nullable()
|
|
586
|
+
}),
|
|
587
|
+
slots: [],
|
|
588
|
+
description: "Empty vertical space between elements.",
|
|
589
|
+
example: { height: 20 }
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
593
|
+
0 && (module.exports = {
|
|
594
|
+
renderToPng,
|
|
595
|
+
renderToSvg,
|
|
596
|
+
schema,
|
|
597
|
+
standardComponentDefinitions,
|
|
598
|
+
standardComponents
|
|
599
|
+
});
|
|
600
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/schema.ts","../src/components/standard.tsx","../src/render.tsx","../src/catalog.ts"],"sourcesContent":["// Schema\nexport { schema, type ImageSchema, type ImageSpec } from \"./schema\";\n\n// Core types (re-exported for convenience)\nexport type { Spec } from \"@json-render/core\";\n\n// Catalog-aware types\nexport type {\n SetState,\n StateModel,\n ComponentContext,\n ComponentFn,\n Components,\n} from \"./catalog-types\";\n\n// Renderer types\nexport type {\n ComponentRenderProps,\n ComponentRenderer,\n ComponentRegistry,\n} from \"./types\";\n\n// Standard components\nexport { standardComponents } from \"./components\";\n\n// Server-side render functions\nexport { renderToSvg, renderToPng, type RenderOptions } from \"./render\";\n\n// Catalog definitions\nexport {\n standardComponentDefinitions,\n type StandardComponentDefinitions,\n type StandardComponentProps,\n} from \"./catalog\";\n","import { defineSchema } from \"@json-render/core\";\n\n/**\n * The schema for @json-render/image\n *\n * Defines:\n * - Spec: A flat tree of elements with keys, types, props, and children references\n * - Catalog: Components with props schemas\n *\n * Reuses the same { root, elements } spec format as the React and React PDF renderers.\n */\nexport const schema = defineSchema(\n (s) => ({\n spec: s.object({\n root: s.string(),\n elements: s.record(\n s.object({\n type: s.ref(\"catalog.components\"),\n props: s.propsOf(\"catalog.components\"),\n children: s.array(s.string()),\n visible: s.any(),\n }),\n ),\n }),\n\n catalog: s.object({\n components: s.map({\n props: s.zod(),\n slots: s.array(s.string()),\n description: s.string(),\n example: s.any(),\n }),\n }),\n }),\n {\n defaultRules: [\n \"The root element MUST be a Frame component. It defines the image dimensions (width, height) and background.\",\n \"Frame width and height determine the output image size. Common sizes: 1200x630 (OG image), 1080x1080 (social square), 1920x1080 (banner).\",\n \"Use Row for horizontal layouts and Column for vertical layouts. Both support gap, align, and justify props.\",\n \"All text content must use Heading or Text components. Raw strings are not supported.\",\n \"Image src must be a fully qualified URL. For placeholder images, use https://picsum.photos/{width}/{height}?random={n}.\",\n \"Satori renders a subset of CSS: flexbox layout, borders, backgrounds, text styling. Absolute positioning is supported via position/top/left/right/bottom.\",\n \"CRITICAL INTEGRITY CHECK: Before outputting ANY element that references children, you MUST have already output (or will output) each child as its own element. If an element has children: ['a', 'b'], then elements 'a' and 'b' MUST exist.\",\n ],\n },\n);\n\nexport type ImageSchema = typeof schema;\n\nexport type ImageSpec<TCatalog> = typeof schema extends {\n createCatalog: (catalog: TCatalog) => { _specType: infer S };\n}\n ? S\n : never;\n","import React from \"react\";\nimport type { ComponentRenderProps, ComponentRegistry } from \"../types\";\nimport type { StandardComponentProps } from \"../catalog\";\n\nconst headingSizes: Record<string, number> = {\n h1: 48,\n h2: 36,\n h3: 28,\n h4: 22,\n};\n\nconst headingWeights: Record<string, number> = {\n h1: 700,\n h2: 700,\n h3: 600,\n h4: 600,\n};\n\n/**\n * Satori crashes on explicit `undefined` style values (e.g. `padding: undefined`).\n * Strip them so only defined properties are passed.\n */\nfunction cleanStyle(raw: Record<string, unknown>): React.CSSProperties {\n const out: Record<string, unknown> = {};\n for (const k in raw) {\n if (raw[k] !== undefined && raw[k] !== null) {\n out[k] = raw[k];\n }\n }\n return out as React.CSSProperties;\n}\n\n// =============================================================================\n// Root\n// =============================================================================\n\nfunction FrameComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Frame\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: p.display ?? \"flex\",\n flexDirection: p.flexDirection ?? \"column\",\n width: p.width,\n height: p.height,\n backgroundColor: p.backgroundColor ?? \"white\",\n padding: p.padding,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n })}\n >\n {children}\n </div>\n );\n}\n\n// =============================================================================\n// Layout Components\n// =============================================================================\n\nfunction BoxComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Box\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n flexDirection: p.flexDirection ?? \"column\",\n padding: p.padding,\n paddingTop: p.paddingTop,\n paddingBottom: p.paddingBottom,\n paddingLeft: p.paddingLeft,\n paddingRight: p.paddingRight,\n margin: p.margin,\n backgroundColor: p.backgroundColor,\n borderWidth: p.borderWidth,\n borderColor: p.borderColor,\n borderRadius: p.borderRadius,\n borderStyle: p.borderWidth ? \"solid\" : undefined,\n flex: p.flex,\n width: p.width,\n height: p.height,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n position: p.position,\n top: p.top,\n left: p.left,\n right: p.right,\n bottom: p.bottom,\n overflow: p.overflow,\n })}\n >\n {children}\n </div>\n );\n}\n\nfunction RowComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Row\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n flexDirection: \"row\",\n gap: p.gap,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n padding: p.padding,\n flex: p.flex,\n flexWrap: p.wrap ? \"wrap\" : undefined,\n })}\n >\n {children}\n </div>\n );\n}\n\nfunction ColumnComponent({\n element,\n children,\n}: ComponentRenderProps<StandardComponentProps<\"Column\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n flexDirection: \"column\",\n gap: p.gap,\n alignItems: p.alignItems,\n justifyContent: p.justifyContent,\n padding: p.padding,\n flex: p.flex,\n })}\n >\n {children}\n </div>\n );\n}\n\n// =============================================================================\n// Content Components\n// =============================================================================\n\nfunction HeadingComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Heading\">>) {\n const p = element.props;\n const level = p.level ?? \"h2\";\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n fontSize: headingSizes[level] ?? 36,\n fontWeight: headingWeights[level] ?? 700,\n color: p.color ?? \"black\",\n textAlign: p.align ?? \"left\",\n letterSpacing: p.letterSpacing,\n lineHeight: p.lineHeight ?? 1.2,\n })}\n >\n {p.text}\n </div>\n );\n}\n\nfunction TextComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Text\">>) {\n const p = element.props;\n\n return (\n <div\n style={cleanStyle({\n display: \"flex\",\n fontSize: p.fontSize ?? 16,\n color: p.color ?? \"black\",\n textAlign: p.align ?? \"left\",\n fontWeight: p.fontWeight === \"bold\" ? 700 : 400,\n fontStyle: p.fontStyle ?? \"normal\",\n lineHeight: p.lineHeight ?? 1.4,\n letterSpacing: p.letterSpacing,\n textDecoration: p.textDecoration,\n })}\n >\n {p.text}\n </div>\n );\n}\n\nfunction ImageComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Image\">>) {\n const p = element.props;\n\n return (\n <img\n src={p.src}\n width={p.width ?? undefined}\n height={p.height ?? undefined}\n style={cleanStyle({\n borderRadius: p.borderRadius,\n objectFit: p.objectFit ?? \"contain\",\n })}\n />\n );\n}\n\n// =============================================================================\n// Decorative Components\n// =============================================================================\n\nfunction DividerComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Divider\">>) {\n const p = element.props;\n\n return (\n <div\n style={{\n display: \"flex\",\n width: \"100%\",\n borderBottom: `${p.thickness ?? 1}px solid ${p.color ?? \"#e5e7eb\"}`,\n marginTop: p.marginTop ?? 8,\n marginBottom: p.marginBottom ?? 8,\n }}\n />\n );\n}\n\nfunction SpacerComponent({\n element,\n}: ComponentRenderProps<StandardComponentProps<\"Spacer\">>) {\n const p = element.props;\n\n return <div style={{ display: \"flex\", height: p.height ?? 20 }} />;\n}\n\n// =============================================================================\n// Registry\n// =============================================================================\n\nexport const standardComponents: ComponentRegistry = {\n Frame: FrameComponent,\n Box: BoxComponent,\n Row: RowComponent,\n Column: ColumnComponent,\n Heading: HeadingComponent,\n Text: TextComponent,\n Image: ImageComponent,\n Divider: DividerComponent,\n Spacer: SpacerComponent,\n};\n","import React from \"react\";\nimport satori, { type SatoriOptions } from \"satori\";\nimport type { Spec, UIElement } from \"@json-render/core\";\nimport {\n resolveElementProps,\n evaluateVisibility,\n getByPath,\n type PropResolutionContext,\n} from \"@json-render/core\";\nimport { standardComponents } from \"./components/standard\";\nimport type { ComponentRegistry } from \"./types\";\n\nexport { standardComponents };\n\nexport interface RenderOptions {\n registry?: ComponentRegistry;\n includeStandard?: boolean;\n state?: Record<string, unknown>;\n fonts?: SatoriOptions[\"fonts\"];\n /** Override the Frame width. When omitted, uses the Frame component's width prop. */\n width?: number;\n /** Override the Frame height. When omitted, uses the Frame component's height prop. */\n height?: number;\n}\n\nconst noopEmit = () => {};\n\nfunction renderElement(\n elementKey: string,\n spec: Spec,\n registry: ComponentRegistry,\n stateModel: Record<string, unknown>,\n repeatItem?: unknown,\n repeatIndex?: number,\n repeatBasePath?: string,\n): React.ReactElement | null {\n const element = spec.elements[elementKey];\n if (!element) return null;\n\n const ctx: PropResolutionContext = {\n stateModel,\n repeatItem,\n repeatIndex,\n repeatBasePath,\n };\n\n if (element.visible !== undefined) {\n if (!evaluateVisibility(element.visible, ctx)) {\n return null;\n }\n }\n\n const resolvedProps = resolveElementProps(\n element.props as Record<string, unknown>,\n ctx,\n );\n const resolvedElement: UIElement = { ...element, props: resolvedProps };\n\n const Component = registry[resolvedElement.type];\n if (!Component) return null;\n\n if (resolvedElement.repeat) {\n const items =\n (getByPath(stateModel, resolvedElement.repeat.statePath) as\n | unknown[]\n | undefined) ?? [];\n\n const fragments = items.map((item, index) => {\n const key =\n resolvedElement.repeat!.key && typeof item === \"object\" && item !== null\n ? String(\n (item as Record<string, unknown>)[resolvedElement.repeat!.key!] ??\n index,\n )\n : String(index);\n\n const childPath = `${resolvedElement.repeat!.statePath}/${index}`;\n const children = resolvedElement.children?.map((childKey) =>\n renderElement(\n childKey,\n spec,\n registry,\n stateModel,\n item,\n index,\n childPath,\n ),\n );\n\n return (\n <Component key={key} element={resolvedElement} emit={noopEmit}>\n {children}\n </Component>\n );\n });\n\n return <>{fragments}</>;\n }\n\n const children = resolvedElement.children?.map((childKey) =>\n renderElement(\n childKey,\n spec,\n registry,\n stateModel,\n repeatItem,\n repeatIndex,\n repeatBasePath,\n ),\n );\n\n return (\n <Component key={elementKey} element={resolvedElement} emit={noopEmit}>\n {children && children.length > 0 ? children : undefined}\n </Component>\n );\n}\n\ninterface ImageDimensions {\n width: number;\n height: number;\n}\n\nfunction getDimensions(\n spec: Spec,\n options: RenderOptions = {},\n): ImageDimensions {\n if (options.width && options.height) {\n return { width: options.width, height: options.height };\n }\n\n const rootElement = spec.elements[spec.root];\n const props = rootElement?.props as Record<string, unknown> | undefined;\n\n return {\n width: options.width ?? (props?.width as number) ?? 1200,\n height: options.height ?? (props?.height as number) ?? 630,\n };\n}\n\nfunction buildTree(\n spec: Spec,\n options: RenderOptions = {},\n): React.ReactElement {\n const {\n registry: customRegistry,\n includeStandard = true,\n state = {},\n } = options;\n\n const mergedState: Record<string, unknown> = {\n ...spec.state,\n ...state,\n };\n\n const registry: ComponentRegistry = {\n ...(includeStandard ? standardComponents : {}),\n ...customRegistry,\n };\n\n const root = renderElement(spec.root, spec, registry, mergedState);\n return root ?? <></>;\n}\n\n/**\n * Render a json-render spec to an SVG string.\n *\n * Uses Satori to convert the spec's component tree into SVG.\n * No additional dependencies are needed beyond satori.\n */\nexport async function renderToSvg(\n spec: Spec,\n options: RenderOptions = {},\n): Promise<string> {\n const tree = buildTree(spec, options);\n const { width, height } = getDimensions(spec, options);\n\n return satori(tree as React.ReactNode, {\n width,\n height,\n fonts: options.fonts ?? [],\n });\n}\n\n/**\n * Render a json-render spec to a PNG buffer.\n *\n * Requires `@resvg/resvg-js` to be installed as a peer dependency.\n * The SVG is first generated via Satori, then rasterized to PNG.\n */\nexport async function renderToPng(\n spec: Spec,\n options: RenderOptions = {},\n): Promise<Uint8Array> {\n const svg = await renderToSvg(spec, options);\n\n let Resvg: typeof import(\"@resvg/resvg-js\").Resvg;\n try {\n const mod = await import(\"@resvg/resvg-js\");\n Resvg = mod.Resvg;\n } catch {\n throw new Error(\n \"@resvg/resvg-js is required for PNG output. Install it with: npm install @resvg/resvg-js\",\n );\n }\n\n const resvg = new Resvg(svg);\n const pngData = resvg.render();\n return pngData.asPng();\n}\n","import { z } from \"zod\";\n\n/**\n * Standard component definitions for image catalogs.\n *\n * These define the available image components with their Zod prop schemas.\n * All components render to Satori-compatible JSX (HTML-like elements with\n * inline CSS flexbox styles).\n */\nexport const standardComponentDefinitions = {\n // ==========================================================================\n // Root\n // ==========================================================================\n\n Frame: {\n props: z.object({\n width: z.number(),\n height: z.number(),\n backgroundColor: z.string().nullable(),\n padding: z.number().nullable(),\n display: z.enum([\"flex\", \"none\"]).nullable(),\n flexDirection: z.enum([\"row\", \"column\"]).nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Root image container. Defines the output image dimensions and background. Must be the root element.\",\n example: { width: 1200, height: 630, backgroundColor: \"#ffffff\" },\n },\n\n // ==========================================================================\n // Layout Components\n // ==========================================================================\n\n Box: {\n props: z.object({\n padding: z.number().nullable(),\n paddingTop: z.number().nullable(),\n paddingBottom: z.number().nullable(),\n paddingLeft: z.number().nullable(),\n paddingRight: z.number().nullable(),\n margin: z.number().nullable(),\n backgroundColor: z.string().nullable(),\n borderWidth: z.number().nullable(),\n borderColor: z.string().nullable(),\n borderRadius: z.number().nullable(),\n flex: z.number().nullable(),\n width: z.union([z.number(), z.string()]).nullable(),\n height: z.union([z.number(), z.string()]).nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n flexDirection: z.enum([\"row\", \"column\"]).nullable(),\n position: z.enum([\"relative\", \"absolute\"]).nullable(),\n top: z.number().nullable(),\n left: z.number().nullable(),\n right: z.number().nullable(),\n bottom: z.number().nullable(),\n overflow: z.enum([\"visible\", \"hidden\"]).nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Generic container with padding, margin, background, border, and flex alignment. Supports absolute positioning.\",\n example: {\n padding: 20,\n backgroundColor: \"#f9f9f9\",\n borderRadius: 8,\n alignItems: \"center\",\n },\n },\n\n Row: {\n props: z.object({\n gap: z.number().nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n padding: z.number().nullable(),\n flex: z.number().nullable(),\n wrap: z.boolean().nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Horizontal flex layout. Use for placing elements side by side.\",\n example: { gap: 10, alignItems: \"center\" },\n },\n\n Column: {\n props: z.object({\n gap: z.number().nullable(),\n alignItems: z\n .enum([\"flex-start\", \"center\", \"flex-end\", \"stretch\"])\n .nullable(),\n justifyContent: z\n .enum([\n \"flex-start\",\n \"center\",\n \"flex-end\",\n \"space-between\",\n \"space-around\",\n ])\n .nullable(),\n padding: z.number().nullable(),\n flex: z.number().nullable(),\n }),\n slots: [\"default\"],\n description:\n \"Vertical flex layout. Use for stacking elements top to bottom.\",\n example: { gap: 8, padding: 10 },\n },\n\n // ==========================================================================\n // Content Components\n // ==========================================================================\n\n Heading: {\n props: z.object({\n text: z.string(),\n level: z.enum([\"h1\", \"h2\", \"h3\", \"h4\"]).nullable(),\n color: z.string().nullable(),\n align: z.enum([\"left\", \"center\", \"right\"]).nullable(),\n letterSpacing: z.union([z.number(), z.string()]).nullable(),\n lineHeight: z.number().nullable(),\n }),\n slots: [],\n description:\n \"Heading text at various levels. h1 is largest, h4 is smallest.\",\n example: { text: \"Hello World\", level: \"h1\", color: \"#000000\" },\n },\n\n Text: {\n props: z.object({\n text: z.string(),\n fontSize: z.number().nullable(),\n color: z.string().nullable(),\n align: z.enum([\"left\", \"center\", \"right\"]).nullable(),\n fontWeight: z.enum([\"normal\", \"bold\"]).nullable(),\n fontStyle: z.enum([\"normal\", \"italic\"]).nullable(),\n lineHeight: z.number().nullable(),\n letterSpacing: z.union([z.number(), z.string()]).nullable(),\n textDecoration: z.enum([\"none\", \"underline\", \"line-through\"]).nullable(),\n }),\n slots: [],\n description:\n \"Body text with configurable size, color, weight, and alignment.\",\n example: { text: \"Some content here.\", fontSize: 16, color: \"#333333\" },\n },\n\n Image: {\n props: z.object({\n src: z.string(),\n width: z.number().nullable(),\n height: z.number().nullable(),\n borderRadius: z.number().nullable(),\n objectFit: z.enum([\"contain\", \"cover\", \"fill\", \"none\"]).nullable(),\n }),\n slots: [],\n description:\n \"Image from a URL. Specify width and/or height to control size. For placeholder images use https://picsum.photos/{width}/{height}?random={n}.\",\n example: {\n src: \"https://picsum.photos/400/300?random=1\",\n width: 400,\n height: 300,\n },\n },\n\n // ==========================================================================\n // Decorative Components\n // ==========================================================================\n\n Divider: {\n props: z.object({\n color: z.string().nullable(),\n thickness: z.number().nullable(),\n marginTop: z.number().nullable(),\n marginBottom: z.number().nullable(),\n }),\n slots: [],\n description: \"Horizontal line separator between content sections.\",\n example: { color: \"#e5e7eb\", thickness: 1 },\n },\n\n Spacer: {\n props: z.object({\n height: z.number().nullable(),\n }),\n slots: [],\n description: \"Empty vertical space between elements.\",\n example: { height: 20 },\n },\n};\n\nexport type StandardComponentDefinitions = typeof standardComponentDefinitions;\n\nexport type StandardComponentProps<\n K extends keyof StandardComponentDefinitions,\n> = StandardComponentDefinitions[K][\"props\"] extends { _output: infer O }\n ? O\n : z.output<StandardComponentDefinitions[K][\"props\"]>;\n"],"mappings":"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","names":["import_core","import_jsx_runtime","children","satori"]}
|