@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
@@ -1,12 +1,10 @@
1
1
  import type { IntrinsicSize, MeasureContext, PlaceContext, Point, Renderable } from '../renderable.js';
2
- import type { BoundingBox } from '../types.js';
3
- export interface ItemNodeInput {
4
- id: string;
2
+ import type { BoundingBox, PositionedItem } from '../types.js';
3
+ /** What the caption fit needs to know about a bar. */
4
+ export interface ItemCaptionInput {
5
5
  title: string;
6
- /** Logical left x of the column the bar lives in. */
7
- logicalLeftX: number;
8
- /** Logical right x of the column the bar lives in. */
9
- logicalRightX: number;
6
+ /** Width of the visible bar box (the logical width less the insets). */
7
+ visualWidth: number;
10
8
  /** Caption text shown under the title (e.g. "1w - 50% remaining"). */
11
9
  metaText?: string;
12
10
  /**
@@ -27,6 +25,44 @@ export interface ItemNodeInput {
27
25
  * collide with the icon.
28
26
  */
29
27
  hasLinkIcon?: boolean;
28
+ /**
29
+ * True when the item carries an inline `after:DATE`, which paints a
30
+ * calendar glyph in the bar's upper-left (right of the link tile
31
+ * when there is one). Caption text indents past the glyph so the
32
+ * title doesn't run under it. The glyph spills out of a bar narrower
33
+ * than `MIN_BAR_WIDTH_FOR_INLINE_DATE_PX`; the fit checks the bar
34
+ * width and reserves nothing in that case.
35
+ */
36
+ hasAfterGlyph?: boolean;
37
+ /**
38
+ * Space (px) the title's FIRST line leaves free at the bar's right
39
+ * edge, so it clears the status dot, footnote digits and `before:`
40
+ * glyph in the upper-right. Layout computes it with
41
+ * `itemTitleFirstLineRightReservePx` once it knows the item's
42
+ * footnotes and `before:` date. Defaults to the status-dot-only
43
+ * reserve for the bar width, because the dot is always present.
44
+ */
45
+ titleFirstLineRightReservePx?: number;
46
+ }
47
+ /** The caption's left indent inside the bar and its fit decision. */
48
+ export interface ItemCaptionMeasure {
49
+ /** Indent (px) from the bar's left edge to an in-bar caption. */
50
+ leftInset: number;
51
+ fit: ItemCaptionFit;
52
+ }
53
+ /**
54
+ * The part of an item's measure (`ItemMeasure`, `item-measure.ts`) that
55
+ * `ItemNode` needs to report its size and place its box.
56
+ */
57
+ export interface ItemNodeGeometry {
58
+ id: string;
59
+ /** Logical width: the item's span in time. */
60
+ naturalWidth: number;
61
+ /** Width of the visible bar box. */
62
+ visualWidth: number;
63
+ caption: ItemCaptionMeasure;
64
+ /** Growth over the band height (a wrapped title, a chip column); 0 for none. */
65
+ barExtra: number;
30
66
  }
31
67
  export interface PlacedItemGeometry {
32
68
  id: string;
@@ -40,10 +76,127 @@ export interface PlacedItemGeometry {
40
76
  textX: number;
41
77
  /** True when text spills past the bar's right edge. */
42
78
  textSpills: boolean;
79
+ /**
80
+ * The title as it should be painted, one entry per line. Always has
81
+ * at least one entry. Exactly two entries (never more than
82
+ * `ITEM_CAPTION_TITLE_MAX_LINES`) when the title auto-wrapped inside
83
+ * the bar; the author's own lines when the title has explicit breaks
84
+ * (any count, in-bar or spilled); otherwise `[title]`, including
85
+ * when a break-free title spills to the right.
86
+ */
87
+ titleLines: string[];
88
+ }
89
+ /**
90
+ * Estimated width (px) of an item's whole meta line: `metaText` plus the
91
+ * trailing capacity suffix (`trailingWidth`, 0 when there is none). Zero
92
+ * when the item has no meta line. `measureItemCaption` feeds it to
93
+ * `fitItemCaption`.
94
+ */
95
+ export declare function estimateItemMetaWidth(metaText: string | undefined, trailingWidth: number): number;
96
+ /**
97
+ * The seam a bar gives up on each side, from inside its dates: `ITEM_SEAM_PX`,
98
+ * shrunk for a bar too short to keep both seams and the `MIN_ITEM_WIDTH`
99
+ * floor, so the floor stays centred in its dates.
100
+ */
101
+ export declare function itemBarInsetPx(logicalWidth: number): number;
102
+ /**
103
+ * The visible bar width for a logical width: the span less a seam on each
104
+ * side, never under `MIN_ITEM_WIDTH` (specs/true-width-layout.md §3.1).
105
+ */
106
+ export declare function itemVisualWidth(logicalWidth: number): number;
107
+ export interface ItemCaptionFit {
108
+ /** True when the caption must render to the right of the bar. */
109
+ textSpills: boolean;
110
+ /** Title lines to paint; see `PlacedItemGeometry.titleLines`. */
111
+ titleLines: string[];
43
112
  }
113
+ /**
114
+ * The lines of a title that contains an explicit line break, or
115
+ * `undefined` for a title with none (the common case, left untouched).
116
+ *
117
+ * `\r\n` and a lone `\r` count as `\n`, each line is trimmed, and
118
+ * leading and trailing empty lines are dropped. Interior empty lines
119
+ * stay as blank lines. A title that is only breaks and whitespace gives
120
+ * `[]`; one that has a single line left after trimming (`"Plan\n"`)
121
+ * gives one line, and callers then treat it as an ordinary single-line
122
+ * title: a break at either end cannot separate anything.
123
+ *
124
+ * Langium's string converter has already turned the source escape `\n`
125
+ * into a real newline and `\\n` into the two characters `\` `n`, so
126
+ * only the former reaches here as a break.
127
+ */
128
+ export declare function titleBreakLines(title: string): string[] | undefined;
129
+ /**
130
+ * Decide how an item's caption sits relative to its bar: one line
131
+ * in-bar, word-wrapped in-bar, or spilled to the right. This is the
132
+ * single source of truth for the decision; `measureItemCaption` calls it,
133
+ * and the row track and `sequenceItem` share that one measure, so the
134
+ * reserved row and the placed bar agree.
135
+ *
136
+ * `metaWidth` is the full estimated width of the meta line (text plus
137
+ * any trailing capacity suffix), or 0 when the item has no meta line.
138
+ * A meta line is never wrapped, so one that is wider than `innerWidth`
139
+ * forces a spill even when the title alone would wrap.
140
+ *
141
+ * `firstLineWidth` (default `innerWidth`) is the budget for the title's
142
+ * first line alone, narrower than `innerWidth` by the top-right
143
+ * decoration cluster. It governs both the single-line fit check and
144
+ * line 1 of a wrapped title; later lines and the meta line use
145
+ * `innerWidth`.
146
+ *
147
+ * `firstLineHardWidth` (default `firstLineWidth`) is the widest line 1 may
148
+ * be: it also uses the top-right decoration's `ITEM_DECORATION_SPILL_GAP_PX`
149
+ * clearance, up to that cluster's own left edge. It is a fallback, tried
150
+ * only for a wrap or explicit break that would otherwise spill, so a caption
151
+ * that fits with the gap never moves; it lets a first word that misses
152
+ * `firstLineWidth` by a hair wrap instead of spilling.
153
+ *
154
+ * Words never break mid-word: a single word wider than its line's
155
+ * budget, or a title that needs more than `ITEM_CAPTION_TITLE_MAX_LINES`
156
+ * lines, spills.
157
+ *
158
+ * A title with an explicit line break (see `titleBreakLines`) skips all
159
+ * of the above: its lines are authoritative and are returned as
160
+ * `titleLines` whether the caption stays in-bar or spills.
161
+ */
162
+ export declare function fitItemCaption(rawTitle: string, innerWidth: number, metaWidth: number, firstLineWidth?: number, firstLineHardWidth?: number): ItemCaptionFit;
163
+ /**
164
+ * The title lines an item finally paints. `fit` is the caption-fit
165
+ * decision; `forcedSpill` is true when something outside it pushes the
166
+ * caption out of the bar anyway (a narrow-bar link icon, `iconSpills`).
167
+ * `measureItem` calls it; the line count sets the bar's growth.
168
+ *
169
+ * - Explicit breaks keep the author's lines, in-bar or spilled.
170
+ * - An auto-wrap (two lines) survives only while the caption stays
171
+ * in-bar; a spilled break-free title is one line.
172
+ * - Otherwise a single line: the title, minus any stray break at
173
+ * either end.
174
+ */
175
+ export declare function resolveCaptionTitleLines(title: string, fit: ItemCaptionFit, forcedSpill: boolean): string[];
176
+ /**
177
+ * Fit an item's caption to its bar: the left indent past the link tile
178
+ * and the `after:` glyph, the inner and first-line widths, and the
179
+ * `fitItemCaption` decision on them.
180
+ */
181
+ export declare function measureItemCaption(input: ItemCaptionInput): ItemCaptionMeasure;
182
+ /**
183
+ * Optional observer of every `ItemNode` that `sequenceItem` places, with
184
+ * the context it was placed in and the item it became. Tests set it to
185
+ * check a node's measure against the item's final box; layout never does.
186
+ */
187
+ export type ItemNodeTrace = (node: ItemNode, ctx: PlaceContext, item: PositionedItem) => void;
188
+ /** Install (or, with `undefined`, remove) the `ItemNodeTrace`. */
189
+ export declare function setItemNodeTrace(trace: ItemNodeTrace | undefined): void;
190
+ /** Report a placed node to the `ItemNodeTrace`, when one is installed. */
191
+ export declare function traceItemNode(node: ItemNode, ctx: PlaceContext, item: PositionedItem): void;
192
+ /**
193
+ * One item bar, built from its measure. `measure` reports the logical
194
+ * width and the grown height (`bandwidth + barExtra`), and `place`
195
+ * returns the box at that height, so no caller patches it afterwards.
196
+ */
44
197
  export declare class ItemNode implements Renderable<PlacedItemGeometry> {
45
- readonly input: ItemNodeInput;
46
- constructor(input: ItemNodeInput);
198
+ readonly geometry: ItemNodeGeometry;
199
+ constructor(geometry: ItemNodeGeometry);
47
200
  get id(): string;
48
201
  measure(ctx: MeasureContext): IntrinsicSize;
49
202
  place(origin: Point, ctx: PlaceContext): PlacedItemGeometry;
@@ -1 +1 @@
1
- {"version":3,"file":"item-node.d.ts","sourceRoot":"","sources":["../../src/nodes/item-node.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACR,aAAa,EACb,cAAc,EACd,YAAY,EACZ,KAAK,EACL,UAAU,EACb,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAqB/C,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,WAAW,CAAC;IACjB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAC;CACvB;AAWD,qBAAa,QAAS,YAAW,UAAU,CAAC,kBAAkB,CAAC;aAC/B,KAAK,EAAE,aAAa;IAAhD,YAA4B,KAAK,EAAE,aAAa,EAAI;IAEpD,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,aAAa,CAS1C;IAED,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,GAAG,kBAAkB,CAgD1D;CACJ"}
1
+ {"version":3,"file":"item-node.d.ts","sourceRoot":"","sources":["../../src/nodes/item-node.ts"],"names":[],"mappings":"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"}
@@ -1,108 +1,295 @@
1
- // ItemNode — first Renderable entity in the m2.5c port. Owns the
2
- // geometry of a single item bar: its visual box (insets + height) and
3
- // its caption x (inside vs. spilled past the bar).
1
+ // ItemNode — the Renderable for a single item bar: its visual box
2
+ // (insets + height) and its caption x (inside vs. spilled past the bar).
4
3
  //
5
- // Constructed from already-resolved inputs (start/end x, status,
6
- // remaining, meta text) so this node stays small and pure. The
7
- // dependency-resolution logic in layout.ts (after/before chains,
8
- // cursor.x, footnote indexing) remains where it is for now; m2.5c's
9
- // remaining work is to migrate the rest into sibling node files.
4
+ // Built from the item's measure (`measureItem`, `item-measure.ts`), which
5
+ // has already resolved the width, the caption fit and the bar's growth,
6
+ // so this node stays small and pure. The start resolution (`after:`
7
+ // chains, pins, the wave floor) and the `before:` caps stay in
8
+ // `sequenceItem`.
10
9
  //
11
- // `measure(ctx)` returns the bar's intrinsic size. `place(origin,
12
- // ctx)` returns a `PositionedItem`-shaped fragment with the box, row,
13
- // and `textX`. The shape is byte-stable with the legacy sequenceItem
14
- // arithmetic when fed the same inputs.
15
- import { ITEM_LINK_ICON_INSET_PX, ITEM_LINK_ICON_TILE_SIZE_PX } from '../item-bar-geometry.js';
16
- import { ITEM_INSET_PX, MIN_ITEM_WIDTH } from '../themes/shared.js';
10
+ // `measure(ctx)` returns the bar's intrinsic size: the logical width and
11
+ // the band height plus the growth a wrapped title or a chip column adds.
12
+ // `place(origin, ctx)` returns a `PositionedItem`-shaped fragment with the
13
+ // box at that grown height, `textX`, and the title lines to paint.
14
+ //
15
+ // Caption fit decision (`fitItemCaption`), in order:
16
+ // 1. Title fits one line AND the meta line fits: in-bar, one line.
17
+ // 2. Otherwise, if the meta line fits and a greedy whitespace
18
+ // word-wrap of the title gives at most
19
+ // `ITEM_CAPTION_TITLE_MAX_LINES` lines (>= 2), each within the
20
+ // inner width: in-bar, wrapped.
21
+ // 3. Otherwise: spill to the right of the bar as a single line.
22
+ //
23
+ // The caption's left edge (`itemCaptionInsetX`) clears the link tile and
24
+ // the `after:` inline-date glyph in the bar's upper-left. The inset
25
+ // applies to EVERY caption line, so the left edge stays straight.
26
+ //
27
+ // The FIRST title line has a narrower budget than the rest: it shares
28
+ // the bar's upper-right with the status dot, footnote digits and the
29
+ // `before:` glyph, so it stops short of that cluster
30
+ // (`itemTitleFirstLineRightReservePx`). Line 2+ and the meta line sit
31
+ // below the cluster and keep the full inner width.
32
+ //
33
+ // Explicit breaks (lolay/nowline#60): a newline in the title is a hard
34
+ // line break and the author's lines are authoritative. No auto-wrap
35
+ // runs on them and the two-line cap does not apply. The caption stays
36
+ // in-bar when line 1 fits the first-line width, every other line fits
37
+ // the inner width and the meta line fits; otherwise it spills right as
38
+ // a multi-line block with its breaks preserved.
39
+ import { ITEM_CAPTION_TITLE_MAX_LINES, ITEM_DECORATION_SPILL_GAP_PX, itemCaptionInsetX, itemTitleFirstLineRightReservePx, } from '../item-bar-geometry.js';
40
+ import { estimateTextWidth, wrapText } from '../text-measure.js';
41
+ import { ITEM_SEAM_PX, MIN_ITEM_WIDTH } from '../themes/shared.js';
17
42
  /**
18
- * Inner padding applied on each side of the title text — the bar's
19
- * inner-padded text area is `box.width - 2 * TEXT_INSET_PX` wide.
20
- * Text spills past the bar when either the title or the meta line
43
+ * Inner padding applied on the RIGHT of the title text (the left inset
44
+ * comes from `itemCaptionInsetX`, which adds the link-icon column and
45
+ * the `after:` glyph column when present) — the bar's inner-padded text area is
46
+ * `box.width - itemCaptionInsetX(..) - TEXT_INSET_PX` wide. Text wraps
47
+ * or spills past the bar when either the title or the meta line
21
48
  * exceeds that area.
22
49
  */
23
50
  const TEXT_INSET_PX = 12;
24
51
  /**
25
52
  * Gap (px) between the bar's right edge and overflow text. Smaller
26
- * than `TEXT_INSET_PX` so the text reads as belonging to this bar —
27
- * adjacent bars are at least `2 * ITEM_INSET_PX = 12` away, so the
28
- * text still has a clear visual home.
53
+ * than `TEXT_INSET_PX` so the text reads as belonging to this bar.
29
54
  */
30
55
  const TEXT_OUTSIDE_GAP_PX = 4;
31
56
  const TITLE_FONT_SIZE_PX = 13;
32
57
  const META_FONT_SIZE_PX = 11;
33
58
  /**
34
- * Approx. rendered width of `text` at `fontSizePx`. Matches the legacy
35
- * `sequenceItem` heuristic (intentionally pessimistic at ~0.58 em/char so
36
- * borderline-fitting captions trigger spill rather than clip).
59
+ * Estimated width (px) of an item's whole meta line: `metaText` plus the
60
+ * trailing capacity suffix (`trailingWidth`, 0 when there is none). Zero
61
+ * when the item has no meta line. `measureItemCaption` feeds it to
62
+ * `fitItemCaption`.
63
+ */
64
+ export function estimateItemMetaWidth(metaText, trailingWidth) {
65
+ const metaTextWidth = metaText ? estimateTextWidth(metaText, META_FONT_SIZE_PX) : 0;
66
+ return metaTextWidth + trailingWidth;
67
+ }
68
+ /**
69
+ * The seam a bar gives up on each side, from inside its dates: `ITEM_SEAM_PX`,
70
+ * shrunk for a bar too short to keep both seams and the `MIN_ITEM_WIDTH`
71
+ * floor, so the floor stays centred in its dates.
72
+ */
73
+ export function itemBarInsetPx(logicalWidth) {
74
+ return Math.max(0, Math.min(ITEM_SEAM_PX, (logicalWidth - MIN_ITEM_WIDTH) / 2));
75
+ }
76
+ /**
77
+ * The visible bar width for a logical width: the span less a seam on each
78
+ * side, never under `MIN_ITEM_WIDTH` (specs/true-width-layout.md §3.1).
79
+ */
80
+ export function itemVisualWidth(logicalWidth) {
81
+ return Math.max(MIN_ITEM_WIDTH, logicalWidth - 2 * itemBarInsetPx(logicalWidth));
82
+ }
83
+ /**
84
+ * The lines of a title that contains an explicit line break, or
85
+ * `undefined` for a title with none (the common case, left untouched).
86
+ *
87
+ * `\r\n` and a lone `\r` count as `\n`, each line is trimmed, and
88
+ * leading and trailing empty lines are dropped. Interior empty lines
89
+ * stay as blank lines. A title that is only breaks and whitespace gives
90
+ * `[]`; one that has a single line left after trimming (`"Plan\n"`)
91
+ * gives one line, and callers then treat it as an ordinary single-line
92
+ * title: a break at either end cannot separate anything.
93
+ *
94
+ * Langium's string converter has already turned the source escape `\n`
95
+ * into a real newline and `\\n` into the two characters `\` `n`, so
96
+ * only the former reaches here as a break.
37
97
  */
38
- function estimateTextWidth(text, fontSizePx) {
39
- return text.length * fontSizePx * 0.58;
98
+ export function titleBreakLines(title) {
99
+ if (!/[\r\n]/.test(title))
100
+ return undefined;
101
+ const lines = title
102
+ .replace(/\r\n?/g, '\n')
103
+ .split('\n')
104
+ .map((line) => line.trim());
105
+ let start = 0;
106
+ let end = lines.length;
107
+ while (start < end && lines[start] === '')
108
+ start += 1;
109
+ while (end > start && lines[end - 1] === '')
110
+ end -= 1;
111
+ return lines.slice(start, end);
40
112
  }
113
+ /**
114
+ * Decide how an item's caption sits relative to its bar: one line
115
+ * in-bar, word-wrapped in-bar, or spilled to the right. This is the
116
+ * single source of truth for the decision; `measureItemCaption` calls it,
117
+ * and the row track and `sequenceItem` share that one measure, so the
118
+ * reserved row and the placed bar agree.
119
+ *
120
+ * `metaWidth` is the full estimated width of the meta line (text plus
121
+ * any trailing capacity suffix), or 0 when the item has no meta line.
122
+ * A meta line is never wrapped, so one that is wider than `innerWidth`
123
+ * forces a spill even when the title alone would wrap.
124
+ *
125
+ * `firstLineWidth` (default `innerWidth`) is the budget for the title's
126
+ * first line alone, narrower than `innerWidth` by the top-right
127
+ * decoration cluster. It governs both the single-line fit check and
128
+ * line 1 of a wrapped title; later lines and the meta line use
129
+ * `innerWidth`.
130
+ *
131
+ * `firstLineHardWidth` (default `firstLineWidth`) is the widest line 1 may
132
+ * be: it also uses the top-right decoration's `ITEM_DECORATION_SPILL_GAP_PX`
133
+ * clearance, up to that cluster's own left edge. It is a fallback, tried
134
+ * only for a wrap or explicit break that would otherwise spill, so a caption
135
+ * that fits with the gap never moves; it lets a first word that misses
136
+ * `firstLineWidth` by a hair wrap instead of spilling.
137
+ *
138
+ * Words never break mid-word: a single word wider than its line's
139
+ * budget, or a title that needs more than `ITEM_CAPTION_TITLE_MAX_LINES`
140
+ * lines, spills.
141
+ *
142
+ * A title with an explicit line break (see `titleBreakLines`) skips all
143
+ * of the above: its lines are authoritative and are returned as
144
+ * `titleLines` whether the caption stays in-bar or spills.
145
+ */
146
+ export function fitItemCaption(rawTitle, innerWidth, metaWidth, firstLineWidth = innerWidth, firstLineHardWidth = firstLineWidth) {
147
+ let title = rawTitle;
148
+ const broken = titleBreakLines(rawTitle);
149
+ if (broken) {
150
+ if (broken.length >= 2) {
151
+ // Explicit breaks: the author's lines are authoritative, so no
152
+ // auto-wrap and no line cap. In-bar only when line 1 fits the
153
+ // first-line width, every other line fits the inner width and
154
+ // the meta line fits; otherwise the whole block spills right.
155
+ const fits = metaWidth <= innerWidth &&
156
+ broken.every((line, n) => estimateTextWidth(line, TITLE_FONT_SIZE_PX) <=
157
+ (n === 0 ? firstLineHardWidth : innerWidth));
158
+ return { textSpills: !fits, titleLines: broken };
159
+ }
160
+ // Zero or one line left after trimming: an ordinary title, now
161
+ // free of its stray break.
162
+ title = broken[0] ?? '';
163
+ }
164
+ const titleOverflows = title.length > 0 && estimateTextWidth(title, TITLE_FONT_SIZE_PX) > firstLineWidth;
165
+ const metaOverflows = metaWidth > innerWidth;
166
+ if (!titleOverflows && !metaOverflows) {
167
+ return { textSpills: false, titleLines: [title] };
168
+ }
169
+ if (titleOverflows && !metaOverflows) {
170
+ // Line 1 first keeps the dot's clearance; only when that spills does
171
+ // it try the hard limit.
172
+ for (const line1Width of [firstLineWidth, firstLineHardWidth]) {
173
+ const lines = wrapText(title, innerWidth, TITLE_FONT_SIZE_PX, line1Width);
174
+ // `lines.length >= 2` keeps single-line behavior byte-identical: a
175
+ // title that only "overflows" because of repeated whitespace in
176
+ // the raw string (the estimate counts every space) normalizes to
177
+ // one line, and that case still spills exactly as it always has.
178
+ if (lines.length >= 2 &&
179
+ lines.length <= ITEM_CAPTION_TITLE_MAX_LINES &&
180
+ lines.every((line, n) => estimateTextWidth(line, TITLE_FONT_SIZE_PX) <=
181
+ (n === 0 ? line1Width : innerWidth))) {
182
+ return { textSpills: false, titleLines: lines };
183
+ }
184
+ }
185
+ }
186
+ return { textSpills: true, titleLines: [title] };
187
+ }
188
+ /**
189
+ * The title lines an item finally paints. `fit` is the caption-fit
190
+ * decision; `forcedSpill` is true when something outside it pushes the
191
+ * caption out of the bar anyway (a narrow-bar link icon, `iconSpills`).
192
+ * `measureItem` calls it; the line count sets the bar's growth.
193
+ *
194
+ * - Explicit breaks keep the author's lines, in-bar or spilled.
195
+ * - An auto-wrap (two lines) survives only while the caption stays
196
+ * in-bar; a spilled break-free title is one line.
197
+ * - Otherwise a single line: the title, minus any stray break at
198
+ * either end.
199
+ */
200
+ export function resolveCaptionTitleLines(title, fit, forcedSpill) {
201
+ const broken = titleBreakLines(title);
202
+ if (broken && broken.length >= 2)
203
+ return broken;
204
+ if (!fit.textSpills && !forcedSpill && fit.titleLines.length >= 2)
205
+ return fit.titleLines;
206
+ return [broken ? (broken[0] ?? '') : title];
207
+ }
208
+ /**
209
+ * Fit an item's caption to its bar: the left indent past the link tile
210
+ * and the `after:` glyph, the inner and first-line widths, and the
211
+ * `fitItemCaption` decision on them.
212
+ */
213
+ export function measureItemCaption(input) {
214
+ const { visualWidth } = input;
215
+ // The link icon and the `after:` glyph (when present) live in the
216
+ // bar's upper-left and share the title's vertical band. The
217
+ // caption indents past them so the title doesn't render on top.
218
+ const leftInset = itemCaptionInsetX(!!input.hasLinkIcon, input.hasAfterGlyph ? { barWidth: visualWidth } : undefined);
219
+ const innerWidth = Math.max(0, visualWidth - leftInset - TEXT_INSET_PX);
220
+ // Trailing decoration (capacity suffix) renders to the right of
221
+ // metaText. When metaText is empty the suffix sits at the
222
+ // caption's leading edge, so its width is the entire meta-line
223
+ // budget; when both exist the suffix needs a small separator gap
224
+ // (rendered via `<tspan dx>` later) included in trailingWidth.
225
+ const metaWidth = estimateItemMetaWidth(input.metaText, input.metaTrailingWidth ?? 0);
226
+ const firstLineReserve = input.titleFirstLineRightReservePx ??
227
+ itemTitleFirstLineRightReservePx({
228
+ barWidth: visualWidth,
229
+ footnoteLabels: [],
230
+ hasBeforeGlyph: false,
231
+ });
232
+ const firstLineWidth = Math.max(0, visualWidth - leftInset - firstLineReserve);
233
+ // The same line without the cluster's clearance gap: its left edge is the limit.
234
+ const firstLineHardWidth = Math.max(firstLineWidth, visualWidth -
235
+ leftInset -
236
+ Math.max(TEXT_INSET_PX, firstLineReserve - ITEM_DECORATION_SPILL_GAP_PX));
237
+ return {
238
+ leftInset,
239
+ fit: fitItemCaption(input.title, innerWidth, metaWidth, firstLineWidth, firstLineHardWidth),
240
+ };
241
+ }
242
+ let itemNodeTrace;
243
+ /** Install (or, with `undefined`, remove) the `ItemNodeTrace`. */
244
+ export function setItemNodeTrace(trace) {
245
+ itemNodeTrace = trace;
246
+ }
247
+ /** Report a placed node to the `ItemNodeTrace`, when one is installed. */
248
+ export function traceItemNode(node, ctx, item) {
249
+ itemNodeTrace?.(node, ctx, item);
250
+ }
251
+ /**
252
+ * One item bar, built from its measure. `measure` reports the logical
253
+ * width and the grown height (`bandwidth + barExtra`), and `place`
254
+ * returns the box at that height, so no caller patches it afterwards.
255
+ */
41
256
  export class ItemNode {
42
- input;
43
- constructor(input) {
44
- this.input = input;
257
+ geometry;
258
+ constructor(geometry) {
259
+ this.geometry = geometry;
45
260
  }
46
261
  get id() {
47
- return this.input.id;
262
+ return this.geometry.id;
48
263
  }
49
264
  measure(ctx) {
50
- const naturalWidth = Math.max(MIN_ITEM_WIDTH, this.input.logicalRightX - this.input.logicalLeftX);
51
265
  return {
52
- width: naturalWidth,
53
- height: ctx.bands.bandwidth(),
266
+ width: this.geometry.naturalWidth,
267
+ height: ctx.bands.bandwidth() + this.geometry.barExtra,
54
268
  };
55
269
  }
56
270
  place(origin, ctx) {
57
- const intrinsic = this.measure(ctx);
58
- const visualWidth = Math.max(MIN_ITEM_WIDTH, intrinsic.width - 2 * ITEM_INSET_PX);
59
- const boxX = origin.x + ITEM_INSET_PX;
271
+ const { naturalWidth, visualWidth, caption, barExtra } = this.geometry;
272
+ const bandwidth = ctx.bands.bandwidth();
273
+ const boxX = origin.x + itemBarInsetPx(naturalWidth);
60
274
  const box = {
61
275
  x: boxX,
62
276
  y: origin.y,
63
277
  width: visualWidth,
64
- height: intrinsic.height,
278
+ // The bar grows downward to enclose a wrapped title or a chip
279
+ // column; an ungrown bar is exactly the band height.
280
+ height: barExtra > 0 ? bandwidth + barExtra : bandwidth,
65
281
  };
66
- // The link icon (when present) lives in the bar's upper-left
67
- // and shares the title's vertical band. The caption indents
68
- // past the icon so the title doesn't render on top of it.
69
- const linkColumn = this.input.hasLinkIcon
70
- ? ITEM_LINK_ICON_INSET_PX +
71
- ITEM_LINK_ICON_TILE_SIZE_PX +
72
- LINK_ICON_TO_CAPTION_GAP_PX -
73
- TEXT_INSET_PX
74
- : 0;
75
- const captionLeftInset = TEXT_INSET_PX + Math.max(0, linkColumn);
76
- const innerWidth = Math.max(0, visualWidth - captionLeftInset - TEXT_INSET_PX);
77
- const titleStr = this.input.title;
78
- const titleWidth = titleStr ? estimateTextWidth(titleStr, TITLE_FONT_SIZE_PX) : 0;
79
- const metaTextWidth = this.input.metaText
80
- ? estimateTextWidth(this.input.metaText, META_FONT_SIZE_PX)
81
- : 0;
82
- const trailingWidth = this.input.metaTrailingWidth ?? 0;
83
- // Trailing decoration (capacity suffix) renders to the right of
84
- // metaText. When metaText is empty the suffix sits at the
85
- // caption's leading edge, so its width is the entire meta-line
86
- // budget; when both exist the suffix needs a small separator gap
87
- // (rendered via `<tspan dx>` later) included in trailingWidth.
88
- const metaWidth = metaTextWidth + trailingWidth;
89
- const hasMetaContent = this.input.metaText !== undefined || trailingWidth > 0;
90
- const textSpills = (titleStr.length > 0 && titleWidth > innerWidth) ||
91
- (hasMetaContent && metaWidth > innerWidth);
282
+ const { textSpills, titleLines } = caption.fit;
92
283
  const textX = textSpills
93
284
  ? boxX + visualWidth + TEXT_OUTSIDE_GAP_PX
94
- : boxX + captionLeftInset;
285
+ : boxX + caption.leftInset;
95
286
  return {
96
- id: this.input.id,
287
+ id: this.geometry.id,
97
288
  box,
98
289
  textX,
99
290
  textSpills,
291
+ titleLines,
100
292
  };
101
293
  }
102
294
  }
103
- /**
104
- * Horizontal gap (px) between the link-icon tile's right edge and the
105
- * start of the caption text when both render inside the bar.
106
- */
107
- const LINK_ICON_TO_CAPTION_GAP_PX = 4;
108
295
  //# sourceMappingURL=item-node.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"item-node.js","sourceRoot":"","sources":["../../src/nodes/item-node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"item-node.js","sourceRoot":"","sources":["../../src/nodes/item-node.ts"],"names":[],"mappings":"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"}