@tileflow/svelte 0.1.0-alpha.28 → 0.1.0-alpha.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -90,12 +90,25 @@ Omitting `theme` uses `defaultTheme`. `system` needs an explicit light/dark mapp
90
90
  supplies. Theme changes keep the MapLibre instance, camera, and interactions, and roll back on
91
91
  failure. `onThemeChange` reports transitions.
92
92
 
93
+ Add `timeOfDay="dusk"` beside `theme` to select a map's optional `day`, `dawn`, `dusk`, or
94
+ `night` preset. For Streets, `theme="light"` with this preset selects the existing `dusk` palette.
95
+ Maps without this capability ignore the option; omitting it keeps the selected theme unchanged.
96
+ Changing it uses the existing theme transition. `themeBlend` takes precedence. See the
97
+ [authoring contract](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/README.md#style-with-themes-and-semantic-modules).
98
+
93
99
  `themeTransition={{duration: 450}}` cross-fades theme changes over that many milliseconds.
94
100
  `themeBlend={{themes: ['night', 'dusk', 'day'], position}}` shows a continuous blend of the map's
95
101
  themes instead of `theme`: position 0 is the first theme and 1.5 is halfway from the second to the
96
102
  third. Moving the position updates the map at once. See
97
103
  [theme transitions and blends](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/theme-transitions-and-blends.md).
98
104
 
105
+ Interactive maps automatically render the map's vegetation. `vegetation` overrides visibility
106
+ (omitting it uses the map default); false hides models and flat artwork alike. `viewMode` is `2d`
107
+ by default and may be `3d`: only maps with `vegetation.mode: 'auto'` switch representation.
108
+ Streets uses model trees in either view. Changing either prop updates the existing map immediately.
109
+ These props do not change camera pitch, buildings or lighting and do not apply in image mode. See
110
+ [vegetation controls](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/trees-3d.md#visibility-and-representation).
111
+
99
112
  `mapOptions` accepts native MapLibre options except `container` and `style`. Direct props win over
100
113
  those options, then the manifest view, then shared defaults. `TileflowMap` always selects a Tileflow
101
114
  map through its manifest; it has no renderer discriminator or direct-style mode. The obsolete
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/svelte",
3
- "version": "0.1.0-alpha.28",
3
+ "version": "0.1.0-alpha.29",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Svelte component for rendering Tileflow maps with MapLibre.",
6
6
  "type": "module",
@@ -44,8 +44,8 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@tileflow/core": ">=0.1.0-alpha.32 <0.1.0-beta.0",
48
- "@tileflow/interactions": ">=0.1.0-alpha.4 <0.1.0-beta.0"
47
+ "@tileflow/core": ">=0.1.0-alpha.35 <0.1.0-beta.0",
48
+ "@tileflow/interactions": ">=0.1.0-alpha.5 <0.1.0-beta.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "maplibre-gl": ">=6.4.1 <7",
@@ -34,6 +34,8 @@
34
34
  attachTileflowMapLifecycle,
35
35
  createTileflowSessionStarter,
36
36
  createTileflowThemeController,
37
+ createTileflowVegetation,
38
+ type TileflowVegetationController,
37
39
  createTileflowTransformRequest,
38
40
  getTileflowSystemColorScheme,
39
41
  loadTileflowStyleFonts,
@@ -71,7 +73,7 @@
71
73
  type TileflowMapLibreSemanticDomRenderTarget,
72
74
  type TileflowMapLibreSemanticDomRuntime,
73
75
  } from '@tileflow/interactions/maplibre';
74
- import type {TileflowMapProps} from './index.js';
76
+ import type {TileflowMapOptions, TileflowMapProps} from './index.js';
75
77
  import {loadTileflowMapLibre} from './maplibre.js';
76
78
  import {assertTileflowMapStyleInputs} from './style-source.js';
77
79
 
@@ -99,7 +101,10 @@
99
101
  export let popup: TileflowMapProps['popup'] = undefined;
100
102
  export let source: TileflowMapProps['source'];
101
103
  export let theme: TileflowMapProps['theme'] = undefined;
104
+ export let timeOfDay: TileflowMapProps['timeOfDay'] = undefined;
102
105
  export let themeBlend: TileflowMapProps['themeBlend'] = undefined;
106
+ export let vegetation: TileflowMapProps['vegetation'] = undefined;
107
+ export let viewMode: NonNullable<TileflowMapProps['viewMode']> = '2d';
103
108
  export let themeTransition: TileflowMapProps['themeTransition'] = undefined;
104
109
  export let tooltip: TileflowMapProps['tooltip'] = undefined;
105
110
  export let zoom: TileflowMapProps['zoom'] = undefined;
@@ -142,6 +147,9 @@
142
147
  let interactionRuntimesDisposing = false;
143
148
  let mapResizeObserver: ResizeObserver | null = null;
144
149
  let mapWorldRequestBridge: TileflowWorldRequestBridge | null = null;
150
+ let vegetationController: TileflowVegetationController | null = null;
151
+ $: vegetationController?.setVisible(vegetation);
152
+ $: vegetationController?.setViewMode(viewMode);
145
153
  let themeController: TileflowThemeController | null = null;
146
154
  let systemColorScheme: 'dark' | 'light' = 'light';
147
155
  let unsubscribeSystemColorScheme: (() => void) | null = null;
@@ -172,7 +180,7 @@
172
180
  : {defaultInteractionState: initialInteractionState}),
