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

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.30",
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.37 <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",
@@ -32,8 +32,11 @@
32
32
  attachTileflowAtmosphere,
33
33
  attachTileflowFairUseNotice,
34
34
  attachTileflowMapLifecycle,
35
+ attachTileflowNotices,
35
36
  createTileflowSessionStarter,
36
37
  createTileflowThemeController,
38
+ createTileflowVegetation,
39
+ type TileflowVegetationController,
37
40
  createTileflowTransformRequest,
38
41
  getTileflowSystemColorScheme,
39
42
  loadTileflowStyleFonts,
@@ -71,7 +74,7 @@
71
74
  type TileflowMapLibreSemanticDomRenderTarget,
72
75
  type TileflowMapLibreSemanticDomRuntime,
73
76
  } from '@tileflow/interactions/maplibre';
74
- import type {TileflowMapProps} from './index.js';
77
+ import type {TileflowMapOptions, TileflowMapProps} from './index.js';
75
78
  import {loadTileflowMapLibre} from './maplibre.js';
76
79
  import {assertTileflowMapStyleInputs} from './style-source.js';
77
80
 
@@ -99,7 +102,10 @@
99
102
  export let popup: TileflowMapProps['popup'] = undefined;
100
103
  export let source: TileflowMapProps['source'];
101
104
  export let theme: TileflowMapProps['theme'] = undefined;
105
+ export let timeOfDay: TileflowMapProps['timeOfDay'] = undefined;
102
106
  export let themeBlend: TileflowMapProps['themeBlend'] = undefined;
107
+ export let vegetation: TileflowMapProps['vegetation'] = undefined;
108
+ export let viewMode: NonNullable<TileflowMapProps['viewMode']> = '2d';
103
109
  export let themeTransition: TileflowMapProps['themeTransition'] = undefined;
104
110
  export let tooltip: TileflowMapProps['tooltip'] = undefined;
105
111
  export let zoom: TileflowMapProps['zoom'] = undefined;
@@ -142,6 +148,9 @@
142
148
  let interactionRuntimesDisposing = false;
143
149
  let mapResizeObserver: ResizeObserver | null = null;
144
150
  let mapWorldRequestBridge: TileflowWorldRequestBridge | null = null;
151
+ let vegetationController: TileflowVegetationController | null = null;
152
+ $: vegetationController?.setVisible(vegetation);
153
+ $: vegetationController?.setViewMode(viewMode);
145
154
  let themeController: TileflowThemeController | null = null;
146
155
  let systemColorScheme: 'dark' | 'light' = 'light';
147
156
  let unsubscribeSystemColorScheme: (() => void) | null = null;
@@ -172,7 +181,7 @@
172
181
  : {defaultInteractionState: initialInteractionState}),
173
182
  });
174
183
  $: resolvedMode = resolveTileflowMapMode({mode});
175
- $: assertTileflowMapStyleInputs({source, theme, themeBlend, themeTransition});
184
+ $: assertTileflowMapStyleInputs({source, theme, timeOfDay, themeBlend, themeTransition});
176
185
  $: resolvedCaptureId = normalizeTileflowCaptureId(captureId);
177
186
  $: isImageMode = resolvedMode === 'image';
178
187
  $: mapName = source.map;
@@ -188,6 +197,7 @@
188
197
  colorScheme: systemColorScheme,
189
198
  manifestMap,
190
199
  theme,
200
+ timeOfDay,
191
201
  themeBlend,
192
202
  });
193
203
  $: themeBlendKey = themeBlend ? JSON.stringify(themeBlend.themes) : undefined;
@@ -450,6 +460,8 @@
450
460
  const unsubscribeSemanticTargets = semanticRuntimeTargetsUnsubscribe;
451
461
  const currentMap = mapInstance;
452
462
  const currentThemeController = themeController;
463
+ const currentVegetationController = vegetationController;
464
+ vegetationController = null;
453
465
  const worldRequestBridge = mapWorldRequestBridge;
454
466
  interactionRuntimesDisposing = true;
455
467
  mapFairUseNotice = null;
@@ -492,6 +504,7 @@
492
504
  () => semanticInteractionsForMap?.dispose(),
493
505
  () => annotationInteractionsForMap?.dispose(),
494
506
  () => lifecycleAttachment?.dispose(),
507
+ () => currentVegetationController?.dispose(),
495
508
  () => currentThemeController?.dispose(),
496
509
  () => worldRequestBridge?.dispose(),
497
510
  () => fairUseNotice?.dispose(),
@@ -592,6 +605,7 @@
592
605
 
593
606
  mapInstance = maplibreMap;
594
607
  attachTileflowAtmosphere(maplibreMap);
608
+ attachTileflowNotices(maplibreMap);
595
609
  themeController =
596
610
  runtime.theme === undefined
597
611
  ? null
@@ -610,6 +624,23 @@
610
624
  },
611
625
  });
612
626
 
627
+ vegetationController = createTileflowVegetation({
628
+ map: maplibreMap,
629
+ ...(themeController ? {controller: themeController} : {}),
630
+ visible: vegetation,
631
+ viewMode,
632
+ transformRequest: createTileflowTransformRequest({
633
+ getAnalytics: () => resolvedAnalytics,
634
+ sessionController: session,
635
+ sessionId: session.sessionId,
636
+ transformRequest: (url) =>
637
+ mapOptions?.transformRequest?.(
638
+ url,
639
+ 'Tile' as Parameters<NonNullable<TileflowMapOptions['transformRequest']>>[1],
640
+ ),
641
+ }),
642
+ });
643
+
613
644
  setBridgeInteractionDiagnostic('annotation-runtime', null);
614
645
  try {
615
646
  const annotationInteractionsForMap = createTileflowMapLibreDomRuntime<
@@ -1238,6 +1269,7 @@
1238
1269
  colorScheme: 'dark' | 'light';
1239
1270
  manifestMap: TileflowRuntimeManifestMap | null;
1240
1271
  theme: TileflowMapProps['theme'];
1272
+ timeOfDay: TileflowMapProps['timeOfDay'];
1241
1273
  themeBlend: TileflowMapProps['themeBlend'];
1242
1274
  }): Readonly<{error: boolean; name: string | undefined}> {
1243
1275
  // A blend shows its nearest theme until the blend style is ready, and names it while blending.
@@ -1255,7 +1287,12 @@
1255
1287
  }
1256
1288
  return {
1257
1289
  error: false,
1258
- name: resolveTileflowRuntimeTheme(input.manifestMap, selection, input.colorScheme).name,
1290
+ name: resolveTileflowRuntimeTheme(
1291
+ input.manifestMap,
1292
+ selection,
1293
+ input.colorScheme,
1294
+ input.themeBlend ? undefined : input.timeOfDay,
1295
+ ).name,
1259
1296
  };
1260
1297
  } catch {
1261
1298
  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)