@appmockup/core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/dist/index.cjs +1138 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1160 -0
- package/dist/index.d.ts +1160 -0
- package/dist/index.js +1079 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1160 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mockup config schema — a faithful port of the Swift `MockupConfig` Codable
|
|
5
|
+
* structs. This zod schema is the single source of truth for both validation and
|
|
6
|
+
* the TypeScript types (inferred below).
|
|
7
|
+
*/
|
|
8
|
+
declare const fontWeightSchema: z.ZodEnum<["regular", "medium", "semibold", "bold", "heavy", "black"]>;
|
|
9
|
+
type FontWeightName = z.infer<typeof fontWeightSchema>;
|
|
10
|
+
declare const outputSizeSchema: z.ZodObject<{
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
width: z.ZodNumber;
|
|
13
|
+
height: z.ZodNumber;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
name: string;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
}, {
|
|
19
|
+
name: string;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}>;
|
|
23
|
+
type OutputSize = z.infer<typeof outputSizeSchema>;
|
|
24
|
+
/**
|
|
25
|
+
* A soft shadow. All fields optional — renderers apply sensible defaults, so a
|
|
26
|
+
* bare `{}` means "shadow on, default look". blur/offsetX/offsetY are fractions
|
|
27
|
+
* of the canvas width (resolution-independent); color is hex (#RRGGBBAA for alpha).
|
|
28
|
+
*/
|
|
29
|
+
declare const shadowSchema: z.ZodObject<{
|
|
30
|
+
color: z.ZodOptional<z.ZodString>;
|
|
31
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
33
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
color?: string | undefined;
|
|
36
|
+
blur?: number | undefined;
|
|
37
|
+
offsetX?: number | undefined;
|
|
38
|
+
offsetY?: number | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
color?: string | undefined;
|
|
41
|
+
blur?: number | undefined;
|
|
42
|
+
offsetX?: number | undefined;
|
|
43
|
+
offsetY?: number | undefined;
|
|
44
|
+
}>;
|
|
45
|
+
type ShadowConfig = z.infer<typeof shadowSchema>;
|
|
46
|
+
/**
|
|
47
|
+
* A decorative background element drawn between the background fill and the
|
|
48
|
+
* content. Geometry is in canvas fractions: x/y of width/height, size of width.
|
|
49
|
+
* All fields except `type` optional — per-type defaults apply at render time.
|
|
50
|
+
*/
|
|
51
|
+
declare const decorationSchema: z.ZodObject<{
|
|
52
|
+
type: z.ZodEnum<["glow", "circle", "dots"]>;
|
|
53
|
+
/** Center x as a fraction of canvas width (glow/circle; ignored by dots). */
|
|
54
|
+
x: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
/** Center y as a fraction of canvas height (glow/circle; ignored by dots). */
|
|
56
|
+
y: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
/** glow/circle: radius as a fraction of canvas width; dots: dot radius. */
|
|
58
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
59
|
+
/** dots only: grid pitch as a fraction of canvas width. */
|
|
60
|
+
spacing: z.ZodOptional<z.ZodNumber>;
|
|
61
|
+
color: z.ZodOptional<z.ZodString>;
|
|
62
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
63
|
+
}, "strip", z.ZodTypeAny, {
|
|
64
|
+
type: "glow" | "circle" | "dots";
|
|
65
|
+
color?: string | undefined;
|
|
66
|
+
x?: number | undefined;
|
|
67
|
+
y?: number | undefined;
|
|
68
|
+
size?: number | undefined;
|
|
69
|
+
spacing?: number | undefined;
|
|
70
|
+
opacity?: number | undefined;
|
|
71
|
+
}, {
|
|
72
|
+
type: "glow" | "circle" | "dots";
|
|
73
|
+
color?: string | undefined;
|
|
74
|
+
x?: number | undefined;
|
|
75
|
+
y?: number | undefined;
|
|
76
|
+
size?: number | undefined;
|
|
77
|
+
spacing?: number | undefined;
|
|
78
|
+
opacity?: number | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
type DecorationConfig = z.infer<typeof decorationSchema>;
|
|
81
|
+
declare const backgroundSchema: z.ZodObject<{
|
|
82
|
+
type: z.ZodEnum<["solid", "gradient", "radial"]>;
|
|
83
|
+
colors: z.ZodArray<z.ZodString, "many">;
|
|
84
|
+
direction: z.ZodOptional<z.ZodEnum<["topToBottom", "leftToRight", "topLeftToBottomRight", "bottomToTop", "rightToLeft", "bottomLeftToTopRight"]>>;
|
|
85
|
+
/** Decorative shapes drawn on top of the fill, behind text and device. */
|
|
86
|
+
decorations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
87
|
+
type: z.ZodEnum<["glow", "circle", "dots"]>;
|
|
88
|
+
/** Center x as a fraction of canvas width (glow/circle; ignored by dots). */
|
|
89
|
+
x: z.ZodOptional<z.ZodNumber>;
|
|
90
|
+
/** Center y as a fraction of canvas height (glow/circle; ignored by dots). */
|
|
91
|
+
y: z.ZodOptional<z.ZodNumber>;
|
|
92
|
+
/** glow/circle: radius as a fraction of canvas width; dots: dot radius. */
|
|
93
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
94
|
+
/** dots only: grid pitch as a fraction of canvas width. */
|
|
95
|
+
spacing: z.ZodOptional<z.ZodNumber>;
|
|
96
|
+
color: z.ZodOptional<z.ZodString>;
|
|
97
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
type: "glow" | "circle" | "dots";
|
|
100
|
+
color?: string | undefined;
|
|
101
|
+
x?: number | undefined;
|
|
102
|
+
y?: number | undefined;
|
|
103
|
+
size?: number | undefined;
|
|
104
|
+
spacing?: number | undefined;
|
|
105
|
+
opacity?: number | undefined;
|
|
106
|
+
}, {
|
|
107
|
+
type: "glow" | "circle" | "dots";
|
|
108
|
+
color?: string | undefined;
|
|
109
|
+
x?: number | undefined;
|
|
110
|
+
y?: number | undefined;
|
|
111
|
+
size?: number | undefined;
|
|
112
|
+
spacing?: number | undefined;
|
|
113
|
+
opacity?: number | undefined;
|
|
114
|
+
}>, "many">>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
type: "solid" | "gradient" | "radial";
|
|
117
|
+
colors: string[];
|
|
118
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
119
|
+
decorations?: {
|
|
120
|
+
type: "glow" | "circle" | "dots";
|
|
121
|
+
color?: string | undefined;
|
|
122
|
+
x?: number | undefined;
|
|
123
|
+
y?: number | undefined;
|
|
124
|
+
size?: number | undefined;
|
|
125
|
+
spacing?: number | undefined;
|
|
126
|
+
opacity?: number | undefined;
|
|
127
|
+
}[] | undefined;
|
|
128
|
+
}, {
|
|
129
|
+
type: "solid" | "gradient" | "radial";
|
|
130
|
+
colors: string[];
|
|
131
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
132
|
+
decorations?: {
|
|
133
|
+
type: "glow" | "circle" | "dots";
|
|
134
|
+
color?: string | undefined;
|
|
135
|
+
x?: number | undefined;
|
|
136
|
+
y?: number | undefined;
|
|
137
|
+
size?: number | undefined;
|
|
138
|
+
spacing?: number | undefined;
|
|
139
|
+
opacity?: number | undefined;
|
|
140
|
+
}[] | undefined;
|
|
141
|
+
}>;
|
|
142
|
+
type BackgroundConfig = z.infer<typeof backgroundSchema>;
|
|
143
|
+
type GradientDirection = NonNullable<BackgroundConfig["direction"]>;
|
|
144
|
+
declare const headlineSchema: z.ZodObject<{
|
|
145
|
+
fontFamily: z.ZodOptional<z.ZodString>;
|
|
146
|
+
fontWeight: z.ZodOptional<z.ZodEnum<["regular", "medium", "semibold", "bold", "heavy", "black"]>>;
|
|
147
|
+
color: z.ZodString;
|
|
148
|
+
relativeSize: z.ZodNumber;
|
|
149
|
+
/** Optional text shadow; a bright color at zero offsets reads as a glow. */
|
|
150
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
151
|
+
color: z.ZodOptional<z.ZodString>;
|
|
152
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
153
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
154
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
155
|
+
}, "strip", z.ZodTypeAny, {
|
|
156
|
+
color?: string | undefined;
|
|
157
|
+
blur?: number | undefined;
|
|
158
|
+
offsetX?: number | undefined;
|
|
159
|
+
offsetY?: number | undefined;
|
|
160
|
+
}, {
|
|
161
|
+
color?: string | undefined;
|
|
162
|
+
blur?: number | undefined;
|
|
163
|
+
offsetX?: number | undefined;
|
|
164
|
+
offsetY?: number | undefined;
|
|
165
|
+
}>>;
|
|
166
|
+
}, "strip", z.ZodTypeAny, {
|
|
167
|
+
color: string;
|
|
168
|
+
relativeSize: number;
|
|
169
|
+
fontFamily?: string | undefined;
|
|
170
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
171
|
+
shadow?: {
|
|
172
|
+
color?: string | undefined;
|
|
173
|
+
blur?: number | undefined;
|
|
174
|
+
offsetX?: number | undefined;
|
|
175
|
+
offsetY?: number | undefined;
|
|
176
|
+
} | undefined;
|
|
177
|
+
}, {
|
|
178
|
+
color: string;
|
|
179
|
+
relativeSize: number;
|
|
180
|
+
fontFamily?: string | undefined;
|
|
181
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
182
|
+
shadow?: {
|
|
183
|
+
color?: string | undefined;
|
|
184
|
+
blur?: number | undefined;
|
|
185
|
+
offsetX?: number | undefined;
|
|
186
|
+
offsetY?: number | undefined;
|
|
187
|
+
} | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
type HeadlineConfig = z.infer<typeof headlineSchema>;
|
|
190
|
+
declare const subtitleSchema: z.ZodObject<{
|
|
191
|
+
text: z.ZodString;
|
|
192
|
+
fontFamily: z.ZodOptional<z.ZodString>;
|
|
193
|
+
fontWeight: z.ZodOptional<z.ZodEnum<["regular", "medium", "semibold", "bold", "heavy", "black"]>>;
|
|
194
|
+
color: z.ZodString;
|
|
195
|
+
relativeSize: z.ZodNumber;
|
|
196
|
+
/** Optional text shadow; a bright color at zero offsets reads as a glow. */
|
|
197
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
198
|
+
color: z.ZodOptional<z.ZodString>;
|
|
199
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
200
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
201
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
202
|
+
}, "strip", z.ZodTypeAny, {
|
|
203
|
+
color?: string | undefined;
|
|
204
|
+
blur?: number | undefined;
|
|
205
|
+
offsetX?: number | undefined;
|
|
206
|
+
offsetY?: number | undefined;
|
|
207
|
+
}, {
|
|
208
|
+
color?: string | undefined;
|
|
209
|
+
blur?: number | undefined;
|
|
210
|
+
offsetX?: number | undefined;
|
|
211
|
+
offsetY?: number | undefined;
|
|
212
|
+
}>>;
|
|
213
|
+
}, "strip", z.ZodTypeAny, {
|
|
214
|
+
color: string;
|
|
215
|
+
relativeSize: number;
|
|
216
|
+
text: string;
|
|
217
|
+
fontFamily?: string | undefined;
|
|
218
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
219
|
+
shadow?: {
|
|
220
|
+
color?: string | undefined;
|
|
221
|
+
blur?: number | undefined;
|
|
222
|
+
offsetX?: number | undefined;
|
|
223
|
+
offsetY?: number | undefined;
|
|
224
|
+
} | undefined;
|
|
225
|
+
}, {
|
|
226
|
+
color: string;
|
|
227
|
+
relativeSize: number;
|
|
228
|
+
text: string;
|
|
229
|
+
fontFamily?: string | undefined;
|
|
230
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
231
|
+
shadow?: {
|
|
232
|
+
color?: string | undefined;
|
|
233
|
+
blur?: number | undefined;
|
|
234
|
+
offsetX?: number | undefined;
|
|
235
|
+
offsetY?: number | undefined;
|
|
236
|
+
} | undefined;
|
|
237
|
+
}>;
|
|
238
|
+
type SubtitleConfig = z.infer<typeof subtitleSchema>;
|
|
239
|
+
declare const deviceFrameSchema: z.ZodObject<{
|
|
240
|
+
style: z.ZodEnum<["iPhone", "iPad"]>;
|
|
241
|
+
bezelColor: z.ZodString;
|
|
242
|
+
cornerRadius: z.ZodNumber;
|
|
243
|
+
bezelWidth: z.ZodNumber;
|
|
244
|
+
screenRelativeWidth: z.ZodNumber;
|
|
245
|
+
verticalOffset: z.ZodNumber;
|
|
246
|
+
/** Device left edge as a fraction of canvas width. Omit/undefined = horizontally centered. */
|
|
247
|
+
horizontalOffset: z.ZodOptional<z.ZodNumber>;
|
|
248
|
+
/** Clockwise rotation about the device center, in degrees. Omit/undefined = 0. */
|
|
249
|
+
rotation: z.ZodOptional<z.ZodNumber>;
|
|
250
|
+
/**
|
|
251
|
+
* How the screenshot fills the device screen. "cover" (default) scales to fill and crops
|
|
252
|
+
* the overflow; "contain" scales to fit entirely, letterboxing with the bezel color.
|
|
253
|
+
*/
|
|
254
|
+
fit: z.ZodOptional<z.ZodEnum<["cover", "contain"]>>;
|
|
255
|
+
/** Drop shadow under the device. A bare `{}` uses the default soft look. */
|
|
256
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
257
|
+
color: z.ZodOptional<z.ZodString>;
|
|
258
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
259
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
260
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
261
|
+
}, "strip", z.ZodTypeAny, {
|
|
262
|
+
color?: string | undefined;
|
|
263
|
+
blur?: number | undefined;
|
|
264
|
+
offsetX?: number | undefined;
|
|
265
|
+
offsetY?: number | undefined;
|
|
266
|
+
}, {
|
|
267
|
+
color?: string | undefined;
|
|
268
|
+
blur?: number | undefined;
|
|
269
|
+
offsetX?: number | undefined;
|
|
270
|
+
offsetY?: number | undefined;
|
|
271
|
+
}>>;
|
|
272
|
+
/** Horizontal shear in degrees about the device center — a pseudo-3D lean. */
|
|
273
|
+
tilt: z.ZodOptional<z.ZodNumber>;
|
|
274
|
+
}, "strip", z.ZodTypeAny, {
|
|
275
|
+
style: "iPhone" | "iPad";
|
|
276
|
+
bezelColor: string;
|
|
277
|
+
cornerRadius: number;
|
|
278
|
+
bezelWidth: number;
|
|
279
|
+
screenRelativeWidth: number;
|
|
280
|
+
verticalOffset: number;
|
|
281
|
+
shadow?: {
|
|
282
|
+
color?: string | undefined;
|
|
283
|
+
blur?: number | undefined;
|
|
284
|
+
offsetX?: number | undefined;
|
|
285
|
+
offsetY?: number | undefined;
|
|
286
|
+
} | undefined;
|
|
287
|
+
horizontalOffset?: number | undefined;
|
|
288
|
+
rotation?: number | undefined;
|
|
289
|
+
fit?: "cover" | "contain" | undefined;
|
|
290
|
+
tilt?: number | undefined;
|
|
291
|
+
}, {
|
|
292
|
+
style: "iPhone" | "iPad";
|
|
293
|
+
bezelColor: string;
|
|
294
|
+
cornerRadius: number;
|
|
295
|
+
bezelWidth: number;
|
|
296
|
+
screenRelativeWidth: number;
|
|
297
|
+
verticalOffset: number;
|
|
298
|
+
shadow?: {
|
|
299
|
+
color?: string | undefined;
|
|
300
|
+
blur?: number | undefined;
|
|
301
|
+
offsetX?: number | undefined;
|
|
302
|
+
offsetY?: number | undefined;
|
|
303
|
+
} | undefined;
|
|
304
|
+
horizontalOffset?: number | undefined;
|
|
305
|
+
rotation?: number | undefined;
|
|
306
|
+
fit?: "cover" | "contain" | undefined;
|
|
307
|
+
tilt?: number | undefined;
|
|
308
|
+
}>;
|
|
309
|
+
type DeviceFrameConfig = z.infer<typeof deviceFrameSchema>;
|
|
310
|
+
declare const screenshotEntrySchema: z.ZodObject<{
|
|
311
|
+
id: z.ZodString;
|
|
312
|
+
file: z.ZodString;
|
|
313
|
+
headlines: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
314
|
+
/** Overrides the global background for this screenshot (incl. its decorations). */
|
|
315
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
316
|
+
type: z.ZodEnum<["solid", "gradient", "radial"]>;
|
|
317
|
+
colors: z.ZodArray<z.ZodString, "many">;
|
|
318
|
+
direction: z.ZodOptional<z.ZodEnum<["topToBottom", "leftToRight", "topLeftToBottomRight", "bottomToTop", "rightToLeft", "bottomLeftToTopRight"]>>;
|
|
319
|
+
/** Decorative shapes drawn on top of the fill, behind text and device. */
|
|
320
|
+
decorations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
321
|
+
type: z.ZodEnum<["glow", "circle", "dots"]>;
|
|
322
|
+
/** Center x as a fraction of canvas width (glow/circle; ignored by dots). */
|
|
323
|
+
x: z.ZodOptional<z.ZodNumber>;
|
|
324
|
+
/** Center y as a fraction of canvas height (glow/circle; ignored by dots). */
|
|
325
|
+
y: z.ZodOptional<z.ZodNumber>;
|
|
326
|
+
/** glow/circle: radius as a fraction of canvas width; dots: dot radius. */
|
|
327
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
328
|
+
/** dots only: grid pitch as a fraction of canvas width. */
|
|
329
|
+
spacing: z.ZodOptional<z.ZodNumber>;
|
|
330
|
+
color: z.ZodOptional<z.ZodString>;
|
|
331
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
332
|
+
}, "strip", z.ZodTypeAny, {
|
|
333
|
+
type: "glow" | "circle" | "dots";
|
|
334
|
+
color?: string | undefined;
|
|
335
|
+
x?: number | undefined;
|
|
336
|
+
y?: number | undefined;
|
|
337
|
+
size?: number | undefined;
|
|
338
|
+
spacing?: number | undefined;
|
|
339
|
+
opacity?: number | undefined;
|
|
340
|
+
}, {
|
|
341
|
+
type: "glow" | "circle" | "dots";
|
|
342
|
+
color?: string | undefined;
|
|
343
|
+
x?: number | undefined;
|
|
344
|
+
y?: number | undefined;
|
|
345
|
+
size?: number | undefined;
|
|
346
|
+
spacing?: number | undefined;
|
|
347
|
+
opacity?: number | undefined;
|
|
348
|
+
}>, "many">>;
|
|
349
|
+
}, "strip", z.ZodTypeAny, {
|
|
350
|
+
type: "solid" | "gradient" | "radial";
|
|
351
|
+
colors: string[];
|
|
352
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
353
|
+
decorations?: {
|
|
354
|
+
type: "glow" | "circle" | "dots";
|
|
355
|
+
color?: string | undefined;
|
|
356
|
+
x?: number | undefined;
|
|
357
|
+
y?: number | undefined;
|
|
358
|
+
size?: number | undefined;
|
|
359
|
+
spacing?: number | undefined;
|
|
360
|
+
opacity?: number | undefined;
|
|
361
|
+
}[] | undefined;
|
|
362
|
+
}, {
|
|
363
|
+
type: "solid" | "gradient" | "radial";
|
|
364
|
+
colors: string[];
|
|
365
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
366
|
+
decorations?: {
|
|
367
|
+
type: "glow" | "circle" | "dots";
|
|
368
|
+
color?: string | undefined;
|
|
369
|
+
x?: number | undefined;
|
|
370
|
+
y?: number | undefined;
|
|
371
|
+
size?: number | undefined;
|
|
372
|
+
spacing?: number | undefined;
|
|
373
|
+
opacity?: number | undefined;
|
|
374
|
+
}[] | undefined;
|
|
375
|
+
}>>;
|
|
376
|
+
}, "strip", z.ZodTypeAny, {
|
|
377
|
+
id: string;
|
|
378
|
+
file: string;
|
|
379
|
+
headlines: Record<string, string>;
|
|
380
|
+
background?: {
|
|
381
|
+
type: "solid" | "gradient" | "radial";
|
|
382
|
+
colors: string[];
|
|
383
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
384
|
+
decorations?: {
|
|
385
|
+
type: "glow" | "circle" | "dots";
|
|
386
|
+
color?: string | undefined;
|
|
387
|
+
x?: number | undefined;
|
|
388
|
+
y?: number | undefined;
|
|
389
|
+
size?: number | undefined;
|
|
390
|
+
spacing?: number | undefined;
|
|
391
|
+
opacity?: number | undefined;
|
|
392
|
+
}[] | undefined;
|
|
393
|
+
} | undefined;
|
|
394
|
+
}, {
|
|
395
|
+
id: string;
|
|
396
|
+
file: string;
|
|
397
|
+
headlines: Record<string, string>;
|
|
398
|
+
background?: {
|
|
399
|
+
type: "solid" | "gradient" | "radial";
|
|
400
|
+
colors: string[];
|
|
401
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
402
|
+
decorations?: {
|
|
403
|
+
type: "glow" | "circle" | "dots";
|
|
404
|
+
color?: string | undefined;
|
|
405
|
+
x?: number | undefined;
|
|
406
|
+
y?: number | undefined;
|
|
407
|
+
size?: number | undefined;
|
|
408
|
+
spacing?: number | undefined;
|
|
409
|
+
opacity?: number | undefined;
|
|
410
|
+
}[] | undefined;
|
|
411
|
+
} | undefined;
|
|
412
|
+
}>;
|
|
413
|
+
type ScreenshotEntry = z.infer<typeof screenshotEntrySchema>;
|
|
414
|
+
declare const mockupConfigSchema: z.ZodObject<{
|
|
415
|
+
appName: z.ZodString;
|
|
416
|
+
outputPrefix: z.ZodString;
|
|
417
|
+
languages: z.ZodArray<z.ZodString, "many">;
|
|
418
|
+
outputSizes: z.ZodArray<z.ZodObject<{
|
|
419
|
+
name: z.ZodString;
|
|
420
|
+
width: z.ZodNumber;
|
|
421
|
+
height: z.ZodNumber;
|
|
422
|
+
}, "strip", z.ZodTypeAny, {
|
|
423
|
+
name: string;
|
|
424
|
+
width: number;
|
|
425
|
+
height: number;
|
|
426
|
+
}, {
|
|
427
|
+
name: string;
|
|
428
|
+
width: number;
|
|
429
|
+
height: number;
|
|
430
|
+
}>, "many">;
|
|
431
|
+
background: z.ZodObject<{
|
|
432
|
+
type: z.ZodEnum<["solid", "gradient", "radial"]>;
|
|
433
|
+
colors: z.ZodArray<z.ZodString, "many">;
|
|
434
|
+
direction: z.ZodOptional<z.ZodEnum<["topToBottom", "leftToRight", "topLeftToBottomRight", "bottomToTop", "rightToLeft", "bottomLeftToTopRight"]>>;
|
|
435
|
+
/** Decorative shapes drawn on top of the fill, behind text and device. */
|
|
436
|
+
decorations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
437
|
+
type: z.ZodEnum<["glow", "circle", "dots"]>;
|
|
438
|
+
/** Center x as a fraction of canvas width (glow/circle; ignored by dots). */
|
|
439
|
+
x: z.ZodOptional<z.ZodNumber>;
|
|
440
|
+
/** Center y as a fraction of canvas height (glow/circle; ignored by dots). */
|
|
441
|
+
y: z.ZodOptional<z.ZodNumber>;
|
|
442
|
+
/** glow/circle: radius as a fraction of canvas width; dots: dot radius. */
|
|
443
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
444
|
+
/** dots only: grid pitch as a fraction of canvas width. */
|
|
445
|
+
spacing: z.ZodOptional<z.ZodNumber>;
|
|
446
|
+
color: z.ZodOptional<z.ZodString>;
|
|
447
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
448
|
+
}, "strip", z.ZodTypeAny, {
|
|
449
|
+
type: "glow" | "circle" | "dots";
|
|
450
|
+
color?: string | undefined;
|
|
451
|
+
x?: number | undefined;
|
|
452
|
+
y?: number | undefined;
|
|
453
|
+
size?: number | undefined;
|
|
454
|
+
spacing?: number | undefined;
|
|
455
|
+
opacity?: number | undefined;
|
|
456
|
+
}, {
|
|
457
|
+
type: "glow" | "circle" | "dots";
|
|
458
|
+
color?: string | undefined;
|
|
459
|
+
x?: number | undefined;
|
|
460
|
+
y?: number | undefined;
|
|
461
|
+
size?: number | undefined;
|
|
462
|
+
spacing?: number | undefined;
|
|
463
|
+
opacity?: number | undefined;
|
|
464
|
+
}>, "many">>;
|
|
465
|
+
}, "strip", z.ZodTypeAny, {
|
|
466
|
+
type: "solid" | "gradient" | "radial";
|
|
467
|
+
colors: string[];
|
|
468
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
469
|
+
decorations?: {
|
|
470
|
+
type: "glow" | "circle" | "dots";
|
|
471
|
+
color?: string | undefined;
|
|
472
|
+
x?: number | undefined;
|
|
473
|
+
y?: number | undefined;
|
|
474
|
+
size?: number | undefined;
|
|
475
|
+
spacing?: number | undefined;
|
|
476
|
+
opacity?: number | undefined;
|
|
477
|
+
}[] | undefined;
|
|
478
|
+
}, {
|
|
479
|
+
type: "solid" | "gradient" | "radial";
|
|
480
|
+
colors: string[];
|
|
481
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
482
|
+
decorations?: {
|
|
483
|
+
type: "glow" | "circle" | "dots";
|
|
484
|
+
color?: string | undefined;
|
|
485
|
+
x?: number | undefined;
|
|
486
|
+
y?: number | undefined;
|
|
487
|
+
size?: number | undefined;
|
|
488
|
+
spacing?: number | undefined;
|
|
489
|
+
opacity?: number | undefined;
|
|
490
|
+
}[] | undefined;
|
|
491
|
+
}>;
|
|
492
|
+
headline: z.ZodObject<{
|
|
493
|
+
fontFamily: z.ZodOptional<z.ZodString>;
|
|
494
|
+
fontWeight: z.ZodOptional<z.ZodEnum<["regular", "medium", "semibold", "bold", "heavy", "black"]>>;
|
|
495
|
+
color: z.ZodString;
|
|
496
|
+
relativeSize: z.ZodNumber;
|
|
497
|
+
/** Optional text shadow; a bright color at zero offsets reads as a glow. */
|
|
498
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
499
|
+
color: z.ZodOptional<z.ZodString>;
|
|
500
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
501
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
502
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
503
|
+
}, "strip", z.ZodTypeAny, {
|
|
504
|
+
color?: string | undefined;
|
|
505
|
+
blur?: number | undefined;
|
|
506
|
+
offsetX?: number | undefined;
|
|
507
|
+
offsetY?: number | undefined;
|
|
508
|
+
}, {
|
|
509
|
+
color?: string | undefined;
|
|
510
|
+
blur?: number | undefined;
|
|
511
|
+
offsetX?: number | undefined;
|
|
512
|
+
offsetY?: number | undefined;
|
|
513
|
+
}>>;
|
|
514
|
+
}, "strip", z.ZodTypeAny, {
|
|
515
|
+
color: string;
|
|
516
|
+
relativeSize: number;
|
|
517
|
+
fontFamily?: string | undefined;
|
|
518
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
519
|
+
shadow?: {
|
|
520
|
+
color?: string | undefined;
|
|
521
|
+
blur?: number | undefined;
|
|
522
|
+
offsetX?: number | undefined;
|
|
523
|
+
offsetY?: number | undefined;
|
|
524
|
+
} | undefined;
|
|
525
|
+
}, {
|
|
526
|
+
color: string;
|
|
527
|
+
relativeSize: number;
|
|
528
|
+
fontFamily?: string | undefined;
|
|
529
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
530
|
+
shadow?: {
|
|
531
|
+
color?: string | undefined;
|
|
532
|
+
blur?: number | undefined;
|
|
533
|
+
offsetX?: number | undefined;
|
|
534
|
+
offsetY?: number | undefined;
|
|
535
|
+
} | undefined;
|
|
536
|
+
}>;
|
|
537
|
+
subtitle: z.ZodOptional<z.ZodObject<{
|
|
538
|
+
text: z.ZodString;
|
|
539
|
+
fontFamily: z.ZodOptional<z.ZodString>;
|
|
540
|
+
fontWeight: z.ZodOptional<z.ZodEnum<["regular", "medium", "semibold", "bold", "heavy", "black"]>>;
|
|
541
|
+
color: z.ZodString;
|
|
542
|
+
relativeSize: z.ZodNumber;
|
|
543
|
+
/** Optional text shadow; a bright color at zero offsets reads as a glow. */
|
|
544
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
545
|
+
color: z.ZodOptional<z.ZodString>;
|
|
546
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
547
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
548
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
549
|
+
}, "strip", z.ZodTypeAny, {
|
|
550
|
+
color?: string | undefined;
|
|
551
|
+
blur?: number | undefined;
|
|
552
|
+
offsetX?: number | undefined;
|
|
553
|
+
offsetY?: number | undefined;
|
|
554
|
+
}, {
|
|
555
|
+
color?: string | undefined;
|
|
556
|
+
blur?: number | undefined;
|
|
557
|
+
offsetX?: number | undefined;
|
|
558
|
+
offsetY?: number | undefined;
|
|
559
|
+
}>>;
|
|
560
|
+
}, "strip", z.ZodTypeAny, {
|
|
561
|
+
color: string;
|
|
562
|
+
relativeSize: number;
|
|
563
|
+
text: string;
|
|
564
|
+
fontFamily?: string | undefined;
|
|
565
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
566
|
+
shadow?: {
|
|
567
|
+
color?: string | undefined;
|
|
568
|
+
blur?: number | undefined;
|
|
569
|
+
offsetX?: number | undefined;
|
|
570
|
+
offsetY?: number | undefined;
|
|
571
|
+
} | undefined;
|
|
572
|
+
}, {
|
|
573
|
+
color: string;
|
|
574
|
+
relativeSize: number;
|
|
575
|
+
text: string;
|
|
576
|
+
fontFamily?: string | undefined;
|
|
577
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
578
|
+
shadow?: {
|
|
579
|
+
color?: string | undefined;
|
|
580
|
+
blur?: number | undefined;
|
|
581
|
+
offsetX?: number | undefined;
|
|
582
|
+
offsetY?: number | undefined;
|
|
583
|
+
} | undefined;
|
|
584
|
+
}>>;
|
|
585
|
+
deviceFrame: z.ZodObject<{
|
|
586
|
+
style: z.ZodEnum<["iPhone", "iPad"]>;
|
|
587
|
+
bezelColor: z.ZodString;
|
|
588
|
+
cornerRadius: z.ZodNumber;
|
|
589
|
+
bezelWidth: z.ZodNumber;
|
|
590
|
+
screenRelativeWidth: z.ZodNumber;
|
|
591
|
+
verticalOffset: z.ZodNumber;
|
|
592
|
+
/** Device left edge as a fraction of canvas width. Omit/undefined = horizontally centered. */
|
|
593
|
+
horizontalOffset: z.ZodOptional<z.ZodNumber>;
|
|
594
|
+
/** Clockwise rotation about the device center, in degrees. Omit/undefined = 0. */
|
|
595
|
+
rotation: z.ZodOptional<z.ZodNumber>;
|
|
596
|
+
/**
|
|
597
|
+
* How the screenshot fills the device screen. "cover" (default) scales to fill and crops
|
|
598
|
+
* the overflow; "contain" scales to fit entirely, letterboxing with the bezel color.
|
|
599
|
+
*/
|
|
600
|
+
fit: z.ZodOptional<z.ZodEnum<["cover", "contain"]>>;
|
|
601
|
+
/** Drop shadow under the device. A bare `{}` uses the default soft look. */
|
|
602
|
+
shadow: z.ZodOptional<z.ZodObject<{
|
|
603
|
+
color: z.ZodOptional<z.ZodString>;
|
|
604
|
+
blur: z.ZodOptional<z.ZodNumber>;
|
|
605
|
+
offsetX: z.ZodOptional<z.ZodNumber>;
|
|
606
|
+
offsetY: z.ZodOptional<z.ZodNumber>;
|
|
607
|
+
}, "strip", z.ZodTypeAny, {
|
|
608
|
+
color?: string | undefined;
|
|
609
|
+
blur?: number | undefined;
|
|
610
|
+
offsetX?: number | undefined;
|
|
611
|
+
offsetY?: number | undefined;
|
|
612
|
+
}, {
|
|
613
|
+
color?: string | undefined;
|
|
614
|
+
blur?: number | undefined;
|
|
615
|
+
offsetX?: number | undefined;
|
|
616
|
+
offsetY?: number | undefined;
|
|
617
|
+
}>>;
|
|
618
|
+
/** Horizontal shear in degrees about the device center — a pseudo-3D lean. */
|
|
619
|
+
tilt: z.ZodOptional<z.ZodNumber>;
|
|
620
|
+
}, "strip", z.ZodTypeAny, {
|
|
621
|
+
style: "iPhone" | "iPad";
|
|
622
|
+
bezelColor: string;
|
|
623
|
+
cornerRadius: number;
|
|
624
|
+
bezelWidth: number;
|
|
625
|
+
screenRelativeWidth: number;
|
|
626
|
+
verticalOffset: number;
|
|
627
|
+
shadow?: {
|
|
628
|
+
color?: string | undefined;
|
|
629
|
+
blur?: number | undefined;
|
|
630
|
+
offsetX?: number | undefined;
|
|
631
|
+
offsetY?: number | undefined;
|
|
632
|
+
} | undefined;
|
|
633
|
+
horizontalOffset?: number | undefined;
|
|
634
|
+
rotation?: number | undefined;
|
|
635
|
+
fit?: "cover" | "contain" | undefined;
|
|
636
|
+
tilt?: number | undefined;
|
|
637
|
+
}, {
|
|
638
|
+
style: "iPhone" | "iPad";
|
|
639
|
+
bezelColor: string;
|
|
640
|
+
cornerRadius: number;
|
|
641
|
+
bezelWidth: number;
|
|
642
|
+
screenRelativeWidth: number;
|
|
643
|
+
verticalOffset: number;
|
|
644
|
+
shadow?: {
|
|
645
|
+
color?: string | undefined;
|
|
646
|
+
blur?: number | undefined;
|
|
647
|
+
offsetX?: number | undefined;
|
|
648
|
+
offsetY?: number | undefined;
|
|
649
|
+
} | undefined;
|
|
650
|
+
horizontalOffset?: number | undefined;
|
|
651
|
+
rotation?: number | undefined;
|
|
652
|
+
fit?: "cover" | "contain" | undefined;
|
|
653
|
+
tilt?: number | undefined;
|
|
654
|
+
}>;
|
|
655
|
+
screenshots: z.ZodArray<z.ZodObject<{
|
|
656
|
+
id: z.ZodString;
|
|
657
|
+
file: z.ZodString;
|
|
658
|
+
headlines: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
659
|
+
/** Overrides the global background for this screenshot (incl. its decorations). */
|
|
660
|
+
background: z.ZodOptional<z.ZodObject<{
|
|
661
|
+
type: z.ZodEnum<["solid", "gradient", "radial"]>;
|
|
662
|
+
colors: z.ZodArray<z.ZodString, "many">;
|
|
663
|
+
direction: z.ZodOptional<z.ZodEnum<["topToBottom", "leftToRight", "topLeftToBottomRight", "bottomToTop", "rightToLeft", "bottomLeftToTopRight"]>>;
|
|
664
|
+
/** Decorative shapes drawn on top of the fill, behind text and device. */
|
|
665
|
+
decorations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
666
|
+
type: z.ZodEnum<["glow", "circle", "dots"]>;
|
|
667
|
+
/** Center x as a fraction of canvas width (glow/circle; ignored by dots). */
|
|
668
|
+
x: z.ZodOptional<z.ZodNumber>;
|
|
669
|
+
/** Center y as a fraction of canvas height (glow/circle; ignored by dots). */
|
|
670
|
+
y: z.ZodOptional<z.ZodNumber>;
|
|
671
|
+
/** glow/circle: radius as a fraction of canvas width; dots: dot radius. */
|
|
672
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
673
|
+
/** dots only: grid pitch as a fraction of canvas width. */
|
|
674
|
+
spacing: z.ZodOptional<z.ZodNumber>;
|
|
675
|
+
color: z.ZodOptional<z.ZodString>;
|
|
676
|
+
opacity: z.ZodOptional<z.ZodNumber>;
|
|
677
|
+
}, "strip", z.ZodTypeAny, {
|
|
678
|
+
type: "glow" | "circle" | "dots";
|
|
679
|
+
color?: string | undefined;
|
|
680
|
+
x?: number | undefined;
|
|
681
|
+
y?: number | undefined;
|
|
682
|
+
size?: number | undefined;
|
|
683
|
+
spacing?: number | undefined;
|
|
684
|
+
opacity?: number | undefined;
|
|
685
|
+
}, {
|
|
686
|
+
type: "glow" | "circle" | "dots";
|
|
687
|
+
color?: string | undefined;
|
|
688
|
+
x?: number | undefined;
|
|
689
|
+
y?: number | undefined;
|
|
690
|
+
size?: number | undefined;
|
|
691
|
+
spacing?: number | undefined;
|
|
692
|
+
opacity?: number | undefined;
|
|
693
|
+
}>, "many">>;
|
|
694
|
+
}, "strip", z.ZodTypeAny, {
|
|
695
|
+
type: "solid" | "gradient" | "radial";
|
|
696
|
+
colors: string[];
|
|
697
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
698
|
+
decorations?: {
|
|
699
|
+
type: "glow" | "circle" | "dots";
|
|
700
|
+
color?: string | undefined;
|
|
701
|
+
x?: number | undefined;
|
|
702
|
+
y?: number | undefined;
|
|
703
|
+
size?: number | undefined;
|
|
704
|
+
spacing?: number | undefined;
|
|
705
|
+
opacity?: number | undefined;
|
|
706
|
+
}[] | undefined;
|
|
707
|
+
}, {
|
|
708
|
+
type: "solid" | "gradient" | "radial";
|
|
709
|
+
colors: string[];
|
|
710
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
711
|
+
decorations?: {
|
|
712
|
+
type: "glow" | "circle" | "dots";
|
|
713
|
+
color?: string | undefined;
|
|
714
|
+
x?: number | undefined;
|
|
715
|
+
y?: number | undefined;
|
|
716
|
+
size?: number | undefined;
|
|
717
|
+
spacing?: number | undefined;
|
|
718
|
+
opacity?: number | undefined;
|
|
719
|
+
}[] | undefined;
|
|
720
|
+
}>>;
|
|
721
|
+
}, "strip", z.ZodTypeAny, {
|
|
722
|
+
id: string;
|
|
723
|
+
file: string;
|
|
724
|
+
headlines: Record<string, string>;
|
|
725
|
+
background?: {
|
|
726
|
+
type: "solid" | "gradient" | "radial";
|
|
727
|
+
colors: string[];
|
|
728
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
729
|
+
decorations?: {
|
|
730
|
+
type: "glow" | "circle" | "dots";
|
|
731
|
+
color?: string | undefined;
|
|
732
|
+
x?: number | undefined;
|
|
733
|
+
y?: number | undefined;
|
|
734
|
+
size?: number | undefined;
|
|
735
|
+
spacing?: number | undefined;
|
|
736
|
+
opacity?: number | undefined;
|
|
737
|
+
}[] | undefined;
|
|
738
|
+
} | undefined;
|
|
739
|
+
}, {
|
|
740
|
+
id: string;
|
|
741
|
+
file: string;
|
|
742
|
+
headlines: Record<string, string>;
|
|
743
|
+
background?: {
|
|
744
|
+
type: "solid" | "gradient" | "radial";
|
|
745
|
+
colors: string[];
|
|
746
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
747
|
+
decorations?: {
|
|
748
|
+
type: "glow" | "circle" | "dots";
|
|
749
|
+
color?: string | undefined;
|
|
750
|
+
x?: number | undefined;
|
|
751
|
+
y?: number | undefined;
|
|
752
|
+
size?: number | undefined;
|
|
753
|
+
spacing?: number | undefined;
|
|
754
|
+
opacity?: number | undefined;
|
|
755
|
+
}[] | undefined;
|
|
756
|
+
} | undefined;
|
|
757
|
+
}>, "many">;
|
|
758
|
+
}, "strip", z.ZodTypeAny, {
|
|
759
|
+
background: {
|
|
760
|
+
type: "solid" | "gradient" | "radial";
|
|
761
|
+
colors: string[];
|
|
762
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
763
|
+
decorations?: {
|
|
764
|
+
type: "glow" | "circle" | "dots";
|
|
765
|
+
color?: string | undefined;
|
|
766
|
+
x?: number | undefined;
|
|
767
|
+
y?: number | undefined;
|
|
768
|
+
size?: number | undefined;
|
|
769
|
+
spacing?: number | undefined;
|
|
770
|
+
opacity?: number | undefined;
|
|
771
|
+
}[] | undefined;
|
|
772
|
+
};
|
|
773
|
+
appName: string;
|
|
774
|
+
outputPrefix: string;
|
|
775
|
+
languages: string[];
|
|
776
|
+
outputSizes: {
|
|
777
|
+
name: string;
|
|
778
|
+
width: number;
|
|
779
|
+
height: number;
|
|
780
|
+
}[];
|
|
781
|
+
headline: {
|
|
782
|
+
color: string;
|
|
783
|
+
relativeSize: number;
|
|
784
|
+
fontFamily?: string | undefined;
|
|
785
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
786
|
+
shadow?: {
|
|
787
|
+
color?: string | undefined;
|
|
788
|
+
blur?: number | undefined;
|
|
789
|
+
offsetX?: number | undefined;
|
|
790
|
+
offsetY?: number | undefined;
|
|
791
|
+
} | undefined;
|
|
792
|
+
};
|
|
793
|
+
deviceFrame: {
|
|
794
|
+
style: "iPhone" | "iPad";
|
|
795
|
+
bezelColor: string;
|
|
796
|
+
cornerRadius: number;
|
|
797
|
+
bezelWidth: number;
|
|
798
|
+
screenRelativeWidth: number;
|
|
799
|
+
verticalOffset: number;
|
|
800
|
+
shadow?: {
|
|
801
|
+
color?: string | undefined;
|
|
802
|
+
blur?: number | undefined;
|
|
803
|
+
offsetX?: number | undefined;
|
|
804
|
+
offsetY?: number | undefined;
|
|
805
|
+
} | undefined;
|
|
806
|
+
horizontalOffset?: number | undefined;
|
|
807
|
+
rotation?: number | undefined;
|
|
808
|
+
fit?: "cover" | "contain" | undefined;
|
|
809
|
+
tilt?: number | undefined;
|
|
810
|
+
};
|
|
811
|
+
screenshots: {
|
|
812
|
+
id: string;
|
|
813
|
+
file: string;
|
|
814
|
+
headlines: Record<string, string>;
|
|
815
|
+
background?: {
|
|
816
|
+
type: "solid" | "gradient" | "radial";
|
|
817
|
+
colors: string[];
|
|
818
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
819
|
+
decorations?: {
|
|
820
|
+
type: "glow" | "circle" | "dots";
|
|
821
|
+
color?: string | undefined;
|
|
822
|
+
x?: number | undefined;
|
|
823
|
+
y?: number | undefined;
|
|
824
|
+
size?: number | undefined;
|
|
825
|
+
spacing?: number | undefined;
|
|
826
|
+
opacity?: number | undefined;
|
|
827
|
+
}[] | undefined;
|
|
828
|
+
} | undefined;
|
|
829
|
+
}[];
|
|
830
|
+
subtitle?: {
|
|
831
|
+
color: string;
|
|
832
|
+
relativeSize: number;
|
|
833
|
+
text: string;
|
|
834
|
+
fontFamily?: string | undefined;
|
|
835
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
836
|
+
shadow?: {
|
|
837
|
+
color?: string | undefined;
|
|
838
|
+
blur?: number | undefined;
|
|
839
|
+
offsetX?: number | undefined;
|
|
840
|
+
offsetY?: number | undefined;
|
|
841
|
+
} | undefined;
|
|
842
|
+
} | undefined;
|
|
843
|
+
}, {
|
|
844
|
+
background: {
|
|
845
|
+
type: "solid" | "gradient" | "radial";
|
|
846
|
+
colors: string[];
|
|
847
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
848
|
+
decorations?: {
|
|
849
|
+
type: "glow" | "circle" | "dots";
|
|
850
|
+
color?: string | undefined;
|
|
851
|
+
x?: number | undefined;
|
|
852
|
+
y?: number | undefined;
|
|
853
|
+
size?: number | undefined;
|
|
854
|
+
spacing?: number | undefined;
|
|
855
|
+
opacity?: number | undefined;
|
|
856
|
+
}[] | undefined;
|
|
857
|
+
};
|
|
858
|
+
appName: string;
|
|
859
|
+
outputPrefix: string;
|
|
860
|
+
languages: string[];
|
|
861
|
+
outputSizes: {
|
|
862
|
+
name: string;
|
|
863
|
+
width: number;
|
|
864
|
+
height: number;
|
|
865
|
+
}[];
|
|
866
|
+
headline: {
|
|
867
|
+
color: string;
|
|
868
|
+
relativeSize: number;
|
|
869
|
+
fontFamily?: string | undefined;
|
|
870
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
871
|
+
shadow?: {
|
|
872
|
+
color?: string | undefined;
|
|
873
|
+
blur?: number | undefined;
|
|
874
|
+
offsetX?: number | undefined;
|
|
875
|
+
offsetY?: number | undefined;
|
|
876
|
+
} | undefined;
|
|
877
|
+
};
|
|
878
|
+
deviceFrame: {
|
|
879
|
+
style: "iPhone" | "iPad";
|
|
880
|
+
bezelColor: string;
|
|
881
|
+
cornerRadius: number;
|
|
882
|
+
bezelWidth: number;
|
|
883
|
+
screenRelativeWidth: number;
|
|
884
|
+
verticalOffset: number;
|
|
885
|
+
shadow?: {
|
|
886
|
+
color?: string | undefined;
|
|
887
|
+
blur?: number | undefined;
|
|
888
|
+
offsetX?: number | undefined;
|
|
889
|
+
offsetY?: number | undefined;
|
|
890
|
+
} | undefined;
|
|
891
|
+
horizontalOffset?: number | undefined;
|
|
892
|
+
rotation?: number | undefined;
|
|
893
|
+
fit?: "cover" | "contain" | undefined;
|
|
894
|
+
tilt?: number | undefined;
|
|
895
|
+
};
|
|
896
|
+
screenshots: {
|
|
897
|
+
id: string;
|
|
898
|
+
file: string;
|
|
899
|
+
headlines: Record<string, string>;
|
|
900
|
+
background?: {
|
|
901
|
+
type: "solid" | "gradient" | "radial";
|
|
902
|
+
colors: string[];
|
|
903
|
+
direction?: "topToBottom" | "leftToRight" | "topLeftToBottomRight" | "bottomToTop" | "rightToLeft" | "bottomLeftToTopRight" | undefined;
|
|
904
|
+
decorations?: {
|
|
905
|
+
type: "glow" | "circle" | "dots";
|
|
906
|
+
color?: string | undefined;
|
|
907
|
+
x?: number | undefined;
|
|
908
|
+
y?: number | undefined;
|
|
909
|
+
size?: number | undefined;
|
|
910
|
+
spacing?: number | undefined;
|
|
911
|
+
opacity?: number | undefined;
|
|
912
|
+
}[] | undefined;
|
|
913
|
+
} | undefined;
|
|
914
|
+
}[];
|
|
915
|
+
subtitle?: {
|
|
916
|
+
color: string;
|
|
917
|
+
relativeSize: number;
|
|
918
|
+
text: string;
|
|
919
|
+
fontFamily?: string | undefined;
|
|
920
|
+
fontWeight?: "regular" | "medium" | "semibold" | "bold" | "heavy" | "black" | undefined;
|
|
921
|
+
shadow?: {
|
|
922
|
+
color?: string | undefined;
|
|
923
|
+
blur?: number | undefined;
|
|
924
|
+
offsetX?: number | undefined;
|
|
925
|
+
offsetY?: number | undefined;
|
|
926
|
+
} | undefined;
|
|
927
|
+
} | undefined;
|
|
928
|
+
}>;
|
|
929
|
+
type MockupConfig = z.infer<typeof mockupConfigSchema>;
|
|
930
|
+
/**
|
|
931
|
+
* Parse + validate an unknown value into a MockupConfig, throwing a readable
|
|
932
|
+
* error on failure. (Equivalent to Swift's `MockupConfig.load`.)
|
|
933
|
+
*/
|
|
934
|
+
declare function parseConfig(input: unknown): MockupConfig;
|
|
935
|
+
/**
|
|
936
|
+
* Cross-field validation: every screenshot must have a headline for every
|
|
937
|
+
* declared language. Mirrors the headline check in Swift `MockupConfig.validate`.
|
|
938
|
+
* (The screenshot-file-exists check is environment-specific and lives in node-render.)
|
|
939
|
+
* Returns a list of human-readable problems; empty means valid.
|
|
940
|
+
*/
|
|
941
|
+
declare function validateHeadlines(config: MockupConfig): string[];
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Minimal structural subset of the Canvas 2D API that the renderer needs.
|
|
945
|
+
*
|
|
946
|
+
* Both the browser's `CanvasRenderingContext2D` and `@napi-rs/canvas`'s
|
|
947
|
+
* `SKRSContext2D` satisfy this shape, so the same rendering code runs in both
|
|
948
|
+
* environments. Adapters pass their real context in (a small `as unknown as Ctx2D`
|
|
949
|
+
* cast at the boundary is expected — see node-render / the studio canvas hook).
|
|
950
|
+
*/
|
|
951
|
+
interface Gradient2D {
|
|
952
|
+
addColorStop(offset: number, color: string): void;
|
|
953
|
+
}
|
|
954
|
+
interface TextMetricsLike {
|
|
955
|
+
width: number;
|
|
956
|
+
actualBoundingBoxAscent?: number;
|
|
957
|
+
actualBoundingBoxDescent?: number;
|
|
958
|
+
fontBoundingBoxAscent?: number;
|
|
959
|
+
fontBoundingBoxDescent?: number;
|
|
960
|
+
}
|
|
961
|
+
interface Ctx2D {
|
|
962
|
+
fillStyle: unknown;
|
|
963
|
+
globalAlpha: number;
|
|
964
|
+
font: string;
|
|
965
|
+
textAlign: string;
|
|
966
|
+
textBaseline: string;
|
|
967
|
+
shadowColor: string;
|
|
968
|
+
shadowBlur: number;
|
|
969
|
+
shadowOffsetX: number;
|
|
970
|
+
shadowOffsetY: number;
|
|
971
|
+
save(): void;
|
|
972
|
+
restore(): void;
|
|
973
|
+
translate(x: number, y: number): void;
|
|
974
|
+
rotate(angle: number): void;
|
|
975
|
+
transform(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
|
976
|
+
beginPath(): void;
|
|
977
|
+
rect(x: number, y: number, w: number, h: number): void;
|
|
978
|
+
roundRect(x: number, y: number, w: number, h: number, radii?: number | number[]): void;
|
|
979
|
+
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number): void;
|
|
980
|
+
clip(): void;
|
|
981
|
+
fill(): void;
|
|
982
|
+
fillRect(x: number, y: number, w: number, h: number): void;
|
|
983
|
+
createLinearGradient(x0: number, y0: number, x1: number, y1: number): Gradient2D;
|
|
984
|
+
createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): Gradient2D;
|
|
985
|
+
drawImage(image: unknown, dx: number, dy: number, dw: number, dh: number): void;
|
|
986
|
+
measureText(text: string): TextMetricsLike;
|
|
987
|
+
fillText(text: string, x: number, y: number): void;
|
|
988
|
+
}
|
|
989
|
+
/** A decoded screenshot ready to be drawn, with its intrinsic pixel dimensions. */
|
|
990
|
+
interface ScreenshotImage {
|
|
991
|
+
/** Anything `ctx.drawImage` accepts (napi-rs Image, HTMLImageElement, ImageBitmap, canvas). */
|
|
992
|
+
source: unknown;
|
|
993
|
+
width: number;
|
|
994
|
+
height: number;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* Hex color parsing, ported from the Swift `ColorParsing.cgColor(from:)`.
|
|
999
|
+
*
|
|
1000
|
+
* Returns a CSS `rgba(...)` string (canvas-ready). Supports #RGB, #RRGGBB and
|
|
1001
|
+
* #RRGGBBAA. Matches the Swift behaviour of falling back to opaque black for
|
|
1002
|
+
* anything it can't parse, so output stays identical to the original tool.
|
|
1003
|
+
*/
|
|
1004
|
+
declare function parseHexColor(hex: string): string;
|
|
1005
|
+
/**
|
|
1006
|
+
* Like parseHexColor, but multiplies the parsed alpha by `alphaScale` (0..1).
|
|
1007
|
+
* Used for gradient fade-outs (e.g. a glow's outer stop at alphaScale 0).
|
|
1008
|
+
*/
|
|
1009
|
+
declare function parseHexColorWithAlpha(hex: string, alphaScale: number): string;
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Default font family. The Swift tool used the macOS system font (San Francisco);
|
|
1013
|
+
* for deterministic, cross-platform output we standardize on Inter and register
|
|
1014
|
+
* the same file in Node (see @appmockup/node-render) and load it via @font-face in
|
|
1015
|
+
* the web studio, so preview == export.
|
|
1016
|
+
*/
|
|
1017
|
+
declare const DEFAULT_FONT_FAMILY = "Inter";
|
|
1018
|
+
/** Broad-coverage fallback (Latin/Cyrillic/Arabic/CJK) appended after the primary family. */
|
|
1019
|
+
declare const FALLBACK_FONT_STACK = "\"Noto Sans\", \"Noto Sans Arabic\", \"Noto Sans KR\", sans-serif";
|
|
1020
|
+
/** Map the Swift Core Text weight names to CSS numeric weights. */
|
|
1021
|
+
declare function cssFontWeight(weight: FontWeightName): number;
|
|
1022
|
+
/** Build a CSS `font` shorthand string for `ctx.font`. */
|
|
1023
|
+
declare function cssFont(family: string | undefined, weight: FontWeightName, sizePx: number): string;
|
|
1024
|
+
|
|
1025
|
+
/** A sensible starter config for a new app — used by `appmockup init`, the MCP
|
|
1026
|
+
* `init_config` tool, and the web studio's "new project" action. */
|
|
1027
|
+
declare function createStarterConfig(appName: string): MockupConfig;
|
|
1028
|
+
/** Standard App Store / Play Store output sizes (marketing asset dimensions). */
|
|
1029
|
+
declare const STANDARD_OUTPUT_SIZES: {
|
|
1030
|
+
name: string;
|
|
1031
|
+
width: number;
|
|
1032
|
+
height: number;
|
|
1033
|
+
note: string;
|
|
1034
|
+
}[];
|
|
1035
|
+
|
|
1036
|
+
/**
|
|
1037
|
+
* Port of Swift `BackgroundRenderer`, extended with radial gradients, more
|
|
1038
|
+
* linear directions, and decorative shapes.
|
|
1039
|
+
*
|
|
1040
|
+
* Note on gradient directions: in Swift/CoreGraphics the y-axis points up, so its
|
|
1041
|
+
* start/end points read "inverted" vs canvas. Working it through, the direction
|
|
1042
|
+
* names map cleanly onto canvas top-left coordinates: topToBottom goes y=0→h, etc.
|
|
1043
|
+
* colors[0] sits at the start point; remaining colors are evenly distributed
|
|
1044
|
+
* (matching CGGradient with `locations: nil`).
|
|
1045
|
+
*/
|
|
1046
|
+
declare function drawBackground(ctx: Ctx2D, width: number, height: number, config: BackgroundConfig): void;
|
|
1047
|
+
|
|
1048
|
+
declare function drawDecorations(ctx: Ctx2D, width: number, height: number, decorations: DecorationConfig[] | undefined): void;
|
|
1049
|
+
|
|
1050
|
+
/** Axis-aligned device bounding box (before rotation) plus its center + rotation. */
|
|
1051
|
+
interface DeviceRect {
|
|
1052
|
+
x: number;
|
|
1053
|
+
y: number;
|
|
1054
|
+
width: number;
|
|
1055
|
+
height: number;
|
|
1056
|
+
centerX: number;
|
|
1057
|
+
centerY: number;
|
|
1058
|
+
rotationDeg: number;
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Compute the device frame's geometry on a canvas. Single source of truth shared by
|
|
1062
|
+
* the renderer and the studio's interactive overlay (hit-testing / handles).
|
|
1063
|
+
*
|
|
1064
|
+
* - Size: `screenRelativeWidth` × canvas width, with iPhone AR 2.167 / iPad 1.4.
|
|
1065
|
+
* - X: `horizontalOffset` × canvas width (left edge); undefined ⇒ horizontally centered.
|
|
1066
|
+
* - Y: `verticalOffset` × canvas height (top edge).
|
|
1067
|
+
* - Rotation: `rotation` degrees about the device center; undefined ⇒ 0.
|
|
1068
|
+
*/
|
|
1069
|
+
declare function deviceFrameRect(canvasWidth: number, canvasHeight: number, config: DeviceFrameConfig): DeviceRect;
|
|
1070
|
+
/**
|
|
1071
|
+
* Port of Swift `DeviceFrameRenderer`, extended with horizontal offset + rotation.
|
|
1072
|
+
*
|
|
1073
|
+
* Works in canvas top-left space. The device top is `verticalOffset * canvasHeight`,
|
|
1074
|
+
* the left is centered unless `horizontalOffset` is set. When `rotation` is set, the
|
|
1075
|
+
* whole device (bezel, screen, Dynamic Island, home indicator) is rotated about its
|
|
1076
|
+
* center. Corner radius and bezel width scale relative to a 400pt baseline width.
|
|
1077
|
+
*/
|
|
1078
|
+
declare function drawDeviceFrame(ctx: Ctx2D, screenshot: ScreenshotImage | null | undefined, canvasWidth: number, canvasHeight: number, config: DeviceFrameConfig): void;
|
|
1079
|
+
|
|
1080
|
+
interface TextResult {
|
|
1081
|
+
/** Canvas y-coordinate of the bottom of the rendered text block. */
|
|
1082
|
+
bottomY: number;
|
|
1083
|
+
}
|
|
1084
|
+
/** Port of Swift `TextRenderer.drawHeadline`. */
|
|
1085
|
+
declare function drawHeadline(ctx: Ctx2D, text: string, canvasWidth: number, canvasHeight: number, config: HeadlineConfig, topMarginFraction?: number): TextResult;
|
|
1086
|
+
/** Port of Swift `TextRenderer.drawSubtitle`. */
|
|
1087
|
+
declare function drawSubtitle(ctx: Ctx2D, text: string, canvasWidth: number, canvasHeight: number, config: SubtitleConfig, belowY: number): TextResult;
|
|
1088
|
+
|
|
1089
|
+
/** A fully-resolved, environment-agnostic description of one mockup to render. */
|
|
1090
|
+
interface RenderScene {
|
|
1091
|
+
width: number;
|
|
1092
|
+
height: number;
|
|
1093
|
+
background: BackgroundConfig;
|
|
1094
|
+
headlineText: string;
|
|
1095
|
+
headline: HeadlineConfig;
|
|
1096
|
+
subtitle?: SubtitleConfig;
|
|
1097
|
+
deviceFrame: DeviceFrameConfig;
|
|
1098
|
+
screenshot?: ScreenshotImage | null;
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Render a single mockup into the given context. Layer order matches Swift
|
|
1102
|
+
* `MockupRenderer.render`: background → headline → subtitle → device/screenshot
|
|
1103
|
+
* (the framed device is drawn last, on top).
|
|
1104
|
+
*/
|
|
1105
|
+
declare function renderMockup(ctx: Ctx2D, scene: RenderScene): void;
|
|
1106
|
+
/**
|
|
1107
|
+
* Resolve a config + screenshot entry + language + size + decoded image into a
|
|
1108
|
+
* RenderScene. Shared by the CLI, MCP and web studio so they stay in lock-step.
|
|
1109
|
+
*/
|
|
1110
|
+
declare function resolveScene(config: MockupConfig, entry: ScreenshotEntry, language: string, size: OutputSize, screenshot: ScreenshotImage | null | undefined): RenderScene;
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* A demo template = a complete sample project (styled background + frame, a
|
|
1114
|
+
* positioned/rotated device, and example screenshots + captions). Surface-agnostic:
|
|
1115
|
+
* the studio overlays its own bundled images per template id; MCP/CLI hand back the
|
|
1116
|
+
* config for the user to point at their own screenshots.
|
|
1117
|
+
*/
|
|
1118
|
+
interface Template {
|
|
1119
|
+
id: string;
|
|
1120
|
+
name: string;
|
|
1121
|
+
description: string;
|
|
1122
|
+
/** CSS background used for the picker swatch in the studio. */
|
|
1123
|
+
swatch: string;
|
|
1124
|
+
config: MockupConfig;
|
|
1125
|
+
}
|
|
1126
|
+
declare const TEMPLATES: Template[];
|
|
1127
|
+
/** Look up a template by id. */
|
|
1128
|
+
declare function getTemplate(id: string): Template | undefined;
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* An accent color theme: a harmonious palette applied over an existing config.
|
|
1132
|
+
* Themes recolor (background colors, text colors, bezel, decoration accents)
|
|
1133
|
+
* but never touch layout — device position/size/rotation, text sizes, gradient
|
|
1134
|
+
* type/direction, decoration geometry and shadows all stay as they are.
|
|
1135
|
+
*/
|
|
1136
|
+
interface AccentTheme {
|
|
1137
|
+
id: string;
|
|
1138
|
+
name: string;
|
|
1139
|
+
/** CSS background used for the picker chip in the studio. */
|
|
1140
|
+
swatch: string;
|
|
1141
|
+
/** Gradient stops; a solid background uses only the first entry. */
|
|
1142
|
+
backgroundColors: string[];
|
|
1143
|
+
headlineColor: string;
|
|
1144
|
+
subtitleColor: string;
|
|
1145
|
+
bezelColor: string;
|
|
1146
|
+
/** Applied to background decoration colors. */
|
|
1147
|
+
accent: string;
|
|
1148
|
+
}
|
|
1149
|
+
declare const THEMES: AccentTheme[];
|
|
1150
|
+
/** Look up a theme by id. */
|
|
1151
|
+
declare function getTheme(id: string): AccentTheme | undefined;
|
|
1152
|
+
/**
|
|
1153
|
+
* Apply a theme to a config: pure — returns a new config, never mutates the
|
|
1154
|
+
* input. Only colors change (background stops, decoration accents, headline,
|
|
1155
|
+
* subtitle if present, bezel, and any per-screenshot background overrides);
|
|
1156
|
+
* layout, sizes, gradient type/direction and shadows are untouched.
|
|
1157
|
+
*/
|
|
1158
|
+
declare function applyTheme(config: MockupConfig, theme: AccentTheme): MockupConfig;
|
|
1159
|
+
|
|
1160
|
+
export { type AccentTheme, type BackgroundConfig, type Ctx2D, DEFAULT_FONT_FAMILY, type DecorationConfig, type DeviceFrameConfig, type DeviceRect, FALLBACK_FONT_STACK, type FontWeightName, type Gradient2D, type GradientDirection, type HeadlineConfig, type MockupConfig, type OutputSize, type RenderScene, STANDARD_OUTPUT_SIZES, type ScreenshotEntry, type ScreenshotImage, type ShadowConfig, type SubtitleConfig, TEMPLATES, THEMES, type Template, type TextMetricsLike, type TextResult, applyTheme, backgroundSchema, createStarterConfig, cssFont, cssFontWeight, decorationSchema, deviceFrameRect, deviceFrameSchema, drawBackground, drawDecorations, drawDeviceFrame, drawHeadline, drawSubtitle, fontWeightSchema, getTemplate, getTheme, headlineSchema, mockupConfigSchema, outputSizeSchema, parseConfig, parseHexColor, parseHexColorWithAlpha, renderMockup, resolveScene, screenshotEntrySchema, shadowSchema, subtitleSchema, validateHeadlines };
|