173
181
  });
174
182
  $: resolvedMode = resolveTileflowMapMode({mode});
175
- $: assertTileflowMapStyleInputs({source, theme, themeBlend, themeTransition});
183
+ $: assertTileflowMapStyleInputs({source, theme, timeOfDay, themeBlend, themeTransition});
176
184
  $: resolvedCaptureId = normalizeTileflowCaptureId(captureId);
177
185
  $: isImageMode = resolvedMode === 'image';
178
186
  $: mapName = source.map;
@@ -188,6 +196,7 @@
188
196
  colorScheme: systemColorScheme,
189
197
  manifestMap,
190
198
  theme,
199
+ timeOfDay,
191
200
  themeBlend,
192
201
  });
193
202
  $: themeBlendKey = themeBlend ? JSON.stringify(themeBlend.themes) : undefined;
@@ -450,6 +459,8 @@
450
459
  const unsubscribeSemanticTargets = semanticRuntimeTargetsUnsubscribe;
451
460
  const currentMap = mapInstance;
452
461
  const currentThemeController = themeController;
462
+ const currentVegetationController = vegetationController;
463
+ vegetationController = null;
453
464
  const worldRequestBridge = mapWorldRequestBridge;
454
465
  interactionRuntimesDisposing = true;
455
466
  mapFairUseNotice = null;
@@ -492,6 +503,7 @@
492
503
  () => semanticInteractionsForMap?.dispose(),
493
504
  () => annotationInteractionsForMap?.dispose(),
494
505
  () => lifecycleAttachment?.dispose(),
506
+ () => currentVegetationController?.dispose(),
495
507
  () => currentThemeController?.dispose(),
496
508
  () => worldRequestBridge?.dispose(),
497
509
  () => fairUseNotice?.dispose(),
@@ -610,6 +622,23 @@
610
622
  },
611
623
  });
612
624
 
625
+ vegetationController = createTileflowVegetation({
626
+ map: maplibreMap,
627
+ ...(themeController ? {controller: themeController} : {}),
628
+ visible: vegetation,
629
+ viewMode,
630
+ transformRequest: createTileflowTransformRequest({
631
+ getAnalytics: () => resolvedAnalytics,
632
+ sessionController: session,
633
+ sessionId: session.sessionId,
634
+ transformRequest: (url) =>
635
+ mapOptions?.transformRequest?.(
636
+ url,
637
+ 'Tile' as Parameters<NonNullable<TileflowMapOptions['transformRequest']>>[1],
638
+ ),
639
+ }),
640
+ });
641
+
613
642
  setBridgeInteractionDiagnostic('annotation-runtime', null);
614
643
  try {
615
644
  const annotationInteractionsForMap = createTileflowMapLibreDomRuntime<
@@ -1238,6 +1267,7 @@
1238
1267
  colorScheme: 'dark' | 'light';
1239
1268
  manifestMap: TileflowRuntimeManifestMap | null;
1240
1269
  theme: TileflowMapProps['theme'];
1270
+ timeOfDay: TileflowMapProps['timeOfDay'];
1241
1271
  themeBlend: TileflowMapProps['themeBlend'];
1242
1272
  }): Readonly<{error: boolean; name: string | undefined}> {
1243
1273
  // A blend shows its nearest theme until the blend style is ready, and names it while blending.
@@ -1255,7 +1285,12 @@
1255
1285
  }
