writetrack 0.11.0 → 0.12.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 CHANGED
@@ -4,7 +4,7 @@ Capture and analyze the writing process through keystroke dynamics.
4
4
 
5
5
  WriteTrack is an embeddable SDK that instruments text inputs to record _how_ text was written — timing, rhythm, corrections, clipboard usage, and composition patterns. It gives platforms behavioral evidence of the writing process, not just the finished text.
6
6
 
7
- - **~118KB** gzipped (18KB JS + 100KB WASM)
7
+ - **~142KB** gzipped (20KB JS + 122KB WASM)
8
8
  - **0** runtime dependencies
9
9
  - **<1ms** per keystroke
10
10
  - **100%** client-side
@@ -15,12 +15,14 @@ WriteTrack is an embeddable SDK that instruments text inputs to record _how_ tex
15
15
  npm install writetrack
16
16
  ```
17
17
 
18
- Then register for a free trial:
18
+ Optionally, register for a free trial license:
19
19
 
20
20
  ```bash
21
- npx writetrack init
21
+ npx writetrack init # starts a 28-day trial and writes the key to .env
22
22
  ```
23
23
 
24
+ A license is required for production domains. On `localhost`, all features work without a license key.
25
+
24
26
  ## Quick Start
25
27
 
26
28
  ```typescript
@@ -29,7 +31,6 @@ import { WriteTrack } from 'writetrack';
29
31
  const responseField = document.getElementById('response-field')!;
30
32
  const tracker = new WriteTrack({
31
33
  target: responseField,
32
- license: process.env.WRITETRACK_LICENSE_KEY, // omit for localhost evaluation
33
34
  });
34
35
 
35
36
  tracker.start();
@@ -45,6 +46,51 @@ tracker.stop();
45
46
 
46
47
  Works with any text input, textarea, or contenteditable element. TypeScript definitions included.
47
48
 
