@kubuild/schema 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +24 -0
  2. package/dist/actions.d.ts +26 -2
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/breakpoints.d.ts +35 -0
  5. package/dist/breakpoints.d.ts.map +1 -0
  6. package/dist/builtin-components.d.ts +17 -0
  7. package/dist/builtin-components.d.ts.map +1 -0
  8. package/dist/canonical-props.d.ts +39 -0
  9. package/dist/canonical-props.d.ts.map +1 -0
  10. package/dist/chunk-MT3M7D67.js +1041 -0
  11. package/dist/chunk-MT3M7D67.js.map +1 -0
  12. package/dist/chunk-PECTZDCI.js +1038 -0
  13. package/dist/chunk-PECTZDCI.js.map +1 -0
  14. package/dist/document.d.ts +21 -82
  15. package/dist/document.d.ts.map +1 -1
  16. package/dist/index.cjs +700 -169
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +4 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +447 -747
  21. package/dist/index.js.map +1 -1
  22. package/dist/json-schema.d.ts +323 -10
  23. package/dist/json-schema.d.ts.map +1 -1
  24. package/dist/template.d.ts +6 -18
  25. package/dist/template.d.ts.map +1 -1
  26. package/dist/theme.d.ts +80 -0
  27. package/dist/theme.d.ts.map +1 -0
  28. package/dist/tracking.d.ts +178 -31
  29. package/dist/tracking.d.ts.map +1 -1
  30. package/dist/types.cjs +19 -0
  31. package/dist/types.cjs.map +1 -0
  32. package/dist/types.d.ts +331 -0
  33. package/dist/types.d.ts.map +1 -0
  34. package/dist/types.js +1 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/validate.cjs +715 -0
  37. package/dist/validate.cjs.map +1 -0
  38. package/dist/validate.d.ts +16 -0
  39. package/dist/validate.d.ts.map +1 -0
  40. package/dist/validate.js +53 -0
  41. package/dist/validate.js.map +1 -0
  42. package/package.json +22 -2
