pict-section-activitygraph 1.0.1 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pict-section-activitygraph",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Pict section that renders a stacked-bar activity timeline: one bar per period, stacked by type or actor, across parallel domains. Themed SVG, no chart dependency.",
5
5
  "main": "source/Pict-Section-ActivityGraph.js",
6
6
  "scripts": {
@@ -140,9 +140,15 @@ function buildSVG(pModel)
140
140
  }
141
141
 
142
142
  let tmpChartTop = TOP + LEGEND_H;
143
- let tmpHeight = tmpChartTop + tmpPeriodOrder.length * ROW_H + 20;
143
+ const GROUP_H = 22; // a super-group (quarter/year) gets its own header band, so its label
144
+ // never shares a line with the per-row date labels.
145
+ // Count the super-group bands up front so the SVG height accounts for them.
146
+ let tmpGroupCount = 0;
147
+ let tmpScanGroup = null;
148
+ tmpPeriodOrder.forEach((pRow) => { let tmpG = _superGroup(pRow.PeriodStart, tmpPeriod); if (tmpG && tmpG !== tmpScanGroup) { tmpGroupCount += 1; tmpScanGroup = tmpG; } });
149
+ let tmpHeight = tmpChartTop + tmpPeriodOrder.length * ROW_H + tmpGroupCount * GROUP_H + 20;
144
150
  let tmpSVG = [];
145
- tmpSVG.push('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + WIDTH + ' ' + tmpHeight + '" width="100%" role="img" aria-label="System activity, one bar per ' + _esc(tmpPeriod) + ' stacked by ' + _esc(tmpStackBy) + '" font-family="-apple-system, Segoe UI, Roboto, sans-serif">');
151
+ tmpSVG.push('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + WIDTH + ' ' + tmpHeight + '" width="100%" role="img" aria-label="System activity, one bar per ' + _esc(tmpPeriod) + ' stacked by ' + _esc(tmpStackBy) + ', each column scaled 0 to ' + tmpMaxTotal + '" font-family="-apple-system, Segoe UI, Roboto, sans-serif">');
146
152
 
147
153
  // legend
148
154
  let tmpLegendX = PAD_L;
@@ -154,25 +160,29 @@ function buildSVG(pModel)
154
160
  tmpLegendX += 20 + _esc(pKey).length * 7.2 + 14;
155
161
  });
156
162
 
157
- // column headers (accent-colored text + underline, never text on a fill)
163
+ // column headers: accent-colored title (left) + the axis scale (right). Both columns share one global
164
+ // max, so labeling each track's full-width value with the same number makes the shared, comparable
165
+ // 0-to-max scale explicit -- a track that fills the whole width equals that max.
158
166
  tmpColumns.forEach((pCol, pIndex) =>
159
167
  {
160
168
  let tmpX = tmpColX[pIndex];
161
169
  tmpSVG.push('<text x="' + tmpX + '" y="' + (tmpChartTop - 8) + '" font-size="13" font-weight="600" fill="' + (pCol.Accent || _C.text) + '">' + _esc(pCol.Title || pCol.Key) + '</text>');
162
170
  tmpSVG.push('<rect x="' + tmpX + '" y="' + (tmpChartTop - 4) + '" width="' + Math.max(40, tmpColWidth * 0.4) + '" height="2" fill="' + (pCol.Accent || _C.border) + '"/>');
171
+ tmpSVG.push('<text x="' + (tmpX + tmpBarMax).toFixed(1) + '" y="' + (tmpChartTop - 8) + '" text-anchor="end" font-size="10" fill="' + _C.muted + '">0 to ' + tmpMaxTotal + '</text>');
163
172
  });
164
173
 
165
- // rows
174
+ // rows (running y, so a super-group header band pushes the rows below it down instead of overlapping)
166
175
  let tmpPrevGroup = null;
167
- tmpPeriodOrder.forEach((pPeriodRow, pRowIndex) =>
176
+ let tmpY = tmpChartTop;
177
+ tmpPeriodOrder.forEach((pPeriodRow) =>
168
178
  {
169
- let tmpY = tmpChartTop + pRowIndex * ROW_H;
170
179
  let tmpGroup = _superGroup(pPeriodRow.PeriodStart, tmpPeriod);
171
180
  if (tmpGroup && tmpGroup !== tmpPrevGroup)
172
181
  {
173
- // super-group separator across the full width + label in the gutter
174
- tmpSVG.push('<line x1="0" y1="' + (tmpY - 2) + '" x2="' + (WIDTH - PAD_R) + '" y2="' + (tmpY - 2) + '" stroke="' + _C.border + '" stroke-width="1"/>');
175
- tmpSVG.push('<text x="0" y="' + (tmpY + 11) + '" font-size="10" font-weight="600" fill="' + _C.muted + '">' + _esc(tmpGroup) + '</text>');
182
+ // A band of its own: a boundary line, then the group label on its own line above the rows.
183
+ tmpSVG.push('<line x1="0" y1="' + (tmpY + 7) + '" x2="' + (WIDTH - PAD_R) + '" y2="' + (tmpY + 7) + '" stroke="' + _C.border + '" stroke-width="1"/>');
184
+ tmpSVG.push('<text x="0" y="' + (tmpY + 19) + '" font-size="11" font-weight="600" fill="' + _C.muted + '">' + _esc(tmpGroup) + '</text>');
185
+ tmpY += GROUP_H;
176
186
  tmpPrevGroup = tmpGroup;
177
187
  }
178
188
  // period label
@@ -198,6 +208,7 @@ function buildSVG(pModel)
198
208
  tmpSVG.push('<text x="' + (tmpX + 6).toFixed(1) + '" y="' + (tmpY + BAR_H) + '" font-size="11" font-weight="600" fill="' + _C.text + '">' + tmpCell.Total + '</text>');
199
209
  }
200
210
  });
211
+ tmpY += ROW_H;
201
212
  });
202
213
 
203
214
  tmpSVG.push('</svg>');