@nowline/layout 0.8.5 → 0.9.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 (339) 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/band-scale.d.ts.map +1 -1
  6. package/dist/calendar-resolver.d.ts +27 -0
  7. package/dist/calendar-resolver.d.ts.map +1 -0
  8. package/dist/calendar-resolver.js +132 -0
  9. package/dist/calendar-resolver.js.map +1 -0
  10. package/dist/calendar.d.ts +0 -19
  11. package/dist/calendar.d.ts.map +1 -1
  12. package/dist/calendar.js +4 -44
  13. package/dist/calendar.js.map +1 -1
  14. package/dist/canvas-width.d.ts +23 -0
  15. package/dist/canvas-width.d.ts.map +1 -0
  16. package/dist/canvas-width.js +26 -0
  17. package/dist/canvas-width.js.map +1 -0
  18. package/dist/capacity.d.ts +28 -0
  19. package/dist/capacity.d.ts.map +1 -1
  20. package/dist/capacity.js +64 -29
  21. package/dist/capacity.js.map +1 -1
  22. package/dist/chart-translation.d.ts +22 -0
  23. package/dist/chart-translation.d.ts.map +1 -0
  24. package/dist/chart-translation.js +83 -0
  25. package/dist/chart-translation.js.map +1 -0
  26. package/dist/container-header-geometry.d.ts +64 -0
  27. package/dist/container-header-geometry.d.ts.map +1 -0
  28. package/dist/container-header-geometry.js +89 -0
  29. package/dist/container-header-geometry.js.map +1 -0
  30. package/dist/dsl-utils.d.ts +3 -4
  31. package/dist/dsl-utils.d.ts.map +1 -1
  32. package/dist/dsl-utils.js +8 -25
  33. package/dist/dsl-utils.js.map +1 -1
  34. package/dist/edge-routing.d.ts +69 -78
  35. package/dist/edge-routing.d.ts.map +1 -1
  36. package/dist/edge-routing.js +271 -401
  37. package/dist/edge-routing.js.map +1 -1
  38. package/dist/frame-tab-geometry.d.ts +24 -14
  39. package/dist/frame-tab-geometry.d.ts.map +1 -1
  40. package/dist/frame-tab-geometry.js +69 -23
  41. package/dist/frame-tab-geometry.js.map +1 -1
  42. package/dist/header-card-geometry.d.ts +12 -0
  43. package/dist/header-card-geometry.d.ts.map +1 -1
  44. package/dist/header-card-geometry.js +14 -2
  45. package/dist/header-card-geometry.js.map +1 -1
  46. package/dist/header-logo.d.ts +28 -0
  47. package/dist/header-logo.d.ts.map +1 -0
  48. package/dist/header-logo.js +51 -0
  49. package/dist/header-logo.js.map +1 -0
  50. package/dist/i18n.d.ts +11 -0
  51. package/dist/i18n.d.ts.map +1 -1
  52. package/dist/i18n.js +11 -1
  53. package/dist/i18n.js.map +1 -1
  54. package/dist/index.d.ts +20 -8
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +17 -7
  57. package/dist/index.js.map +1 -1
  58. package/dist/inline-date-pin-geometry.d.ts +19 -11
  59. package/dist/inline-date-pin-geometry.d.ts.map +1 -1
  60. package/dist/inline-date-pin-geometry.js +45 -46
  61. package/dist/inline-date-pin-geometry.js.map +1 -1
  62. package/dist/item-bar-geometry.d.ts +192 -4
  63. package/dist/item-bar-geometry.d.ts.map +1 -1
  64. package/dist/item-bar-geometry.js +258 -5
  65. package/dist/item-bar-geometry.js.map +1 -1
  66. package/dist/item-port-geometry.d.ts +13 -0
  67. package/dist/item-port-geometry.d.ts.map +1 -0
  68. package/dist/item-port-geometry.js +63 -0
  69. package/dist/item-port-geometry.js.map +1 -0
  70. package/dist/layout-context.d.ts +115 -51
  71. package/dist/layout-context.d.ts.map +1 -1
  72. package/dist/layout-context.js +96 -5
  73. package/dist/layout-context.js.map +1 -1
  74. package/dist/layout-insights.d.ts.map +1 -1
  75. package/dist/layout-insights.js +73 -1
  76. package/dist/layout-insights.js.map +1 -1
  77. package/dist/layout.d.ts +35 -0
  78. package/dist/layout.d.ts.map +1 -1
  79. package/dist/layout.js +18 -1315
  80. package/dist/layout.js.map +1 -1
  81. package/dist/nodes/anchor-node.d.ts.map +1 -1
  82. package/dist/nodes/anchor-node.js +11 -4
  83. package/dist/nodes/anchor-node.js.map +1 -1
  84. package/dist/nodes/content-extent.d.ts +24 -0
  85. package/dist/nodes/content-extent.d.ts.map +1 -0
  86. package/dist/nodes/content-extent.js +100 -0
  87. package/dist/nodes/content-extent.js.map +1 -0
  88. package/dist/nodes/dependency-edges.d.ts +6 -0
  89. package/dist/nodes/dependency-edges.d.ts.map +1 -0
  90. package/dist/nodes/dependency-edges.js +148 -0
  91. package/dist/nodes/dependency-edges.js.map +1 -0
  92. package/dist/nodes/footnote-node.d.ts +24 -3
  93. package/dist/nodes/footnote-node.d.ts.map +1 -1
  94. package/dist/nodes/footnote-node.js +129 -25
  95. package/dist/nodes/footnote-node.js.map +1 -1
  96. package/dist/nodes/group-node.d.ts +10 -21
  97. package/dist/nodes/group-node.d.ts.map +1 -1
  98. package/dist/nodes/group-node.js +79 -154
  99. package/dist/nodes/group-node.js.map +1 -1
  100. package/dist/nodes/header-node.d.ts +56 -0
  101. package/dist/nodes/header-node.d.ts.map +1 -0
  102. package/dist/nodes/header-node.js +163 -0
  103. package/dist/nodes/header-node.js.map +1 -0
  104. package/dist/nodes/include-node.d.ts +22 -12
  105. package/dist/nodes/include-node.d.ts.map +1 -1
  106. package/dist/nodes/include-node.js +95 -62
  107. package/dist/nodes/include-node.js.map +1 -1
  108. package/dist/nodes/item-measure.d.ts +135 -0
  109. package/dist/nodes/item-measure.d.ts.map +1 -0
  110. package/dist/nodes/item-measure.js +514 -0
  111. package/dist/nodes/item-measure.js.map +1 -0
  112. package/dist/nodes/item-node.d.ts +162 -9
  113. package/dist/nodes/item-node.d.ts.map +1 -1
  114. package/dist/nodes/item-node.js +256 -69
  115. package/dist/nodes/item-node.js.map +1 -1
  116. package/dist/nodes/marker-band.d.ts +118 -0
  117. package/dist/nodes/marker-band.d.ts.map +1 -0
  118. package/dist/nodes/marker-band.js +303 -0
  119. package/dist/nodes/marker-band.js.map +1 -0
  120. package/dist/nodes/marker-geometry.js +1 -1
  121. package/dist/nodes/marker-geometry.js.map +1 -1
  122. package/dist/nodes/milestone-node.d.ts +112 -15
  123. package/dist/nodes/milestone-node.d.ts.map +1 -1
  124. package/dist/nodes/milestone-node.js +246 -95
  125. package/dist/nodes/milestone-node.js.map +1 -1
  126. package/dist/nodes/nowline-node.d.ts +8 -0
  127. package/dist/nodes/nowline-node.d.ts.map +1 -0
  128. package/dist/nodes/nowline-node.js +74 -0
  129. package/dist/nodes/nowline-node.js.map +1 -0
  130. package/dist/nodes/parallel-node.d.ts +7 -12
  131. package/dist/nodes/parallel-node.d.ts.map +1 -1
  132. package/dist/nodes/parallel-node.js +66 -32
  133. package/dist/nodes/parallel-node.js.map +1 -1
  134. package/dist/nodes/region-markers.d.ts +41 -0
  135. package/dist/nodes/region-markers.d.ts.map +1 -0
  136. package/dist/nodes/region-markers.js +130 -0
  137. package/dist/nodes/region-markers.js.map +1 -0
  138. package/dist/nodes/roadmap-node.d.ts +9 -72
  139. package/dist/nodes/roadmap-node.d.ts.map +1 -1
  140. package/dist/nodes/roadmap-node.js +38 -788
  141. package/dist/nodes/roadmap-node.js.map +1 -1
  142. package/dist/nodes/row-track.d.ts +33 -0
  143. package/dist/nodes/row-track.d.ts.map +1 -0
  144. package/dist/nodes/row-track.js +170 -0
  145. package/dist/nodes/row-track.js.map +1 -0
  146. package/dist/nodes/sequence-item.d.ts +25 -0
  147. package/dist/nodes/sequence-item.d.ts.map +1 -0
  148. package/dist/nodes/sequence-item.js +396 -0
  149. package/dist/nodes/sequence-item.js.map +1 -0
  150. package/dist/nodes/sequence-one.d.ts +5 -0
  151. package/dist/nodes/sequence-one.d.ts.map +1 -0
  152. package/dist/nodes/sequence-one.js +26 -0
  153. package/dist/nodes/sequence-one.js.map +1 -0
  154. package/dist/nodes/swimlane-node.d.ts +5 -17
  155. package/dist/nodes/swimlane-node.d.ts.map +1 -1
  156. package/dist/nodes/swimlane-node.js +62 -147
  157. package/dist/nodes/swimlane-node.js.map +1 -1
  158. package/dist/nodes/wave-node.d.ts +52 -0
  159. package/dist/nodes/wave-node.d.ts.map +1 -0
  160. package/dist/nodes/wave-node.js +483 -0
  161. package/dist/nodes/wave-node.js.map +1 -0
  162. package/dist/non-working-display.d.ts +14 -0
  163. package/dist/non-working-display.d.ts.map +1 -0
  164. package/dist/non-working-display.js +28 -0
  165. package/dist/non-working-display.js.map +1 -0
  166. package/dist/phases/date-window.d.ts +48 -0
  167. package/dist/phases/date-window.d.ts.map +1 -0
  168. package/dist/phases/date-window.js +130 -0
  169. package/dist/phases/date-window.js.map +1 -0
  170. package/dist/phases/finalize.d.ts +198 -0
  171. package/dist/phases/finalize.d.ts.map +1 -0
  172. package/dist/phases/finalize.js +1058 -0
  173. package/dist/phases/finalize.js.map +1 -0
  174. package/dist/phases/measure.d.ts +77 -0
  175. package/dist/phases/measure.d.ts.map +1 -0
  176. package/dist/phases/measure.js +222 -0
  177. package/dist/phases/measure.js.map +1 -0
  178. package/dist/phases/place.d.ts +28 -0
  179. package/dist/phases/place.d.ts.map +1 -0
  180. package/dist/phases/place.js +225 -0
  181. package/dist/phases/place.js.map +1 -0
  182. package/dist/renderable.d.ts.map +1 -1
  183. package/dist/renderable.js +23 -3
  184. package/dist/renderable.js.map +1 -1
  185. package/dist/resolve-today.d.ts +11 -1
  186. package/dist/resolve-today.d.ts.map +1 -1
  187. package/dist/resolve-today.js +26 -12
  188. package/dist/resolve-today.js.map +1 -1
  189. package/dist/row-packer.d.ts +42 -16
  190. package/dist/row-packer.d.ts.map +1 -1
  191. package/dist/row-packer.js +51 -78
  192. package/dist/row-packer.js.map +1 -1
  193. package/dist/schedule.d.ts +58 -1
  194. package/dist/schedule.d.ts.map +1 -1
  195. package/dist/schedule.js +280 -106
  196. package/dist/schedule.js.map +1 -1
  197. package/dist/start-rules.d.ts +27 -0
  198. package/dist/start-rules.d.ts.map +1 -0
  199. package/dist/start-rules.js +91 -0
  200. package/dist/start-rules.js.map +1 -0
  201. package/dist/start-terms.d.ts +23 -0
  202. package/dist/start-terms.d.ts.map +1 -0
  203. package/dist/start-terms.js +27 -0
  204. package/dist/start-terms.js.map +1 -0
  205. package/dist/status-dot.d.ts +46 -0
  206. package/dist/status-dot.d.ts.map +1 -0
  207. package/dist/status-dot.js +78 -0
  208. package/dist/status-dot.js.map +1 -0
  209. package/dist/style-resolution.d.ts.map +1 -1
  210. package/dist/style-resolution.js +23 -43
  211. package/dist/style-resolution.js.map +1 -1
  212. package/dist/text-measure.d.ts +28 -0
  213. package/dist/text-measure.d.ts.map +1 -0
  214. package/dist/text-measure.js +70 -0
  215. package/dist/text-measure.js.map +1 -0
  216. package/dist/themes/contrast.d.ts +4 -0
  217. package/dist/themes/contrast.d.ts.map +1 -0
  218. package/dist/themes/contrast.js +32 -0
  219. package/dist/themes/contrast.js.map +1 -0
  220. package/dist/themes/dark.d.ts.map +1 -1
  221. package/dist/themes/dark.js +28 -1
  222. package/dist/themes/dark.js.map +1 -1
  223. package/dist/themes/grayscale.d.ts.map +1 -1
  224. package/dist/themes/grayscale.js +28 -1
  225. package/dist/themes/grayscale.js.map +1 -1
  226. package/dist/themes/index.d.ts +4 -11
  227. package/dist/themes/index.d.ts.map +1 -1
  228. package/dist/themes/index.js +6 -4
  229. package/dist/themes/index.js.map +1 -1
  230. package/dist/themes/light.d.ts.map +1 -1
  231. package/dist/themes/light.js +28 -1
  232. package/dist/themes/light.js.map +1 -1
  233. package/dist/themes/shape.d.ts +31 -0
  234. package/dist/themes/shape.d.ts.map +1 -1
  235. package/dist/themes/shared.d.ts +44 -50
  236. package/dist/themes/shared.d.ts.map +1 -1
  237. package/dist/themes/shared.js +79 -83
  238. package/dist/themes/shared.js.map +1 -1
  239. package/dist/time-scale.d.ts +42 -6
  240. package/dist/time-scale.d.ts.map +1 -1
  241. package/dist/time-scale.js +109 -17
  242. package/dist/time-scale.js.map +1 -1
  243. package/dist/types.d.ts +528 -11
  244. package/dist/types.d.ts.map +1 -1
  245. package/dist/view-preset.d.ts +61 -6
  246. package/dist/view-preset.d.ts.map +1 -1
  247. package/dist/view-preset.js +439 -24
  248. package/dist/view-preset.js.map +1 -1
  249. package/dist/wave-barrier.d.ts +107 -0
  250. package/dist/wave-barrier.d.ts.map +1 -0
  251. package/dist/wave-barrier.js +174 -0
  252. package/dist/wave-barrier.js.map +1 -0
  253. package/dist/wave-hatch.d.ts +4 -0
  254. package/dist/wave-hatch.d.ts.map +1 -0
  255. package/dist/wave-hatch.js +21 -0
  256. package/dist/wave-hatch.js.map +1 -0
  257. package/dist/wave-layout.d.ts +99 -0
  258. package/dist/wave-layout.d.ts.map +1 -0
  259. package/dist/wave-layout.js +130 -0
  260. package/dist/wave-layout.js.map +1 -0
  261. package/dist/working-calendar.d.ts +128 -4
  262. package/dist/working-calendar.d.ts.map +1 -1
  263. package/dist/working-calendar.js +725 -51
  264. package/dist/working-calendar.js.map +1 -1
  265. package/dist/working-span.d.ts +11 -0
  266. package/dist/working-span.d.ts.map +1 -0
  267. package/dist/working-span.js +18 -0
  268. package/dist/working-span.js.map +1 -0
  269. package/package.json +7 -7
  270. package/src/axis-columns.ts +140 -0
  271. package/src/calendar-resolver.ts +161 -0
  272. package/src/calendar.ts +4 -45
  273. package/src/canvas-width.ts +36 -0
  274. package/src/capacity.ts +71 -30
  275. package/src/chart-translation.ts +88 -0
  276. package/src/container-header-geometry.ts +116 -0
  277. package/src/dsl-utils.ts +8 -26
  278. package/src/edge-routing.ts +347 -491
  279. package/src/frame-tab-geometry.ts +78 -25
  280. package/src/header-card-geometry.ts +17 -2
  281. package/src/header-logo.ts +67 -0
  282. package/src/i18n.ts +22 -1
  283. package/src/index.ts +97 -12
  284. package/src/inline-date-pin-geometry.ts +55 -58
  285. package/src/item-bar-geometry.ts +341 -5
  286. package/src/item-port-geometry.ts +69 -0
  287. package/src/layout-context.ts +210 -72
  288. package/src/layout-insights.ts +109 -2
  289. package/src/layout.ts +57 -1530
  290. package/src/nodes/anchor-node.ts +11 -4
  291. package/src/nodes/content-extent.ts +107 -0
  292. package/src/nodes/dependency-edges.ts +171 -0
  293. package/src/nodes/footnote-node.ts +171 -31
  294. package/src/nodes/group-node.ts +92 -215
  295. package/src/nodes/header-node.ts +255 -0
  296. package/src/nodes/include-node.ts +124 -110
  297. package/src/nodes/item-measure.ts +723 -0
  298. package/src/nodes/item-node.ts +358 -80
  299. package/src/nodes/marker-band.ts +406 -0
  300. package/src/nodes/marker-geometry.ts +1 -1
  301. package/src/nodes/milestone-node.ts +321 -136
  302. package/src/nodes/nowline-node.ts +87 -0
  303. package/src/nodes/parallel-node.ts +69 -39
  304. package/src/nodes/region-markers.ts +194 -0
  305. package/src/nodes/roadmap-node.ts +46 -950
  306. package/src/nodes/row-track.ts +217 -0
  307. package/src/nodes/sequence-item.ts +433 -0
  308. package/src/nodes/sequence-one.ts +40 -0
  309. package/src/nodes/swimlane-node.ts +66 -206
  310. package/src/nodes/wave-node.ts +609 -0
  311. package/src/non-working-display.ts +32 -0
  312. package/src/phases/date-window.ts +191 -0
  313. package/src/phases/finalize.ts +1303 -0
  314. package/src/phases/measure.ts +329 -0
  315. package/src/phases/place.ts +318 -0
  316. package/src/renderable.ts +23 -3
  317. package/src/resolve-today.ts +28 -25
  318. package/src/row-packer.ts +85 -84
  319. package/src/schedule.ts +362 -114
  320. package/src/start-rules.ts +113 -0
  321. package/src/start-terms.ts +38 -0
  322. package/src/status-dot.ts +81 -0
  323. package/src/style-resolution.ts +27 -57
  324. package/src/text-measure.ts +71 -0
  325. package/src/themes/contrast.ts +34 -0
  326. package/src/themes/dark.ts +28 -1
  327. package/src/themes/grayscale.ts +28 -1
  328. package/src/themes/index.ts +10 -7
  329. package/src/themes/light.ts +28 -1
  330. package/src/themes/shape.ts +38 -0
  331. package/src/themes/shared.ts +85 -93
  332. package/src/time-scale.ts +117 -19
  333. package/src/types.ts +529 -20
  334. package/src/view-preset.ts +520 -27
  335. package/src/wave-barrier.ts +242 -0
  336. package/src/wave-hatch.ts +25 -0
  337. package/src/wave-layout.ts +203 -0
  338. package/src/working-calendar.ts +875 -57
  339. package/src/working-span.ts +19 -0
