@homepages/template-kit 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +182 -0
  2. package/README.md +71 -14
  3. package/dist/base.css +85 -0
  4. package/dist/browser.d.ts +26 -0
  5. package/dist/browser.js +55 -0
  6. package/dist/cli.js +1 -1
  7. package/dist/contracts/image-descriptor.d.ts +17 -0
  8. package/dist/contracts/markers.d.ts +20 -0
  9. package/dist/contracts/markers.js +21 -0
  10. package/dist/contracts/slot-catalog.d.ts +237 -0
  11. package/dist/contracts/slot-catalog.js +247 -0
  12. package/dist/contracts/transforms.d.ts +108 -0
  13. package/dist/contracts/transforms.js +117 -0
  14. package/dist/design-system/breakpoints.d.ts +5 -0
  15. package/dist/design-system/breakpoints.js +14 -0
  16. package/dist/design-system/theme.d.ts +307 -0
  17. package/dist/design-system/theme.js +95 -0
  18. package/dist/eslint/is-client-file.js +79 -0
  19. package/dist/eslint/rules/image-bare-needs-reason.js +38 -0
  20. package/dist/eslint/rules/no-client-directive-in-contract.js +26 -0
  21. package/dist/eslint/rules/no-client-runtime-in-server.js +99 -0
  22. package/dist/eslint/rules/no-css-import-from-render-path.js +23 -0
  23. package/dist/eslint/rules/no-hex.js +111 -0
  24. package/dist/eslint/rules/no-inline-style.js +23 -0
  25. package/dist/eslint/rules/no-nondeterminism.js +44 -0
  26. package/dist/eslint/rules/no-raw-element.js +32 -0
  27. package/dist/eslint/rules/props-from-schema.js +32 -0
  28. package/dist/eslint/rules/serializable-island-props.js +108 -0
  29. package/dist/eslint/rules/slot-marker-literal.js +33 -0
  30. package/dist/eslint.d.ts +4 -8
  31. package/dist/eslint.js +75 -11
  32. package/dist/fixtures/sample-property.d.ts +67 -0
  33. package/dist/fixtures/sample-property.js +707 -0
  34. package/dist/fixtures.d.ts +2 -0
  35. package/dist/fixtures.js +3 -0
  36. package/dist/index.d.ts +37 -13
  37. package/dist/index.js +34 -2
  38. package/dist/island-runtime.d.ts +30 -0
  39. package/dist/island-runtime.js +73 -0
  40. package/dist/islands/contract.d.ts +56 -0
  41. package/dist/islands/contract.js +71 -0
  42. package/dist/islands/marker.d.ts +16 -0
  43. package/dist/islands/marker.js +18 -0
  44. package/dist/package.js +5 -0
  45. package/dist/primitives/Image.d.ts +49 -0
  46. package/dist/primitives/Image.js +95 -0
  47. package/dist/primitives/Section.d.ts +22 -0
  48. package/dist/primitives/Section.js +26 -0
  49. package/dist/primitives/Slot.d.ts +50 -0
  50. package/dist/primitives/Slot.js +39 -0
  51. package/dist/primitives/SlotGroup.d.ts +38 -0
  52. package/dist/primitives/SlotGroup.js +24 -0
  53. package/dist/primitives/SlotItem.d.ts +43 -0
  54. package/dist/primitives/SlotItem.js +38 -0
  55. package/dist/primitives/index.d.ts +7 -0
  56. package/dist/primitives/picture-sources.d.ts +22 -0
  57. package/dist/primitives/picture-sources.js +52 -0
  58. package/dist/schema/fill-spec.d.ts +692 -0
  59. package/dist/schema/fill-spec.js +98 -0
  60. package/dist/schema/fixture-schema.d.ts +143 -0
  61. package/dist/schema/fixture-schema.js +113 -0
  62. package/dist/schema/index.d.ts +16 -0
  63. package/dist/schema/manifest.d.ts +527 -0
  64. package/dist/schema/manifest.js +73 -0
  65. package/dist/schema/property-facts.d.ts +44 -0
  66. package/dist/schema/resolve-variants.d.ts +11 -0
  67. package/dist/schema/resolve-variants.js +15 -0
  68. package/dist/schema/runtime-values.d.ts +45 -0
  69. package/dist/schema/section-nav.d.ts +7 -0
  70. package/dist/schema/section-props.d.ts +69 -0
  71. package/dist/schema/section-schema.d.ts +533 -0
  72. package/dist/schema/section-schema.js +72 -0
  73. package/dist/schema/slot-types.d.ts +117 -0
  74. package/dist/schema/slot-types.js +181 -0
  75. package/dist/schema/source.d.ts +13 -0
  76. package/dist/schema/source.js +12 -0
  77. package/dist/schema/synthesize-nullable.d.ts +18 -0
  78. package/dist/schema/synthesize-nullable.js +47 -0
  79. package/dist/styles.css +131 -9
  80. package/docs/INDEX.md +6 -4
  81. package/docs/eslint.md +90 -0
  82. package/docs/islands.md +150 -0
  83. package/docs/llms.txt +30 -3
  84. package/docs/primitives.md +214 -0
  85. package/docs/schema-system.md +240 -0
  86. package/docs/theme-and-css.md +179 -0
  87. package/package.json +30 -6
  88. package/tsconfig.base.json +16 -0
  89. package/tsconfig.json +2 -13
  90. package/dist/src-CrdHXijV.js +0 -23
