@maplibre-yaml/core 0.1.0-alpha.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.
@@ -0,0 +1,710 @@
1
+ import { z } from 'zod';
2
+
3
+ // @maplibre-yaml/core - Declarative web maps with YAML
4
+
5
+ var LongitudeSchema = z.number().min(-180, "Longitude must be >= -180").max(180, "Longitude must be <= 180").describe("Longitude in degrees (-180 to 180)");
6
+ var LatitudeSchema = z.number().min(-90, "Latitude must be >= -90").max(90, "Latitude must be <= 90").describe("Latitude in degrees (-90 to 90)");
7
+ var LngLatSchema = z.tuple([LongitudeSchema, LatitudeSchema]).describe("Geographic coordinates as [longitude, latitude]");
8
+ var LngLatBoundsSchema = z.tuple([
9
+ LongitudeSchema,
10
+ // west
11
+ LatitudeSchema,
12
+ // south
13
+ LongitudeSchema,
14
+ // east
15
+ LatitudeSchema
16
+ // north
17
+ ]).describe("Bounding box as [west, south, east, north]");
18
+ var ColorSchema = z.string().refine(
19
+ (val) => {
20
+ if (val.startsWith("#")) {
21
+ return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(val);
22
+ }
23
+ if (val.startsWith("rgb")) {
24
+ return /^rgba?\s*\([^)]+\)$/.test(val);
25
+ }
26
+ if (val.startsWith("hsl")) {
27
+ return /^hsla?\s*\([^)]+\)$/.test(val);
28
+ }
29
+ return true;
30
+ },
31
+ {
32
+ message: "Invalid color format. Use hex (#rgb, #rrggbb), rgb(), rgba(), hsl(), hsla(), or named colors."
33
+ }
34
+ ).describe("CSS color value");
35
+ var ExpressionSchema = z.array(z.any()).refine((val) => val.length > 0 && typeof val[0] === "string", {
36
+ message: 'Expression must be an array starting with a string operator (e.g., ["get", "property"])'
37
+ }).describe("MapLibre expression for data-driven styling");
38
+ var NumberOrExpressionSchema = z.union([z.number(), ExpressionSchema]).describe("Number value or MapLibre expression");
39
+ var ColorOrExpressionSchema = z.union([ColorSchema, ExpressionSchema]).describe("Color value or MapLibre expression");
40
+ var ZoomLevelSchema = z.number().min(0, "Zoom level must be >= 0").max(24, "Zoom level must be <= 24").describe("Map zoom level (0-24)");
41
+ var StreamConfigSchema = z.object({
42
+ type: z.enum(["websocket", "sse"]).describe("Streaming connection type"),
43
+ url: z.string().url().optional().describe("WebSocket or SSE endpoint URL"),
44
+ reconnect: z.boolean().default(true).describe("Automatically reconnect on disconnect"),
45
+ reconnectMaxAttempts: z.number().min(0).default(10).describe("Maximum number of reconnection attempts"),
46
+ reconnectDelay: z.number().min(100).default(1e3).describe("Initial delay in milliseconds before reconnecting"),
47
+ reconnectMaxDelay: z.number().min(1e3).default(3e4).describe("Maximum delay in milliseconds for exponential backoff"),
48
+ eventTypes: z.array(z.string()).optional().describe("Event types to listen for (SSE only)"),
49
+ protocols: z.union([z.string(), z.array(z.string())]).optional().describe("WebSocket sub-protocols (WebSocket only)")
50
+ });
51
+ var LoadingConfigSchema = z.object({
52
+ enabled: z.boolean().default(false).describe("Enable loading UI overlays"),
53
+ message: z.string().optional().describe("Custom loading message to display"),
54
+ showErrorOverlay: z.boolean().default(true).describe("Show error overlay on fetch failure")
55
+ });
56
+ var CacheConfigSchema = z.object({
57
+ enabled: z.boolean().default(true).describe("Enable HTTP caching"),
58
+ ttl: z.number().positive().optional().describe("Cache TTL in milliseconds (overrides default)")
59
+ });
60
+ var RefreshConfigSchema = z.object({
61
+ refreshInterval: z.number().min(1e3).optional().describe("Polling interval in milliseconds (minimum 1000ms)"),
62
+ updateStrategy: z.enum(["replace", "merge", "append-window"]).default("replace").describe("How to merge incoming data with existing data"),
63
+ updateKey: z.string().optional().describe("Property key for merge strategy (required for merge)"),
64
+ windowSize: z.number().positive().optional().describe("Maximum features to keep (append-window)"),
65
+ windowDuration: z.number().positive().optional().describe("Maximum age in milliseconds (append-window)"),
66
+ timestampField: z.string().optional().describe("Property field containing timestamp (append-window)")
67
+ }).refine((data) => !(data.updateStrategy === "merge" && !data.updateKey), {
68
+ message: "updateKey is required when updateStrategy is 'merge'"
69
+ });
70
+ var GeoJSONSourceSchema = z.object({
71
+ type: z.literal("geojson").describe("Source type"),
72
+ url: z.string().url().optional().describe("URL to fetch GeoJSON data"),
73
+ data: z.any().optional().describe("Inline GeoJSON object"),
74
+ prefetchedData: z.any().optional().describe("Pre-fetched data from build time"),
75
+ fetchStrategy: z.enum(["runtime", "build", "hybrid"]).default("runtime").describe("When to fetch data: runtime (default), build, or hybrid"),
76
+ stream: StreamConfigSchema.optional().describe(
77
+ "WebSocket/SSE streaming configuration"
78
+ ),
79
+ refresh: RefreshConfigSchema.optional().describe(
80
+ "Polling refresh configuration"
81
+ ),
82
+ // Legacy support for direct refresh properties
83
+ refreshInterval: z.number().min(1e3).optional().describe("Polling interval in milliseconds (legacy, use refresh.refreshInterval)"),
84
+ updateStrategy: z.enum(["replace", "merge", "append-window"]).optional().describe("Update strategy (legacy, use refresh.updateStrategy)"),
85
+ updateKey: z.string().optional().describe("Update key (legacy, use refresh.updateKey)"),
86
+ loading: LoadingConfigSchema.optional().describe(
87
+ "Loading UI configuration"
88
+ ),
89
+ cache: CacheConfigSchema.optional().describe("Cache configuration"),
90
+ // MapLibre clustering options
91
+ cluster: z.boolean().optional().describe("Enable point clustering"),
92
+ clusterRadius: z.number().int().min(0).default(50).describe("Cluster radius in pixels"),
93
+ clusterMaxZoom: z.number().min(0).max(24).optional().describe("Maximum zoom level to cluster points"),
94
+ clusterMinPoints: z.number().int().min(2).optional().describe("Minimum points to form a cluster"),
95
+ clusterProperties: z.record(z.any()).optional().describe("Aggregate cluster properties"),
96
+ // Additional MapLibre options (passthrough)
97
+ tolerance: z.number().optional(),
98
+ buffer: z.number().optional(),
99
+ lineMetrics: z.boolean().optional(),
100
+ generateId: z.boolean().optional(),
101
+ promoteId: z.union([z.string(), z.record(z.string())]).optional(),
102
+ attribution: z.string().optional()
103
+ }).passthrough().refine((data) => data.url || data.data || data.prefetchedData, {
104
+ message: 'GeoJSON source requires at least one of: url, data, or prefetchedData. Use "url" to fetch from an endpoint, "data" for inline GeoJSON, or "prefetchedData" for build-time fetched data.'
105
+ });
106
+ var VectorSourceSchema = z.object({
107
+ type: z.literal("vector").describe("Source type"),
108
+ url: z.string().url().optional().describe("TileJSON URL"),
109
+ tiles: z.array(z.string().url()).optional().describe("Tile URL template array"),
110
+ minzoom: z.number().min(0).max(24).optional().describe("Minimum zoom level"),
111
+ maxzoom: z.number().min(0).max(24).optional().describe("Maximum zoom level"),
112
+ bounds: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional().describe("Bounding box [west, south, east, north]"),
113
+ scheme: z.enum(["xyz", "tms"]).optional().describe("Tile coordinate scheme"),
114
+ attribution: z.string().optional().describe("Attribution text"),
115
+ promoteId: z.union([z.string(), z.record(z.string())]).optional(),
116
+ volatile: z.boolean().optional()
117
+ }).passthrough().refine((data) => data.url || data.tiles, {
118
+ message: 'Vector source requires either "url" (TileJSON) or "tiles" (tile URL array). Provide at least one of these properties.'
119
+ });
120
+ var RasterSourceSchema = z.object({
121
+ type: z.literal("raster").describe("Source type"),
122
+ url: z.string().url().optional().describe("TileJSON URL"),
123
+ tiles: z.array(z.string().url()).optional().describe("Tile URL template array"),
124
+ tileSize: z.number().int().min(1).default(512).describe("Tile size in pixels"),
125
+ minzoom: z.number().min(0).max(24).optional().describe("Minimum zoom level"),
126
+ maxzoom: z.number().min(0).max(24).optional().describe("Maximum zoom level"),
127
+ bounds: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional().describe("Bounding box [west, south, east, north]"),
128
+ scheme: z.enum(["xyz", "tms"]).optional().describe("Tile coordinate scheme"),
129
+ attribution: z.string().optional().describe("Attribution text"),
130
+ volatile: z.boolean().optional()
131
+ }).passthrough().refine((data) => data.url || data.tiles, {
132
+ message: 'Raster source requires either "url" (TileJSON) or "tiles" (tile URL array). Provide at least one of these properties.'
133
+ });
134
+ var ImageSourceSchema = z.object({
135
+ type: z.literal("image").describe("Source type"),
136
+ url: z.string().url().describe("Image URL"),
137
+ coordinates: z.tuple([LngLatSchema, LngLatSchema, LngLatSchema, LngLatSchema]).describe(
138
+ "Four corner coordinates [topLeft, topRight, bottomRight, bottomLeft]"
139
+ )
140
+ }).passthrough();
141
+ var VideoSourceSchema = z.object({
142
+ type: z.literal("video").describe("Source type"),
143
+ urls: z.array(z.string().url()).min(1).describe("Array of video URLs for browser compatibility"),
144
+ coordinates: z.tuple([LngLatSchema, LngLatSchema, LngLatSchema, LngLatSchema]).describe(
145
+ "Four corner coordinates [topLeft, topRight, bottomRight, bottomLeft]"
146
+ )
147
+ }).passthrough();
148
+ var LayerSourceSchema = z.union([
149
+ GeoJSONSourceSchema,
150
+ VectorSourceSchema,
151
+ RasterSourceSchema,
152
+ ImageSourceSchema,
153
+ VideoSourceSchema
154
+ ]);
155
+ var PopupContentItemSchema = z.object({
156
+ str: z.string().optional().describe("Static text string"),
157
+ property: z.string().optional().describe("Feature property name"),
158
+ else: z.string().optional().describe("Fallback value if property missing"),
159
+ format: z.string().optional().describe('Number format string (e.g., ",.0f")'),
160
+ href: z.string().url().optional().describe("Link URL"),
161
+ text: z.string().optional().describe("Link text"),
162
+ src: z.string().url().optional().describe("Image/iframe source"),
163
+ alt: z.string().optional().describe("Image alt text")
164
+ }).passthrough().describe("Popup content item with static or dynamic values");
165
+ var PopupContentSchema = z.array(z.record(z.array(PopupContentItemSchema))).describe("Popup content structure as array of HTML elements");
166
+ var InteractiveConfigSchema = z.object({
167
+ hover: z.object({
168
+ cursor: z.string().optional().describe('CSS cursor style (e.g., "pointer")'),
169
+ highlight: z.boolean().optional().describe("Highlight feature on hover")
170
+ }).optional().describe("Hover behavior"),
171
+ click: z.object({
172
+ popup: PopupContentSchema.optional().describe(
173
+ "Popup content to display"
174
+ ),
175
+ action: z.string().optional().describe("Custom action name to trigger"),
176
+ flyTo: z.object({
177
+ center: z.tuple([z.number(), z.number()]).optional(),
178
+ zoom: ZoomLevelSchema.optional(),
179
+ duration: z.number().optional()
180
+ }).optional().describe("Fly to location on click")
181
+ }).optional().describe("Click behavior"),
182
+ mouseenter: z.object({
183
+ action: z.string().optional().describe("Custom action on mouse enter")
184
+ }).optional(),
185
+ mouseleave: z.object({
186
+ action: z.string().optional().describe("Custom action on mouse leave")
187
+ }).optional()
188
+ }).optional().describe("Interactive event configuration");
189
+ var LegendItemSchema = z.object({
190
+ color: z.string().describe("CSS color value"),
191
+ label: z.string().describe("Legend label text"),
192
+ shape: z.enum(["circle", "square", "line", "icon"]).default("square").describe("Symbol shape"),
193
+ icon: z.string().optional().describe("Icon name or URL (for shape: icon)")
194
+ }).describe("Legend item configuration");
195
+ var BaseLayerPropertiesSchema = z.object({
196
+ id: z.string().describe("Unique layer identifier"),
197
+ label: z.string().optional().describe("Human-readable layer label"),
198
+ source: z.union([LayerSourceSchema, z.string()]).describe("Layer source (inline definition or source ID reference)"),
199
+ "source-layer": z.string().optional().describe("Source layer name (for vector sources)"),
200
+ minzoom: ZoomLevelSchema.optional().describe(
201
+ "Minimum zoom level to show layer"
202
+ ),
203
+ maxzoom: ZoomLevelSchema.optional().describe(
204
+ "Maximum zoom level to show layer"
205
+ ),
206
+ filter: ExpressionSchema.optional().describe("MapLibre filter expression"),
207
+ visible: z.boolean().default(true).describe("Initial visibility state"),
208
+ toggleable: z.boolean().default(true).describe("Allow users to toggle visibility"),
209
+ before: z.string().optional().describe("Layer ID to insert this layer before"),
210
+ interactive: InteractiveConfigSchema.describe(
211
+ "Interactive event configuration"
212
+ ),
213
+ legend: LegendItemSchema.optional().describe("Legend configuration"),
214
+ metadata: z.record(z.any()).optional().describe("Custom metadata")
215
+ });
216
+ var CircleLayerSchema = BaseLayerPropertiesSchema.extend({
217
+ type: z.literal("circle").describe("Layer type"),
218
+ paint: z.object({
219
+ "circle-radius": NumberOrExpressionSchema.optional(),
220
+ "circle-color": ColorOrExpressionSchema.optional(),
221
+ "circle-blur": NumberOrExpressionSchema.optional(),
222
+ "circle-opacity": NumberOrExpressionSchema.optional(),
223
+ "circle-stroke-width": NumberOrExpressionSchema.optional(),
224
+ "circle-stroke-color": ColorOrExpressionSchema.optional(),
225
+ "circle-stroke-opacity": NumberOrExpressionSchema.optional(),
226
+ "circle-pitch-scale": z.enum(["map", "viewport"]).optional(),
227
+ "circle-pitch-alignment": z.enum(["map", "viewport"]).optional(),
228
+ "circle-translate": z.tuple([z.number(), z.number()]).optional(),
229
+ "circle-translate-anchor": z.enum(["map", "viewport"]).optional()
230
+ }).passthrough().optional().describe("Circle paint properties"),
231
+ layout: z.object({}).passthrough().optional().describe("Circle layout properties")
232
+ }).passthrough();
233
+ var LineLayerSchema = BaseLayerPropertiesSchema.extend({
234
+ type: z.literal("line").describe("Layer type"),
235
+ paint: z.object({
236
+ "line-opacity": NumberOrExpressionSchema.optional(),
237
+ "line-color": ColorOrExpressionSchema.optional(),
238
+ "line-width": NumberOrExpressionSchema.optional(),
239
+ "line-gap-width": NumberOrExpressionSchema.optional(),
240
+ "line-offset": NumberOrExpressionSchema.optional(),
241
+ "line-blur": NumberOrExpressionSchema.optional(),
242
+ "line-dasharray": z.array(z.number()).optional(),
243
+ "line-pattern": z.string().optional(),
244
+ "line-gradient": ColorOrExpressionSchema.optional(),
245
+ "line-translate": z.tuple([z.number(), z.number()]).optional(),
246
+ "line-translate-anchor": z.enum(["map", "viewport"]).optional()
247
+ }).passthrough().optional().describe("Line paint properties"),
248
+ layout: z.object({
249
+ "line-cap": z.enum(["butt", "round", "square"]).optional(),
250
+ "line-join": z.enum(["bevel", "round", "miter"]).optional(),
251
+ "line-miter-limit": z.number().optional(),
252
+ "line-round-limit": z.number().optional(),
253
+ "line-sort-key": NumberOrExpressionSchema.optional()
254
+ }).passthrough().optional().describe("Line layout properties")
255
+ }).passthrough();
256
+ var FillLayerSchema = BaseLayerPropertiesSchema.extend({
257
+ type: z.literal("fill").describe("Layer type"),
258
+ paint: z.object({
259
+ "fill-antialias": z.boolean().optional(),
260
+ "fill-opacity": NumberOrExpressionSchema.optional(),
261
+ "fill-color": ColorOrExpressionSchema.optional(),
262
+ "fill-outline-color": ColorOrExpressionSchema.optional(),
263
+ "fill-translate": z.tuple([z.number(), z.number()]).optional(),
264
+ "fill-translate-anchor": z.enum(["map", "viewport"]).optional(),
265
+ "fill-pattern": z.string().optional()
266
+ }).passthrough().optional().describe("Fill paint properties"),
267
+ layout: z.object({
268
+ "fill-sort-key": NumberOrExpressionSchema.optional()
269
+ }).passthrough().optional().describe("Fill layout properties")
270
+ }).passthrough();
271
+ var SymbolLayerSchema = BaseLayerPropertiesSchema.extend({
272
+ type: z.literal("symbol").describe("Layer type"),
273
+ layout: z.object({
274
+ "symbol-placement": z.enum(["point", "line", "line-center"]).optional(),
275
+ "symbol-spacing": z.number().optional(),
276
+ "symbol-avoid-edges": z.boolean().optional(),
277
+ "symbol-sort-key": NumberOrExpressionSchema.optional(),
278
+ "symbol-z-order": z.enum(["auto", "viewport-y", "source"]).optional(),
279
+ "icon-allow-overlap": z.boolean().optional(),
280
+ "icon-ignore-placement": z.boolean().optional(),
281
+ "icon-optional": z.boolean().optional(),
282
+ "icon-rotation-alignment": z.enum(["map", "viewport", "auto"]).optional(),
283
+ "icon-size": NumberOrExpressionSchema.optional(),
284
+ "icon-text-fit": z.enum(["none", "width", "height", "both"]).optional(),
285
+ "icon-text-fit-padding": z.tuple([z.number(), z.number(), z.number(), z.number()]).optional(),
286
+ "icon-image": z.union([z.string(), ExpressionSchema]).optional(),
287
+ "icon-rotate": NumberOrExpressionSchema.optional(),
288
+ "icon-padding": z.number().optional(),
289
+ "icon-keep-upright": z.boolean().optional(),
290
+ "icon-offset": z.tuple([z.number(), z.number()]).optional(),
291
+ "icon-anchor": z.enum([
292
+ "center",
293
+ "left",
294
+ "right",
295
+ "top",
296
+ "bottom",
297
+ "top-left",
298
+ "top-right",
299
+ "bottom-left",
300
+ "bottom-right"
301
+ ]).optional(),
302
+ "icon-pitch-alignment": z.enum(["map", "viewport", "auto"]).optional(),
303
+ "text-pitch-alignment": z.enum(["map", "viewport", "auto"]).optional(),
304
+ "text-rotation-alignment": z.enum(["map", "viewport", "auto"]).optional(),
305
+ "text-field": z.union([z.string(), ExpressionSchema]).optional(),
306
+ "text-font": z.array(z.string()).optional(),
307
+ "text-size": NumberOrExpressionSchema.optional(),
308
+ "text-max-width": NumberOrExpressionSchema.optional(),
309
+ "text-line-height": z.number().optional(),
310
+ "text-letter-spacing": z.number().optional(),
311
+ "text-justify": z.enum(["auto", "left", "center", "right"]).optional(),
312
+ "text-radial-offset": z.number().optional(),
313
+ "text-variable-anchor": z.array(
314
+ z.enum([
315
+ "center",
316
+ "left",
317
+ "right",
318
+ "top",
319
+ "bottom",
320
+ "top-left",
321
+ "top-right",
322
+ "bottom-left",
323
+ "bottom-right"
324
+ ])
325
+ ).optional(),
326
+ "text-anchor": z.enum([
327
+ "center",
328
+ "left",
329
+ "right",
330
+ "top",
331
+ "bottom",
332
+ "top-left",
333
+ "top-right",
334
+ "bottom-left",
335
+ "bottom-right"
336
+ ]).optional(),
337
+ "text-max-angle": z.number().optional(),
338
+ "text-rotate": NumberOrExpressionSchema.optional(),
339
+ "text-padding": z.number().optional(),
340
+ "text-keep-upright": z.boolean().optional(),
341
+ "text-transform": z.enum(["none", "uppercase", "lowercase"]).optional(),
342
+ "text-offset": z.tuple([z.number(), z.number()]).optional(),
343
+ "text-allow-overlap": z.boolean().optional(),
344
+ "text-ignore-placement": z.boolean().optional(),
345
+ "text-optional": z.boolean().optional()
346
+ }).passthrough().optional().describe("Symbol layout properties"),
347
+ paint: z.object({
348
+ "icon-opacity": NumberOrExpressionSchema.optional(),
349
+ "icon-color": ColorOrExpressionSchema.optional(),
350
+ "icon-halo-color": ColorOrExpressionSchema.optional(),
351
+ "icon-halo-width": NumberOrExpressionSchema.optional(),
352
+ "icon-halo-blur": NumberOrExpressionSchema.optional(),
353
+ "icon-translate": z.tuple([z.number(), z.number()]).optional(),
354
+ "icon-translate-anchor": z.enum(["map", "viewport"]).optional(),
355
+ "text-opacity": NumberOrExpressionSchema.optional(),
356
+ "text-color": ColorOrExpressionSchema.optional(),
357
+ "text-halo-color": ColorOrExpressionSchema.optional(),
358
+ "text-halo-width": NumberOrExpressionSchema.optional(),
359
+ "text-halo-blur": NumberOrExpressionSchema.optional(),
360
+ "text-translate": z.tuple([z.number(), z.number()]).optional(),
361
+ "text-translate-anchor": z.enum(["map", "viewport"]).optional()
362
+ }).passthrough().optional().describe("Symbol paint properties")
363
+ }).passthrough();
364
+ var RasterLayerSchema = BaseLayerPropertiesSchema.extend({
365
+ type: z.literal("raster").describe("Layer type"),
366
+ paint: z.object({
367
+ "raster-opacity": NumberOrExpressionSchema.optional(),
368
+ "raster-hue-rotate": NumberOrExpressionSchema.optional(),
369
+ "raster-brightness-min": NumberOrExpressionSchema.optional(),
370
+ "raster-brightness-max": NumberOrExpressionSchema.optional(),
371
+ "raster-saturation": NumberOrExpressionSchema.optional(),
372
+ "raster-contrast": NumberOrExpressionSchema.optional(),
373
+ "raster-resampling": z.enum(["linear", "nearest"]).optional(),
374
+ "raster-fade-duration": z.number().optional()
375
+ }).passthrough().optional().describe("Raster paint properties"),
376
+ layout: z.object({}).passthrough().optional().describe("Raster layout properties")
377
+ }).passthrough();
378
+ var FillExtrusionLayerSchema = BaseLayerPropertiesSchema.extend({
379
+ type: z.literal("fill-extrusion").describe("Layer type"),
380
+ paint: z.object({
381
+ "fill-extrusion-opacity": NumberOrExpressionSchema.optional(),
382
+ "fill-extrusion-color": ColorOrExpressionSchema.optional(),
383
+ "fill-extrusion-translate": z.tuple([z.number(), z.number()]).optional(),
384
+ "fill-extrusion-translate-anchor": z.enum(["map", "viewport"]).optional(),
385
+ "fill-extrusion-pattern": z.string().optional(),
386
+ "fill-extrusion-height": NumberOrExpressionSchema.optional(),
387
+ "fill-extrusion-base": NumberOrExpressionSchema.optional(),
388
+ "fill-extrusion-vertical-gradient": z.boolean().optional()
389
+ }).passthrough().optional().describe("Fill extrusion paint properties"),
390
+ layout: z.object({}).passthrough().optional().describe("Fill extrusion layout properties")
391
+ }).passthrough();
392
+ var HeatmapLayerSchema = BaseLayerPropertiesSchema.extend({
393
+ type: z.literal("heatmap").describe("Layer type"),
394
+ paint: z.object({
395
+ "heatmap-radius": NumberOrExpressionSchema.optional(),
396
+ "heatmap-weight": NumberOrExpressionSchema.optional(),
397
+ "heatmap-intensity": NumberOrExpressionSchema.optional(),
398
+ "heatmap-color": ColorOrExpressionSchema.optional(),
399
+ "heatmap-opacity": NumberOrExpressionSchema.optional()
400
+ }).passthrough().optional().describe("Heatmap paint properties"),
401
+ layout: z.object({}).passthrough().optional().describe("Heatmap layout properties")
402
+ }).passthrough();
403
+ var HillshadeLayerSchema = BaseLayerPropertiesSchema.extend({
404
+ type: z.literal("hillshade").describe("Layer type"),
405
+ paint: z.object({
406
+ "hillshade-illumination-direction": z.number().optional(),
407
+ "hillshade-illumination-anchor": z.enum(["map", "viewport"]).optional(),
408
+ "hillshade-exaggeration": NumberOrExpressionSchema.optional(),
409
+ "hillshade-shadow-color": ColorOrExpressionSchema.optional(),
410
+ "hillshade-highlight-color": ColorOrExpressionSchema.optional(),
411
+ "hillshade-accent-color": ColorOrExpressionSchema.optional()
412
+ }).passthrough().optional().describe("Hillshade paint properties"),
413
+ layout: z.object({}).passthrough().optional().describe("Hillshade layout properties")
414
+ }).passthrough();
415
+ var BackgroundLayerSchema = z.object({
416
+ id: z.string().describe("Unique layer identifier"),
417
+ type: z.literal("background").describe("Layer type"),
418
+ paint: z.object({
419
+ "background-color": ColorOrExpressionSchema.optional(),
420
+ "background-pattern": z.string().optional(),
421
+ "background-opacity": NumberOrExpressionSchema.optional()
422
+ }).passthrough().optional().describe("Background paint properties"),
423
+ layout: z.object({}).passthrough().optional().describe("Background layout properties"),
424
+ metadata: z.record(z.any()).optional().describe("Custom metadata")
425
+ }).passthrough();
426
+ var LayerSchema = z.union([
427
+ CircleLayerSchema,
428
+ LineLayerSchema,
429
+ FillLayerSchema,
430
+ SymbolLayerSchema,
431
+ RasterLayerSchema,
432
+ FillExtrusionLayerSchema,
433
+ HeatmapLayerSchema,
434
+ HillshadeLayerSchema,
435
+ BackgroundLayerSchema
436
+ ]);
437
+ var LayerReferenceSchema = z.object({
438
+ $ref: z.string().describe('Reference to global layer (e.g., "#/layers/bikeLayer")')
439
+ }).describe("Layer reference");
440
+ var LayerOrReferenceSchema = z.union([
441
+ LayerSchema,
442
+ LayerReferenceSchema
443
+ ]);
444
+ var ValidTagNames = [
445
+ "h1",
446
+ "h2",
447
+ "h3",
448
+ "h4",
449
+ "h5",
450
+ "h6",
451
+ "p",
452
+ "span",
453
+ "div",
454
+ "a",
455
+ "strong",
456
+ "em",
457
+ "code",
458
+ "pre",
459
+ "img",
460
+ "iframe",
461
+ "ul",
462
+ "ol",
463
+ "li",
464
+ "blockquote",
465
+ "hr",
466
+ "br"
467
+ ];
468
+ var ContentElementSchema = z.object({
469
+ // Content
470
+ str: z.string().optional().describe("Static text string"),
471
+ property: z.string().optional().describe("Dynamic property from context"),
472
+ else: z.string().optional().describe("Fallback value if property missing"),
473
+ // Styling
474
+ classList: z.union([z.string(), z.array(z.string())]).optional().describe("CSS class names (space-separated string or array)"),
475
+ id: z.string().optional().describe("Element ID attribute"),
476
+ style: z.string().optional().describe("Inline CSS styles"),
477
+ // Links
478
+ href: z.string().url().optional().describe("Link URL"),
479
+ target: z.string().optional().describe("Link target (_blank, _self, _parent, _top)"),
480
+ // Media
481
+ src: z.string().url().optional().describe("Source URL for img or iframe"),
482
+ alt: z.string().optional().describe("Alternative text for images"),
483
+ width: z.union([z.string(), z.number()]).optional().describe("Width (pixels or %)"),
484
+ height: z.union([z.string(), z.number()]).optional().describe("Height (pixels or %)")
485
+ }).passthrough().describe("Content element with styling and properties");
486
+ var ContentItemSchema = z.record(z.enum(ValidTagNames), z.array(ContentElementSchema)).describe("Content item mapping tag to elements");
487
+ var ContentBlockSchema = z.object({
488
+ type: z.literal("content").describe("Block type"),
489
+ id: z.string().optional().describe("Unique block identifier"),
490
+ className: z.string().optional().describe("CSS class name for the block container"),
491
+ style: z.string().optional().describe("Inline CSS styles for the block container"),
492
+ content: z.array(ContentItemSchema).describe("Array of content items to render")
493
+ }).describe("Content block for rich text and media");
494
+ var ControlPositionSchema = z.enum([
495
+ "top-left",
496
+ "top-right",
497
+ "bottom-left",
498
+ "bottom-right"
499
+ ]);
500
+ var ControlConfigSchema = z.union([
501
+ z.boolean(),
502
+ z.object({
503
+ enabled: z.boolean().describe("Whether control is enabled"),
504
+ position: ControlPositionSchema.optional().describe("Control position")
505
+ })
506
+ ]);
507
+ var ControlsConfigSchema = z.object({
508
+ navigation: ControlConfigSchema.optional().describe(
509
+ "Navigation controls (zoom, rotation)"
510
+ ),
511
+ geolocate: ControlConfigSchema.optional().describe("Geolocation control"),
512
+ scale: ControlConfigSchema.optional().describe("Scale control"),
513
+ fullscreen: ControlConfigSchema.optional().describe("Fullscreen control"),
514
+ attribution: ControlConfigSchema.optional().describe("Attribution control")
515
+ }).describe("Map controls configuration");
516
+ var LegendConfigSchema = z.object({
517
+ position: ControlPositionSchema.default("top-left").describe("Legend position"),
518
+ title: z.string().optional().describe("Legend title"),
519
+ collapsed: z.boolean().default(false).describe("Start collapsed"),
520
+ items: z.array(
521
+ z.object({
522
+ color: z.string().describe("Item color"),
523
+ label: z.string().describe("Item label"),
524
+ shape: z.enum(["circle", "square", "line", "icon"]).default("square").describe("Symbol shape"),
525
+ icon: z.string().optional().describe("Icon name/URL (for shape: icon)")
526
+ })
527
+ ).optional().describe("Custom legend items (overrides layer legends)")
528
+ }).describe("Legend configuration");
529
+ var MapConfigSchema = z.object({
530
+ // Required
531
+ center: LngLatSchema.describe("Initial map center [longitude, latitude]"),
532
+ zoom: ZoomLevelSchema.describe("Initial zoom level (0-24)"),
533
+ mapStyle: z.union([z.string().url(), z.any()]).describe("MapLibre style URL or style object"),
534
+ // View
535
+ pitch: z.number().min(0).max(85).default(0).describe("Camera pitch angle in degrees (0-85)"),
536
+ bearing: z.number().min(-180).max(180).default(0).describe("Camera bearing (rotation) in degrees (-180 to 180)"),
537
+ bounds: z.union([LngLatBoundsSchema, z.array(z.number())]).optional().describe("Fit map to bounds"),
538
+ // Constraints
539
+ minZoom: ZoomLevelSchema.optional().describe("Minimum zoom level"),
540
+ maxZoom: ZoomLevelSchema.optional().describe("Maximum zoom level"),
541
+ minPitch: z.number().min(0).max(85).optional().describe("Minimum pitch"),
542
+ maxPitch: z.number().min(0).max(85).optional().describe("Maximum pitch"),
543
+ maxBounds: LngLatBoundsSchema.optional().describe(
544
+ "Maximum geographic bounds"
545
+ ),
546
+ // Interaction
547
+ interactive: z.boolean().default(true).describe("Enable map interaction"),
548
+ scrollZoom: z.boolean().optional().describe("Enable scroll to zoom"),
549
+ boxZoom: z.boolean().optional().describe("Enable box zoom (shift+drag)"),
550
+ dragRotate: z.boolean().optional().describe("Enable drag to rotate"),
551
+ dragPan: z.boolean().optional().describe("Enable drag to pan"),
552
+ keyboard: z.boolean().optional().describe("Enable keyboard shortcuts"),
553
+ doubleClickZoom: z.boolean().optional().describe("Enable double-click zoom"),
554
+ touchZoomRotate: z.boolean().optional().describe("Enable touch zoom/rotate"),
555
+ touchPitch: z.boolean().optional().describe("Enable touch pitch"),
556
+ // Display
557
+ hash: z.boolean().optional().describe("Sync map state with URL hash"),
558
+ attributionControl: z.boolean().optional().describe("Show attribution control"),
559
+ logoPosition: ControlPositionSchema.optional().describe(
560
+ "MapLibre logo position"
561
+ ),
562
+ fadeDuration: z.number().optional().describe("Fade duration in milliseconds"),
563
+ crossSourceCollisions: z.boolean().optional().describe("Check for cross-source collisions"),
564
+ // Rendering
565
+ antialias: z.boolean().optional().describe("Enable antialiasing"),
566
+ refreshExpiredTiles: z.boolean().optional().describe("Refresh expired tiles"),
567
+ renderWorldCopies: z.boolean().optional().describe("Render multiple world copies"),
568
+ locale: z.record(z.string()).optional().describe("Localization strings"),
569
+ // Performance
570
+ maxTileCacheSize: z.number().optional().describe("Maximum tiles to cache"),
571
+ localIdeographFontFamily: z.string().optional().describe("Font for CJK characters"),
572
+ trackResize: z.boolean().optional().describe("Track container resize"),
573
+ preserveDrawingBuffer: z.boolean().optional().describe("Preserve drawing buffer"),
574
+ failIfMajorPerformanceCaveat: z.boolean().optional().describe("Fail if major performance caveat")
575
+ }).passthrough().describe("Map configuration with MapLibre options");
576
+ var MapBlockSchema = z.object({
577
+ type: z.literal("map").describe("Block type"),
578
+ id: z.string().describe("Unique block identifier"),
579
+ className: z.string().optional().describe("CSS class name for container"),
580
+ style: z.string().optional().describe("Inline CSS styles for container"),
581
+ config: MapConfigSchema.describe("Map configuration"),
582
+ layers: z.array(LayerOrReferenceSchema).default([]).describe("Map layers"),
583
+ controls: ControlsConfigSchema.optional().describe("Map controls"),
584
+ legend: LegendConfigSchema.optional().describe("Legend configuration")
585
+ }).describe("Standard map block");
586
+ var MapFullPageBlockSchema = z.object({
587
+ type: z.literal("map-fullpage").describe("Block type"),
588
+ id: z.string().describe("Unique block identifier"),
589
+ className: z.string().optional().describe("CSS class name for container"),
590
+ style: z.string().optional().describe("Inline CSS styles for container"),
591
+ config: MapConfigSchema.describe("Map configuration"),
592
+ layers: z.array(LayerOrReferenceSchema).default([]).describe("Map layers"),
593
+ controls: ControlsConfigSchema.optional().describe("Map controls"),
594
+ legend: LegendConfigSchema.optional().describe("Legend configuration")
595
+ }).describe("Full-page map block");
596
+ var ChapterActionSchema = z.object({
597
+ action: z.enum([
598
+ "setFilter",
599
+ "setPaintProperty",
600
+ "setLayoutProperty",
601
+ "flyTo",
602
+ "easeTo",
603
+ "fitBounds",
604
+ "custom"
605
+ ]).describe("Action type"),
606
+ layer: z.string().optional().describe("Target layer ID"),
607
+ property: z.string().optional().describe("Property name (for setPaintProperty/setLayoutProperty)"),
608
+ value: z.any().optional().describe("Property value"),
609
+ filter: ExpressionSchema.nullable().optional().describe("Filter expression (for setFilter, null to clear)"),
610
+ bounds: z.array(z.number()).optional().describe("Bounds array (for fitBounds)"),
611
+ options: z.record(z.any()).optional().describe("Additional options")
612
+ }).describe("Chapter action for map state changes");
613
+ var ChapterLayersSchema = z.object({
614
+ show: z.array(z.string()).default([]).describe("Layer IDs to show"),
615
+ hide: z.array(z.string()).default([]).describe("Layer IDs to hide")
616
+ }).describe("Chapter layer visibility configuration");
617
+ var ChapterSchema = z.object({
618
+ // Required
619
+ id: z.string().describe("Unique chapter identifier"),
620
+ title: z.string().describe("Chapter title"),
621
+ center: LngLatSchema.describe("Map center [longitude, latitude]"),
622
+ zoom: z.number().describe("Zoom level"),
623
+ // Content
624
+ description: z.string().optional().describe("Chapter description (HTML/markdown supported)"),
625
+ image: z.string().url().optional().describe("Hero image URL"),
626
+ video: z.string().url().optional().describe("Video URL"),
627
+ // Camera
628
+ pitch: z.number().min(0).max(85).default(0).describe("Camera pitch angle (0-85)"),
629
+ bearing: z.number().min(-180).max(180).default(0).describe("Camera bearing (-180 to 180)"),
630
+ speed: z.number().min(0).max(2).default(0.6).describe("Animation speed multiplier (0-2)"),
631
+ curve: z.number().min(0).max(2).default(1).describe("Animation curve (0=linear, 1=default, 2=steep)"),
632
+ animation: z.enum(["flyTo", "easeTo", "jumpTo"]).default("flyTo").describe("Animation type"),
633
+ // Rotation animation
634
+ rotateAnimation: z.boolean().optional().describe("Enable continuous rotation animation"),
635
+ spinGlobe: z.boolean().optional().describe("Spin globe animation (for low zoom levels)"),
636
+ // Layout
637
+ alignment: z.enum(["left", "right", "center", "full"]).default("center").describe("Content alignment"),
638
+ hidden: z.boolean().default(false).describe("Hide chapter content (map-only)"),
639
+ // Layers
640
+ layers: ChapterLayersSchema.optional().describe("Layer visibility control"),
641
+ // Actions
642
+ onChapterEnter: z.array(ChapterActionSchema).default([]).describe("Actions when entering chapter"),
643
+ onChapterExit: z.array(ChapterActionSchema).default([]).describe("Actions when exiting chapter"),
644
+ // Custom
645
+ callback: z.string().optional().describe("Custom callback function name")
646
+ }).describe("Scrollytelling chapter");
647
+ var ScrollytellingBlockSchema = z.object({
648
+ type: z.literal("scrollytelling").describe("Block type"),
649
+ id: z.string().describe("Unique block identifier"),
650
+ className: z.string().optional().describe("CSS class name for container"),
651
+ style: z.string().optional().describe("Inline CSS styles for container"),
652
+ // Base config
653
+ config: MapConfigSchema.describe("Base map configuration"),
654
+ // Theme
655
+ theme: z.enum(["light", "dark"]).default("light").describe("Visual theme"),
656
+ // Markers
657
+ showMarkers: z.boolean().default(false).describe("Show chapter markers on map"),
658
+ markerColor: z.string().default("#3FB1CE").describe("Chapter marker color"),
659
+ // Layers (persistent across all chapters)
660
+ layers: z.array(LayerOrReferenceSchema).default([]).describe("Persistent layers (visible throughout story)"),
661
+ // Chapters
662
+ chapters: z.array(ChapterSchema).min(1, "At least one chapter is required for scrollytelling").describe("Story chapters"),
663
+ // Footer
664
+ footer: z.string().optional().describe("Footer content (HTML)")
665
+ }).describe("Scrollytelling block for narrative map stories");
666
+ var MixedBlockSchema = z.lazy(
667
+ () => z.object({
668
+ type: z.literal("mixed").describe("Block type"),
669
+ id: z.string().optional().describe("Unique block identifier"),
670
+ className: z.string().optional().describe("CSS class name for container"),
671
+ style: z.string().optional().describe("Inline CSS styles for container"),
672
+ layout: z.enum(["row", "column", "grid"]).default("row").describe("Layout direction"),
673
+ gap: z.string().optional().describe("Gap between blocks (CSS gap property)"),
674
+ blocks: z.array(BlockSchema).describe("Child blocks")
675
+ }).describe("Mixed block for combining multiple block types")
676
+ );
677
+ var BlockSchema = z.union([
678
+ ContentBlockSchema,
679
+ MapBlockSchema,
680
+ MapFullPageBlockSchema,
681
+ ScrollytellingBlockSchema,
682
+ MixedBlockSchema
683
+ ]);
684
+ var PageSchema = z.object({
685
+ path: z.string().describe('URL path (e.g., "/", "/about")'),
686
+ title: z.string().describe("Page title"),
687
+ description: z.string().optional().describe("Page description for SEO"),
688
+ blocks: z.array(BlockSchema).describe("Page content blocks")
689
+ }).describe("Page configuration");
690
+ var GlobalConfigSchema = z.object({
691
+ title: z.string().optional().describe("Application title"),
692
+ description: z.string().optional().describe("Application description"),
693
+ defaultMapStyle: z.string().url().optional().describe("Default map style URL"),
694
+ theme: z.enum(["light", "dark"]).default("light").describe("Default theme"),
695
+ dataFetching: z.object({
696
+ defaultStrategy: z.enum(["runtime", "build", "hybrid"]).default("runtime").describe("Default fetch strategy"),
697
+ timeout: z.number().min(1e3).default(3e4).describe("Default timeout in milliseconds"),
698
+ retryAttempts: z.number().int().min(0).default(3).describe("Default retry attempts")
699
+ }).optional().describe("Data fetching configuration")
700
+ }).describe("Global configuration");
701
+ var RootSchema = z.object({
702
+ config: GlobalConfigSchema.optional().describe("Global configuration"),
703
+ layers: z.record(LayerSchema).optional().describe("Named layer definitions for reuse"),
704
+ sources: z.record(LayerSourceSchema).optional().describe("Named source definitions for reuse"),
705
+ pages: z.array(PageSchema).min(1, "At least one page is required").describe("Page definitions")
706
+ }).describe("Root configuration schema");
707
+
708
+ export { BackgroundLayerSchema, BaseLayerPropertiesSchema, BlockSchema, ChapterActionSchema, ChapterLayersSchema, ChapterSchema, CircleLayerSchema, ColorOrExpressionSchema, ColorSchema, ContentBlockSchema, ContentElementSchema, ContentItemSchema, ControlPositionSchema, ControlsConfigSchema, ExpressionSchema, FillExtrusionLayerSchema, FillLayerSchema, GeoJSONSourceSchema, GlobalConfigSchema, HeatmapLayerSchema, HillshadeLayerSchema, ImageSourceSchema, InteractiveConfigSchema, LatitudeSchema, LayerOrReferenceSchema, LayerReferenceSchema, LayerSchema, LayerSourceSchema, LegendConfigSchema, LegendItemSchema, LineLayerSchema, LngLatBoundsSchema, LngLatSchema, LoadingConfigSchema, LongitudeSchema, MapBlockSchema, MapConfigSchema, MapFullPageBlockSchema, MixedBlockSchema, NumberOrExpressionSchema, PageSchema, PopupContentItemSchema, PopupContentSchema, RasterLayerSchema, RasterSourceSchema, RootSchema, ScrollytellingBlockSchema, StreamConfigSchema, SymbolLayerSchema, ValidTagNames, VectorSourceSchema, VideoSourceSchema, ZoomLevelSchema };
709
+ //# sourceMappingURL=index.js.map
710
+ //# sourceMappingURL=index.js.map