@@ -18,14 +18,6 @@ export const PADDING_PX = {
18
18
  lg: 20,
19
19
  xl: 32,
20
20
  };
21
- export const HEADER_HEIGHT_PX = {
22
- none: 0,
23
- xs: 24,
24
- sm: 36,
25
- md: 56,
26
- lg: 80,
27
- xl: 112,
28
- };
29
21
  export const TEXT_SIZE_PX = {
30
22
  none: 0,
31
23
  xs: 10,
@@ -54,8 +46,10 @@ export const LOGO_SIZE_PX = {
54
46
  // `ITEM_ROW_HEIGHT - 8 = 56`) are owned by `BandScale` as of m2.5b.
55
47
  // `defaultRowBand()` keeps the legacy 64/56 split byte-stable; new
56
48
  // callers should consume `bandScale.step()` and `bandScale.bandwidth()`.
57
- // Minimum item bar width so zero-duration items remain visible.
58
- export const MIN_ITEM_WIDTH = 8;
49
+ // Minimum painted bar width: a bar spans exactly its dates, so this floor
50
+ // only keeps a sub-pixel or zero-duration item visible
51
+ // (specs/true-width-layout.md §3.1).
52
+ export const MIN_ITEM_WIDTH = 1;
59
53
  // Height (px) of the bottom progress strip drawn along the item bar's
60
54
  // bottom edge. Single source of truth used by:
61
55
  // - the renderer (strip rect height + bottom-edge offset)
@@ -69,26 +63,37 @@ export const MIN_ITEM_WIDTH = 8;
69
63
  // grows, chips lift, and the slack arrow stays centered on the strip.
70
64
  export const PROGRESS_STRIP_HEIGHT_PX = 4;
71
65
  // Timeline tick header band — a single row that holds the date labels
72
- // (e.g. "Jan 05", "Feb 14"). Layout sizes the panel; the renderer
73
- // paints the labels at a fixed baseline offset from the panel's top.
74
- //
75
- // Bumping the panel height without re-centering the baseline mis-centers
76
- // the dates — keep both knobs together so a change to either one is
77
- // visible at a glance.
78
- export const TIMELINE_TICK_PANEL_HEIGHT_PX = 24;
66
+ // (e.g. "Jan 05", "Feb 14"). The roadmap's `header-height` style key
67
+ // picks the panel height from this table; `none` drops the panel (top
68
+ // and mirrored bottom) entirely. Layout sizes the panel; the renderer
69
+ // paints the labels at `timelineTickLabelBaselineOffsetPx(height)` from
70
+ // the panel's top, so the dates stay centered at every bucket.
71
+ export const HEADER_HEIGHT_PX = {
72
+ none: 0,
73
+ xs: 16,
74
+ sm: 20,
75
+ md: 24,
76
+ lg: 32,
77
+ xl: 40,
78
+ };
79
+ /** Tick panel height at the default `header-height:md`. */
80
+ export const TIMELINE_TICK_PANEL_HEIGHT_PX = HEADER_HEIGHT_PX.md;
79
81
  /**
80
- * Baseline Y of the tick-label text relative to the tick panel's top.
81
- * Approximately vertically centers a 10 pt label in the panel.
82
+ * Baseline Y of the tick-label text relative to the tick panel's top,
83
+ * for a panel `panelHeightPx` tall. Approximately vertically centers a
84
+ * 10 pt label: half the panel plus ~3 px of descender allowance.
82
85
  */
83
- export const TIMELINE_TICK_LABEL_BASELINE_OFFSET_PX = 15;
86
+ export function timelineTickLabelBaselineOffsetPx(panelHeightPx) {
87
+ return Math.round(panelHeightPx / 2 + 3);
88
+ }
89
+ /** Tick-label baseline offset at the default panel height. */
90
+ export const TIMELINE_TICK_LABEL_BASELINE_OFFSET_PX = timelineTickLabelBaselineOffsetPx(TIMELINE_TICK_PANEL_HEIGHT_PX);
84
91
  /**
85
- * Horizontal breathing room (px) added to a track-block's right edge
86
- * after sequencing. Applied to `group { ... }` and `parallel { ... }`
87
- * blocks so successive blocks don't crowd each other. Items butt up
88
- * against their neighbors (no gutter) — only block boundaries get this
89
- * gutter.
92
+ * Font size of the tick labels. Layout reads it to decide whether a
93
+ * partial edge column is wide enough to hold its label; the renderer
94
+ * paints at the same size.
90
95
  */
91
- export const TRACK_BLOCK_TAIL_GUTTER_PX = 8;
96
+ export const TIMELINE_TICK_LABEL_FONT_SIZE_PX = 10;
92
97
  // Frame-tab chiclet — the rounded label tab that overhangs a swimlane
93
98
  // frame and the dashed include-region border. Both surfaces share the
94
99
  // same height + label baseline so the chiclets read as siblings.
@@ -100,51 +105,6 @@ export const TRACK_BLOCK_TAIL_GUTTER_PX = 8;
100
105
  export const FRAME_TAB_HEIGHT_PX = 22;
101
106
  /** Baseline Y of the chiclet label relative to the tab's top edge. */
102
107
  export const FRAME_TAB_LABEL_BASELINE_OFFSET_PX = 15;
103
- // Group title chiclet — the small label tab anchored flush in the upper-left
104
- // corner of a styled group's bounding box. Smaller than the frame-tab so it
105
- // reads as a "container label" rather than a sibling of the swimlane tab.
106
- //
107
- // The chiclet's top edge aligns with the group box's top edge and its left
108
- // edge aligns with the box's left edge (no overhang). The group reserves
109
- // `GROUP_TITLE_TAB_HEIGHT_PX + GROUP_TITLE_TAB_GUTTER_PX` of vertical top
110
- // padding inside the box before the first child row begins, so the chiclet
111
- // never overlaps content. Bumping the height without re-tuning
112
- // `GROUP_TITLE_TAB_LABEL_BASELINE_OFFSET_PX` mis-centers the label.
113
- /** Height (px) of the group-title chiclet anchored at the box's upper-left. */
114
- export const GROUP_TITLE_TAB_HEIGHT_PX = 16;
115
- /** Horizontal padding (px) on each side of the title text inside the chiclet. */
116
- export const GROUP_TITLE_TAB_PAD_X_PX = 6;
117
- /** Vertical gap (px) between the chiclet's bottom edge and the first inner row. */
118
- export const GROUP_TITLE_TAB_GUTTER_PX = 4;
119
- /** Baseline Y of the chiclet label relative to the chiclet's top edge.
120
- * Tuned for a 9 pt bold glyph roughly vertically centered in a 16 px tab. */
121
- export const GROUP_TITLE_TAB_LABEL_BASELINE_OFFSET_PX = 11;
122
- /** Font size (px) of the group-title chiclet label. */
123
- export const GROUP_TITLE_TAB_LABEL_FONT_SIZE_PX = 9;
124
- /** Approximate per-character width factor used to size the chiclet to its
125
- * title text. Mirrors the constant used in the renderer's pre-port code
126
- * so the chiclet hugs short titles without clipping long ones. */
127
- export const GROUP_TITLE_TAB_CHAR_WIDTH_PX = 5.5;
128
- /** Padding (px) reserved on the inside-bottom of a styled group box before
129
- * its lower stroke. Symmetric with the chiclet gutter so children breathe
130
- * on both ends. */
131
- export const GROUP_BOTTOM_PAD_PX = 4;
132
- /**
133
- * Vertical space (px) reserved ABOVE a bracket-style (no-fill) group's
134
- * box to host its overhanging title label. Bracket groups paint their
135
- * label at `box.y - 2` (baseline) in the renderer — the glyph extent
136
- * lives entirely ABOVE box.y. Without an explicit reservation, that
137
- * overhang collides with the previous sibling's bracket-foot when two
138
- * bracket-titled groups stack in a parallel (the foot ends right where
139
- * the next label's top would render). The group shifts its own box.y
140
- * down by this amount so the label has clear space above it; the
141
- * caller advances by `bracketLabelOverhang + box.height + interRowGap`.
142
- *
143
- * Filled-style ("chiclet") groups use `GROUP_TITLE_TAB_HEIGHT_PX +
144
- * GROUP_TITLE_TAB_GUTTER_PX` instead — the chiclet sits INSIDE the box,
145
- * so they need no above-box reservation.
146
- */
147
- export const GROUP_BRACKET_LABEL_OVERHANG_PX = 12;
148
108
  /**
149
109
  * Dashed-accent pattern (px on / px off) used for two nowline accents
150
110
  * that read as "structural emphasis": the milestone vertical cut line
@@ -191,14 +151,14 @@ export const NOW_PILL_LABEL_INSET_X_PX = 6;
191
151
  * stroke peeks past the pill's squared edge by half-stroke).
192
152
  */
193
153
  export const NOWLINE_STROKE_WIDTH_PX = 2.25;
194
- // Visual inset applied on each side of an item bar. Two adjacent (logically
195
- // chained) items therefore have a 2× ITEM_INSET_PX visible gutter between
196
- // them, leaving room for vertical drop-lines (dependency arrows, anchor /
197
- // milestone cuts, the now-line) to pass between bars without crossing them.
198
- export const ITEM_INSET_PX = 6;
154
+ // The seam a bar gives up on each side, from inside its dates, so two bars
155
+ // that abut in time show a 2 px gap between their strokes
156
+ // (specs/true-width-layout.md §3.1). A bar too short for both seams and the
157
+ // `MIN_ITEM_WIDTH` floor shrinks its seams instead, staying centred in its
158
+ // dates.
159
+ export const ITEM_SEAM_PX = 1;
199
160
  // Canonical content gutter — the rest-state spacing between adjacent
200
161
  // pieces of chart content. Used for:
201
- // - the gap between two adjacent items in a track (= 2 × ITEM_INSET_PX),
202
162
  // - the gap between the header card and the chart's left edge (originX
203
163
  // offset from chartLeftX),
204
164
  // - the bottom margin around the attribution wordmark.
@@ -208,10 +168,13 @@ export const ITEM_INSET_PX = 6;
208
168
  // That's a runtime concern — the layout engine emits a static positioned
209
169
  // model and the interactive shell animates spacing on top. Keep this
210
170
  // constant as the rest-state baseline.
211
- export const GUTTER_PX = 2 * ITEM_INSET_PX;
212
- // Default pixel-per-day when no explicit scale is set. Calibrated so a
213
- // 26-week (180 day) roadmap fits a 1200 px content area.
214
- export const DEFAULT_PIXELS_PER_DAY = 5;
171
+ export const GUTTER_PX = 12;
172
+ // Pixels per day at the days scale (`scale:1d`). A day literal labels
173
+ // every column, so a day must hold its widest `M/D` label (`12/31`, about
174
+ // 29 px at the 10 px tick font), as a 40 px week holds `Sep 28`. That
175
+ // also keeps a day here wider than a day inside a default week column
176
+ // (8 px under business, about 5.7 px under full).
177
+ export const DEFAULT_PIXELS_PER_DAY = 32;
215
178
  // Header box defaults per position. The beside-mode card width is dynamic
216
179
  // (sized to the title + author text, clamped to MIN..MAX with text wrap),
217
180
  // so the layout uses these bounds instead of a single fixed width.
@@ -227,13 +190,15 @@ export const HEADER_ABOVE_HEIGHT_PX = 72;
227
190
  // │ Footnotes ↑ │ header band (HEADER_HEIGHT)
228
191
  // │ │ │
229
192
  // ├─────────────────────────┘ │ gap = PANEL_PADDING
230
- // │ N Title — description │ row N (ROW_HEIGHT each)
193
+ // │ N Title — description │ row (ROW_HEIGHT each)
194
+ // │ that wraps at the title │ wrapped row
231
195
  // │ N … │
232
196
  // │ │
233
197
  // └───────────────────────────────┘ bottom pad = PANEL_PADDING
234
198
  //
235
199
  // Total panel height (when entries.length > 0):
236
- // HEADER_HEIGHT + entries × ROW_HEIGHT + PANEL_PADDING
200
+ // HEADER_HEIGHT + rows × ROW_HEIGHT + PANEL_PADDING, where rows counts
201
+ // every entry's rows (wrapped ones included) and each region heading.
237
202
  /** Height (px) of the header band above the entry rows. */
238
203
  export const FOOTNOTE_HEADER_HEIGHT_PX = 28;
239
204
  /**
@@ -307,4 +272,35 @@ export const LABEL_THINNING = {
307
272
  quarters: 4,
308
273
  years: 5,
309
274
  };
275
+ // Opacity of a non-working band (`timeline.nonWorkingFill`) under the
276
+ // `show` display (specs/working-calendar.md §7.3).
277
+ export const NON_WORKING_FILL_OPACITY = 0.1;
278
+ // Waves (specs/waves.md section 9.10; hatch geometry section 9.3).
279
+ export const WAVE_STRIP_HEIGHT_PX = 20;
280
+ export const WAVE_BOUNDARY_WIDTH_PX = 2;
281
+ export const WAVE_CROSS_DASH = '2 2';
282
+ export const WAVE_HATCH_OPACITY = 0.13;
283
+ export const WAVE_HATCH_TILE_PX = 6;
284
+ export const WAVE_HATCH_STROKE_PX = 2;
285
+ export const WAVE_STYLED_TINT_OPACITY = 0.12;
286
+ export const WAVE_STYLED_STRIP_MIX_OPACITY = 0.25;
287
+ export const WAVE_STRIP_LABEL_FONT_SIZE_PX = 10;
288
+ export const WAVE_LEGEND_LINE_PX = 14;
289
+ export const WAVE_LEGEND_GAP_PX = 8;
290
+ // Wave strip and legend geometry (specs/waves.md §9.1, §9.5).
291
+ /** Horizontal padding on each side of a strip label in the fit test. */
292
+ export const WAVE_STRIP_LABEL_PAD_PX = 6;
293
+ /** Horizontal padding of a strip label's halo on each side. */
294
+ export const WAVE_LABEL_HALO_PAD_PX = 2;
295
+ /** Vertical inset of a strip label's halo from the strip's top and bottom. */
296
+ export const WAVE_LABEL_HALO_INSET_Y_PX = 3;
297
+ /** How far a strip cell sits inside the backing panel: half its 1 px stroke. */
298
+ export const WAVE_CELL_INSET_PX = 0.5;
299
+ /** Legend swatch (a hatched bar) size. */
300
+ export const WAVE_LEGEND_SWATCH_WIDTH_PX = 18;
301
+ export const WAVE_LEGEND_SWATCH_HEIGHT_PX = 10;
302
+ /** Gap between a legend swatch and its text. */
303
+ export const WAVE_LEGEND_SWATCH_GAP_PX = 6;
304
+ /** Legend text baseline below its line's top (10 px text in a 14 px line). */
305
+ export const WAVE_LEGEND_BASELINE_OFFSET_PX = 11;
310
306
  //# sourceMappingURL=shared.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/themes/shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/themes/shared.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,33 @@
1
+ import type { NonWorkingDisplay } from './non-working-display.js';
1
2
  import type { WorkingCalendar } from './working-calendar.js';
2
3
  export interface TimeScaleOptions {
3
4
  /** [start, end] in calendar dates (UTC midnight assumed). */
4
5
  domain: [Date, Date];
5
6
  /** [originX, originX + chartWidth]. */
6
7
  range: [number, number];
7
- /** Optional non-continuous calendar for future weekend-skip support. */
8
+ /** The working calendar; without one every day is a working day. */
8
9
  calendar?: WorkingCalendar;
10
+ /** How non-working days are drawn; `hide` when omitted. */
11
+ nonWorking?: NonWorkingDisplay;
9
12
  }
10
13
  export declare class TimeScale {
11
14
  readonly domain: [Date, Date];
12
15
  readonly range: [number, number];
13
16
  readonly pixelsPerDay: number;
14
17
  readonly calendar?: WorkingCalendar;
15
- private readonly d3;
18
+ /** The requested display; `showsNonWorking` says whether it takes effect. */
19
+ readonly nonWorking: NonWorkingDisplay;
16
20
  constructor(opts: TimeScaleOptions);
21
+ /**
22
+ * True when non-working days are drawn at full width: the `show`
23
+ * display over a calendar that has non-working days. The one predicate
24
+ * every show-only branch in the layout is gated on.
25
+ */
26
+ get showsNonWorking(): boolean;
27
+ /** Working days from the domain start to `date` (calendar days without a calendar). */
28
+ private indexOf;
29
+ /** Calendar days from the domain start to `x`, and the whole day `x` lies in. */
30
+ private dayAt;
17
31
  /**
18
32
  * Project a date onto the x-axis. Always returns a number, even
19
33
  * for dates outside the domain (callers that need clamping use
@@ -22,15 +36,37 @@ export declare class TimeScale {
22
36
  forward(date: Date): number;
23
37
  /**
24
38
  * Project a date onto the x-axis, returning `null` when the date
25
- * is outside [domain[0], domain[1]]. Replaces the legacy
26
- * `xForDate(date, timeline)` helper.
39
+ * is outside [domain[0], domain[1]]. The guard compares raw dates,
40
+ * so a hidden day inside the window still projects. Replaces the
41
+ * legacy `xForDate(date, timeline)` helper.
27
42
  */
28
43
  forwardWithinDomain(date: Date): number | null;
29
44
  /**
30
- * Inverse projection. Returns a Date for any x in the chart;
31
- * callers that want day-resolution can floor the result.
45
+ * Inverse projection: the working day whose start is nearest x
46
+ * (UTC midnight). Never a non-working day, except under `show`, where
47
+ * every day has width and this is the calendar day nearest x.
32
48
  */
33
49
  invert(x: number): Date;
50
+ /**
51
+ * The working-day index at `x`, with the fraction of a working day it
52
+ * is into. Under `show` an x inside a non-working day reads as the start
53
+ * of the next working day; otherwise x is linear in the index.
54
+ */
55
+ indexAtX(x: number): number;
56
+ /**
57
+ * Where an item placed at `x` starts. Under `show` an x inside a
58
+ * non-working day moves forward to the start of the next working day;
59
+ * an x inside a working day keeps its fraction, so a start mid-Friday
60
+ * stays mid-Friday. The identity otherwise.
61
+ */
62
+ startX(x: number): number;
63
+ /**
64
+ * The x where `n` working days from `startX(x)` end. Under `show` that is
65
+ * the end of the last working day the span reaches, with a partial day
66
+ * interpolated, so a Mon-Fri item ends on Friday evening and the weekend
67
+ * after it stays open. `x + n * pixelsPerDay` otherwise.
68
+ */
69
+ advanceX(x: number, n: number): number;
34
70
  /** First pixel of the chart (start of range). */
35
71
  get originX(): number;
36
72
  /** Width of the chart band in pixels. */
@@ -1 +1 @@
1
- {"version":3,"file":"time-scale.d.ts","sourceRoot":"","sources":["../src/time-scale.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrB,uCAAuC;IACvC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,qBAAa,SAAS;IAClB,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA4B;gBAEnC,IAAI,EAAE,gBAAgB;IASlC;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAK3B;;;;OAIG;IACH,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI;IAK9C;;;OAGG;IACH,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAIvB,iDAAiD;IACjD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,yCAAyC;IACzC,IAAI,OAAO,IAAI,MAAM,CAEpB;CACJ"}
1
+ {"version":3,"file":"time-scale.d.ts","sourceRoot":"","sources":["../src/time-scale.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQ7D,MAAM,WAAW,gBAAgB;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrB,uCAAuC;IACvC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAClC;AAED,qBAAa,SAAS;IAClB,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IAEvC,YAAY,IAAI,EAAE,gBAAgB,EAYjC;IAED;;;;OAIG;IACH,IAAI,eAAe,IAAI,OAAO,CAE7B;IAED,uFAAuF;IACvF,OAAO,CAAC,OAAO;IAMf,iFAAiF;IACjF,OAAO,CAAC,KAAK;IAKb;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAK1B;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAG7C;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAMtB;IAED;;;;OAIG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO1B;IAED;;;;;OAKG;IACH,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMxB;IAED;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUrC;IAED,iDAAiD;IACjD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,yCAAyC;IACzC,IAAI,OAAO,IAAI,MAAM,CAEpB;CACJ"}
@@ -3,26 +3,60 @@
3
3
  // also exposes `invert(x) -> Date` for the m4 editor work and that
4
4
  // composes with a `WorkingCalendar` for non-continuous time models.
5
5
  //
6
- // Forward direction matches the legacy arithmetic byte-for-byte
7
- // (`originX + daysBetween(domain[0], date) * pixelsPerDay`) so the
8
- // m2.5a refactor leaves the rendered output unchanged. Invert uses
9
- // `d3-scale.scaleTime` so callers get a precise Date back from a
10
- // pixel coordinate.
11
- import { scaleTime } from 'd3-scale';
12
- import { daysBetween } from './calendar.js';
6
+ // x is linear in the working-day index from the domain start
7
+ // (specs/working-calendar.md §7.1): `originX + index * pixelsPerDay`.
8
+ // With no calendar, or one with no non-working day, the index is
9
+ // `daysBetween`, so the forward direction matches the legacy
10
+ // arithmetic byte-for-byte. Under a calendar with non-working days a
11
+ // hidden date maps to the start of the next working day, and `invert`
12
+ // returns the working day whose start is nearest x.
13
+ //
14
+ // Under the `show` display (§7.3) a calendar's non-working days keep their
15
+ // full width instead: x is linear in calendar days, and `startX` /
16
+ // `advanceX` step an item over the non-working days it crosses. Every
17
+ // branch for it is gated on `showsNonWorking`, so `hide`, a calendar with no
18
+ // non-working day and a scale with no calendar keep the code above verbatim.
19
+ import { addDays, daysBetween } from './calendar.js';
20
+ /**
21
+ * Tolerance, in days, for reading a day off an x. Pixel sums carry float
22
+ * noise, so an x a hair before a day's start counts as that day.
23
+ */
24
+ const DAY_EPSILON = 1e-6;
13
25
  export class TimeScale {
14
26
  domain;
15
27
  range;
16
28
  pixelsPerDay;
17
29
  calendar;
18
- d3;
30
+ /** The requested display; `showsNonWorking` says whether it takes effect. */
31
+ nonWorking;
19
32
  constructor(opts) {
20
33
  this.domain = opts.domain;
21
34
  this.range = opts.range;
22
35
  this.calendar = opts.calendar;
23
- const spanDays = Math.max(1, daysBetween(opts.domain[0], opts.domain[1]));
36
+ this.nonWorking = opts.nonWorking ?? 'hide';
37
+ const spanDays = Math.max(1, this.showsNonWorking
38
+ ? daysBetween(opts.domain[0], opts.domain[1])
39
+ : this.indexOf(opts.domain[1]));
24
40
  this.pixelsPerDay = (opts.range[1] - opts.range[0]) / spanDays;
25
- this.d3 = scaleTime().domain(opts.domain).range(opts.range);
41
+ }
42
+ /**
43
+ * True when non-working days are drawn at full width: the `show`
44
+ * display over a calendar that has non-working days. The one predicate
45
+ * every show-only branch in the layout is gated on.
46
+ */
47
+ get showsNonWorking() {
48
+ return this.nonWorking === 'show' && this.calendar?.hasNonWorkingDays === true;
49
+ }
50
+ /** Working days from the domain start to `date` (calendar days without a calendar). */
51
+ indexOf(date) {
52
+ return this.calendar
53
+ ? this.calendar.workingIndexOf(this.domain[0], date)
54
+ : daysBetween(this.domain[0], date);
55
+ }
56
+ /** Calendar days from the domain start to `x`, and the whole day `x` lies in. */
57
+ dayAt(x) {
58
+ const days = (x - this.range[0]) / this.pixelsPerDay;
59
+ return { days, day: Math.floor(days + DAY_EPSILON) };
26
60
  }
27
61
  /**
28
62
  * Project a date onto the x-axis. Always returns a number, even
@@ -30,13 +64,16 @@ export class TimeScale {
30
64
  * `forwardWithinDomain`).
31
65
  */
32
66
  forward(date) {
33
- const days = daysBetween(this.domain[0], date);
34
- return this.range[0] + days * this.pixelsPerDay;
67
+ if (this.showsNonWorking) {
68
+ return this.range[0] + daysBetween(this.domain[0], date) * this.pixelsPerDay;
69
+ }
70
+ return this.range[0] + this.indexOf(date) * this.pixelsPerDay;
35
71
  }
36
72
  /**
37
73
  * Project a date onto the x-axis, returning `null` when the date
38
- * is outside [domain[0], domain[1]]. Replaces the legacy
39
- * `xForDate(date, timeline)` helper.
74
+ * is outside [domain[0], domain[1]]. The guard compares raw dates,
75
+ * so a hidden day inside the window still projects. Replaces the
76
+ * legacy `xForDate(date, timeline)` helper.
40
77
  */
41
78
  forwardWithinDomain(date) {
42
79
  if (date < this.domain[0] || date > this.domain[1])
@@ -44,11 +81,66 @@ export class TimeScale {
44
81
  return this.forward(date);
45
82
  }
46
83
  /**
47
- * Inverse projection. Returns a Date for any x in the chart;
48
- * callers that want day-resolution can floor the result.
84
+ * Inverse projection: the working day whose start is nearest x
85
+ * (UTC midnight). Never a non-working day, except under `show`, where
86
+ * every day has width and this is the calendar day nearest x.
49
87
  */
50
88
  invert(x) {
51
- return this.d3.invert(x);
89
+ const index = Math.round((x - this.range[0]) / this.pixelsPerDay);
90
+ if (this.showsNonWorking)
91
+ return addDays(this.domain[0], index);
92
+ return this.calendar
93
+ ? this.calendar.dateAtWorkingIndex(this.domain[0], index)
94
+ : addDays(this.domain[0], index);
95
+ }
96
+ /**
97
+ * The working-day index at `x`, with the fraction of a working day it
98
+ * is into. Under `show` an x inside a non-working day reads as the start
99
+ * of the next working day; otherwise x is linear in the index.
100
+ */
101
+ indexAtX(x) {
102
+ const { days, day } = this.dayAt(x);
103
+ if (!this.showsNonWorking || !this.calendar)
104
+ return days;
105
+ const date = addDays(this.domain[0], day);
106
+ const index = this.calendar.workingIndexOf(this.domain[0], date);
107
+ if (!this.calendar.isWorkingDay(date))
108
+ return index;
109
+ return index + Math.max(0, days - day);
110
+ }
111
+ /**
112
+ * Where an item placed at `x` starts. Under `show` an x inside a
113
+ * non-working day moves forward to the start of the next working day;
114
+ * an x inside a working day keeps its fraction, so a start mid-Friday
115
+ * stays mid-Friday. The identity otherwise.
116
+ */
117
+ startX(x) {
118
+ if (!this.showsNonWorking || !this.calendar)
119
+ return x;
120
+ const date = addDays(this.domain[0], this.dayAt(x).day);
121
+ if (this.calendar.isWorkingDay(date))
122
+ return x;
123
+ const index = this.calendar.workingIndexOf(this.domain[0], date);
124
+ return this.forward(this.calendar.dateAtWorkingIndex(this.domain[0], index));
125
+ }
126
+ /**
127
+ * The x where `n` working days from `startX(x)` end. Under `show` that is
128
+ * the end of the last working day the span reaches, with a partial day
129
+ * interpolated, so a Mon-Fri item ends on Friday evening and the weekend
130
+ * after it stays open. `x + n * pixelsPerDay` otherwise.
131
+ */
132
+ advanceX(x, n) {
133
+ if (!this.showsNonWorking || !this.calendar)
134
+ return x + n * this.pixelsPerDay;
135
+ const start = this.startX(x);
136
+ if (n <= 0)
137
+ return start;
138
+ const target = this.indexAtX(start) + n;
139
+ // The working day the span ends in, and how much of it it covers (0, 1].
140
+ const lastDay = Math.ceil(target - DAY_EPSILON) - 1;
141
+ const covered = target - lastDay;
142
+ const lastDate = this.calendar.dateAtWorkingIndex(this.domain[0], lastDay);
143
+ return this.forward(lastDate) + covered * this.pixelsPerDay;
52
144
  }
53
145
  /** First pixel of the chart (start of range). */
54
146
  get originX() {
@@ -1 +1 @@
1
- {"version":3,"file":"time-scale.js","sourceRoot":"","sources":["../src/time-scale.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,mEAAmE;AACnE,mEAAmE;AACnE,oEAAoE;AACpE,EAAE;AACF,gEAAgE;AAChE,mEAAmE;AACnE,mEAAmE;AACnE,iEAAiE;AACjE,oBAAoB;AAEpB,OAAO,EAAkB,SAAS,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAY5C,MAAM,OAAO,SAAS;IACT,MAAM,CAAe;IACrB,KAAK,CAAmB;IACxB,YAAY,CAAS;IACrB,QAAQ,CAAmB;IACnB,EAAE,CAA4B;IAE/C,YAAY,IAAsB;QAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;QAC/D,IAAI,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChE,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAU;QACd,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,mBAAmB,CAAC,IAAU;QAC1B,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAChE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,CAAS;QACZ,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,iDAAiD;IACjD,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;CACJ"}
1
+ {"version":3,"file":"time-scale.js","sourceRoot":"","sources":["../src/time-scale.ts"],"names":[],"mappings":"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"}