49
+ > **Note:** WriteTrack uses WASM, which requires an HTTP server — `file://` won't work. Any bundler (Vite, webpack, etc.) handles this automatically. For a no-bundler setup, see the [vanilla JS guide](https://writetrack.dev/docs/vanilla-js/).
50
+
51
+ ### React / Next.js
52
+
53
+ ```tsx
54
+ import { useRef } from 'react';
55
+ import { useWriteTrack } from 'writetrack/react';
56
+
57
+ function ResponseForm() {
58
+ const textareaRef = useRef<HTMLTextAreaElement>(null);
59
+ const { tracker } = useWriteTrack(textareaRef);
60
+
61
+ const handleSubmit = async (e: React.FormEvent) => {
62
+ e.preventDefault();
63
+ if (tracker) {
64
+ const data = tracker.getData();
65
+ const analysis = await tracker.getAnalysis();
66
+ console.log('Session:', data.quality, analysis);
67
+ }
68
+ };
69
+
70
+ return (
71
+ <form onSubmit={handleSubmit}>
72
+ <textarea ref={textareaRef} rows={10} />
73
+ <button type="submit">Submit</button>
74
+ </form>
75
+ );
76
+ }
77
+ ```
78
+
79
+ For App Router, Server Actions, and dev-mode WASM setup, see the [Next.js guide](https://writetrack.dev/docs/nextjs/).
80
+
81
+ ## Production
82
+
83
+ Add your license key to enable analysis on production domains:
84
+
85
+ ```typescript
86
+ const tracker = new WriteTrack({
87
+ target: textarea,
88
+ license: process.env.WRITETRACK_LICENSE_KEY,
89
+ });
90
+ ```
91
+
92
+ On `localhost`, all features work without a key. See the [licensing guide](https://writetrack.dev/docs/license/) for trial setup, domain binding, and expiration details.
93
+
48
94
  ## Framework Integrations
49
95
 
50
96
  First-party bindings available as subpath exports:
@@ -136,30 +182,54 @@ interface WriteTrackOptions {
136
182
 
137
183
  ### Methods
138
184
 
139
- | Method | Returns | Description |
140
- | ---------------------------------- | -------------------------------- | ------------------------------------------------ |
141
- | `start()` | `void` | Begin capturing events |
142
- | `stop()` | `void` | Stop capturing and clean up |
143
- | `stopAndWait()` | `Promise<void>` | Stop and wait for pending IndexedDB save |
144
- | `getData()` | `WriteTrackDataSchema` | Export full session data |
145
- | `getText()` | `string` | Current text content |
146
- | `getRawEvents()` | `KeystrokeEvent[]` | All captured keystroke events |
147
- | `getClipboardEvents()` | `ClipboardEvent[]` | Paste/copy/cut events |
148
- | `getSelectionEvents()` | `SelectionEvent[]` | Text selection events |
149
- | `getUndoRedoEvents()` | `UndoRedoEvent[]` | Undo/redo events |
150
- | `getCompositionEvents()` | `CompositionEvent[]` | IME composition events |
151
- | `getProgrammaticInsertionEvents()` | `ProgrammaticInsertionEvent[]` | Programmatic insertion events |
152
- | `getSessionDuration()` | `number` | Session duration in ms |
153
- | `getActiveTime()` | `number` | Active (visible) session time in ms |
154
- | `getKeystrokeCount()` | `number` | Total keystrokes captured |
155
- | `getAnalysis()` | `Promise<SessionAnalysis\|null>` | WASM-powered session analysis |
156
- | `getSessionReport()` | `Promise<SessionReport>` | Combined data + analysis |
157
- | `pipe(sink)` | `this` | Register an output sink |
158
- | `on(event, handler)` | `() => void` | Register an event listener (returns unsubscribe) |
159
- | `isLicenseValid()` | `boolean` | Whether license is valid |
160
- | `isLicenseValidated()` | `boolean` | Whether license check has completed |
161
- | `isTargetDetached()` | `boolean` | Whether the target element was removed |
162
- | `clearPersistedData()` | `Promise<void>` | Clear IndexedDB persisted session |
185
+ | Method | Returns | Description |
186
+ | ---------------------------------- | -------------------------------- | --------------------------------------------- |
187
+ | `start()` | `void` | Begin capturing events |
188
+ | `stop()` | `void` | Stop capturing and clean up |
189
+ | `stopAndWait()` | `Promise<void>` | Stop and wait for pending IndexedDB save |
190
+ | `getData()` | `WriteTrackDataSchema` | Export full session data |
191
+ | `getText()` | `string` | Current text content |
192
+ | `getRawEvents()` | `KeystrokeEvent[]` | All captured keystroke events |
193
+ | `getClipboardEvents()` | `ClipboardEvent[]` | Paste/copy/cut events |
194
+ | `getSelectionEvents()` | `SelectionEvent[]` | Text selection events |
195
+ | `getUndoRedoEvents()` | `UndoRedoEvent[]` | Undo/redo events |
196
+ | `getCompositionEvents()` | `CompositionEvent[]` | IME composition events |
197
+ | `getProgrammaticInsertionEvents()` | `ProgrammaticInsertionEvent[]` | Programmatic insertion events |
198
+ | `getSessionDuration()` | `number` | Session duration in ms |
199
+ | `getActiveTime()` | `number` | Active (visible) session time in ms |
200
+ | `getKeystrokeCount()` | `number` | Total keystrokes captured |
201
+ | `getAnalysis()` | `Promise<SessionAnalysis\|null>` | WASM-powered session analysis |
202
+ | `getSessionReport()` | `Promise<SessionReport>` | Combined data + analysis |
203
+ | `pipe(sink)` | `this` | Register an output sink |
204
+ | `on(event, handler)` | `() => void` | Register event listener (returns unsubscribe) |
205
+ | `isLicenseValid()` | `boolean` | Whether license is valid |
206
+ | `isLicenseValidated()` | `boolean` | Whether license check has completed |
207
+ | `isTargetDetached()` | `boolean` | Whether the target element was removed |
208
+ | `clearPersistedData()` | `Promise<void>` | Clear IndexedDB persisted session |
209
+
210
+ `getData()` returns a `WriteTrackDataSchema` with four top-level fields: `version`, `metadata` (session context, user/content IDs, custom fields), `session` (raw events and text), and `quality` (completeness score, validation status). See the [API reference](https://writetrack.dev/docs/api-reference#getdata) for the full shape.
211
+
212
+ ### Events
213
+
214
+ The `on(event, handler)` method supports the following events:
215
+
216
+ | Event | Payload | Description |
217
+ | ------------ | ---------------------------------------------------------------- | --------------------------------------------------------------- |
218
+ | `change` | `{ eventCount: number; keystrokeCount: number }` | Fires on any data mutation (keystroke, paste, selection, etc.) |
219
+ | `tick` | `{ activeTime: number; totalTime: number; tracker: WriteTrack }` | Fires every ~1s while session is active |
220
+ | `analysis` | `SessionAnalysis` | Fires when analysis updates (lazy-loads WASM on first listener) |
221
+ | `ready` | _(none)_ | Fires when tracker is ready (late listeners auto-fire) |
222
+ | `wasm:ready` | _(none)_ | Fires when WASM binary loads successfully |
223
+ | `wasm:error` | `Error` | Fires if WASM binary fails to load |
224
+ | `stop` | _(none)_ | Fires when `stop()` is called |
225
+ | `pipe:error` | `Error, WriteTrackSink` | Fires when an output sink fails |
226
+
227
+ ```typescript
228
+ const unsub = tracker.on('change', ({ eventCount, keystrokeCount }) => {
229
+ console.log(`${keystrokeCount} keystrokes, ${eventCount} total events`);
230
+ });
231
+ // Later: unsub();
232
+ ```
163
233
 
164
234
  ### Static Methods
165
235
 
@@ -228,9 +298,9 @@ const tracker = createMockTracker({ analysis });
228
298
 
229
299
  Full type definitions are included in the package:
230
300
 
231
- **Functions:** `analyzeEvents`, `createSessionReport`, `formatIndicator`, `getHighResolutionTime`
301
+ **Functions:** `analyzeEvents`, `createSessionReport`, `formatIndicator`, `getHighResolutionTime`, `WriteTrackController`
232
302
 
233
- **Types:** `WriteTrackOptions`, `PersistedSessionInfo`, `KeystrokeEvent`, `ClipboardEvent`, `SelectionEvent`, `UndoRedoEvent`, `CompositionEvent`, `ProgrammaticInsertionEvent`, `ModifierState`, `InputSource`, `WriteTrackDataSchema`, `DataQualityMetrics`, `SessionMetadata`, `SessionAnalysis`, `SessionReport`, `IndicatorOutput`, `ContentOriginAnalysis`, `TimingAuthenticityAnalysis`, `SessionContinuityAnalysis`, `PhysicalPlausibilityAnalysis`, `RevisionBehaviorAnalysis`, `TemporalPatternsAnalysis`, `WritingProcessAnalysis`, `WritingProcessSegment`, `PhaseTransition`, `WindowFeatures`, `AnalyzeEventsOptions`, `WriteTrackSink`, `WebhookOptions`, `DatadogOptions`, `DatadogClient`, `SegmentOptions`, `SegmentClient`, `OpenTelemetryOptions`, `OTelTracer`, `OTelSpan`
303
+ **Types:** `WriteTrackOptions`, `PersistedSessionInfo`, `KeystrokeEvent`, `ClipboardEvent`, `SelectionEvent`, `UndoRedoEvent`, `CompositionEvent`, `ProgrammaticInsertionEvent`, `ModifierState`, `InputSource`, `WriteTrackDataSchema`, `DataQualityMetrics`, `SessionMetadata`, `SessionAnalysis`, `SessionReport`, `IndicatorOutput`, `ContentOriginAnalysis`, `TimingAuthenticityAnalysis`, `SessionContinuityAnalysis`, `PhysicalPlausibilityAnalysis`, `RevisionBehaviorAnalysis`, `TemporalPatternsAnalysis`, `WritingProcessAnalysis`, `WritingProcessSegment`, `PhaseTransition`, `WindowFeatures`, `AnalyzeEventsOptions`, `WriteTrackSink`, `WebhookOptions`, `DatadogOptions`, `DatadogClient`, `SegmentOptions`, `SegmentClient`, `OpenTelemetryOptions`, `OTelTracer`, `OTelSpan`, `BaseBindingOptions`, `OnTickData`, `ControllerState`, `ControllerOptions`
234
304
 
235
305
  ## Browser Support
236
306