@nowline/layout 0.8.6 → 0.10.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 (338) hide show
  1. package/dist/axis-columns.d.ts +70 -0
  2. package/dist/axis-columns.d.ts.map +1 -0
  3. package/dist/axis-columns.js +104 -0
  4. package/dist/axis-columns.js.map +1 -0
  5. package/dist/calendar-resolver.d.ts +27 -0
  6. package/dist/calendar-resolver.d.ts.map +1 -0
  7. package/dist/calendar-resolver.js +132 -0
  8. package/dist/calendar-resolver.js.map +1 -0
  9. package/dist/calendar.d.ts +0 -19
  10. package/dist/calendar.d.ts.map +1 -1
  11. package/dist/calendar.js +4 -44
  12. package/dist/calendar.js.map +1 -1
  13. package/dist/canvas-width.d.ts +23 -0
  14. package/dist/canvas-width.d.ts.map +1 -0
  15. package/dist/canvas-width.js +26 -0
  16. package/dist/canvas-width.js.map +1 -0
  17. package/dist/capacity.d.ts +28 -0
  18. package/dist/capacity.d.ts.map +1 -1
  19. package/dist/capacity.js +64 -29
  20. package/dist/capacity.js.map +1 -1
  21. package/dist/chart-translation.d.ts +22 -0
  22. package/dist/chart-translation.d.ts.map +1 -0
  23. package/dist/chart-translation.js +83 -0
  24. package/dist/chart-translation.js.map +1 -0
  25. package/dist/container-header-geometry.d.ts +64 -0
  26. package/dist/container-header-geometry.d.ts.map +1 -0
  27. package/dist/container-header-geometry.js +89 -0
  28. package/dist/container-header-geometry.js.map +1 -0
  29. package/dist/dsl-utils.d.ts +3 -4
  30. package/dist/dsl-utils.d.ts.map +1 -1
  31. package/dist/dsl-utils.js +8 -25
  32. package/dist/dsl-utils.js.map +1 -1
  33. package/dist/edge-routing.d.ts +69 -78
  34. package/dist/edge-routing.d.ts.map +1 -1
  35. package/dist/edge-routing.js +271 -401
  36. package/dist/edge-routing.js.map +1 -1
  37. package/dist/frame-tab-geometry.d.ts +24 -14
  38. package/dist/frame-tab-geometry.d.ts.map +1 -1
  39. package/dist/frame-tab-geometry.js +69 -23
  40. package/dist/frame-tab-geometry.js.map +1 -1
  41. package/dist/header-card-geometry.d.ts +12 -0
  42. package/dist/header-card-geometry.d.ts.map +1 -1
  43. package/dist/header-card-geometry.js +14 -2
  44. package/dist/header-card-geometry.js.map +1 -1
  45. package/dist/header-logo.d.ts +28 -0
  46. package/dist/header-logo.d.ts.map +1 -0
  47. package/dist/header-logo.js +51 -0
  48. package/dist/header-logo.js.map +1 -0
  49. package/dist/i18n.d.ts +11 -0
  50. package/dist/i18n.d.ts.map +1 -1
  51. package/dist/i18n.js +11 -1
  52. package/dist/i18n.js.map +1 -1
  53. package/dist/index.d.ts +20 -8
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +17 -7
  56. package/dist/index.js.map +1 -1
  57. package/dist/inline-date-pin-geometry.d.ts +19 -11
  58. package/dist/inline-date-pin-geometry.d.ts.map +1 -1
  59. package/dist/inline-date-pin-geometry.js +45 -46
  60. package/dist/inline-date-pin-geometry.js.map +1 -1
  61. package/dist/item-bar-geometry.d.ts +192 -4
  62. package/dist/item-bar-geometry.d.ts.map +1 -1
  63. package/dist/item-bar-geometry.js +258 -5
  64. package/dist/item-bar-geometry.js.map +1 -1
  65. package/dist/item-port-geometry.d.ts +13 -0
  66. package/dist/item-port-geometry.d.ts.map +1 -0
  67. package/dist/item-port-geometry.js +63 -0
  68. package/dist/item-port-geometry.js.map +1 -0
  69. package/dist/layout-context.d.ts +115 -51
  70. package/dist/layout-context.d.ts.map +1 -1
  71. package/dist/layout-context.js +96 -5
  72. package/dist/layout-context.js.map +1 -1
  73. package/dist/layout-insights.d.ts.map +1 -1
  74. package/dist/layout-insights.js +73 -1
  75. package/dist/layout-insights.js.map +1 -1
  76. package/dist/layout.d.ts +35 -0
  77. package/dist/layout.d.ts.map +1 -1
  78. package/dist/layout.js +18 -1315
  79. package/dist/layout.js.map +1 -1
  80. package/dist/nodes/anchor-node.d.ts.map +1 -1
  81. package/dist/nodes/anchor-node.js +11 -4
  82. package/dist/nodes/anchor-node.js.map +1 -1
  83. package/dist/nodes/content-extent.d.ts +24 -0
  84. package/dist/nodes/content-extent.d.ts.map +1 -0
  85. package/dist/nodes/content-extent.js +100 -0
  86. package/dist/nodes/content-extent.js.map +1 -0
  87. package/dist/nodes/dependency-edges.d.ts +6 -0
  88. package/dist/nodes/dependency-edges.d.ts.map +1 -0
  89. package/dist/nodes/dependency-edges.js +148 -0
  90. package/dist/nodes/dependency-edges.js.map +1 -0
  91. package/dist/nodes/footnote-node.d.ts +24 -3
  92. package/dist/nodes/footnote-node.d.ts.map +1 -1
  93. package/dist/nodes/footnote-node.js +129 -25
  94. package/dist/nodes/footnote-node.js.map +1 -1
  95. package/dist/nodes/group-node.d.ts +10 -21
  96. package/dist/nodes/group-node.d.ts.map +1 -1
  97. package/dist/nodes/group-node.js +79 -152
  98. package/dist/nodes/group-node.js.map +1 -1
  99. package/dist/nodes/header-node.d.ts +56 -0
  100. package/dist/nodes/header-node.d.ts.map +1 -0
  101. package/dist/nodes/header-node.js +163 -0
  102. package/dist/nodes/header-node.js.map +1 -0
  103. package/dist/nodes/include-node.d.ts +22 -12
  104. package/dist/nodes/include-node.d.ts.map +1 -1
  105. package/dist/nodes/include-node.js +95 -62
  106. package/dist/nodes/include-node.js.map +1 -1
  107. package/dist/nodes/item-measure.d.ts +135 -0
  108. package/dist/nodes/item-measure.d.ts.map +1 -0
  109. package/dist/nodes/item-measure.js +514 -0
  110. package/dist/nodes/item-measure.js.map +1 -0
  111. package/dist/nodes/item-node.d.ts +162 -9
  112. package/dist/nodes/item-node.d.ts.map +1 -1
  113. package/dist/nodes/item-node.js +256 -69
  114. package/dist/nodes/item-node.js.map +1 -1
  115. package/dist/nodes/marker-band.d.ts +118 -0
  116. package/dist/nodes/marker-band.d.ts.map +1 -0
  117. package/dist/nodes/marker-band.js +303 -0
  118. package/dist/nodes/marker-band.js.map +1 -0
  119. package/dist/nodes/marker-geometry.js +1 -1
  120. package/dist/nodes/marker-geometry.js.map +1 -1
  121. package/dist/nodes/milestone-node.d.ts +112 -15
  122. package/dist/nodes/milestone-node.d.ts.map +1 -1
  123. package/dist/nodes/milestone-node.js +246 -95
  124. package/dist/nodes/milestone-node.js.map +1 -1
  125. package/dist/nodes/nowline-node.d.ts +8 -0
  126. package/dist/nodes/nowline-node.d.ts.map +1 -0
  127. package/dist/nodes/nowline-node.js +74 -0
  128. package/dist/nodes/nowline-node.js.map +1 -0
  129. package/dist/nodes/parallel-node.d.ts +7 -12
  130. package/dist/nodes/parallel-node.d.ts.map +1 -1
  131. package/dist/nodes/parallel-node.js +66 -30
  132. package/dist/nodes/parallel-node.js.map +1 -1
  133. package/dist/nodes/region-markers.d.ts +41 -0
  134. package/dist/nodes/region-markers.d.ts.map +1 -0
  135. package/dist/nodes/region-markers.js +130 -0
  136. package/dist/nodes/region-markers.js.map +1 -0
  137. package/dist/nodes/roadmap-node.d.ts +9 -72
  138. package/dist/nodes/roadmap-node.d.ts.map +1 -1
  139. package/dist/nodes/roadmap-node.js +38 -788
  140. package/dist/nodes/roadmap-node.js.map +1 -1
  141. package/dist/nodes/row-track.d.ts +33 -0
  142. package/dist/nodes/row-track.d.ts.map +1 -0
  143. package/dist/nodes/row-track.js +170 -0
  144. package/dist/nodes/row-track.js.map +1 -0
  145. package/dist/nodes/sequence-item.d.ts +25 -0
  146. package/dist/nodes/sequence-item.d.ts.map +1 -0
  147. package/dist/nodes/sequence-item.js +396 -0
  148. package/dist/nodes/sequence-item.js.map +1 -0
  149. package/dist/nodes/sequence-one.d.ts +5 -0
  150. package/dist/nodes/sequence-one.d.ts.map +1 -0
  151. package/dist/nodes/sequence-one.js +26 -0
  152. package/dist/nodes/sequence-one.js.map +1 -0
  153. package/dist/nodes/swimlane-node.d.ts +5 -17
  154. package/dist/nodes/swimlane-node.d.ts.map +1 -1
  155. package/dist/nodes/swimlane-node.js +62 -145
  156. package/dist/nodes/swimlane-node.js.map +1 -1
  157. package/dist/nodes/wave-node.d.ts +52 -0
  158. package/dist/nodes/wave-node.d.ts.map +1 -0
  159. package/dist/nodes/wave-node.js +483 -0
  160. package/dist/nodes/wave-node.js.map +1 -0
  161. package/dist/non-working-display.d.ts +14 -0
  162. package/dist/non-working-display.d.ts.map +1 -0
  163. package/dist/non-working-display.js +28 -0
  164. package/dist/non-working-display.js.map +1 -0
  165. package/dist/phases/date-window.d.ts +48 -0
  166. package/dist/phases/date-window.d.ts.map +1 -0
  167. package/dist/phases/date-window.js +130 -0
  168. package/dist/phases/date-window.js.map +1 -0
  169. package/dist/phases/finalize.d.ts +198 -0
  170. package/dist/phases/finalize.d.ts.map +1 -0
  171. package/dist/phases/finalize.js +1058 -0
  172. package/dist/phases/finalize.js.map +1 -0
  173. package/dist/phases/measure.d.ts +77 -0
  174. package/dist/phases/measure.d.ts.map +1 -0
  175. package/dist/phases/measure.js +222 -0
  176. package/dist/phases/measure.js.map +1 -0
  177. package/dist/phases/place.d.ts +28 -0
  178. package/dist/phases/place.d.ts.map +1 -0
  179. package/dist/phases/place.js +225 -0
  180. package/dist/phases/place.js.map +1 -0
  181. package/dist/renderable.d.ts.map +1 -1
  182. package/dist/renderable.js +23 -3
  183. package/dist/renderable.js.map +1 -1
  184. package/dist/resolve-today.d.ts +11 -1
  185. package/dist/resolve-today.d.ts.map +1 -1
  186. package/dist/resolve-today.js +26 -12
  187. package/dist/resolve-today.js.map +1 -1
  188. package/dist/row-packer.d.ts +42 -16
  189. package/dist/row-packer.d.ts.map +1 -1
  190. package/dist/row-packer.js +51 -78
  191. package/dist/row-packer.js.map +1 -1
  192. package/dist/schedule.d.ts +58 -1
  193. package/dist/schedule.d.ts.map +1 -1
  194. package/dist/schedule.js +280 -106
  195. package/dist/schedule.js.map +1 -1
  196. package/dist/start-rules.d.ts +27 -0
  197. package/dist/start-rules.d.ts.map +1 -0
  198. package/dist/start-rules.js +91 -0
  199. package/dist/start-rules.js.map +1 -0
  200. package/dist/start-terms.d.ts +23 -0
  201. package/dist/start-terms.d.ts.map +1 -0
  202. package/dist/start-terms.js +27 -0
  203. package/dist/start-terms.js.map +1 -0
  204. package/dist/status-dot.d.ts +46 -0
  205. package/dist/status-dot.d.ts.map +1 -0
  206. package/dist/status-dot.js +78 -0
  207. package/dist/status-dot.js.map +1 -0
  208. package/dist/style-resolution.d.ts.map +1 -1
  209. package/dist/style-resolution.js +23 -43
  210. package/dist/style-resolution.js.map +1 -1
  211. package/dist/text-measure.d.ts +28 -0
  212. package/dist/text-measure.d.ts.map +1 -0
  213. package/dist/text-measure.js +70 -0
  214. package/dist/text-measure.js.map +1 -0
  215. package/dist/themes/contrast.d.ts +4 -0
  216. package/dist/themes/contrast.d.ts.map +1 -0
  217. package/dist/themes/contrast.js +32 -0
  218. package/dist/themes/contrast.js.map +1 -0
  219. package/dist/themes/dark.d.ts.map +1 -1
  220. package/dist/themes/dark.js +28 -1
  221. package/dist/themes/dark.js.map +1 -1
  222. package/dist/themes/grayscale.d.ts.map +1 -1
  223. package/dist/themes/grayscale.js +28 -1
  224. package/dist/themes/grayscale.js.map +1 -1
  225. package/dist/themes/index.d.ts +4 -11
  226. package/dist/themes/index.d.ts.map +1 -1
  227. package/dist/themes/index.js +6 -4
  228. package/dist/themes/index.js.map +1 -1
  229. package/dist/themes/light.d.ts.map +1 -1
  230. package/dist/themes/light.js +28 -1
  231. package/dist/themes/light.js.map +1 -1
  232. package/dist/themes/shape.d.ts +31 -0
  233. package/dist/themes/shape.d.ts.map +1 -1
  234. package/dist/themes/shared.d.ts +44 -50
  235. package/dist/themes/shared.d.ts.map +1 -1
  236. package/dist/themes/shared.js +79 -83
  237. package/dist/themes/shared.js.map +1 -1
  238. package/dist/time-scale.d.ts +42 -6
  239. package/dist/time-scale.d.ts.map +1 -1
  240. package/dist/time-scale.js +109 -17
  241. package/dist/time-scale.js.map +1 -1
  242. package/dist/types.d.ts +528 -11
  243. package/dist/types.d.ts.map +1 -1
  244. package/dist/view-preset.d.ts +61 -6
  245. package/dist/view-preset.d.ts.map +1 -1
  246. package/dist/view-preset.js +439 -24
  247. package/dist/view-preset.js.map +1 -1
  248. package/dist/wave-barrier.d.ts +107 -0
  249. package/dist/wave-barrier.d.ts.map +1 -0
  250. package/dist/wave-barrier.js +174 -0
  251. package/dist/wave-barrier.js.map +1 -0
  252. package/dist/wave-hatch.d.ts +4 -0
  253. package/dist/wave-hatch.d.ts.map +1 -0
  254. package/dist/wave-hatch.js +21 -0
  255. package/dist/wave-hatch.js.map +1 -0
  256. package/dist/wave-layout.d.ts +99 -0
  257. package/dist/wave-layout.d.ts.map +1 -0
  258. package/dist/wave-layout.js +130 -0
  259. package/dist/wave-layout.js.map +1 -0
  260. package/dist/working-calendar.d.ts +128 -4
  261. package/dist/working-calendar.d.ts.map +1 -1
  262. package/dist/working-calendar.js +725 -51
  263. package/dist/working-calendar.js.map +1 -1
  264. package/dist/working-span.d.ts +11 -0
  265. package/dist/working-span.d.ts.map +1 -0
  266. package/dist/working-span.js +18 -0
  267. package/dist/working-span.js.map +1 -0
  268. package/package.json +4 -4
  269. package/src/axis-columns.ts +140 -0
  270. package/src/calendar-resolver.ts +161 -0
  271. package/src/calendar.ts +4 -45
  272. package/src/canvas-width.ts +36 -0
  273. package/src/capacity.ts +71 -30
  274. package/src/chart-translation.ts +88 -0
  275. package/src/container-header-geometry.ts +116 -0
  276. package/src/dsl-utils.ts +8 -26
  277. package/src/edge-routing.ts +347 -491
  278. package/src/frame-tab-geometry.ts +78 -25
  279. package/src/header-card-geometry.ts +17 -2
  280. package/src/header-logo.ts +67 -0
  281. package/src/i18n.ts +22 -1
  282. package/src/index.ts +97 -12
  283. package/src/inline-date-pin-geometry.ts +55 -58
  284. package/src/item-bar-geometry.ts +341 -5
  285. package/src/item-port-geometry.ts +69 -0
  286. package/src/layout-context.ts +210 -72
  287. package/src/layout-insights.ts +109 -2
  288. package/src/layout.ts +57 -1530
  289. package/src/nodes/anchor-node.ts +11 -4
  290. package/src/nodes/content-extent.ts +107 -0
  291. package/src/nodes/dependency-edges.ts +171 -0
  292. package/src/nodes/footnote-node.ts +171 -31
  293. package/src/nodes/group-node.ts +92 -214
  294. package/src/nodes/header-node.ts +255 -0
  295. package/src/nodes/include-node.ts +124 -110
  296. package/src/nodes/item-measure.ts +723 -0
  297. package/src/nodes/item-node.ts +358 -80
  298. package/src/nodes/marker-band.ts +406 -0
  299. package/src/nodes/marker-geometry.ts +1 -1
  300. package/src/nodes/milestone-node.ts +321 -136
  301. package/src/nodes/nowline-node.ts +87 -0
  302. package/src/nodes/parallel-node.ts +69 -38
  303. package/src/nodes/region-markers.ts +194 -0
  304. package/src/nodes/roadmap-node.ts +46 -950
  305. package/src/nodes/row-track.ts +217 -0
  306. package/src/nodes/sequence-item.ts +433 -0
  307. package/src/nodes/sequence-one.ts +40 -0
  308. package/src/nodes/swimlane-node.ts +66 -205
  309. package/src/nodes/wave-node.ts +609 -0
  310. package/src/non-working-display.ts +32 -0
  311. package/src/phases/date-window.ts +191 -0
  312. package/src/phases/finalize.ts +1303 -0
  313. package/src/phases/measure.ts +329 -0
  314. package/src/phases/place.ts +318 -0
  315. package/src/renderable.ts +23 -3
  316. package/src/resolve-today.ts +28 -25
  317. package/src/row-packer.ts +85 -84
  318. package/src/schedule.ts +362 -114
  319. package/src/start-rules.ts +113 -0
  320. package/src/start-terms.ts +38 -0
  321. package/src/status-dot.ts +81 -0
  322. package/src/style-resolution.ts +27 -57
  323. package/src/text-measure.ts +71 -0
  324. package/src/themes/contrast.ts +34 -0
  325. package/src/themes/dark.ts +28 -1
  326. package/src/themes/grayscale.ts +28 -1
  327. package/src/themes/index.ts +10 -7
  328. package/src/themes/light.ts +28 -1
  329. package/src/themes/shape.ts +38 -0
  330. package/src/themes/shared.ts +85 -93
  331. package/src/time-scale.ts +117 -19
  332. package/src/types.ts +529 -20
  333. package/src/view-preset.ts +520 -27
  334. package/src/wave-barrier.ts +242 -0
  335. package/src/wave-hatch.ts +25 -0
  336. package/src/wave-layout.ts +203 -0
  337. package/src/working-calendar.ts +875 -57
  338. package/src/working-span.ts +19 -0