1256
1286
  return {
1257
1287
  error: false,
1258
- name: resolveTileflowRuntimeTheme(input.manifestMap, selection, input.colorScheme).name,
1288
+ name: resolveTileflowRuntimeTheme(
1289
+ input.manifestMap,
1290
+ selection,
1291
+ input.colorScheme,
1292
+ input.themeBlend ? undefined : input.timeOfDay,
1293
+ ).name,
1259
1294
  };
1260
1295
  } catch {
1261
1296
  return {error: true, name: undefined};
package/src/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import type {TileflowTimeOfDay} from '@tileflow/core/runtime';
1
2
  import type {Map as MapLibreMap, MapOptions as MapLibreMapOptions} from 'maplibre-gl';
2
3
  import type {Snippet, SvelteComponentTyped} from 'svelte';
3
4
  import type {
4
5
  TileflowBrowserThemeBlendSelection,
5
6
  TileflowThemeTransition,
7
+ TileflowViewMode,
6
8
  TileflowThemeTransitionOptions,
7
9
  } from '@tileflow/core/browser';
8
10
  import type {
@@ -37,6 +39,8 @@ export type TileflowMapInteractionSnippet<
37
39
  > = Snippet<[context: TileflowInteractionViewContext<TAnnotation>]>;
38
40
 
39
41
  type TileflowMapBaseProps = {
42
+ vegetation?: boolean;
43
+ viewMode?: TileflowViewMode;
40
44
  alt?: string;
41
45
  analytics?: TileflowAnalytics;
42
46
  center?: [number, number];
@@ -49,6 +53,7 @@ type TileflowMapBaseProps = {
49
53
  mapOptions?: TileflowMapOptions;
50
54
  onThemeChange?: (transition: TileflowThemeTransition) => void;
51
55
  theme?: TileflowThemeSelection;
56
+ timeOfDay?: TileflowTimeOfDay;
52
57
  /**
53
58
  * Shows a continuous blend of the map's themes instead of `theme`. Moving `position` changes the
54
59
  * map at once; changing `themes` prepares a new blend. `hold` keeps labels, icons, and mixed
@@ -1,6 +1,7 @@
1
1
  type TileflowMapStyleInput = {
2
2
  source?: unknown;
3
3
  theme?: unknown;
4
+ timeOfDay?: unknown;
4
5
  themeBlend?: unknown;
5
6
  themeTransition?: unknown;
6
7
  };
@@ -1,11 +1,12 @@
1
1
  import {validateTileflowBrowserThemeBlendSelection} from '@tileflow/core/browser';
2
2
  import {
3
+ isTileflowTimeOfDay,
3
4
  validateTileflowRuntimeSource,
4
5
  validateTileflowThemeSelection,
5
6
  } from '@tileflow/core/runtime';
6
7
 
7
8
  /**
8
- * @typedef {{source?: unknown, theme?: unknown, themeBlend?: unknown, themeTransition?: unknown}}
9
+ * @typedef {{source?: unknown, theme?: unknown, timeOfDay?: unknown, themeBlend?: unknown, themeTransition?: unknown}}
9
10
  * TileflowMapStyleInput
10
11
  */
11
12
  /** @typedef {{ok: true} | {error: string; ok: false}} TileflowMapStyleInputValidation */
@@ -20,6 +21,9 @@ export function validateTileflowMapStyleInputs(input) {
20
21
  if (input.theme !== undefined && !validateTileflowThemeSelection(input.theme)) {
21
22
  return {error: 'theme must be a concrete portable theme name or "system"', ok: false};
22
23
  }
24
+ if (input.timeOfDay !== undefined && !isTileflowTimeOfDay(input.timeOfDay)) {
25
+ return {error: 'timeOfDay must be day, dawn, dusk, or night', ok: false};
26
+ }
23
27
  if (
24
28
  input.themeBlend !== undefined &&
25
29
  !validateTileflowBrowserThemeBlendSelection(input.themeBlend)