package/dist/index.js CHANGED
@@ -1,747 +1,161 @@
1
- // src/document.ts
2
- import { z as z4 } from "zod";
3
-
4
- // src/actions.ts
5
- import { z as z2 } from "zod";
6
-
7
- // src/tracking.ts
8
- import { z } from "zod";
9
- var TrackingProviderTypeSchema = z.enum([
10
- "meta",
11
- "google",
12
- "gtm",
13
- "tiktok",
14
- "custom"
15
- ]);
16
- var TrackingDeliverySchema = z.enum(["both", "client_only", "server_only"]);
17
- var MetaTrackingProviderConfigSchema = z.object({
18
- enabled: z.boolean().default(true),
19
- /** Optional linked account/workspace credential ID */
20
- credentialId: z.string().optional(),
21
- /** Meta Pixel ID (e.g. 123456789012345) */
22
- pixelId: z.string().optional().default(""),
23
- /** Enable Server-Side Conversions API */
24
- capiEnabled: z.boolean().optional().default(false),
25
- /**
26
- * System User Access Token for Meta Graph API.
27
- * Note: For security in production, prefer configuring tokens on your server backend
28
- * or proxying via `serverRelayUrl`.
29
- */
30
- capiAccessToken: z.string().optional().default(""),
31
- /** Test Event Code from Meta Events Manager (e.g. "TEST12345") */
32
- testEventCode: z.string().optional().default(""),
33
- /**
34
- * Host Server Relay URL (e.g. "/api/tracking/meta").
35
- * Recommended for browser clients to post CAPI events safely without exposing the secret token.
36
- */
37
- serverRelayUrl: z.string().optional().default("")
38
- });
39
- var GoogleTrackingProviderConfigSchema = z.object({
40
- enabled: z.boolean().default(true),
41
- /** Optional linked account/workspace credential ID */
42
- credentialId: z.string().optional(),
43
- /** GA4 Measurement ID (e.g. "G-XXXXXXXXXX") */
44
- measurementId: z.string().optional().default(""),
45
- /** GA4 Measurement Protocol API Secret (for server-side events) */
46
- measurementProtocolSecret: z.string().optional().default(""),
47
- /** Host Server Relay URL (e.g. "/api/tracking/ga4") */
48
- serverRelayUrl: z.string().optional().default("")
49
- });
50
- var GtmTrackingProviderConfigSchema = z.object({
51
- enabled: z.boolean().default(true),
52
- /** Optional linked account/workspace credential ID */
53
- credentialId: z.string().optional(),
54
- /** GTM Container ID (e.g. "GTM-XXXXXXX") */
55
- containerId: z.string().optional().default(""),
56
- /** Host Server Relay URL */
57
- serverRelayUrl: z.string().optional().default("")
58
- });
59
- var TikTokTrackingProviderConfigSchema = z.object({
60
- enabled: z.boolean().default(true),
61
- /** Optional linked account/workspace credential ID */
62
- credentialId: z.string().optional(),
63
- /** TikTok Pixel ID (e.g. "C1234567890") */
64
- pixelId: z.string().optional().default(""),
65
- /** Enable TikTok Events API (server-side) */
66
- eventsApiEnabled: z.boolean().optional().default(false),
67
- /** Long-term Access Token for TikTok Events API */
68
- accessToken: z.string().optional().default(""),
69
- /** Test Event Code from TikTok Event Manager */
70
- testEventCode: z.string().optional().default(""),
71
- /** Host Server Relay URL (e.g. "/api/tracking/tiktok") */
72
- serverRelayUrl: z.string().optional().default("")
73
- });
74
- var CustomTrackingProviderConfigSchema = z.object({
75
- enabled: z.boolean().default(true),
76
- /** Optional linked account/workspace credential ID */
77
- credentialId: z.string().optional(),
78
- /** Custom Webhook endpoint URL */
79
- endpointUrl: z.string().optional().default(""),
80
- /** Optional headers sent with the webhook POST request */
81
- headers: z.record(z.string(), z.string()).optional().default({})
82
- });
83
- var TrackingConfigSchema = z.object({
84
- /** Master toggle: dynamically enables or disables all tracking operations */
85
- enabled: z.boolean().default(true),
86
- /** When enabled, events are logged to console and can bypass live API calls for safe debugging */
87
- debugMode: z.boolean().optional().default(false),
88
- /** Automatically trigger PageView event upon page load */
89
- autoPageView: z.boolean().optional().default(true),
90
- /** Default delivery method when not explicitly overridden in an action step */
91
- defaultDelivery: TrackingDeliverySchema.optional().default("both"),
92
- /** Provider-specific settings */
93
- providers: z.object({
94
- meta: MetaTrackingProviderConfigSchema.optional(),
95
- google: GoogleTrackingProviderConfigSchema.optional(),
96
- gtm: GtmTrackingProviderConfigSchema.optional(),
97
- tiktok: TikTokTrackingProviderConfigSchema.optional(),
98
- custom: CustomTrackingProviderConfigSchema.optional()
99
- }).optional().default({})
100
- });
101
- var StandardTrackingEventSchema = z.enum([
102
- "PageView",
103
- "ViewContent",
104
- "AddToCart",
105
- "InitiateCheckout",
106
- "Purchase",
107
- "Lead",
108
- "Contact",
109
- "CompleteRegistration",
110
- "Subscribe",
111
- "Search",
112
- "SubmitApplication",
113
- "Schedule"
114
- ]);
115
- var TrackEventStepPayloadSchema = z.object({
116
- /** Event name: e.g. "Purchase", "Lead", or custom string */
117
- eventName: z.string().min(1, "Event name cannot be empty"),
118
- /** Standard event vs custom event identifier */
119
- eventType: z.enum(["standard", "custom"]).optional().default("standard"),
120
- /** Target provider: 'all' or a specific provider */
121
- provider: z.enum(["all", "meta", "google", "tiktok", "custom"]).optional().default("all"),
122
- /** Delivery channel: 'both', 'client_only', or 'server_only' */
123
- delivery: TrackingDeliverySchema.optional().default("both"),
124
- /**
125
- * Deduplication Event ID.
126
- * If omitted, a unique ID is automatically generated so Meta/TikTok CAPI
127
- * deduplicates cleanly with the browser pixel.
128
- */
129
- eventId: z.string().optional(),
130
- /**
131
- * Event parameters/properties (e.g. currency, value, content_name, order_id).
132
- * Supports runtime variable interpolation (e.g. {{ form.price }} or {{ variables.currency }}).
133
- */
134
- params: z.record(z.string(), z.unknown()).optional().default({}),
135
- /**
136
- * User Data for advanced matching and server CAPI (e.g. email, phone, firstName, lastName).
137
- * Supports runtime variable interpolation (e.g. {{ form.email }}).
138
- */
139
- userData: z.record(z.string(), z.unknown()).optional().default({}),
140
- /** Step-level active toggle */
141
- enabled: z.boolean().optional().default(true)
142
- });
143
- function isTrackingConfig(value) {
144
- return TrackingConfigSchema.safeParse(value).success;
145
- }
146
- function isTrackEventStepPayload(value) {
147
- return TrackEventStepPayloadSchema.safeParse(value).success;
148
- }
149
-
150
- // src/actions.ts
151
- var ActionTriggerTypeSchema = z2.enum([
152
- "click",
153
- "submit",
154
- "change",
155
- "blur",
156
- "focus",
157
- "load"
158
- ]);
159
- var ActionTriggerSchema = ActionTriggerTypeSchema;
160
- var ActionStepTypeSchema = z2.enum([
161
- "api_request",
162
- "navigate",
163
- "set_state",
164
- "reset_form",
165
- "show_toast",
166
- "open_modal",
167
- "close_modal",
168
- "copy_clipboard",
169
- "custom_event",
170
- "track_event"
171
- ]);
172
- var ConditionOperatorSchema = z2.enum([
173
- "equals",
174
- "not_equals",
175
- "contains",
176
- "not_contains",
177
- "is_truthy",
178
- "is_falsy",
179
- "gt",
180
- "gte",
181
- "lt",
182
- "lte",
183
- "regex"
184
- ]);
185
- var ActionStepConditionSchema = z2.object({
186
- field: z2.string().min(1, "Condition field cannot be empty"),
187
- operator: ConditionOperatorSchema,
188
- value: z2.unknown().optional()
189
- });
190
- var DANGEROUS_URL_PATTERN = /(javascript:|vbscript:|data:text\/html)/i;
191
- var DANGEROUS_SCRIPT_PATTERN = /<\s*script/i;
192
- function isSafeActionUrl(url) {
193
- if (!url || typeof url !== "string") return false;
194
- const trimmed = url.trim();
195
- if (DANGEROUS_URL_PATTERN.test(trimmed)) return false;
196
- if (DANGEROUS_SCRIPT_PATTERN.test(trimmed)) return false;
197
- return true;
198
- }
199
- var SafeUrlStringSchema = z2.string().min(1, "URL cannot be empty").refine(isSafeActionUrl, {
200
- message: "URL contains disallowed or unsafe protocol/script pattern"
201
- });
202
- var SafeEventNameSchema = z2.string().min(1, "Event name cannot be empty").regex(/^[a-zA-Z0-9_\-:]+$/, {
203
- message: "Event name must contain only alphanumeric characters, dashes, colons, or underscores"
204
- });
205
- var ApiRequestStepPayloadSchema = z2.object({
206
- url: SafeUrlStringSchema,
207
- method: z2.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).default("GET"),
208
- headers: z2.record(z2.string(), z2.string()).optional(),
209
- queryParams: z2.record(z2.string(), z2.union([z2.string(), z2.number(), z2.boolean()])).optional(),
210
- body: z2.union([z2.string(), z2.record(z2.string(), z2.unknown()), z2.array(z2.unknown())]).optional(),
211
- bodyFormat: z2.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
212
- bodyType: z2.enum(["json", "form-data", "formData", "urlencoded", "url-encoded", "raw", "text"]).optional(),
213
- timeout: z2.number().positive("Timeout must be greater than 0 ms").optional(),
214
- responseMapping: z2.record(z2.string(), z2.string()).optional()
215
- });
216
- var NavigateStepPayloadSchema = z2.object({
217
- url: SafeUrlStringSchema,
218
- target: z2.enum(["_self", "_blank", "_parent", "_top"]).optional().default("_self"),
219
- replace: z2.boolean().optional(),
220
- scroll: z2.boolean().optional(),
221
- behavior: z2.enum(["smooth", "auto"]).optional()
222
- });
223
- var SetStateStepPayloadSchema = z2.object({
224
- key: z2.string().min(1, "State key cannot be empty"),
225
- value: z2.unknown(),
226
- scope: z2.enum(["runtime", "document", "session", "local"]).optional().default("runtime")
227
- });
228
- var ResetFormStepPayloadSchema = z2.object({
229
- formId: z2.string().optional()
230
- });
231
- var ShowToastStepPayloadSchema = z2.object({
232
- message: z2.string().min(1, "Toast message cannot be empty"),
233
- type: z2.enum(["success", "error", "warning", "info"]).optional().default("info"),
234
- variant: z2.enum(["success", "error", "warning", "info"]).optional(),
235
- title: z2.string().optional(),
236
- duration: z2.number().nonnegative("Duration must be >= 0 ms").optional(),
237
- position: z2.enum(["top-right", "top-left", "bottom-right", "bottom-left", "top-center", "bottom-center"]).optional()
238
- });
239
- var OpenModalStepPayloadSchema = z2.object({
240
- modalId: z2.string().optional(),
241
- modalNodeId: z2.string().optional(),
242
- toggle: z2.boolean().optional()
243
- }).refine((data) => Boolean(data.modalId || data.modalNodeId), {
244
- message: "Modal ID or Modal Node ID cannot be empty"
245
- });
246
- var CloseModalStepPayloadSchema = z2.object({
247
- modalId: z2.string().optional(),
248
- modalNodeId: z2.string().optional()
249
- });
250
- var CopyClipboardStepPayloadSchema = z2.object({
251
- text: z2.string().optional(),
252
- value: z2.unknown().optional(),
253
- notify: z2.boolean().optional(),
254
- toastMessage: z2.string().optional()
255
- });
256
- var CustomEventStepPayloadSchema = z2.object({
257
- eventName: SafeEventNameSchema,
258
- detail: z2.record(z2.string(), z2.unknown()).optional(),
259
- bubbles: z2.boolean().optional().default(true),
260
- cancelable: z2.boolean().optional().default(true)
261
- });
262
- var StepPayloadSchemas = {
263
- api_request: ApiRequestStepPayloadSchema,
264
- navigate: NavigateStepPayloadSchema,
265
- set_state: SetStateStepPayloadSchema,
266
- reset_form: ResetFormStepPayloadSchema,
267
- show_toast: ShowToastStepPayloadSchema,
268
- open_modal: OpenModalStepPayloadSchema,
269
- close_modal: CloseModalStepPayloadSchema,
270
- copy_clipboard: CopyClipboardStepPayloadSchema,
271
- custom_event: CustomEventStepPayloadSchema,
272
- track_event: TrackEventStepPayloadSchema
273
- };
274
- var ActionStepSchema = z2.lazy(
275
- () => z2.object({
276
- id: z2.string().min(1, "Step ID cannot be empty"),
277
- type: ActionStepTypeSchema,
278
- label: z2.string().optional(),
279
- payload: z2.record(z2.string(), z2.unknown()).optional().default({}),
280
- condition: ActionStepConditionSchema.optional(),
281
- timeout: z2.number().positive().optional(),
282
- continueOnError: z2.boolean().optional(),
283
- onSuccess: z2.array(ActionStepSchema).optional(),
284
- onError: z2.array(ActionStepSchema).optional()
285
- })
286
- );
287
- var ActionPipelineSchema = z2.object({
288
- id: z2.string().min(1, "Pipeline ID cannot be empty"),
289
- trigger: ActionTriggerTypeSchema,
290
- label: z2.string().optional(),
291
- debounceMs: z2.number().nonnegative("Debounce ms must be >= 0").optional(),
292
- preventDuplicate: z2.boolean().optional(),
293
- enabled: z2.boolean().optional().default(true),
294
- steps: z2.array(ActionStepSchema).min(1, "Action pipeline must contain at least one step")
295
- });
296
- function isActionTriggerType(value) {
297
- return ActionTriggerTypeSchema.safeParse(value).success;
298
- }
299
- function isActionStepType(value) {
300
- return ActionStepTypeSchema.safeParse(value).success;
301
- }
302
- function isConditionOperator(value) {
303
- return ConditionOperatorSchema.safeParse(value).success;
304
- }
305
- function isActionStepCondition(value) {
306
- return ActionStepConditionSchema.safeParse(value).success;
307
- }
308
- function isActionStep(value) {
309
- return ActionStepSchema.safeParse(value).success;
310
- }
311
- function isActionPipeline(value) {
312
- return ActionPipelineSchema.safeParse(value).success;
313
- }
314
- function validateActionStepPayload(type, payload) {
315
- const schema = StepPayloadSchemas[type];
316
- if (!schema) {
317
- return {
318
- success: false,
319
- error: new z2.ZodError([
320
- {
321
- code: z2.ZodIssueCode.custom,
322
- message: `Unknown step type: ${type}`,
323
- path: ["type"]
324
- }
325
- ])
326
- };
327
- }
328
- const result = schema.safeParse(payload);
329
- if (result.success) {
330
- return { success: true, data: result.data };
331
- }
332
- return { success: false, error: result.error };
333
- }
334
- function sanitizeActionUrl(url, fallback = "") {
335
- if (typeof url !== "string") return fallback;
336
- const trimmed = url.trim();
337
- if (!isSafeActionUrl(trimmed)) {
338
- return fallback;
339
- }
340
- return trimmed;
341
- }
342
- function sanitizeActionString(value, fallback = "") {
343
- if (typeof value !== "string") return fallback;
344
- if (DANGEROUS_SCRIPT_PATTERN.test(value)) {
345
- return value.replace(/<\s*script[^>]*>[\s\S]*?<\s*\/\s*script\s*>/gi, "").replace(/<\s*script[^>]*>/gi, "");
346
- }
347
- return value;
348
- }
349
- function sanitizeActionValue(value) {
350
- if (value === null || value === void 0) return value;
351
- if (typeof value === "string") {
352
- const trimmed = value.trim();
353
- if (DANGEROUS_URL_PATTERN.test(trimmed)) {
354
- return "";
355
- }
356
- return sanitizeActionString(value);
357
- }
358
- if (Array.isArray(value)) {
359
- return value.map((item) => sanitizeActionValue(item));
360
- }
361
- if (typeof value === "object") {
362
- const result = {};
363
- for (const [k, v] of Object.entries(value)) {
364
- if (/^(url|href|src|endpoint|targetUrl)$/i.test(k) && typeof v === "string") {
365
- result[k] = sanitizeActionUrl(v);
366
- } else {
367
- result[k] = sanitizeActionValue(v);
368
- }
369
- }
370
- return result;
371
- }
372
- return value;
373
- }
374
- function sanitizeActionPayload(payload) {
375
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
376
- return {};
377
- }
378
- return sanitizeActionValue(payload);
379
- }
380
- function sanitizeActionStep(step) {
381
- const sanitized = {
382
- ...step,
383
- label: step.label ? sanitizeActionString(step.label) : step.label,
384
- payload: sanitizeActionPayload(step.payload)
385
- };
386
- if (step.condition && step.condition.value !== void 0) {
387
- sanitized.condition = {
388
- ...step.condition,
389
- value: sanitizeActionValue(step.condition.value)
390
- };
391
- }
392
- if (step.onSuccess && Array.isArray(step.onSuccess)) {
393
- sanitized.onSuccess = step.onSuccess.map((s) => sanitizeActionStep(s));
394
- }
395
- if (step.onError && Array.isArray(step.onError)) {
396
- sanitized.onError = step.onError.map((s) => sanitizeActionStep(s));
397
- }
398
- return sanitized;
399
- }
400
- function sanitizeActionPipeline(pipeline) {
401
- return {
402
- ...pipeline,
403
- label: pipeline.label ? sanitizeActionString(pipeline.label) : pipeline.label,
404
- steps: Array.isArray(pipeline.steps) ? pipeline.steps.map((s) => sanitizeActionStep(s)) : []
405
- };
406
- }
407
-
408
- // src/form.ts
409
- import { z as z3 } from "zod";
410
- var ValidationRuleTypeSchema = z3.enum([
411
- "required",
412
- "email",
413
- "url",
414
- "min_length",
415
- "max_length",
416
- "numeric_min",
417
- "numeric_max",
418
- "pattern",
419
- "match_field",
420
- "custom_regex"
421
- ]);
422
- var ValidateOnEventSchema = z3.enum(["blur", "change", "submit"]);
423
- var ValidationRuleSchema = z3.object({
424
- type: ValidationRuleTypeSchema,
425
- value: z3.unknown().optional(),
426
- message: z3.string().min(1, "Validation error message cannot be empty")
427
- });
428
- var FormFieldBindingSchema = z3.object({
429
- name: z3.string().min(1, "Field name cannot be empty"),
430
- label: z3.string().optional(),
431
- defaultValue: z3.unknown().optional(),
432
- rules: z3.array(ValidationRuleSchema).optional().default([]),
433
- validateOn: ValidateOnEventSchema.optional().default("blur"),
434
- transform: z3.enum(["trim", "lowercase", "uppercase", "number"]).optional(),
435
- disabled: z3.boolean().optional(),
436
- required: z3.boolean().optional()
437
- });
438
- var FormConfigSchema = z3.object({
439
- formId: z3.string().min(1, "Form ID cannot be empty"),
440
- resetOnSubmit: z3.boolean().optional().default(false),
441
- scrollToFirstError: z3.boolean().optional().default(true),
442
- validateOn: ValidateOnEventSchema.optional().default("blur"),
443
- initialValues: z3.record(z3.string(), z3.unknown()).optional(),
444
- rules: z3.array(ValidationRuleSchema).optional()
445
- });
446
- function isValidationRuleType(value) {
447
- return ValidationRuleTypeSchema.safeParse(value).success;
448
- }
449
- function isValidationRule(value) {
450
- return ValidationRuleSchema.safeParse(value).success;
451
- }
452
- function isValidateOnEvent(value) {
453
- return ValidateOnEventSchema.safeParse(value).success;
454
- }
455
- function isFormFieldBinding(value) {
456
- return FormFieldBindingSchema.safeParse(value).success;
457
- }
458
- function isFormConfig(value) {
459
- return FormConfigSchema.safeParse(value).success;
460
- }
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";
461
127
 
