writetrack 0.6.0 → 0.7.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.
@@ -0,0 +1,360 @@
1
+ import { W as WriteTrackDataSchema } from './index-ChEZuqzG.js';
2
+ import { S as SessionAnalysis, a as SessionReport, d as IntegrityProof } from './analysis-types-CZ2xI-JI.js';
3
+
4
+ /**
5
+ * BaseChart — abstract web component base class for WriteTrack visualizations.
6
+ *
7
+ * Handles Shadow DOM creation, CSS token injection, data management,
8
+ * resize observation, and provides an abstract render() hook for subclasses.
9
+ */
10
+ declare abstract class BaseChart<T = unknown> extends HTMLElement {
11
+ /** Override in subclasses to set the custom element tag name */
12
+ static tagName: string;
13
+ protected shadow: ShadowRoot;
14
+ protected container: HTMLDivElement;
15
+ protected _data: T | null;
16
+ private _resizeObserver;
17
+ private _resizeRaf;
18
+ private _themeObserver;
19
+ private _initialResize;
20
+ private _rendered;
21
+ private _internalTheme;
22
+ static get observedAttributes(): string[];
23
+ constructor();
24
+ /** Override in subclasses to provide component-specific CSS */
25
+ protected getStylesheet(): string;
26
+ connectedCallback(): void;
27
+ disconnectedCallback(): void;
28
+ attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
29
+ /** Set session data and trigger a render */
30
+ setData(data: T): void;
31
+ /** Get the current data */
32
+ getData(): T | null;
33
+ /** Whether the last render() produced visible content */
34
+ get hasRendered(): boolean;
35
+ /** Replace the chart container content with new element(s) */
36
+ protected replaceChart(...elements: (Node | string)[]): void;
37
+ /** Show an empty-state message when there's no renderable data */
38
+ protected showEmptyState(message?: string): void;
39
+ /** Tear down observers and clear the container */
40
+ destroy(): void;
41
+ /** Called on container resize. Override in subclasses that shouldn't full re-render. */
42
+ protected onResize(): void;
43
+ /** Subclasses implement this to draw their visualization */
44
+ protected abstract render(): void;
45
+ /** Register the custom element if not already defined */
46
+ static register(this: {
47
+ tagName: string;
48
+ new (): HTMLElement;
49
+ }): void;
50
+ /**
51
+ * Sync theme attribute from nearest ancestor with data-theme.
52
+ * Workaround for :host-context() not being supported in Firefox.
53
+ */
54
+ private _syncThemeFromAncestors;
55
+ }
56
+
57
+ /**
58
+ * Sparkline — compact typing speed chart using Observable Plot.
59
+ *
60
+ * Renders a minimal line chart (no axes, no cursor, no legend)
61
+ * showing rolling characters-per-minute derived from keydown flightTimes.
62
+ */
63
+
64
+ /**
65
+ * Extract [timestamps[], speeds[]] from WriteTrack session data.
66
+ *
67
+ * - Filters keydown events with flightTime > 0
68
+ * - Computes rolling CPM (characters per minute) over a sliding window
69
+ * - Returns seconds-from-start on the X axis and CPM on the Y axis
70
+ */
71
+ declare function extractSeries(data: WriteTrackDataSchema): [number[], number[]];
72
+ declare class Sparkline extends BaseChart<WriteTrackDataSchema> {
73
+ static tagName: string;
74
+ connectedCallback(): void;
75
+ protected render(): void;
76
+ /**
77
+ * Programmatic factory: create a Sparkline, append it to a container,
78
+ * and set its data.
79
+ */
80
+ static create(container: HTMLElement, data: WriteTrackDataSchema): Sparkline;
81
+ }
82
+
83
+ /**
84
+ * SpeedTimeline — typing speed over time chart.
85
+ *
86
+ * Renders a line+area chart showing characters-per-minute from the
87
+ * WASM analysis pipeline's speedTimeline time series.
88
+ */
89
+
90
+ interface SpeedPoint {
91
+ time: number;
92
+ speed: number;
93
+ }
94
+ /** Extract speed timeline data from analysis, converting ms to seconds. */
95
+ declare function extractSpeedData(analysis: SessionAnalysis): SpeedPoint[];
96
+ declare class SpeedTimeline extends BaseChart<SessionAnalysis> {
97
+ static tagName: string;
98
+ protected render(): void;
99
+ }
100
+
101
+ /**
102
+ * CompositionTimeline — session activity segments over time.
103
+ *
104
+ * Shows typing/paste/pause/tabAway segments as colored horizontal bars
105
+ * and paste events as dots scaled by character count.
106
+ */
107
+
108
+ declare const SEGMENT_COLORS: Record<string, string>;
109
+ interface SegmentDatum {
110
+ start: number;
111
+ end: number;
112
+ type: string;
113
+ color: string;
114
+ }
115
+ interface PasteDatum {
116
+ time: number;
117
+ chars: number;
118
+ source: string;
119
+ }
120
+ /** Extract activity segments from analysis, converting ms to seconds. */
121
+ declare function extractSegments(analysis: SessionAnalysis): SegmentDatum[];
122
+ /** Extract paste event markers from analysis. */
123
+ declare function extractPasteMarkers(analysis: SessionAnalysis): PasteDatum[];
124
+ declare class CompositionTimeline extends BaseChart<SessionAnalysis> {
125
+ static tagName: string;
126
+ protected render(): void;
127
+ }
128
+
129
+ /**
130
+ * RhythmHeatmap — dwell time vs flight time scatter plot.
131
+ *
132
+ * Shows the distribution of keystroke rhythm as a dot cloud,
133
+ * revealing clusters that indicate typing style (hunt-and-peck vs touch typing).
134
+ */
135
+
136
+ interface RhythmPoint {
137
+ dwell: number;
138
+ flight: number;
139
+ }
140
+ /** Extract paired (dwell, flight) data points from timing series. */
141
+ declare function extractRhythmPairs(analysis: SessionAnalysis): RhythmPoint[];
142
+ declare class RhythmHeatmap extends BaseChart<SessionAnalysis> {
143
+ static tagName: string;
144
+ protected render(): void;
145
+ }
146
+
147
+ /**
148
+ * PauseDistribution — histogram of pause durations.
149
+ *
150
+ * Shows the distribution of typing pauses using pre-binned data
151
+ * from the WASM analysis pipeline.
152
+ */
153
+
154
+ interface PauseBin {
155
+ start: number;
156
+ end: number;
157
+ count: number;
158
+ }
159
+ /** Extract pre-binned pause histogram data from analysis. */
160
+ declare function extractPauseHistogram(analysis: SessionAnalysis): PauseBin[];
161
+ declare class PauseDistribution extends BaseChart<SessionAnalysis> {
162
+ static tagName: string;
163
+ protected render(): void;
164
+ }
165
+
166
+ /**
167
+ * DocumentGrowth — cumulative character count over time.
168
+ *
169
+ * Vertical jumps indicate paste/cut events. Slope indicates typing speed.
170
+ * Consumes raw WriteTrackDataSchema (not WASM analysis output).
171
+ */
172
+
173
+ interface GrowthPoint {
174
+ time: number;
175
+ chars: number;
176
+ isPaste: boolean;
177
+ isCut: boolean;
178
+ pasteLength?: number;
179
+ cutLength?: number;
180
+ }
181
+ /** Extract cumulative character growth from raw events. */
182
+ declare function extractGrowthData(data: WriteTrackDataSchema): GrowthPoint[];
183
+ declare class DocumentGrowth extends BaseChart<WriteTrackDataSchema> {
184
+ static tagName: string;
185
+ protected render(): void;
186
+ }
187
+
188
+ /**
189
+ * DocumentRibbon — keystroke ribbon colored by inter-key gap.
190
+ *
191
+ * Each bar represents one keystroke. Yellow = short gaps (fast), red = long gaps (slow).
192
+ * Consumes raw WriteTrackDataSchema (not WASM analysis output).
193
+ */
194
+
195
+ interface RibbonDatum {
196
+ start: number;
197
+ end: number;
198
+ flight: number;
199
+ }
200
+ /** Extract ribbon data from raw keydown events. */
201
+ declare function extractRibbonData(data: WriteTrackDataSchema): RibbonDatum[];
202
+ declare class DocumentRibbon extends BaseChart<WriteTrackDataSchema> {
203
+ static tagName: string;
204
+ protected render(): void;
205
+ }
206
+
207
+ /**
208
+ * EditWaterfall — cursor position over time.
209
+ *
210
+ * Diagonal lines = sequential typing. Jumps = navigation.
211
+ * Cyan dots = paste events, orange dots = cut events. Y-axis reversed so position 0 is at top.
212
+ * Consumes raw WriteTrackDataSchema (not WASM analysis output).
213
+ */
214
+
215
+ interface WaterfallPoint {
216
+ time: number;
217
+ position: number;
218
+ }
219
+ interface WaterfallData {
220
+ keystrokes: WaterfallPoint[];
221
+ pastes: WaterfallPoint[];
222
+ cuts: WaterfallPoint[];
223
+ }
224
+ /** Extract cursor position data from raw events. */
225
+ declare function extractWaterfallData(data: WriteTrackDataSchema): WaterfallData;
226
+ declare class EditWaterfall extends BaseChart<WriteTrackDataSchema> {
227
+ static tagName: string;
228
+ protected render(): void;
229
+ }
230
+
231
+ /**
232
+ * CorrectionsBubble — edit run visualization.
233
+ *
234
+ * Green bubbles = insertions, red = deletions, cyan = paste, orange = cut.
235
+ * Size = log2(character count). Consecutive same-type actions are grouped.
236
+ * Consumes raw WriteTrackDataSchema (not WASM analysis output).
237
+ */
238
+
239
+ type EditType = 'insert' | 'delete' | 'paste' | 'cut';
240
+ interface BubbleDatum {
241
+ time: number;
242
+ chars: number;
243
+ type: EditType;
244
+ size: number;
245
+ }
246
+ /** Group consecutive keystrokes into edit runs and add paste/cut events. */
247
+ declare function extractCorrectionBubbles(data: WriteTrackDataSchema): BubbleDatum[];
248
+ declare class CorrectionsBubble extends BaseChart<WriteTrackDataSchema> {
249
+ static tagName: string;
250
+ protected render(): void;
251
+ }
252
+
253
+ declare class WtScorecard extends BaseChart<SessionReport> {
254
+ static tagName: string;
255
+ private _activeDetail;
256
+ constructor();
257
+ /**
258
+ * Override onResize to only re-render charts instead of full re-render.
259
+ * A full re-render replaces container content → changes height →
260
+ * triggers ResizeObserver again → infinite loop.
261
+ */
262
+ protected onResize(): void;
263
+ protected getStylesheet(): string;
264
+ /** Override to handle theme changes without full re-render. */
265
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
266
+ protected render(): void;
267
+ private buildHeader;
268
+ private buildSummary;
269
+ private buildTierLabel;
270
+ private buildGrid;
271
+ private buildCell;
272
+ private buildCellMetrics;
273
+ private buildDetailPanel;
274
+ private selectCell;
275
+ private populateDetail;
276
+ private closeDetail;
277
+ private expandPanel;
278
+ private collapsePanel;
279
+ private getIndicatorCode;
280
+ private getComputedColors;
281
+ private getChartWidth;
282
+ private plotOpts;
283
+ private plotCategory;
284
+ private renderAllCharts;
285
+ private rerenderAllCharts;
286
+ private plotContentOrigin;
287
+ private plotTimingAuthenticity;
288
+ private plotRevisionBehavior;
289
+ private plotSessionContinuity;
290
+ private plotPhysicalPlausibility;
291
+ private plotTemporalPatterns;
292
+ }
293
+
294
+ interface IntegrityFooterData {
295
+ integrity: IntegrityProof;
296
+ outputSignature: string;
297
+ sessionId: string;
298
+ }
299
+ declare class IntegrityFooter extends BaseChart<IntegrityFooterData> {
300
+ static tagName: string;
301
+ protected getStylesheet(): string;
302
+ protected render(): void;
303
+ private renderQr;
304
+ }
305
+
306
+ /**
307
+ * Scorecard text generation — pass/flag classification, category names,
308
+ * summary generators, chart captions, and metric annotations.
309
+ *
310
+ * Pure functions with no DOM dependency. Used by scorecard components
311
+ * to generate explanatory text from SessionAnalysis data.
312
+ */
313
+ declare function isPass(code: string): boolean;
314
+ declare function getStatus(code: string | undefined): 'pass' | 'flag' | 'unknown';
315
+ /** Display names for SessionAnalysis category fields. */
316
+ declare const CATEGORY_NAMES: Record<string, string>;
317
+ /** All 6 analysis category keys in display order. */
318
+ declare const CATEGORY_KEYS: readonly ["contentOrigin", "timingAuthenticity", "revisionBehavior", "sessionContinuity", "physicalPlausibility", "temporalPatterns"];
319
+ type CategoryKey = (typeof CATEGORY_KEYS)[number];
320
+ /** Tier 1 categories are expanded by default. */
321
+ declare const TIER1_CATEGORIES: CategoryKey[];
322
+ /** Tier 2 categories are collapsed by default. */
323
+ declare const TIER2_CATEGORIES: CategoryKey[];
324
+
325
+ /** Generate a plain-English section summary from the indicator code + analysis data. */
326
+ declare function generateSummary(category: string, analysis: SessionAnalysis): string;
327
+ /** Return a chart caption for the given category, or null if no chart. */
328
+ declare function generateCaption(category: string): string | null;
329
+ /** A single metric for display in the metric grid. */
330
+ interface ScorecardMetric {
331
+ label: string;
332
+ value: string;
333
+ flagged: boolean;
334
+ }
335
+ /**
336
+ * Extract displayable metrics for a given category from analysis data.
337
+ *
338
+ * Note: timing metrics use periodicity + entropy rather than WPM + variance
339
+ * because TimingAuthenticityAnalysis doesn't include WPM — those fields are
340
+ * directly available and diagnostically meaningful for automation detection.
341
+ */
342
+ declare function getMetrics(category: string, analysis: SessionAnalysis): ScorecardMetric[];
343
+ /** Format milliseconds to human-readable duration. */
344
+ declare function formatDuration(ms: number): string;
345
+
346
+ interface GlossaryEntry {
347
+ definition: string;
348
+ docsPath?: string;
349
+ }
350
+ declare const GLOSSARY: Record<string, GlossaryEntry>;
351
+ /**
352
+ * Wrap known glossary terms in HTML with <abbr> elements containing
353
+ * a title tooltip. Terms with a docsPath are additionally wrapped
354
+ * in an <a> link (Amendment #3).
355
+ *
356
+ * Terms are matched case-insensitively.
357
+ */
358
+ declare function wrapTerms(text: string, baseUrl?: string): string;
359
+
360
+ export { BaseChart, type BubbleDatum, CATEGORY_NAMES, type CategoryKey, CompositionTimeline, CorrectionsBubble, DocumentGrowth, DocumentRibbon, type EditType, EditWaterfall, GLOSSARY, type GlossaryEntry, type GrowthPoint, IntegrityFooter, type PasteDatum, type PauseBin, PauseDistribution, RhythmHeatmap, type RhythmPoint, type RibbonDatum, SEGMENT_COLORS, type ScorecardMetric, type SegmentDatum, Sparkline, type SpeedPoint, SpeedTimeline, TIER1_CATEGORIES, TIER2_CATEGORIES, type WaterfallData, type WaterfallPoint, WtScorecard, extractCorrectionBubbles, extractGrowthData, extractPasteMarkers, extractPauseHistogram, extractRhythmPairs, extractRibbonData, extractSegments, extractSeries, extractSpeedData, extractWaterfallData, formatDuration, generateCaption, generateSummary, getMetrics, getStatus, isPass, wrapTerms };