@atlaskit/editor-plugin-limited-mode 13.0.18 → 14.1.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.
Files changed (31) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/afm-cc/tsconfig.json +9 -0
  3. package/dist/cjs/limitedModePlugin.js +7 -4
  4. package/dist/cjs/pm-plugins/main.js +201 -18
  5. package/dist/cjs/pm-plugins/plugin-key.js +8 -0
  6. package/dist/cjs/pm-plugins/utils/latch-detector-types.js +5 -0
  7. package/dist/cjs/pm-plugins/utils/latch-detector.js +108 -0
  8. package/dist/cjs/pm-plugins/utils/latch-policy-types.js +1 -0
  9. package/dist/cjs/pm-plugins/utils/latch-policy.js +314 -0
  10. package/dist/es2019/limitedModePlugin.js +4 -3
  11. package/dist/es2019/pm-plugins/main.js +195 -16
  12. package/dist/es2019/pm-plugins/plugin-key.js +2 -0
  13. package/dist/es2019/pm-plugins/utils/latch-detector-types.js +1 -0
  14. package/dist/es2019/pm-plugins/utils/latch-detector.js +92 -0
  15. package/dist/es2019/pm-plugins/utils/latch-policy-types.js +0 -0
  16. package/dist/es2019/pm-plugins/utils/latch-policy.js +277 -0
  17. package/dist/esm/limitedModePlugin.js +6 -3
  18. package/dist/esm/pm-plugins/main.js +199 -16
  19. package/dist/esm/pm-plugins/plugin-key.js +2 -0
  20. package/dist/esm/pm-plugins/utils/latch-detector-types.js +1 -0
  21. package/dist/esm/pm-plugins/utils/latch-detector.js +102 -0
  22. package/dist/esm/pm-plugins/utils/latch-policy-types.js +0 -0
  23. package/dist/esm/pm-plugins/utils/latch-policy.js +307 -0
  24. package/dist/types/limitedModePluginType.d.ts +34 -1
  25. package/dist/types/pm-plugins/main.d.ts +12 -4
  26. package/dist/types/pm-plugins/plugin-key.d.ts +2 -0
  27. package/dist/types/pm-plugins/utils/latch-detector-types.d.ts +30 -0
  28. package/dist/types/pm-plugins/utils/latch-detector.d.ts +15 -0
  29. package/dist/types/pm-plugins/utils/latch-policy-types.d.ts +150 -0
  30. package/dist/types/pm-plugins/utils/latch-policy.d.ts +112 -0
  31. package/package.json +7 -3
