@kubuild/schema 0.7.0 → 0.8.1
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 +24 -0
- package/dist/actions.d.ts +5 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/breakpoints.d.ts +35 -0
- package/dist/breakpoints.d.ts.map +1 -0
- package/dist/builtin-components.d.ts +17 -0
- package/dist/builtin-components.d.ts.map +1 -0
- package/dist/canonical-props.d.ts +39 -0
- package/dist/canonical-props.d.ts.map +1 -0
- package/dist/chunk-MT3M7D67.js +1041 -0
- package/dist/chunk-MT3M7D67.js.map +1 -0
- package/dist/chunk-PECTZDCI.js +1038 -0
- package/dist/chunk-PECTZDCI.js.map +1 -0
- package/dist/document.d.ts +21 -1
- package/dist/document.d.ts.map +1 -1
- package/dist/index.cjs +437 -126
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +316 -819
- package/dist/index.js.map +1 -1
- package/dist/json-schema.d.ts +74 -6
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/template.d.ts +6 -0
- package/dist/template.d.ts.map +1 -1
- package/dist/theme.d.ts +80 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/types.cjs +19 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.ts +331 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.cjs +715 -0
- package/dist/validate.cjs.map +1 -0
- package/dist/validate.d.ts +16 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +53 -0
- package/dist/validate.js.map +1 -0
- package/package.json +22 -2
package/dist/index.js
CHANGED
|
@@ -1,818 +1,161 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* Deduplication Event ID.
|
|
128
|
-
* If omitted, a unique ID is automatically generated so Meta/TikTok CAPI
|
|
129
|
-
* deduplicates cleanly with the browser pixel.
|
|
130
|
-
*/
|
|
131
|
-
eventId: z.string().optional(),
|
|
132
|
-
/**
|
|
133
|
-
* Event parameters/properties (e.g. currency, value, content_name, order_id).
|
|
134
|
-
* Supports runtime variable interpolation (e.g. {{ form.price }} or {{ variables.currency }}).
|
|
135
|
-
*/
|
|
136
|
-
params: z.record(z.string(), z.unknown()).optional().default({}),
|
|
137
|
-
/**
|
|
138
|
-
* User Data for advanced matching and server CAPI (e.g. email, phone, firstName, lastName).
|
|
139
|
-
* Supports runtime variable interpolation (e.g. {{ form.email }}).
|
|
140
|
-
*/
|
|
141
|
-
userData: z.record(z.string(), z.unknown()).optional().default({}),
|
|
142
|
-
/** Step-level active toggle */
|
|
143
|
-
enabled: z.boolean().optional().default(true)
|
|
144
|
-
});
|
|
145
|
-
var TRACKING_RELAY_PROTOCOL_VERSION = 1;
|
|
146
|
-
var ServerTrackingEventSchema = z.object({
|
|
147
|
-
eventName: z.string().min(1).max(256),
|
|
148
|
-
eventType: z.enum(["standard", "custom"]).optional(),
|
|
149
|
-
eventId: z.string().max(256).optional(),
|
|
150
|
-
/** Unix epoch seconds. */
|
|
151
|
-
eventTime: z.number().int().nonnegative().optional(),
|
|
152
|
-
eventSourceUrl: z.string().max(4096).optional(),
|
|
153
|
-
actionSource: z.enum(["website", "app", "system_generated"]).optional(),
|
|
154
|
-
params: z.record(z.string(), z.unknown()).optional(),
|
|
155
|
-
/** Raw (unhashed) user data; the relay hashes PII per provider spec before forwarding. */
|
|
156
|
-
userData: z.record(z.string(), z.unknown()).optional(),
|
|
157
|
-
customData: z.record(z.string(), z.unknown()).optional()
|
|
158
|
-
});
|
|
159
|
-
var TrackingRelayRequestSchema = z.object({
|
|
160
|
-
version: z.literal(TRACKING_RELAY_PROTOCOL_VERSION),
|
|
161
|
-
event: ServerTrackingEventSchema,
|
|
162
|
-
provider: TrackEventProviderSchema.optional().default("all"),
|
|
163
|
-
/** Optional hint only; the relay uses the credentialId from its trusted config. */
|
|
164
|
-
credentialId: z.string().max(256).optional(),
|
|
165
|
-
/** Host document/page id so the relay can look up the trusted tracking config. */
|
|
166
|
-
documentId: z.string().max(256).optional()
|
|
167
|
-
});
|
|
168
|
-
var TrackingRelayProviderResultSchema = z.object({
|
|
169
|
-
provider: z.string(),
|
|
170
|
-
success: z.boolean(),
|
|
171
|
-
status: z.number().int().optional(),
|
|
172
|
-
skipped: z.boolean().optional(),
|
|
173
|
-
reason: z.string().optional(),
|
|
174
|
-
error: z.string().optional()
|
|
175
|
-
});
|
|
176
|
-
var TrackingRelayErrorCodeSchema = z.enum([
|
|
177
|
-
"INVALID_REQUEST",
|
|
178
|
-
"UNSUPPORTED_VERSION",
|
|
179
|
-
"FORBIDDEN_ORIGIN",
|
|
180
|
-
"METHOD_NOT_ALLOWED",
|
|
181
|
-
"CONFIG_NOT_FOUND",
|
|
182
|
-
"INTERNAL_ERROR"
|
|
183
|
-
]);
|
|
184
|
-
var TrackingRelayResponseSchema = z.object({
|
|
185
|
-
version: z.literal(TRACKING_RELAY_PROTOCOL_VERSION),
|
|
186
|
-
success: z.boolean(),
|
|
187
|
-
eventId: z.string().optional(),
|
|
188
|
-
skipped: z.boolean().optional(),
|
|
189
|
-
reason: z.string().optional(),
|
|
190
|
-
results: z.record(z.string(), TrackingRelayProviderResultSchema).optional(),
|
|
191
|
-
error: z.object({
|
|
192
|
-
code: TrackingRelayErrorCodeSchema,
|
|
193
|
-
message: z.string()
|
|
194
|
-
}).optional()
|
|
195
|
-
});
|
|
196
|
-
function isTrackingConfig(value) {
|
|
197
|
-
return TrackingConfigSchema.safeParse(value).success;
|
|
198
|
-
}
|
|
199
|
-
function isTrackEventStepPayload(value) {
|
|
200
|
-
return TrackEventStepPayloadSchema.safeParse(value).success;
|
|
201
|
-
}
|
|
202
|
-
function isTrackingRelayRequest(value) {
|
|
203
|
-
return TrackingRelayRequestSchema.safeParse(value).success;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// src/actions.ts
|
|
207
|
-
var ActionTriggerTypeSchema = z2.enum([
|
|
208
|
-
"click",
|
|
209
|
-
"submit",
|
|
210
|
-
"change",
|
|
211
|
-
"blur",
|
|
212
|
-
"focus",
|
|
213
|
-
"load"
|
|
214
|
-
]);
|
|
215
|
-
var ActionTriggerSchema = ActionTriggerTypeSchema;
|
|
216
|
-
var ActionStepTypeSchema = z2.enum([
|
|
217
|
-
"api_request",
|
|
218
|
-
"navigate",
|
|
219
|
-
"set_state",
|
|
220
|
-
"reset_form",
|
|
221
|
-
"show_toast",
|
|
222
|
-
"open_modal",
|
|
223
|
-
"close_modal",
|
|
224
|
-
"toggle_modal",
|
|
225
|
-
"copy_clipboard",
|
|
226
|
-
"custom_event",
|
|
227
|
-
"track_event"
|
|
228
|
-
]);
|
|
229
|
-
var ConditionOperatorSchema = z2.enum([
|
|
230
|
-
"equals",
|
|
231
|
-
"not_equals",
|
|
232
|
-
"contains",
|
|
233
|
-
"not_contains",
|
|
234
|
-
"is_truthy",
|
|
235
|
-
"is_falsy",
|
|
236
|
-
"gt",
|
|
237
|
-
"gte",
|
|
238
|
-
"lt",
|
|
239
|
-
"lte",
|
|
240
|
-
"regex"
|
|
241
|
-
]);
|
|
242
|
-
var ActionStepConditionSchema = z2.object({
|
|
243
|
-
field: z2.string().min(1, "Condition field cannot be empty"),
|
|
244
|
-
operator: ConditionOperatorSchema,
|
|
245
|
-
value: z2.unknown().optional()
|
|
246
|
-
});
|
|
247
|
-
var DANGEROUS_URL_PATTERN = /(javascript:|vbscript:|data:text\/html)/i;
|
|
248
|
-
var DANGEROUS_SCRIPT_PATTERN = /<\s*script/i;
|
|
249
|
-
function isSafeActionUrl(url) {
|
|
250
|
-
if (!url || typeof url !== "string") return false;
|
|
251
|
-
const trimmed = url.trim();
|
|
252
|
-
if (DANGEROUS_URL_PATTERN.test(trimmed)) return false;
|
|
253
|
-
if (DANGEROUS_SCRIPT_PATTERN.test(trimmed)) return false;
|
|
254
|
-
return true;
|
|
255
|
-
}
|
|
256
|
-
var SafeUrlStringSchema = z2.string().min(1, "URL cannot be empty").refine(isSafeActionUrl, {
|
|
257
|
-
message: "URL contains disallowed or unsafe protocol/script pattern"
|
|
258
|
-
});
|
|
259
|
-
var SafeEventNameSchema = z2.string().min(1, "Event name cannot be empty").regex(/^[a-zA-Z0-9_\-:]+$/, {
|
|
260
|
-
message: "Event name must contain only alphanumeric characters, dashes, colons, or underscores"
|
|
261
|
-
});
|
|
262
|
-
var ApiRequestStepPayloadSchema = z2.object({
|
|
263
|
-
url: SafeUrlStringSchema,
|
|
264
|
-
method: z2.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).default("GET"),
|
|
265
|
-
headers: z2.record(z2.string(), z2.string()).optional(),
|
|
266
|
-
queryParams: z2.record(z2.string(), z2.union([z2.string(), z2.number(), z2.boolean()])).optional(),
|
|
267
|
-
body: z2.union([z2.string(), z2.record(z2.string(), z2.unknown()), z2.array(z2.unknown())]).optional(),
|
|
268
|
-
bodyFormat: z2.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
|
|
269
|
-
bodyType: z2.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
|
|
270
|
-
timeout: z2.number().positive("Timeout must be greater than 0 ms").optional(),
|
|
271
|
-
responseMapping: z2.record(z2.string(), z2.string()).optional()
|
|
272
|
-
});
|
|
273
|
-
var NavigateStepPayloadSchema = z2.object({
|
|
274
|
-
url: SafeUrlStringSchema,
|
|
275
|
-
target: z2.enum(["_self", "_blank", "_parent", "_top"]).optional().default("_self"),
|
|
276
|
-
replace: z2.boolean().optional(),
|
|
277
|
-
scroll: z2.boolean().optional(),
|
|
278
|
-
behavior: z2.enum(["smooth", "auto"]).optional()
|
|
279
|
-
});
|
|
280
|
-
var SetStateStepPayloadSchema = z2.object({
|
|
281
|
-
key: z2.string().min(1, "State key cannot be empty"),
|
|
282
|
-
value: z2.unknown(),
|
|
283
|
-
scope: z2.enum(["runtime", "document", "session", "local"]).optional().default("runtime")
|
|
284
|
-
});
|
|
285
|
-
var ResetFormStepPayloadSchema = z2.object({
|
|
286
|
-
formId: z2.string().optional()
|
|
287
|
-
});
|
|
288
|
-
var ShowToastStepPayloadSchema = z2.object({
|
|
289
|
-
message: z2.string().min(1, "Toast message cannot be empty"),
|
|
290
|
-
type: z2.enum(["success", "error", "warning", "info"]).optional().default("info"),
|
|
291
|
-
variant: z2.enum(["success", "error", "warning", "info"]).optional(),
|
|
292
|
-
title: z2.string().optional(),
|
|
293
|
-
duration: z2.number().nonnegative("Duration must be >= 0 ms").optional(),
|
|
294
|
-
position: z2.enum(["top-right", "top-left", "bottom-right", "bottom-left", "top-center", "bottom-center"]).optional()
|
|
295
|
-
});
|
|
296
|
-
var OpenModalStepPayloadSchema = z2.object({
|
|
297
|
-
modalId: z2.string().optional(),
|
|
298
|
-
modalNodeId: z2.string().optional(),
|
|
299
|
-
toggle: z2.boolean().optional()
|
|
300
|
-
}).refine((data) => Boolean(data.modalId || data.modalNodeId), {
|
|
301
|
-
message: "Modal ID or Modal Node ID cannot be empty"
|
|
302
|
-
});
|
|
303
|
-
var CloseModalStepPayloadSchema = z2.object({
|
|
304
|
-
modalId: z2.string().optional(),
|
|
305
|
-
modalNodeId: z2.string().optional()
|
|
306
|
-
});
|
|
307
|
-
var ToggleModalStepPayloadSchema = z2.object({
|
|
308
|
-
modalId: z2.string().optional(),
|
|
309
|
-
modalNodeId: z2.string().optional(),
|
|
310
|
-
targetNodeId: z2.string().optional(),
|
|
311
|
-
nodeId: z2.string().optional()
|
|
312
|
-
}).refine(
|
|
313
|
-
(data) => [data.modalId, data.modalNodeId, data.targetNodeId, data.nodeId].some(
|
|
314
|
-
(id) => typeof id === "string" && id.trim().length > 0
|
|
315
|
-
),
|
|
316
|
-
{
|
|
317
|
-
message: "Modal ID or Modal Node ID cannot be empty"
|
|
318
|
-
}
|
|
319
|
-
);
|
|
320
|
-
var CopyClipboardStepPayloadSchema = z2.object({
|
|
321
|
-
text: z2.string().optional(),
|
|
322
|
-
value: z2.unknown().optional(),
|
|
323
|
-
notify: z2.boolean().optional(),
|
|
324
|
-
toastMessage: z2.string().optional()
|
|
325
|
-
});
|
|
326
|
-
var CustomEventStepPayloadSchema = z2.object({
|
|
327
|
-
eventName: SafeEventNameSchema,
|
|
328
|
-
detail: z2.record(z2.string(), z2.unknown()).optional(),
|
|
329
|
-
bubbles: z2.boolean().optional().default(true),
|
|
330
|
-
cancelable: z2.boolean().optional().default(true)
|
|
331
|
-
});
|
|
332
|
-
var StepPayloadSchemas = {
|
|
333
|
-
api_request: ApiRequestStepPayloadSchema,
|
|
334
|
-
navigate: NavigateStepPayloadSchema,
|
|
335
|
-
set_state: SetStateStepPayloadSchema,
|
|
336
|
-
reset_form: ResetFormStepPayloadSchema,
|
|
337
|
-
show_toast: ShowToastStepPayloadSchema,
|
|
338
|
-
open_modal: OpenModalStepPayloadSchema,
|
|
339
|
-
close_modal: CloseModalStepPayloadSchema,
|
|
340
|
-
toggle_modal: ToggleModalStepPayloadSchema,
|
|
341
|
-
copy_clipboard: CopyClipboardStepPayloadSchema,
|
|
342
|
-
custom_event: CustomEventStepPayloadSchema,
|
|
343
|
-
track_event: TrackEventStepPayloadSchema
|
|
344
|
-
};
|
|
345
|
-
var ActionStepSchema = z2.lazy(
|
|
346
|
-
() => z2.object({
|
|
347
|
-
id: z2.string().min(1, "Step ID cannot be empty"),
|
|
348
|
-
type: ActionStepTypeSchema,
|
|
349
|
-
label: z2.string().optional(),
|
|
350
|
-
payload: z2.record(z2.string(), z2.unknown()).optional().default({}),
|
|
351
|
-
condition: ActionStepConditionSchema.optional(),
|
|
352
|
-
timeout: z2.number().positive().optional(),
|
|
353
|
-
continueOnError: z2.boolean().optional(),
|
|
354
|
-
onSuccess: z2.array(ActionStepSchema).optional(),
|
|
355
|
-
onError: z2.array(ActionStepSchema).optional()
|
|
356
|
-
})
|
|
357
|
-
);
|
|
358
|
-
var ActionPipelineSchema = z2.object({
|
|
359
|
-
id: z2.string().min(1, "Pipeline ID cannot be empty"),
|
|
360
|
-
trigger: ActionTriggerTypeSchema,
|
|
361
|
-
label: z2.string().optional(),
|
|
362
|
-
debounceMs: z2.number().nonnegative("Debounce ms must be >= 0").optional(),
|
|
363
|
-
preventDuplicate: z2.boolean().optional(),
|
|
364
|
-
enabled: z2.boolean().optional().default(true),
|
|
365
|
-
steps: z2.array(ActionStepSchema).min(1, "Action pipeline must contain at least one step")
|
|
366
|
-
});
|
|
367
|
-
function isActionTriggerType(value) {
|
|
368
|
-
return ActionTriggerTypeSchema.safeParse(value).success;
|
|
369
|
-
}
|
|
370
|
-
function isActionStepType(value) {
|
|
371
|
-
return ActionStepTypeSchema.safeParse(value).success;
|
|
372
|
-
}
|
|
373
|
-
function isConditionOperator(value) {
|
|
374
|
-
return ConditionOperatorSchema.safeParse(value).success;
|
|
375
|
-
}
|
|
376
|
-
function isActionStepCondition(value) {
|
|
377
|
-
return ActionStepConditionSchema.safeParse(value).success;
|
|
378
|
-
}
|
|
379
|
-
function isActionStep(value) {
|
|
380
|
-
return ActionStepSchema.safeParse(value).success;
|
|
381
|
-
}
|
|
382
|
-
function isActionPipeline(value) {
|
|
383
|
-
return ActionPipelineSchema.safeParse(value).success;
|
|
384
|
-
}
|
|
385
|
-
function validateActionStepPayload(type, payload) {
|
|
386
|
-
const schema = StepPayloadSchemas[type];
|
|
387
|
-
if (!schema) {
|
|
388
|
-
return {
|
|
389
|
-
success: false,
|
|
390
|
-
error: new z2.ZodError([
|
|
391
|
-
{
|
|
392
|
-
code: z2.ZodIssueCode.custom,
|
|
393
|
-
message: `Unknown step type: ${type}`,
|
|
394
|
-
path: ["type"]
|
|
395
|
-
}
|
|
396
|
-
])
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
const result = schema.safeParse(payload);
|
|
400
|
-
if (result.success) {
|
|
401
|
-
return { success: true, data: result.data };
|
|
402
|
-
}
|
|
403
|
-
return { success: false, error: result.error };
|
|
404
|
-
}
|
|
405
|
-
function sanitizeActionUrl(url, fallback = "") {
|
|
406
|
-
if (typeof url !== "string") return fallback;
|
|
407
|
-
const trimmed = url.trim();
|
|
408
|
-
if (!isSafeActionUrl(trimmed)) {
|
|
409
|
-
return fallback;
|
|
410
|
-
}
|
|
411
|
-
return trimmed;
|
|
412
|
-
}
|
|
413
|
-
function sanitizeActionString(value, fallback = "") {
|
|
414
|
-
if (typeof value !== "string") return fallback;
|
|
415
|
-
if (DANGEROUS_SCRIPT_PATTERN.test(value)) {
|
|
416
|
-
return value.replace(/<\s*script[^>]*>[\s\S]*?<\s*\/\s*script\s*>/gi, "").replace(/<\s*script[^>]*>/gi, "");
|
|
417
|
-
}
|
|
418
|
-
return value;
|
|
419
|
-
}
|
|
420
|
-
function sanitizeActionValue(value) {
|
|
421
|
-
if (value === null || value === void 0) return value;
|
|
422
|
-
if (typeof value === "string") {
|
|
423
|
-
const trimmed = value.trim();
|
|
424
|
-
if (DANGEROUS_URL_PATTERN.test(trimmed)) {
|
|
425
|
-
return "";
|
|
426
|
-
}
|
|
427
|
-
return sanitizeActionString(value);
|
|
428
|
-
}
|
|
429
|
-
if (Array.isArray(value)) {
|
|
430
|
-
return value.map((item) => sanitizeActionValue(item));
|
|
431
|
-
}
|
|
432
|
-
if (typeof value === "object") {
|
|
433
|
-
const result = {};
|
|
434
|
-
for (const [k, v] of Object.entries(value)) {
|
|
435
|
-
if (/^(url|href|src|endpoint|targetUrl)$/i.test(k) && typeof v === "string") {
|
|
436
|
-
result[k] = sanitizeActionUrl(v);
|
|
437
|
-
} else {
|
|
438
|
-
result[k] = sanitizeActionValue(v);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return result;
|
|
442
|
-
}
|
|
443
|
-
return value;
|
|
444
|
-
}
|
|
445
|
-
function sanitizeActionPayload(payload) {
|
|
446
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
447
|
-
return {};
|
|
448
|
-
}
|
|
449
|
-
return sanitizeActionValue(payload);
|
|
450
|
-
}
|
|
451
|
-
function sanitizeActionStep(step) {
|
|
452
|
-
const sanitized = {
|
|
453
|
-
...step,
|
|
454
|
-
label: step.label ? sanitizeActionString(step.label) : step.label,
|
|
455
|
-
payload: sanitizeActionPayload(step.payload)
|
|
456
|
-
};
|
|
457
|
-
if (step.condition && step.condition.value !== void 0) {
|
|
458
|
-
sanitized.condition = {
|
|
459
|
-
...step.condition,
|
|
460
|
-
value: sanitizeActionValue(step.condition.value)
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
if (step.onSuccess && Array.isArray(step.onSuccess)) {
|
|
464
|
-
sanitized.onSuccess = step.onSuccess.map((s) => sanitizeActionStep(s));
|
|
465
|
-
}
|
|
466
|
-
if (step.onError && Array.isArray(step.onError)) {
|
|
467
|
-
sanitized.onError = step.onError.map((s) => sanitizeActionStep(s));
|
|
468
|
-
}
|
|
469
|
-
return sanitized;
|
|
470
|
-
}
|
|
471
|
-
function sanitizeActionPipeline(pipeline) {
|
|
472
|
-
return {
|
|
473
|
-
...pipeline,
|
|
474
|
-
label: pipeline.label ? sanitizeActionString(pipeline.label) : pipeline.label,
|
|
475
|
-
steps: Array.isArray(pipeline.steps) ? pipeline.steps.map((s) => sanitizeActionStep(s)) : []
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// src/form.ts
|
|
480
|
-
import { z as z3 } from "zod";
|
|
481
|
-
var ValidationRuleTypeSchema = z3.enum([
|
|
482
|
-
"required",
|
|
483
|
-
"email",
|
|
484
|
-
"url",
|
|
485
|
-
"min_length",
|
|
486
|
-
"max_length",
|
|
487
|
-
"numeric_min",
|
|
488
|
-
"numeric_max",
|
|
489
|
-
"pattern",
|
|
490
|
-
"match_field",
|
|
491
|
-
"custom_regex"
|
|
492
|
-
]);
|
|
493
|
-
var ValidateOnEventSchema = z3.enum(["blur", "change", "submit"]);
|
|
494
|
-
var ValidationRuleSchema = z3.object({
|
|
495
|
-
type: ValidationRuleTypeSchema,
|
|
496
|
-
value: z3.unknown().optional(),
|
|
497
|
-
message: z3.string().min(1, "Validation error message cannot be empty")
|
|
498
|
-
});
|
|
499
|
-
var FormFieldBindingSchema = z3.object({
|
|
500
|
-
name: z3.string().min(1, "Field name cannot be empty"),
|
|
501
|
-
label: z3.string().optional(),
|
|
502
|
-
defaultValue: z3.unknown().optional(),
|
|
503
|
-
rules: z3.array(ValidationRuleSchema).optional().default([]),
|
|
504
|
-
validateOn: ValidateOnEventSchema.optional().default("blur"),
|
|
505
|
-
transform: z3.enum(["trim", "lowercase", "uppercase", "number"]).optional(),
|
|
506
|
-
disabled: z3.boolean().optional(),
|
|
507
|
-
required: z3.boolean().optional()
|
|
508
|
-
});
|
|
509
|
-
var FormConfigSchema = z3.object({
|
|
510
|
-
formId: z3.string().min(1, "Form ID cannot be empty"),
|
|
511
|
-
resetOnSubmit: z3.boolean().optional().default(false),
|
|
512
|
-
scrollToFirstError: z3.boolean().optional().default(true),
|
|
513
|
-
validateOn: ValidateOnEventSchema.optional().default("blur"),
|
|
514
|
-
initialValues: z3.record(z3.string(), z3.unknown()).optional(),
|
|
515
|
-
rules: z3.array(ValidationRuleSchema).optional()
|
|
516
|
-
});
|
|
517
|
-
function isValidationRuleType(value) {
|
|
518
|
-
return ValidationRuleTypeSchema.safeParse(value).success;
|
|
519
|
-
}
|
|
520
|
-
function isValidationRule(value) {
|
|
521
|
-
return ValidationRuleSchema.safeParse(value).success;
|
|
522
|
-
}
|
|
523
|
-
function isValidateOnEvent(value) {
|
|
524
|
-
return ValidateOnEventSchema.safeParse(value).success;
|
|
525
|
-
}
|
|
526
|
-
function isFormFieldBinding(value) {
|
|
527
|
-
return FormFieldBindingSchema.safeParse(value).success;
|
|
528
|
-
}
|
|
529
|
-
function isFormConfig(value) {
|
|
530
|
-
return FormConfigSchema.safeParse(value).success;
|
|
531
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
ARTBOARD_REFERENCE_NODE_TYPE,
|
|
3
|
+
ActionBindingSchema,
|
|
4
|
+
ActionPipelineSchema,
|
|
5
|
+
ActionStepConditionSchema,
|
|
6
|
+
ActionStepSchema,
|
|
7
|
+
ActionStepTypeSchema,
|
|
8
|
+
ActionTriggerSchema,
|
|
9
|
+
ActionTriggerTypeSchema,
|
|
10
|
+
AnimationConfigSchema,
|
|
11
|
+
ApiRequestStepPayloadSchema,
|
|
12
|
+
ArtboardSchema,
|
|
13
|
+
ArtboardTypeSchema,
|
|
14
|
+
AssetReferenceSchema,
|
|
15
|
+
CURRENT_PROJECT_SCHEMA_VERSION,
|
|
16
|
+
CURRENT_SCHEMA_VERSION,
|
|
17
|
+
CloseModalStepPayloadSchema,
|
|
18
|
+
ConditionOperatorSchema,
|
|
19
|
+
CopyClipboardStepPayloadSchema,
|
|
20
|
+
CustomEventStepPayloadSchema,
|
|
21
|
+
CustomTrackingProviderConfigSchema,
|
|
22
|
+
CustomTrackingSecretsSchema,
|
|
23
|
+
DEFAULT_ANIMATION_CONFIG,
|
|
24
|
+
DocumentMetadataSchema,
|
|
25
|
+
FormConfigSchema,
|
|
26
|
+
FormFieldBindingSchema,
|
|
27
|
+
GoogleTrackingProviderConfigSchema,
|
|
28
|
+
GoogleTrackingSecretsSchema,
|
|
29
|
+
GtmTrackingProviderConfigSchema,
|
|
30
|
+
LEGACY_TRACKING_SECRET_KEYS,
|
|
31
|
+
ManifestAssetItemSchema,
|
|
32
|
+
ManifestSchema,
|
|
33
|
+
MetaTrackingProviderConfigSchema,
|
|
34
|
+
MetaTrackingSecretsSchema,
|
|
35
|
+
NavigateStepPayloadSchema,
|
|
36
|
+
NodeSchema,
|
|
37
|
+
OpenModalStepPayloadSchema,
|
|
38
|
+
PROJECT_SCHEMA_NAME,
|
|
39
|
+
PageDocumentSchema,
|
|
40
|
+
ProjectDocumentSchema,
|
|
41
|
+
PseudoStateStylesSchema,
|
|
42
|
+
ResetFormStepPayloadSchema,
|
|
43
|
+
ResponsiveStylesSchema,
|
|
44
|
+
RootPageNodeSchema,
|
|
45
|
+
SCHEMA_NAME,
|
|
46
|
+
SafeThumbnailObjectSchema,
|
|
47
|
+
SafeThumbnailSchema,
|
|
48
|
+
SafeThumbnailUrlSchema,
|
|
49
|
+
ServerTrackingEventSchema,
|
|
50
|
+
SetStateStepPayloadSchema,
|
|
51
|
+
ShowToastStepPayloadSchema,
|
|
52
|
+
StandardTrackingEventSchema,
|
|
53
|
+
StepPayloadSchemas,
|
|
54
|
+
StyleDefinitionSchema,
|
|
55
|
+
StyleValueSchema,
|
|
56
|
+
THEME_TOKEN_CSS_PREFIX,
|
|
57
|
+
THEME_TOKEN_GROUPS,
|
|
58
|
+
TRACKING_RELAY_PROTOCOL_VERSION,
|
|
59
|
+
TemplatePackageRefSchema,
|
|
60
|
+
TemplateRecordSchema,
|
|
61
|
+
TemplateRequirementsSchema,
|
|
62
|
+
ThemeSchema,
|
|
63
|
+
ThemeTokenKeySchema,
|
|
64
|
+
ThemeTokenMapSchema,
|
|
65
|
+
ThemeTokenValueSchema,
|
|
66
|
+
TikTokTrackingProviderConfigSchema,
|
|
67
|
+
TikTokTrackingSecretsSchema,
|
|
68
|
+
ToggleModalStepPayloadSchema,
|
|
69
|
+
TrackEventProviderSchema,
|
|
70
|
+
TrackEventStepPayloadSchema,
|
|
71
|
+
TrackingConfigSchema,
|
|
72
|
+
TrackingDeliverySchema,
|
|
73
|
+
TrackingProviderTypeSchema,
|
|
74
|
+
TrackingRelayErrorCodeSchema,
|
|
75
|
+
TrackingRelayProviderResultSchema,
|
|
76
|
+
TrackingRelayRequestSchema,
|
|
77
|
+
TrackingRelayResponseSchema,
|
|
78
|
+
ValidateOnEventSchema,
|
|
79
|
+
ValidationRuleSchema,
|
|
80
|
+
ValidationRuleTypeSchema,
|
|
81
|
+
VariableBindingSchema,
|
|
82
|
+
collectNodeIds,
|
|
83
|
+
generateDeterministicNodeId,
|
|
84
|
+
isActionBinding,
|
|
85
|
+
isActionPipeline,
|
|
86
|
+
isActionStep,
|
|
87
|
+
isActionStepCondition,
|
|
88
|
+
isActionStepType,
|
|
89
|
+
isActionTriggerType,
|
|
90
|
+
isAnimationConfig,
|
|
91
|
+
isArtboardReferenceNode,
|
|
92
|
+
isAssetReference,
|
|
93
|
+
isConditionOperator,
|
|
94
|
+
isFormConfig,
|
|
95
|
+
isFormFieldBinding,
|
|
96
|
+
isManifest,
|
|
97
|
+
isProjectDocument,
|
|
98
|
+
isSafeActionUrl,
|
|
99
|
+
isSafeThemeTokenKey,
|
|
100
|
+
isSafeThemeTokenValue,
|
|
101
|
+
isSafeThumbnail,
|
|
102
|
+
isSafeThumbnailUrl,
|
|
103
|
+
isTemplateRecord,
|
|
104
|
+
isTheme,
|
|
105
|
+
isTrackEventStepPayload,
|
|
106
|
+
isTrackingConfig,
|
|
107
|
+
isTrackingRelayRequest,
|
|
108
|
+
isValidateOnEvent,
|
|
109
|
+
isValidationRule,
|
|
110
|
+
isValidationRuleType,
|
|
111
|
+
isVariableBinding,
|
|
112
|
+
looksLikeProjectDocument,
|
|
113
|
+
mergeThemes,
|
|
114
|
+
parseThemeTokenRef,
|
|
115
|
+
sanitizeActionPayload,
|
|
116
|
+
sanitizeActionPipeline,
|
|
117
|
+
sanitizeActionStep,
|
|
118
|
+
sanitizeActionString,
|
|
119
|
+
sanitizeActionUrl,
|
|
120
|
+
sanitizeActionValue,
|
|
121
|
+
themeToCssVariables,
|
|
122
|
+
themeTokenCssVarName,
|
|
123
|
+
themeTokenRef,
|
|
124
|
+
validateActionStepPayload,
|
|
125
|
+
validateNodeIdUniqueness
|
|
126
|
+
} from "./chunk-MT3M7D67.js";
|
|
532
127
|
|
|
533
|
-
// src/
|
|
534
|
-
var
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
assetId: z4.string().min(1, "Asset ID cannot be empty"),
|
|
539
|
-
filename: z4.string().optional(),
|
|
540
|
-
mimeType: z4.string().optional(),
|
|
541
|
-
fallbackUrl: z4.string().url().optional()
|
|
542
|
-
});
|
|
543
|
-
var VariableBindingSchema = z4.object({
|
|
544
|
-
type: z4.literal("variable"),
|
|
545
|
-
key: z4.string().min(1, "Variable key cannot be empty"),
|
|
546
|
-
fallback: z4.unknown().optional()
|
|
128
|
+
// src/breakpoints.ts
|
|
129
|
+
var BREAKPOINTS = Object.freeze({
|
|
130
|
+
mobile: Object.freeze({ minWidth: 0, maxWidth: 767 }),
|
|
131
|
+
tablet: Object.freeze({ minWidth: 768, maxWidth: 1023 }),
|
|
132
|
+
desktop: Object.freeze({ minWidth: 1024, maxWidth: null })
|
|
547
133
|
});
|
|
548
|
-
var
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
var DANGEROUS_STYLE_VALUE_PATTERN = /javascript:|expression\(|@import|<script|vbscript:|data:text\/html/i;
|
|
553
|
-
var StyleValueSchema = z4.union([
|
|
554
|
-
z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
|
|
555
|
-
message: "Style value contains a disallowed or unsafe pattern"
|
|
556
|
-
}),
|
|
557
|
-
z4.number(),
|
|
558
|
-
z4.boolean(),
|
|
559
|
-
z4.null(),
|
|
560
|
-
z4.undefined()
|
|
134
|
+
var BREAKPOINT_ORDER = Object.freeze([
|
|
135
|
+
"desktop",
|
|
136
|
+
"tablet",
|
|
137
|
+
"mobile"
|
|
561
138
|
]);
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
var ResponsiveStylesSchema = z4.object({
|
|
565
|
-
base: StyleDefinitionSchema.optional(),
|
|
566
|
-
desktop: StyleDefinitionSchema.optional(),
|
|
567
|
-
tablet: StyleDefinitionSchema.optional(),
|
|
568
|
-
mobile: StyleDefinitionSchema.optional(),
|
|
569
|
-
states: PseudoStateStylesSchema.optional()
|
|
570
|
-
}).passthrough().default({});
|
|
571
|
-
var AnimationConfigSchema = z4.object({
|
|
572
|
-
type: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
|
|
573
|
-
message: "Animation type contains a disallowed or unsafe pattern"
|
|
574
|
-
}).optional().default("none"),
|
|
575
|
-
duration: z4.number().min(0, "Duration must be non-negative").optional().default(600),
|
|
576
|
-
delay: z4.number().min(0, "Delay must be non-negative").optional().default(0),
|
|
577
|
-
easing: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
|
|
578
|
-
message: "Animation easing contains a disallowed or unsafe pattern"
|
|
579
|
-
}).optional().default("ease-out"),
|
|
580
|
-
once: z4.boolean().optional().default(true),
|
|
581
|
-
hoverEffect: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
|
|
582
|
-
message: "Hover effect contains a disallowed or unsafe pattern"
|
|
583
|
-
}).optional().default("none"),
|
|
584
|
-
loopEffect: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
|
|
585
|
-
message: "Loop effect contains a disallowed or unsafe pattern"
|
|
586
|
-
}).optional().default("none")
|
|
587
|
-
});
|
|
588
|
-
var DEFAULT_ANIMATION_CONFIG = {
|
|
589
|
-
type: "none",
|
|
590
|
-
duration: 600,
|
|
591
|
-
delay: 0,
|
|
592
|
-
easing: "ease-out",
|
|
593
|
-
once: true,
|
|
594
|
-
hoverEffect: "none",
|
|
595
|
-
loopEffect: "none"
|
|
596
|
-
};
|
|
597
|
-
var NodeSchema = z4.lazy(
|
|
598
|
-
() => z4.object({
|
|
599
|
-
id: z4.string().min(1, "Node ID must be a non-empty string"),
|
|
600
|
-
type: z4.string().min(1, "Node type must be a non-empty string"),
|
|
601
|
-
props: z4.record(z4.string(), z4.unknown()).optional().default({}),
|
|
602
|
-
styles: ResponsiveStylesSchema.optional().default({}),
|
|
603
|
-
animation: AnimationConfigSchema.optional(),
|
|
604
|
-
actions: z4.array(ActionPipelineSchema).optional(),
|
|
605
|
-
formConfig: FormConfigSchema.optional(),
|
|
606
|
-
children: z4.array(NodeSchema).optional().default([])
|
|
607
|
-
})
|
|
608
|
-
);
|
|
609
|
-
var RootPageNodeSchema = NodeSchema.refine(
|
|
610
|
-
(node) => node.type === "page",
|
|
611
|
-
{
|
|
612
|
-
message: 'Root node must have type "page"',
|
|
613
|
-
path: ["type"]
|
|
614
|
-
}
|
|
615
|
-
);
|
|
616
|
-
var DocumentMetadataSchema = z4.object({
|
|
617
|
-
title: z4.string().min(1, "Title is required").default("Untitled Page"),
|
|
618
|
-
description: z4.string().optional().default(""),
|
|
619
|
-
author: z4.string().optional().default(""),
|
|
620
|
-
createdAt: z4.string().optional(),
|
|
621
|
-
updatedAt: z4.string().optional(),
|
|
622
|
-
tags: z4.array(z4.string()).optional().default([]),
|
|
623
|
-
category: z4.string().optional().default("general"),
|
|
624
|
-
version: z4.string().optional().default("1.0.0"),
|
|
625
|
-
custom: z4.record(z4.string(), z4.unknown()).optional(),
|
|
626
|
-
tracking: TrackingConfigSchema.optional()
|
|
627
|
-
});
|
|
628
|
-
var PageDocumentSchema = z4.object({
|
|
629
|
-
schema: z4.literal(SCHEMA_NAME),
|
|
630
|
-
version: z4.string().min(1, "Schema version is required").default(CURRENT_SCHEMA_VERSION),
|
|
631
|
-
metadata: DocumentMetadataSchema.optional(),
|
|
632
|
-
tracking: TrackingConfigSchema.optional(),
|
|
633
|
-
document: RootPageNodeSchema
|
|
634
|
-
});
|
|
635
|
-
var PROJECT_SCHEMA_NAME = "stora.project";
|
|
636
|
-
var CURRENT_PROJECT_SCHEMA_VERSION = "1.0.0";
|
|
637
|
-
var ARTBOARD_REFERENCE_NODE_TYPE = "artboard-reference";
|
|
638
|
-
var ArtboardTypeSchema = z4.enum(["page", "component"]);
|
|
639
|
-
var ArtboardSchema = z4.object({
|
|
640
|
-
id: z4.string().min(1, "Artboard ID is required"),
|
|
641
|
-
name: z4.string().min(1, "Artboard name is required"),
|
|
642
|
-
artboardType: ArtboardTypeSchema,
|
|
643
|
-
/** Route for page artboards (e.g. "/about"). */
|
|
644
|
-
slug: z4.string().optional(),
|
|
645
|
-
/**
|
|
646
|
-
* For component artboards: the id that `open_modal` / `close_modal` actions target.
|
|
647
|
-
* Mirrors the detached node's own `props.modalId` so ModalManager keeps working unchanged.
|
|
648
|
-
*/
|
|
649
|
-
triggerId: z4.string().optional(),
|
|
650
|
-
/**
|
|
651
|
-
* Viewport/breakpoint this artboard is currently authored at. Declared inline
|
|
652
|
-
* (rather than imported) because viewport is otherwise an editor/renderer concept.
|
|
653
|
-
*/
|
|
654
|
-
viewport: z4.enum(["desktop", "tablet", "mobile"]).optional(),
|
|
655
|
-
/** Persisted artboard width in px, matching the canvas ViewportResizer's `width`. */
|
|
656
|
-
width: z4.number().positive().optional(),
|
|
657
|
-
/**
|
|
658
|
-
* Free position on the builder's infinite canvas, in unscaled canvas px. Absent means
|
|
659
|
-
* "not placed yet" — the canvas then falls back to laying the artboard out in a row.
|
|
660
|
-
*/
|
|
661
|
-
position: z4.object({
|
|
662
|
-
x: z4.number(),
|
|
663
|
-
y: z4.number()
|
|
664
|
-
}).optional(),
|
|
665
|
-
document: PageDocumentSchema
|
|
666
|
-
});
|
|
667
|
-
var ProjectDocumentSchema = z4.object({
|
|
668
|
-
schema: z4.literal(PROJECT_SCHEMA_NAME),
|
|
669
|
-
version: z4.string().min(1, "Schema version is required").default(CURRENT_PROJECT_SCHEMA_VERSION),
|
|
670
|
-
metadata: DocumentMetadataSchema.optional(),
|
|
671
|
-
tracking: TrackingConfigSchema.optional(),
|
|
672
|
-
artboards: z4.array(ArtboardSchema).min(1, "A project needs at least one artboard"),
|
|
673
|
-
activeArtboardId: z4.string().optional()
|
|
674
|
-
});
|
|
675
|
-
function isAssetReference(value) {
|
|
676
|
-
return AssetReferenceSchema.safeParse(value).success;
|
|
677
|
-
}
|
|
678
|
-
function isVariableBinding(value) {
|
|
679
|
-
return VariableBindingSchema.safeParse(value).success;
|
|
680
|
-
}
|
|
681
|
-
function isActionBinding(value) {
|
|
682
|
-
return ActionBindingSchema.safeParse(value).success;
|
|
683
|
-
}
|
|
684
|
-
function isAnimationConfig(value) {
|
|
685
|
-
return AnimationConfigSchema.safeParse(value).success;
|
|
686
|
-
}
|
|
687
|
-
function isProjectDocument(value) {
|
|
688
|
-
return ProjectDocumentSchema.safeParse(value).success;
|
|
689
|
-
}
|
|
690
|
-
function looksLikeProjectDocument(value) {
|
|
691
|
-
if (typeof value !== "object" || value === null) return false;
|
|
692
|
-
const candidate = value;
|
|
693
|
-
return candidate.schema === PROJECT_SCHEMA_NAME || Array.isArray(candidate.artboards);
|
|
694
|
-
}
|
|
695
|
-
function isArtboardReferenceNode(node) {
|
|
696
|
-
return node.type === ARTBOARD_REFERENCE_NODE_TYPE;
|
|
697
|
-
}
|
|
698
|
-
function generateDeterministicNodeId(prefix, indexOrKey) {
|
|
699
|
-
const cleanPrefix = prefix.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
|
|
700
|
-
return `${cleanPrefix}_${indexOrKey}`;
|
|
701
|
-
}
|
|
702
|
-
function collectNodeIds(node) {
|
|
703
|
-
const ids = [node.id];
|
|
704
|
-
if (node.children && Array.isArray(node.children)) {
|
|
705
|
-
for (const child of node.children) {
|
|
706
|
-
ids.push(...collectNodeIds(child));
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
return ids;
|
|
710
|
-
}
|
|
711
|
-
function validateNodeIdUniqueness(node) {
|
|
712
|
-
const allIds = collectNodeIds(node);
|
|
713
|
-
const seen = /* @__PURE__ */ new Set();
|
|
714
|
-
const duplicates = /* @__PURE__ */ new Set();
|
|
715
|
-
for (const id of allIds) {
|
|
716
|
-
if (seen.has(id)) {
|
|
717
|
-
duplicates.add(id);
|
|
718
|
-
} else {
|
|
719
|
-
seen.add(id);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
return {
|
|
723
|
-
valid: duplicates.size === 0,
|
|
724
|
-
duplicateIds: Array.from(duplicates)
|
|
725
|
-
};
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
// src/manifest.ts
|
|
729
|
-
import { z as z5 } from "zod";
|
|
730
|
-
var ManifestAssetItemSchema = z5.object({
|
|
731
|
-
id: z5.string().min(1, "Asset ID cannot be empty"),
|
|
732
|
-
path: z5.string().min(1, "Asset archive path cannot be empty"),
|
|
733
|
-
mimeType: z5.string().min(1, "MIME type cannot be empty"),
|
|
734
|
-
size: z5.number().nonnegative("Asset size must be non-negative"),
|
|
735
|
-
checksum: z5.string().optional()
|
|
736
|
-
});
|
|
737
|
-
var ManifestSchema = z5.object({
|
|
738
|
-
schema: z5.literal(SCHEMA_NAME).default(SCHEMA_NAME),
|
|
739
|
-
schemaVersion: z5.string().min(1, "Schema version cannot be empty").default("1.0.0"),
|
|
740
|
-
packageVersion: z5.string().min(1, "Package version cannot be empty").default("1.0.0"),
|
|
741
|
-
builderCompatibility: z5.string().default(">=0.1.0"),
|
|
742
|
-
requiredComponents: z5.array(z5.string()).default([]),
|
|
743
|
-
requiredCapabilities: z5.array(z5.string()).default([]),
|
|
744
|
-
assets: z5.array(ManifestAssetItemSchema).default([]),
|
|
745
|
-
createdAt: z5.string().optional()
|
|
746
|
-
});
|
|
747
|
-
function isManifest(value) {
|
|
748
|
-
return ManifestSchema.safeParse(value).success;
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
// src/template.ts
|
|
752
|
-
import { z as z6 } from "zod";
|
|
753
|
-
var DANGEROUS_URI_PATTERN = /^(javascript:|vbscript:|data:(?!image\/))|<script/i;
|
|
754
|
-
function isSafeThumbnailUrl(url) {
|
|
755
|
-
if (!url || typeof url !== "string") return false;
|
|
756
|
-
const trimmed = url.trim();
|
|
757
|
-
if (trimmed.length === 0) return false;
|
|
758
|
-
if (DANGEROUS_URI_PATTERN.test(trimmed)) return false;
|
|
759
|
-
return true;
|
|
139
|
+
function formatMaxWidth(maxWidth) {
|
|
140
|
+
return `${maxWidth + 0.98}px`;
|
|
760
141
|
}
|
|
761
|
-
var
|
|
762
|
-
(
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
alt: z6.string().optional(),
|
|
768
|
-
width: z6.number().positive().optional(),
|
|
769
|
-
height: z6.number().positive().optional()
|
|
770
|
-
});
|
|
771
|
-
var SafeThumbnailSchema = z6.union([
|
|
772
|
-
AssetReferenceSchema,
|
|
773
|
-
SafeThumbnailObjectSchema,
|
|
774
|
-
SafeThumbnailUrlSchema
|
|
775
|
-
]);
|
|
776
|
-
var TemplatePackageRefSchema = z6.object({
|
|
777
|
-
path: z6.string().optional(),
|
|
778
|
-
url: SafeThumbnailUrlSchema.optional(),
|
|
779
|
-
checksum: z6.string().optional(),
|
|
780
|
-
format: z6.enum(["stora", "json"]).default("stora")
|
|
781
|
-
});
|
|
782
|
-
var TemplateRequirementsSchema = z6.object({
|
|
783
|
-
requiredComponents: z6.array(z6.string()).default([]),
|
|
784
|
-
requiredCapabilities: z6.array(z6.string()).default([])
|
|
142
|
+
var BREAKPOINT_MEDIA_QUERIES = Object.freeze({
|
|
143
|
+
desktop: `(min-width: ${BREAKPOINTS.desktop.minWidth}px)`,
|
|
144
|
+
tablet: `(min-width: ${BREAKPOINTS.tablet.minWidth}px) and (max-width: ${formatMaxWidth(
|
|
145
|
+
BREAKPOINTS.tablet.maxWidth
|
|
146
|
+
)})`,
|
|
147
|
+
mobile: `(max-width: ${formatMaxWidth(BREAKPOINTS.mobile.maxWidth)})`
|
|
785
148
|
});
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
category: z6.string().optional().default("general"),
|
|
791
|
-
tags: z6.array(z6.string()).optional().default([]),
|
|
792
|
-
thumbnail: SafeThumbnailSchema.optional(),
|
|
793
|
-
author: z6.string().optional().default(""),
|
|
794
|
-
version: z6.string().optional().default("1.0.0"),
|
|
795
|
-
document: PageDocumentSchema.optional(),
|
|
796
|
-
packageReference: TemplatePackageRefSchema.optional(),
|
|
797
|
-
requirements: TemplateRequirementsSchema.default({
|
|
798
|
-
requiredComponents: [],
|
|
799
|
-
requiredCapabilities: []
|
|
800
|
-
}),
|
|
801
|
-
createdAt: z6.string().optional(),
|
|
802
|
-
updatedAt: z6.string().optional(),
|
|
803
|
-
custom: z6.record(z6.string(), z6.unknown()).optional()
|
|
804
|
-
});
|
|
805
|
-
function isTemplateRecord(value) {
|
|
806
|
-
return TemplateRecordSchema.safeParse(value).success;
|
|
807
|
-
}
|
|
808
|
-
function isSafeThumbnail(value) {
|
|
809
|
-
return SafeThumbnailSchema.safeParse(value).success;
|
|
149
|
+
function getBreakpointForWidth(width) {
|
|
150
|
+
if (width < BREAKPOINTS.tablet.minWidth) return "mobile";
|
|
151
|
+
if (width < BREAKPOINTS.desktop.minWidth) return "tablet";
|
|
152
|
+
return "desktop";
|
|
810
153
|
}
|
|
811
154
|
|
|
812
155
|
// src/fixtures/starter-page.json
|
|
813
156
|
var starter_page_default = {
|
|
814
157
|
schema: "stora.page",
|
|
815
|
-
version: "1.
|
|
158
|
+
version: "1.2.0",
|
|
816
159
|
metadata: {
|
|
817
160
|
title: "Welcome to KUBUILD",
|
|
818
161
|
description: "A starter template built with KUBUILD portable web builder",
|
|
@@ -893,7 +236,8 @@ var starter_page_default = {
|
|
|
893
236
|
id: "hero-text",
|
|
894
237
|
type: "text",
|
|
895
238
|
props: {
|
|
896
|
-
|
|
239
|
+
as: "p",
|
|
240
|
+
text: "KUBUILD is an open, portable web page builder engine designed for modern web applications."
|
|
897
241
|
},
|
|
898
242
|
styles: {
|
|
899
243
|
base: {
|
|
@@ -934,14 +278,24 @@ var starter_page_default = {
|
|
|
934
278
|
id: "hero-button",
|
|
935
279
|
type: "button",
|
|
936
280
|
props: {
|
|
937
|
-
label: "Get Started"
|
|
938
|
-
action: {
|
|
939
|
-
type: "navigate",
|
|
940
|
-
payload: {
|
|
941
|
-
url: "/docs"
|
|
942
|
-
}
|
|
943
|
-
}
|
|
281
|
+
label: "Get Started"
|
|
944
282
|
},
|
|
283
|
+
actions: [
|
|
284
|
+
{
|
|
285
|
+
id: "hero-button-click",
|
|
286
|
+
trigger: "click",
|
|
287
|
+
enabled: true,
|
|
288
|
+
steps: [
|
|
289
|
+
{
|
|
290
|
+
id: "hero-button-navigate",
|
|
291
|
+
type: "navigate",
|
|
292
|
+
payload: {
|
|
293
|
+
url: "/docs"
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
],
|
|
945
299
|
styles: {
|
|
946
300
|
base: {
|
|
947
301
|
backgroundColor: "#2563eb",
|
|
@@ -971,7 +325,7 @@ var starter_page_default = {
|
|
|
971
325
|
var starterPageFixture = starter_page_default;
|
|
972
326
|
|
|
973
327
|
// src/json-schema.ts
|
|
974
|
-
import { z
|
|
328
|
+
import { z } from "zod";
|
|
975
329
|
var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
|
|
976
330
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
977
331
|
$id: "https://schema.stora.page/v1/page.json",
|
|
@@ -990,7 +344,7 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
|
|
|
990
344
|
type: "string",
|
|
991
345
|
pattern: "^\\d+(\\.\\d+)*$",
|
|
992
346
|
description: "Schema version of the document",
|
|
993
|
-
default: "1.
|
|
347
|
+
default: "1.2.0"
|
|
994
348
|
},
|
|
995
349
|
metadata: {
|
|
996
350
|
$ref: "#/definitions/documentMetadata"
|
|
@@ -1000,9 +354,33 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
|
|
|
1000
354
|
},
|
|
1001
355
|
tracking: {
|
|
1002
356
|
$ref: "#/definitions/trackingConfig"
|
|
357
|
+
},
|
|
358
|
+
theme: {
|
|
359
|
+
$ref: "#/definitions/theme"
|
|
1003
360
|
}
|
|
1004
361
|
},
|
|
1005
362
|
definitions: {
|
|
363
|
+
themeTokenMap: {
|
|
364
|
+
type: "object",
|
|
365
|
+
propertyNames: { pattern: "^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$" },
|
|
366
|
+
additionalProperties: {
|
|
367
|
+
type: ["string", "number"],
|
|
368
|
+
maxLength: 512,
|
|
369
|
+
pattern: "^[^;{}<>\\\\]*$"
|
|
370
|
+
},
|
|
371
|
+
description: "Design tokens keyed by name. Values must not contain ; { } < > or backslashes."
|
|
372
|
+
},
|
|
373
|
+
theme: {
|
|
374
|
+
type: "object",
|
|
375
|
+
description: "Document design tokens, emitted as CSS custom properties (--kb-color-*, --kb-font-*, --kb-radius-*, --kb-space-*) and referenced from styles as var(--kb-color-<key>).",
|
|
376
|
+
properties: {
|
|
377
|
+
colors: { $ref: "#/definitions/themeTokenMap" },
|
|
378
|
+
fonts: { $ref: "#/definitions/themeTokenMap" },
|
|
379
|
+
radii: { $ref: "#/definitions/themeTokenMap" },
|
|
380
|
+
spacing: { $ref: "#/definitions/themeTokenMap" }
|
|
381
|
+
},
|
|
382
|
+
additionalProperties: false
|
|
383
|
+
},
|
|
1006
384
|
trackingConfig: {
|
|
1007
385
|
type: "object",
|
|
1008
386
|
description: "Tracking configuration. Contains only public ids, flags and opaque credential ids \u2014 secrets are host-owned.",
|
|
@@ -1263,7 +641,7 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
|
|
|
1263
641
|
},
|
|
1264
642
|
trigger: {
|
|
1265
643
|
type: "string",
|
|
1266
|
-
enum: ["click", "submit", "change", "blur", "focus", "load"]
|
|
644
|
+
enum: ["click", "submit", "change", "blur", "focus", "load", "expire"]
|
|
1267
645
|
},
|
|
1268
646
|
label: { type: "string" },
|
|
1269
647
|
debounceMs: { type: "number", minimum: 0 },
|
|
@@ -1684,7 +1062,7 @@ var ACTION_PIPELINE_JSON_SCHEMA_V1 = {
|
|
|
1684
1062
|
},
|
|
1685
1063
|
trigger: {
|
|
1686
1064
|
type: "string",
|
|
1687
|
-
enum: ["click", "submit", "change", "blur", "focus", "load"],
|
|
1065
|
+
enum: ["click", "submit", "change", "blur", "focus", "load", "expire"],
|
|
1688
1066
|
description: "DOM or component event that triggers the action pipeline"
|
|
1689
1067
|
},
|
|
1690
1068
|
label: {
|
|
@@ -1903,7 +1281,7 @@ function getFormFieldBindingJsonSchema() {
|
|
|
1903
1281
|
}
|
|
1904
1282
|
function toDraft7(schema, id, title, io) {
|
|
1905
1283
|
return {
|
|
1906
|
-
...
|
|
1284
|
+
...z.toJSONSchema(schema, { target: "draft-7", io }),
|
|
1907
1285
|
$id: id,
|
|
1908
1286
|
title
|
|
1909
1287
|
};
|
|
@@ -1931,7 +1309,7 @@ function getTrackingRelayResponseJsonSchema() {
|
|
|
1931
1309
|
}
|
|
1932
1310
|
function getTrackingProviderSecretsJsonSchema() {
|
|
1933
1311
|
trackingProviderSecretsJsonSchema ??= toDraft7(
|
|
1934
|
-
|
|
1312
|
+
z.object({
|
|
1935
1313
|
meta: MetaTrackingSecretsSchema.optional(),
|
|
1936
1314
|
google: GoogleTrackingSecretsSchema.optional(),
|
|
1937
1315
|
tiktok: TikTokTrackingSecretsSchema.optional(),
|
|
@@ -1943,6 +1321,102 @@ function getTrackingProviderSecretsJsonSchema() {
|
|
|
1943
1321
|
);
|
|
1944
1322
|
return trackingProviderSecretsJsonSchema;
|
|
1945
1323
|
}
|
|
1324
|
+
|
|
1325
|
+
// src/builtin-components.ts
|
|
1326
|
+
var BUILTIN_COMPONENT_TYPES = [
|
|
1327
|
+
// layout
|
|
1328
|
+
"page",
|
|
1329
|
+
"section",
|
|
1330
|
+
"container",
|
|
1331
|
+
"columns",
|
|
1332
|
+
"flex",
|
|
1333
|
+
"grid",
|
|
1334
|
+
// typography
|
|
1335
|
+
"heading",
|
|
1336
|
+
"text",
|
|
1337
|
+
"paragraph",
|
|
1338
|
+
"link",
|
|
1339
|
+
"blockquote",
|
|
1340
|
+
"badge",
|
|
1341
|
+
"code-block",
|
|
1342
|
+
// media
|
|
1343
|
+
"image",
|
|
1344
|
+
"video",
|
|
1345
|
+
"icon",
|
|
1346
|
+
"html-embed",
|
|
1347
|
+
// form
|
|
1348
|
+
"button",
|
|
1349
|
+
"button-submit",
|
|
1350
|
+
"form",
|
|
1351
|
+
"input",
|
|
1352
|
+
"textarea",
|
|
1353
|
+
"select",
|
|
1354
|
+
"checkbox",
|
|
1355
|
+
"switch",
|
|
1356
|
+
"radio-group",
|
|
1357
|
+
"radio",
|
|
1358
|
+
"radio-item",
|
|
1359
|
+
"file-upload",
|
|
1360
|
+
// data
|
|
1361
|
+
"collection",
|
|
1362
|
+
"list",
|
|
1363
|
+
"list-item",
|
|
1364
|
+
"table",
|
|
1365
|
+
"table-row",
|
|
1366
|
+
"table-cell",
|
|
1367
|
+
// interactive
|
|
1368
|
+
"modal",
|
|
1369
|
+
"drawer",
|
|
1370
|
+
"collapsible",
|
|
1371
|
+
// conversion (Epic 60)
|
|
1372
|
+
"countdown",
|
|
1373
|
+
"accordion",
|
|
1374
|
+
"accordion-item",
|
|
1375
|
+
"tabs",
|
|
1376
|
+
"tab-panel",
|
|
1377
|
+
"carousel",
|
|
1378
|
+
"rating",
|
|
1379
|
+
"divider",
|
|
1380
|
+
"spacer"
|
|
1381
|
+
];
|
|
1382
|
+
function isBuiltinComponentType(type) {
|
|
1383
|
+
return typeof type === "string" && BUILTIN_COMPONENT_TYPES.includes(type);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
// src/canonical-props.ts
|
|
1387
|
+
var CANONICAL_TEXT_PROPS = Object.freeze({
|
|
1388
|
+
heading: { canonical: "text", aliases: ["content"], legacyReadOrder: ["text", "content"] },
|
|
1389
|
+
text: { canonical: "text", aliases: ["content"], legacyReadOrder: ["text", "content"] },
|
|
1390
|
+
paragraph: { canonical: "text", aliases: ["content"], legacyReadOrder: ["text", "content"] },
|
|
1391
|
+
link: {
|
|
1392
|
+
canonical: "text",
|
|
1393
|
+
aliases: ["label", "content"],
|
|
1394
|
+
legacyReadOrder: ["text", "label", "content"]
|
|
1395
|
+
},
|
|
1396
|
+
badge: { canonical: "text", aliases: ["label"], legacyReadOrder: ["text", "label"] },
|
|
1397
|
+
blockquote: { canonical: "text", aliases: ["quote"], legacyReadOrder: ["quote", "text"] },
|
|
1398
|
+
button: {
|
|
1399
|
+
canonical: "label",
|
|
1400
|
+
aliases: ["text", "content"],
|
|
1401
|
+
legacyReadOrder: ["label", "text", "content"]
|
|
1402
|
+
}
|
|
1403
|
+
});
|
|
1404
|
+
function getCanonicalTextPropRule(componentType) {
|
|
1405
|
+
return Object.prototype.hasOwnProperty.call(CANONICAL_TEXT_PROPS, componentType) ? CANONICAL_TEXT_PROPS[componentType] : void 0;
|
|
1406
|
+
}
|
|
1407
|
+
function findDeprecatedPropAliases(componentType, props) {
|
|
1408
|
+
const rule = getCanonicalTextPropRule(componentType);
|
|
1409
|
+
if (!rule || !props) return [];
|
|
1410
|
+
const canonicalPresent = props[rule.canonical] !== void 0;
|
|
1411
|
+
let aliasInEffect = canonicalPresent;
|
|
1412
|
+
const usages = [];
|
|
1413
|
+
for (const alias of rule.aliases) {
|
|
1414
|
+
if (props[alias] === void 0) continue;
|
|
1415
|
+
usages.push({ propName: alias, canonicalName: rule.canonical, inEffect: !aliasInEffect });
|
|
1416
|
+
aliasInEffect = true;
|
|
1417
|
+
}
|
|
1418
|
+
return usages;
|
|
1419
|
+
}
|
|
1946
1420
|
export {
|
|
1947
1421
|
ACTION_PIPELINE_JSON_SCHEMA_V1,
|
|
1948
1422
|
ARTBOARD_REFERENCE_NODE_TYPE,
|
|
@@ -1958,6 +1432,11 @@ export {
|
|
|
1958
1432
|
ArtboardSchema,
|
|
1959
1433
|
ArtboardTypeSchema,
|
|
1960
1434
|
AssetReferenceSchema,
|
|
1435
|
+
BREAKPOINTS,
|
|
1436
|
+
BREAKPOINT_MEDIA_QUERIES,
|
|
1437
|
+
BREAKPOINT_ORDER,
|
|
1438
|
+
BUILTIN_COMPONENT_TYPES,
|
|
1439
|
+
CANONICAL_TEXT_PROPS,
|
|
1961
1440
|
CURRENT_PROJECT_SCHEMA_VERSION,
|
|
1962
1441
|
CURRENT_SCHEMA_VERSION,
|
|
1963
1442
|
CloseModalStepPayloadSchema,
|
|
@@ -2004,10 +1483,16 @@ export {
|
|
|
2004
1483
|
StyleDefinitionSchema,
|
|
2005
1484
|
StyleValueSchema,
|
|
2006
1485
|
TEMPLATE_RECORD_JSON_SCHEMA_V1,
|
|
1486
|
+
THEME_TOKEN_CSS_PREFIX,
|
|
1487
|
+
THEME_TOKEN_GROUPS,
|
|
2007
1488
|
TRACKING_RELAY_PROTOCOL_VERSION,
|
|
2008
1489
|
TemplatePackageRefSchema,
|
|
2009
1490
|
TemplateRecordSchema,
|
|
2010
1491
|
TemplateRequirementsSchema,
|
|
1492
|
+
ThemeSchema,
|
|
1493
|
+
ThemeTokenKeySchema,
|
|
1494
|
+
ThemeTokenMapSchema,
|
|
1495
|
+
ThemeTokenValueSchema,
|
|
2011
1496
|
TikTokTrackingProviderConfigSchema,
|
|
2012
1497
|
TikTokTrackingSecretsSchema,
|
|
2013
1498
|
ToggleModalStepPayloadSchema,
|
|
@@ -2025,8 +1510,11 @@ export {
|
|
|
2025
1510
|
ValidationRuleTypeSchema,
|
|
2026
1511
|
VariableBindingSchema,
|
|
2027
1512
|
collectNodeIds,
|
|
1513
|
+
findDeprecatedPropAliases,
|
|
2028
1514
|
generateDeterministicNodeId,
|
|
2029
1515
|
getActionPipelineJsonSchema,
|
|
1516
|
+
getBreakpointForWidth,
|
|
1517
|
+
getCanonicalTextPropRule,
|
|
2030
1518
|
getFormConfigJsonSchema,
|
|
2031
1519
|
getFormFieldBindingJsonSchema,
|
|
2032
1520
|
getManifestJsonSchema,
|
|
@@ -2044,15 +1532,19 @@ export {
|
|
|
2044
1532
|
isAnimationConfig,
|
|
2045
1533
|
isArtboardReferenceNode,
|
|
2046
1534
|
isAssetReference,
|
|
1535
|
+
isBuiltinComponentType,
|
|
2047
1536
|
isConditionOperator,
|
|
2048
1537
|
isFormConfig,
|
|
2049
1538
|
isFormFieldBinding,
|
|
2050
1539
|
isManifest,
|
|
2051
1540
|
isProjectDocument,
|
|
2052
1541
|
isSafeActionUrl,
|
|
1542
|
+
isSafeThemeTokenKey,
|
|
1543
|
+
isSafeThemeTokenValue,
|
|
2053
1544
|
isSafeThumbnail,
|
|
2054
1545
|
isSafeThumbnailUrl,
|
|
2055
1546
|
isTemplateRecord,
|
|
1547
|
+
isTheme,
|
|
2056
1548
|
isTrackEventStepPayload,
|
|
2057
1549
|
isTrackingConfig,
|
|
2058
1550
|
isTrackingRelayRequest,
|
|
@@ -2061,6 +1553,8 @@ export {
|
|
|
2061
1553
|
isValidationRuleType,
|
|
2062
1554
|
isVariableBinding,
|
|
2063
1555
|
looksLikeProjectDocument,
|
|
1556
|
+
mergeThemes,
|
|
1557
|
+
parseThemeTokenRef,
|
|
2064
1558
|
sanitizeActionPayload,
|
|
2065
1559
|
sanitizeActionPipeline,
|
|
2066
1560
|
sanitizeActionStep,
|
|
@@ -2068,6 +1562,9 @@ export {
|
|
|
2068
1562
|
sanitizeActionUrl,
|
|
2069
1563
|
sanitizeActionValue,
|
|
2070
1564
|
starterPageFixture,
|
|
1565
|
+
themeToCssVariables,
|
|
1566
|
+
themeTokenCssVarName,
|
|
1567
|
+
themeTokenRef,
|
|
2071
1568
|
validateActionStepPayload,
|
|
2072
1569
|
validateNodeIdUniqueness
|
|
2073
1570
|
};
|