@humanforest/nuxt-layer 0.1.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.
Files changed (324) hide show
  1. package/LICENSE +67 -0
  2. package/README.md +208 -0
  3. package/app.config.ts +10 -0
  4. package/assets/icons/forest/bike-asterisk.svg +21 -0
  5. package/assets/icons/forest/bike-down.svg +19 -0
  6. package/assets/icons/forest/bike-off.svg +20 -0
  7. package/assets/icons/forest/bike-up.svg +19 -0
  8. package/assets/icons/forest/bike-x.svg +19 -0
  9. package/assets/icons/forest/bike.svg +18 -0
  10. package/assets/icons/forest/mark-fill.svg +6 -0
  11. package/assets/icons/forest/mark.svg +6 -0
  12. package/assets/icons/forest/parking.svg +3 -0
  13. package/assets/icons/forest/star-fill.svg +4 -0
  14. package/assets/icons/forest/star.svg +4 -0
  15. package/assets/icons/forest/traffic-light-caution.svg +8 -0
  16. package/assets/icons/forest/traffic-light-go.svg +8 -0
  17. package/assets/icons/forest/traffic-light-lit.svg +8 -0
  18. package/assets/icons/forest/traffic-light-stop.svg +8 -0
  19. package/assets/icons/forest/traffic-light.svg +8 -0
  20. package/nuxt.config.ts +81 -0
  21. package/package.json +35 -0
  22. package/packages/charts/src/FBoroughShape.vue +52 -0
  23. package/packages/charts/src/FCalendarGrid.vue +332 -0
  24. package/packages/charts/src/FCellLegend.vue +54 -0
  25. package/packages/charts/src/FChartFrame.vue +201 -0
  26. package/packages/charts/src/FChartFrameSingle.vue +91 -0
  27. package/packages/charts/src/FChartLegend.vue +26 -0
  28. package/packages/charts/src/FDistributionBar.vue +224 -0
  29. package/packages/charts/src/FDottedMap.vue +335 -0
  30. package/packages/charts/src/FLondonMap.vue +399 -0
  31. package/packages/charts/src/FSparkline.vue +198 -0
  32. package/packages/charts/src/FStatusTrack.vue +151 -0
  33. package/packages/charts/src/cellSize.ts +46 -0
  34. package/packages/charts/src/distribution.ts +99 -0
  35. package/packages/charts/src/engine.ts +15 -0
  36. package/packages/charts/src/forestTooltip.ts +110 -0
  37. package/packages/charts/src/fromCategories.ts +43 -0
  38. package/packages/charts/src/index.ts +87 -0
  39. package/packages/charts/src/londonAreas.ts +75 -0
  40. package/packages/charts/src/londonGrid.ts +67 -0
  41. package/packages/charts/src/motionDuration.ts +49 -0
  42. package/packages/charts/src/presets.ts +143 -0
  43. package/packages/charts/src/resolveVar.ts +21 -0
  44. package/packages/charts/src/snapTooltip.ts +154 -0
  45. package/packages/charts/src/tooltipStandIn.ts +58 -0
  46. package/packages/charts/src/useCellScale.ts +155 -0
  47. package/packages/charts/src/useChartPalette.ts +61 -0
  48. package/packages/charts/src/useChartRepaintKey.ts +22 -0
  49. package/packages/charts/src/useThemeVersion.ts +17 -0
  50. package/packages/frames/src/FBrowserFrame.vue +53 -0
  51. package/packages/frames/src/FDeviceFrame.vue +242 -0
  52. package/packages/frames/src/FFitFrame.vue +83 -0
  53. package/packages/frames/src/art/iphone-11.svg +124 -0
  54. package/packages/frames/src/art/iphone-12.svg +601 -0
  55. package/packages/frames/src/art/iphone-13-pro.svg +820 -0
  56. package/packages/frames/src/art/iphone-13.svg +849 -0
  57. package/packages/frames/src/art/iphone-14.svg +681 -0
  58. package/packages/frames/src/art/iphone-15-pro.svg +633 -0
  59. package/packages/frames/src/art/iphone-15.svg +713 -0
  60. package/packages/frames/src/art/iphone-16-plus.svg +685 -0
  61. package/packages/frames/src/art/iphone-16-pro-max.svg +611 -0
  62. package/packages/frames/src/art/iphone-16-pro.svg +631 -0
  63. package/packages/frames/src/art/iphone-16.svg +713 -0
  64. package/packages/frames/src/art/iphone-17-pro-max.svg +355 -0
  65. package/packages/frames/src/art/iphone-17.svg +305 -0
  66. package/packages/frames/src/art/iphone-air.svg +389 -0
  67. package/packages/frames/src/art/iphone-se-3.svg +473 -0
  68. package/packages/frames/src/art/iphone-x.svg +652 -0
  69. package/packages/frames/src/art/pixel-10-pro-xl.svg +32 -0
  70. package/packages/frames/src/art/pixel-10-pro.svg +32 -0
  71. package/packages/frames/src/art/pixel-10.svg +32 -0
  72. package/packages/frames/src/art/pixel-8-pro.svg +208 -0
  73. package/packages/frames/src/art/pixel-8.svg +208 -0
  74. package/packages/frames/src/art/pixel-8a.svg +8 -0
  75. package/packages/frames/src/art/pixel-9-pro-xl.svg +32 -0
  76. package/packages/frames/src/art/pixel-9-pro.svg +34 -0
  77. package/packages/frames/src/art/pixel-9a.svg +25 -0
  78. package/packages/frames/src/art.ts +29 -0
  79. package/packages/frames/src/devices.ts +337 -0
  80. package/packages/frames/src/index.ts +15 -0
  81. package/packages/tokens/geo/london-boroughs.json +1 -0
  82. package/packages/tokens/geo/london-dots-coarse.json +1 -0
  83. package/packages/tokens/geo/london-dots-fine.json +1 -0
  84. package/packages/tokens/geo/london-dots-medium.json +1 -0
  85. package/packages/tokens/geo/london-dots-ultra.json +1 -0
  86. package/packages/tokens/geo/london-wards.json +1 -0
  87. package/packages/tokens/glyphs/glyphs.json +1 -0
  88. package/packages/tokens/logos/f-rot.svg +4 -0
  89. package/packages/tokens/logos/f.svg +4 -0
  90. package/packages/tokens/logos/favicon-c2w.svg +9 -0
  91. package/packages/tokens/logos/favicon-console.svg +9 -0
  92. package/packages/tokens/logos/favicon-ds.svg +9 -0
  93. package/packages/tokens/logos/favicon-fleet.svg +9 -0
  94. package/packages/tokens/logos/favicon-flex.svg +9 -0
  95. package/packages/tokens/logos/favicon-plus.svg +9 -0
  96. package/packages/tokens/logos/favicon-radar.svg +9 -0
  97. package/packages/tokens/logos/favicon-tower.svg +9 -0
  98. package/packages/tokens/logos/lockup-horizontal.svg +17 -0
  99. package/packages/tokens/logos/lockup-vertical.svg +17 -0
  100. package/packages/tokens/logos/mark-mono.svg +4 -0
  101. package/packages/tokens/logos/mark.svg +7 -0
  102. package/packages/tokens/logos/wordmark.svg +9 -0
  103. package/packages/tokens/src/colourEngine.ts +604 -0
  104. package/packages/tokens/src/glyphs.ts +127 -0
  105. package/packages/tokens/src/logo.ts +50 -0
  106. package/packages/tokens/src/subbrands.ts +44 -0
  107. package/packages/tokens/src/sublogo.ts +80 -0
  108. package/packages/ui/icons/forest/map/forest-place-count.svg +21 -0
  109. package/packages/ui/icons/forest/map/forest-place-marker.svg +17 -0
  110. package/packages/ui/icons/forest/map/forest-vehicle-marker.svg +73 -0
  111. package/packages/ui/icons/forest/map/manifest.json +373 -0
  112. package/packages/ui/icons/forest/map/place-count-manifest.json +83 -0
  113. package/packages/ui/icons/forest/map/place-manifest.json +74 -0
  114. package/packages/ui/src/address/address.ts +125 -0
  115. package/packages/ui/src/address/autofill.ts +78 -0
  116. package/packages/ui/src/address/geocode.ts +55 -0
  117. package/packages/ui/src/address/index.ts +31 -0
  118. package/packages/ui/src/address/validate.ts +91 -0
  119. package/packages/ui/src/canvas/FCanvasCard.vue +97 -0
  120. package/packages/ui/src/canvas/FCanvasControl.vue +121 -0
  121. package/packages/ui/src/canvas/FCanvasControlGroup.vue +100 -0
  122. package/packages/ui/src/canvas/FCanvasFlyout.vue +216 -0
  123. package/packages/ui/src/canvas/FCanvasHud.vue +402 -0
  124. package/packages/ui/src/canvas/canvasSurface.ts +39 -0
  125. package/packages/ui/src/canvas/index.ts +17 -0
  126. package/packages/ui/src/contexts/ForestContext.vue +53 -0
  127. package/packages/ui/src/contexts/contexts.ts +153 -0
  128. package/packages/ui/src/contexts/index.ts +23 -0
  129. package/packages/ui/src/contexts/marketing-theme.ts +214 -0
  130. package/packages/ui/src/contexts/mobile-theme.ts +402 -0
  131. package/packages/ui/src/filter/FFilterBar.vue +72 -0
  132. package/packages/ui/src/filter/FFilterChip.vue +362 -0
  133. package/packages/ui/src/filter/FFilterClauses.vue +104 -0
  134. package/packages/ui/src/filter/FFilterTrigger.vue +183 -0
  135. package/packages/ui/src/filter/filter.theme.ts +27 -0
  136. package/packages/ui/src/filter/filterClause.ts +265 -0
  137. package/packages/ui/src/filter/filterPredicate.ts +134 -0
  138. package/packages/ui/src/filter/filterSchema.ts +82 -0
  139. package/packages/ui/src/filter/index.ts +36 -0
  140. package/packages/ui/src/forest-preset.ts +68 -0
  141. package/packages/ui/src/icons.ts +79 -0
  142. package/packages/ui/src/index.ts +17 -0
  143. package/packages/ui/src/kpi/FKpi.vue +253 -0
  144. package/packages/ui/src/kpi/FKpiGroup.vue +161 -0
  145. package/packages/ui/src/kpi/index.ts +20 -0
  146. package/packages/ui/src/kpi/kpi.theme.ts +168 -0
  147. package/packages/ui/src/kpi/kpiDelta.ts +82 -0
  148. package/packages/ui/src/kpi/kpiFormat.ts +72 -0
  149. package/packages/ui/src/kpi/kpiGroupState.ts +63 -0
  150. package/packages/ui/src/logo/FLogo.vue +52 -0
  151. package/packages/ui/src/logo/FSubLogo.vue +214 -0
  152. package/packages/ui/src/logo/index.ts +8 -0
  153. package/packages/ui/src/map/FMap.vue +355 -0
  154. package/packages/ui/src/map/FMapCompass.vue +154 -0
  155. package/packages/ui/src/map/FMapCoordinates.vue +134 -0
  156. package/packages/ui/src/map/FMapDrawTools.vue +116 -0
  157. package/packages/ui/src/map/FMapFullscreen.vue +92 -0
  158. package/packages/ui/src/map/FMapGeolocate.vue +208 -0
  159. package/packages/ui/src/map/FMapLayers.vue +75 -0
  160. package/packages/ui/src/map/FMapLegend.vue +45 -0
  161. package/packages/ui/src/map/FMapPopup.vue +129 -0
  162. package/packages/ui/src/map/FMapRamp.vue +69 -0
  163. package/packages/ui/src/map/FMapRegion.vue +77 -0
  164. package/packages/ui/src/map/FMapScale.vue +107 -0
  165. package/packages/ui/src/map/FMapSearch.vue +362 -0
  166. package/packages/ui/src/map/FMapTilt.vue +87 -0
  167. package/packages/ui/src/map/FMapTools.vue +61 -0
  168. package/packages/ui/src/map/FMapZoom.vue +81 -0
  169. package/packages/ui/src/map/FMarker.vue +218 -0
  170. package/packages/ui/src/map/FTrackScrubber.vue +94 -0
  171. package/packages/ui/src/map/FVehicleLegend.vue +72 -0
  172. package/packages/ui/src/map/FVehicleMark.vue +166 -0
  173. package/packages/ui/src/map/bin.ts +196 -0
  174. package/packages/ui/src/map/coordinates.ts +83 -0
  175. package/packages/ui/src/map/density.ts +401 -0
  176. package/packages/ui/src/map/draw.ts +356 -0
  177. package/packages/ui/src/map/ease.ts +67 -0
  178. package/packages/ui/src/map/fullscreen.ts +59 -0
  179. package/packages/ui/src/map/heat.ts +160 -0
  180. package/packages/ui/src/map/index.ts +351 -0
  181. package/packages/ui/src/map/liveMarkers.ts +60 -0
  182. package/packages/ui/src/map/map.css +116 -0
  183. package/packages/ui/src/map/mapColor.ts +31 -0
  184. package/packages/ui/src/map/mapContext.ts +12 -0
  185. package/packages/ui/src/map/mapLayers.ts +55 -0
  186. package/packages/ui/src/map/mapLegend.ts +70 -0
  187. package/packages/ui/src/map/mapSearch.theme.ts +79 -0
  188. package/packages/ui/src/map/mapSearch.ts +279 -0
  189. package/packages/ui/src/map/mapUrl.ts +117 -0
  190. package/packages/ui/src/map/markerAsset.ts +3 -0
  191. package/packages/ui/src/map/padding.ts +39 -0
  192. package/packages/ui/src/map/place.ts +192 -0
  193. package/packages/ui/src/map/ramp.ts +95 -0
  194. package/packages/ui/src/map/regionSelect.ts +163 -0
  195. package/packages/ui/src/map/route.ts +167 -0
  196. package/packages/ui/src/map/scale.ts +329 -0
  197. package/packages/ui/src/map/scaleBar.ts +67 -0
  198. package/packages/ui/src/map/selectionModel.ts +50 -0
  199. package/packages/ui/src/map/sources/coordinates.ts +58 -0
  200. package/packages/ui/src/map/sources/mapboxPlaces.ts +71 -0
  201. package/packages/ui/src/map/style.ts +14 -0
  202. package/packages/ui/src/map/track.ts +279 -0
  203. package/packages/ui/src/map/useFeatureSelect.ts +230 -0
  204. package/packages/ui/src/map/useLiveMarkers.ts +84 -0
  205. package/packages/ui/src/map/useMap.ts +150 -0
  206. package/packages/ui/src/map/useMapDraw.ts +776 -0
  207. package/packages/ui/src/map/useMapOverlay.ts +421 -0
  208. package/packages/ui/src/map/useMapTableSelection.ts +101 -0
  209. package/packages/ui/src/map/useMapUrlState.ts +155 -0
  210. package/packages/ui/src/map/useMarkerSource.ts +163 -0
  211. package/packages/ui/src/map/useRegionSelect.ts +309 -0
  212. package/packages/ui/src/map/useTokenMode.ts +61 -0
  213. package/packages/ui/src/map/useTrackPlayback.ts +131 -0
  214. package/packages/ui/src/map/useVehicleFilter.ts +51 -0
  215. package/packages/ui/src/map/useVisibleFeatures.ts +124 -0
  216. package/packages/ui/src/map/vehicle.ts +807 -0
  217. package/packages/ui/src/map/vehicleFilter.ts +284 -0
  218. package/packages/ui/src/map/vehicleLegend.ts +155 -0
  219. package/packages/ui/src/map/visibleFeatures.ts +192 -0
  220. package/packages/ui/src/map/zone.ts +291 -0
  221. package/packages/ui/src/shell/FAppNavbar.vue +68 -0
  222. package/packages/ui/src/shell/FAppShell.vue +163 -0
  223. package/packages/ui/src/shell/FAppSidebar.vue +215 -0
  224. package/packages/ui/src/shell/FPageToolbar.vue +126 -0
  225. package/packages/ui/src/shell/FScrollShadow.vue +43 -0
  226. package/packages/ui/src/shell/FSidePanel.vue +258 -0
  227. package/packages/ui/src/shell/FToolbarActions.vue +32 -0
  228. package/packages/ui/src/shell/index.ts +33 -0
  229. package/packages/ui/src/shell/nav.ts +37 -0
  230. package/packages/ui/src/shell/pageToolbar.ts +69 -0
  231. package/packages/ui/src/shell/shell.ts +74 -0
  232. package/packages/ui/src/shell/sidePanel.ts +115 -0
  233. package/packages/ui/src/themes/accordion.ts +36 -0
  234. package/packages/ui/src/themes/alert.ts +16 -0
  235. package/packages/ui/src/themes/auth-form.ts +19 -0
  236. package/packages/ui/src/themes/avatar-group.ts +9 -0
  237. package/packages/ui/src/themes/avatar.ts +18 -0
  238. package/packages/ui/src/themes/badge.ts +51 -0
  239. package/packages/ui/src/themes/banner.ts +21 -0
  240. package/packages/ui/src/themes/breadcrumb.ts +10 -0
  241. package/packages/ui/src/themes/button.mechanics.ts +191 -0
  242. package/packages/ui/src/themes/button.ts +136 -0
  243. package/packages/ui/src/themes/calendar.ts +29 -0
  244. package/packages/ui/src/themes/card.ts +67 -0
  245. package/packages/ui/src/themes/carousel.ts +41 -0
  246. package/packages/ui/src/themes/checkbox-group.ts +20 -0
  247. package/packages/ui/src/themes/checkbox.ts +47 -0
  248. package/packages/ui/src/themes/chip.ts +50 -0
  249. package/packages/ui/src/themes/collapsible.ts +26 -0
  250. package/packages/ui/src/themes/color-picker.ts +13 -0
  251. package/packages/ui/src/themes/command-palette.ts +37 -0
  252. package/packages/ui/src/themes/container.ts +14 -0
  253. package/packages/ui/src/themes/context-menu.ts +38 -0
  254. package/packages/ui/src/themes/dashboard-group.ts +11 -0
  255. package/packages/ui/src/themes/dashboard-navbar.ts +10 -0
  256. package/packages/ui/src/themes/dashboard-panel.ts +18 -0
  257. package/packages/ui/src/themes/dashboard-resize-handle.ts +35 -0
  258. package/packages/ui/src/themes/dashboard-sidebar-collapse.ts +7 -0
  259. package/packages/ui/src/themes/dashboard-sidebar-toggle.ts +7 -0
  260. package/packages/ui/src/themes/dashboard-sidebar.ts +58 -0
  261. package/packages/ui/src/themes/dashboard-toolbar.ts +15 -0
  262. package/packages/ui/src/themes/drawer.ts +45 -0
  263. package/packages/ui/src/themes/dropdown-menu.ts +38 -0
  264. package/packages/ui/src/themes/empty.ts +43 -0
  265. package/packages/ui/src/themes/field-group.ts +52 -0
  266. package/packages/ui/src/themes/file-upload.ts +38 -0
  267. package/packages/ui/src/themes/footer-columns.ts +13 -0
  268. package/packages/ui/src/themes/footer.ts +9 -0
  269. package/packages/ui/src/themes/form-field.ts +25 -0
  270. package/packages/ui/src/themes/form.ts +22 -0
  271. package/packages/ui/src/themes/header.ts +12 -0
  272. package/packages/ui/src/themes/icon.ts +61 -0
  273. package/packages/ui/src/themes/index.ts +99 -0
  274. package/packages/ui/src/themes/input-date.ts +73 -0
  275. package/packages/ui/src/themes/input-menu.ts +66 -0
  276. package/packages/ui/src/themes/input-number.ts +58 -0
  277. package/packages/ui/src/themes/input-rating.ts +25 -0
  278. package/packages/ui/src/themes/input-tags.ts +63 -0
  279. package/packages/ui/src/themes/input-time.ts +70 -0
  280. package/packages/ui/src/themes/input.ts +148 -0
  281. package/packages/ui/src/themes/kbd.ts +27 -0
  282. package/packages/ui/src/themes/link.ts +27 -0
  283. package/packages/ui/src/themes/listbox.ts +48 -0
  284. package/packages/ui/src/themes/main.ts +6 -0
  285. package/packages/ui/src/themes/marquee.ts +45 -0
  286. package/packages/ui/src/themes/modal.ts +46 -0
  287. package/packages/ui/src/themes/navigation-menu.ts +80 -0
  288. package/packages/ui/src/themes/page-anchors.ts +7 -0
  289. package/packages/ui/src/themes/page-aside.ts +7 -0
  290. package/packages/ui/src/themes/page-card.ts +22 -0
  291. package/packages/ui/src/themes/page-cta.ts +18 -0
  292. package/packages/ui/src/themes/page-feature.ts +13 -0
  293. package/packages/ui/src/themes/page-header.ts +16 -0
  294. package/packages/ui/src/themes/page-hero.ts +15 -0
  295. package/packages/ui/src/themes/page-links.ts +12 -0
  296. package/packages/ui/src/themes/page-section.ts +14 -0
  297. package/packages/ui/src/themes/page.ts +7 -0
  298. package/packages/ui/src/themes/pagination.ts +17 -0
  299. package/packages/ui/src/themes/pin-input.ts +73 -0
  300. package/packages/ui/src/themes/popover.ts +30 -0
  301. package/packages/ui/src/themes/progress.ts +29 -0
  302. package/packages/ui/src/themes/prose.ts +45 -0
  303. package/packages/ui/src/themes/radio-group.ts +39 -0
  304. package/packages/ui/src/themes/scroll-area.ts +23 -0
  305. package/packages/ui/src/themes/select-menu.ts +71 -0
  306. package/packages/ui/src/themes/select.ts +72 -0
  307. package/packages/ui/src/themes/separator.ts +28 -0
  308. package/packages/ui/src/themes/sidebar.ts +127 -0
  309. package/packages/ui/src/themes/skeleton.ts +15 -0
  310. package/packages/ui/src/themes/slideover.ts +87 -0
  311. package/packages/ui/src/themes/slider.ts +48 -0
  312. package/packages/ui/src/themes/stepper.ts +41 -0
  313. package/packages/ui/src/themes/switch.ts +63 -0
  314. package/packages/ui/src/themes/table.ts +34 -0
  315. package/packages/ui/src/themes/tabs.ts +74 -0
  316. package/packages/ui/src/themes/textarea.ts +77 -0
  317. package/packages/ui/src/themes/timeline.ts +25 -0
  318. package/packages/ui/src/themes/toast.ts +29 -0
  319. package/packages/ui/src/themes/toaster.ts +66 -0
  320. package/packages/ui/src/themes/tooltip.ts +31 -0
  321. package/packages/ui/src/themes/tree.ts +41 -0
  322. package/packages/ui/src/themes/user.ts +28 -0
  323. package/styles.cdn.gen.css +2047 -0
  324. package/theme.gen.json +1 -0
