@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
package/LICENSE ADDED
@@ -0,0 +1,67 @@
1
+ Forest Design System — Licence
2
+ Copyright (c) 2026 HumanForest Ltd. All rights reserved.
3
+
4
+ This software is published openly so that people building Forest products can install it
5
+ without access to its source repository. It is not open-source software.
6
+
7
+
8
+ 1. GRANT
9
+
10
+ You may install, use, copy and modify this software, and incorporate it into applications,
11
+ prototypes, documents and presentations, for the purpose of building or operating Forest
12
+ products, services and communications.
13
+
14
+ This grant is free of charge and requires no separate agreement. It runs to anyone who
15
+ obtains the software from a public registry.
16
+
17
+
18
+ 2. RESERVED
19
+
20
+ All rights not granted above are reserved. In particular, you may not:
21
+
22
+ (a) redistribute this software, modified or unmodified, as a design system, component
23
+ library, template or theme of your own;
24
+
25
+ (b) use the HumanForest and Forest names, logos, wordmarks, sub-brand marks or any
26
+ confusingly similar mark. Nothing here grants any trademark right. The brand marks
27
+ included in these packages are provided to render Forest's own products correctly,
28
+ not as artwork you may adopt;
29
+
30
+ (c) represent your product as being made, endorsed or approved by HumanForest.
31
+
32
+
33
+ 3. THIRD-PARTY MATERIAL
34
+
35
+ Parts of these packages are not HumanForest's to license, and the grant in section 1 does
36
+ not extend to them. Each keeps its own terms:
37
+
38
+ TYPEFACES — Mohr and GT Haptik are licensed to HumanForest by their foundries and are NOT
39
+ sublicensed to you. No font binary is included in any published package. The stylesheets
40
+ reference https://assets.forest.bike/fonts/, which serves them to those entitled to use
41
+ them. If you are not covered by Forest's licences, substitute your own faces. JetBrains
42
+ Mono is licensed under the SIL Open Font License 1.1 and may be used under those terms.
43
+
44
+ GLYPH OUTLINES — packages/tokens ships `glyphs/glyphs.json`, letterforms of the above
45
+ typefaces outlined as vector paths so sub-brand lockups can be composed at runtime. It is
46
+ covered by the same foundry terms as the typefaces themselves, not by section 1.
47
+
48
+ DEVICE ARTWORK — packages/frames ships device renders from Wikimedia Commons under the
49
+ Creative Commons Attribution-ShareAlike 4.0 International licence
50
+ (https://creativecommons.org/licenses/by-sa/4.0/). They are unmodified. Attribution is a
51
+ condition of that licence: see ATTRIBUTION.md in that package, and keep it with the art
52
+ wherever the art travels. Works derived from the artwork must themselves be CC BY-SA 4.0.
53
+
54
+ DEPENDENCIES — third-party packages installed alongside these keep their own licences.
55
+
56
+
57
+ 4. NO WARRANTY
58
+
59
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
60
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
61
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
62
+ FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
63
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
64
+ DEALINGS IN THE SOFTWARE.
65
+
66
+
67
+ Questions about use beyond this grant: design@forest.bike
package/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # @humanforest/nuxt-layer
2
+
3
+ Forest design system as a [Nuxt layer](https://nuxt.com/docs/getting-started/layers). Extend it and a
4
+ Nuxt app inherits the Forest theme, colour families, icons and the real brand fonts — no npm publish
5
+ involved.
6
+
7
+ The layer is **self-contained** — no `@humanforest/*` imports, no climbing to sibling packages — so giget
8
+ can fetch this one directory and it still works. The generated files are committed; regenerate them
9
+ from the source packages with `bun run build:layer` (in the design-system repo root).
10
+
11
+ ## What the layer delivers
12
+
13
+ - **`nuxt.config.ts`** — registers `@nuxt/ui`, the Forest colour families (`color="forest|maple|river|warm|acid"`), the `i-forest-*` icon set (SVGs in `assets/icons/forest/`), the 23 Forest components below, and the composables listed under "Composables and helpers".
14
+ - **`app.config.ts`** — the Nuxt UI theme: per-component tailwind-variants fragments + the semantic role map (`primary→forest`, `error→maple`, …), read from `theme.gen.json`.
15
+ - **`styles.gen.css`** — fonts + ramps + theme registration + type scale + the motion ladder + the Forest base layer. The `@font-face` rules point at `./files/`, so a giget consumer renders in the brand faces offline. **This file is not published to npm.**
16
+ - **`styles.cdn.gen.css`** — byte-identical from the first token onward; only the `@font-face` rules differ, naming `assets.forest.bike` instead. This is the build the npm package ships, because a public tarball may not carry licensed binaries.
17
+ - **`files/`** — the real brand font binaries. Giget only; excluded from the npm tarball.
18
+ - **`packages/tokens/logos/`** — the 15 generated brand SVGs (mark, wordmark, both lockups, the `f`, and eight sub-brand favicons). Nothing in the layer imports them: `FLogo` and `FSubLogo` compose their marks live. They ship for the uses a component cannot serve — a Vue component does not go in `<link rel="icon">`, an email template or an OG image.
19
+ - **`packages/ui/src`, `packages/charts/src`, `packages/frames/src`** (+ their supporting trees, mirrored at repo-relative paths — see "Regenerating") — the 39 registered Forest components, auto-registered like any Nuxt component, no import needed: `ForestContext`; `FLogo`, `FSubLogo`; `FFilterBar`, `FFilterChip`; `FKpi`, `FKpiGroup`; six shell components (`FAppShell`, `FAppSidebar`, `FAppNavbar`, `FPageToolbar`, `FScrollShadow`, `FSidePanel`); four canvas components (`FCanvasHud`, `FCanvasCard`, `FCanvasControl`, `FCanvasControlGroup`); eight map components (`FMap`, `FMapPopup`, `FMarker`, `FVehicleMark`, and the four controls `FMapZoom`, `FMapCompass`, `FMapTilt`, `FMapGeolocate`); eleven chart components (`FBoroughShape`, `FCalendarGrid`, `FCellLegend`, `FChartFrame`, `FChartFrameSingle`, `FChartLegend`, `FDistributionBar`, `FDottedMap`, `FLondonMap`, `FSparkline`, `FStatusTrack`); three presentation frames (`FDeviceFrame`, `FBrowserFrame`, `FFitFrame`) for staging a prototype at true scale — these carry CC BY-SA 4.0 device art, which is why they ship here and not on public npm. It is the mirrored source trees that make auto-registration possible — the components aren't published separately, they ARE those trees.
20
+
21
+ ## Composables and helpers
22
+
23
+ Eight are auto-imported alongside the components — `FMap`'s imperative API plus the chart palette and
24
+ the KPI formatters:
25
+
26
+ ```ts
27
+ // no import needed
28
+ const { flyTo } = useMapCamera()
29
+ const palette = useChartPalette()
30
+ formatMetric(4218, { format: 'compact' }) // "4.2k"
31
+ ```
32
+
33
+ `useMapReady` · `useMapCamera` · `useMapOverlay` · `useFeatureSelect` · `MAP_SLOT` ·
34
+ `useChartPalette` · `formatMetric` · `formatPercent`
35
+
36
+ This is an ALLOW-LIST, not `imports.dirs`, and the rest is deliberate. A directory scan would take
37
+ every export in the mirrored trees, and those barrels carry names like `token`, `isSelected`,
38
+ `nextKey` and `addClause` — generic enough to collide with a consuming app's own code, silently and
39
+ at a distance. Everything else stays reachable by path:
40
+
41
+ ```ts
42
+ import { STATE_LABEL, resolveMapColor } from '#layers/forest/packages/ui/src/map'
43
+ import { distributionShares } from '#layers/forest/packages/charts/src/distribution'
44
+ ```
45
+
46
+ Those paths are the layer's internal shape, so treat them as less stable than the auto-imported set:
47
+ they move when the source tree is reorganised.
48
+
49
+ ## Quickstart
50
+
51
+ Three files in the consuming app. This exact setup is verified end to end: a Nuxt 4 app in a separate
52
+ repo consuming this layer over giget, with the colour ramps, semantic roles, `.type-*` utilities,
53
+ `i-forest-*` icons and the brand font binaries all reaching the production build. The 21 Forest
54
+ components are verified too, but via a local-extends probe app rather than a giget one — see "Local
55
+ development against the layer" for a dependency step that a giget consumer gets automatically and a
56
+ local one does not.
57
+
58
+ **`nuxt.config.ts`**
59
+
60
+ ```ts
61
+ export default defineNuxtConfig({
62
+ // `install: true` is load-bearing — see "Staying up to date".
63
+ // Keep Forest LAST in extends so your own layers and app can override it.
64
+ extends: [['github:humanforest/design-system/packages/nuxt-layer#main', { install: true }]],
65
+ modules: ['@nuxt/ui'],
66
+ css: ['~/assets/css/main.css'],
67
+ })
68
+ ```
69
+
70
+ **`app/assets/css/main.css`**
71
+
72
+ ```css
73
+ @import "tailwindcss";
74
+ @import "@nuxt/ui";
75
+ @import "#layers/forest/styles.gen.css";
76
+ ```
77
+
78
+ Installed from npm instead, the same line names the CDN build — the self-hosted one is not in the
79
+ tarball, so a stale copy of this snippet fails to resolve rather than quietly falling back:
80
+
81
+ ```css
82
+ @import "@humanforest/nuxt-layer/styles.cdn.gen.css";
83
+ ```
84
+
85
+ **`package.json`** — `nuxt ^4`, `@nuxt/ui ^4`, `tailwindcss ^4`, plus `typescript` in
86
+ `devDependencies`. Without `typescript`, `@nuxt/ui`'s unresolved peer makes bun discard the lockfile and
87
+ re-resolve on every build — noisy rather than fatal, but easy to avoid.
88
+
89
+ **`GIGET_AUTH`** — a GitHub PAT with read access to this private repo, present for **both** install and
90
+ build:
91
+
92
+ ```bash
93
+ GIGET_AUTH=$(gh auth token) bun install
94
+ GIGET_AUTH=$(gh auth token) bun run build
95
+ ```
96
+
97
+ ## Why the CSS needs its own import line
98
+
99
+ Forest's stylesheet uses Tailwind at-rules (`@utility`, `@custom-variant`) and mode-order-sensitive
100
+ `:root` re-points, so it **must compile in-band with your app's `@import "tailwindcss"`**, after
101
+ `@nuxt/ui`. A layer `css: []` entry would be the wrong build and the wrong order, so the consumer
102
+ imports it from their own entry CSS.
103
+
104
+ It does **not** need copying out of the cache. `#layers/forest` is the alias Nuxt derives from this
105
+ layer's `$meta.name`, and it resolves straight into giget's fetched copy — including the relative
106
+ `url('./files/…')` `@font-face` paths, which Vite rewrites into content-hashed font assets emitted
107
+ alongside the CSS that references them.
108
+
109
+ **You do not need a `@source` line.** Other Nuxt layer setups carry one (e.g.
110
+ `@source ".../node_modules/.c12/*/app/**"`) to make Tailwind scan the fetched layer for used classes.
111
+ `@nuxt/ui` already does this for you: it detects every extended layer — the giget-fetched one included —
112
+ and emits its own `@source` pointing at the resolved path. Verified by removing the manual line and
113
+ rebuilding: byte-identical CSS, same 3,997 selectors, including Forest-only classes such as the
114
+ `coarse:` touch-target utilities that appear in no app template. Copying another layer's glob is
115
+ duplicate work, and here it would also walk the ~27k vendored files that `install: true` creates inside
116
+ the cache. If a future `@nuxt/ui` ever stops auto-detecting layers and Forest classes go missing, add a
117
+ narrow `@source` scoped to the layer root rather than a `**` glob that descends into its `node_modules`.
118
+
119
+ One detail bites silently: **the alias is `#layers/forest`** (from `$meta.name`), not the directory name.
120
+
121
+ **Precedence:** earlier in `extends` wins, and the app wins over every layer. As a foundation, keep
122
+ Forest last.
123
+
124
+ ## Staying up to date
125
+
126
+ Push a change to `main` and the **next build of every consuming app picks it up** — no cache-busting
127
+ step, no manual cache deletion.
128
+
129
+ That follows from `{ install: true }`: Nuxt's config loader (c12) passes it to giget as `force: true`,
130
+ which makes giget re-fetch the ref's tarball and extract it over `node_modules/.c12/<hash>/` on every
131
+ build. Drop `install: true` and giget's "destination already exists" guard re-engages, and an app can
132
+ keep building against a stale layer. It is also load-bearing for the build to succeed at all: giget
133
+ only installs the layer's own `dependencies` (`mapbox-gl`, `@unovis/vue`, `@unovis/ts`,
134
+ `tailwind-variants`, `@internationalized/date`) when `install: true` runs it inside the cache — drop
135
+ the flag and every map or chart component fails to resolve its imports, not just goes stale.
136
+
137
+ The trade-off: **freshness and reproducibility are the same knob.** There is no lockfile pin, so a push
138
+ to `main` reaches consumers unbidden. An app that needs reproducible builds should extend a tag or commit
139
+ SHA instead of `#main`, and will then stop receiving updates automatically. Versioning is lockstep across
140
+ the design system, cut as `v0.x.y` git tags — but **no tag has been cut yet**, so `#main` is the only
141
+ option until the first one is (see `CONTRIBUTING.md`). Every build also reaches the
142
+ GitHub API, which is why `GIGET_AUTH` is required at build time and not only at install time.
143
+
144
+ Because giget serves **whatever is committed**, run `bun run build:layer` and commit the regenerated
145
+ files after any token, theme, preset or font change — this includes the mirrored component sources (see
146
+ "What the layer delivers"), since editing `packages/ui/src` or `packages/charts/src` doesn't touch this
147
+ layer's copy until you regenerate it. The layer ships generated output (`theme.gen.json`,
148
+ `styles.gen.css`, the icon set, the font files) alongside 171 mirrored component-source files, not
149
+ generated output alone.
150
+
151
+ ## Local development against the layer
152
+
153
+ When you are changing the layer itself, point the app at your local checkout so you see edits without
154
+ pushing:
155
+
156
+ ```ts
157
+ const useLocalLayer = process.env.USE_LOCAL_LAYER === 'true'
158
+
159
+ export default defineNuxtConfig({
160
+ extends: [
161
+ useLocalLayer
162
+ ? '../design-system/packages/nuxt-layer' // adjust to wherever you cloned it
163
+ : ['github:humanforest/design-system/packages/nuxt-layer#main', { install: true }],
164
+ ],
165
+ })
166
+ ```
167
+
168
+ ```bash
169
+ USE_LOCAL_LAYER=true bun run dev
170
+ ```
171
+
172
+ **This path does not install the layer's dependencies.** Extending a local directory skips giget
173
+ entirely, so nothing installs `mapbox-gl`, `@unovis/vue`, `@unovis/ts`, `tailwind-variants` or
174
+ `@internationalized/date`: the layer directory has no `node_modules` of its own, and climbing to the
175
+ design-system repo's root `node_modules` doesn't find them either — bun links dependencies
176
+ per-workspace, not at the root. Add all five to the consuming app's own `package.json` `dependencies`.
177
+ Measured against a real probe app: skip this and the build fails with `Failed to resolve import
178
+ "mapbox-gl"` from `packages/ui/src/map/FMap.vue`.
179
+
180
+ The CSS import is unchanged — `#layers/forest` is derived from `$meta.name`, so it resolves whether the
181
+ layer came from a local path or the giget cache.
182
+
183
+ ## Fonts: bundled, real, offline
184
+
185
+ This layer has **two channels**, and the font source is the only thing that differs between them.
186
+
187
+ Via giget, from this private repo with a PAT, it carries the real brand fonts: `files/` ships the
188
+ actual woff/woff2 (GT Haptik, Mohr, JetBrains Mono) and `styles.gen.css` points at them with relative
189
+ `url('./files/…')` paths — no CDN, no cross-origin fetch, no `Access-Control-Allow-Origin`
190
+ requirement. Real Mohr renders offline the moment a consuming app resolves this layer. That closed,
191
+ access-controlled distribution is what makes shipping the binaries defensible.
192
+
193
+ Via npm it carries none of them. `styles.cdn.gen.css` names the faces on `assets.forest.bike`, and
194
+ the `files` array leaves both `files/` and `styles.gen.css` out of the tarball — Mohr and GT Haptik
195
+ are licensed to Forest, not to whoever runs `npm add`. A licence-holder who wants to self-host from
196
+ npm brings their own `@font-face` block.
197
+
198
+ Mohr remains licensed **Black + UPPERCASE only**. Because distribution is limited to the private repo
199
+ plus a PAT-gated giget fetch, this stays within the licence — do not copy `files/` out of this channel
200
+ into a publicly published package.
201
+
202
+ ## Regenerating
203
+
204
+ Run after any token / theme / preset / font change, then commit the generated files:
205
+
206
+ ```bash
207
+ bun run build:layer # emits theme.gen.json, styles.gen.css, assets/icons/forest, files, packages/, apps/
208
+ ```
package/app.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import theme from './theme.gen.json'
2
+
3
+ // Nuxt UI reads its component theme, semantic colour roles and icon aliases from app.config.ui.
4
+ // theme.ui is the resolved forestPreset.ui: per-component tailwind-variants fragments, the
5
+ // primary/secondary/success/… → forest/warm/… role map, and the rating-star icon alias. Deep-merged
6
+ // across layers, so a downstream layer or app can override individual slots. Regenerate via
7
+ // `bun run build:layer`.
8
+ export default defineAppConfig({
9
+ ui: theme.ui
10
+ })
@@ -0,0 +1,21 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M5 3V7.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
19
+ <path d="M7 4L3 6.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
20
+ <path d="M3 4L7 6.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
21
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M4 8L4 2.5M4 8L2 5.5M4 8L6 5.5" stroke-width="2" stroke-linecap="round" />
19
+ </svg>
@@ -0,0 +1,20 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 18C20.433 18 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 18 18.5 18Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 18C7.433 18 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 18 5.5 18Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M8 18H3" stroke-width="2" stroke-linecap="round" />
19
+ <path d="M21 18H16" stroke-width="2" stroke-linecap="round" />
20
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M4 2.5V8M4 2.5L6 5M4 2.5L2 5" stroke-width="2" stroke-linecap="round" />
19
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M3 7L7 3M7 7L3 3" stroke-width="2" stroke-linecap="round" />
19
+ </svg>
@@ -0,0 +1,18 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12 2L17.2 12.4H15.4L17.2 16H6.8L8.6 12.4H6.8L12 2Z" stroke-width="2"
3
+ stroke-linecap="round" stroke-linejoin="round" />
4
+ <path d="M10.2 16V22H8.6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path d="M13.8 16V22H15.4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12 2L17.2 12.4H15.4L17.2 16H6.8L8.6 12.4H6.8L12 2Z" stroke-width="2"
3
+ stroke-linecap="round" stroke-linejoin="round" />
4
+ <path d="M10.2 16V22H8.6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path d="M13.8 16V22H15.4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
6
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M4.68 20.5 6.48 3.5H12.99Q16.15 3.5 17.78 5.02Q19.41 6.53 19.32 9.35Q19.24 12.66 17.19 14.43Q15.14 16.2 11.62 16.2H10.22L9.78 20.5ZM10.7 11.79H11.95Q13 11.79 13.57 11.26Q14.14 10.73 14.2 9.74Q14.23 8.88 13.77 8.4Q13.3 7.91 12.38 7.91H11.1Z" />
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M 11.5251 2.2969 a 0.5299 0.5299 0 0 1 0.9498 0 l 2.3095 4.6781 a 2.1196 2.1196 0 0 0 1.5947 1.1598 l 5.165 0.7558 a 0.5299 0.5299 0 0 1 0.2939 0.9038 l -3.7353 3.6373 a 2.1196 2.1196 0 0 0 -0.6109 1.8776 l 0.8818 5.139 a 0.5299 0.5299 0 0 1 -0.7708 0.5599 l -4.6171 -2.4275 a 2.1196 2.1196 0 0 0 -1.9726 0 L 6.3971 21.0082 a 0.5299 0.5299 0 0 1 -0.7698 -0.5599 l 0.8808 -5.138 a 2.1196 2.1196 0 0 0 -0.6109 -1.8786 L 2.162 9.7954 a 0.5299 0.5299 0 0 1 0.2939 -0.9058 l 5.164 -0.7548 a 2.1196 2.1196 0 0 0 1.5967 -1.1598 z"
3
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M 11.5251 2.2969 a 0.5299 0.5299 0 0 1 0.9498 0 l 2.3095 4.6781 a 2.1196 2.1196 0 0 0 1.5947 1.1598 l 5.165 0.7558 a 0.5299 0.5299 0 0 1 0.2939 0.9038 l -3.7353 3.6373 a 2.1196 2.1196 0 0 0 -0.6109 1.8776 l 0.8818 5.139 a 0.5299 0.5299 0 0 1 -0.7708 0.5599 l -4.6171 -2.4275 a 2.1196 2.1196 0 0 0 -1.9726 0 L 6.3971 21.0082 a 0.5299 0.5299 0 0 1 -0.7698 -0.5599 l 0.8808 -5.138 a 2.1196 2.1196 0 0 0 -0.6109 -1.8786 L 2.162 9.7954 a 0.5299 0.5299 0 0 1 0.2939 -0.9058 l 5.164 -0.7548 a 2.1196 2.1196 0 0 0 1.5967 -1.1598 z"
3
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
4
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="currentColor" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="var(--ui-warning, currentColor)" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="currentColor" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="currentColor" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="currentColor" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="var(--ui-success, currentColor)" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="var(--ui-error, currentColor)" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="var(--ui-warning, currentColor)" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="var(--ui-success, currentColor)" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="var(--ui-error, currentColor)" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="currentColor" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="currentColor" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="currentColor" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="currentColor" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="currentColor" stroke="none" />
8
+ </svg>
package/nuxt.config.ts ADDED
@@ -0,0 +1,81 @@
1
+ import { fileURLToPath } from 'node:url'
2
+ import { dirname, join } from 'node:path'
3
+ import theme from './theme.gen.json'
4
+
5
+ // SELF-CONTAINED layer — no @humanforest/* imports, no climbing to sibling packages — so giget can fetch
6
+ // this directory alone (`github:humanforest/design-system/packages/nuxt-layer#main`) and it still
7
+ // works. Regenerate theme.gen.json / styles.gen.css / assets via `bun run build:layer`.
8
+ //
9
+ // CSS is NOT registered here: Forest's stylesheet uses Tailwind at-rules (@utility, @custom-variant)
10
+ // and must be compiled in-band with the app's `@import "tailwindcss"`. So the consumer @imports
11
+ // styles.gen.css from their own entry CSS, after `@nuxt/ui`. See README.md.
12
+
13
+ const currentDir = dirname(fileURLToPath(import.meta.url))
14
+
15
+ export default defineNuxtConfig({
16
+ $meta: { name: 'forest' },
17
+
18
+ // Self-sufficient; deduped when the consumer already lists @nuxt/ui.
19
+ modules: ['@nuxt/ui'],
20
+
21
+ // Forest scale families (color="forest|maple|river|warm|acid") + the default roles the plugin
22
+ // would otherwise drop. From the resolved preset.
23
+ ui: {
24
+ theme: {
25
+ colors: theme.theme.colors as string[]
26
+ }
27
+ },
28
+
29
+ // Forest icons (i-forest-*) — SVGs copied into the layer, so @nuxt/icon scans them from the
30
+ // giget-fetched dir too (currentDir is the cache path at build).
31
+ icon: {
32
+ customCollections: [
33
+ { prefix: 'forest', dir: join(currentDir, 'assets/icons/forest') }
34
+ ]
35
+ },
36
+
37
+ // Forest components, from the mirrored source trees. Absolute paths via currentDir: `~/` in a layer
38
+ // resolves against the CONSUMER's srcDir, not this one. pathPrefix:false keeps map/FMap.vue as
39
+ // <FMap> rather than <MapFMap>; the pattern restricts scanning to SFCs so the sibling .ts modules
40
+ // are not treated as components.
41
+ components: [
42
+ { path: join(currentDir, 'packages/ui/src'), pathPrefix: false, pattern: '**/*.vue' },
43
+ { path: join(currentDir, 'packages/charts/src'), pathPrefix: false, pattern: '**/*.vue' },
44
+ // Presentation frames (FDeviceFrame / FBrowserFrame / FFitFrame). They stage a prototype rather
45
+ // than appear in one, so they carry CC BY-SA device art — which is exactly why they ship on this
46
+ // private giget layer and not on public npm. See packages/frames/README.md.
47
+ { path: join(currentDir, 'packages/frames/src'), pathPrefix: false, pattern: '**/*.vue' }
48
+ ],
49
+
50
+ // Auto-imported composables — an ALLOW-LIST, not `imports.dirs`. A directory scan would take every
51
+ // export in the mirrored trees, and those barrels carry names like `token`, `isSelected`, `nextKey`
52
+ // and `addClause`: generic enough that dropping them into a consuming app's global namespace
53
+ // invites a collision the app author never asked for and cannot see coming.
54
+ //
55
+ // Listed here is the call-site API — the imperative half of FMap, the chart palette, the two KPI
56
+ // formatters. Everything else a barrel exports stays reachable, deliberately, by path:
57
+ // import { STATE_LABEL } from '#layers/forest/packages/ui/src/map'
58
+ imports: {
59
+ presets: [
60
+ {
61
+ from: join(currentDir, 'packages/ui/src/map/index.ts'),
62
+ // The four state composables join the list because a console needs all of them and each name
63
+ // says "map" or "vehicle" out loud. Their pure cores do NOT: `collectVisible`, `rowKey` and
64
+ // `patchQuery` are exactly the generic names this allow-list exists to keep out of an app's
65
+ // global namespace, and they stay reachable by path.
66
+ imports: [
67
+ 'useMapReady', 'useMapCamera', 'useMapOverlay', 'useFeatureSelect', 'MAP_SLOT',
68
+ 'useMapUrlState', 'useVisibleFeatures', 'useMapTableSelection', 'useVehicleFilter'
69
+ ]
70
+ },
71
+ {
72
+ from: join(currentDir, 'packages/ui/src/kpi/index.ts'),
73
+ imports: ['formatMetric', 'formatPercent']
74
+ },
75
+ {
76
+ from: join(currentDir, 'packages/charts/src/index.ts'),
77
+ imports: ['useChartPalette']
78
+ }
79
+ ]
80
+ }
81
+ })
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@humanforest/nuxt-layer",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "description": "Forest design system as a Nuxt layer — extend it to inherit the theme, colour roles, icons and brand fonts in one line.",
6
+ "main": "./nuxt.config.ts",
7
+ "files": [
8
+ "nuxt.config.ts",
9
+ "app.config.ts",
10
+ "theme.gen.json",
11
+ "styles.cdn.gen.css",
12
+ "assets",
13
+ "packages",
14
+ "apps",
15
+ "README.md"
16
+ ],
17
+ "dependencies": {
18
+ "@humanforest/tokens": "^0.1.0",
19
+ "@internationalized/date": "^3.12.2",
20
+ "@mapbox/search-js-core": "^1.6.0",
21
+ "@unovis/ts": "^1.6.7",
22
+ "@unovis/vue": "^1.6.7",
23
+ "mapbox-gl": "^3.28.1",
24
+ "tailwind-variants": "3.2.2"
25
+ },
26
+ "peerDependencies": {
27
+ "@nuxt/ui": ">=4.5.0",
28
+ "nuxt": "^4.0.0",
29
+ "vue": "^3.5"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "license": "SEE LICENSE IN LICENSE"
35
+ }