@homepages/template-kit 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/README.md +38 -27
- package/dist/base.css +6 -4
- package/dist/cli/dev/fill-state.js +5 -3
- package/dist/cli/link/overlay.js +1 -1
- package/dist/cli/new/scaffold/template/sections/hero/fixtures.ts +7 -7
- package/dist/contracts/slot-catalog.d.ts +2 -2
- package/dist/contracts/slot-catalog.js +3 -1
- package/dist/eslint/rules/no-raw-element.js +3 -2
- package/dist/fixtures/helpers.d.ts +23 -0
- package/dist/fixtures/helpers.js +50 -0
- package/dist/fixtures/sample-property.d.ts +7 -17
- package/dist/fixtures/sample-property.js +179 -57
- package/dist/fixtures/scenario.d.ts +20 -0
- package/dist/fixtures/scenarios/for-rent-condo.d.ts +5 -0
- package/dist/fixtures/scenarios/for-rent-condo.js +364 -0
- package/dist/fixtures/scenarios/index.d.ts +8 -0
- package/dist/fixtures/scenarios/index.js +13 -0
- package/dist/fixtures/scenarios/luxury-multi-unit.d.ts +5 -0
- package/dist/fixtures/scenarios/luxury-multi-unit.js +19 -0
- package/dist/fixtures/scenarios/sparse-single-family.d.ts +5 -0
- package/dist/fixtures/scenarios/sparse-single-family.js +233 -0
- package/dist/fixtures.d.ts +8 -2
- package/dist/fixtures.js +7 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/island-runtime.js +22 -7
- package/dist/package.js +1 -1
- package/dist/primitives/Image.d.ts +1 -1
- package/dist/primitives/Video.d.ts +38 -0
- package/dist/primitives/Video.js +63 -0
- package/dist/primitives/index.d.ts +2 -1
- package/dist/rules/registry.js +3 -3
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/runtime-values.d.ts +20 -1
- package/dist/schema/section-props.d.ts +8 -1
- package/dist/schema/section-schema.d.ts +2 -2
- package/dist/schema/slot-types.d.ts +15 -1
- package/dist/schema/slot-types.js +34 -0
- package/dist/schema/synthesize-nullable.js +1 -0
- package/{docs → guide}/INDEX.md +7 -6
- package/{docs → guide}/check.md +2 -2
- package/{docs → guide}/islands.md +6 -1
- package/{docs → guide}/llms.txt +34 -14
- package/{docs → guide}/overview.md +4 -4
- package/{docs → guide}/pack.md +2 -2
- package/{docs → guide}/primitives.md +59 -11
- package/{docs → guide}/recipes/INDEX.md +1 -0
- package/{docs → guide}/recipes/collection-slot.md +10 -8
- package/guide/recipes/fixture-states.md +109 -0
- package/{docs → guide}/recipes/image-slot-crop.md +5 -3
- package/guide/recipes/pick-a-scenario.md +119 -0
- package/{docs → guide}/rules/INDEX.md +2 -2
- package/{docs → guide}/rules/fixtures-invalid.md +2 -2
- package/{docs → guide}/rules/no-raw-element.md +13 -8
- package/{docs → guide}/rules/render-invariant.md +4 -3
- package/{docs → guide}/schema-system.md +97 -16
- package/{docs → guide}/theme-and-css.md +3 -2
- package/guide/upgrading.md +61 -0
- package/{docs → guide}/vocabulary.md +3 -1
- package/package.json +8 -3
- package/docs/recipes/fixture-states.md +0 -68
- /package/{docs → guide}/assets.md +0 -0
- /package/{docs → guide}/dev.md +0 -0
- /package/{docs → guide}/eslint.md +0 -0
- /package/{docs → guide}/new.md +0 -0
- /package/{docs → guide}/quickstart.md +0 -0
- /package/{docs → guide}/recipes/bind-property-fact.md +0 -0
- /package/{docs → guide}/recipes/fill-spec-decision.md +0 -0
- /package/{docs → guide}/recipes/interactive-island.md +0 -0
- /package/{docs → guide}/recipes/organize-section-folder.md +0 -0
- /package/{docs → guide}/recipes/prepare-submission.md +0 -0
- /package/{docs → guide}/recipes/second-template.md +0 -0
- /package/{docs → guide}/recipes/select-slot.md +0 -0
- /package/{docs → guide}/recipes/static-asset.md +0 -0
- /package/{docs → guide}/recipes/third-party-package.md +0 -0
- /package/{docs → guide}/rules/audit-severity.md +0 -0
- /package/{docs → guide}/rules/bundle-binary-asset.md +0 -0
- /package/{docs → guide}/rules/bundle-incomplete.md +0 -0
- /package/{docs → guide}/rules/css-reason.md +0 -0
- /package/{docs → guide}/rules/determinism-drift.md +0 -0
- /package/{docs → guide}/rules/image-bare-needs-reason.md +0 -0
- /package/{docs → guide}/rules/license-denied.md +0 -0
- /package/{docs → guide}/rules/lockfile-missing.md +0 -0
- /package/{docs → guide}/rules/lockfile-stale.md +0 -0
- /package/{docs → guide}/rules/manifest-invalid.md +0 -0
- /package/{docs → guide}/rules/missing-slot-marker.md +0 -0
- /package/{docs → guide}/rules/no-bare-css-import.md +0 -0
- /package/{docs → guide}/rules/no-client-directive-in-contract.md +0 -0
- /package/{docs → guide}/rules/no-client-runtime-in-server.md +0 -0
- /package/{docs → guide}/rules/no-css-import-from-render-path.md +0 -0
- /package/{docs → guide}/rules/no-hex.md +0 -0
- /package/{docs → guide}/rules/no-inline-style.md +0 -0
- /package/{docs → guide}/rules/no-nondeterminism.md +0 -0
- /package/{docs → guide}/rules/no-templates.md +0 -0
- /package/{docs → guide}/rules/parse-error.md +0 -0
- /package/{docs → guide}/rules/props-from-schema.md +0 -0
- /package/{docs → guide}/rules/schema-invalid.md +0 -0
- /package/{docs → guide}/rules/serializable-island-props.md +0 -0
- /package/{docs → guide}/rules/server-vs-client.md +0 -0
- /package/{docs → guide}/rules/sidebar-order.md +0 -0
- /package/{docs → guide}/rules/single-react.md +0 -0
- /package/{docs → guide}/rules/size-assets.md +0 -0
- /package/{docs → guide}/rules/size-island-bundle.md +0 -0
- /package/{docs → guide}/rules/size-renderer-bundle.md +0 -0
- /package/{docs → guide}/rules/size-section-css.md +0 -0
- /package/{docs → guide}/rules/slot-group-marker.md +0 -0
- /package/{docs → guide}/rules/slot-marker-literal.md +0 -0
- /package/{docs → guide}/rules/typecheck.md +0 -0
- /package/{docs → guide}/rules/unlayered-fence.md +0 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { mkResponsive } from "../sample-property.js";
|
|
2
|
+
|
|
3
|
+
//#region src/fixtures/scenarios/for-rent-condo.ts
|
|
4
|
+
const PHOTO_BASE = "https://example.invalid/photos/pearl-street";
|
|
5
|
+
const photos = [
|
|
6
|
+
{
|
|
7
|
+
id: "ph_01",
|
|
8
|
+
url: `${PHOTO_BASE}/01-exterior-front.jpg`,
|
|
9
|
+
alt: "Brick townhome exterior with a street-facing entry stoop.",
|
|
10
|
+
tags: {
|
|
11
|
+
room: "exterior-front",
|
|
12
|
+
category: "exterior"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "ph_02",
|
|
17
|
+
url: `${PHOTO_BASE}/02-living.jpg`,
|
|
18
|
+
alt: "Living room with tall windows and exposed-beam ceiling.",
|
|
19
|
+
tags: {
|
|
20
|
+
room: "living",
|
|
21
|
+
category: "interior"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "ph_03",
|
|
26
|
+
url: `${PHOTO_BASE}/03-dining.jpg`,
|
|
27
|
+
alt: "Open dining area beside the kitchen island.",
|
|
28
|
+
tags: {
|
|
29
|
+
room: "dining",
|
|
30
|
+
category: "interior"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "ph_04",
|
|
35
|
+
url: `${PHOTO_BASE}/04-kitchen.jpg`,
|
|
36
|
+
alt: "Kitchen with stainless appliances and quartz counters.",
|
|
37
|
+
tags: {
|
|
38
|
+
room: "kitchen",
|
|
39
|
+
category: "interior"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "ph_05",
|
|
44
|
+
url: `${PHOTO_BASE}/05-primary-bedroom.jpg`,
|
|
45
|
+
alt: "Primary bedroom with a walk-in closet.",
|
|
46
|
+
tags: {
|
|
47
|
+
room: "bedroom",
|
|
48
|
+
category: "interior"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "ph_06",
|
|
53
|
+
url: `${PHOTO_BASE}/06-second-bedroom.jpg`,
|
|
54
|
+
alt: "Second bedroom used as a home office.",
|
|
55
|
+
tags: {
|
|
56
|
+
room: "bedroom",
|
|
57
|
+
category: "interior"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: "ph_07",
|
|
62
|
+
url: `${PHOTO_BASE}/07-primary-bath.jpg`,
|
|
63
|
+
alt: "Primary bath with a glass-enclosed shower.",
|
|
64
|
+
tags: {
|
|
65
|
+
room: "bath",
|
|
66
|
+
category: "interior"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "ph_08",
|
|
71
|
+
url: `${PHOTO_BASE}/08-powder-room.jpg`,
|
|
72
|
+
alt: "Powder room off the main hallway.",
|
|
73
|
+
tags: {
|
|
74
|
+
room: "bath",
|
|
75
|
+
category: "interior"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "ph_09",
|
|
80
|
+
url: `${PHOTO_BASE}/09-balcony.jpg`,
|
|
81
|
+
alt: "Private balcony overlooking a landscaped courtyard.",
|
|
82
|
+
tags: {
|
|
83
|
+
room: "balcony",
|
|
84
|
+
category: "exterior"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "ph_10",
|
|
89
|
+
url: `${PHOTO_BASE}/10-rooftop-deck.jpg`,
|
|
90
|
+
alt: "Shared rooftop deck with skyline views.",
|
|
91
|
+
tags: {
|
|
92
|
+
room: "rooftop",
|
|
93
|
+
category: "exterior"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
];
|
|
97
|
+
const FP_BASE = "https://example.invalid/floorplans/pearl-street";
|
|
98
|
+
const units = [{
|
|
99
|
+
unit_id: "unit_04",
|
|
100
|
+
unit_label: "Unit 4",
|
|
101
|
+
beds: 2,
|
|
102
|
+
baths: 2.5,
|
|
103
|
+
sqft: 1380,
|
|
104
|
+
price: "2895",
|
|
105
|
+
notes: "Available Aug 1. One year lease minimum.",
|
|
106
|
+
description: "A two-story townhome-style condo with tall windows, exposed-beam ceilings, and an open kitchen-to-dining flow. The primary suite occupies the upper floor alongside a second bedroom that works well as a home office, while a private balcony off the living room overlooks a landscaped courtyard. In-unit laundry and a deeded parking space round out the layout.",
|
|
107
|
+
features: [
|
|
108
|
+
"Exposed-beam ceilings",
|
|
109
|
+
"Quartz kitchen counters",
|
|
110
|
+
"Private balcony",
|
|
111
|
+
"In-unit washer & dryer",
|
|
112
|
+
"Deeded parking space"
|
|
113
|
+
],
|
|
114
|
+
position: 0,
|
|
115
|
+
floor_plans: [{
|
|
116
|
+
id: "fp_unit04_main",
|
|
117
|
+
url: `${FP_BASE}/unit04-main.png`,
|
|
118
|
+
alt: "Unit 4 floor plan — main floor (living, dining, kitchen).",
|
|
119
|
+
floor_label: "Main Floor",
|
|
120
|
+
position: 0,
|
|
121
|
+
responsive: mkResponsive(`${FP_BASE}/unit04-main.png`, 1024, 1024)
|
|
122
|
+
}, {
|
|
123
|
+
id: "fp_unit04_upper",
|
|
124
|
+
url: `${FP_BASE}/unit04-upper.png`,
|
|
125
|
+
alt: "Unit 4 floor plan — upper floor (bedrooms, baths).",
|
|
126
|
+
floor_label: "Upper Floor",
|
|
127
|
+
position: 1,
|
|
128
|
+
responsive: mkResponsive(`${FP_BASE}/unit04-upper.png`, 1024, 1024)
|
|
129
|
+
}]
|
|
130
|
+
}];
|
|
131
|
+
const pois = [
|
|
132
|
+
{
|
|
133
|
+
id: "poi_r1",
|
|
134
|
+
category: "restaurant",
|
|
135
|
+
name: "The Cherry Creek Grill",
|
|
136
|
+
place_id: "gplace_cherry_creek_grill",
|
|
137
|
+
address: "770 Pearl Street, Denver, CO 80203",
|
|
138
|
+
distance: "0.2 mi",
|
|
139
|
+
distance_m: 320,
|
|
140
|
+
lat: 39.7251,
|
|
141
|
+
lng: -104.9808,
|
|
142
|
+
url: "https://example.invalid/poi/cherry-creek-grill"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: "poi_r2",
|
|
146
|
+
category: "restaurant",
|
|
147
|
+
name: "Uptown Tavern & Kitchen",
|
|
148
|
+
place_id: "gplace_uptown_tavern",
|
|
149
|
+
address: "1600 Logan Street, Denver, CO 80203",
|
|
150
|
+
distance: "0.5 mi",
|
|
151
|
+
distance_m: 800,
|
|
152
|
+
lat: 39.7318,
|
|
153
|
+
lng: -104.9761,
|
|
154
|
+
url: "https://example.invalid/poi/uptown-tavern"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "poi_p1",
|
|
158
|
+
category: "park",
|
|
159
|
+
name: "Governor's Park",
|
|
160
|
+
place_id: "gplace_governors_park",
|
|
161
|
+
address: "700 Logan Street, Denver, CO 80203",
|
|
162
|
+
distance: "0.2 mi",
|
|
163
|
+
distance_m: 320,
|
|
164
|
+
lat: 39.7282,
|
|
165
|
+
lng: -104.9782,
|
|
166
|
+
url: "https://example.invalid/poi/governors-park"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
id: "poi_t1",
|
|
170
|
+
category: "transit",
|
|
171
|
+
name: "RTD Bus Stop – 8th & Pearl",
|
|
172
|
+
place_id: "gplace_bus_8th_pearl",
|
|
173
|
+
address: "800 E 8th Avenue, Denver, CO 80203",
|
|
174
|
+
distance: "0.1 mi",
|
|
175
|
+
distance_m: 160,
|
|
176
|
+
lat: 39.7273,
|
|
177
|
+
lng: -104.9793,
|
|
178
|
+
url: "https://example.invalid/poi/bus-8th-pearl"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: "poi_t2",
|
|
182
|
+
category: "transit",
|
|
183
|
+
name: "Colfax & Broadway RTD Hub",
|
|
184
|
+
place_id: "gplace_colfax_broadway_hub",
|
|
185
|
+
address: "1490 Broadway, Denver, CO 80202",
|
|
186
|
+
distance: "1.2 mi",
|
|
187
|
+
distance_m: 1930,
|
|
188
|
+
lat: 39.7402,
|
|
189
|
+
lng: -104.9878,
|
|
190
|
+
url: "https://example.invalid/poi/colfax-broadway-hub"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: "poi_s1",
|
|
194
|
+
category: "shopping",
|
|
195
|
+
name: "Speer Corner Market",
|
|
196
|
+
place_id: "gplace_speer_corner_market",
|
|
197
|
+
address: "900 E 6th Avenue, Denver, CO 80203",
|
|
198
|
+
distance: "0.3 mi",
|
|
199
|
+
distance_m: 480,
|
|
200
|
+
lat: 39.7258,
|
|
201
|
+
lng: -104.977,
|
|
202
|
+
url: "https://example.invalid/poi/speer-corner-market"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: "poi_c1",
|
|
206
|
+
category: "coffee",
|
|
207
|
+
name: "Pearl Street Coffee Roasters",
|
|
208
|
+
place_id: "gplace_pearl_street_coffee",
|
|
209
|
+
address: "780 Pearl Street, Denver, CO 80203",
|
|
210
|
+
distance: "0.1 mi",
|
|
211
|
+
distance_m: 160,
|
|
212
|
+
lat: 39.7283,
|
|
213
|
+
lng: -104.9814,
|
|
214
|
+
url: "https://example.invalid/poi/pearl-street-coffee"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: "poi_f1",
|
|
218
|
+
category: "fitness",
|
|
219
|
+
name: "Governor's Park Fitness Studio",
|
|
220
|
+
place_id: "gplace_governors_park_fitness",
|
|
221
|
+
address: "650 Corona Street, Denver, CO 80218",
|
|
222
|
+
distance: "0.2 mi",
|
|
223
|
+
distance_m: 320,
|
|
224
|
+
lat: 39.7294,
|
|
225
|
+
lng: -104.9795,
|
|
226
|
+
url: "https://example.invalid/poi/governors-park-fitness"
|
|
227
|
+
}
|
|
228
|
+
];
|
|
229
|
+
const amenities = [
|
|
230
|
+
{
|
|
231
|
+
id: "parking",
|
|
232
|
+
label: "Parking",
|
|
233
|
+
icon: "square-parking",
|
|
234
|
+
description: "One deeded parking space included.",
|
|
235
|
+
items: [
|
|
236
|
+
"Deeded off-street space",
|
|
237
|
+
"Guest parking permits available",
|
|
238
|
+
"Bike storage room"
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: "outdoors",
|
|
243
|
+
label: "Outdoor Space",
|
|
244
|
+
icon: "trees",
|
|
245
|
+
description: "Private balcony plus a shared rooftop deck.",
|
|
246
|
+
items: [
|
|
247
|
+
"Private balcony",
|
|
248
|
+
"Shared rooftop deck",
|
|
249
|
+
"Landscaped courtyard"
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
id: "laundry",
|
|
254
|
+
label: "In-Unit Laundry",
|
|
255
|
+
icon: "washing-machine",
|
|
256
|
+
description: "Full-size washer and dryer in the unit.",
|
|
257
|
+
items: ["Full-size stacked washer/dryer", "Utility closet storage"]
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
id: "finishes",
|
|
261
|
+
label: "Interior Finishes",
|
|
262
|
+
icon: "swatch-book",
|
|
263
|
+
description: "Updated kitchen and exposed-beam ceilings.",
|
|
264
|
+
items: [
|
|
265
|
+
"Quartz kitchen counters",
|
|
266
|
+
"Exposed-beam ceilings",
|
|
267
|
+
"Engineered hardwood floors"
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
];
|
|
271
|
+
const contacts = [{
|
|
272
|
+
library_item_id: "li_okafor",
|
|
273
|
+
category: "contact",
|
|
274
|
+
type: "agent",
|
|
275
|
+
position: 0,
|
|
276
|
+
fields: {
|
|
277
|
+
display_name: "Ngozi Okafor",
|
|
278
|
+
title: "Leasing Agent",
|
|
279
|
+
bio: "Ngozi Okafor leases condos and townhomes across Denver's Speer, Uptown, and Governor's Park neighborhoods, with a focus on responsive turnarounds for one-year leases and relocation clients.",
|
|
280
|
+
headshot_url: "https://example.invalid/contacts/ngozi-okafor.jpg",
|
|
281
|
+
website_url: "https://bluebird-realty-group.example.invalid",
|
|
282
|
+
email: "ngozi@homepages.io",
|
|
283
|
+
phone: "(720) 555-0173",
|
|
284
|
+
address: "845 Pearl Street, Denver, CO 80203",
|
|
285
|
+
org_name: "Bluebird Realty Group",
|
|
286
|
+
logo_light: "https://example.invalid/brand/bluebird-logo-light.svg",
|
|
287
|
+
logo_dark: "https://example.invalid/brand/bluebird-logo-dark.svg",
|
|
288
|
+
socials: [{
|
|
289
|
+
platform: "instagram",
|
|
290
|
+
url: "https://instagram.com/ngozileases/"
|
|
291
|
+
}]
|
|
292
|
+
}
|
|
293
|
+
}, {
|
|
294
|
+
library_item_id: "li_bianchi",
|
|
295
|
+
category: "contact",
|
|
296
|
+
type: "agent",
|
|
297
|
+
position: 1,
|
|
298
|
+
fields: {
|
|
299
|
+
display_name: "Marco Bianchi",
|
|
300
|
+
title: "Property Manager",
|
|
301
|
+
bio: "Marco Bianchi manages day-to-day operations and maintenance for the Pearl Street townhome portfolio, coordinating move-ins, repairs, and lease renewals for residents.",
|
|
302
|
+
headshot_url: "https://example.invalid/contacts/marco-bianchi.jpg",
|
|
303
|
+
website_url: "https://bluebird-realty-group.example.invalid",
|
|
304
|
+
email: "marco@homepages.io",
|
|
305
|
+
phone: "(720) 555-0184",
|
|
306
|
+
address: "845 Pearl Street, Denver, CO 80203",
|
|
307
|
+
org_name: "Bluebird Realty Group",
|
|
308
|
+
logo_light: "https://example.invalid/brand/bluebird-logo-light.svg",
|
|
309
|
+
logo_dark: "https://example.invalid/brand/bluebird-logo-dark.svg",
|
|
310
|
+
socials: [{
|
|
311
|
+
platform: "linkedin",
|
|
312
|
+
url: "https://linkedin.com/in/marco-bianchi-pm/"
|
|
313
|
+
}]
|
|
314
|
+
}
|
|
315
|
+
}];
|
|
316
|
+
const facts = {
|
|
317
|
+
address: "845 Pearl Street, Denver, CO 80203",
|
|
318
|
+
address_lines: ["845 Pearl Street", "Denver, CO 80203"],
|
|
319
|
+
coordinates: {
|
|
320
|
+
lat: 39.7273,
|
|
321
|
+
lng: -104.9808
|
|
322
|
+
},
|
|
323
|
+
listing_intent: "for_rent",
|
|
324
|
+
status: "For Rent",
|
|
325
|
+
property_type: "condo_townhome",
|
|
326
|
+
year_built: 1998,
|
|
327
|
+
lot_size: "0.04 acres",
|
|
328
|
+
units,
|
|
329
|
+
contacts: contacts.map((c, i) => ({
|
|
330
|
+
id: i === 0 ? "primary" : c.library_item_id,
|
|
331
|
+
primary: i === 0,
|
|
332
|
+
name: c.fields.display_name,
|
|
333
|
+
title: c.fields.title,
|
|
334
|
+
bio: c.fields.bio,
|
|
335
|
+
email: c.fields.email,
|
|
336
|
+
phone: c.fields.phone,
|
|
337
|
+
address: c.fields.address,
|
|
338
|
+
website_url: c.fields.website_url,
|
|
339
|
+
avatar_upload_id: `upload_headshot_${c.library_item_id}`,
|
|
340
|
+
org_name: c.fields.org_name,
|
|
341
|
+
logo_light_upload_id: c.fields.logo_light ? `upload_logo_light_${c.library_item_id}` : null,
|
|
342
|
+
logo_dark_upload_id: c.fields.logo_dark ? `upload_logo_dark_${c.library_item_id}` : null,
|
|
343
|
+
instagram_url: c.fields.socials.find((s) => s.platform === "instagram")?.url ?? null,
|
|
344
|
+
linkedin_url: c.fields.socials.find((s) => s.platform === "linkedin")?.url ?? null,
|
|
345
|
+
x_url: c.fields.socials.find((s) => s.platform === "x")?.url ?? null,
|
|
346
|
+
facebook_url: c.fields.socials.find((s) => s.platform === "facebook")?.url ?? null
|
|
347
|
+
}))
|
|
348
|
+
};
|
|
349
|
+
const forRentCondo = {
|
|
350
|
+
key: "forRentCondo",
|
|
351
|
+
label: "For-rent condo/townhome",
|
|
352
|
+
facts,
|
|
353
|
+
photos,
|
|
354
|
+
pois,
|
|
355
|
+
amenities,
|
|
356
|
+
contacts,
|
|
357
|
+
media: {
|
|
358
|
+
video_url: "https://vimeo.com/128373708",
|
|
359
|
+
tour_3d_url: null
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
//#endregion
|
|
364
|
+
export { forRentCondo };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Scenario, ScenarioKey } from "../scenario.js";
|
|
2
|
+
import { forRentCondo } from "./for-rent-condo.js";
|
|
3
|
+
import { luxuryMultiUnit } from "./luxury-multi-unit.js";
|
|
4
|
+
import { sparseSingleFamily } from "./sparse-single-family.js";
|
|
5
|
+
//#region src/fixtures/scenarios/index.d.ts
|
|
6
|
+
declare const scenarios: Record<ScenarioKey, Scenario>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { forRentCondo, luxuryMultiUnit, scenarios, sparseSingleFamily };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { forRentCondo } from "./for-rent-condo.js";
|
|
2
|
+
import { luxuryMultiUnit } from "./luxury-multi-unit.js";
|
|
3
|
+
import { sparseSingleFamily } from "./sparse-single-family.js";
|
|
4
|
+
|
|
5
|
+
//#region src/fixtures/scenarios/index.ts
|
|
6
|
+
const scenarios = {
|
|
7
|
+
luxuryMultiUnit,
|
|
8
|
+
sparseSingleFamily,
|
|
9
|
+
forRentCondo
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { forRentCondo, luxuryMultiUnit, scenarios, sparseSingleFamily };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { allPhotos, sampleAmenities, sampleContacts, samplePois, sampleProperty } from "../sample-property.js";
|
|
2
|
+
|
|
3
|
+
//#region src/fixtures/scenarios/luxury-multi-unit.ts
|
|
4
|
+
const luxuryMultiUnit = {
|
|
5
|
+
key: "luxuryMultiUnit",
|
|
6
|
+
label: "Luxury multi-unit (for sale)",
|
|
7
|
+
facts: sampleProperty,
|
|
8
|
+
photos: allPhotos,
|
|
9
|
+
pois: samplePois,
|
|
10
|
+
amenities: sampleAmenities,
|
|
11
|
+
contacts: sampleContacts,
|
|
12
|
+
media: {
|
|
13
|
+
video_url: "https://vimeo.com/76979871",
|
|
14
|
+
tour_3d_url: "https://my.matterport.com/show/?m=SxQL3iGyoDo"
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { luxuryMultiUnit };
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { mkResponsive } from "../sample-property.js";
|
|
2
|
+
|
|
3
|
+
//#region src/fixtures/scenarios/sparse-single-family.ts
|
|
4
|
+
const PHOTO_BASE = "https://example.invalid/photos/tuscan-road";
|
|
5
|
+
const photos = [
|
|
6
|
+
{
|
|
7
|
+
id: "ph_01",
|
|
8
|
+
url: `${PHOTO_BASE}/01-exterior-front.jpg`,
|
|
9
|
+
alt: "Center-hall colonial facade with a covered front porch.",
|
|
10
|
+
tags: {
|
|
11
|
+
room: "exterior-front",
|
|
12
|
+
category: "exterior"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: "ph_02",
|
|
17
|
+
url: `${PHOTO_BASE}/02-living.jpg`,
|
|
18
|
+
alt: "Living room with a bay window and original hardwood floors.",
|
|
19
|
+
tags: {
|
|
20
|
+
room: "living",
|
|
21
|
+
category: "interior"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "ph_03",
|
|
26
|
+
url: `${PHOTO_BASE}/03-kitchen.jpg`,
|
|
27
|
+
alt: "Updated kitchen with white shaker cabinets and butcher-block counters.",
|
|
28
|
+
tags: {
|
|
29
|
+
room: "kitchen",
|
|
30
|
+
category: "interior"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "ph_04",
|
|
35
|
+
url: `${PHOTO_BASE}/04-bedroom.jpg`,
|
|
36
|
+
alt: "Primary bedroom with double-hung windows and a ceiling fan.",
|
|
37
|
+
tags: {
|
|
38
|
+
room: "bedroom",
|
|
39
|
+
category: "interior"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: "ph_05",
|
|
44
|
+
url: `${PHOTO_BASE}/05-backyard.jpg`,
|
|
45
|
+
alt: "Fenced backyard with a paver patio and mature shade trees.",
|
|
46
|
+
tags: {
|
|
47
|
+
room: "backyard",
|
|
48
|
+
category: "exterior"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
const floorplanUrl = `https://example.invalid/floorplans/tuscan-road/main-floor.png`;
|
|
53
|
+
const units = [{
|
|
54
|
+
unit_id: "unit_01",
|
|
55
|
+
unit_label: null,
|
|
56
|
+
beds: 3,
|
|
57
|
+
baths: 2,
|
|
58
|
+
sqft: 1620,
|
|
59
|
+
price: "459000",
|
|
60
|
+
notes: "Move-in ready, updated kitchen.",
|
|
61
|
+
description: "A classic center-hall colonial with an updated kitchen and original hardwood floors throughout. The sun-filled living room opens to a formal dining room, while three bedrooms and a renovated bath fill the second floor. A fenced backyard patio completes the home.",
|
|
62
|
+
features: [
|
|
63
|
+
"Updated kitchen",
|
|
64
|
+
"Original hardwood floors",
|
|
65
|
+
"Fenced backyard patio"
|
|
66
|
+
],
|
|
67
|
+
position: 0,
|
|
68
|
+
floor_plans: [{
|
|
69
|
+
id: "fp_main",
|
|
70
|
+
url: floorplanUrl,
|
|
71
|
+
alt: "Full-house floor plan — first and second floor.",
|
|
72
|
+
floor_label: null,
|
|
73
|
+
position: 0,
|
|
74
|
+
responsive: mkResponsive(floorplanUrl, 1024, 1024)
|
|
75
|
+
}]
|
|
76
|
+
}];
|
|
77
|
+
const pois = [
|
|
78
|
+
{
|
|
79
|
+
id: "poi_r1",
|
|
80
|
+
category: "restaurant",
|
|
81
|
+
name: "Maplewood Diner",
|
|
82
|
+
place_id: "gplace_maplewood_diner",
|
|
83
|
+
address: "1712 Springfield Ave, Maplewood, NJ 07040",
|
|
84
|
+
distance: "0.3 mi",
|
|
85
|
+
distance_m: 480,
|
|
86
|
+
lat: 40.7291,
|
|
87
|
+
lng: -74.2771,
|
|
88
|
+
url: "https://example.invalid/poi/maplewood-diner"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "poi_r2",
|
|
92
|
+
category: "restaurant",
|
|
93
|
+
name: "Due Fratelli Ristorante",
|
|
94
|
+
place_id: "gplace_due_fratelli",
|
|
95
|
+
address: "195 Maplewood Ave, Maplewood, NJ 07040",
|
|
96
|
+
distance: "0.5 mi",
|
|
97
|
+
distance_m: 800,
|
|
98
|
+
lat: 40.7349,
|
|
99
|
+
lng: -74.2677,
|
|
100
|
+
url: "https://example.invalid/poi/due-fratelli"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: "poi_p1",
|
|
104
|
+
category: "park",
|
|
105
|
+
name: "South Mountain Reservation",
|
|
106
|
+
place_id: "gplace_south_mountain_reservation",
|
|
107
|
+
address: "S Orange Ave, Maplewood, NJ 07040",
|
|
108
|
+
distance: "0.6 mi",
|
|
109
|
+
distance_m: 970,
|
|
110
|
+
lat: 40.7275,
|
|
111
|
+
lng: -74.2825,
|
|
112
|
+
url: "https://example.invalid/poi/south-mountain-reservation"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
id: "poi_t1",
|
|
116
|
+
category: "transit",
|
|
117
|
+
name: "Maplewood Station (NJ Transit)",
|
|
118
|
+
place_id: "gplace_maplewood_station",
|
|
119
|
+
address: "1 Durand Rd, Maplewood, NJ 07040",
|
|
120
|
+
distance: "0.4 mi",
|
|
121
|
+
distance_m: 640,
|
|
122
|
+
lat: 40.7345,
|
|
123
|
+
lng: -74.2693,
|
|
124
|
+
url: "https://example.invalid/poi/maplewood-station"
|
|
125
|
+
}
|
|
126
|
+
];
|
|
127
|
+
const amenities = [
|
|
128
|
+
{
|
|
129
|
+
id: "parking",
|
|
130
|
+
label: "Parking",
|
|
131
|
+
icon: "square-parking",
|
|
132
|
+
description: "Private driveway, no permit needed.",
|
|
133
|
+
items: [
|
|
134
|
+
"Two-car driveway",
|
|
135
|
+
"Street parking permitted",
|
|
136
|
+
"No HOA restrictions"
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: "outdoors",
|
|
141
|
+
label: "Outdoor Space",
|
|
142
|
+
icon: "trees",
|
|
143
|
+
description: "Fenced yard with a covered patio.",
|
|
144
|
+
items: [
|
|
145
|
+
"Fenced backyard",
|
|
146
|
+
"Paver patio",
|
|
147
|
+
"Mature shade trees"
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: "finishes",
|
|
152
|
+
label: "Interior Finishes",
|
|
153
|
+
icon: "swatch-book",
|
|
154
|
+
description: "Updated kitchen and refinished floors.",
|
|
155
|
+
items: [
|
|
156
|
+
"Shaker cabinets",
|
|
157
|
+
"Butcher-block counters",
|
|
158
|
+
"Refinished hardwood floors"
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
];
|
|
162
|
+
const contacts = [{
|
|
163
|
+
library_item_id: "li_chandran",
|
|
164
|
+
category: "contact",
|
|
165
|
+
type: "agent",
|
|
166
|
+
position: 0,
|
|
167
|
+
fields: {
|
|
168
|
+
display_name: "Priya Chandran",
|
|
169
|
+
title: "Owner/Broker",
|
|
170
|
+
bio: "Priya Chandran is a solo independent broker serving Maplewood and the surrounding South Orange Valley towns. She handles every listing personally, from staging through closing, with a focus on single-family colonials and first-time sellers.",
|
|
171
|
+
headshot_url: "https://example.invalid/contacts/priya-chandran.jpg",
|
|
172
|
+
website_url: "https://priya-chandran-realty.example.invalid",
|
|
173
|
+
email: "priya@homepages.io",
|
|
174
|
+
phone: "(973) 555-0148",
|
|
175
|
+
address: "1620 Springfield Ave, Maplewood, NJ 07040",
|
|
176
|
+
org_name: "Priya Chandran Realty",
|
|
177
|
+
logo_light: null,
|
|
178
|
+
logo_dark: null,
|
|
179
|
+
socials: [{
|
|
180
|
+
platform: "instagram",
|
|
181
|
+
url: "https://instagram.com/priyachandranrealty/"
|
|
182
|
+
}]
|
|
183
|
+
}
|
|
184
|
+
}];
|
|
185
|
+
const facts = {
|
|
186
|
+
address: "212 Tuscan Road, Maplewood, NJ 07040",
|
|
187
|
+
address_lines: ["212 Tuscan Road", "Maplewood, NJ 07040"],
|
|
188
|
+
coordinates: {
|
|
189
|
+
lat: 40.7315,
|
|
190
|
+
lng: -74.2739
|
|
191
|
+
},
|
|
192
|
+
listing_intent: "for_sale",
|
|
193
|
+
status: "For Sale",
|
|
194
|
+
property_type: "single_family",
|
|
195
|
+
year_built: 1948,
|
|
196
|
+
lot_size: "0.21 acres",
|
|
197
|
+
units,
|
|
198
|
+
contacts: contacts.map((c) => ({
|
|
199
|
+
id: "primary",
|
|
200
|
+
primary: true,
|
|
201
|
+
name: c.fields.display_name,
|
|
202
|
+
title: c.fields.title,
|
|
203
|
+
bio: c.fields.bio,
|
|
204
|
+
email: c.fields.email,
|
|
205
|
+
phone: c.fields.phone,
|
|
206
|
+
address: c.fields.address,
|
|
207
|
+
website_url: c.fields.website_url,
|
|
208
|
+
avatar_upload_id: `upload_headshot_${c.library_item_id}`,
|
|
209
|
+
org_name: c.fields.org_name,
|
|
210
|
+
logo_light_upload_id: c.fields.logo_light ? `upload_logo_light_${c.library_item_id}` : null,
|
|
211
|
+
logo_dark_upload_id: c.fields.logo_dark ? `upload_logo_dark_${c.library_item_id}` : null,
|
|
212
|
+
instagram_url: c.fields.socials.find((s) => s.platform === "instagram")?.url ?? null,
|
|
213
|
+
linkedin_url: c.fields.socials.find((s) => s.platform === "linkedin")?.url ?? null,
|
|
214
|
+
x_url: c.fields.socials.find((s) => s.platform === "x")?.url ?? null,
|
|
215
|
+
facebook_url: c.fields.socials.find((s) => s.platform === "facebook")?.url ?? null
|
|
216
|
+
}))
|
|
217
|
+
};
|
|
218
|
+
const sparseSingleFamily = {
|
|
219
|
+
key: "sparseSingleFamily",
|
|
220
|
+
label: "Sparse single-family (for sale)",
|
|
221
|
+
facts,
|
|
222
|
+
photos,
|
|
223
|
+
pois,
|
|
224
|
+
amenities,
|
|
225
|
+
contacts,
|
|
226
|
+
media: {
|
|
227
|
+
video_url: null,
|
|
228
|
+
tour_3d_url: null
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
//#endregion
|
|
233
|
+
export { sparseSingleFamily };
|
package/dist/fixtures.d.ts
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
import { AmenityItem, ContactFixture, PhotoFixture, PoiFixture,
|
|
2
|
-
|
|
1
|
+
import { AmenityItem, ContactFixture, PhotoFixture, PoiFixture, mkResponsive } from "./fixtures/sample-property.js";
|
|
2
|
+
import { MediaFixture, Scenario, ScenarioKey } from "./fixtures/scenario.js";
|
|
3
|
+
import { forRentCondo } from "./fixtures/scenarios/for-rent-condo.js";
|
|
4
|
+
import { luxuryMultiUnit } from "./fixtures/scenarios/luxury-multi-unit.js";
|
|
5
|
+
import { sparseSingleFamily } from "./fixtures/scenarios/sparse-single-family.js";
|
|
6
|
+
import { scenarios } from "./fixtures/scenarios/index.js";
|
|
7
|
+
import { PropertyMetrics, contactCards, poisByCategory, primaryContact, propertyMetrics } from "./fixtures/helpers.js";
|
|
8
|
+
export { type AmenityItem, type ContactFixture, type MediaFixture, type PhotoFixture, type PoiFixture, type PropertyMetrics, type Scenario, type ScenarioKey, contactCards, forRentCondo, luxuryMultiUnit, mkResponsive, poisByCategory, primaryContact, propertyMetrics, scenarios, sparseSingleFamily };
|
package/dist/fixtures.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkResponsive } from "./fixtures/sample-property.js";
|
|
2
|
+
import { forRentCondo } from "./fixtures/scenarios/for-rent-condo.js";
|
|
3
|
+
import { luxuryMultiUnit } from "./fixtures/scenarios/luxury-multi-unit.js";
|
|
4
|
+
import { sparseSingleFamily } from "./fixtures/scenarios/sparse-single-family.js";
|
|
5
|
+
import { scenarios } from "./fixtures/scenarios/index.js";
|
|
6
|
+
import { contactCards, poisByCategory, primaryContact, propertyMetrics } from "./fixtures/helpers.js";
|
|
2
7
|
|
|
3
|
-
export {
|
|
8
|
+
export { contactCards, forRentCondo, luxuryMultiUnit, mkResponsive, poisByCategory, primaryContact, propertyMetrics, scenarios, sparseSingleFamily };
|