@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.
- package/dist/axis-columns.d.ts +70 -0
- package/dist/axis-columns.d.ts.map +1 -0
- package/dist/axis-columns.js +104 -0
- package/dist/axis-columns.js.map +1 -0
- package/dist/band-scale.d.ts.map +1 -1
- package/dist/calendar-resolver.d.ts +27 -0
- package/dist/calendar-resolver.d.ts.map +1 -0
- package/dist/calendar-resolver.js +132 -0
- package/dist/calendar-resolver.js.map +1 -0
- package/dist/calendar.d.ts +0 -19
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +4 -44
- package/dist/calendar.js.map +1 -1
- package/dist/canvas-width.d.ts +23 -0
- package/dist/canvas-width.d.ts.map +1 -0
- package/dist/canvas-width.js +26 -0
- package/dist/canvas-width.js.map +1 -0
- package/dist/capacity.d.ts +28 -0
- package/dist/capacity.d.ts.map +1 -1
- package/dist/capacity.js +64 -29
- package/dist/capacity.js.map +1 -1
- package/dist/chart-translation.d.ts +22 -0
- package/dist/chart-translation.d.ts.map +1 -0
- package/dist/chart-translation.js +83 -0
- package/dist/chart-translation.js.map +1 -0
- package/dist/container-header-geometry.d.ts +64 -0
- package/dist/container-header-geometry.d.ts.map +1 -0
- package/dist/container-header-geometry.js +89 -0
- package/dist/container-header-geometry.js.map +1 -0
- package/dist/dsl-utils.d.ts +3 -4
- package/dist/dsl-utils.d.ts.map +1 -1
- package/dist/dsl-utils.js +8 -25
- package/dist/dsl-utils.js.map +1 -1
- package/dist/edge-routing.d.ts +69 -78
- package/dist/edge-routing.d.ts.map +1 -1
- package/dist/edge-routing.js +271 -401
- package/dist/edge-routing.js.map +1 -1
- package/dist/frame-tab-geometry.d.ts +24 -14
- package/dist/frame-tab-geometry.d.ts.map +1 -1
- package/dist/frame-tab-geometry.js +69 -23
- package/dist/frame-tab-geometry.js.map +1 -1
- package/dist/header-card-geometry.d.ts +12 -0
- package/dist/header-card-geometry.d.ts.map +1 -1
- package/dist/header-card-geometry.js +14 -2
- package/dist/header-card-geometry.js.map +1 -1
- package/dist/header-logo.d.ts +28 -0
- package/dist/header-logo.d.ts.map +1 -0
- package/dist/header-logo.js +51 -0
- package/dist/header-logo.js.map +1 -0
- package/dist/i18n.d.ts +11 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +11 -1
- package/dist/i18n.js.map +1 -1
- package/dist/index.d.ts +20 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/inline-date-pin-geometry.d.ts +19 -11
- package/dist/inline-date-pin-geometry.d.ts.map +1 -1
- package/dist/inline-date-pin-geometry.js +45 -46
- package/dist/inline-date-pin-geometry.js.map +1 -1
- package/dist/item-bar-geometry.d.ts +192 -4
- package/dist/item-bar-geometry.d.ts.map +1 -1
- package/dist/item-bar-geometry.js +258 -5
- package/dist/item-bar-geometry.js.map +1 -1
- package/dist/item-port-geometry.d.ts +13 -0
- package/dist/item-port-geometry.d.ts.map +1 -0
- package/dist/item-port-geometry.js +63 -0
- package/dist/item-port-geometry.js.map +1 -0
- package/dist/layout-context.d.ts +115 -51
- package/dist/layout-context.d.ts.map +1 -1
- package/dist/layout-context.js +96 -5
- package/dist/layout-context.js.map +1 -1
- package/dist/layout-insights.d.ts.map +1 -1
- package/dist/layout-insights.js +73 -1
- package/dist/layout-insights.js.map +1 -1
- package/dist/layout.d.ts +35 -0
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +18 -1315
- package/dist/layout.js.map +1 -1
- package/dist/nodes/anchor-node.d.ts.map +1 -1
- package/dist/nodes/anchor-node.js +11 -4
- package/dist/nodes/anchor-node.js.map +1 -1
- package/dist/nodes/content-extent.d.ts +24 -0
- package/dist/nodes/content-extent.d.ts.map +1 -0
- package/dist/nodes/content-extent.js +100 -0
- package/dist/nodes/content-extent.js.map +1 -0
- package/dist/nodes/dependency-edges.d.ts +6 -0
- package/dist/nodes/dependency-edges.d.ts.map +1 -0
- package/dist/nodes/dependency-edges.js +148 -0
- package/dist/nodes/dependency-edges.js.map +1 -0
- package/dist/nodes/footnote-node.d.ts +24 -3
- package/dist/nodes/footnote-node.d.ts.map +1 -1
- package/dist/nodes/footnote-node.js +129 -25
- package/dist/nodes/footnote-node.js.map +1 -1
- package/dist/nodes/group-node.d.ts +10 -21
- package/dist/nodes/group-node.d.ts.map +1 -1
- package/dist/nodes/group-node.js +79 -154
- package/dist/nodes/group-node.js.map +1 -1
- package/dist/nodes/header-node.d.ts +56 -0
- package/dist/nodes/header-node.d.ts.map +1 -0
- package/dist/nodes/header-node.js +163 -0
- package/dist/nodes/header-node.js.map +1 -0
- package/dist/nodes/include-node.d.ts +22 -12
- package/dist/nodes/include-node.d.ts.map +1 -1
- package/dist/nodes/include-node.js +95 -62
- package/dist/nodes/include-node.js.map +1 -1
- package/dist/nodes/item-measure.d.ts +135 -0
- package/dist/nodes/item-measure.d.ts.map +1 -0
- package/dist/nodes/item-measure.js +514 -0
- package/dist/nodes/item-measure.js.map +1 -0
- package/dist/nodes/item-node.d.ts +162 -9
- package/dist/nodes/item-node.d.ts.map +1 -1
- package/dist/nodes/item-node.js +256 -69
- package/dist/nodes/item-node.js.map +1 -1
- package/dist/nodes/marker-band.d.ts +118 -0
- package/dist/nodes/marker-band.d.ts.map +1 -0
- package/dist/nodes/marker-band.js +303 -0
- package/dist/nodes/marker-band.js.map +1 -0
- package/dist/nodes/marker-geometry.js +1 -1
- package/dist/nodes/marker-geometry.js.map +1 -1
- package/dist/nodes/milestone-node.d.ts +112 -15
- package/dist/nodes/milestone-node.d.ts.map +1 -1
- package/dist/nodes/milestone-node.js +246 -95
- package/dist/nodes/milestone-node.js.map +1 -1
- package/dist/nodes/nowline-node.d.ts +8 -0
- package/dist/nodes/nowline-node.d.ts.map +1 -0
- package/dist/nodes/nowline-node.js +74 -0
- package/dist/nodes/nowline-node.js.map +1 -0
- package/dist/nodes/parallel-node.d.ts +7 -12
- package/dist/nodes/parallel-node.d.ts.map +1 -1
- package/dist/nodes/parallel-node.js +66 -32
- package/dist/nodes/parallel-node.js.map +1 -1
- package/dist/nodes/region-markers.d.ts +41 -0
- package/dist/nodes/region-markers.d.ts.map +1 -0
- package/dist/nodes/region-markers.js +130 -0
- package/dist/nodes/region-markers.js.map +1 -0
- package/dist/nodes/roadmap-node.d.ts +9 -72
- package/dist/nodes/roadmap-node.d.ts.map +1 -1
- package/dist/nodes/roadmap-node.js +38 -788
- package/dist/nodes/roadmap-node.js.map +1 -1
- package/dist/nodes/row-track.d.ts +33 -0
- package/dist/nodes/row-track.d.ts.map +1 -0
- package/dist/nodes/row-track.js +170 -0
- package/dist/nodes/row-track.js.map +1 -0
- package/dist/nodes/sequence-item.d.ts +25 -0
- package/dist/nodes/sequence-item.d.ts.map +1 -0
- package/dist/nodes/sequence-item.js +396 -0
- package/dist/nodes/sequence-item.js.map +1 -0
- package/dist/nodes/sequence-one.d.ts +5 -0
- package/dist/nodes/sequence-one.d.ts.map +1 -0
- package/dist/nodes/sequence-one.js +26 -0
- package/dist/nodes/sequence-one.js.map +1 -0
- package/dist/nodes/swimlane-node.d.ts +5 -17
- package/dist/nodes/swimlane-node.d.ts.map +1 -1
- package/dist/nodes/swimlane-node.js +62 -147
- package/dist/nodes/swimlane-node.js.map +1 -1
- package/dist/nodes/wave-node.d.ts +52 -0
- package/dist/nodes/wave-node.d.ts.map +1 -0
- package/dist/nodes/wave-node.js +483 -0
- package/dist/nodes/wave-node.js.map +1 -0
- package/dist/non-working-display.d.ts +14 -0
- package/dist/non-working-display.d.ts.map +1 -0
- package/dist/non-working-display.js +28 -0
- package/dist/non-working-display.js.map +1 -0
- package/dist/phases/date-window.d.ts +48 -0
- package/dist/phases/date-window.d.ts.map +1 -0
- package/dist/phases/date-window.js +130 -0
- package/dist/phases/date-window.js.map +1 -0
- package/dist/phases/finalize.d.ts +198 -0
- package/dist/phases/finalize.d.ts.map +1 -0
- package/dist/phases/finalize.js +1058 -0
- package/dist/phases/finalize.js.map +1 -0
- package/dist/phases/measure.d.ts +77 -0
- package/dist/phases/measure.d.ts.map +1 -0
- package/dist/phases/measure.js +222 -0
- package/dist/phases/measure.js.map +1 -0
- package/dist/phases/place.d.ts +28 -0
- package/dist/phases/place.d.ts.map +1 -0
- package/dist/phases/place.js +225 -0
- package/dist/phases/place.js.map +1 -0
- package/dist/renderable.d.ts.map +1 -1
- package/dist/renderable.js +23 -3
- package/dist/renderable.js.map +1 -1
- package/dist/resolve-today.d.ts +11 -1
- package/dist/resolve-today.d.ts.map +1 -1
- package/dist/resolve-today.js +26 -12
- package/dist/resolve-today.js.map +1 -1
- package/dist/row-packer.d.ts +42 -16
- package/dist/row-packer.d.ts.map +1 -1
- package/dist/row-packer.js +51 -78
- package/dist/row-packer.js.map +1 -1
- package/dist/schedule.d.ts +58 -1
- package/dist/schedule.d.ts.map +1 -1
- package/dist/schedule.js +280 -106
- package/dist/schedule.js.map +1 -1
- package/dist/start-rules.d.ts +27 -0
- package/dist/start-rules.d.ts.map +1 -0
- package/dist/start-rules.js +91 -0
- package/dist/start-rules.js.map +1 -0
- package/dist/start-terms.d.ts +23 -0
- package/dist/start-terms.d.ts.map +1 -0
- package/dist/start-terms.js +27 -0
- package/dist/start-terms.js.map +1 -0
- package/dist/status-dot.d.ts +46 -0
- package/dist/status-dot.d.ts.map +1 -0
- package/dist/status-dot.js +78 -0
- package/dist/status-dot.js.map +1 -0
- package/dist/style-resolution.d.ts.map +1 -1
- package/dist/style-resolution.js +23 -43
- package/dist/style-resolution.js.map +1 -1
- package/dist/text-measure.d.ts +28 -0
- package/dist/text-measure.d.ts.map +1 -0
- package/dist/text-measure.js +70 -0
- package/dist/text-measure.js.map +1 -0
- package/dist/themes/contrast.d.ts +4 -0
- package/dist/themes/contrast.d.ts.map +1 -0
- package/dist/themes/contrast.js +32 -0
- package/dist/themes/contrast.js.map +1 -0
- package/dist/themes/dark.d.ts.map +1 -1
- package/dist/themes/dark.js +28 -1
- package/dist/themes/dark.js.map +1 -1
- package/dist/themes/grayscale.d.ts.map +1 -1
- package/dist/themes/grayscale.js +28 -1
- package/dist/themes/grayscale.js.map +1 -1
- package/dist/themes/index.d.ts +4 -11
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +6 -4
- package/dist/themes/index.js.map +1 -1
- package/dist/themes/light.d.ts.map +1 -1
- package/dist/themes/light.js +28 -1
- package/dist/themes/light.js.map +1 -1
- package/dist/themes/shape.d.ts +31 -0
- package/dist/themes/shape.d.ts.map +1 -1
- package/dist/themes/shared.d.ts +44 -50
- package/dist/themes/shared.d.ts.map +1 -1
- package/dist/themes/shared.js +79 -83
- package/dist/themes/shared.js.map +1 -1
- package/dist/time-scale.d.ts +42 -6
- package/dist/time-scale.d.ts.map +1 -1
- package/dist/time-scale.js +109 -17
- package/dist/time-scale.js.map +1 -1
- package/dist/types.d.ts +528 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/view-preset.d.ts +61 -6
- package/dist/view-preset.d.ts.map +1 -1
- package/dist/view-preset.js +439 -24
- package/dist/view-preset.js.map +1 -1
- package/dist/wave-barrier.d.ts +107 -0
- package/dist/wave-barrier.d.ts.map +1 -0
- package/dist/wave-barrier.js +174 -0
- package/dist/wave-barrier.js.map +1 -0
- package/dist/wave-hatch.d.ts +4 -0
- package/dist/wave-hatch.d.ts.map +1 -0
- package/dist/wave-hatch.js +21 -0
- package/dist/wave-hatch.js.map +1 -0
- package/dist/wave-layout.d.ts +99 -0
- package/dist/wave-layout.d.ts.map +1 -0
- package/dist/wave-layout.js +130 -0
- package/dist/wave-layout.js.map +1 -0
- package/dist/working-calendar.d.ts +128 -4
- package/dist/working-calendar.d.ts.map +1 -1
- package/dist/working-calendar.js +725 -51
- package/dist/working-calendar.js.map +1 -1
- package/dist/working-span.d.ts +11 -0
- package/dist/working-span.d.ts.map +1 -0
- package/dist/working-span.js +18 -0
- package/dist/working-span.js.map +1 -0
- package/package.json +7 -7
- package/src/axis-columns.ts +140 -0
- package/src/calendar-resolver.ts +161 -0
- package/src/calendar.ts +4 -45
- package/src/canvas-width.ts +36 -0
- package/src/capacity.ts +71 -30
- package/src/chart-translation.ts +88 -0
- package/src/container-header-geometry.ts +116 -0
- package/src/dsl-utils.ts +8 -26
- package/src/edge-routing.ts +347 -491
- package/src/frame-tab-geometry.ts +78 -25
- package/src/header-card-geometry.ts +17 -2
- package/src/header-logo.ts +67 -0
- package/src/i18n.ts +22 -1
- package/src/index.ts +97 -12
- package/src/inline-date-pin-geometry.ts +55 -58
- package/src/item-bar-geometry.ts +341 -5
- package/src/item-port-geometry.ts +69 -0
- package/src/layout-context.ts +210 -72
- package/src/layout-insights.ts +109 -2
- package/src/layout.ts +57 -1530
- package/src/nodes/anchor-node.ts +11 -4
- package/src/nodes/content-extent.ts +107 -0
- package/src/nodes/dependency-edges.ts +171 -0
- package/src/nodes/footnote-node.ts +171 -31
- package/src/nodes/group-node.ts +92 -215
- package/src/nodes/header-node.ts +255 -0
- package/src/nodes/include-node.ts +124 -110
- package/src/nodes/item-measure.ts +723 -0
- package/src/nodes/item-node.ts +358 -80
- package/src/nodes/marker-band.ts +406 -0
- package/src/nodes/marker-geometry.ts +1 -1
- package/src/nodes/milestone-node.ts +321 -136
- package/src/nodes/nowline-node.ts +87 -0
- package/src/nodes/parallel-node.ts +69 -39
- package/src/nodes/region-markers.ts +194 -0
- package/src/nodes/roadmap-node.ts +46 -950
- package/src/nodes/row-track.ts +217 -0
- package/src/nodes/sequence-item.ts +433 -0
- package/src/nodes/sequence-one.ts +40 -0
- package/src/nodes/swimlane-node.ts +66 -206
- package/src/nodes/wave-node.ts +609 -0
- package/src/non-working-display.ts +32 -0
- package/src/phases/date-window.ts +191 -0
- package/src/phases/finalize.ts +1303 -0
- package/src/phases/measure.ts +329 -0
- package/src/phases/place.ts +318 -0
- package/src/renderable.ts +23 -3
- package/src/resolve-today.ts +28 -25
- package/src/row-packer.ts +85 -84
- package/src/schedule.ts +362 -114
- package/src/start-rules.ts +113 -0
- package/src/start-terms.ts +38 -0
- package/src/status-dot.ts +81 -0
- package/src/style-resolution.ts +27 -57
- package/src/text-measure.ts +71 -0
- package/src/themes/contrast.ts +34 -0
- package/src/themes/dark.ts +28 -1
- package/src/themes/grayscale.ts +28 -1
- package/src/themes/index.ts +10 -7
- package/src/themes/light.ts +28 -1
- package/src/themes/shape.ts +38 -0
- package/src/themes/shared.ts +85 -93
- package/src/time-scale.ts +117 -19
- package/src/types.ts +529 -20
- package/src/view-preset.ts +520 -27
- package/src/wave-barrier.ts +242 -0
- package/src/wave-hatch.ts +25 -0
- package/src/wave-layout.ts +203 -0
- package/src/working-calendar.ts +875 -57
- package/src/working-span.ts +19 -0
package/src/types.ts
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
// top-left. All colors in `ResolvedStyle` are concrete hex strings baked
|
|
4
4
|
// in by style-resolution; the renderer is palette-dumb.
|
|
5
5
|
|
|
6
|
+
import type { FrameTabGeometry } from './frame-tab-geometry.js';
|
|
7
|
+
import type { NonWorkingDisplay } from './non-working-display.js';
|
|
8
|
+
|
|
6
9
|
export type SizeBucket = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
7
10
|
export type ShadowKind = 'none' | 'subtle' | 'soft' | 'hard';
|
|
8
11
|
export type BorderKind = 'solid' | 'dashed' | 'dotted';
|
|
@@ -17,9 +20,16 @@ export type HeaderPosition = 'beside' | 'above';
|
|
|
17
20
|
// either edge of the viewport
|
|
18
21
|
export type TimelinePosition = 'top' | 'bottom' | 'both';
|
|
19
22
|
export type StatusKind = 'planned' | 'in-progress' | 'done' | 'at-risk' | 'blocked' | 'neutral';
|
|
23
|
+
/**
|
|
24
|
+
* Which hatch stroke marks background work on a fill (specs/waves.md §9.3):
|
|
25
|
+
* `dark` (`wave.hatch`) on a light fill, `light` (`wave.hatchOnDark`) on a
|
|
26
|
+
* dark one.
|
|
27
|
+
*/
|
|
28
|
+
export type WaveHatchKind = 'dark' | 'light';
|
|
20
29
|
|
|
21
|
-
// The
|
|
22
|
-
//
|
|
30
|
+
// The style properties from specs/dsl.md § Style Properties, including the
|
|
31
|
+
// roadmap-only knobs (`header-height`, `header-position`, `timeline-position`,
|
|
32
|
+
// `minor-grid`, `non-working`).
|
|
23
33
|
// Every one has a concrete value after resolution (theme + defaults fill gaps).
|
|
24
34
|
export interface ResolvedStyle {
|
|
25
35
|
bg: string; // hex or 'none'
|
|
@@ -50,6 +60,12 @@ export interface ResolvedStyle {
|
|
|
50
60
|
capacityIcon: string;
|
|
51
61
|
timelinePosition: TimelinePosition;
|
|
52
62
|
minorGrid: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* How a calendar's non-working days are drawn (roadmap-only, from
|
|
65
|
+
* `default roadmap non-working:`). Default `'hide'`; a surface option
|
|
66
|
+
* overrides it (`LayoutOptions.nonWorking`).
|
|
67
|
+
*/
|
|
68
|
+
nonWorking: NonWorkingDisplay;
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
export interface BoundingBox {
|
|
@@ -90,8 +106,13 @@ export interface Point {
|
|
|
90
106
|
|
|
91
107
|
// Header + attribution mark + optional logo.
|
|
92
108
|
export interface PositionedLogo {
|
|
109
|
+
// Drawn box in canvas coordinates. Its aspect ratio matches the asset's,
|
|
110
|
+
// so the logo fills it exactly.
|
|
93
111
|
box: BoundingBox;
|
|
94
112
|
assetRef?: string; // path as declared in DSL; renderer resolves via AssetResolver
|
|
113
|
+
// The asset's own size (SVG width/height or viewBox, raster pixels),
|
|
114
|
+
// which the renderer scales from.
|
|
115
|
+
intrinsic?: { width: number; height: number };
|
|
95
116
|
}
|
|
96
117
|
|
|
97
118
|
export interface PositionedHeader {
|
|
@@ -110,6 +131,10 @@ export interface PositionedHeader {
|
|
|
110
131
|
// height grows for wrapped lines).
|
|
111
132
|
cardBox: BoundingBox;
|
|
112
133
|
logo?: PositionedLogo;
|
|
134
|
+
// Offset applied to every title and author line, set only when a logo
|
|
135
|
+
// shares the card: `x` clears the logo, `y` centers the text block
|
|
136
|
+
// when the logo made the card taller than the text needs.
|
|
137
|
+
textInset?: Point;
|
|
113
138
|
style: ResolvedStyle;
|
|
114
139
|
// Attribution mark (Nowline wordmark + link) lives in the top-right.
|
|
115
140
|
attributionBox: BoundingBox;
|
|
@@ -166,11 +191,107 @@ export interface PositionedTimelineScale {
|
|
|
166
191
|
// is purely a date reference for tall canvases.
|
|
167
192
|
bottomTickPanelY?: number;
|
|
168
193
|
bottomTickPanelHeight?: number;
|
|
194
|
+
/**
|
|
195
|
+
* The wave strip row (specs/waves.md §8.8): `WAVE_STRIP_HEIGHT_PX`
|
|
196
|
+
* high, directly under the top tick panel (under the now-pill row
|
|
197
|
+
* with `timeline-position:bottom`) and above the marker rows, which
|
|
198
|
+
* move down by its height. Present only when some declared wave has
|
|
199
|
+
* items (specs/waves.md §9.1); the mirrored bottom panel never has one.
|
|
200
|
+
*/
|
|
201
|
+
waveStrip?: {
|
|
202
|
+
y: number;
|
|
203
|
+
height: number;
|
|
204
|
+
};
|
|
169
205
|
// When `true`, the renderer draws a faint dotted line at every tick
|
|
170
206
|
// boundary (not just major ticks) using `theme.timeline.minorGridLine`.
|
|
171
207
|
// Mirrors the roadmap's resolved `minor-grid` style property. Default
|
|
172
208
|
// `false` preserves byte-stable output for existing roadmaps.
|
|
173
209
|
minorGrid: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* How the axis shows non-working days (specs/working-calendar.md §7):
|
|
212
|
+
* `hide` collapses them to zero width, `show` draws them at full width.
|
|
213
|
+
* Present, with `nonWorking`, only when the window holds a non-working
|
|
214
|
+
* day.
|
|
215
|
+
*/
|
|
216
|
+
nonWorkingDisplay?: NonWorkingDisplay;
|
|
217
|
+
/** The window's non-working runs, left to right; see `PositionedNonWorkingRun`. */
|
|
218
|
+
nonWorking?: PositionedNonWorkingRun[];
|
|
219
|
+
/**
|
|
220
|
+
* The window's labelled working exceptions, left to right; see
|
|
221
|
+
* `PositionedWorkingException`. Omitted when there are none.
|
|
222
|
+
*/
|
|
223
|
+
workingExceptions?: PositionedWorkingException[];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* One run of days that titled dated `working` rules turn from non-working
|
|
228
|
+
* to working (specs/working-calendar.md §7.4, §7.5). It is labelled in the
|
|
229
|
+
* marker row like a titled non-working run, but never drawn as a cut line
|
|
230
|
+
* or a band: a working day removes no time.
|
|
231
|
+
*/
|
|
232
|
+
export interface PositionedWorkingException {
|
|
233
|
+
/** The run's first day: its column start under `hide`, its day start under `show` (clamped to the window). */
|
|
234
|
+
x: number;
|
|
235
|
+
/** First day the rules turn (UTC midnight). */
|
|
236
|
+
from: Date;
|
|
237
|
+
/** Last day the rules turn, inclusive (UTC midnight). */
|
|
238
|
+
through: Date;
|
|
239
|
+
/** Titles of the titled dated working rules that turn a day of the run. */
|
|
240
|
+
titles: string[];
|
|
241
|
+
/** The titles joined with `, `, then ` · +Nd` for the N days turned. */
|
|
242
|
+
label: string;
|
|
243
|
+
/** Resolved placement of `label` in the marker row, like `PositionedNonWorkingRun.labelBox`. */
|
|
244
|
+
labelBox?: BoundingBox;
|
|
245
|
+
labelSide?: 'left' | 'right';
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* One maximal run of non-working days in (or straddling) the window
|
|
250
|
+
* (specs/working-calendar.md §7.5). Under `hide` its `width` is 0 and `x`
|
|
251
|
+
* is the start of the next working day. Under `show` it spans its days,
|
|
252
|
+
* with `x` and the right edge clamped to the window; `from` / `through`
|
|
253
|
+
* keep the run's real dates.
|
|
254
|
+
*/
|
|
255
|
+
export interface PositionedNonWorkingRun {
|
|
256
|
+
x: number;
|
|
257
|
+
width: number;
|
|
258
|
+
/** First non-working date of the run (UTC midnight). */
|
|
259
|
+
from: Date;
|
|
260
|
+
/** Last non-working date of the run, inclusive. */
|
|
261
|
+
through: Date;
|
|
262
|
+
/** Titles of the dated rules inside it; omitted for a plain weekend. */
|
|
263
|
+
titles?: string[];
|
|
264
|
+
/**
|
|
265
|
+
* The marker-row label of a titled run: its titles joined with `, `,
|
|
266
|
+
* then ` · Nd` for the N working days of the open-ended week the run
|
|
267
|
+
* closes (dropped when N is 0). Omitted on a run without titles.
|
|
268
|
+
*/
|
|
269
|
+
label?: string;
|
|
270
|
+
/**
|
|
271
|
+
* Resolved placement of `label` in the marker row, exactly like
|
|
272
|
+
* `PositionedMilestone.labelBox` / `labelSide`. Omitted on a run
|
|
273
|
+
* without titles.
|
|
274
|
+
*/
|
|
275
|
+
labelBox?: BoundingBox;
|
|
276
|
+
labelSide?: 'left' | 'right';
|
|
277
|
+
/**
|
|
278
|
+
* Set under `hide` on a titled run, at every scale: the renderer draws
|
|
279
|
+
* the named cut line at `x` from the label row down through the chart
|
|
280
|
+
* (spec §7.2, "a named seam always draws"). Independent of `seam`.
|
|
281
|
+
*/
|
|
282
|
+
cut?: true;
|
|
283
|
+
/**
|
|
284
|
+
* Set at the days scale when the run lies strictly inside the chart and
|
|
285
|
+
* no grid line is drawn at its x; the renderer draws a seam there.
|
|
286
|
+
* Never set under `show`.
|
|
287
|
+
*/
|
|
288
|
+
seam?: true;
|
|
289
|
+
/**
|
|
290
|
+
* Set under `show` at the days and weeks scales, or when the run has
|
|
291
|
+
* titles: the renderer paints the run as a shaded band. Coarser scales
|
|
292
|
+
* leave a plain weekend unpainted.
|
|
293
|
+
*/
|
|
294
|
+
band?: true;
|
|
174
295
|
}
|
|
175
296
|
|
|
176
297
|
/**
|
|
@@ -250,9 +371,56 @@ export interface InlineDatePin {
|
|
|
250
371
|
export interface PositionedItem {
|
|
251
372
|
kind: 'item';
|
|
252
373
|
id?: string;
|
|
374
|
+
/**
|
|
375
|
+
* The full, unwrapped title exactly as authored, explicit line breaks
|
|
376
|
+
* included (`"Technology\nSelection"` keeps its newline here). Always
|
|
377
|
+
* present, wrapped or not.
|
|
378
|
+
*/
|
|
253
379
|
title: string;
|
|
380
|
+
/**
|
|
381
|
+
* The title split into the lines the renderer paints, one `<text>` per
|
|
382
|
+
* line. Present when the painted lines differ from `[title]`:
|
|
383
|
+
*
|
|
384
|
+
* - the title word-wrapped INSIDE the bar (`length === 2`, at most
|
|
385
|
+
* `ITEM_CAPTION_TITLE_MAX_LINES`), or
|
|
386
|
+
* - the title carries explicit `\n` breaks (any `length >= 2`, in-bar
|
|
387
|
+
* or spilled to the right of the bar). Lines are trimmed, leading
|
|
388
|
+
* and trailing empty lines are dropped, interior empty lines stay as
|
|
389
|
+
* blank entries. An explicit title never auto-wraps.
|
|
390
|
+
*
|
|
391
|
+
* Omitted for a one-line title, and for a break-free title that spilled
|
|
392
|
+
* to the right (always one line), unless the caption cap at the chart's
|
|
393
|
+
* end truncated it (`titleTruncated`). Line `n` (0-based) sits at baseline
|
|
394
|
+
* `ITEM_CAPTION_TITLE_BASELINE_OFFSET_PX + n * ITEM_CAPTION_TITLE_LINE_HEIGHT_PX`
|
|
395
|
+
* from the bar's top, and the meta line follows at
|
|
396
|
+
* `itemCaptionMetaBaselineOffset(titleLines.length)`. A multi-line
|
|
397
|
+
* caption with a meta line grows the bar (`box.height`) by 16px per
|
|
398
|
+
* extra line.
|
|
399
|
+
*/
|
|
400
|
+
titleLines?: string[];
|
|
401
|
+
/**
|
|
402
|
+
* True when a spilled caption that would run past the axis end was
|
|
403
|
+
* capped at the overhang budget past it: `titleLines` carries the lines truncated
|
|
404
|
+
* with `…`, and the renderer gives the bar the full `title` as its
|
|
405
|
+
* `<title>` tooltip (specs/rendering.md § "Caption cap at the chart's
|
|
406
|
+
* end"). Omitted otherwise.
|
|
407
|
+
*/
|
|
408
|
+
titleTruncated?: true;
|
|
254
409
|
box: BoundingBox;
|
|
410
|
+
/**
|
|
411
|
+
* The item's dates in x: its scheduled start and end through the time
|
|
412
|
+
* scale. The bar (`box`) is drawn inside them, a seam in from each
|
|
413
|
+
* (specs/true-width-layout.md §3.1); dependency arrows and milestone
|
|
414
|
+
* slack lines read them (§3.4, §3.5).
|
|
415
|
+
*/
|
|
416
|
+
dateSpan: { startX: number; endX: number };
|
|
255
417
|
status: StatusKind;
|
|
418
|
+
/**
|
|
419
|
+
* The status dot's resolved colour: the theme's `statusDot.onLight` or
|
|
420
|
+
* `onDark` entry for `status`, picked by the luminance of `style.bg`
|
|
421
|
+
* (`statusDotColor` in `status-dot.ts`).
|
|
422
|
+
*/
|
|
423
|
+
statusDotColor: string;
|
|
256
424
|
progressFraction: number; // 0..1; 1 == fully filled
|
|
257
425
|
footnoteIndicators: number[]; // 1-based superscript numbers, empty when no footnotes
|
|
258
426
|
labelChips: PositionedLabelChip[];
|
|
@@ -286,12 +454,14 @@ export interface PositionedItem {
|
|
|
286
454
|
// renderer stays palette-and-string-dumb.
|
|
287
455
|
metaText?: string;
|
|
288
456
|
// True when the title OR the meta line is wider than the bar's inner
|
|
289
|
-
// padded width
|
|
457
|
+
// padded width AND a word-wrap of the title can't make it fit (see
|
|
458
|
+
// `titleLines`). We treat title + meta as an atomic block: if either
|
|
290
459
|
// one wouldn't fit inside the bar, BOTH get drawn beside the bar
|
|
291
460
|
// (stacked, just past its right edge) so they read as one caption
|
|
292
461
|
// rather than splitting across the bar boundary. The layout also
|
|
293
462
|
// bumps the next item to a fresh row so the spilled caption has
|
|
294
|
-
// empty space to occupy.
|
|
463
|
+
// empty space to occupy. A title that wrapped inside the bar has
|
|
464
|
+
// `textSpills === false` and reserves no spill extent.
|
|
295
465
|
textSpills: boolean;
|
|
296
466
|
/** True when the bar is too narrow to host the status dot inside
|
|
297
467
|
* with its full inset (`MIN_BAR_WIDTH_FOR_DOT_PX`). The dot
|
|
@@ -342,6 +512,32 @@ export interface PositionedItem {
|
|
|
342
512
|
*/
|
|
343
513
|
size: ResolvedSize | null;
|
|
344
514
|
style: ResolvedStyle;
|
|
515
|
+
/**
|
|
516
|
+
* Wave membership (specs/waves.md §8.7): `member` for an item with an
|
|
517
|
+
* effective wave, `background` for one without. Set on every item, in
|
|
518
|
+
* the main lanes and in isolated regions, when the roadmap declares
|
|
519
|
+
* waves; omitted otherwise.
|
|
520
|
+
*/
|
|
521
|
+
waveRole?: 'member' | 'background';
|
|
522
|
+
/**
|
|
523
|
+
* The hatch kind for the bar's fill (`waveHatchKind` in
|
|
524
|
+
* `wave-hatch.ts`). Set exactly on background items; omitted otherwise.
|
|
525
|
+
*/
|
|
526
|
+
waveHatch?: WaveHatchKind;
|
|
527
|
+
/**
|
|
528
|
+
* The hover tooltip line wave membership adds to the bar, localized
|
|
529
|
+
* (`Background (no wave)`; specs/waves.md §9.3). Set only on
|
|
530
|
+
* background items; omitted otherwise.
|
|
531
|
+
*/
|
|
532
|
+
waveTooltip?: string;
|
|
533
|
+
/**
|
|
534
|
+
* Present when the item's `after:DATE` pin falls on a non-working day
|
|
535
|
+
* and that pin set the start (NL.I1008, specs/working-calendar.md §6):
|
|
536
|
+
* `key` / `pin` are the pin as written, `start` the working day the
|
|
537
|
+
* item starts on (YYYY-MM-DD). Omitted when a later `after:` ref, the
|
|
538
|
+
* lane cursor or a wave floor set the start.
|
|
539
|
+
*/
|
|
540
|
+
nonWorkingPin?: { key: 'after'; pin: string; start: string };
|
|
345
541
|
}
|
|
346
542
|
|
|
347
543
|
/**
|
|
@@ -359,6 +555,15 @@ export interface PositionedCapacity {
|
|
|
359
555
|
text: string;
|
|
360
556
|
/** Resolved glyph instruction, or `null` when the icon is `'none'`. */
|
|
361
557
|
icon: ResolvedCapacityIconRef | null;
|
|
558
|
+
/**
|
|
559
|
+
* For a built-in SVG icon (person, people, points, time): the px terms
|
|
560
|
+
* that, added in order to the start x of the text run the suffix is
|
|
561
|
+
* painted in (the item caption x, or the lane badge x), give the icon's
|
|
562
|
+
* x, from `capacityIconDxTerms`. Kept apart so the sum rounds the same
|
|
563
|
+
* as adding each width to x in turn. Omitted for every other glyph,
|
|
564
|
+
* which paints inside the `<text>`.
|
|
565
|
+
*/
|
|
566
|
+
iconDxTerms?: readonly number[];
|
|
362
567
|
}
|
|
363
568
|
|
|
364
569
|
/**
|
|
@@ -384,20 +589,36 @@ export interface PositionedGroup {
|
|
|
384
589
|
kind: 'group';
|
|
385
590
|
id?: string;
|
|
386
591
|
title?: string;
|
|
592
|
+
/** The whole container: `box.y` is the header's top, `box.x` and
|
|
593
|
+
* `box.width` span exactly its children's dates
|
|
594
|
+
* (specs/true-width-layout.md §3.3). */
|
|
387
595
|
box: BoundingBox;
|
|
388
|
-
|
|
596
|
+
/** Header band height above the body (title, glyphs, bracket); 0 when
|
|
597
|
+
* there is no header. The body runs from `box.y + headerHeight` to the
|
|
598
|
+
* box's bottom. */
|
|
599
|
+
headerHeight: number;
|
|
389
600
|
children: PositionedTrackChild[];
|
|
390
601
|
/** Inline-date pins attached to this group (`after:DATE` / `before:DATE`).
|
|
391
602
|
* See `InlineDatePin` and specs/rendering.md "Inline-date glyph". */
|
|
392
603
|
inlineDatePins?: InlineDatePin[];
|
|
393
604
|
style: ResolvedStyle;
|
|
605
|
+
/**
|
|
606
|
+
* True for an untitled group with no `style:` and no `labels:` that
|
|
607
|
+
* carries `wave:`, in a roadmap with waves: it only assigns wave
|
|
608
|
+
* membership, so the renderer draws nothing for it (specs/waves.md §9.7).
|
|
609
|
+
* Omitted otherwise.
|
|
610
|
+
*/
|
|
611
|
+
waveOnly?: true;
|
|
394
612
|
}
|
|
395
613
|
|
|
396
614
|
export interface PositionedParallel {
|
|
397
615
|
kind: 'parallel';
|
|
398
616
|
id?: string;
|
|
399
617
|
title?: string;
|
|
618
|
+
/** The whole container, as `PositionedGroup.box`. */
|
|
400
619
|
box: BoundingBox;
|
|
620
|
+
/** Header band height above the body, as `PositionedGroup.headerHeight`. */
|
|
621
|
+
headerHeight: number;
|
|
401
622
|
children: PositionedTrackChild[]; // sub-tracks stacked vertically
|
|
402
623
|
/** Inline-date pins attached to this parallel (`after:DATE` / `before:DATE`).
|
|
403
624
|
* See `InlineDatePin` and specs/rendering.md "Inline-date glyph". */
|
|
@@ -416,8 +637,15 @@ export interface PositionedSwimlane {
|
|
|
416
637
|
nested: PositionedSwimlane[]; // recursive sub-swimlanes
|
|
417
638
|
style: ResolvedStyle;
|
|
418
639
|
// Owner display string ("Platform Team", "Sam Chen") rendered inside
|
|
419
|
-
// the frame tab. Resolved from team/person id → title
|
|
640
|
+
// the frame tab. Resolved from team/person id → title (nested teams
|
|
641
|
+
// included); the bare id when it names neither.
|
|
420
642
|
owner?: string;
|
|
643
|
+
/**
|
|
644
|
+
* What `owner` names, for the glyph that leads it in the frame tab:
|
|
645
|
+
* `person` for a declared person, `team` otherwise (a team, or an id
|
|
646
|
+
* that names neither). Set exactly when `owner` is.
|
|
647
|
+
*/
|
|
648
|
+
ownerKind?: 'person' | 'team';
|
|
421
649
|
// Footnote indicator numbers attached to this swimlane (via `on:` in the
|
|
422
650
|
// footnote declaration). Rendered in the upper-right of the frame tab.
|
|
423
651
|
footnoteIndicators: number[];
|
|
@@ -434,6 +662,13 @@ export interface PositionedSwimlane {
|
|
|
434
662
|
* want the badge fully hidden simply omit `capacity:`.
|
|
435
663
|
*/
|
|
436
664
|
capacity: PositionedCapacity | null;
|
|
665
|
+
/**
|
|
666
|
+
* The frame tab's geometry, from `frameTabGeometry` with the lane's
|
|
667
|
+
* box x, its title, the owner display title and the capacity badge and
|
|
668
|
+
* footnote-indicator widths. Layout sizes the tab's collision box from
|
|
669
|
+
* it and the renderer draws it as is. Null when the lane has no title.
|
|
670
|
+
*/
|
|
671
|
+
tab: FrameTabGeometry | null;
|
|
437
672
|
/**
|
|
438
673
|
* Tri-state utilization underline data when the lane declares
|
|
439
674
|
* `capacity:` AND has at least one item contributing load AND has not
|
|
@@ -512,6 +747,12 @@ export interface PositionedAnchor {
|
|
|
512
747
|
// (start-anchored text) — no further geometry decisions.
|
|
513
748
|
labelBox: BoundingBox;
|
|
514
749
|
labelSide: 'left' | 'right';
|
|
750
|
+
/**
|
|
751
|
+
* The anchor's `date:` (YYYY-MM-DD) when it falls on a non-working day
|
|
752
|
+
* the axis hides; the renderer surfaces it as a `<title>`. Omitted on a
|
|
753
|
+
* working day and under a calendar with no non-working days.
|
|
754
|
+
*/
|
|
755
|
+
hiddenDate?: string;
|
|
515
756
|
}
|
|
516
757
|
|
|
517
758
|
export interface PositionedMilestone {
|
|
@@ -526,6 +767,16 @@ export interface PositionedMilestone {
|
|
|
526
767
|
// milestone has zero or one predecessor.
|
|
527
768
|
slackArrows?: Array<{ x: number; y: number }>;
|
|
528
769
|
isOverrun: boolean; // true when the aggregated predecessor end exceeds `date:`
|
|
770
|
+
/**
|
|
771
|
+
* Where an overrun dated milestone actually lands: the end of its
|
|
772
|
+
* latest predecessor or overrunning wave. `center` stays on the
|
|
773
|
+
* planned date; the renderer draws that diamond in the overrun colour,
|
|
774
|
+
* a dotted span on the same row to a second diamond at `slip.x`, and
|
|
775
|
+
* puts the label and the cut line there (specs/rendering.md,
|
|
776
|
+
* Milestones). Omitted when the milestone does not overrun, or when
|
|
777
|
+
* the two diamonds would meet.
|
|
778
|
+
*/
|
|
779
|
+
slip?: { x: number };
|
|
529
780
|
style: ResolvedStyle;
|
|
530
781
|
// Vertical span of the milestone's cut line through the swimlane area.
|
|
531
782
|
cutTopY: number;
|
|
@@ -533,6 +784,31 @@ export interface PositionedMilestone {
|
|
|
533
784
|
// See PositionedAnchor.labelBox — same packing logic applies.
|
|
534
785
|
labelBox: BoundingBox;
|
|
535
786
|
labelSide: 'left' | 'right';
|
|
787
|
+
/**
|
|
788
|
+
* True when the diamond sits on a wave boundary (within 0.5 px of any
|
|
789
|
+
* `S_k` or `E_k` other than the origin; specs/waves.md §9.2). The
|
|
790
|
+
* boundary line carries the vertical, so the cut line is not drawn.
|
|
791
|
+
* Omitted when false and when the roadmap has no waves.
|
|
792
|
+
*/
|
|
793
|
+
onWaveBoundary?: boolean;
|
|
794
|
+
/**
|
|
795
|
+
* The wave that runs past this dated milestone: its `after:` lists the
|
|
796
|
+
* wave and the wave's end `E_k` lies past `date:` (NL.I1007). The
|
|
797
|
+
* latest-ending such wave; omitted when none.
|
|
798
|
+
*/
|
|
799
|
+
overrunByWave?: string;
|
|
800
|
+
/**
|
|
801
|
+
* The milestone's own `date:` (YYYY-MM-DD), set together with
|
|
802
|
+
* `overrunByWave`, so NL.I1007 never reads the date back off x.
|
|
803
|
+
*/
|
|
804
|
+
overrunDate?: string;
|
|
805
|
+
/**
|
|
806
|
+
* The milestone's `date:` (YYYY-MM-DD) when it falls on a non-working
|
|
807
|
+
* day the axis hides; the renderer surfaces it as a `<title>`. Omitted
|
|
808
|
+
* on a working day, for after-only milestones, and under a calendar
|
|
809
|
+
* with no non-working days.
|
|
810
|
+
*/
|
|
811
|
+
hiddenDate?: string;
|
|
536
812
|
}
|
|
537
813
|
|
|
538
814
|
/**
|
|
@@ -559,7 +835,7 @@ export interface MarkerRowPlacement {
|
|
|
559
835
|
export interface SlackCorridor {
|
|
560
836
|
xStart: number; // slack pred's right edge (logical chart x)
|
|
561
837
|
xEnd: number; // binding pred's right edge / milestone center.x
|
|
562
|
-
y: number; // slack pred's
|
|
838
|
+
y: number; // slack pred's slack-arrow attach y, in the chart's local frame
|
|
563
839
|
slackPredId: string; // exempt from bumping (owns the arrow's origin)
|
|
564
840
|
milestoneId: string;
|
|
565
841
|
}
|
|
@@ -567,19 +843,23 @@ export interface SlackCorridor {
|
|
|
567
843
|
export interface PositionedDependencyEdge {
|
|
568
844
|
fromId: string;
|
|
569
845
|
toId: string;
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
846
|
+
/**
|
|
847
|
+
* Orthogonal path on the dates (specs/true-width-layout.md §3.4): first
|
|
848
|
+
* = source port, last = target port, where the arrowhead's tip lands.
|
|
849
|
+
* Item and container sources route vertical, horizontal (in a gap
|
|
850
|
+
* between rows), vertical; a target on its source's row and a marker
|
|
851
|
+
* stub are one horizontal leg.
|
|
852
|
+
*/
|
|
853
|
+
waypoints: Point[];
|
|
854
|
+
/** The target waits on its source: the horizontal legs are dotted. */
|
|
855
|
+
slack: boolean;
|
|
856
|
+
/**
|
|
857
|
+
* Arrowhead width across its leg, scaled down to the target's width;
|
|
858
|
+
* a target narrower than `ARROW_HEAD_MIN_PX` gets a dot that wide
|
|
859
|
+
* (`head: 'dot'`) instead (§8 O6).
|
|
860
|
+
*/
|
|
861
|
+
headWidth: number;
|
|
862
|
+
head: 'arrow' | 'dot';
|
|
583
863
|
style: ResolvedStyle;
|
|
584
864
|
}
|
|
585
865
|
|
|
@@ -597,12 +877,40 @@ export interface PositionedFootnoteArea {
|
|
|
597
877
|
}
|
|
598
878
|
|
|
599
879
|
export interface PositionedFootnoteEntry {
|
|
880
|
+
/**
|
|
881
|
+
* The title of the isolated region the footnote comes from; the
|
|
882
|
+
* renderer heads each region's run of entries with it. Omitted on the
|
|
883
|
+
* host's own footnotes.
|
|
884
|
+
*/
|
|
885
|
+
region?: string;
|
|
886
|
+
/**
|
|
887
|
+
* Baseline of the region's heading row, on the first entry of each
|
|
888
|
+
* region's run only.
|
|
889
|
+
*/
|
|
890
|
+
regionHeadingY?: number;
|
|
600
891
|
number: number;
|
|
892
|
+
/** Baseline of the entry's first row, where its number sits. */
|
|
893
|
+
y: number;
|
|
601
894
|
title: string;
|
|
895
|
+
/** The title's rows: one unless it is wider than the panel. */
|
|
896
|
+
titleLines: PositionedFootnoteLine[];
|
|
602
897
|
description?: string;
|
|
898
|
+
/**
|
|
899
|
+
* The description's rows, the first led by `— `: beside the title when
|
|
900
|
+
* its first word fits there, the rest wrapped at the title's x. Omitted
|
|
901
|
+
* when the footnote has no description.
|
|
902
|
+
*/
|
|
903
|
+
descriptionLines?: PositionedFootnoteLine[];
|
|
603
904
|
style: ResolvedStyle;
|
|
604
905
|
}
|
|
605
906
|
|
|
907
|
+
/** One row of footnote text, at its baseline. */
|
|
908
|
+
export interface PositionedFootnoteLine {
|
|
909
|
+
x: number;
|
|
910
|
+
y: number;
|
|
911
|
+
text: string;
|
|
912
|
+
}
|
|
913
|
+
|
|
606
914
|
export interface PositionedIncludeRegion {
|
|
607
915
|
sourcePath: string; // relative to the parent file
|
|
608
916
|
label: string; // e.g. the child roadmap's title or basename
|
|
@@ -612,6 +920,193 @@ export interface PositionedIncludeRegion {
|
|
|
612
920
|
// tick row above the region.
|
|
613
921
|
nestedSwimlanes: PositionedSwimlane[];
|
|
614
922
|
style: ResolvedStyle;
|
|
923
|
+
/**
|
|
924
|
+
* Wave crossings over this region's background bars (specs/waves.md
|
|
925
|
+
* §9.3, §9.8), re-emitted inside the region because its opaque fill
|
|
926
|
+
* hides the global layers. Omitted when there are none.
|
|
927
|
+
*/
|
|
928
|
+
waveCrossings?: PositionedWaveCrossing[];
|
|
929
|
+
/**
|
|
930
|
+
* The region's own anchors and milestones, in its own marker row
|
|
931
|
+
* under the label tab; their cut lines stop at its last lane. Omitted
|
|
932
|
+
* when it has none to draw.
|
|
933
|
+
*/
|
|
934
|
+
anchors?: PositionedAnchor[];
|
|
935
|
+
milestones?: PositionedMilestone[];
|
|
936
|
+
/**
|
|
937
|
+
* The region's own dependency edges, routed among its lanes. Omitted
|
|
938
|
+
* when it has none.
|
|
939
|
+
*/
|
|
940
|
+
edges?: PositionedDependencyEdge[];
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* One wave's solved span (specs/waves.md §5.1, §8.7), in declaration order.
|
|
945
|
+
* Only present in a roadmap that declares waves.
|
|
946
|
+
*/
|
|
947
|
+
export interface PositionedWave {
|
|
948
|
+
id: string;
|
|
949
|
+
/** The wave's title, else its id. */
|
|
950
|
+
title: string;
|
|
951
|
+
/** 0-based declaration order. */
|
|
952
|
+
index: number;
|
|
953
|
+
/** `S_k` in logical px. */
|
|
954
|
+
startX: number;
|
|
955
|
+
/** `E_k` in logical px; equals `startX` for an empty wave. */
|
|
956
|
+
endX: number;
|
|
957
|
+
/** `S_k` as a whole UTC day. */
|
|
958
|
+
startDate: Date;
|
|
959
|
+
/** `E_k` as a whole UTC day, exclusive. */
|
|
960
|
+
endDate: Date;
|
|
961
|
+
/** Members placed in the main lanes and first-level isolated regions. */
|
|
962
|
+
memberCount: number;
|
|
963
|
+
/** True when the wave has no members (it spans no time). */
|
|
964
|
+
empty: boolean;
|
|
965
|
+
/**
|
|
966
|
+
* The member that sets `E_k` (its id, else its title). Omitted when no
|
|
967
|
+
* member's end equals `E_k` with `E_k > S_k` (§5.1 "Held by").
|
|
968
|
+
*/
|
|
969
|
+
heldBy?: string;
|
|
970
|
+
/** The wave's `after:` value that set `S_k`, when it beat `E_{k-1}`. */
|
|
971
|
+
floorRef?: string;
|
|
972
|
+
/**
|
|
973
|
+
* 0-based position among the non-empty waves; drives the strip-cell
|
|
974
|
+
* alternation (even: `wave.stripFill`, odd: `wave.stripFillAlt`), so
|
|
975
|
+
* empty waves and gaps never break it. Omitted for an empty wave.
|
|
976
|
+
*/
|
|
977
|
+
visibleOrdinal?: number;
|
|
978
|
+
/** The wave's column: `startX..endX` × `chartTopY..swimlaneBottomY`. */
|
|
979
|
+
columnBox: BoundingBox;
|
|
980
|
+
/** The wave's strip cell (specs/waves.md §9.1). */
|
|
981
|
+
strip: PositionedWaveStrip;
|
|
982
|
+
/** Resolved colours (specs/waves.md §9.4). */
|
|
983
|
+
style: PositionedWaveStyle;
|
|
984
|
+
/** 1-based numbers of the footnotes whose `on:` names this wave, ascending. */
|
|
985
|
+
footnoteIndicators: number[];
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/** One wave's strip cell (specs/waves.md §9.1). */
|
|
989
|
+
export interface PositionedWaveStrip {
|
|
990
|
+
/** `startX..endX` at `waveStrip.y`; zero width for an empty wave. */
|
|
991
|
+
box: BoundingBox;
|
|
992
|
+
/** The label text; omitted when `labelKind` is `none`. */
|
|
993
|
+
label?: string;
|
|
994
|
+
/**
|
|
995
|
+
* The painted cell: `box` clipped to the timeline's backing panel and
|
|
996
|
+
* inset by `WAVE_CELL_INSET_PX` (half the panel's stroke) so it never
|
|
997
|
+
* covers the panel border. Omitted for an empty wave and for one that
|
|
998
|
+
* lies outside the timeline.
|
|
999
|
+
*/
|
|
1000
|
+
cell?: BoundingBox;
|
|
1001
|
+
/**
|
|
1002
|
+
* Where the label is drawn when the wave has a `cell`: `x` is the text
|
|
1003
|
+
* centre (`labelX`, moved left when the superscripts would cover it)
|
|
1004
|
+
* and `halo` the backing box in the cell's fill. Omitted when there is
|
|
1005
|
+
* no label or no cell.
|
|
1006
|
+
*/
|
|
1007
|
+
labelDraw?: { x: number; halo: BoundingBox };
|
|
1008
|
+
/**
|
|
1009
|
+
* The calendar glyph for a declared date floor (`wave launch after:2026-11-02`),
|
|
1010
|
+
* at the cell's left, vertically centred in the strip, whether or not the
|
|
1011
|
+
* floor opened a gap. The label clears it. Omitted when the wave has no
|
|
1012
|
+
* date floor, no `cell`, or the cell is too narrow to host it.
|
|
1013
|
+
*/
|
|
1014
|
+
inlineDatePin?: InlineDatePin;
|
|
1015
|
+
/**
|
|
1016
|
+
* The footnote superscripts when `footnotesShown` and the wave has a
|
|
1017
|
+
* `cell`: `rightX` is the last superscript's right edge (they walk left
|
|
1018
|
+
* by `ITEM_FOOTNOTE_INDICATOR_STEP_PX`, end-anchored) and `halo` their
|
|
1019
|
+
* backing box. Omitted otherwise.
|
|
1020
|
+
*/
|
|
1021
|
+
superscripts?: { rightX: number; halo: BoundingBox };
|
|
1022
|
+
/**
|
|
1023
|
+
* Which step of the fit chain won: the title, the id, the title
|
|
1024
|
+
* ellipsized to 3 or more characters plus "…", the 1-based `#k`, or
|
|
1025
|
+
* no label. Always `none` for an empty wave (it has no cell).
|
|
1026
|
+
*/
|
|
1027
|
+
labelKind: 'title' | 'id' | 'ellipsis' | 'ordinal' | 'none';
|
|
1028
|
+
/**
|
|
1029
|
+
* Centre of the visible part of the span (clipped to the timeline);
|
|
1030
|
+
* `startX` for an empty wave, which is not drawn.
|
|
1031
|
+
*/
|
|
1032
|
+
labelX: number;
|
|
1033
|
+
/**
|
|
1034
|
+
* The cell's hover text, e.g. `Launch · 2026-02-02 – 2026-02-23 · held
|
|
1035
|
+
* by i2` (end exclusive). An empty wave reads `title · date · no items`.
|
|
1036
|
+
*/
|
|
1037
|
+
tooltip: string;
|
|
1038
|
+
/**
|
|
1039
|
+
* True when `footnoteIndicators` are drawn right-aligned in the cell;
|
|
1040
|
+
* false when there are none or they did not fit (they are then not
|
|
1041
|
+
* drawn; the footnote panel still lists the footnote).
|
|
1042
|
+
*/
|
|
1043
|
+
footnotesShown: boolean;
|
|
1044
|
+
/**
|
|
1045
|
+
* The floor reference (`fy-budget`, `2026-02-02`) centred in the gap
|
|
1046
|
+
* this wave's start floor opened before it (`S_k > E_{k-1}`, k >= 2),
|
|
1047
|
+
* when it fits; drawn in muted italics. `halo` is its backing box in the
|
|
1048
|
+
* panel's fill, sized from the text's estimated width at 10 px (the one
|
|
1049
|
+
* its fit was tested at). Omitted otherwise.
|
|
1050
|
+
*/
|
|
1051
|
+
gapLabel?: { text: string; x: number; halo: BoundingBox };
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/** A wave's resolved colours (specs/waves.md §9.4). */
|
|
1055
|
+
export interface PositionedWaveStyle {
|
|
1056
|
+
/** The style's `bg`: the column tint and the strip-cell overlay. Omitted when unset. */
|
|
1057
|
+
tint?: string;
|
|
1058
|
+
/** The cell's base fill by `visibleOrdinal` parity. */
|
|
1059
|
+
stripFill: string;
|
|
1060
|
+
/** Label colour: the style's `text`, else `wave.labelText`, else a dark or light pick at 4.5:1. */
|
|
1061
|
+
text: string;
|
|
1062
|
+
/** Boundary colour: the style's `fg`, else `wave.boundary`. */
|
|
1063
|
+
boundary: string;
|
|
1064
|
+
/** `4 2` for `border:dashed`, `1 2` for `dotted`, null for solid. */
|
|
1065
|
+
boundaryDash: string | null;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* One wave boundary line (specs/waves.md §9.2), at a distinct x in
|
|
1070
|
+
* `{S_k} ∪ {E_k}` of the non-empty waves other than the origin. It runs
|
|
1071
|
+
* from the top of the strip down to `swimlaneBottomY`.
|
|
1072
|
+
*/
|
|
1073
|
+
export interface PositionedWaveBoundary {
|
|
1074
|
+
x: number;
|
|
1075
|
+
topY: number;
|
|
1076
|
+
bottomY: number;
|
|
1077
|
+
stroke: string;
|
|
1078
|
+
dash: string | null;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* A boundary drawn over a background bar whose visual extent strictly
|
|
1083
|
+
* contains it (specs/waves.md §9.3), from the bar's top to its bottom.
|
|
1084
|
+
*/
|
|
1085
|
+
export interface PositionedWaveCrossing {
|
|
1086
|
+
x: number;
|
|
1087
|
+
topY: number;
|
|
1088
|
+
bottomY: number;
|
|
1089
|
+
stroke: string;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/** One legend entry (specs/waves.md §9.5). */
|
|
1093
|
+
export interface WaveLegendEntry {
|
|
1094
|
+
/** The hatch swatch for background work, the legend's only entry. */
|
|
1095
|
+
kind: 'background';
|
|
1096
|
+
/** The entry's full text. */
|
|
1097
|
+
text: string;
|
|
1098
|
+
/** The swatch box: a hatched bar. */
|
|
1099
|
+
swatch: BoundingBox;
|
|
1100
|
+
/** The swatch's hatch kind, a default item bar's fill. */
|
|
1101
|
+
hatch: WaveHatchKind;
|
|
1102
|
+
/** The text, one run on the swatch's line. `y` is the text baseline. */
|
|
1103
|
+
runs: Array<{ text: string; x: number; y: number }>;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/** The wave legend below the chart (specs/waves.md §9.5). */
|
|
1107
|
+
export interface PositionedWaveLegend {
|
|
1108
|
+
box: BoundingBox;
|
|
1109
|
+
entries: WaveLegendEntry[];
|
|
615
1110
|
}
|
|
616
1111
|
|
|
617
1112
|
// Top-level result handed to the renderer.
|
|
@@ -638,4 +1133,18 @@ export interface PositionedRoadmap {
|
|
|
638
1133
|
includes: PositionedIncludeRegion[];
|
|
639
1134
|
// Frame (chart area) in chart-space. Useful for renderer overlays.
|
|
640
1135
|
chartBox: BoundingBox;
|
|
1136
|
+
/**
|
|
1137
|
+
* The wave barrier driver's result (specs/waves.md §8.7): the passes it
|
|
1138
|
+
* ran and whether it hit the `n + 1` cap (NL.W1002, invalid input).
|
|
1139
|
+
* Present only when the roadmap declares waves.
|
|
1140
|
+
*/
|
|
1141
|
+
waveSolve?: { passes: number; capped: boolean };
|
|
1142
|
+
/** The waves in declaration order; present only when the roadmap declares waves. */
|
|
1143
|
+
waves?: PositionedWave[];
|
|
1144
|
+
/** Wave boundary lines, left to right; omitted when there are none. */
|
|
1145
|
+
waveBoundaries?: PositionedWaveBoundary[];
|
|
1146
|
+
/** Crossings over the main lanes' background bars; omitted when there are none. */
|
|
1147
|
+
waveCrossings?: PositionedWaveCrossing[];
|
|
1148
|
+
/** The wave legend; present only when one of its triggers holds (§9.5). */
|
|
1149
|
+
waveLegend?: PositionedWaveLegend;
|
|
641
1150
|
}
|