@nowline/layout 0.2.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 (183) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +103 -0
  3. package/dist/band-scale.d.ts +56 -0
  4. package/dist/band-scale.d.ts.map +1 -0
  5. package/dist/band-scale.js +86 -0
  6. package/dist/band-scale.js.map +1 -0
  7. package/dist/calendar.d.ts +79 -0
  8. package/dist/calendar.d.ts.map +1 -0
  9. package/dist/calendar.js +210 -0
  10. package/dist/calendar.js.map +1 -0
  11. package/dist/capacity.d.ts +72 -0
  12. package/dist/capacity.d.ts.map +1 -0
  13. package/dist/capacity.js +163 -0
  14. package/dist/capacity.js.map +1 -0
  15. package/dist/dsl-utils.d.ts +5 -0
  16. package/dist/dsl-utils.d.ts.map +1 -0
  17. package/dist/dsl-utils.js +28 -0
  18. package/dist/dsl-utils.js.map +1 -0
  19. package/dist/edge-routing.d.ts +89 -0
  20. package/dist/edge-routing.d.ts.map +1 -0
  21. package/dist/edge-routing.js +435 -0
  22. package/dist/edge-routing.js.map +1 -0
  23. package/dist/frame-tab-geometry.d.ts +78 -0
  24. package/dist/frame-tab-geometry.d.ts.map +1 -0
  25. package/dist/frame-tab-geometry.js +115 -0
  26. package/dist/frame-tab-geometry.js.map +1 -0
  27. package/dist/header-card-geometry.d.ts +29 -0
  28. package/dist/header-card-geometry.d.ts.map +1 -0
  29. package/dist/header-card-geometry.js +41 -0
  30. package/dist/header-card-geometry.js.map +1 -0
  31. package/dist/i18n.d.ts +48 -0
  32. package/dist/i18n.d.ts.map +1 -0
  33. package/dist/i18n.js +114 -0
  34. package/dist/i18n.js.map +1 -0
  35. package/dist/include-chrome-geometry.d.ts +86 -0
  36. package/dist/include-chrome-geometry.d.ts.map +1 -0
  37. package/dist/include-chrome-geometry.js +104 -0
  38. package/dist/include-chrome-geometry.js.map +1 -0
  39. package/dist/index.d.ts +11 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +10 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/item-bar-geometry.d.ts +127 -0
  44. package/dist/item-bar-geometry.d.ts.map +1 -0
  45. package/dist/item-bar-geometry.js +173 -0
  46. package/dist/item-bar-geometry.js.map +1 -0
  47. package/dist/lane-utilization.d.ts +90 -0
  48. package/dist/lane-utilization.d.ts.map +1 -0
  49. package/dist/lane-utilization.js +206 -0
  50. package/dist/lane-utilization.js.map +1 -0
  51. package/dist/layout-context.d.ts +143 -0
  52. package/dist/layout-context.d.ts.map +1 -0
  53. package/dist/layout-context.js +8 -0
  54. package/dist/layout-context.js.map +1 -0
  55. package/dist/layout.d.ts +18 -0
  56. package/dist/layout.d.ts.map +1 -0
  57. package/dist/layout.js +1213 -0
  58. package/dist/layout.js.map +1 -0
  59. package/dist/nodes/anchor-node.d.ts +16 -0
  60. package/dist/nodes/anchor-node.d.ts.map +1 -0
  61. package/dist/nodes/anchor-node.js +68 -0
  62. package/dist/nodes/anchor-node.js.map +1 -0
  63. package/dist/nodes/footnote-node.d.ts +10 -0
  64. package/dist/nodes/footnote-node.d.ts.map +1 -0
  65. package/dist/nodes/footnote-node.js +41 -0
  66. package/dist/nodes/footnote-node.js.map +1 -0
  67. package/dist/nodes/group-node.d.ts +29 -0
  68. package/dist/nodes/group-node.d.ts.map +1 -0
  69. package/dist/nodes/group-node.js +187 -0
  70. package/dist/nodes/group-node.js.map +1 -0
  71. package/dist/nodes/include-node.d.ts +16 -0
  72. package/dist/nodes/include-node.d.ts.map +1 -0
  73. package/dist/nodes/include-node.js +117 -0
  74. package/dist/nodes/include-node.js.map +1 -0
  75. package/dist/nodes/item-node.d.ts +51 -0
  76. package/dist/nodes/item-node.d.ts.map +1 -0
  77. package/dist/nodes/item-node.js +108 -0
  78. package/dist/nodes/item-node.js.map +1 -0
  79. package/dist/nodes/marker-geometry.d.ts +22 -0
  80. package/dist/nodes/marker-geometry.d.ts.map +1 -0
  81. package/dist/nodes/marker-geometry.js +38 -0
  82. package/dist/nodes/marker-geometry.js.map +1 -0
  83. package/dist/nodes/milestone-node.d.ts +48 -0
  84. package/dist/nodes/milestone-node.d.ts.map +1 -0
  85. package/dist/nodes/milestone-node.js +210 -0
  86. package/dist/nodes/milestone-node.js.map +1 -0
  87. package/dist/nodes/parallel-node.d.ts +21 -0
  88. package/dist/nodes/parallel-node.d.ts.map +1 -0
  89. package/dist/nodes/parallel-node.js +80 -0
  90. package/dist/nodes/parallel-node.js.map +1 -0
  91. package/dist/nodes/roadmap-node.d.ts +76 -0
  92. package/dist/nodes/roadmap-node.d.ts.map +1 -0
  93. package/dist/nodes/roadmap-node.js +788 -0
  94. package/dist/nodes/roadmap-node.js.map +1 -0
  95. package/dist/nodes/swimlane-node.d.ts +38 -0
  96. package/dist/nodes/swimlane-node.d.ts.map +1 -0
  97. package/dist/nodes/swimlane-node.js +308 -0
  98. package/dist/nodes/swimlane-node.js.map +1 -0
  99. package/dist/renderable.d.ts +44 -0
  100. package/dist/renderable.d.ts.map +1 -0
  101. package/dist/renderable.js +21 -0
  102. package/dist/renderable.js.map +1 -0
  103. package/dist/row-packer.d.ts +125 -0
  104. package/dist/row-packer.d.ts.map +1 -0
  105. package/dist/row-packer.js +169 -0
  106. package/dist/row-packer.js.map +1 -0
  107. package/dist/style-resolution.d.ts +14 -0
  108. package/dist/style-resolution.d.ts.map +1 -0
  109. package/dist/style-resolution.js +191 -0
  110. package/dist/style-resolution.js.map +1 -0
  111. package/dist/themes/dark.d.ts +4 -0
  112. package/dist/themes/dark.d.ts.map +1 -0
  113. package/dist/themes/dark.js +241 -0
  114. package/dist/themes/dark.js.map +1 -0
  115. package/dist/themes/index.d.ts +15 -0
  116. package/dist/themes/index.d.ts.map +1 -0
  117. package/dist/themes/index.js +30 -0
  118. package/dist/themes/index.js.map +1 -0
  119. package/dist/themes/light.d.ts +4 -0
  120. package/dist/themes/light.d.ts.map +1 -0
  121. package/dist/themes/light.js +248 -0
  122. package/dist/themes/light.js.map +1 -0
  123. package/dist/themes/shape.d.ts +194 -0
  124. package/dist/themes/shape.d.ts.map +1 -0
  125. package/dist/themes/shape.js +6 -0
  126. package/dist/themes/shape.js.map +1 -0
  127. package/dist/themes/shared.d.ts +145 -0
  128. package/dist/themes/shared.d.ts.map +1 -0
  129. package/dist/themes/shared.js +310 -0
  130. package/dist/themes/shared.js.map +1 -0
  131. package/dist/time-scale.d.ts +39 -0
  132. package/dist/time-scale.d.ts.map +1 -0
  133. package/dist/time-scale.js +62 -0
  134. package/dist/time-scale.js.map +1 -0
  135. package/dist/types.d.ts +483 -0
  136. package/dist/types.d.ts.map +1 -0
  137. package/dist/types.js +6 -0
  138. package/dist/types.js.map +1 -0
  139. package/dist/view-preset.d.ts +23 -0
  140. package/dist/view-preset.d.ts.map +1 -0
  141. package/dist/view-preset.js +146 -0
  142. package/dist/view-preset.js.map +1 -0
  143. package/dist/working-calendar.d.ts +14 -0
  144. package/dist/working-calendar.d.ts.map +1 -0
  145. package/dist/working-calendar.js +74 -0
  146. package/dist/working-calendar.js.map +1 -0
  147. package/package.json +37 -0
  148. package/src/band-scale.ts +115 -0
  149. package/src/calendar.ts +244 -0
  150. package/src/capacity.ts +191 -0
  151. package/src/dsl-utils.ts +30 -0
  152. package/src/edge-routing.ts +550 -0
  153. package/src/frame-tab-geometry.ts +165 -0
  154. package/src/header-card-geometry.ts +48 -0
  155. package/src/i18n.ts +124 -0
  156. package/src/include-chrome-geometry.ts +156 -0
  157. package/src/index.ts +116 -0
  158. package/src/item-bar-geometry.ts +222 -0
  159. package/src/lane-utilization.ts +259 -0
  160. package/src/layout-context.ts +182 -0
  161. package/src/layout.ts +1446 -0
  162. package/src/nodes/anchor-node.ts +77 -0
  163. package/src/nodes/footnote-node.ts +60 -0
  164. package/src/nodes/group-node.ts +252 -0
  165. package/src/nodes/include-node.ts +168 -0
  166. package/src/nodes/item-node.ts +171 -0
  167. package/src/nodes/marker-geometry.ts +43 -0
  168. package/src/nodes/milestone-node.ts +263 -0
  169. package/src/nodes/parallel-node.ts +101 -0
  170. package/src/nodes/roadmap-node.ts +957 -0
  171. package/src/nodes/swimlane-node.ts +423 -0
  172. package/src/renderable.ts +68 -0
  173. package/src/row-packer.ts +271 -0
  174. package/src/style-resolution.ts +243 -0
  175. package/src/themes/dark.ts +244 -0
  176. package/src/themes/index.ts +36 -0
  177. package/src/themes/light.ts +251 -0
  178. package/src/themes/shape.ts +230 -0
  179. package/src/themes/shared.ts +369 -0
  180. package/src/time-scale.ts +78 -0
  181. package/src/types.ts +607 -0
  182. package/src/view-preset.ts +180 -0
  183. package/src/working-calendar.ts +91 -0