package/dist/types.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { FrameTabGeometry } from './frame-tab-geometry.js';
2
+ import type { NonWorkingDisplay } from './non-working-display.js';
1
3
  export type SizeBucket = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
2
4
  export type ShadowKind = 'none' | 'subtle' | 'soft' | 'hard';
3
5
  export type BorderKind = 'solid' | 'dashed' | 'dotted';
@@ -7,6 +9,12 @@ export type BracketKind = 'none' | 'solid' | 'dashed';
7
9
  export type HeaderPosition = 'beside' | 'above';
8
10
  export type TimelinePosition = 'top' | 'bottom' | 'both';
9
11
  export type StatusKind = 'planned' | 'in-progress' | 'done' | 'at-risk' | 'blocked' | 'neutral';
12
+ /**
13
+ * Which hatch stroke marks background work on a fill (specs/waves.md §9.3):
14
+ * `dark` (`wave.hatch`) on a light fill, `light` (`wave.hatchOnDark`) on a
15
+ * dark one.
16
+ */
17
+ export type WaveHatchKind = 'dark' | 'light';
10
18
  export interface ResolvedStyle {
11
19
  bg: string;
12
20
  fg: string;
@@ -36,6 +44,12 @@ export interface ResolvedStyle {
36
44
  capacityIcon: string;
37
45
  timelinePosition: TimelinePosition;
38
46
  minorGrid: boolean;
47
+ /**
48
+ * How a calendar's non-working days are drawn (roadmap-only, from
49
+ * `default roadmap non-working:`). Default `'hide'`; a surface option
50
+ * overrides it (`LayoutOptions.nonWorking`).
51
+ */
52
+ nonWorking: NonWorkingDisplay;
39
53
  }
40
54
  export interface BoundingBox {
41
55
  x: number;
@@ -73,6 +87,10 @@ export interface Point {
73
87
  export interface PositionedLogo {
74
88
  box: BoundingBox;
75
89
  assetRef?: string;
90
+ intrinsic?: {
91
+ width: number;
92
+ height: number;
93
+ };
76
94
  }
77
95
  export interface PositionedHeader {
78
96
  box: BoundingBox;
@@ -83,6 +101,7 @@ export interface PositionedHeader {
83
101
  authorLines: string[];
84
102
  cardBox: BoundingBox;
85
103
  logo?: PositionedLogo;
104
+ textInset?: Point;
86
105
  style: ResolvedStyle;
87
106
  attributionBox: BoundingBox;
88
107
  }
@@ -110,7 +129,101 @@ export interface PositionedTimelineScale {
110
129
  };
111
130
  bottomTickPanelY?: number;
112
131
  bottomTickPanelHeight?: number;
132
+ /**
133
+ * The wave strip row (specs/waves.md §8.8): `WAVE_STRIP_HEIGHT_PX`
134
+ * high, directly under the top tick panel (under the now-pill row
135
+ * with `timeline-position:bottom`) and above the marker rows, which
136
+ * move down by its height. Present only when some declared wave has
137
+ * items (specs/waves.md §9.1); the mirrored bottom panel never has one.
138
+ */
139
+ waveStrip?: {
140
+ y: number;
141
+ height: number;
142
+ };
113
143
  minorGrid: boolean;
144
+ /**
145
+ * How the axis shows non-working days (specs/working-calendar.md §7):
146
+ * `hide` collapses them to zero width, `show` draws them at full width.
147
+ * Present, with `nonWorking`, only when the window holds a non-working
148
+ * day.
149
+ */
150
+ nonWorkingDisplay?: NonWorkingDisplay;
151
+ /** The window's non-working runs, left to right; see `PositionedNonWorkingRun`. */
152
+ nonWorking?: PositionedNonWorkingRun[];
153
+ /**
154
+ * The window's labelled working exceptions, left to right; see
155
+ * `PositionedWorkingException`. Omitted when there are none.
156
+ */
157
+ workingExceptions?: PositionedWorkingException[];
158
+ }
159
+ /**
160
+ * One run of days that titled dated `working` rules turn from non-working
161
+ * to working (specs/working-calendar.md §7.4, §7.5). It is labelled in the
162
+ * marker row like a titled non-working run, but never drawn as a cut line
163
+ * or a band: a working day removes no time.
164
+ */
165
+ export interface PositionedWorkingException {
166
+ /** The run's first day: its column start under `hide`, its day start under `show` (clamped to the window). */
167
+ x: number;
168
+ /** First day the rules turn (UTC midnight). */
169
+ from: Date;
170
+ /** Last day the rules turn, inclusive (UTC midnight). */
171
+ through: Date;
172
+ /** Titles of the titled dated working rules that turn a day of the run. */
173
+ titles: string[];
174
+ /** The titles joined with `, `, then ` · +Nd` for the N days turned. */
175
+ label: string;
176
+ /** Resolved placement of `label` in the marker row, like `PositionedNonWorkingRun.labelBox`. */
177
+ labelBox?: BoundingBox;
178
+ labelSide?: 'left' | 'right';
179
+ }
180
+ /**
181
+ * One maximal run of non-working days in (or straddling) the window
182
+ * (specs/working-calendar.md §7.5). Under `hide` its `width` is 0 and `x`
183
+ * is the start of the next working day. Under `show` it spans its days,
184
+ * with `x` and the right edge clamped to the window; `from` / `through`
185
+ * keep the run's real dates.
186
+ */
187
+ export interface PositionedNonWorkingRun {
188
+ x: number;
189
+ width: number;
190
+ /** First non-working date of the run (UTC midnight). */
191
+ from: Date;
192
+ /** Last non-working date of the run, inclusive. */
193
+ through: Date;
194
+ /** Titles of the dated rules inside it; omitted for a plain weekend. */
195
+ titles?: string[];
196
+ /**
197
+ * The marker-row label of a titled run: its titles joined with `, `,
198
+ * then ` · Nd` for the N working days of the open-ended week the run
199
+ * closes (dropped when N is 0). Omitted on a run without titles.
200
+ */
201
+ label?: string;
202
+ /**
203
+ * Resolved placement of `label` in the marker row, exactly like
204
+ * `PositionedMilestone.labelBox` / `labelSide`. Omitted on a run
205
+ * without titles.
206
+ */
207
+ labelBox?: BoundingBox;
208
+ labelSide?: 'left' | 'right';
209
+ /**
210
+ * Set under `hide` on a titled run, at every scale: the renderer draws
211
+ * the named cut line at `x` from the label row down through the chart
212
+ * (spec §7.2, "a named seam always draws"). Independent of `seam`.
213
+ */
214
+ cut?: true;
215
+ /**
216
+ * Set at the days scale when the run lies strictly inside the chart and
217
+ * no grid line is drawn at its x; the renderer draws a seam there.
218
+ * Never set under `show`.
219
+ */
220
+ seam?: true;
221
+ /**
222
+ * Set under `show` at the days and weeks scales, or when the run has
223
+ * titles: the renderer paints the run as a shaded band. Coarser scales
224
+ * leave a plain weekend unpainted.
225
+ */
226
+ band?: true;
114
227
  }
115
228
  /**
116
229
  * How the now-pill is positioned relative to the now-line.
@@ -179,9 +292,59 @@ export interface InlineDatePin {
179
292
  export interface PositionedItem {
180
293
  kind: 'item';
181
294
  id?: string;
295
+ /**
296
+ * The full, unwrapped title exactly as authored, explicit line breaks
297
+ * included (`"Technology\nSelection"` keeps its newline here). Always
298
+ * present, wrapped or not.
299
+ */
182
300
  title: string;
301
+ /**
302
+ * The title split into the lines the renderer paints, one `<text>` per
303
+ * line. Present when the painted lines differ from `[title]`:
304
+ *
305
+ * - the title word-wrapped INSIDE the bar (`length === 2`, at most
306
+ * `ITEM_CAPTION_TITLE_MAX_LINES`), or
307
+ * - the title carries explicit `\n` breaks (any `length >= 2`, in-bar
308
+ * or spilled to the right of the bar). Lines are trimmed, leading
309
+ * and trailing empty lines are dropped, interior empty lines stay as
310
+ * blank entries. An explicit title never auto-wraps.
311
+ *
312
+ * Omitted for a one-line title, and for a break-free title that spilled
313
+ * to the right (always one line), unless the caption cap at the chart's
314
+ * end truncated it (`titleTruncated`). Line `n` (0-based) sits at baseline
315
+ * `ITEM_CAPTION_TITLE_BASELINE_OFFSET_PX + n * ITEM_CAPTION_TITLE_LINE_HEIGHT_PX`
316
+ * from the bar's top, and the meta line follows at
317
+ * `itemCaptionMetaBaselineOffset(titleLines.length)`. A multi-line
318
+ * caption with a meta line grows the bar (`box.height`) by 16px per
319
+ * extra line.
320
+ */
321
+ titleLines?: string[];
322
+ /**
323
+ * True when a spilled caption that would run past the axis end was
324
+ * capped at the overhang budget past it: `titleLines` carries the lines truncated
325
+ * with `…`, and the renderer gives the bar the full `title` as its
326
+ * `<title>` tooltip (specs/rendering.md § "Caption cap at the chart's
327
+ * end"). Omitted otherwise.
328
+ */
329
+ titleTruncated?: true;
183
330
  box: BoundingBox;
331
+ /**
332
+ * The item's dates in x: its scheduled start and end through the time
333
+ * scale. The bar (`box`) is drawn inside them, a seam in from each
334
+ * (specs/true-width-layout.md §3.1); dependency arrows and milestone
335
+ * slack lines read them (§3.4, §3.5).
336
+ */
337
+ dateSpan: {
338
+ startX: number;
339
+ endX: number;
340
+ };
184
341
  status: StatusKind;
342
+ /**
343
+ * The status dot's resolved colour: the theme's `statusDot.onLight` or
344
+ * `onDark` entry for `status`, picked by the luminance of `style.bg`
345
+ * (`statusDotColor` in `status-dot.ts`).
346
+ */
347
+ statusDotColor: string;
185
348
  progressFraction: number;
186
349
  footnoteIndicators: number[];
187
350
  labelChips: PositionedLabelChip[];
@@ -259,6 +422,36 @@ export interface PositionedItem {
259
422
  */
260
423
  size: ResolvedSize | null;
261
424
  style: ResolvedStyle;
425
+ /**
426
+ * Wave membership (specs/waves.md §8.7): `member` for an item with an
427
+ * effective wave, `background` for one without. Set on every item, in
428
+ * the main lanes and in isolated regions, when the roadmap declares
429
+ * waves; omitted otherwise.
430
+ */
431
+ waveRole?: 'member' | 'background';
432
+ /**
433
+ * The hatch kind for the bar's fill (`waveHatchKind` in
434
+ * `wave-hatch.ts`). Set exactly on background items; omitted otherwise.
435
+ */
436
+ waveHatch?: WaveHatchKind;
437
+ /**
438
+ * The hover tooltip line wave membership adds to the bar, localized
439
+ * (`Background (no wave)`; specs/waves.md §9.3). Set only on
440
+ * background items; omitted otherwise.
441
+ */
442
+ waveTooltip?: string;
443
+ /**
444
+ * Present when the item's `after:DATE` pin falls on a non-working day
445
+ * and that pin set the start (NL.I1008, specs/working-calendar.md §6):
446
+ * `key` / `pin` are the pin as written, `start` the working day the
447
+ * item starts on (YYYY-MM-DD). Omitted when a later `after:` ref, the
448
+ * lane cursor or a wave floor set the start.
449
+ */
450
+ nonWorkingPin?: {
451
+ key: 'after';
452
+ pin: string;
453
+ start: string;
454
+ };
262
455
  }
263
456
  /**
264
457
  * Positioned capacity suffix shared by `PositionedItem` and (in m7) the lane
@@ -275,6 +468,15 @@ export interface PositionedCapacity {
275
468
  text: string;
276
469
  /** Resolved glyph instruction, or `null` when the icon is `'none'`. */
277
470
  icon: ResolvedCapacityIconRef | null;
471
+ /**
472
+ * For a built-in SVG icon (person, people, points, time): the px terms
473
+ * that, added in order to the start x of the text run the suffix is
474
+ * painted in (the item caption x, or the lane badge x), give the icon's
475
+ * x, from `capacityIconDxTerms`. Kept apart so the sum rounds the same
476
+ * as adding each width to x in turn. Omitted for every other glyph,
477
+ * which paints inside the `<text>`.
478
+ */
479
+ iconDxTerms?: readonly number[];
278
480
  }
279
481
  /**
280
482
  * Renderer-facing capacity-icon reference. Mirrors the layout-internal
@@ -299,18 +501,35 @@ export interface PositionedGroup {
299
501
  kind: 'group';
300
502
  id?: string;
301
503
  title?: string;
504
+ /** The whole container: `box.y` is the header's top, `box.x` and
505
+ * `box.width` span exactly its children's dates
506
+ * (specs/true-width-layout.md §3.3). */
302
507
  box: BoundingBox;
508
+ /** Header band height above the body (title, glyphs, bracket); 0 when
509
+ * there is no header. The body runs from `box.y + headerHeight` to the
510
+ * box's bottom. */
511
+ headerHeight: number;
303
512
  children: PositionedTrackChild[];
304
513
  /** Inline-date pins attached to this group (`after:DATE` / `before:DATE`).
305
514
  * See `InlineDatePin` and specs/rendering.md "Inline-date glyph". */
306
515
  inlineDatePins?: InlineDatePin[];
307
516
  style: ResolvedStyle;
517
+ /**
518
+ * True for an untitled group with no `style:` and no `labels:` that
519
+ * carries `wave:`, in a roadmap with waves: it only assigns wave
520
+ * membership, so the renderer draws nothing for it (specs/waves.md §9.7).
521
+ * Omitted otherwise.
522
+ */
523
+ waveOnly?: true;
308
524
  }
309
525
  export interface PositionedParallel {
310
526
  kind: 'parallel';
311
527
  id?: string;
312
528
  title?: string;
529
+ /** The whole container, as `PositionedGroup.box`. */
313
530
  box: BoundingBox;
531
+ /** Header band height above the body, as `PositionedGroup.headerHeight`. */
532
+ headerHeight: number;
314
533
  children: PositionedTrackChild[];
315
534
  /** Inline-date pins attached to this parallel (`after:DATE` / `before:DATE`).
316
535
  * See `InlineDatePin` and specs/rendering.md "Inline-date glyph". */
@@ -327,6 +546,12 @@ export interface PositionedSwimlane {
327
546
  nested: PositionedSwimlane[];
328
547
  style: ResolvedStyle;
329
548
  owner?: string;
549
+ /**
550
+ * What `owner` names, for the glyph that leads it in the frame tab:
551
+ * `person` for a declared person, `team` otherwise (a team, or an id
552
+ * that names neither). Set exactly when `owner` is.
553
+ */
554
+ ownerKind?: 'person' | 'team';
330
555
  footnoteIndicators: number[];
331
556
  /**
332
557
  * Lane-level capacity badge data when the swimlane declares
@@ -341,6 +566,13 @@ export interface PositionedSwimlane {
341
566
  * want the badge fully hidden simply omit `capacity:`.
342
567
  */
343
568
  capacity: PositionedCapacity | null;
569
+ /**
570
+ * The frame tab's geometry, from `frameTabGeometry` with the lane's
571
+ * box x, its title, the owner display title and the capacity badge and
572
+ * footnote-indicator widths. Layout sizes the tab's collision box from
573
+ * it and the renderer draws it as is. Null when the lane has no title.
574
+ */
575
+ tab: FrameTabGeometry | null;
344
576
  /**
345
577
  * Tri-state utilization underline data when the lane declares
346
578
  * `capacity:` AND has at least one item contributing load AND has not
@@ -405,6 +637,12 @@ export interface PositionedAnchor {
405
637
  bumpedUp: boolean;
406
638
  labelBox: BoundingBox;
407
639
  labelSide: 'left' | 'right';
640
+ /**
641
+ * The anchor's `date:` (YYYY-MM-DD) when it falls on a non-working day
642
+ * the axis hides; the renderer surfaces it as a `<title>`. Omitted on a
643
+ * working day and under a calendar with no non-working days.
644
+ */
645
+ hiddenDate?: string;
408
646
  }
409
647
  export interface PositionedMilestone {
410
648
  id?: string;
@@ -417,11 +655,48 @@ export interface PositionedMilestone {
417
655
  y: number;
418
656
  }>;
419
657
  isOverrun: boolean;
658
+ /**
659
+ * Where an overrun dated milestone actually lands: the end of its
660
+ * latest predecessor or overrunning wave. `center` stays on the
661
+ * planned date; the renderer draws that diamond in the overrun colour,
662
+ * a dotted span on the same row to a second diamond at `slip.x`, and
663
+ * puts the label and the cut line there (specs/rendering.md,
664
+ * Milestones). Omitted when the milestone does not overrun, or when
665
+ * the two diamonds would meet.
666
+ */
667
+ slip?: {
668
+ x: number;
669
+ };
420
670
  style: ResolvedStyle;
421
671
  cutTopY: number;
422
672
  cutBottomY: number;
423
673
  labelBox: BoundingBox;
424
674
  labelSide: 'left' | 'right';
675
+ /**
676
+ * True when the diamond sits on a wave boundary (within 0.5 px of any
677
+ * `S_k` or `E_k` other than the origin; specs/waves.md §9.2). The
678
+ * boundary line carries the vertical, so the cut line is not drawn.
679
+ * Omitted when false and when the roadmap has no waves.
680
+ */
681
+ onWaveBoundary?: boolean;
682
+ /**
683
+ * The wave that runs past this dated milestone: its `after:` lists the
684
+ * wave and the wave's end `E_k` lies past `date:` (NL.I1007). The
685
+ * latest-ending such wave; omitted when none.
686
+ */
687
+ overrunByWave?: string;
688
+ /**
689
+ * The milestone's own `date:` (YYYY-MM-DD), set together with
690
+ * `overrunByWave`, so NL.I1007 never reads the date back off x.
691
+ */
692
+ overrunDate?: string;
693
+ /**
694
+ * The milestone's `date:` (YYYY-MM-DD) when it falls on a non-working
695
+ * day the axis hides; the renderer surfaces it as a `<title>`. Omitted
696
+ * on a working day, for after-only milestones, and under a calendar
697
+ * with no non-working days.
698
+ */
699
+ hiddenDate?: string;
425
700
  }
426
701
  /**
427
702
  * Result of packing a marker-row entity (anchor or milestone) into the
@@ -453,19 +728,23 @@ export interface SlackCorridor {
453
728
  export interface PositionedDependencyEdge {
454
729
  fromId: string;
455
730
  toId: string;
731
+ /**
732
+ * Orthogonal path on the dates (specs/true-width-layout.md §3.4): first
733
+ * = source port, last = target port, where the arrowhead's tip lands.
734
+ * Item and container sources route vertical, horizontal (in a gap
735
+ * between rows), vertical; a target on its source's row and a marker
736
+ * stub are one horizontal leg.
737
+ */
456
738
  waypoints: Point[];
739
+ /** The target waits on its source: the horizontal legs are dotted. */
740
+ slack: boolean;
457
741
  /**
458
- * - `normal` — orthogonal arrow drawn AFTER swimlane / item /
459
- * marker fills so it sits on top of lane bands.
460
- * - `overflow` — currently unused at construction; reserved for the
461
- * red `before:` overrun annotation arrow.
462
- * - `underBar` — channel router could not find a clear vertical
463
- * gutter between the source and target columns; the arrow's
464
- * vertical leg crosses one or more item bars. The renderer paints
465
- * these edges BEFORE bar fills with a thinner stroke so the bar
466
- * stays the visual foreground.
467
- */
468
- kind: 'normal' | 'overflow' | 'underBar';
742
+ * Arrowhead width across its leg, scaled down to the target's width;
743
+ * a target narrower than `ARROW_HEAD_MIN_PX` gets a dot that wide
744
+ * (`head: 'dot'`) instead (§8 O6).
745
+ */
746
+ headWidth: number;
747
+ head: 'arrow' | 'dot';
469
748
  style: ResolvedStyle;
470
749
  }
471
750
  export interface PositionedFootnoteIndicator {
@@ -478,17 +757,238 @@ export interface PositionedFootnoteArea {
478
757
  entries: PositionedFootnoteEntry[];
479
758
  }
480
759
  export interface PositionedFootnoteEntry {
760
+ /**
761
+ * The title of the isolated region the footnote comes from; the
762
+ * renderer heads each region's run of entries with it. Omitted on the
763
+ * host's own footnotes.
764
+ */
765
+ region?: string;
766
+ /**
767
+ * Baseline of the region's heading row, on the first entry of each
768
+ * region's run only.
769
+ */
770
+ regionHeadingY?: number;
481
771
  number: number;
772
+ /** Baseline of the entry's first row, where its number sits. */
773
+ y: number;
482
774
  title: string;
775
+ /** The title's rows: one unless it is wider than the panel. */
776
+ titleLines: PositionedFootnoteLine[];
483
777
  description?: string;
778
+ /**
779
+ * The description's rows, the first led by `— `: beside the title when
780
+ * its first word fits there, the rest wrapped at the title's x. Omitted
781
+ * when the footnote has no description.
782
+ */
783
+ descriptionLines?: PositionedFootnoteLine[];
484
784
  style: ResolvedStyle;
485
785
  }
786
+ /** One row of footnote text, at its baseline. */
787
+ export interface PositionedFootnoteLine {
788
+ x: number;
789
+ y: number;
790
+ text: string;
791
+ }
486
792
  export interface PositionedIncludeRegion {
487
793
  sourcePath: string;
488
794
  label: string;
489
795
  box: BoundingBox;
490
796
  nestedSwimlanes: PositionedSwimlane[];
491
797
  style: ResolvedStyle;
798
+ /**
799
+ * Wave crossings over this region's background bars (specs/waves.md
800
+ * §9.3, §9.8), re-emitted inside the region because its opaque fill
801
+ * hides the global layers. Omitted when there are none.
802
+ */
803
+ waveCrossings?: PositionedWaveCrossing[];
804
+ /**
805
+ * The region's own anchors and milestones, in its own marker row
806
+ * under the label tab; their cut lines stop at its last lane. Omitted
807
+ * when it has none to draw.
808
+ */
809
+ anchors?: PositionedAnchor[];
810
+ milestones?: PositionedMilestone[];
811
+ /**
812
+ * The region's own dependency edges, routed among its lanes. Omitted
813
+ * when it has none.
814
+ */
815
+ edges?: PositionedDependencyEdge[];
816
+ }
817
+ /**
818
+ * One wave's solved span (specs/waves.md §5.1, §8.7), in declaration order.
819
+ * Only present in a roadmap that declares waves.
820
+ */
821
+ export interface PositionedWave {
822
+ id: string;
823
+ /** The wave's title, else its id. */
824
+ title: string;
825
+ /** 0-based declaration order. */
826
+ index: number;
827
+ /** `S_k` in logical px. */
828
+ startX: number;
829
+ /** `E_k` in logical px; equals `startX` for an empty wave. */
830
+ endX: number;
831
+ /** `S_k` as a whole UTC day. */
832
+ startDate: Date;
833
+ /** `E_k` as a whole UTC day, exclusive. */
834
+ endDate: Date;
835
+ /** Members placed in the main lanes and first-level isolated regions. */
836
+ memberCount: number;
837
+ /** True when the wave has no members (it spans no time). */
838
+ empty: boolean;
839
+ /**
840
+ * The member that sets `E_k` (its id, else its title). Omitted when no
841
+ * member's end equals `E_k` with `E_k > S_k` (§5.1 "Held by").
842
+ */
843
+ heldBy?: string;
844
+ /** The wave's `after:` value that set `S_k`, when it beat `E_{k-1}`. */
845
+ floorRef?: string;
846
+ /**
847
+ * 0-based position among the non-empty waves; drives the strip-cell
848
+ * alternation (even: `wave.stripFill`, odd: `wave.stripFillAlt`), so
849
+ * empty waves and gaps never break it. Omitted for an empty wave.
850
+ */
851
+ visibleOrdinal?: number;
852
+ /** The wave's column: `startX..endX` × `chartTopY..swimlaneBottomY`. */
853
+ columnBox: BoundingBox;
854
+ /** The wave's strip cell (specs/waves.md §9.1). */
855
+ strip: PositionedWaveStrip;
856
+ /** Resolved colours (specs/waves.md §9.4). */
857
+ style: PositionedWaveStyle;
858
+ /** 1-based numbers of the footnotes whose `on:` names this wave, ascending. */
859
+ footnoteIndicators: number[];
860
+ }
861
+ /** One wave's strip cell (specs/waves.md §9.1). */
862
+ export interface PositionedWaveStrip {
863
+ /** `startX..endX` at `waveStrip.y`; zero width for an empty wave. */
864
+ box: BoundingBox;
865
+ /** The label text; omitted when `labelKind` is `none`. */
866
+ label?: string;
867
+ /**
868
+ * The painted cell: `box` clipped to the timeline's backing panel and
869
+ * inset by `WAVE_CELL_INSET_PX` (half the panel's stroke) so it never
870
+ * covers the panel border. Omitted for an empty wave and for one that
871
+ * lies outside the timeline.
872
+ */
873
+ cell?: BoundingBox;
874
+ /**
875
+ * Where the label is drawn when the wave has a `cell`: `x` is the text
876
+ * centre (`labelX`, moved left when the superscripts would cover it)
877
+ * and `halo` the backing box in the cell's fill. Omitted when there is
878
+ * no label or no cell.
879
+ */
880
+ labelDraw?: {
881
+ x: number;
882
+ halo: BoundingBox;
883
+ };
884
+ /**
885
+ * The calendar glyph for a declared date floor (`wave launch after:2026-11-02`),
886
+ * at the cell's left, vertically centred in the strip, whether or not the
887
+ * floor opened a gap. The label clears it. Omitted when the wave has no
888
+ * date floor, no `cell`, or the cell is too narrow to host it.
889
+ */
890
+ inlineDatePin?: InlineDatePin;
891
+ /**
892
+ * The footnote superscripts when `footnotesShown` and the wave has a
893
+ * `cell`: `rightX` is the last superscript's right edge (they walk left
894
+ * by `ITEM_FOOTNOTE_INDICATOR_STEP_PX`, end-anchored) and `halo` their
895
+ * backing box. Omitted otherwise.
896
+ */
897
+ superscripts?: {
898
+ rightX: number;
899
+ halo: BoundingBox;
900
+ };
901
+ /**
902
+ * Which step of the fit chain won: the title, the id, the title
903
+ * ellipsized to 3 or more characters plus "…", the 1-based `#k`, or
904
+ * no label. Always `none` for an empty wave (it has no cell).
905
+ */
906
+ labelKind: 'title' | 'id' | 'ellipsis' | 'ordinal' | 'none';
907
+ /**
908
+ * Centre of the visible part of the span (clipped to the timeline);
909
+ * `startX` for an empty wave, which is not drawn.
910
+ */
911
+ labelX: number;
912
+ /**
913
+ * The cell's hover text, e.g. `Launch · 2026-02-02 – 2026-02-23 · held
914
+ * by i2` (end exclusive). An empty wave reads `title · date · no items`.
915
+ */
916
+ tooltip: string;
917
+ /**
918
+ * True when `footnoteIndicators` are drawn right-aligned in the cell;
919
+ * false when there are none or they did not fit (they are then not
920
+ * drawn; the footnote panel still lists the footnote).
921
+ */
922
+ footnotesShown: boolean;
923
+ /**
924
+ * The floor reference (`fy-budget`, `2026-02-02`) centred in the gap
925
+ * this wave's start floor opened before it (`S_k > E_{k-1}`, k >= 2),
926
+ * when it fits; drawn in muted italics. `halo` is its backing box in the
927
+ * panel's fill, sized from the text's estimated width at 10 px (the one
928
+ * its fit was tested at). Omitted otherwise.
929
+ */
930
+ gapLabel?: {
931
+ text: string;
932
+ x: number;
933
+ halo: BoundingBox;
934
+ };
935
+ }
936
+ /** A wave's resolved colours (specs/waves.md §9.4). */
937
+ export interface PositionedWaveStyle {
938
+ /** The style's `bg`: the column tint and the strip-cell overlay. Omitted when unset. */
939
+ tint?: string;
940
+ /** The cell's base fill by `visibleOrdinal` parity. */
941
+ stripFill: string;
942
+ /** Label colour: the style's `text`, else `wave.labelText`, else a dark or light pick at 4.5:1. */
943
+ text: string;
944
+ /** Boundary colour: the style's `fg`, else `wave.boundary`. */
945
+ boundary: string;
946
+ /** `4 2` for `border:dashed`, `1 2` for `dotted`, null for solid. */
947
+ boundaryDash: string | null;
948
+ }
949
+ /**
950
+ * One wave boundary line (specs/waves.md §9.2), at a distinct x in
951
+ * `{S_k} ∪ {E_k}` of the non-empty waves other than the origin. It runs
952
+ * from the top of the strip down to `swimlaneBottomY`.
953
+ */
954
+ export interface PositionedWaveBoundary {
955
+ x: number;
956
+ topY: number;
957
+ bottomY: number;
958
+ stroke: string;
959
+ dash: string | null;
960
+ }
961
+ /**
962
+ * A boundary drawn over a background bar whose visual extent strictly
963
+ * contains it (specs/waves.md §9.3), from the bar's top to its bottom.
964
+ */
965
+ export interface PositionedWaveCrossing {
966
+ x: number;
967
+ topY: number;
968
+ bottomY: number;
969
+ stroke: string;
970
+ }
971
+ /** One legend entry (specs/waves.md §9.5). */
972
+ export interface WaveLegendEntry {
973
+ /** The hatch swatch for background work, the legend's only entry. */
974
+ kind: 'background';
975
+ /** The entry's full text. */
976
+ text: string;
977
+ /** The swatch box: a hatched bar. */
978
+ swatch: BoundingBox;
979
+ /** The swatch's hatch kind, a default item bar's fill. */
980
+ hatch: WaveHatchKind;
981
+ /** The text, one run on the swatch's line. `y` is the text baseline. */
982
+ runs: Array<{
983
+ text: string;
984
+ x: number;
985
+ y: number;
986
+ }>;
987
+ }
988
+ /** The wave legend below the chart (specs/waves.md §9.5). */
989
+ export interface PositionedWaveLegend {
990
+ box: BoundingBox;
991
+ entries: WaveLegendEntry[];
492
992
  }
493
993
  export interface PositionedRoadmap {
494
994
  width: number;
@@ -512,5 +1012,22 @@ export interface PositionedRoadmap {
512
1012
  footnotes: PositionedFootnoteArea;
513
1013
  includes: PositionedIncludeRegion[];
514
1014
  chartBox: BoundingBox;
1015
+ /**
1016
+ * The wave barrier driver's result (specs/waves.md §8.7): the passes it
1017
+ * ran and whether it hit the `n + 1` cap (NL.W1002, invalid input).
1018
+ * Present only when the roadmap declares waves.
1019
+ */
1020
+ waveSolve?: {
1021
+ passes: number;
1022
+ capped: boolean;
1023
+ };
1024
+ /** The waves in declaration order; present only when the roadmap declares waves. */
1025
+ waves?: PositionedWave[];
1026
+ /** Wave boundary lines, left to right; omitted when there are none. */
1027
+ waveBoundaries?: PositionedWaveBoundary[];
1028
+ /** Crossings over the main lanes' background bars; omitted when there are none. */
1029
+ waveCrossings?: PositionedWaveCrossing[];
1030
+ /** The wave legend; present only when one of its triggers holds (§9.5). */
1031
+ waveLegend?: PositionedWaveLegend;
515
1032
  }
516
1033
  //# sourceMappingURL=types.d.ts.map