462
- // src/document.ts
463
- var SCHEMA_NAME = "stora.page";
464
- var CURRENT_SCHEMA_VERSION = "1.0.0";
465
- var AssetReferenceSchema = z4.object({
466
- type: z4.literal("asset"),
467
- assetId: z4.string().min(1, "Asset ID cannot be empty"),
468
- filename: z4.string().optional(),
469
- mimeType: z4.string().optional(),
470
- fallbackUrl: z4.string().url().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 })
471
133
  });
472
- var VariableBindingSchema = z4.object({
473
- type: z4.literal("variable"),
474
- key: z4.string().min(1, "Variable key cannot be empty"),
475
- fallback: z4.unknown().optional()
476
- });
477
- var ActionBindingSchema = z4.object({
478
- type: z4.string().min(1, "Action type cannot be empty"),
479
- payload: z4.record(z4.string(), z4.unknown()).optional()
480
- });
481
- var DANGEROUS_STYLE_VALUE_PATTERN = /javascript:|expression\(|@import|<script|vbscript:|data:text\/html/i;
482
- var StyleValueSchema = z4.union([
483
- z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
484
- message: "Style value contains a disallowed or unsafe pattern"
485
- }),
486
- z4.number(),
487
- z4.boolean(),
488
- z4.null(),
489
- z4.undefined()
134
+ var BREAKPOINT_ORDER = Object.freeze([
135
+ "desktop",
136
+ "tablet",
137
+ "mobile"
490
138
  ]);
491
- var StyleDefinitionSchema = z4.record(z4.string(), StyleValueSchema);
492
- var PseudoStateStylesSchema = z4.record(z4.string(), StyleDefinitionSchema);
493
- var ResponsiveStylesSchema = z4.object({
494
- base: StyleDefinitionSchema.optional(),
495
- desktop: StyleDefinitionSchema.optional(),
496
- tablet: StyleDefinitionSchema.optional(),
497
- mobile: StyleDefinitionSchema.optional(),
498
- states: PseudoStateStylesSchema.optional()
499
- }).passthrough().default({});
500
- var AnimationConfigSchema = z4.object({
501
- type: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
502
- message: "Animation type contains a disallowed or unsafe pattern"
503
- }).optional().default("none"),
504
- duration: z4.number().min(0, "Duration must be non-negative").optional().default(600),
505
- delay: z4.number().min(0, "Delay must be non-negative").optional().default(0),
506
- easing: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
507
- message: "Animation easing contains a disallowed or unsafe pattern"
508
- }).optional().default("ease-out"),
509
- once: z4.boolean().optional().default(true),
510
- hoverEffect: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
511
- message: "Hover effect contains a disallowed or unsafe pattern"
512
- }).optional().default("none"),
513
- loopEffect: z4.string().refine((value) => !DANGEROUS_STYLE_VALUE_PATTERN.test(value), {
514
- message: "Loop effect contains a disallowed or unsafe pattern"
515
- }).optional().default("none")
516
- });
517
- var DEFAULT_ANIMATION_CONFIG = {
518
- type: "none",
519
- duration: 600,
520
- delay: 0,
521
- easing: "ease-out",
522
- once: true,
523
- hoverEffect: "none",
524
- loopEffect: "none"
525
- };
526
- var NodeSchema = z4.lazy(
527
- () => z4.object({
528
- id: z4.string().min(1, "Node ID must be a non-empty string"),
529
- type: z4.string().min(1, "Node type must be a non-empty string"),
530
- props: z4.record(z4.string(), z4.unknown()).optional().default({}),
531
- styles: ResponsiveStylesSchema.optional().default({}),
532
- animation: AnimationConfigSchema.optional(),
533
- actions: z4.array(ActionPipelineSchema).optional(),
534
- formConfig: FormConfigSchema.optional(),
535
- children: z4.array(NodeSchema).optional().default([])
536
- })
537
- );
538
- var RootPageNodeSchema = NodeSchema.refine(
539
- (node) => node.type === "page",
540
- {
541
- message: 'Root node must have type "page"',
542
- path: ["type"]
543
- }
544
- );
545
- var DocumentMetadataSchema = z4.object({
546
- title: z4.string().min(1, "Title is required").default("Untitled Page"),
547
- description: z4.string().optional().default(""),
548
- author: z4.string().optional().default(""),
549
- createdAt: z4.string().optional(),
550
- updatedAt: z4.string().optional(),
551
- tags: z4.array(z4.string()).optional().default([]),
552
- category: z4.string().optional().default("general"),
553
- version: z4.string().optional().default("1.0.0"),
554
- custom: z4.record(z4.string(), z4.unknown()).optional(),
555
- tracking: TrackingConfigSchema.optional()
556
- });
557
- var PageDocumentSchema = z4.object({
558
- schema: z4.literal(SCHEMA_NAME),
559
- version: z4.string().min(1, "Schema version is required").default(CURRENT_SCHEMA_VERSION),
560
- metadata: DocumentMetadataSchema.optional(),
561
- tracking: TrackingConfigSchema.optional(),
562
- document: RootPageNodeSchema
563
- });
564
- var PROJECT_SCHEMA_NAME = "stora.project";
565
- var CURRENT_PROJECT_SCHEMA_VERSION = "1.0.0";
566
- var ARTBOARD_REFERENCE_NODE_TYPE = "artboard-reference";
567
- var ArtboardTypeSchema = z4.enum(["page", "component"]);
568
- var ArtboardSchema = z4.object({
569
- id: z4.string().min(1, "Artboard ID is required"),
570
- name: z4.string().min(1, "Artboard name is required"),
571
- artboardType: ArtboardTypeSchema,
572
- /** Route for page artboards (e.g. "/about"). */
573
- slug: z4.string().optional(),
574
- /**
575
- * For component artboards: the id that `open_modal` / `close_modal` actions target.
576
- * Mirrors the detached node's own `props.modalId` so ModalManager keeps working unchanged.
577
- */
578
- triggerId: z4.string().optional(),
579
- /**
580
- * Viewport/breakpoint this artboard is currently authored at. Declared inline
581
- * (rather than imported) because viewport is otherwise an editor/renderer concept.
582
- */
583
- viewport: z4.enum(["desktop", "tablet", "mobile"]).optional(),
584
- /** Persisted artboard width in px, matching the canvas ViewportResizer's `width`. */
585
- width: z4.number().positive().optional(),
586
- /**
587
- * Free position on the builder's infinite canvas, in unscaled canvas px. Absent means
588
- * "not placed yet" — the canvas then falls back to laying the artboard out in a row.
589
- */
590
- position: z4.object({
591
- x: z4.number(),
592
- y: z4.number()
593
- }).optional(),
594
- document: PageDocumentSchema
595
- });
596
- var ProjectDocumentSchema = z4.object({
597
- schema: z4.literal(PROJECT_SCHEMA_NAME),
598
- version: z4.string().min(1, "Schema version is required").default(CURRENT_PROJECT_SCHEMA_VERSION),
599
- metadata: DocumentMetadataSchema.optional(),
600
- tracking: TrackingConfigSchema.optional(),
601
- artboards: z4.array(ArtboardSchema).min(1, "A project needs at least one artboard"),
602
- activeArtboardId: z4.string().optional()
603
- });
604
- function isAssetReference(value) {
605
- return AssetReferenceSchema.safeParse(value).success;
606
- }
607
- function isVariableBinding(value) {
608
- return VariableBindingSchema.safeParse(value).success;
609
- }
610
- function isActionBinding(value) {
611
- return ActionBindingSchema.safeParse(value).success;
612
- }
613
- function isAnimationConfig(value) {
614
- return AnimationConfigSchema.safeParse(value).success;
615
- }
616
- function isProjectDocument(value) {
617
- return ProjectDocumentSchema.safeParse(value).success;
618
- }
619
- function looksLikeProjectDocument(value) {
620
- if (typeof value !== "object" || value === null) return false;
621
- const candidate = value;
622
- return candidate.schema === PROJECT_SCHEMA_NAME || Array.isArray(candidate.artboards);
623
- }
624
- function isArtboardReferenceNode(node) {
625
- return node.type === ARTBOARD_REFERENCE_NODE_TYPE;
626
- }
627
- function generateDeterministicNodeId(prefix, indexOrKey) {
628
- const cleanPrefix = prefix.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
629
- return `${cleanPrefix}_${indexOrKey}`;
630
- }
631
- function collectNodeIds(node) {
632
- const ids = [node.id];
633
- if (node.children && Array.isArray(node.children)) {
634
- for (const child of node.children) {
635
- ids.push(...collectNodeIds(child));
636
- }
637
- }
638
- return ids;
639
- }
640
- function validateNodeIdUniqueness(node) {
641
- const allIds = collectNodeIds(node);
642
- const seen = /* @__PURE__ */ new Set();
643
- const duplicates = /* @__PURE__ */ new Set();
644
- for (const id of allIds) {
645
- if (seen.has(id)) {
646
- duplicates.add(id);
647
- } else {
648
- seen.add(id);
649
- }
650
- }
651
- return {
652
- valid: duplicates.size === 0,
653
- duplicateIds: Array.from(duplicates)
654
- };
139
+ function formatMaxWidth(maxWidth) {
140
+ return `${maxWidth + 0.98}px`;
655
141
  }
656
-
657
- // src/manifest.ts
658
- import { z as z5 } from "zod";
659
- var ManifestAssetItemSchema = z5.object({
660
- id: z5.string().min(1, "Asset ID cannot be empty"),
661
- path: z5.string().min(1, "Asset archive path cannot be empty"),
662
- mimeType: z5.string().min(1, "MIME type cannot be empty"),
663
- size: z5.number().nonnegative("Asset size must be non-negative"),
664
- checksum: z5.string().optional()
665
- });
666
- var ManifestSchema = z5.object({
667
- schema: z5.literal(SCHEMA_NAME).default(SCHEMA_NAME),
668
- schemaVersion: z5.string().min(1, "Schema version cannot be empty").default("1.0.0"),
669
- packageVersion: z5.string().min(1, "Package version cannot be empty").default("1.0.0"),
670
- builderCompatibility: z5.string().default(">=0.1.0"),
671
- requiredComponents: z5.array(z5.string()).default([]),
672
- requiredCapabilities: z5.array(z5.string()).default([]),
673
- assets: z5.array(ManifestAssetItemSchema).default([]),
674
- createdAt: z5.string().optional()
675
- });
676
- function isManifest(value) {
677
- return ManifestSchema.safeParse(value).success;
678
- }
679
-
680
- // src/template.ts
681
- import { z as z6 } from "zod";
682
- var DANGEROUS_URI_PATTERN = /^(javascript:|vbscript:|data:(?!image\/))|<script/i;
683
- function isSafeThumbnailUrl(url) {
684
- if (!url || typeof url !== "string") return false;
685
- const trimmed = url.trim();
686
- if (trimmed.length === 0) return false;
687
- if (DANGEROUS_URI_PATTERN.test(trimmed)) return false;
688
- return true;
689
- }
690
- var SafeThumbnailUrlSchema = z6.string().min(1, "Thumbnail URL cannot be empty").refine(
691
- (url) => isSafeThumbnailUrl(url),
692
- { message: "Thumbnail URL contains an unsafe protocol or payload" }
693
- );
694
- var SafeThumbnailObjectSchema = z6.object({
695
- url: SafeThumbnailUrlSchema,
696
- alt: z6.string().optional(),
697
- width: z6.number().positive().optional(),
698
- height: z6.number().positive().optional()
699
- });
700
- var SafeThumbnailSchema = z6.union([
701
- AssetReferenceSchema,
702
- SafeThumbnailObjectSchema,
703
- SafeThumbnailUrlSchema
704
- ]);
705
- var TemplatePackageRefSchema = z6.object({
706
- path: z6.string().optional(),
707
- url: SafeThumbnailUrlSchema.optional(),
708
- checksum: z6.string().optional(),
709
- format: z6.enum(["stora", "json"]).default("stora")
710
- });
711
- var TemplateRequirementsSchema = z6.object({
712
- requiredComponents: z6.array(z6.string()).default([]),
713
- requiredCapabilities: z6.array(z6.string()).default([])
714
- });
715
- var TemplateRecordSchema = z6.object({
716
- id: z6.string().min(1, "Template ID must be a non-empty string"),
717
- name: z6.string().min(1, "Template name must be a non-empty string"),
718
- description: z6.string().optional().default(""),
719
- category: z6.string().optional().default("general"),
720
- tags: z6.array(z6.string()).optional().default([]),
721
- thumbnail: SafeThumbnailSchema.optional(),
722
- author: z6.string().optional().default(""),
723
- version: z6.string().optional().default("1.0.0"),
724
- document: PageDocumentSchema.optional(),
725
- packageReference: TemplatePackageRefSchema.optional(),
726
- requirements: TemplateRequirementsSchema.default({
727
- requiredComponents: [],
728
- requiredCapabilities: []
729
- }),
730
- createdAt: z6.string().optional(),
731
- updatedAt: z6.string().optional(),
732
- custom: z6.record(z6.string(), z6.unknown()).optional()
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)})`
733
148
  });
734
- function isTemplateRecord(value) {
735
- return TemplateRecordSchema.safeParse(value).success;
736
- }
737
- function isSafeThumbnail(value) {
738
- 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";
739
153
  }
740
154
 
741
155
  // src/fixtures/starter-page.json
742
156
  var starter_page_default = {
743
157
  schema: "stora.page",
744
- version: "1.0.0",
158
+ version: "1.2.0",
745
159
  metadata: {
746
160
  title: "Welcome to KUBUILD",
747
161
  description: "A starter template built with KUBUILD portable web builder",
@@ -822,7 +236,8 @@ var starter_page_default = {
822
236
  id: "hero-text",
823
237
  type: "text",
824
238
  props: {
825
- content: "KUBUILD is an open, portable web page builder engine designed for modern web applications."
239
+ as: "p",
240
+ text: "KUBUILD is an open, portable web page builder engine designed for modern web applications."
826
241
  },
827
242
  styles: {
828
243
  base: {
@@ -863,14 +278,24 @@ var starter_page_default = {
863
278
  id: "hero-button",
864
279
  type: "button",
865
280
  props: {
866
- label: "Get Started",
867
- action: {
868
- type: "navigate",
869
- payload: {
870
- url: "/docs"
871
- }
872
- }
281
+ label: "Get Started"
873
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
+ ],
874
299
  styles: {
875
300
  base: {
876
301
  backgroundColor: "#2563eb",
@@ -900,6 +325,7 @@ var starter_page_default = {
900
325
  var starterPageFixture = starter_page_default;
901
326
 
902
327
  // src/json-schema.ts
328
+ import { z } from "zod";
903
329
  var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
904
330
  $schema: "http://json-schema.org/draft-07/schema#",
905
331
  $id: "https://schema.stora.page/v1/page.json",
@@ -918,16 +344,108 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
918
344
  type: "string",
919
345
  pattern: "^\\d+(\\.\\d+)*$",
920
346
  description: "Schema version of the document",
921
- default: "1.0.0"
347
+ default: "1.2.0"
922
348
  },
923
349
  metadata: {
924
350
  $ref: "#/definitions/documentMetadata"
925
351
  },
926
352
  document: {
927
353
  $ref: "#/definitions/rootPageNode"
354
+ },
355
+ tracking: {
356
+ $ref: "#/definitions/trackingConfig"
357
+ },
358
+ theme: {
359
+ $ref: "#/definitions/theme"
928
360
  }
929
361
  },
930
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
+ },
384
+ trackingConfig: {
385
+ type: "object",
386
+ description: "Tracking configuration. Contains only public ids, flags and opaque credential ids \u2014 secrets are host-owned.",
387
+ properties: {
388
+ enabled: { type: "boolean", default: true },
389
+ debugMode: { type: "boolean", default: false },
390
+ autoPageView: { type: "boolean", default: true },
391
+ defaultDelivery: { type: "string", enum: ["both", "client_only", "server_only"], default: "both" },
392
+ providers: {
393
+ type: "object",
394
+ properties: {
395
+ meta: {
396
+ type: "object",
397
+ properties: {
398
+ enabled: { type: "boolean" },
399
+ credentialId: { type: "string" },
400
+ pixelId: { type: "string" },
401
+ capiEnabled: { type: "boolean" },
402
+ testEventCode: { type: "string" }
403
+ },
404
+ additionalProperties: false
405
+ },
406
+ google: {
407
+ type: "object",
408
+ properties: {
409
+ enabled: { type: "boolean" },
410
+ credentialId: { type: "string" },
411
+ measurementId: { type: "string" }
412
+ },
413
+ additionalProperties: false
414
+ },
415
+ gtm: {
416
+ type: "object",
417
+ properties: {
418
+ enabled: { type: "boolean" },
419
+ credentialId: { type: "string" },
420
+ containerId: { type: "string" }
421
+ },
422
+ additionalProperties: false
423
+ },
424
+ tiktok: {
425
+ type: "object",
426
+ properties: {
427
+ enabled: { type: "boolean" },
428
+ credentialId: { type: "string" },
429
+ pixelId: { type: "string" },
430
+ eventsApiEnabled: { type: "boolean" },
431
+ testEventCode: { type: "string" }
432
+ },
433
+ additionalProperties: false
434
+ },
435
+ custom: {
436
+ type: "object",
437
+ properties: {
438
+ enabled: { type: "boolean" },
439
+ credentialId: { type: "string" }
440
+ },
441
+ additionalProperties: false
442
+ }
443
+ },
444
+ additionalProperties: false
445
+ }
446
+ },
447
+ additionalProperties: false
448
+ },
931
449
  styleValue: {
932
450
  type: ["string", "number", "boolean", "null"],
933
451
  description: "A CSS property or design token value"
@@ -1067,8 +585,10 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
1067
585
  "show_toast",
1068
586
  "open_modal",
1069
587
  "close_modal",
588
+ "toggle_modal",
1070
589
  "copy_clipboard",
1071
- "custom_event"
590
+ "custom_event",
591
+ "track_event"
1072
592
  ]
1073
593
  },
1074
594
  label: { type: "string" },
@@ -1121,7 +641,7 @@ var PAGE_DOCUMENT_JSON_SCHEMA_V1 = {
1121
641
  },
1122
642
  trigger: {
1123
643
  type: "string",
1124
- enum: ["click", "submit", "change", "blur", "focus", "load"]
644
+ enum: ["click", "submit", "change", "blur", "focus", "load", "expire"]
1125
645
  },
1126
646
  label: { type: "string" },
1127
647
  debounceMs: { type: "number", minimum: 0 },
@@ -1542,7 +1062,7 @@ var ACTION_PIPELINE_JSON_SCHEMA_V1 = {
1542
1062
  },
1543
1063
  trigger: {
1544
1064
  type: "string",
1545
- enum: ["click", "submit", "change", "blur", "focus", "load"],
1065
+ enum: ["click", "submit", "change", "blur", "focus", "load", "expire"],
1546
1066
  description: "DOM or component event that triggers the action pipeline"
1547
1067
  },
1548
1068
  label: {
@@ -1589,8 +1109,10 @@ var ACTION_PIPELINE_JSON_SCHEMA_V1 = {
1589
1109
  "show_toast",
1590
1110
  "open_modal",
1591
1111
  "close_modal",
1112
+ "toggle_modal",
1592
1113
  "copy_clipboard",
1593
- "custom_event"
1114
+ "custom_event",
1115
+ "track_event"
1594
1116
  ]
1595
1117
  },
1596
1118
  label: { type: "string" },
@@ -1757,6 +1279,144 @@ var FORM_FIELD_BINDING_JSON_SCHEMA_V1 = {
1757
1279
  function getFormFieldBindingJsonSchema() {
1758
1280
  return FORM_FIELD_BINDING_JSON_SCHEMA_V1;
1759
1281
  }
1282
+ function toDraft7(schema, id, title, io) {
1283
+ return {
1284
+ ...z.toJSONSchema(schema, { target: "draft-7", io }),
1285
+ $id: id,
1286
+ title
1287
+ };
1288
+ }
1289
+ var trackingRelayRequestJsonSchema;
1290
+ var trackingRelayResponseJsonSchema;
1291
+ var trackingProviderSecretsJsonSchema;
1292
+ function getTrackingRelayRequestJsonSchema() {
1293
+ trackingRelayRequestJsonSchema ??= toDraft7(
1294
+ TrackingRelayRequestSchema,
1295
+ "https://schema.stora.page/v1/tracking-relay-request.json",
1296
+ "StoraTrackingRelayRequest",
1297
+ "input"
1298
+ );
1299
+ return trackingRelayRequestJsonSchema;
1300
+ }
1301
+ function getTrackingRelayResponseJsonSchema() {
1302
+ trackingRelayResponseJsonSchema ??= toDraft7(
1303
+ TrackingRelayResponseSchema,
1304
+ "https://schema.stora.page/v1/tracking-relay-response.json",
1305
+ "StoraTrackingRelayResponse",
1306
+ "output"
1307
+ );
1308
+ return trackingRelayResponseJsonSchema;
1309
+ }
1310
+ function getTrackingProviderSecretsJsonSchema() {
1311
+ trackingProviderSecretsJsonSchema ??= toDraft7(
1312
+ z.object({
1313
+ meta: MetaTrackingSecretsSchema.optional(),
1314
+ google: GoogleTrackingSecretsSchema.optional(),
1315
+ tiktok: TikTokTrackingSecretsSchema.optional(),
1316
+ custom: CustomTrackingSecretsSchema.optional()
1317
+ }),
1318
+ "https://schema.stora.page/v1/tracking-provider-secrets.json",
1319
+ "StoraTrackingProviderSecrets",
1320
+ "input"
1321
+ );
1322
+ return trackingProviderSecretsJsonSchema;
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
+ }
1760
1420
  export {
1761
1421
  ACTION_PIPELINE_JSON_SCHEMA_V1,
1762
1422
  ARTBOARD_REFERENCE_NODE_TYPE,
@@ -1772,6 +1432,11 @@ export {
1772
1432
  ArtboardSchema,
1773
1433
  ArtboardTypeSchema,
1774
1434
  AssetReferenceSchema,
1435
+ BREAKPOINTS,
1436
+ BREAKPOINT_MEDIA_QUERIES,
1437
+ BREAKPOINT_ORDER,
1438
+ BUILTIN_COMPONENT_TYPES,
1439
+ CANONICAL_TEXT_PROPS,
1775
1440
  CURRENT_PROJECT_SCHEMA_VERSION,
1776
1441
  CURRENT_SCHEMA_VERSION,
1777
1442
  CloseModalStepPayloadSchema,
@@ -1779,6 +1444,7 @@ export {
1779
1444
  CopyClipboardStepPayloadSchema,
1780
1445
  CustomEventStepPayloadSchema,
1781
1446
  CustomTrackingProviderConfigSchema,
1447
+ CustomTrackingSecretsSchema,
1782
1448
  DEFAULT_ANIMATION_CONFIG,
1783
1449
  DocumentMetadataSchema,
1784
1450
  FORM_CONFIG_JSON_SCHEMA_V1,
@@ -1786,11 +1452,14 @@ export {
1786
1452
  FormConfigSchema,
1787
1453
  FormFieldBindingSchema,
1788
1454
  GoogleTrackingProviderConfigSchema,
1455
+ GoogleTrackingSecretsSchema,
1789
1456
  GtmTrackingProviderConfigSchema,
1457
+ LEGACY_TRACKING_SECRET_KEYS,
1790
1458
  MANIFEST_JSON_SCHEMA_V1,
1791
1459
  ManifestAssetItemSchema,
1792
1460
  ManifestSchema,
1793
1461
  MetaTrackingProviderConfigSchema,
1462
+ MetaTrackingSecretsSchema,
1794
1463
  NavigateStepPayloadSchema,
1795
1464
  NodeSchema,
1796
1465
  OpenModalStepPayloadSchema,
@@ -1806,6 +1475,7 @@ export {
1806
1475
  SafeThumbnailObjectSchema,
1807
1476
  SafeThumbnailSchema,
1808
1477
  SafeThumbnailUrlSchema,
1478
+ ServerTrackingEventSchema,
1809
1479
  SetStateStepPayloadSchema,
1810
1480
  ShowToastStepPayloadSchema,
1811
1481
  StandardTrackingEventSchema,
@@ -1813,26 +1483,46 @@ export {
1813
1483
  StyleDefinitionSchema,
1814
1484
  StyleValueSchema,
1815
1485
  TEMPLATE_RECORD_JSON_SCHEMA_V1,
1486
+ THEME_TOKEN_CSS_PREFIX,
1487
+ THEME_TOKEN_GROUPS,
1488
+ TRACKING_RELAY_PROTOCOL_VERSION,
1816
1489
  TemplatePackageRefSchema,
1817
1490
  TemplateRecordSchema,
1818
1491
  TemplateRequirementsSchema,
1492
+ ThemeSchema,
1493
+ ThemeTokenKeySchema,
1494
+ ThemeTokenMapSchema,
1495
+ ThemeTokenValueSchema,
1819
1496
  TikTokTrackingProviderConfigSchema,
1497
+ TikTokTrackingSecretsSchema,
1498
+ ToggleModalStepPayloadSchema,
1499
+ TrackEventProviderSchema,
1820
1500
  TrackEventStepPayloadSchema,
1821
1501
  TrackingConfigSchema,
1822
1502
  TrackingDeliverySchema,
1823
1503
  TrackingProviderTypeSchema,
1504
+ TrackingRelayErrorCodeSchema,
1505
+ TrackingRelayProviderResultSchema,
1506
+ TrackingRelayRequestSchema,
1507
+ TrackingRelayResponseSchema,
1824
1508
  ValidateOnEventSchema,
1825
1509
  ValidationRuleSchema,
1826
1510
  ValidationRuleTypeSchema,
1827
1511
  VariableBindingSchema,
1828
1512
  collectNodeIds,
1513
+ findDeprecatedPropAliases,
1829
1514
  generateDeterministicNodeId,
1830
1515
  getActionPipelineJsonSchema,
1516
+ getBreakpointForWidth,
1517
+ getCanonicalTextPropRule,
1831
1518
  getFormConfigJsonSchema,
1832
1519
  getFormFieldBindingJsonSchema,
1833
1520
  getManifestJsonSchema,
1834
1521
  getPageDocumentJsonSchema,
1835
1522
  getTemplateRecordJsonSchema,
1523
+ getTrackingProviderSecretsJsonSchema,
1524
+ getTrackingRelayRequestJsonSchema,
1525
+ getTrackingRelayResponseJsonSchema,
1836
1526
  isActionBinding,
1837
1527
  isActionPipeline,
1838
1528
  isActionStep,
@@ -1842,22 +1532,29 @@ export {
1842
1532
  isAnimationConfig,
1843
1533
  isArtboardReferenceNode,
1844
1534
  isAssetReference,
1535
+ isBuiltinComponentType,
1845
1536
  isConditionOperator,
1846
1537
  isFormConfig,
1847
1538
  isFormFieldBinding,
1848
1539
  isManifest,
1849
1540
  isProjectDocument,
1850
1541
  isSafeActionUrl,
1542
+ isSafeThemeTokenKey,
1543
+ isSafeThemeTokenValue,
1851
1544
  isSafeThumbnail,
1852
1545
  isSafeThumbnailUrl,
1853
1546
  isTemplateRecord,
1547
+ isTheme,
1854
1548
  isTrackEventStepPayload,
1855
1549
  isTrackingConfig,
1550
+ isTrackingRelayRequest,
1856
1551
  isValidateOnEvent,
1857
1552
  isValidationRule,
1858
1553
  isValidationRuleType,
1859
1554
  isVariableBinding,
1860
1555
  looksLikeProjectDocument,
1556
+ mergeThemes,
1557
+ parseThemeTokenRef,
1861
1558
  sanitizeActionPayload,
1862
1559
  sanitizeActionPipeline,
1863
1560
  sanitizeActionStep,
@@ -1865,6 +1562,9 @@ export {
1865
1562
  sanitizeActionUrl,
1866
1563
  sanitizeActionValue,
1867
1564
  starterPageFixture,
1565
+ themeToCssVariables,
1566
+ themeTokenCssVarName,
1567
+ themeTokenRef,
1868
1568
  validateActionStepPayload,
1869
1569
  validateNodeIdUniqueness
1870
1570
  };