@tileflow/dev 0.1.0-alpha.32 → 0.1.0-alpha.33

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
@@ -36,7 +36,7 @@ needs no API key, but serving a map can still cause requests to its remote data
36
36
  The CLI's local Map DevTools provides a dockable layer inspector, loaded tiles, assets, scene
37
37
  controls and frame timing. Its element picker selects a layer and evaluates its rules using the
38
38
  feature clicked on the map.
39
- Performance's Overdraw overlay uses a heatmap with a visible pass-count legend and explanation.
39
+ Debug's Overdraw overlay uses a heatmap with a visible pass-count legend and explanation.
40
40
  See [Map DevTools and compiler inspection](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/docs/local-comparison-workbench-and-compiler-inspection.md)
41
41
  for interaction details and observation limits.
42
42
 
@@ -139,14 +139,20 @@ contract, including experimental preview-only rendering; it does not promise hos
139
139
  The package has no root entry point. `/server` also exposes the reusable Map DevTools shell. The CLI
140
140
  connects appearance controls and shared browser context through its optional local
141
141
  workflow adapter; see the [Map DevTools guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/docs/local-comparison-workbench-and-compiler-inspection.md).
142
- The navigation contains **Map**, **Layers**, **Tiles**, **Assets**, **Debug** and **Beacon**.
143
- Zoom, Bearing and Pitch occupy a separate row directly below it, with a live zoom slider,
144
- **Reset** to restore all three initial camera values, and **Copy context for agent**.
142
+ The navigation contains **Map**, **Layers**, **Tiles**, **Assets**, **Debug** and **Diagnostics**.
143
+ Zoom, Pitch and Bearing appear as **Z**, **P** and **B** directly below it, with live Zoom and Pitch
144
+ sliders and **Copy for AI**. Pitch and Bearing each have an inline reset to 0° within the map's
145
+ camera limits. Camera resets preserve the current zoom and map position.
145
146
  The active tab and selected layer remain in the URL across reloads. The menu provides left,
146
147
  right and bottom docking, System/Light/Dark appearance, and **Reset all changes**.
148
+ Side docking has a minimum width of 640 CSS pixels, including restored layouts.
147
149
 
148
- **Map** exposes time-of-day segments, palette cards with actual style swatches, 3D view,
150
+ **Map** exposes time-of-day segments, theme cards with actual style swatches, 3D view,
149
151
  Off/Grow/Fade building animation, and the map's module settings. The command selects the map.
152
+ Streets shows **Default**, **Faded** and **Monochrome**; Default keeps the compatible `light`
153
+ theme ID in configs, URLs and capture commands. Time of day is selected independently.
154
+ 3D view defaults to on for every map. Buildings fade in between zoom 15 and 15.25.
155
+ Toggling 3D view preserves the camera, including pitch; an explicit off setting stays off.
150
156
  Changes update the existing map after a 300 ms pause while the form remains editable. Superseded
151
157
  compilations are discarded. Runtime controls do not recompile the style. Scene and layer edits
152
158
  share the header Undo/Redo controls; source files stay unchanged.
@@ -165,19 +171,21 @@ Inspection reads resident data without issuing tile requests. MLT and inaccessib
165
171
  have explicit unavailable states.
166
172
 
167
173
  **Assets** separates Icons, 3D models and Fonts. Icons lists real registered images and loads actual
168
- sprite variants for the map's palettes and times of day. Models previews bounded samples of loaded
174
+ sprite variants for the map's themes and times of day. Models previews bounded samples of loaded
169
175
  controller meshes, with available counts, bytes and LODs. Fonts renders editable samples from actual
170
176
  font files or glyphs and links back to consuming layers.
171
177
 
172
178
  **Debug** contains overdraw, collision and tile-boundary overlays, explanations, and controls for
173
- the map's actual pixel ratio. **Beacon** runs 48 checks across Rendering, Loading, Legibility,
174
- Accessibility, Cartography and Integrity. Choose Desktop/Mobile and Active tour (default), Quick check or All zooms. The active tour measures
175
- navigation and settled frames across the current view and five world cities within an approximately
176
- one-minute budget, reports partial coverage explicitly and restores the original camera. Findings
177
- link to Layers, Tiles and Debug and can be copied with evidence for an agent. Unknown or
178
- informational measurements do not contribute passing scores. See
179
- [Beacon map audits](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/docs/beacon-map-audits.md)
180
- for sampling, scoring and measurement limits.
179
+ the map's actual pixel ratio. **Diagnostics** lists actionable findings under Readability, Style,
180
+ Assets and Performance. Problems identify confirmed failures; Review findings describe situations
181
+ that can be intentional. There are no quality scores or automatic camera tours. Style checks refresh
182
+ when the map changes; **Check view** collects bounded current-view evidence and briefly samples
183
+ drawing work. Findings open the affected layer and rule, show available evidence, and copy context
184
+ for an agent. Unavailable observations and stale results remain explicit. **Diagnosis** in
185
+ Layers describes the selected layer's zoom, visibility and feature-rule context without turning
186
+ empty viewport queries into errors. Legacy `tab=beacon` links open Diagnostics.
187
+ See [Map design diagnostics](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/docs/map-design-diagnostics.md)
188
+ for detectors, sampling and interpretation limits.
181
189
 
