@humanforest/tokens 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ Every @humanforest package shares one version, so one entry covers all seven packages. Newest first.
4
+
5
+ ## 0.3.7 — 2026-09-13
6
+
7
+ ### Features
8
+
9
+ - **ui**: add FMapContextMenu, a right-click menu on the map
10
+ - **charts**: chart frames and sparklines can be named for screen readers
11
+
12
+ ### Fixes
13
+
14
+ - **charts**: CellScale types what useCellScale returns
15
+ - **charts**: an empty distribution bar is still named, as "No data"
16
+ - **charts**: a bar sparkline warns that :curve="false" is ignored
17
+ - **charts**: a sparkline leaves non-finite readings off its scale
18
+ - **tokens**: the sub-logo builder passes noUncheckedIndexedAccess
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@humanforest/tokens",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Forest design tokens — the OKLCH colour engine (src/colourEngine.ts) plus the CSS + JSON it generates via scripts/{scales,type,motion,deck,dataviz,logo}.ts, and the logo SVGs. The generated files are framework-agnostic; do not edit them by hand, run `bun run build`.",
5
5
  "files": [
6
+ "CHANGELOG.md",
6
7
  "glyphs",
7
8
  "scales",
8
9
  "type",
package/src/glyphs.ts CHANGED
@@ -14,7 +14,7 @@ import glyphAtlas from '../glyphs/glyphs.json';
14
14
  import { WORDMARK_PATHS, F } from './logo';
15
15
 
16
16
  type Glyph = { d?: string; advance: number; x1?: number; y1?: number; x2?: number; y2?: number };
17
- type Atlas = Record<string, { upm: number; glyphs: Record<string, Glyph> }>;
17
+ type Atlas = Record<FontKey, { upm: number; glyphs: Record<string, Glyph> }>;
18
18
  const ATLAS = glyphAtlas as unknown as Atlas;
19
19
 
20
20
  export type FontKey = 'gt' | 'mohr';
@@ -77,8 +77,8 @@ export function setWord(
77
77
  // lands WORDMARK_F_GAP away — calibrated on the f→o pair the wordmark itself defines.
78
78
  const gtF = ATLAS.gt.glyphs['f'];
79
79
  const gtO = ATLAS.gt.glyphs['o'];
80
- const fLsb = (gtF.x1 ?? 0) * (size / ATLAS.gt.upm);
81
- const fAdvance = fLsb + F.w + (WORDMARK_F_GAP - (gtO.x1 ?? 0) * (size / ATLAS.gt.upm));
80
+ const fLsb = (gtF?.x1 ?? 0) * (size / ATLAS.gt.upm);
81
+ const fAdvance = fLsb + F.w + (WORDMARK_F_GAP - (gtO?.x1 ?? 0) * (size / ATLAS.gt.upm));
82
82
 
83
83
  const out: PlacedGlyph[] = [];
84
84
  let pen = x;
@@ -91,7 +91,7 @@ export function setWord(
91
91
  for (const ch of text) {
92
92
  if (brandF && ch === 'f') {
93
93
  // the artwork, authored in wordmark units with its baseline at F.h — no scaling, it IS the size
94
- out.push({ d: WORDMARK_PATHS[0], transform: `translate(${round(pen + fLsb)} ${round(baseline - F.h)})`, cut: false });
94
+ out.push({ d: WORDMARK_PATHS[0]!, transform: `translate(${round(pen + fLsb)} ${round(baseline - F.h)})`, cut: false });
95
95
  extend(pen + fLsb, baseline - F.h, pen + fLsb + F.w, baseline);
96
96
  pen += fAdvance;
97
97
  continue;
package/src/sublogoSvg.ts CHANGED
@@ -17,7 +17,11 @@ import {
17
17
  } from './sublogo';
18
18
 
19
19
  const ramps = rj as unknown as Record<string, { levels: Record<number, { hex: string; p3: string }> }>;
20
- const level = (family: string, lvl: number) => ramps[family].levels[lvl];
20
+ const level = (family: string, lvl: number) => {
21
+ const colour = ramps[family]?.levels[lvl];
22
+ if (!colour) throw new Error(`sublogoSvg: the ramps have no ${family} ${lvl}`);
23
+ return colour;
24
+ };
21
25
  const fillOf = (family: string, lvl: number) => {
22
26
  const { hex, p3 } = level(family, lvl);
23
27
  return `fill="${hex}" style="fill:${hex};fill:${p3};fill-opacity:1;"`;
@@ -106,9 +110,9 @@ export function buildIconSvg(seed: SubBrand, { classes = true } = {}): { svg: st
106
110
 
107
111
  const ic = iconGeometry();
108
112
  const upper = seed.word.toUpperCase();
109
- const probe = setWord(upper[0], { font: 'mohr', size: SUBLOGO_MOHR_SIZE });
113
+ const probe = setWord(upper.charAt(0), { font: 'mohr', size: SUBLOGO_MOHR_SIZE });
110
114
  const size = (SUBLOGO_MOHR_SIZE * ic.letterCap) / (probe.inkBottom - probe.inkTop);
111
- const run = setWord(upper[0], { font: 'mohr', size });
115
+ const run = setWord(upper.charAt(0), { font: 'mohr', size });
112
116
  const x = ic.cx - (run.inkLeft + (run.inkRight - run.inkLeft) / 2);
113
117
  const y = ic.cy - (run.inkTop + (run.inkBottom - run.inkTop) / 2);
114
118