@@ -0,0 +1,145 @@
1
+ export declare const SPACING_PX: Record<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl', number>;
2
+ export declare const PADDING_PX: Record<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl', number>;
3
+ export declare const HEADER_HEIGHT_PX: Record<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl', number>;
4
+ export declare const TEXT_SIZE_PX: Record<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl', number>;
5
+ export declare const CORNER_RADIUS_PX: Record<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full', number>;
6
+ export declare const LOGO_SIZE_PX: Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', number>;
7
+ export declare const MIN_ITEM_WIDTH = 8;
8
+ export declare const PROGRESS_STRIP_HEIGHT_PX = 4;
9
+ export declare const TIMELINE_TICK_PANEL_HEIGHT_PX = 24;
10
+ /**
11
+ * Baseline Y of the tick-label text relative to the tick panel's top.
12
+ * Approximately vertically centers a 10 pt label in the panel.
13
+ */
14
+ export declare const TIMELINE_TICK_LABEL_BASELINE_OFFSET_PX = 15;
15
+ /**
16
+ * Horizontal breathing room (px) added to a track-block's right edge
17
+ * after sequencing. Applied to `group { ... }` and `parallel { ... }`
18
+ * blocks so successive blocks don't crowd each other. Items butt up
19
+ * against their neighbors (no gutter) — only block boundaries get this
20
+ * gutter.
21
+ */
22
+ export declare const TRACK_BLOCK_TAIL_GUTTER_PX = 8;
23
+ /** Height (px) of the frame-tab chiclet (swimlane + include region). */
24
+ export declare const FRAME_TAB_HEIGHT_PX = 22;
25
+ /** Baseline Y of the chiclet label relative to the tab's top edge. */
26
+ export declare const FRAME_TAB_LABEL_BASELINE_OFFSET_PX = 15;
27
+ /** Height (px) of the group-title chiclet anchored at the box's upper-left. */
28
+ export declare const GROUP_TITLE_TAB_HEIGHT_PX = 16;
29
+ /** Horizontal padding (px) on each side of the title text inside the chiclet. */
30
+ export declare const GROUP_TITLE_TAB_PAD_X_PX = 6;
31
+ /** Vertical gap (px) between the chiclet's bottom edge and the first inner row. */
32
+ export declare const GROUP_TITLE_TAB_GUTTER_PX = 4;
33
+ /** Baseline Y of the chiclet label relative to the chiclet's top edge.
34
+ * Tuned for a 9 pt bold glyph roughly vertically centered in a 16 px tab. */
35
+ export declare const GROUP_TITLE_TAB_LABEL_BASELINE_OFFSET_PX = 11;
36
+ /** Font size (px) of the group-title chiclet label. */
37
+ export declare const GROUP_TITLE_TAB_LABEL_FONT_SIZE_PX = 9;
38
+ /** Approximate per-character width factor used to size the chiclet to its
39
+ * title text. Mirrors the constant used in the renderer's pre-port code
40
+ * so the chiclet hugs short titles without clipping long ones. */
41
+ export declare const GROUP_TITLE_TAB_CHAR_WIDTH_PX = 5.5;
42
+ /** Padding (px) reserved on the inside-bottom of a styled group box before
43
+ * its lower stroke. Symmetric with the chiclet gutter so children breathe
44
+ * on both ends. */
45
+ export declare const GROUP_BOTTOM_PAD_PX = 4;
46
+ /**
47
+ * Vertical space (px) reserved ABOVE a bracket-style (no-fill) group's
48
+ * box to host its overhanging title label. Bracket groups paint their
49
+ * label at `box.y - 2` (baseline) in the renderer — the glyph extent
50
+ * lives entirely ABOVE box.y. Without an explicit reservation, that
51
+ * overhang collides with the previous sibling's bracket-foot when two
52
+ * bracket-titled groups stack in a parallel (the foot ends right where
53
+ * the next label's top would render). The group shifts its own box.y
54
+ * down by this amount so the label has clear space above it; the
55
+ * caller advances by `bracketLabelOverhang + box.height + interRowGap`.
56
+ *
57
+ * Filled-style ("chiclet") groups use `GROUP_TITLE_TAB_HEIGHT_PX +
58
+ * GROUP_TITLE_TAB_GUTTER_PX` instead — the chiclet sits INSIDE the box,
59
+ * so they need no above-box reservation.
60
+ */
61
+ export declare const GROUP_BRACKET_LABEL_OVERHANG_PX = 12;
62
+ /**
63
+ * Dashed-accent pattern (px on / px off) used for two nowline accents
64
+ * that read as "structural emphasis": the milestone vertical cut line
65
+ * and the include-region's dashed border. Coupling them in one constant
66
+ * keeps both surfaces visually in sync.
67
+ *
68
+ * Mirrors the spec samples (`stroke-dasharray="6 4"`).
69
+ */
70
+ export declare const ACCENT_DASH_PATTERN = "6 4";
71
+ /** Width (px) of the rounded "now" pill above the now-line. */
72
+ export declare const NOW_PILL_WIDTH_PX = 36;
73
+ /** Height (px) of the rounded "now" pill. Matches the pill row band
74
+ * reserved at the top of the timeline. */
75
+ export declare const NOW_PILL_HEIGHT_PX = 16;
76
+ /** Corner radius (px) of the pill — half of `NOW_PILL_HEIGHT_PX` so
77
+ * the rect renders as a fully-rounded chiclet. */
78
+ export declare const NOW_PILL_CORNER_RADIUS_PX: number;
79
+ /** Font size (px) of the "now" label inside the pill. */
80
+ export declare const NOW_PILL_LABEL_FONT_SIZE_PX = 10;
81
+ /** Baseline offset (px) of the label text from the pill's top edge.
82
+ * Tuned to vertically center a 10 pt bold glyph in a 16 px pill. */
83
+ export declare const NOW_PILL_LABEL_BASELINE_OFFSET_PX: number;
84
+ /**
85
+ * Horizontal inset (px) of the "now" label from the pill's squared
86
+ * edge in flag mode. In `flag-right` mode the label sits at
87
+ * `squaredEdgeX + INSET` (left-aligned past the line); in `flag-left`
88
+ * mode at `squaredEdgeX - INSET` (right-aligned before the line).
89
+ * Center mode ignores this — the label sits at `nowX` with
90
+ * `text-anchor=middle`.
91
+ */
92
+ export declare const NOW_PILL_LABEL_INSET_X_PX = 6;
93
+ /**
94
+ * Stroke width (px) of the now-line. Shared between the line itself
95
+ * and the flag-mode pill geometry so the squared edge of the pill
96
+ * lines up with the OUTER edge of the line stroke (SVG strokes are
97
+ * centered on their geometry, so without this offset the line
98
+ * stroke peeks past the pill's squared edge by half-stroke).
99
+ */
100
+ export declare const NOWLINE_STROKE_WIDTH_PX = 2.25;
101
+ export declare const ITEM_INSET_PX = 6;
102
+ export declare const GUTTER_PX: number;
103
+ export declare const DEFAULT_PIXELS_PER_DAY = 5;
104
+ export declare const HEADER_BESIDE_MIN_WIDTH_PX = 120;
105
+ export declare const HEADER_BESIDE_MAX_WIDTH_PX = 240;
106
+ export declare const HEADER_ABOVE_HEIGHT_PX = 72;
107
+ /** Height (px) of the header band above the entry rows. */
108
+ export declare const FOOTNOTE_HEADER_HEIGHT_PX = 28;
109
+ /**
110
+ * Single padding value (px) reused as: left/right text inset, bottom
111
+ * padding under the last row, gap between the header band and the
112
+ * first entry, and gap between the number column and the title column.
113
+ * Bumping it changes every footnote panel inset consistently.
114
+ */
115
+ export declare const FOOTNOTE_PANEL_PADDING_PX = 16;
116
+ /** Baseline Y of the "Footnotes" header text relative to the panel top. */
117
+ export declare const FOOTNOTE_HEADER_BASELINE_OFFSET_PX = 22;
118
+ /** Baseline-to-baseline spacing between footnote entry rows. */
119
+ export declare const FOOTNOTE_ROW_HEIGHT = 18;
120
+ export declare const ATTRIBUTION_TEXT = "Powered by";
121
+ export declare const ATTRIBUTION_LINK = "https://nowline.io";
122
+ export declare const ATTRIBUTION_SCALE = 0.22;
123
+ export declare const ATTRIBUTION_WORDMARK_FONT_SIZE = 40;
124
+ export declare const ATTRIBUTION_PREFIX_FONT_SIZE = 32;
125
+ export declare const ATTRIBUTION_PREFIX_LOGICAL_WIDTH: number;
126
+ export declare const ATTRIBUTION_PREFIX_TO_WORDMARK_GAP = 10;
127
+ export declare const ATTRIBUTION_NOW_LOGICAL_X: number;
128
+ export declare const ATTRIBUTION_BAR_LOGICAL_X: number;
129
+ export declare const ATTRIBUTION_BAR_LOGICAL_WIDTH = 5;
130
+ export declare const ATTRIBUTION_INE_LOGICAL_X: number;
131
+ export declare const ATTRIBUTION_INE_LOGICAL_WIDTH: number;
132
+ export declare const ATTRIBUTION_GLYPH_LOGICAL_WIDTH: number;
133
+ export declare const ATTRIBUTION_GLYPH_LOGICAL_HEIGHT: number;
134
+ export declare const ATTRIBUTION_GLYPH_WIDTH: number;
135
+ export declare const ATTRIBUTION_GLYPH_HEIGHT: number;
136
+ export declare const EDGE_CORNER_RADIUS = 4;
137
+ export declare const SHADOW_PARAMS: Record<'none' | 'subtle' | 'soft' | 'hard', {
138
+ dx: number;
139
+ dy: number;
140
+ stdDeviation: number;
141
+ opacity: number;
142
+ }>;
143
+ export declare const FONT_STACK: Record<'sans' | 'serif' | 'mono', string>;
144
+ export declare const LABEL_THINNING: Record<'days' | 'weeks' | 'months' | 'quarters' | 'years', number>;
145
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/themes/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,310 @@
1
+ // Values that are currently identical across every theme. The split is
2
+ // allowed to move: if a theme needs its own padding or shadow tuning, the
3
+ // value migrates into the Theme interface + both per-theme files. Nothing
4
+ // in the layout engine assumes a particular split.
5
+ export const SPACING_PX = {
6
+ none: 0,
7
+ xs: 2,
8
+ sm: 4,
9
+ md: 8,
10
+ lg: 16,
11
+ xl: 24,
12
+ };
13
+ export const PADDING_PX = {
14
+ none: 0,
15
+ xs: 4,
16
+ sm: 8,
17
+ md: 12,
18
+ lg: 20,
19
+ xl: 32,
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
+ export const TEXT_SIZE_PX = {
30
+ none: 0,
31
+ xs: 10,
32
+ sm: 12,
33
+ md: 14,
34
+ lg: 18,
35
+ xl: 24,
36
+ };
37
+ export const CORNER_RADIUS_PX = {
38
+ none: 0,
39
+ xs: 2,
40
+ sm: 4,
41
+ md: 8,
42
+ lg: 12,
43
+ xl: 20,
44
+ full: 9999,
45
+ };
46
+ export const LOGO_SIZE_PX = {
47
+ xs: 18,
48
+ sm: 24,
49
+ md: 36,
50
+ lg: 48,
51
+ xl: 72,
52
+ };
53
+ // Row pitch (formerly `ITEM_ROW_HEIGHT = 64`) and bar height (formerly
54
+ // `ITEM_ROW_HEIGHT - 8 = 56`) are owned by `BandScale` as of m2.5b.
55
+ // `defaultRowBand()` keeps the legacy 64/56 split byte-stable; new
56
+ // 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;
59
+ // Height (px) of the bottom progress strip drawn along the item bar's
60
+ // bottom edge. Single source of truth used by:
61
+ // - the renderer (strip rect height + bottom-edge offset)
62
+ // - layout (label-chip Y reservation above the strip)
63
+ // - milestone slack-arrow attach Y (when a predecessor's caption
64
+ // spills past the bar's right edge, the arrow drops to the strip's
65
+ // vertical center so it visually aligns with the progress bar
66
+ // instead of running through the spilled text)
67
+ //
68
+ // Bumping this updates all three call sites consistently — the strip
69
+ // grows, chips lift, and the slack arrow stays centered on the strip.
70
+ export const PROGRESS_STRIP_HEIGHT_PX = 4;
71
+ // 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;
79
+ /**
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
+ */
83
+ export const TIMELINE_TICK_LABEL_BASELINE_OFFSET_PX = 15;
84
+ /**
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.
90
+ */
91
+ export const TRACK_BLOCK_TAIL_GUTTER_PX = 8;
92
+ // Frame-tab chiclet — the rounded label tab that overhangs a swimlane
93
+ // frame and the dashed include-region border. Both surfaces share the
94
+ // same height + label baseline so the chiclets read as siblings.
95
+ //
96
+ // The `FRAME_TAB_LABEL_BASELINE_OFFSET_PX` is tuned for a 12 pt label
97
+ // roughly vertically centered in the tab; bumping the height without
98
+ // adjusting the baseline pushes labels off-center.
99
+ /** Height (px) of the frame-tab chiclet (swimlane + include region). */
100
+ export const FRAME_TAB_HEIGHT_PX = 22;
101
+ /** Baseline Y of the chiclet label relative to the tab's top edge. */
102
+ 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
+ /**
149
+ * Dashed-accent pattern (px on / px off) used for two nowline accents
150
+ * that read as "structural emphasis": the milestone vertical cut line
151
+ * and the include-region's dashed border. Coupling them in one constant
152
+ * keeps both surfaces visually in sync.
153
+ *
154
+ * Mirrors the spec samples (`stroke-dasharray="6 4"`).
155
+ */
156
+ export const ACCENT_DASH_PATTERN = '6 4';
157
+ // Now-line pill — the rounded "now" chiclet that sits above the
158
+ // timeline at the now-line's x. Layout reserves the pill row's height
159
+ // in the timeline header AND uses NOW_PILL_WIDTH_PX/2 to keep the
160
+ // canvas wide enough that the pill never clips at the right edge
161
+ // (centered on the line, the pill extends ±half-width past it). The
162
+ // renderer paints with the same constants so the layout's reservation
163
+ // matches the painted glyph 1:1.
164
+ /** Width (px) of the rounded "now" pill above the now-line. */
165
+ export const NOW_PILL_WIDTH_PX = 36;
166
+ /** Height (px) of the rounded "now" pill. Matches the pill row band
167
+ * reserved at the top of the timeline. */
168
+ export const NOW_PILL_HEIGHT_PX = 16;
169
+ /** Corner radius (px) of the pill — half of `NOW_PILL_HEIGHT_PX` so
170
+ * the rect renders as a fully-rounded chiclet. */
171
+ export const NOW_PILL_CORNER_RADIUS_PX = NOW_PILL_HEIGHT_PX / 2;
172
+ /** Font size (px) of the "now" label inside the pill. */
173
+ export const NOW_PILL_LABEL_FONT_SIZE_PX = 10;
174
+ /** Baseline offset (px) of the label text from the pill's top edge.
175
+ * Tuned to vertically center a 10 pt bold glyph in a 16 px pill. */
176
+ export const NOW_PILL_LABEL_BASELINE_OFFSET_PX = NOW_PILL_HEIGHT_PX - 4;
177
+ /**
178
+ * Horizontal inset (px) of the "now" label from the pill's squared
179
+ * edge in flag mode. In `flag-right` mode the label sits at
180
+ * `squaredEdgeX + INSET` (left-aligned past the line); in `flag-left`
181
+ * mode at `squaredEdgeX - INSET` (right-aligned before the line).
182
+ * Center mode ignores this — the label sits at `nowX` with
183
+ * `text-anchor=middle`.
184
+ */
185
+ export const NOW_PILL_LABEL_INSET_X_PX = 6;
186
+ /**
187
+ * Stroke width (px) of the now-line. Shared between the line itself
188
+ * and the flag-mode pill geometry so the squared edge of the pill
189
+ * lines up with the OUTER edge of the line stroke (SVG strokes are
190
+ * centered on their geometry, so without this offset the line
191
+ * stroke peeks past the pill's squared edge by half-stroke).
192
+ */
193
+ 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;
199
+ // Canonical content gutter — the rest-state spacing between adjacent
200
+ // pieces of chart content. Used for:
201
+ // - the gap between two adjacent items in a track (= 2 × ITEM_INSET_PX),
202
+ // - the gap between the header card and the chart's left edge (originX
203
+ // offset from chartLeftX),
204
+ // - the bottom margin around the attribution wordmark.
205
+ //
206
+ // Future interactive layers (e.g. drag-and-drop authoring) may locally
207
+ // inflate this gutter at the active drop site to reveal a target slot.
208
+ // That's a runtime concern — the layout engine emits a static positioned
209
+ // model and the interactive shell animates spacing on top. Keep this
210
+ // 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;
215
+ // Header box defaults per position. The beside-mode card width is dynamic
216
+ // (sized to the title + author text, clamped to MIN..MAX with text wrap),
217
+ // so the layout uses these bounds instead of a single fixed width.
218
+ export const HEADER_BESIDE_MIN_WIDTH_PX = 120;
219
+ export const HEADER_BESIDE_MAX_WIDTH_PX = 240;
220
+ export const HEADER_ABOVE_HEIGHT_PX = 72;
221
+ // Footnote panel — fixed-position panel below the chart with a
222
+ // "Footnotes" header and one row per entry. Layout sizes the panel
223
+ // using these values; the renderer paints labels at offsets derived
224
+ // from the same constants so a padding bump cascades to both surfaces.
225
+ //
226
+ // ┌───────────────────────────────┐
227
+ // │ Footnotes ↑ │ header band (HEADER_HEIGHT)
228
+ // │ │ │
229
+ // ├─────────────────────────┘ │ gap = PANEL_PADDING
230
+ // │ N Title — description │ row N (ROW_HEIGHT each)
231
+ // │ N … │
232
+ // │ │
233
+ // └───────────────────────────────┘ bottom pad = PANEL_PADDING
234
+ //
235
+ // Total panel height (when entries.length > 0):
236
+ // HEADER_HEIGHT + entries × ROW_HEIGHT + PANEL_PADDING
237
+ /** Height (px) of the header band above the entry rows. */
238
+ export const FOOTNOTE_HEADER_HEIGHT_PX = 28;
239
+ /**
240
+ * Single padding value (px) reused as: left/right text inset, bottom
241
+ * padding under the last row, gap between the header band and the
242
+ * first entry, and gap between the number column and the title column.
243
+ * Bumping it changes every footnote panel inset consistently.
244
+ */
245
+ export const FOOTNOTE_PANEL_PADDING_PX = 16;
246
+ /** Baseline Y of the "Footnotes" header text relative to the panel top. */
247
+ export const FOOTNOTE_HEADER_BASELINE_OFFSET_PX = 22;
248
+ /** Baseline-to-baseline spacing between footnote entry rows. */
249
+ export const FOOTNOTE_ROW_HEIGHT = 18;
250
+ // Attribution mark — a clickable "Powered by nowline" link that sits in
251
+ // the canvas's bottom margin. Single source of truth for layout (which
252
+ // reserves a glyph-sized slot at canvas-bottom-right) and the renderer
253
+ // (which paints the glyph inside that slot at the same scale, so the
254
+ // reserved box hugs the painted glyph 1:1).
255
+ //
256
+ // "Powered by" is rendered at 80% of the wordmark's font size so it
257
+ // reads as a subdued tag rather than competing with the brand. Both
258
+ // share the same baseline (y = wordmarkFontSize) so the tag's x-height
259
+ // sits cleanly above the wordmark's baseline.
260
+ //
261
+ // Logical units (before `ATTRIBUTION_SCALE`):
262
+ // "Powered by" text ≈ 10 × 32 × 0.58 = 185.6 weight 400, x=0
263
+ // gap 10
264
+ // "now" text ≈ 3 × 40 × 0.58 = 69.6 weight 700, x=195.6
265
+ // bar (the "l") x=195.6+74=269.6, w=5
266
+ // "ine" text ≈ 3 × 40 × 0.58 = 69.6 weight 400, x=195.6+81=276.6
267
+ // Bar bottom is y = 12 + 40 = 52. The 74/81 internal offsets keep the
268
+ // red bar reading as a single "l" between "now" and "ine".
269
+ export const ATTRIBUTION_TEXT = 'Powered by';
270
+ export const ATTRIBUTION_LINK = 'https://nowline.io';
271
+ export const ATTRIBUTION_SCALE = 0.22;
272
+ export const ATTRIBUTION_WORDMARK_FONT_SIZE = 40;
273
+ export const ATTRIBUTION_PREFIX_FONT_SIZE = 32;
274
+ const ATTR_CHAR_FACTOR = 0.58;
275
+ export const ATTRIBUTION_PREFIX_LOGICAL_WIDTH = ATTRIBUTION_TEXT.length * ATTRIBUTION_PREFIX_FONT_SIZE * ATTR_CHAR_FACTOR; // 185.6
276
+ export const ATTRIBUTION_PREFIX_TO_WORDMARK_GAP = 10;
277
+ export const ATTRIBUTION_NOW_LOGICAL_X = ATTRIBUTION_PREFIX_LOGICAL_WIDTH + ATTRIBUTION_PREFIX_TO_WORDMARK_GAP; // 195.6
278
+ export const ATTRIBUTION_BAR_LOGICAL_X = ATTRIBUTION_NOW_LOGICAL_X + 74; // 269.6
279
+ export const ATTRIBUTION_BAR_LOGICAL_WIDTH = 5;
280
+ export const ATTRIBUTION_INE_LOGICAL_X = ATTRIBUTION_NOW_LOGICAL_X + 81; // 276.6
281
+ export const ATTRIBUTION_INE_LOGICAL_WIDTH = 3 * ATTRIBUTION_WORDMARK_FONT_SIZE * ATTR_CHAR_FACTOR; // 69.6
282
+ export const ATTRIBUTION_GLYPH_LOGICAL_WIDTH = ATTRIBUTION_INE_LOGICAL_X + ATTRIBUTION_INE_LOGICAL_WIDTH; // 346.2
283
+ export const ATTRIBUTION_GLYPH_LOGICAL_HEIGHT = 12 + ATTRIBUTION_WORDMARK_FONT_SIZE; // 52
284
+ export const ATTRIBUTION_GLYPH_WIDTH = ATTRIBUTION_GLYPH_LOGICAL_WIDTH * ATTRIBUTION_SCALE;
285
+ export const ATTRIBUTION_GLYPH_HEIGHT = ATTRIBUTION_GLYPH_LOGICAL_HEIGHT * ATTRIBUTION_SCALE;
286
+ // Dependency-edge rounded-corner radius (for Manhattan routing).
287
+ export const EDGE_CORNER_RADIUS = 4;
288
+ // Shadow filter parameters per shadow kind.
289
+ export const SHADOW_PARAMS = {
290
+ none: { dx: 0, dy: 0, stdDeviation: 0, opacity: 0 },
291
+ subtle: { dx: 0, dy: 1, stdDeviation: 1.5, opacity: 0.2 },
292
+ soft: { dx: 0, dy: 3, stdDeviation: 5, opacity: 0.3 },
293
+ hard: { dx: 2, dy: 2, stdDeviation: 0, opacity: 0.45 },
294
+ };
295
+ // Font stacks keyed by DSL `font:` value.
296
+ export const FONT_STACK = {
297
+ sans: 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif',
298
+ serif: 'Georgia, "Times New Roman", serif',
299
+ mono: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
300
+ };
301
+ // Label thinning defaults per scale unit (from specs/rendering.md § Timeline).
302
+ // Values are label-every counts (i.e. label every Nth tick).
303
+ export const LABEL_THINNING = {
304
+ days: 7,
305
+ weeks: 4,
306
+ months: 3,
307
+ quarters: 4,
308
+ years: 5,
309
+ };
310
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/themes/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { WorkingCalendar } from './working-calendar.js';
2
+ export interface TimeScaleOptions {
3
+ /** [start, end] in calendar dates (UTC midnight assumed). */
4
+ domain: [Date, Date];
5
+ /** [originX, originX + chartWidth]. */
6
+ range: [number, number];
7
+ /** Optional non-continuous calendar for future weekend-skip support. */
8
+ calendar?: WorkingCalendar;
9
+ }
10
+ export declare class TimeScale {
11
+ readonly domain: [Date, Date];
12
+ readonly range: [number, number];
13
+ readonly pixelsPerDay: number;
14
+ readonly calendar?: WorkingCalendar;
15
+ private readonly d3;
16
+ constructor(opts: TimeScaleOptions);
17
+ /**
18
+ * Project a date onto the x-axis. Always returns a number, even
19
+ * for dates outside the domain (callers that need clamping use
20
+ * `forwardWithinDomain`).
21
+ */
22
+ forward(date: Date): number;
23
+ /**
24
+ * 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.
27
+ */
28
+ forwardWithinDomain(date: Date): number | null;
29
+ /**
30
+ * Inverse projection. Returns a Date for any x in the chart;
31
+ * callers that want day-resolution can floor the result.
32
+ */
33
+ invert(x: number): Date;
34
+ /** First pixel of the chart (start of range). */
35
+ get originX(): number;
36
+ /** Width of the chart band in pixels. */
37
+ get widthPx(): number;
38
+ }
39
+ //# sourceMappingURL=time-scale.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,62 @@
1
+ // Date <-> pixel mapping. Replaces the hand-coded `xForDate` /
2
+ // `pixelsPerDay` arithmetic from `timeline.ts` with a wrapper that
3
+ // also exposes `invert(x) -> Date` for the m4 editor work and that
4
+ // composes with a `WorkingCalendar` for non-continuous time models.
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';
13
+ export class TimeScale {
14
+ domain;
15
+ range;
16
+ pixelsPerDay;
17
+ calendar;
18
+ d3;
19
+ constructor(opts) {
20
+ this.domain = opts.domain;
21
+ this.range = opts.range;
22
+ this.calendar = opts.calendar;
23
+ const spanDays = Math.max(1, daysBetween(opts.domain[0], opts.domain[1]));
24
+ this.pixelsPerDay = (opts.range[1] - opts.range[0]) / spanDays;
25
+ this.d3 = scaleTime().domain(opts.domain).range(opts.range);
26
+ }
27
+ /**
28
+ * Project a date onto the x-axis. Always returns a number, even
29
+ * for dates outside the domain (callers that need clamping use
30
+ * `forwardWithinDomain`).
31
+ */
32
+ forward(date) {
33
+ const days = daysBetween(this.domain[0], date);
34
+ return this.range[0] + days * this.pixelsPerDay;
35
+ }
36
+ /**
37
+ * 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.
40
+ */
41
+ forwardWithinDomain(date) {
42
+ if (date < this.domain[0] || date > this.domain[1])
43
+ return null;
44
+ return this.forward(date);
45
+ }
46
+ /**
47
+ * Inverse projection. Returns a Date for any x in the chart;
48
+ * callers that want day-resolution can floor the result.
49
+ */
50
+ invert(x) {
51
+ return this.d3.invert(x);
52
+ }
53
+ /** First pixel of the chart (start of range). */
54
+ get originX() {
55
+ return this.range[0];
56
+ }
57
+ /** Width of the chart band in pixels. */
58
+ get widthPx() {
59
+ return this.range[1] - this.range[0];
60
+ }
61
+ }
62
+ //# sourceMappingURL=time-scale.js.map
@@ -0,0 +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"}