@@ -0,0 +1,373 @@
1
+ {
2
+ "id": "forest-vehicle-marker",
3
+ "file": "forest-vehicle-marker.svg",
4
+ "size": 40,
5
+ "disc": {
6
+ "cx": 20,
7
+ "cy": 20,
8
+ "r": 14.4
9
+ },
10
+ "inner": {
11
+ "r": 15.2,
12
+ "disc": 14.4,
13
+ "stroke": 1.6
14
+ },
15
+ "outer": {
16
+ "r": 19.2,
17
+ "band": 2.4,
18
+ "stroke": 1.6,
19
+ "ratio": 0.16666666666666666,
20
+ "edgeRatio": 0.6666666666666666
21
+ },
22
+ "bandMid": 17.2,
23
+ "withoutBattery": {
24
+ "outerEdge": 16
25
+ },
26
+ "dot": {
27
+ "cx": 32.16,
28
+ "cy": 7.84,
29
+ "r": 4.64,
30
+ "edge": 1.6
31
+ },
32
+ "floor": {
33
+ "px": 1,
34
+ "atIconSize": 0.625,
35
+ "edges": [
36
+ {
37
+ "name": "edge (inner stroke)",
38
+ "units": 1.6,
39
+ "painted": 1
40
+ },
41
+ {
42
+ "name": "batteryEdge (outer stroke)",
43
+ "units": 1.6,
44
+ "painted": 1
45
+ },
46
+ {
47
+ "name": "battery band",
48
+ "units": 2.4,
49
+ "painted": 1.5
50
+ },
51
+ {
52
+ "name": "dotEdge",
53
+ "units": 1.6,
54
+ "painted": 1
55
+ },
56
+ {
57
+ "name": "badge edges",
58
+ "units": 1.6,
59
+ "painted": 1
60
+ },
61
+ {
62
+ "name": "locked pause bar",
63
+ "units": 1.95,
64
+ "painted": 1.22
65
+ }
66
+ ]
67
+ },
68
+ "locked": {
69
+ "cx": 32.16,
70
+ "cy": 32.16,
71
+ "r": 4.64,
72
+ "edge": 1.6,
73
+ "barW": 1.95,
74
+ "barH": 5.34
75
+ },
76
+ "corner": {
77
+ "scale": 1.15,
78
+ "r": 4.64,
79
+ "edge": 1.6
80
+ },
81
+ "inUse": {
82
+ "cx": 0.35,
83
+ "cy": 0.3,
84
+ "r": 0.85,
85
+ "discR": 14.4
86
+ },
87
+ "badge": {
88
+ "cx": 7.84,
89
+ "cy": 32.16,
90
+ "r": 4.64,
91
+ "edge": 1.6,
92
+ "shapes": [
93
+ "square",
94
+ "triangle",
95
+ "circle",
96
+ "star"
97
+ ],
98
+ "forbidden": [
99
+ "--ui-error",
100
+ "--ui-warning"
101
+ ]
102
+ },
103
+ "glyph": {
104
+ "canvas": 24,
105
+ "scale": 0.828,
106
+ "strokeWidth": 1.74,
107
+ "inset": 10.06,
108
+ "paintedStroke": 1.441,
109
+ "floorIconSize": 0.694
110
+ },
111
+ "params": [
112
+ {
113
+ "name": "body",
114
+ "sentinel": "#FF00FF",
115
+ "kind": "disc",
116
+ "region": "The disc",
117
+ "use": "The colour of the state group"
118
+ },
119
+ {
120
+ "name": "edge",
121
+ "sentinel": "#FF01FF",
122
+ "kind": "extra",
123
+ "region": "The inner circle’s stroke",
124
+ "use": "The stroke of the inner circle. Always the background colour"
125
+ },
126
+ {
127
+ "name": "battery",
128
+ "sentinel": "#FF02FF",
129
+ "kind": "extra",
130
+ "region": "The outer circle’s fill",
131
+ "use": "The fill of the outer circle. Switch it off and the whole ring goes"
132
+ },
133
+ {
134
+ "name": "batteryEdge",
135
+ "sentinel": "#FF03FF",
136
+ "kind": "extra",
137
+ "region": "The outer circle’s stroke",
138
+ "use": "The stroke of the outer circle. Always the background colour"
139
+ },
140
+ {
141
+ "name": "dot",
142
+ "sentinel": "#FF04FF",
143
+ "kind": "extra",
144
+ "region": "The offline dot",
145
+ "use": "Connectivity. The dot appears when the vehicle is offline"
146
+ },
147
+ {
148
+ "name": "dotEdge",
149
+ "sentinel": "#FF05FF",
150
+ "kind": "extra",
151
+ "region": "The offline dot’s outline",
152
+ "use": "The outline of the dot, which separates it from the disc"
153
+ },
154
+ {
155
+ "name": "badgeSquare",
156
+ "sentinel": "#FF06FF",
157
+ "kind": "extra",
158
+ "region": "The square badge",
159
+ "use": "A badge on the lower shoulder. A square carries one class of fact"
160
+ },
161
+ {
162
+ "name": "badgeSquareEdge",
163
+ "sentinel": "#FF07FF",
164
+ "kind": "extra",
165
+ "region": "The square badge’s outline",
166
+ "use": "The outline of the square badge"
167
+ },
168
+ {
169
+ "name": "badgeTriangle",
170
+ "sentinel": "#FF08FF",
171
+ "kind": "extra",
172
+ "region": "The triangle badge",
173
+ "use": "The same badge as a triangle, for a second class of fact"
174
+ },
175
+ {
176
+ "name": "badgeTriangleEdge",
177
+ "sentinel": "#FF09FF",
178
+ "kind": "extra",
179
+ "region": "The triangle badge’s outline",
180
+ "use": "The outline of the triangle badge"
181
+ },
182
+ {
183
+ "name": "badgeCircle",
184
+ "sentinel": "#FF0AFF",
185
+ "kind": "extra",
186
+ "region": "The circle badge",
187
+ "use": "The same badge as a circle, for a third class of fact"
188
+ },
189
+ {
190
+ "name": "badgeCircleEdge",
191
+ "sentinel": "#FF0BFF",
192
+ "kind": "extra",
193
+ "region": "The circle badge’s outline",
194
+ "use": "The outline of the circle badge"
195
+ },
196
+ {
197
+ "name": "badgeStar",
198
+ "sentinel": "#FF0CFF",
199
+ "kind": "extra",
200
+ "region": "The star badge",
201
+ "use": "The same badge as a star, for a fourth class of fact"
202
+ },
203
+ {
204
+ "name": "badgeStarEdge",
205
+ "sentinel": "#FF0DFF",
206
+ "kind": "extra",
207
+ "region": "The star badge’s outline",
208
+ "use": "The outline of the star badge"
209
+ },
210
+ {
211
+ "name": "inUseFrom",
212
+ "sentinel": "#FF0EFF",
213
+ "kind": "extra",
214
+ "region": "The in-use gradient’s centre stop",
215
+ "use": "The centre stop of the in-use gradient. Transparent and the disc keeps `body`"
216
+ },
217
+ {
218
+ "name": "inUseTo",
219
+ "sentinel": "#FF0FFF",
220
+ "kind": "extra",
221
+ "region": "The in-use gradient’s edge stop",
222
+ "use": "The edge stop of the in-use gradient. Both stops go off together"
223
+ },
224
+ {
225
+ "name": "locked",
226
+ "sentinel": "#FF10FF",
227
+ "kind": "extra",
228
+ "region": "The pause mark",
229
+ "use": "The fill of the pause mark. It appears when the rider has locked the vehicle"
230
+ },
231
+ {
232
+ "name": "lockedEdge",
233
+ "sentinel": "#FF11FF",
234
+ "kind": "extra",
235
+ "region": "The pause mark’s outline and bars",
236
+ "use": "The pause mark’s outline AND its two bars — both are the background colour"
237
+ },
238
+ {
239
+ "name": "bike",
240
+ "sentinel": "#FF12FF",
241
+ "kind": "glyph",
242
+ "region": "The bike glyph",
243
+ "use": "FUNCTIONAL / Active. The only state that uses the brand mark",
244
+ "source": "packages/ui/icons/forest/bike.svg"
245
+ },
246
+ {
247
+ "name": "pine",
248
+ "sentinel": "#FF13FF",
249
+ "kind": "glyph",
250
+ "region": "The pine glyph",
251
+ "use": "Any rental. A rider has it",
252
+ "source": "packages/ui/icons/forest/mark.svg"
253
+ },
254
+ {
255
+ "name": "eye",
256
+ "sentinel": "#FF14FF",
257
+ "kind": "glyph",
258
+ "region": "The eye glyph",
259
+ "use": "INSPECT / Inspect. Somebody looks at it",
260
+ "source": "lucide:eye"
261
+ },
262
+ {
263
+ "name": "relocate",
264
+ "sentinel": "#FF15FF",
265
+ "kind": "glyph",
266
+ "region": "The relocate glyph",
267
+ "use": "RELOCATE / Relocate. It must be moved",
268
+ "source": "lucide:arrow-right-left"
269
+ },
270
+ {
271
+ "name": "wrench",
272
+ "sentinel": "#FF16FF",
273
+ "kind": "glyph",
274
+ "region": "The wrench glyph",
275
+ "use": "MAINTENANCE / Task in progress",
276
+ "source": "lucide:wrench"
277
+ },
278
+ {
279
+ "name": "warehouse",
280
+ "sentinel": "#FF17FF",
281
+ "kind": "glyph",
282
+ "region": "The warehouse glyph",
283
+ "use": "SERVICE_WORKSHOP / Warehouse",
284
+ "source": "lucide:warehouse"
285
+ },
286
+ {
287
+ "name": "truck",
288
+ "sentinel": "#FF18FF",
289
+ "kind": "glyph",
290
+ "region": "The truck glyph",
291
+ "use": "COLLECT / Damage collect. Someone takes it away",
292
+ "source": "lucide:truck"
293
+ },
294
+ {
295
+ "name": "bandage",
296
+ "sentinel": "#FF19FF",
297
+ "kind": "glyph",
298
+ "region": "The bandage glyph",
299
+ "use": "SERVICE_ON_SITE / Damaged",
300
+ "source": "lucide:bandage"
301
+ },
302
+ {
303
+ "name": "question",
304
+ "sentinel": "#FF1AFF",
305
+ "kind": "glyph",
306
+ "region": "The question glyph",
307
+ "use": "LOST / Missing",
308
+ "source": "lucide:circle-question-mark"
309
+ },
310
+ {
311
+ "name": "hand",
312
+ "sentinel": "#FF1BFF",
313
+ "kind": "glyph",
314
+ "region": "The hand glyph",
315
+ "use": "OPERATIONAL_HOLD / Support & community",
316
+ "source": "lucide:hand"
317
+ },
318
+ {
319
+ "name": "flag",
320
+ "sentinel": "#FF1CFF",
321
+ "kind": "glyph",
322
+ "region": "The flag glyph",
323
+ "use": "AWAITING_ACTION / Investigation",
324
+ "source": "lucide:flag"
325
+ },
326
+ {
327
+ "name": "ready",
328
+ "sentinel": "#FF1DFF",
329
+ "kind": "glyph",
330
+ "region": "The ready glyph",
331
+ "use": "READY_FOR_DEPLOYMENT / Ready for deployment",
332
+ "source": "lucide:package-check"
333
+ },
334
+ {
335
+ "name": "skull",
336
+ "sentinel": "#FF1EFF",
337
+ "kind": "glyph",
338
+ "region": "The skull glyph",
339
+ "use": "RETIRED / Terminated. Out of the fleet permanently",
340
+ "source": "lucide:skull"
341
+ },
342
+ {
343
+ "name": "container",
344
+ "sentinel": "#FF1FFF",
345
+ "kind": "glyph",
346
+ "region": "The container glyph",
347
+ "use": "IMPOUNDED / Storage",
348
+ "source": "lucide:container"
349
+ },
350
+ {
351
+ "name": "staff",
352
+ "sentinel": "#FF20FF",
353
+ "kind": "glyph",
354
+ "region": "The staff glyph",
355
+ "use": "SERVICE_MECHANICS / Staff. An internal team has it",
356
+ "source": "lucide:briefcase-business"
357
+ }
358
+ ],
359
+ "bannedElements": [
360
+ "style",
361
+ "text",
362
+ "tspan",
363
+ "image",
364
+ "clipPath",
365
+ "mask",
366
+ "filter",
367
+ "pattern",
368
+ "marker",
369
+ "symbol",
370
+ "foreignObject"
371
+ ],
372
+ "generator": "scripts/mapMarker.ts"
373
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "id": "forest-place-count",
3
+ "file": "forest-place-count.svg",
4
+ "width": 42,
5
+ "height": 28,
6
+ "shape": "stretchable-pill",
7
+ "ring": {
8
+ "stroke": 2.8,
9
+ "ratio": 0.2
10
+ },
11
+ "floor": {
12
+ "px": 1,
13
+ "atIconSize": 0.7,
14
+ "edges": [
15
+ {
16
+ "name": "ring",
17
+ "units": 2.8,
18
+ "painted": 1.96
19
+ }
20
+ ]
21
+ },
22
+ "glyph": {
23
+ "canvas": 24,
24
+ "scale": 0.5,
25
+ "strokeWidth": 2.52,
26
+ "cx": 14,
27
+ "cy": 14
28
+ },
29
+ "stretchX": {
30
+ "left": 25,
31
+ "width": 2
32
+ },
33
+ "content": {
34
+ "left": 25,
35
+ "top": 0,
36
+ "width": 9,
37
+ "height": 28
38
+ },
39
+ "requires": {
40
+ "icon-text-fit": "width"
41
+ },
42
+ "params": [
43
+ {
44
+ "name": "body",
45
+ "sentinel": "#FF00FF",
46
+ "kind": "body",
47
+ "region": "The pill",
48
+ "use": "The colour of the place."
49
+ },
50
+ {
51
+ "name": "ring",
52
+ "sentinel": "#FF01FF",
53
+ "kind": "extra",
54
+ "region": "The ring",
55
+ "use": "The border, and the halo that separates the mark from the basemap."
56
+ },
57
+ {
58
+ "name": "warehouse",
59
+ "sentinel": "#FF02FF",
60
+ "kind": "glyph",
61
+ "region": "the warehouse glyph",
62
+ "use": "A warehouse or workshop. Vehicles are repaired and stored here.",
63
+ "source": "lucide:house"
64
+ },
65
+ {
66
+ "name": "parking",
67
+ "sentinel": "#FF03FF",
68
+ "kind": "glyph",
69
+ "region": "the parking glyph",
70
+ "use": "A parking bay or station. A rider should leave a vehicle here.",
71
+ "source": "packages/ui/icons/forest/parking.svg"
72
+ },
73
+ {
74
+ "name": "bike",
75
+ "sentinel": "#FF04FF",
76
+ "kind": "glyph",
77
+ "region": "the bike glyph",
78
+ "use": "A count of vehicles. Used on the pill, where the number says how many.",
79
+ "source": "packages/ui/icons/forest/bike.svg"
80
+ }
81
+ ],
82
+ "generator": "scripts/mapPlaces.ts"
83
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "id": "forest-place-marker",
3
+ "file": "forest-place-marker.svg",
4
+ "size": 40,
5
+ "shape": "rounded-square",
6
+ "square": {
7
+ "x": 1.665,
8
+ "y": 1.665,
9
+ "side": 36.67,
10
+ "corner": 9.17,
11
+ "half": 16.67
12
+ },
13
+ "ring": {
14
+ "stroke": 3.33,
15
+ "ratio": 0.2
16
+ },
17
+ "floor": {
18
+ "px": 1,
19
+ "atIconSize": 0.7,
20
+ "edges": [
21
+ {
22
+ "name": "ring",
23
+ "units": 3.33,
24
+ "painted": 2.33
25
+ }
26
+ ]
27
+ },
28
+ "glyph": {
29
+ "canvas": 24,
30
+ "scale": 0.9585,
31
+ "strokeWidth": 1.74
32
+ },
33
+ "params": [
34
+ {
35
+ "name": "body",
36
+ "sentinel": "#FF00FF",
37
+ "kind": "body",
38
+ "region": "The square",
39
+ "use": "The colour of the place."
40
+ },
41
+ {
42
+ "name": "ring",
43
+ "sentinel": "#FF01FF",
44
+ "kind": "extra",
45
+ "region": "The ring",
46
+ "use": "The border, and the halo that separates the mark from the basemap."
47
+ },
48
+ {
49
+ "name": "warehouse",
50
+ "sentinel": "#FF02FF",
51
+ "kind": "glyph",
52
+ "region": "the warehouse glyph",
53
+ "use": "A warehouse or workshop. Vehicles are repaired and stored here.",
54
+ "source": "lucide:house"
55
+ },
56
+ {
57
+ "name": "parking",
58
+ "sentinel": "#FF03FF",
59
+ "kind": "glyph",
60
+ "region": "the parking glyph",
61
+ "use": "A parking bay or station. A rider should leave a vehicle here.",
62
+ "source": "packages/ui/icons/forest/parking.svg"
63
+ },
64
+ {
65
+ "name": "bike",
66
+ "sentinel": "#FF04FF",
67
+ "kind": "glyph",
68
+ "region": "the bike glyph",
69
+ "use": "A count of vehicles. Used on the pill, where the number says how many.",
70
+ "source": "packages/ui/icons/forest/bike.svg"
71
+ }
72
+ ],
73
+ "generator": "scripts/mapPlaces.ts"
74
+ }
@@ -0,0 +1,125 @@
1
+ // One address shape, and the normalisers that get Mapbox's several into it.
2
+ //
3
+ // ★ THE NORMALISING IS THE POINT, not the requests. Mapbox answers address questions from three
4
+ // different endpoints and each names the parts differently: Autofill flattens them onto W3C-ish keys
5
+ // (`address_line1`, `address_level2`), Geocoding nests them under `context` with its own slot names
6
+ // (`context.place`, `context.region`), and Validation echoes a third variation back. A form binding
7
+ // six inputs does not want to know which endpoint answered — so everything here lands on one shape and
8
+ // the endpoint wrappers stay thin.
9
+
10
+ /** An address, in the shape a form binds to. Every part optional: Mapbox omits what it cannot find. */
11
+ export interface ForestAddress {
12
+ line1?: string;
13
+ line2?: string;
14
+ /**
15
+ * The named area below the city — Islington, Hackney, Shoreditch.
16
+ *
17
+ * ★ THIS IS NOT `city`, and conflating them is the trap. For any London address Mapbox answers
18
+ * `place: "London"`, and the borough a rider would actually name lands in `locality`. A surface
19
+ * writing "Islington to Hackney" that read `city` would print "London to London" and lose the only
20
+ * distinction it was making.
21
+ */
22
+ locality?: string;
23
+ /** finer still — a named neighbourhood inside a locality, where Mapbox has one */
24
+ neighborhood?: string;
25
+ /** the town or city — `address_level2` in W3C terms, `context.place` in Geocoding's */
26
+ city?: string;
27
+ /** county, state or province — `address_level1` / `context.region` */
28
+ region?: string;
29
+ postcode?: string;
30
+ country?: string;
31
+ /** ISO 3166-1 alpha-2, uppercase */
32
+ countryCode?: string;
33
+ /** what Mapbox itself would print for this address, when it offered one */
34
+ formatted?: string;
35
+ /** [lng, lat] — present when the answer came with a position */
36
+ at?: [number, number];
37
+ }
38
+
39
+ /**
40
+ * ★ Absent parts stay `undefined`, never ''. A form binds these straight to inputs, and the two are
41
+ * not interchangeable there: '' blanks a field the reader may have typed into, `undefined` leaves it
42
+ * alone. Autofill routinely omits line2 and region, so this is the common path rather than an edge.
43
+ */
44
+ const text = (v: unknown): string | undefined => (typeof v === 'string' && v.length ? v : undefined);
45
+
46
+ function position(geometry: unknown): [number, number] | undefined {
47
+ const coords = (geometry as { coordinates?: unknown } | undefined)?.coordinates;
48
+ return Array.isArray(coords) && typeof coords[0] === 'number' && typeof coords[1] === 'number'
49
+ ? [coords[0], coords[1]]
50
+ : undefined;
51
+ }
52
+
53
+ /**
54
+ * A retrieved Address Autofill feature → ForestAddress.
55
+ *
56
+ * ★ `properties` is typed loosely on purpose. Mapbox declares a different concrete interface for each
57
+ * endpoint's feature, and naming one here would reject the others at the call site for no gain — this
58
+ * reads a handful of optional string fields and checks each one anyway.
59
+ */
60
+ export function fromAutofill(feature: { properties?: unknown; geometry?: unknown }): ForestAddress {
61
+ const p = (feature.properties ?? {}) as Record<string, unknown>;
62
+ return {
63
+ line1: text(p.address_line1),
64
+ line2: text(p.address_line2),
65
+ // Autofill's level3 is the same rung as Geocoding's `locality`; it has no neighbourhood at all.
66
+ locality: text(p.address_level3),
67
+ neighborhood: undefined,
68
+ city: text(p.address_level2),
69
+ region: text(p.address_level1),
70
+ postcode: text(p.postcode),
71
+ country: text(p.country),
72
+ countryCode: text(p.country_code)?.toUpperCase(),
73
+ formatted: text(p.full_address),
74
+ at: position(feature.geometry),
75
+ };
76
+ }
77
+
78
+ /** A Geocoding feature — forward or reverse — → ForestAddress. */
79
+ export function fromGeocodingFeature(feature: {
80
+ properties?: unknown;
81
+ geometry?: unknown;
82
+ }): ForestAddress {
83
+ const p = (feature.properties ?? {}) as Record<string, unknown>;
84
+ const ctx = (p.context ?? {}) as Record<string, { name?: unknown; country_code?: unknown }>;
85
+ const slot = (key: string) => text(ctx[key]?.name);
86
+
87
+ return {
88
+ // `context.address` is the street line when Mapbox resolved to a building; `properties.name` is
89
+ // what it resolved to at any other precision, which for a reverse lookup is often the street.
90
+ line1: slot('address') ?? text(p.name),
91
+ line2: undefined,
92
+ locality: slot('locality'),
93
+ neighborhood: slot('neighborhood'),
94
+ city: slot('place'),
95
+ region: slot('region'),
96
+ postcode: slot('postcode'),
97
+ country: slot('country'),
98
+ countryCode: text(ctx.country?.country_code)?.toUpperCase(),
99
+ formatted: text(p.full_address),
100
+ at: position(feature.geometry),
101
+ };
102
+ }
103
+
104
+ /**
105
+ * The address as one line, in postal order, skipping whatever is missing.
106
+ *
107
+ * For when Mapbox gave no `formatted` of its own, or the reader has edited the parts since — a
108
+ * surface that printed a stale `formatted` beside edited fields would be showing two addresses.
109
+ */
110
+ /**
111
+ * The most specific name a person would use for where this is — "Shoreditch", "Islington", "London".
112
+ *
113
+ * For naming a place in a sentence rather than addressing an envelope: a ride's start and end, a bay's
114
+ * area, "reported near…". Falls down the rungs because Mapbox does not have every one everywhere —
115
+ * a village has a `place` and nothing below it.
116
+ */
117
+ export function areaLabel(address: ForestAddress): string | undefined {
118
+ return address.neighborhood ?? address.locality ?? address.city;
119
+ }
120
+
121
+ export function formatAddress(address: ForestAddress): string {
122
+ return [address.line1, address.line2, address.city, address.postcode, address.country]
123
+ .filter((part): part is string => !!part)
124
+ .join(', ');
125
+ }