@tileflow/svelte 0.1.0-alpha.27 → 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 +13 -0
- package/package.json +5 -5
- package/src/TileflowMap.svelte +42 -11
- package/src/index.d.ts +13 -4
- package/src/style-source.d.ts +1 -0
- package/src/style-source.js +11 -4
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.
|
|
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,16 +44,16 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@tileflow/core": ">=0.1.0-alpha.
|
|
48
|
-
"@tileflow/interactions": ">=0.1.0-alpha.
|
|
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",
|
|
52
52
|
"svelte": ">=5 <6"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
|
-
"maplibre-gl": "6.
|
|
56
|
-
"svelte": "^5.
|
|
55
|
+
"maplibre-gl": "6.13.0",
|
|
56
|
+
"svelte": "^5.57.2",
|
|
57
57
|
"svelte-check": "^4.3.4"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
package/src/TileflowMap.svelte
CHANGED
|
@@ -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,10 +196,12 @@
|
|
|
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;
|
|
194
203
|
$: themeBlendPosition = themeBlend?.position;
|
|
204
|
+
$: themeBlendHold = themeBlend?.hold === true;
|
|
195
205
|
$: resolvedThemeName = themeResolution.name;
|
|
196
206
|
$: manifestView = resolveTileflowRuntimeView({manifestMap});
|
|
197
207
|
$: manifestCenter = normalizeTileflowRuntimeCenter(manifestView.center);
|
|
@@ -307,6 +317,7 @@
|
|
|
307
317
|
$: if (mounted) {
|
|
308
318
|
blendStyles;
|
|
309
319
|
themeBlendPosition;
|
|
320
|
+
themeBlendHold;
|
|
310
321
|
void switchBlend();
|
|
311
322
|
}
|
|
312
323
|
|
|
@@ -448,6 +459,8 @@
|
|
|
448
459
|
const unsubscribeSemanticTargets = semanticRuntimeTargetsUnsubscribe;
|
|
449
460
|
const currentMap = mapInstance;
|
|
450
461
|
const currentThemeController = themeController;
|
|
462
|
+
const currentVegetationController = vegetationController;
|
|
463
|
+
vegetationController = null;
|
|
451
464
|
const worldRequestBridge = mapWorldRequestBridge;
|
|
452
465
|
interactionRuntimesDisposing = true;
|
|
453
466
|
mapFairUseNotice = null;
|
|
@@ -490,6 +503,7 @@
|
|
|
490
503
|
() => semanticInteractionsForMap?.dispose(),
|
|
491
504
|
() => annotationInteractionsForMap?.dispose(),
|
|
492
505
|
() => lifecycleAttachment?.dispose(),
|
|
506
|
+
() => currentVegetationController?.dispose(),
|
|
493
507
|
() => currentThemeController?.dispose(),
|
|
494
508
|
() => worldRequestBridge?.dispose(),
|
|
495
509
|
() => fairUseNotice?.dispose(),
|
|
@@ -579,8 +593,6 @@
|
|
|
579
593
|
pitch: resolvedPitch,
|
|
580
594
|
style: runtime.style as StyleSpecification | string,
|
|
581
595
|
transformRequest: createTileflowTransformRequest({
|
|
582
|
-
always: true,
|
|
583
|
-
asyncAnalyticsTiming: 'request',
|
|
584
596
|
getAnalytics: () => resolvedAnalytics,
|
|
585
597
|
sessionController: session,
|
|
586
598
|
sessionId: session.sessionId,
|
|
@@ -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<
|
|
@@ -784,7 +813,7 @@
|
|
|
784
813
|
if (!themeController || !blendStyles || position === undefined) return;
|
|
785
814
|
if (runtimeStyle) activeRuntimeResource = runtimeStyle;
|
|
786
815
|
const result = await themeController.setBlend(
|
|
787
|
-
{position, themes: blendStyles},
|
|
816
|
+
{hold: themeBlendHold, position, themes: blendStyles},
|
|
788
817
|
{transition: themeTransition},
|
|
789
818
|
);
|
|
790
819
|
if (result.status === 'failed') {
|
|
@@ -1035,11 +1064,7 @@
|
|
|
1035
1064
|
}
|
|
1036
1065
|
|
|
1037
1066
|
type BridgeInteractionDiagnosticSource =
|
|
1038
|
-
| '
|
|
1039
|
-
| 'portal'
|
|
1040
|
-
| 'renderers'
|
|
1041
|
-
| 'semantic-runtime'
|
|
1042
|
-
| 'state';
|
|
1067
|
+
'annotation-runtime' | 'portal' | 'renderers' | 'semantic-runtime' | 'state';
|
|
1043
1068
|
|
|
1044
1069
|
function setBridgeInteractionDiagnostic(
|
|
1045
1070
|
source: BridgeInteractionDiagnosticSource,
|
|
@@ -1242,6 +1267,7 @@
|
|
|
1242
1267
|
colorScheme: 'dark' | 'light';
|
|
1243
1268
|
manifestMap: TileflowRuntimeManifestMap | null;
|
|
1244
1269
|
theme: TileflowMapProps['theme'];
|
|
1270
|
+
timeOfDay: TileflowMapProps['timeOfDay'];
|
|
1245
1271
|
themeBlend: TileflowMapProps['themeBlend'];
|
|
1246
1272
|
}): Readonly<{error: boolean; name: string | undefined}> {
|
|
1247
1273
|
// A blend shows its nearest theme until the blend style is ready, and names it while blending.
|
|
@@ -1259,7 +1285,12 @@
|
|
|
1259
1285
|
}
|
|
1260
1286
|
return {
|
|
1261
1287
|
error: false,
|
|
1262
|
-
name: resolveTileflowRuntimeTheme(
|
|
1288
|
+
name: resolveTileflowRuntimeTheme(
|
|
1289
|
+
input.manifestMap,
|
|
1290
|
+
selection,
|
|
1291
|
+
input.colorScheme,
|
|
1292
|
+
input.themeBlend ? undefined : input.timeOfDay,
|
|
1293
|
+
).name,
|
|
1263
1294
|
};
|
|
1264
1295
|
} catch {
|
|
1265
1296
|
return {error: true, name: undefined};
|
package/src/index.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
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
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
TileflowBrowserThemeBlendSelection,
|
|
6
|
+
TileflowThemeTransition,
|
|
7
|
+
TileflowViewMode,
|
|
8
|
+
TileflowThemeTransitionOptions,
|
|
9
|
+
} from '@tileflow/core/browser';
|
|
4
10
|
import type {
|
|
5
11
|
TileflowAnalytics,
|
|
6
12
|
TileflowRuntimeSource,
|
|
7
|
-
TileflowThemeBlendSelection,
|
|
8
13
|
TileflowThemeSelection,
|
|
9
14
|
} from '@tileflow/core/runtime';
|
|
10
15
|
import type {
|
|
@@ -34,6 +39,8 @@ export type TileflowMapInteractionSnippet<
|
|
|
34
39
|
> = Snippet<[context: TileflowInteractionViewContext<TAnnotation>]>;
|
|
35
40
|
|
|
36
41
|
type TileflowMapBaseProps = {
|
|
42
|
+
vegetation?: boolean;
|
|
43
|
+
viewMode?: TileflowViewMode;
|
|
37
44
|
alt?: string;
|
|
38
45
|
analytics?: TileflowAnalytics;
|
|
39
46
|
center?: [number, number];
|
|
@@ -46,11 +53,13 @@ type TileflowMapBaseProps = {
|
|
|
46
53
|
mapOptions?: TileflowMapOptions;
|
|
47
54
|
onThemeChange?: (transition: TileflowThemeTransition) => void;
|
|
48
55
|
theme?: TileflowThemeSelection;
|
|
56
|
+
timeOfDay?: TileflowTimeOfDay;
|
|
49
57
|
/**
|
|
50
58
|
* Shows a continuous blend of the map's themes instead of `theme`. Moving `position` changes the
|
|
51
|
-
* map at once; changing `themes` prepares a new blend.
|
|
59
|
+
* map at once; changing `themes` prepares a new blend. `hold` keeps labels, icons, and mixed
|
|
60
|
+
* artwork back during a camera move; clearing it brings them in at once.
|
|
52
61
|
*/
|
|
53
|
-
themeBlend?:
|
|
62
|
+
themeBlend?: TileflowBrowserThemeBlendSelection;
|
|
54
63
|
/** Cross-fades theme changes, including entering and leaving a blend. */
|
|
55
64
|
themeTransition?: TileflowThemeTransitionOptions;
|
|
56
65
|
zoom?: number;
|
package/src/style-source.d.ts
CHANGED
package/src/style-source.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import {validateTileflowBrowserThemeBlendSelection} from '@tileflow/core/browser';
|
|
1
2
|
import {
|
|
3
|
+
isTileflowTimeOfDay,
|
|
2
4
|
validateTileflowRuntimeSource,
|
|
3
|
-
validateTileflowThemeBlendSelection,
|
|
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,10 +21,16 @@ 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
|
}
|
|
23
|
-
if (input.
|
|
24
|
+
if (input.timeOfDay !== undefined && !isTileflowTimeOfDay(input.timeOfDay)) {
|
|
25
|
+
return {error: 'timeOfDay must be day, dawn, dusk, or night', ok: false};
|
|
26
|
+
}
|
|
27
|
+
if (
|
|
28
|
+
input.themeBlend !== undefined &&
|
|
29
|
+
!validateTileflowBrowserThemeBlendSelection(input.themeBlend)
|
|
30
|
+
) {
|
|
24
31
|
return {
|
|
25
32
|
error:
|
|
26
|
-
'themeBlend must name two to eight concrete themes
|
|
33
|
+
'themeBlend must name two to eight concrete themes, a position from 0 to themes.length - 1, and an optional boolean hold',
|
|
27
34
|
ok: false,
|
|
28
35
|
};
|
|
29
36
|
}
|