@@ -0,0 +1,527 @@
1
+ import { z } from "zod";
2
+ //#region src/schema/manifest.d.ts
3
+ declare const TemplateManifest: z.ZodEffects<z.ZodObject<{
4
+ key: z.ZodString;
5
+ name: z.ZodString;
6
+ deliverable_type: z.ZodEnum<["single_property_website"]>;
7
+ options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
8
+ user_editable: z.ZodDefault<z.ZodBoolean>;
9
+ template_overridable: z.ZodDefault<z.ZodBoolean>;
10
+ planner_settable: z.ZodDefault<z.ZodBoolean>;
11
+ affects_decisions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
12
+ affects_slots: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
13
+ type: z.ZodLiteral<"enum">;
14
+ values: z.ZodArray<z.ZodString, "many">;
15
+ default: z.ZodString;
16
+ }, "strict", z.ZodTypeAny, {
17
+ type: "enum";
18
+ values: string[];
19
+ default: string;
20
+ user_editable: boolean;
21
+ template_overridable: boolean;
22
+ planner_settable: boolean;
23
+ affects_decisions: string[];
24
+ affects_slots: string[];
25
+ }, {
26
+ type: "enum";
27
+ values: string[];
28
+ default: string;
29
+ user_editable?: boolean | undefined;
30
+ template_overridable?: boolean | undefined;
31
+ planner_settable?: boolean | undefined;
32
+ affects_decisions?: string[] | undefined;
33
+ affects_slots?: string[] | undefined;
34
+ }>, z.ZodObject<{
35
+ user_editable: z.ZodDefault<z.ZodBoolean>;
36
+ template_overridable: z.ZodDefault<z.ZodBoolean>;
37
+ planner_settable: z.ZodDefault<z.ZodBoolean>;
38
+ affects_decisions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
39
+ affects_slots: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
40
+ type: z.ZodLiteral<"bool">;
41
+ default: z.ZodBoolean;
42
+ }, "strict", z.ZodTypeAny, {
43
+ type: "bool";
44
+ default: boolean;
45
+ user_editable: boolean;
46
+ template_overridable: boolean;
47
+ planner_settable: boolean;
48
+ affects_decisions: string[];
49
+ affects_slots: string[];
50
+ }, {
51
+ type: "bool";
52
+ default: boolean;
53
+ user_editable?: boolean | undefined;
54
+ template_overridable?: boolean | undefined;
55
+ planner_settable?: boolean | undefined;
56
+ affects_decisions?: string[] | undefined;
57
+ affects_slots?: string[] | undefined;
58
+ }>, z.ZodObject<{
59
+ user_editable: z.ZodDefault<z.ZodBoolean>;
60
+ template_overridable: z.ZodDefault<z.ZodBoolean>;
61
+ planner_settable: z.ZodDefault<z.ZodBoolean>;
62
+ affects_decisions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
63
+ affects_slots: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
64
+ type: z.ZodLiteral<"int">;
65
+ default: z.ZodNumber;
66
+ min: z.ZodOptional<z.ZodNumber>;
67
+ max: z.ZodOptional<z.ZodNumber>;
68
+ }, "strict", z.ZodTypeAny, {
69
+ type: "int";
70
+ default: number;
71
+ user_editable: boolean;
72
+ template_overridable: boolean;
73
+ planner_settable: boolean;
74
+ affects_decisions: string[];
75
+ affects_slots: string[];
76
+ min?: number | undefined;
77
+ max?: number | undefined;
78
+ }, {
79
+ type: "int";
80
+ default: number;
81
+ user_editable?: boolean | undefined;
82
+ template_overridable?: boolean | undefined;
83
+ planner_settable?: boolean | undefined;
84
+ affects_decisions?: string[] | undefined;
85
+ affects_slots?: string[] | undefined;
86
+ min?: number | undefined;
87
+ max?: number | undefined;
88
+ }>, z.ZodObject<{
89
+ user_editable: z.ZodDefault<z.ZodBoolean>;
90
+ template_overridable: z.ZodDefault<z.ZodBoolean>;
91
+ planner_settable: z.ZodDefault<z.ZodBoolean>;
92
+ affects_decisions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
93
+ affects_slots: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
94
+ type: z.ZodLiteral<"string">;
95
+ default: z.ZodString;
96
+ }, "strict", z.ZodTypeAny, {
97
+ type: "string";
98
+ default: string;
99
+ user_editable: boolean;
100
+ template_overridable: boolean;
101
+ planner_settable: boolean;
102
+ affects_decisions: string[];
103
+ affects_slots: string[];
104
+ }, {
105
+ type: "string";
106
+ default: string;
107
+ user_editable?: boolean | undefined;
108
+ template_overridable?: boolean | undefined;
109
+ planner_settable?: boolean | undefined;
110
+ affects_decisions?: string[] | undefined;
111
+ affects_slots?: string[] | undefined;
112
+ }>, z.ZodObject<{
113
+ user_editable: z.ZodDefault<z.ZodBoolean>;
114
+ template_overridable: z.ZodDefault<z.ZodBoolean>;
115
+ planner_settable: z.ZodDefault<z.ZodBoolean>;
116
+ affects_decisions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
117
+ affects_slots: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
118
+ type: z.ZodLiteral<"json">;
119
+ default: z.ZodUnknown;
120
+ }, "strict", z.ZodTypeAny, {
121
+ type: "json";
122
+ user_editable: boolean;
123
+ template_overridable: boolean;
124
+ planner_settable: boolean;
125
+ affects_decisions: string[];
126
+ affects_slots: string[];
127
+ default?: unknown;
128
+ }, {
129
+ type: "json";
130
+ default?: unknown;
131
+ user_editable?: boolean | undefined;
132
+ template_overridable?: boolean | undefined;
133
+ planner_settable?: boolean | undefined;
134
+ affects_decisions?: string[] | undefined;
135
+ affects_slots?: string[] | undefined;
136
+ }>]>>>;
137
+ sections: z.ZodArray<z.ZodObject<{
138
+ section: z.ZodString;
139
+ instance_id: z.ZodString;
140
+ options: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
141
+ locked: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
142
+ required: z.ZodDefault<z.ZodBoolean>;
143
+ reorderable: z.ZodDefault<z.ZodBoolean>;
144
+ }, "strict", z.ZodTypeAny, {
145
+ options: Record<string, unknown>;
146
+ required: boolean;
147
+ section: string;
148
+ instance_id: string;
149
+ locked: string[];
150
+ reorderable: boolean;
151
+ }, {
152
+ section: string;
153
+ instance_id: string;
154
+ options?: Record<string, unknown> | undefined;
155
+ required?: boolean | undefined;
156
+ locked?: string[] | undefined;
157
+ reorderable?: boolean | undefined;
158
+ }>, "many">;
159
+ reconcile: z.ZodDefault<z.ZodArray<z.ZodObject<{
160
+ type: z.ZodLiteral<"dedup-image">;
161
+ from: z.ZodObject<{
162
+ section: z.ZodString;
163
+ slot: z.ZodString;
164
+ }, "strict", z.ZodTypeAny, {
165
+ slot: string;
166
+ section: string;
167
+ }, {
168
+ slot: string;
169
+ section: string;
170
+ }>;
171
+ into: z.ZodObject<{
172
+ section: z.ZodString;
173
+ slot: z.ZodString;
174
+ }, "strict", z.ZodTypeAny, {
175
+ slot: string;
176
+ section: string;
177
+ }, {
178
+ slot: string;
179
+ section: string;
180
+ }>;
181
+ predicate_tags: z.ZodArray<z.ZodString, "many">;
182
+ min: z.ZodNumber;
183
+ }, "strict", z.ZodTypeAny, {
184
+ type: "dedup-image";
185
+ min: number;
186
+ from: {
187
+ slot: string;
188
+ section: string;
189
+ };
190
+ into: {
191
+ slot: string;
192
+ section: string;
193
+ };
194
+ predicate_tags: string[];
195
+ }, {
196
+ type: "dedup-image";
197
+ min: number;
198
+ from: {
199
+ slot: string;
200
+ section: string;
201
+ };
202
+ into: {
203
+ slot: string;
204
+ section: string;
205
+ };
206
+ predicate_tags: string[];
207
+ }>, "many">>;
208
+ preview: z.ZodOptional<z.ZodObject<{
209
+ blurb: z.ZodString;
210
+ intents: z.ZodArray<z.ZodEnum<["for_sale", "for_rent"]>, "many">;
211
+ types: z.ZodArray<z.ZodEnum<["single_family", "condo_townhome", "multi_family", "investment"]>, "many">;
212
+ demoUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
213
+ }, "strict", z.ZodTypeAny, {
214
+ blurb: string;
215
+ intents: ("for_sale" | "for_rent")[];
216
+ types: ("single_family" | "condo_townhome" | "multi_family" | "investment")[];
217
+ demoUrl?: string | null | undefined;
218
+ }, {
219
+ blurb: string;
220
+ intents: ("for_sale" | "for_rent")[];
221
+ types: ("single_family" | "condo_townhome" | "multi_family" | "investment")[];
222
+ demoUrl?: string | null | undefined;
223
+ }>>;
224
+ }, "strict", z.ZodTypeAny, {
225
+ key: string;
226
+ name: string;
227
+ deliverable_type: "single_property_website";
228
+ sections: {
229
+ options: Record<string, unknown>;
230
+ required: boolean;
231
+ section: string;
232
+ instance_id: string;
233
+ locked: string[];
234
+ reorderable: boolean;
235
+ }[];
236
+ reconcile: {
237
+ type: "dedup-image";
238
+ min: number;
239
+ from: {
240
+ slot: string;
241
+ section: string;
242
+ };
243
+ into: {
244
+ slot: string;
245
+ section: string;
246
+ };
247
+ predicate_tags: string[];
248
+ }[];
249
+ options?: Record<string, {
250
+ type: "enum";
251
+ values: string[];
252
+ default: string;
253
+ user_editable: boolean;
254
+ template_overridable: boolean;
255
+ planner_settable: boolean;
256
+ affects_decisions: string[];
257
+ affects_slots: string[];
258
+ } | {
259
+ type: "bool";
260
+ default: boolean;
261
+ user_editable: boolean;
262
+ template_overridable: boolean;
263
+ planner_settable: boolean;
264
+ affects_decisions: string[];
265
+ affects_slots: string[];
266
+ } | {
267
+ type: "int";
268
+ default: number;
269
+ user_editable: boolean;
270
+ template_overridable: boolean;
271
+ planner_settable: boolean;
272
+ affects_decisions: string[];
273
+ affects_slots: string[];
274
+ min?: number | undefined;
275
+ max?: number | undefined;
276
+ } | {
277
+ type: "string";
278
+ default: string;
279
+ user_editable: boolean;
280
+ template_overridable: boolean;
281
+ planner_settable: boolean;
282
+ affects_decisions: string[];
283
+ affects_slots: string[];
284
+ } | {
285
+ type: "json";
286
+ user_editable: boolean;
287
+ template_overridable: boolean;
288
+ planner_settable: boolean;
289
+ affects_decisions: string[];
290
+ affects_slots: string[];
291
+ default?: unknown;
292
+ }> | undefined;
293
+ preview?: {
294
+ blurb: string;
295
+ intents: ("for_sale" | "for_rent")[];
296
+ types: ("single_family" | "condo_townhome" | "multi_family" | "investment")[];
297
+ demoUrl?: string | null | undefined;
298
+ } | undefined;
299
+ }, {
300
+ key: string;
301
+ name: string;
302
+ deliverable_type: "single_property_website";
303
+ sections: {
304
+ section: string;
305
+ instance_id: string;
306
+ options?: Record<string, unknown> | undefined;
307
+ required?: boolean | undefined;
308
+ locked?: string[] | undefined;
309
+ reorderable?: boolean | undefined;
310
+ }[];
311
+ options?: Record<string, {
312
+ type: "enum";
313
+ values: string[];
314
+ default: string;
315
+ user_editable?: boolean | undefined;
316
+ template_overridable?: boolean | undefined;
317
+ planner_settable?: boolean | undefined;
318
+ affects_decisions?: string[] | undefined;
319
+ affects_slots?: string[] | undefined;
320
+ } | {
321
+ type: "bool";
322
+ default: boolean;
323
+ user_editable?: boolean | undefined;
324
+ template_overridable?: boolean | undefined;
325
+ planner_settable?: boolean | undefined;
326
+ affects_decisions?: string[] | undefined;
327
+ affects_slots?: string[] | undefined;
328
+ } | {
329
+ type: "int";
330
+ default: number;
331
+ user_editable?: boolean | undefined;
332
+ template_overridable?: boolean | undefined;
333
+ planner_settable?: boolean | undefined;
334
+ affects_decisions?: string[] | undefined;
335
+ affects_slots?: string[] | undefined;
336
+ min?: number | undefined;
337
+ max?: number | undefined;
338
+ } | {
339
+ type: "string";
340
+ default: string;
341
+ user_editable?: boolean | undefined;
342
+ template_overridable?: boolean | undefined;
343
+ planner_settable?: boolean | undefined;
344
+ affects_decisions?: string[] | undefined;
345
+ affects_slots?: string[] | undefined;
346
+ } | {
347
+ type: "json";
348
+ default?: unknown;
349
+ user_editable?: boolean | undefined;
350
+ template_overridable?: boolean | undefined;
351
+ planner_settable?: boolean | undefined;
352
+ affects_decisions?: string[] | undefined;
353
+ affects_slots?: string[] | undefined;
354
+ }> | undefined;
355
+ reconcile?: {
356
+ type: "dedup-image";
357
+ min: number;
358
+ from: {
359
+ slot: string;
360
+ section: string;
361
+ };
362
+ into: {
363
+ slot: string;
364
+ section: string;
365
+ };
366
+ predicate_tags: string[];
367
+ }[] | undefined;
368
+ preview?: {
369
+ blurb: string;
370
+ intents: ("for_sale" | "for_rent")[];
371
+ types: ("single_family" | "condo_townhome" | "multi_family" | "investment")[];
372
+ demoUrl?: string | null | undefined;
373
+ } | undefined;
374
+ }>, {
375
+ key: string;
376
+ name: string;
377
+ deliverable_type: "single_property_website";
378
+ sections: {
379
+ options: Record<string, unknown>;
380
+ required: boolean;
381
+ section: string;
382
+ instance_id: string;
383
+ locked: string[];
384
+ reorderable: boolean;
385
+ }[];
386
+ reconcile: {
387
+ type: "dedup-image";
388
+ min: number;
389
+ from: {
390
+ slot: string;
391
+ section: string;
392
+ };
393
+ into: {
394
+ slot: string;
395
+ section: string;
396
+ };
397
+ predicate_tags: string[];
398
+ }[];
399
+ options?: Record<string, {
400
+ type: "enum";
401
+ values: string[];
402
+ default: string;
403
+ user_editable: boolean;
404
+ template_overridable: boolean;
405
+ planner_settable: boolean;
406
+ affects_decisions: string[];
407
+ affects_slots: string[];
408
+ } | {
409
+ type: "bool";
410
+ default: boolean;
411
+ user_editable: boolean;
412
+ template_overridable: boolean;
413
+ planner_settable: boolean;
414
+ affects_decisions: string[];
415
+ affects_slots: string[];
416
+ } | {
417
+ type: "int";
418
+ default: number;
419
+ user_editable: boolean;
420
+ template_overridable: boolean;
421
+ planner_settable: boolean;
422
+ affects_decisions: string[];
423
+ affects_slots: string[];
424
+ min?: number | undefined;
425
+ max?: number | undefined;
426
+ } | {
427
+ type: "string";
428
+ default: string;
429
+ user_editable: boolean;
430
+ template_overridable: boolean;
431
+ planner_settable: boolean;
432
+ affects_decisions: string[];
433
+ affects_slots: string[];
434
+ } | {
435
+ type: "json";
436
+ user_editable: boolean;
437
+ template_overridable: boolean;
438
+ planner_settable: boolean;
439
+ affects_decisions: string[];
440
+ affects_slots: string[];
441
+ default?: unknown;
442
+ }> | undefined;
443
+ preview?: {
444
+ blurb: string;
445
+ intents: ("for_sale" | "for_rent")[];
446
+ types: ("single_family" | "condo_townhome" | "multi_family" | "investment")[];
447
+ demoUrl?: string | null | undefined;
448
+ } | undefined;
449
+ }, {
450
+ key: string;
451
+ name: string;
452
+ deliverable_type: "single_property_website";
453
+ sections: {
454
+ section: string;
455
+ instance_id: string;
456
+ options?: Record<string, unknown> | undefined;
457
+ required?: boolean | undefined;
458
+ locked?: string[] | undefined;
459
+ reorderable?: boolean | undefined;
460
+ }[];
461
+ options?: Record<string, {
462
+ type: "enum";
463
+ values: string[];
464
+ default: string;
465
+ user_editable?: boolean | undefined;
466
+ template_overridable?: boolean | undefined;
467
+ planner_settable?: boolean | undefined;
468
+ affects_decisions?: string[] | undefined;
469
+ affects_slots?: string[] | undefined;
470
+ } | {
471
+ type: "bool";
472
+ default: boolean;
473
+ user_editable?: boolean | undefined;
474
+ template_overridable?: boolean | undefined;
475
+ planner_settable?: boolean | undefined;
476
+ affects_decisions?: string[] | undefined;
477
+ affects_slots?: string[] | undefined;
478
+ } | {
479
+ type: "int";
480
+ default: number;
481
+ user_editable?: boolean | undefined;
482
+ template_overridable?: boolean | undefined;
483
+ planner_settable?: boolean | undefined;
484
+ affects_decisions?: string[] | undefined;
485
+ affects_slots?: string[] | undefined;
486
+ min?: number | undefined;
487
+ max?: number | undefined;
488
+ } | {
489
+ type: "string";
490
+ default: string;
491
+ user_editable?: boolean | undefined;
492
+ template_overridable?: boolean | undefined;
493
+ planner_settable?: boolean | undefined;
494
+ affects_decisions?: string[] | undefined;
495
+ affects_slots?: string[] | undefined;
496
+ } | {
497
+ type: "json";
498
+ default?: unknown;
499
+ user_editable?: boolean | undefined;
500
+ template_overridable?: boolean | undefined;
501
+ planner_settable?: boolean | undefined;
502
+ affects_decisions?: string[] | undefined;
503
+ affects_slots?: string[] | undefined;
504
+ }> | undefined;
505
+ reconcile?: {
506
+ type: "dedup-image";
507
+ min: number;
508
+ from: {
509
+ slot: string;
510
+ section: string;
511
+ };
512
+ into: {
513
+ slot: string;
514
+ section: string;
515
+ };
516
+ predicate_tags: string[];
517
+ }[] | undefined;
518
+ preview?: {
519
+ blurb: string;
520
+ intents: ("for_sale" | "for_rent")[];
521
+ types: ("single_family" | "condo_townhome" | "multi_family" | "investment")[];
522
+ demoUrl?: string | null | undefined;
523
+ } | undefined;
524
+ }>;
525
+ type TemplateManifestShape = z.infer<typeof TemplateManifest>;
526
+ //#endregion
527
+ export { TemplateManifest, TemplateManifestShape };
@@ -0,0 +1,73 @@
1
+ import { OptionDef } from "./section-schema.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/schema/manifest.ts
5
+ const SectionInstance = z.object({
6
+ section: z.string().min(1),
7
+ instance_id: z.string().min(1),
8
+ options: z.record(z.string(), z.unknown()).default({}),
9
+ locked: z.array(z.string()).default([]),
10
+ required: z.boolean().default(false),
11
+ reorderable: z.boolean().default(true)
12
+ }).strict();
13
+ const ReconcileRule = z.object({
14
+ type: z.literal("dedup-image"),
15
+ from: z.object({
16
+ section: z.string(),
17
+ slot: z.string()
18
+ }).strict(),
19
+ into: z.object({
20
+ section: z.string(),
21
+ slot: z.string()
22
+ }).strict(),
23
+ predicate_tags: z.array(z.string().regex(/^[a-z]+:[a-z][a-z0-9-]*$/)).min(1),
24
+ min: z.number().int().nonnegative()
25
+ }).strict();
26
+ const TemplatePreview = z.object({
27
+ blurb: z.string().min(1),
28
+ intents: z.array(z.enum(["for_sale", "for_rent"])),
29
+ types: z.array(z.enum([
30
+ "single_family",
31
+ "condo_townhome",
32
+ "multi_family",
33
+ "investment"
34
+ ])),
35
+ demoUrl: z.string().nullable().optional()
36
+ }).strict();
37
+ const TemplateManifest = z.object({
38
+ key: z.string().min(1),
39
+ name: z.string().min(1),
40
+ deliverable_type: z.enum(["single_property_website"]),
41
+ options: z.record(z.string(), OptionDef).optional(),
42
+ sections: z.array(SectionInstance).min(1),
43
+ reconcile: z.array(ReconcileRule).default([]),
44
+ preview: TemplatePreview.optional()
45
+ }).strict().superRefine((manifest, ctx) => {
46
+ manifest.sections.forEach((inst, idx) => {
47
+ for (const lockedKey of inst.locked) if (!(lockedKey in inst.options)) ctx.addIssue({
48
+ code: z.ZodIssueCode.custom,
49
+ path: [
50
+ "sections",
51
+ idx,
52
+ "locked"
53
+ ],
54
+ message: `Locked option "${lockedKey}" must also appear in this section instance's options.`
55
+ });
56
+ });
57
+ const seen = /* @__PURE__ */ new Set();
58
+ manifest.sections.forEach((inst, idx) => {
59
+ if (seen.has(inst.instance_id)) ctx.addIssue({
60
+ code: z.ZodIssueCode.custom,
61
+ path: [
62
+ "sections",
63
+ idx,
64
+ "instance_id"
65
+ ],
66
+ message: `Duplicate instance_id "${inst.instance_id}".`
67
+ });
68
+ seen.add(inst.instance_id);
69
+ });
70
+ });
71
+
72
+ //#endregion
73
+ export { TemplateManifest };
@@ -0,0 +1,44 @@
1
+ import { ResponsiveImage } from "../contracts/image-descriptor.js";
2
+ //#region src/schema/property-facts.d.ts
3
+ type Coordinates = {
4
+ lat: number;
5
+ lng: number;
6
+ };
7
+ type FloorplanAssignment = {
8
+ id: string;
9
+ upload_id?: string;
10
+ url: string;
11
+ alt: string;
12
+ floor_label: string | null;
13
+ position: number;
14
+ responsive?: ResponsiveImage | null;
15
+ };
16
+ type UnitRow = {
17
+ unit_id: string;
18
+ unit_label: string | null;
19
+ beds: number | null;
20
+ baths: number | null;
21
+ sqft: number | null;
22
+ price: string | null;
23
+ notes: string | null;
24
+ description: string | null;
25
+ features: string[];
26
+ position: number;
27
+ floor_plans: FloorplanAssignment[];
28
+ };
29
+ type PropertyFacts = {
30
+ address: string;
31
+ address_lines?: string[];
32
+ lat?: number | null;
33
+ lon?: number | null;
34
+ coordinates?: Coordinates | null;
35
+ listing_intent: "for_sale" | "for_rent";
36
+ status: string | null;
37
+ property_type: "single_family" | "condo_townhome" | "multi_family" | "investment";
38
+ year_built: number | null;
39
+ lot_size: string | null;
40
+ units: UnitRow[];
41
+ contacts?: Array<Record<string, unknown>>;
42
+ };
43
+ //#endregion
44
+ export { Coordinates, FloorplanAssignment, PropertyFacts, UnitRow };
@@ -0,0 +1,11 @@
1
+ import { TransformInput } from "../contracts/transforms.js";
2
+ //#region src/schema/resolve-variants.d.ts
3
+ type VariantSelectorFn = (input: TransformInput) => string;
4
+ type VariantsMeta = Record<string, {
5
+ cases: string[];
6
+ default: string;
7
+ select: VariantSelectorFn;
8
+ }>;
9
+ declare function makeResolveVariants(meta: VariantsMeta | undefined): (input: TransformInput) => Record<string, string>;
10
+ //#endregion
11
+ export { VariantSelectorFn, VariantsMeta, makeResolveVariants };
@@ -0,0 +1,15 @@
1
+ //#region src/schema/resolve-variants.ts
2
+ function makeResolveVariants(meta) {
3
+ const axes = meta ?? {};
4
+ return (input) => {
5
+ const out = {};
6
+ for (const [axis, def] of Object.entries(axes)) {
7
+ const value = def.select(input);
8
+ out[axis] = def.cases.includes(value) ? value : def.default;
9
+ }
10
+ return out;
11
+ };
12
+ }
13
+
14
+ //#endregion
15
+ export { makeResolveVariants };