writetrack 0.9.0 → 0.10.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/README.md +10 -2
- package/dist/browser/index.js +1 -1
- package/dist/browser/pipes.js +1 -1
- package/dist/browser/viz.js +229 -97
- package/dist/browser/writetrack.wasm +0 -0
- package/dist/esm/index.d.ts +32 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/pipes.js +1 -1
- package/dist/esm/verify.d.ts +1 -1
- package/dist/esm/viz.d.ts +121 -61
- package/dist/esm/viz.js +229 -97
- package/dist/esm/writetrack.wasm +0 -0
- package/dist/index.cjs +1 -1
- package/dist/lexical/index.d.ts +3 -0
- package/dist/pipes.cjs +1 -1
- package/dist/quill/index.d.ts +8 -1
- package/dist/slate/index.d.ts +2 -0
- package/dist/viz.cjs +229 -97
- package/dist/writetrack.wasm +0 -0
- package/package.json +11 -3
package/dist/esm/pipes.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function p(n){let{url:o,headers:i={},retries:t=0,backoffMs:e=100,maxBackoffMs:a=3e4,keepalive:c=!1}=n;return{async send(f){let u=null;for(let s=0;s<=t;s++){if(s>0){let r=Math.min(e*Math.pow(2,s-1),a);await new Promise(l=>setTimeout(l,r))}try{let r=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",...i},body:JSON.stringify(f),keepalive:c});if(r.ok)return;u=new Error(`Webhook failed: ${r.status} ${r.statusText}`)}catch(r){u=r instanceof Error?r:new Error(String(r))}}throw u}}}function m(n){return n instanceof Error?n.message:String(n)}function d(n){let{client:o,actionName:i="writetrack_session",tags:t={}}=n;return{async send(e){let a={...t,duration:e.metadata.duration,keystrokeCount:e.session.events.length,qualityLevel:e.quality.qualityLevel,targetElement:e.metadata.targetElement,schemaVersion:e.version};e.metadata.userId&&(a.userId=e.metadata.userId),e.metadata.contentId&&(a.contentId=e.metadata.contentId),e.metadata.custom&&(a.custom=e.metadata.custom);try{o.addAction(i,a)}catch(c){throw new Error(`Datadog addAction failed: ${m(c)}`)}}}}function g(n){let{client:o,eventName:i="WriteTrack Session"}=n;return{async send(t){let e={duration:t.metadata.duration,keystrokeCount:t.session.events.length,qualityLevel:t.quality.qualityLevel,targetElement:t.metadata.targetElement,schemaVersion:t.version};t.metadata.userId&&(e.userId=t.metadata.userId),t.metadata.contentId&&(e.contentId=t.metadata.contentId),t.metadata.custom&&(e.custom=t.metadata.custom),o.track(i,e)}}}function v(n){let{tracer:o,spanName:i="writetrack.session"}=n;return{async send(t){let e=o.startSpan(i);try{e.setAttribute("writetrack.duration",t.metadata.duration),e.setAttribute("writetrack.keystroke_count",t.session.events.length),e.setAttribute("writetrack.quality_level",t.quality.qualityLevel),e.setAttribute("writetrack.target_element",t.metadata.targetElement),e.setAttribute("writetrack.schema_version",t.version),t.metadata.userId&&e.setAttribute("writetrack.user_id",t.metadata.userId),t.metadata.contentId&&e.setAttribute("writetrack.content_id",t.metadata.contentId),e.setStatus({code:1})}finally{e.end()}}}}export{d as datadog,v as opentelemetry,g as segment,p as webhook};
|
package/dist/esm/verify.d.ts
CHANGED
package/dist/esm/viz.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { W as WriteTrackDataSchema } from './index-Cy91q_po.js';
|
|
2
|
-
import { S as SessionAnalysis, a as SessionReport, d as IntegrityProof } from './analysis-types-
|
|
2
|
+
import { S as SessionAnalysis, a as SessionReport, d as IntegrityProof } from './analysis-types-DvrvSEh0.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* BaseChart — abstract web component base class for WriteTrack visualizations.
|
|
@@ -16,10 +16,20 @@ declare abstract class BaseChart<T = unknown> extends HTMLElement {
|
|
|
16
16
|
private _resizeObserver;
|
|
17
17
|
private _resizeRaf;
|
|
18
18
|
private _themeObserver;
|
|
19
|
-
private
|
|
19
|
+
private _lastWidth;
|
|
20
20
|
private _rendered;
|
|
21
21
|
private _internalTheme;
|
|
22
22
|
static get observedAttributes(): string[];
|
|
23
|
+
/** Whether to render in compact/sparkline mode (no axes, tight margins). */
|
|
24
|
+
get compact(): boolean;
|
|
25
|
+
/** Get the chart width — reads --wt-chart-width CSS var (set by scorecard
|
|
26
|
+
* bridge), then container/host clientWidth, then fallback. The CSS var
|
|
27
|
+
* ensures the chart renders at the correct width even before layout. */
|
|
28
|
+
protected getChartWidth(fallback: number): number;
|
|
29
|
+
/** Get the chart height — reads --wt-chart-height CSS var, then explicit
|
|
30
|
+
* inline height, then fallback. Avoids reading content-derived clientHeight
|
|
31
|
+
* to prevent a resize feedback loop. */
|
|
32
|
+
protected getChartHeight(fallback: number): number;
|
|
23
33
|
constructor();
|
|
24
34
|
/** Override in subclasses to provide component-specific CSS */
|
|
25
35
|
protected getStylesheet(): string;
|
|
@@ -40,6 +50,8 @@ declare abstract class BaseChart<T = unknown> extends HTMLElement {
|
|
|
40
50
|
destroy(): void;
|
|
41
51
|
/** Called on container resize. Override in subclasses that shouldn't full re-render. */
|
|
42
52
|
protected onResize(): void;
|
|
53
|
+
/** Wrap render() in try/catch so subclasses don't need individual error handling */
|
|
54
|
+
private safeRender;
|
|
43
55
|
/** Subclasses implement this to draw their visualization */
|
|
44
56
|
protected abstract render(): void;
|
|
45
57
|
/** Register the custom element if not already defined */
|
|
@@ -98,34 +110,6 @@ declare class SpeedTimeline extends BaseChart<SessionAnalysis> {
|
|
|
98
110
|
protected render(): void;
|
|
99
111
|
}
|
|
100
112
|
|
|
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
113
|
/**
|
|
130
114
|
* RhythmHeatmap — dwell time vs flight time scatter plot.
|
|
131
115
|
*
|
|
@@ -182,26 +166,47 @@ interface GrowthPoint {
|
|
|
182
166
|
declare function extractGrowthData(data: WriteTrackDataSchema): GrowthPoint[];
|
|
183
167
|
declare class DocumentGrowth extends BaseChart<WriteTrackDataSchema> {
|
|
184
168
|
static tagName: string;
|
|
169
|
+
/** Optional change point time (seconds) — renders as a dashed vertical rule. */
|
|
170
|
+
private _changePointTime;
|
|
171
|
+
/** Set a change point time (in seconds) to display as a vertical marker. */
|
|
172
|
+
setChangePoint(timeSec: number | null): void;
|
|
185
173
|
protected render(): void;
|
|
186
174
|
}
|
|
187
175
|
|
|
188
176
|
/**
|
|
189
|
-
*
|
|
177
|
+
* EditBeeswarm — per-keystroke beeswarm visualization.
|
|
190
178
|
*
|
|
191
|
-
* Each
|
|
179
|
+
* Each dot is a single edit action. Inserts, deletes, pastes, and cuts
|
|
180
|
+
* are color-coded and dodged vertically by time using Plot.dodgeY.
|
|
192
181
|
* Consumes raw WriteTrackDataSchema (not WASM analysis output).
|
|
193
182
|
*/
|
|
194
183
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
184
|
+
type BeeswarmType = 'insert' | 'delete' | 'paste' | 'cut';
|
|
185
|
+
interface BeeswarmDatum {
|
|
186
|
+
time: number;
|
|
187
|
+
type: BeeswarmType;
|
|
188
|
+
chars: number;
|
|
189
|
+
key: string;
|
|
199
190
|
}
|
|
200
|
-
/** Extract
|
|
201
|
-
declare function
|
|
202
|
-
declare class
|
|
191
|
+
/** Extract per-keystroke beeswarm data from raw session events. */
|
|
192
|
+
declare function extractBeeswarmData(data: WriteTrackDataSchema): BeeswarmDatum[];
|
|
193
|
+
declare class EditBeeswarm extends BaseChart<WriteTrackDataSchema> {
|
|
203
194
|
static tagName: string;
|
|
195
|
+
static get observedAttributes(): string[];
|
|
196
|
+
/** Whether to render typed characters as letter glyphs instead of dots.
|
|
197
|
+
* Internal/experimental — not part of the public API. */
|
|
198
|
+
get glyphs(): boolean;
|
|
199
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
204
200
|
protected render(): void;
|
|
201
|
+
/** Compact render: binned data, no axes, no tooltips, tight margins. */
|
|
202
|
+
private renderCompact;
|
|
203
|
+
/** Dot marks for all event types (default mode). */
|
|
204
|
+
private buildDotMarks;
|
|
205
|
+
/** Glyph marks: single text mark so everything dodges together.
|
|
206
|
+
* Typed chars as letters, deletes as ×, pastes as 📋, cuts as ✂. */
|
|
207
|
+
private buildGlyphMarks;
|
|
208
|
+
/** Crop the SVG viewBox top to fit content, preserving the bottom (axis). */
|
|
209
|
+
private cropViewBox;
|
|
205
210
|
}
|
|
206
211
|
|
|
207
212
|
/**
|
|
@@ -241,23 +246,49 @@ interface BubbleDatum {
|
|
|
241
246
|
time: number;
|
|
242
247
|
chars: number;
|
|
243
248
|
type: EditType;
|
|
244
|
-
size: number;
|
|
245
249
|
}
|
|
246
250
|
/** Group consecutive keystrokes into edit runs and add paste/cut events. */
|
|
247
251
|
declare function extractCorrectionBubbles(data: WriteTrackDataSchema): BubbleDatum[];
|
|
248
252
|
declare class CorrectionsBubble extends BaseChart<WriteTrackDataSchema> {
|
|
249
253
|
static tagName: string;
|
|
250
254
|
protected render(): void;
|
|
255
|
+
/** Compact render: 2 lanes if no clipboard events, time-binned if clipboard present. */
|
|
256
|
+
private renderCompact;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* OriginBar — content origin proportion as a horizontal stacked bar.
|
|
261
|
+
*
|
|
262
|
+
* Shows typed / pasted / autocompleted as percentages of all content created.
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
interface OriginDatum {
|
|
266
|
+
category: 'origin';
|
|
267
|
+
segment: string;
|
|
268
|
+
value: number;
|
|
269
|
+
}
|
|
270
|
+
interface OriginBarColors {
|
|
271
|
+
typed: string;
|
|
272
|
+
pasted: string;
|
|
273
|
+
autocompleted: string;
|
|
274
|
+
}
|
|
275
|
+
/** Extract origin proportions from analysis, filtering out 0% segments. */
|
|
276
|
+
declare function extractOriginData(analysis: SessionAnalysis): OriginDatum[];
|
|
277
|
+
/** Render a horizontal stacked bar showing content origin proportions. */
|
|
278
|
+
declare function renderOriginBar(data: OriginDatum[], width: number, colors?: OriginBarColors): SVGSVGElement | null;
|
|
279
|
+
declare class WtOriginBar extends BaseChart<SessionAnalysis> {
|
|
280
|
+
static tagName: string;
|
|
281
|
+
protected render(): void;
|
|
251
282
|
}
|
|
252
283
|
|
|
253
284
|
declare class WtScorecard extends BaseChart<SessionReport> {
|
|
254
285
|
static tagName: string;
|
|
255
|
-
|
|
256
|
-
|
|
286
|
+
static get observedAttributes(): string[];
|
|
287
|
+
private _activeCategory;
|
|
257
288
|
/**
|
|
258
289
|
* Override onResize to only re-render charts instead of full re-render.
|
|
259
|
-
* A full re-render replaces container content
|
|
260
|
-
* triggers ResizeObserver again
|
|
290
|
+
* A full re-render replaces container content -> changes height ->
|
|
291
|
+
* triggers ResizeObserver again -> infinite loop.
|
|
261
292
|
*/
|
|
262
293
|
protected onResize(): void;
|
|
263
294
|
protected getStylesheet(): string;
|
|
@@ -265,30 +296,27 @@ declare class WtScorecard extends BaseChart<SessionReport> {
|
|
|
265
296
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
266
297
|
protected render(): void;
|
|
267
298
|
private buildHeader;
|
|
268
|
-
private
|
|
269
|
-
private
|
|
299
|
+
private buildFlags;
|
|
300
|
+
private buildIntegrityDetails;
|
|
270
301
|
private buildGrid;
|
|
271
302
|
private buildCell;
|
|
272
303
|
private buildCellMetrics;
|
|
273
304
|
private buildDetailPanel;
|
|
274
305
|
private selectCell;
|
|
306
|
+
private populateAndRenderDetail;
|
|
275
307
|
private populateDetail;
|
|
276
|
-
private closeDetail;
|
|
277
|
-
private expandPanel;
|
|
278
|
-
private collapsePanel;
|
|
279
308
|
private getIndicatorCode;
|
|
280
309
|
private getComputedColors;
|
|
281
|
-
|
|
282
|
-
private
|
|
283
|
-
|
|
310
|
+
/** Render the origin proportion bar into #origin-bar if it exists and data is available. */
|
|
311
|
+
private renderOriginBarIfPresent;
|
|
312
|
+
/**
|
|
313
|
+
* Create a standalone chart component.
|
|
314
|
+
* Returns { el, init } — append el to DOM first, then call init()
|
|
315
|
+
* so the chart can measure its real container width.
|
|
316
|
+
*/
|
|
317
|
+
private createDetailChart;
|
|
284
318
|
private renderAllCharts;
|
|
285
319
|
private rerenderAllCharts;
|
|
286
|
-
private plotContentOrigin;
|
|
287
|
-
private plotTimingAuthenticity;
|
|
288
|
-
private plotRevisionBehavior;
|
|
289
|
-
private plotSessionContinuity;
|
|
290
|
-
private plotPhysicalPlausibility;
|
|
291
|
-
private plotTemporalPatterns;
|
|
292
320
|
}
|
|
293
321
|
|
|
294
322
|
interface IntegrityFooterData {
|
|
@@ -314,8 +342,8 @@ declare function isPass(code: string): boolean;
|
|
|
314
342
|
declare function getStatus(code: string | undefined): 'pass' | 'flag' | 'unknown';
|
|
315
343
|
/** Display names for SessionAnalysis category fields. */
|
|
316
344
|
declare const CATEGORY_NAMES: Record<string, string>;
|
|
317
|
-
/** All
|
|
318
|
-
declare const CATEGORY_KEYS: readonly ["contentOrigin", "timingAuthenticity", "revisionBehavior", "sessionContinuity", "physicalPlausibility", "temporalPatterns"];
|
|
345
|
+
/** All 7 analysis category keys in display order. */
|
|
346
|
+
declare const CATEGORY_KEYS: readonly ["contentOrigin", "timingAuthenticity", "revisionBehavior", "sessionContinuity", "physicalPlausibility", "temporalPatterns", "writingProcess"];
|
|
319
347
|
type CategoryKey = (typeof CATEGORY_KEYS)[number];
|
|
320
348
|
/** Tier 1 categories are expanded by default. */
|
|
321
349
|
declare const TIER1_CATEGORIES: CategoryKey[];
|
|
@@ -357,4 +385,36 @@ declare const GLOSSARY: Record<string, GlossaryEntry>;
|
|
|
357
385
|
*/
|
|
358
386
|
declare function wrapTerms(text: string, baseUrl?: string): string;
|
|
359
387
|
|
|
360
|
-
|
|
388
|
+
/**
|
|
389
|
+
* StatBadge — compact pill/lozenge badges for at-a-glance session stats.
|
|
390
|
+
*
|
|
391
|
+
* Renders a row of inline badges with label + color-coded value.
|
|
392
|
+
*/
|
|
393
|
+
|
|
394
|
+
type BadgeData = SessionAnalysis;
|
|
395
|
+
type BadgeStatus = 'clear' | 'flag' | 'neutral';
|
|
396
|
+
interface StatBadge {
|
|
397
|
+
label: string;
|
|
398
|
+
value: string;
|
|
399
|
+
status: BadgeStatus;
|
|
400
|
+
metric: string;
|
|
401
|
+
}
|
|
402
|
+
/** Extract headline stat badges from analysis data. */
|
|
403
|
+
declare function extractStatBadges(analysis: SessionAnalysis): StatBadge[];
|
|
404
|
+
/** Render a row of stat badge pills as a DOM element. */
|
|
405
|
+
declare function renderStatBadges(badges: StatBadge[]): HTMLElement;
|
|
406
|
+
declare class WtBadge extends BaseChart<BadgeData> {
|
|
407
|
+
static tagName: string;
|
|
408
|
+
static get observedAttributes(): string[];
|
|
409
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
410
|
+
protected getStylesheet(): string;
|
|
411
|
+
protected render(): void;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Generate a plain-English summary of a writing session from analysis data.
|
|
416
|
+
* Returns null if there is insufficient data to summarise.
|
|
417
|
+
*/
|
|
418
|
+
declare function generateWritingSummary(analysis: SessionAnalysis): string | null;
|
|
419
|
+
|
|
420
|
+
export { type BadgeData, type BadgeStatus, BaseChart, type BeeswarmDatum, type BeeswarmType, type BubbleDatum, CATEGORY_NAMES, type CategoryKey, CorrectionsBubble, DocumentGrowth, EditBeeswarm, type EditType, EditWaterfall, GLOSSARY, type GlossaryEntry, type GrowthPoint, IntegrityFooter, type OriginBarColors, type OriginDatum, type PauseBin, PauseDistribution, RhythmHeatmap, type RhythmPoint, type ScorecardMetric, Sparkline, type SpeedPoint, SpeedTimeline, type StatBadge, TIER1_CATEGORIES, TIER2_CATEGORIES, type WaterfallData, type WaterfallPoint, WtBadge, WtOriginBar, WtScorecard, extractBeeswarmData, extractCorrectionBubbles, extractGrowthData, extractOriginData, extractPauseHistogram, extractRhythmPairs, extractSeries, extractSpeedData, extractStatBadges, extractWaterfallData, formatDuration, generateCaption, generateSummary, generateWritingSummary, getMetrics, getStatus, isPass, renderOriginBar, renderStatBadges, wrapTerms };
|