182
190
  The preview's globe rim follows the rendered canvas silhouette, including camera and viewport
183
191
  changes, and fades between zooms 3 and 6. Its colors follow the map's atmosphere when declared.
@@ -3,8 +3,8 @@ export { tileflowLandmarkRegionOf, tileflowLandmarkRegionZoom, tileflowLandmarkT
3
3
  import { TileflowBuildCatalog, TileflowBuildStyles, TileflowMapBuildManifestV1, TileflowRendererDeploymentArtifact, TileflowPreparedMapAssets, TileflowStyleInspection, TileflowMapBuildProvenanceV1 } from '@tileflow/core/build';
4
4
  import { TileflowRuntimeManifest } from '@tileflow/core/manifest';
5
5
  import { TileflowRenderer, TileflowNativeBuildRecord } from '@tileflow/core/native-profile';
6
- import { T as TileflowBuildAsset, a as TileflowIconResolutionOptions, P as PreparedTileflowBuildCatalog, b as TileflowSourceCatalog, c as PreparedTileflowCatalog } from './icons-B84H8Ymu.js';
7
- export { d as TileflowBuildingModelLevels, e as TileflowLandmarkSource, f as encodeTileflowLandmarkRegion, p as packageTileflowLandmarkTile, g as prepareTileflowBuildingModel } from './icons-B84H8Ymu.js';
6
+ import { T as TileflowBuildAsset, a as TileflowIconResolutionOptions, P as PreparedTileflowBuildCatalog, b as TileflowSourceCatalog, c as PreparedTileflowCatalog } from './icons-BdOehQmB.js';
7
+ export { d as TileflowBuildingModelLevels, e as TileflowLandmarkSource, f as encodeTileflowLandmarkRegion, p as packageTileflowLandmarkTile, g as prepareTileflowBuildingModel } from './icons-BdOehQmB.js';
8
8
  export { defaultTileflowConfigPath } from './config.js';
9
9
 
10
10
  /**
package/dist/artifacts.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  usesTileflowLineBackgroundGlyphs,
32
32
  writeTileflowArtifactPlan,
33
33
  writeTileflowBuildArtifacts
34
- } from "./chunk-CM6ZTYDJ.js";
34
+ } from "./chunk-WJOF6USY.js";
35
35
  import {
36
36
  getTileflowAssetBasePath,
37
37
  getTileflowAssetFileName,
@@ -43,7 +43,7 @@ import {
43
43
  encodeTileflowLandmarkRegion,
44
44
  packageTileflowLandmarkTile,
45
45
  prepareTileflowBuildingModel
46
- } from "./chunk-F4PLTZS4.js";
46
+ } from "./chunk-QYU4OW5A.js";
47
47
  import "./chunk-7C4F6GAX.js";
48
48
  import "./chunk-KDFTE4Q5.js";
49
49
  import {
@@ -25,7 +25,7 @@ import {
25
25
  sha256Hex as sha256Hex3,
26
26
  tileflowIconIdPattern,
27
27
  tileflowIconPackageLimits as tileflowIconPackageLimits4,
28
- tileflowModelContentType
28
+ tileflowModelContentType as tileflowModelContentType2
29
29
  } from "@tileflow/core";
30
30
 
31
31
  // src/icon-composition.ts
@@ -949,8 +949,12 @@ import {
949
949
  compareCodeUnits as compareCodeUnits4,
950
950
  encodeTileflowModels,
951
951
  encodeTileflowTreeModel,
952
+ hashTileflowModelBundleManifest,
952
953
  serializeTileflowLandmarkRegion,
953
954
  tileflowLandmarkTileOf,
955
+ tileflowModelBundleFileName,
956
+ tileflowModelBundleLimits,
957
+ tileflowModelContentType,
954
958
  tileflowTreeModelLimits as tileflowTreeModelLimits2
955
959
  } from "@tileflow/core";
956
960
 
@@ -1746,6 +1750,34 @@ function buildingModelEntry(id, levels) {
1746
1750
  )
1747
1751
  };
1748
1752
  }
1753
+ async function createTileflowModelBundle(buildings) {
1754
+ const entries = Object.entries(buildings).sort(([a], [b]) => compareCodeUnits4(a, b));
1755
+ if (entries.length === 0) return void 0;
1756
+ const totalBytes = entries.reduce((total, [, model]) => total + model.bytes.byteLength, 0);
1757
+ if (totalBytes > tileflowModelBundleLimits.maxPackageBytes)
1758
+ throw new RangeError(
1759
+ `The map's building models together are ${totalBytes} bytes once prepared; a hosted map takes at most ${tileflowModelBundleLimits.maxPackageBytes}. Simplify or remove models.`
1760
+ );
1761
+ const manifest = {
1762
+ format: "tileflow-model-bundle-v1",
1763
+ models: entries.map(([id, model]) => ({
1764
+ byteLength: model.bytes.byteLength,
1765
+ contentType: tileflowModelContentType,
1766
+ file: model.fileName,
1767
+ id,
1768
+ sha256: model.sha256
1769
+ }))
1770
+ };
1771
+ return {
1772
+ contentHash: await hashTileflowModelBundleManifest(manifest),
1773
+ manifest,
1774
+ files: entries.map(([, model]) => ({
1775
+ contentType: tileflowModelContentType,
1776
+ fileName: model.fileName,
1777
+ source: model.bytes
1778
+ }))
1779
+ };
1780
+ }
1749
1781
  function sha256Of(bytes) {
1750
1782
  return createHash("sha256").update(bytes).digest("hex");
1751
1783
  }
@@ -1840,8 +1872,9 @@ async function prepareTileflowMapTreeModels(directories, options) {
1840
1872
  failing = entry.near;
1841
1873
  const prepared2 = await prepareTileflowBuildingModel(id, files2);
1842
1874
  buildings[id] = {
1843
- fileName: `${id}-${prepared2.sha256.slice(0, 16)}.glb`,
1844
- bytes: prepared2.bytes
1875
+ fileName: tileflowModelBundleFileName(id, prepared2.sha256),
1876
+ bytes: prepared2.bytes,
1877
+ sha256: prepared2.sha256
1845
1878
  };
1846
1879
  } catch (error) {
1847
1880
  issues.push({
@@ -2182,7 +2215,7 @@ async function prepareTileflowCatalogIcons(project, options) {
2182
2215
  const buildingModels = {};
2183
2216
  for (const [id, model] of Object.entries(models.buildings)) {
2184
2217
  const fileName = `models/${mapName}/${model.fileName}`;
2185
- assets.push({ contentType: tileflowModelContentType, fileName, source: model.bytes });
2218
+ assets.push({ contentType: tileflowModelContentType2, fileName, source: model.bytes });
2186
2219
  buildingModels[id] = joinUrl(options.assetBaseUrl, fileName);
2187
2220
  }
2188
2221
  mapAssets[mapName] = {
@@ -2800,6 +2833,7 @@ export {
2800
2833
  prepareTileflowBuildingModel,
2801
2834
  packageTileflowLandmarkTile,
2802
2835
  encodeTileflowLandmarkRegion,
2836
+ createTileflowModelBundle,
2803
2837
  prepareTileflowMapTreeModels,
2804
2838
  renderTileflowIconAtlasPreview,
2805
2839
  TileflowIconCompilationError,
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  getTileflowIconWatchPaths,
10
10
  prepareTileflowCatalogIcons
11
- } from "./chunk-F4PLTZS4.js";
11
+ } from "./chunk-QYU4OW5A.js";
12
12
  import {
13
13
  TileflowStyleValidationError,
14
14
  normalizeTileflowStyleValidationIssues,
@@ -2518,7 +2518,8 @@ function retargetLocalFontAssetUrl(source, assets, generation) {
2518
2518
  function getMapBuildAssets(mapName, assets, fontAssets) {
2519
2519
  const selected = /* @__PURE__ */ new Map();
2520
2520
  for (const asset of assets) {
2521
- if (asset.fileName.startsWith(`icons/${mapName}/`)) selected.set(asset.fileName, asset);
2521
+ if (asset.fileName.startsWith(`icons/${mapName}/`) || asset.fileName.startsWith(`models/${mapName}/`))
2522
+ selected.set(asset.fileName, asset);
2522
2523
  }
2523
2524
  for (const asset of fontAssets) {
2524
2525
  selected.set(asset.fileName, asset);