@@ -0,0 +1,112 @@
1
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
+ import type { LatchDetails, LatchEvaluation, LatchPolicyConfig, LatchPolicyOptions } from './latch-policy-types';
3
+ /**
4
+ * The shipped policy.
5
+ *
6
+ * These values add up to: nothing counts for the first 10s; then a window qualifies on either 6 of
7
+ * 12 keystrokes slower than 100ms with that window's median also over 100ms, or 3 long tasks over
8
+ * 600ms within 30s corroborated by a slow keystroke in that same 30s. Two qualifying windows at
9
+ * least 30s apart latch limited mode.
10
+ *
11
+ * `freezeTaskMs` matches `DEFAULT_FREEZE_THRESHOLD` in
12
+ * `editor-plugin-base/src/pm-plugins/frozen-editor.ts`, which backs the existing
13
+ * `ACTION.BROWSER_FREEZE` telemetry, so production dashboards can be used to calibrate it.
14
+ * `slowInputMs` is deliberately tighter than that file's `DEFAULT_SLOW_THRESHOLD` of 300 — this
15
+ * needs to notice a degraded experience, not just an unusable one.
16
+ *
17
+ * `requiredConfirmations` and `confirmationGapMs` are the values that matter most — see the comment
18
+ * on the former.
19
+ */
20
+ export declare const DEFAULT_LATCH_POLICY_CONFIG: LatchPolicyConfig;
21
+ /**
22
+ * Decides whether limited mode should be on.
23
+ *
24
+ * The single authority for that question, covering both reasons:
25
+ *
26
+ * - **The document** — too large, too many nodes, or containing a legacy content macro. Evaluated on
27
+ * load and on document replacement, so it can turn back off (a `replaceDocument` onto a smaller
28
+ * page) without costing a full-document walk per transaction.
29
+ * - **The device** — sustained slow keystrokes or repeated long tasks. **One-way**: once the runtime
30
+ * bar is met the policy stops evaluating, so the editor can never oscillate between modes.
31
+ *
32
+ * `isBreached()` is the combined verdict. Everything tunable is in `config`, so the whole high bar is
33
+ * unit-testable without needing to make a real browser slow, and a caller can substitute a
34
+ * differently configured policy. `latch-detector.ts` owns the browser plumbing that feeds the runtime
35
+ * criteria, and takes a policy instance rather than constructing one.
36
+ */
37
+ export declare class LatchPolicy {
38
+ /** Public so the detector can read the tunables it needs rather than duplicating them. */
39
+ readonly config: LatchPolicyConfig;
40
+ /** Public so the detector shares one clock with the policy. */
41
+ readonly now: () => number;
42
+ private readonly startedAt;
43
+ private latencySamples;
44
+ private freezeTimes;
45
+ private lastSlowInputAt;
46
+ private firstQualifiedAt;
47
+ private lastQualifiedAt;
48
+ private qualifiedWindows;
49
+ private suppressedUntil;
50
+ private latched;
51
+ private documentBreached;
52
+ private firstWindowReason;
53
+ private latchDetails;
54
+ /** Cumulative for the session and never cleared, unlike the evidence buffers. */
55
+ private totalInputSamples;
56
+ private totalSlowInputs;
57
+ private totalFreezes;
58
+ constructor({ now, config }: LatchPolicyOptions);
59
+ /**
60
+ * Whether limited mode should be on, for either reason. This is the verdict consumers act on.
61
+ */
62
+ isBreached(): boolean;
63
+ /**
64
+ * What the latch was based on, or `undefined` while un-latched. Intended for telemetry — nothing in
65
+ * the decision reads it back.
66
+ */
67
+ getLatchDetails(): LatchDetails | undefined;
68
+ /** Whether the runtime (device) criteria have latched. One-way, and never cleared. */
69
+ isLatched(): boolean;
70
+ /**
71
+ * Latch the runtime reason directly, without accumulating evidence for it.
72
+ *
73
+ * The policy latches itself when its own criteria are met, so this exists for callers that have
74
+ * already decided: the plugin replaying the detector's latch transaction, and dev tooling forcing
75
+ * the state by hand. Idempotent, and one-way like every other route to `latched`.
76
+ */
77
+ latch(): void;
78
+ /** Whether the document currently breaches the thresholds. Can go back to false. */
79
+ isDocumentBreached(): boolean;
80
+ /**
81
+ * Evaluate the document reason against the size / node-count / legacy-content-macro thresholds.
82
+ *
83
+ * Walks the whole document, so the caller decides when it is worth paying for: `pm-plugins/main.ts`
84
+ * calls this on load and on `replaceDocument` (e.g. live-to-live page navigation) only, never per
85
+ * transaction. Editing therefore cannot turn the document reason on — a page that grows past the
86
+ * thresholds mid-session is only re-judged the next time it loads — but replacement can still turn
87
+ * it back off.
88
+ */
89
+ evaluateDocument(doc: PMNode): void;
90
+ /**
91
+ * Whether a `doc.nodeSize` delta is large enough to be bulk work rather than typing. A keystroke
92
+ * moves this by 1; a paste, a bulk replace or a document load moves it far more.
93
+ */
94
+ isBulkChange(nodeSizeDelta: number): boolean;
95
+ /**
96
+ * Discard signals for a window. Called for bulk work, which is expensive but transient and
97
+ * self-limiting, so its cost must not be attributed to the device struggling.
98
+ */
99
+ suppress(): void;
100
+ /**
101
+ * Feed one keystroke's input latency (dispatch through to the next animation frame).
102
+ */
103
+ recordInputLatency(durationMs: number): LatchEvaluation;
104
+ /**
105
+ * Feed one `longtask` PerformanceObserver entry.
106
+ */
107
+ recordLongTask(durationMs: number): LatchEvaluation;
108
+ private canRecord;
109
+ /** Snapshot of what the latch was based on. Called before the evidence buffers are cleared. */
110
+ private buildDetails;
111
+ private qualify;
112
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-limited-mode",
3
- "version": "13.0.18",
3
+ "version": "14.1.0",
4
4
  "description": "LimitedMode plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -20,18 +20,22 @@
20
20
  "sideEffects": false,
21
21
  "atlaskit:src": "src/index.ts",
22
22
  "dependencies": {
23
+ "@atlaskit/editor-plugin-analytics": "^17.0.0",
23
24
  "@atlaskit/editor-prosemirror": "^8.0.0",
25
+ "@atlaskit/feature-gate-js-client": "^6.0.0",
26
+ "@atlaskit/platform-feature-experiments": "^0.3.0",
24
27
  "@atlaskit/platform-feature-flags": "^2.2.0",
25
- "@atlaskit/tmp-editor-statsig": "^178.0.0",
28
+ "@atlaskit/tmp-editor-statsig": "^179.0.0",
26
29
  "@babel/runtime": "^7.0.0",
27
30
  "bind-event-listener": "^3.0.0"
28
31
  },
29
32
  "peerDependencies": {
30
- "@atlaskit/editor-common": "^120.16.0",
33
+ "@atlaskit/editor-common": "^121.1.0",
31
34
  "react": "^18.2.0 || ^19.2.0",
32
35
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
33
36
  },
34
37
  "devDependencies": {
38
+ "@atlassian/experiment-test-utils": "^0.2.0",
35
39
  "react": "^19.2.0",
36
40
  "react-intl": "^7.0.0",
37
41
  "typescript": "npm:@typescript/typescript6@^6.0.2"