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 +100 -30
- package/dist/browser/index.js +1 -1
- package/dist/browser/viz.js +12 -12
- package/dist/browser/writetrack.wasm +0 -0
- package/dist/ckeditor/index.d.ts +2 -20
- package/dist/esm/index.d.ts +69 -4
- package/dist/esm/index.js +1 -1
- package/dist/esm/testing.d.ts +1 -1
- package/dist/esm/testing.js +1 -1
- package/dist/esm/verify.d.ts +1 -1
- package/dist/esm/viz.d.ts +38 -12
- package/dist/esm/viz.js +12 -12
- package/dist/esm/writetrack.wasm +0 -0
- package/dist/index.cjs +1 -1
- package/dist/lexical/index.d.ts +2 -20
- package/dist/lexical/index.js +1 -1
- package/dist/prosemirror/index.d.ts +2 -20
- package/dist/prosemirror/index.js +1 -1
- package/dist/quill/index.d.ts +2 -20
- package/dist/quill/index.js +1 -1
- package/dist/react/index.d.ts +2 -19
- package/dist/react/index.js +1 -1
- package/dist/slate/index.d.ts +2 -20
- package/dist/tiptap/index.d.ts +11 -21
- package/dist/viz.cjs +12 -12
- package/dist/vue/index.d.ts +2 -19
- package/dist/vue/index.js +1 -1
- package/dist/writetrack.wasm +0 -0
- package/package.json +2 -2
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
|
-
- **~
|
|
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
|
-
|
|
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
|
|
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
|
|