react-os-shell 4.2.2 → 4.4.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 (58) hide show
  1. package/README.md +5 -0
  2. package/dist/{Browser-TPAIWPZX.js → Browser-YVV3HOKJ.js} +6 -6
  3. package/dist/{Browser-TPAIWPZX.js.map → Browser-YVV3HOKJ.js.map} +1 -1
  4. package/dist/{Calculator-RCNLBRHK.js → Calculator-GBC3FLAJ.js} +5 -5
  5. package/dist/{Calculator-RCNLBRHK.js.map → Calculator-GBC3FLAJ.js.map} +1 -1
  6. package/dist/ConfirmDialog-R7NZVI2V.js +4 -0
  7. package/dist/{ConfirmDialog-QMBUHDXK.js.map → ConfirmDialog-R7NZVI2V.js.map} +1 -1
  8. package/dist/{CurrencyConverter-CM5OTXWF.js → CurrencyConverter-URPZQBNV.js} +5 -5
  9. package/dist/{CurrencyConverter-CM5OTXWF.js.map → CurrencyConverter-URPZQBNV.js.map} +1 -1
  10. package/dist/{Documents-3BPIAGQT.js → Documents-5SFFQZBP.js} +6 -6
  11. package/dist/{Documents-3BPIAGQT.js.map → Documents-5SFFQZBP.js.map} +1 -1
  12. package/dist/{Files-CR3L5C2L.js → Files-YQJRHUGF.js} +8 -8
  13. package/dist/{Files-CR3L5C2L.js.map → Files-YQJRHUGF.js.map} +1 -1
  14. package/dist/{Notepad-C6JHCCF2.js → Notepad-FUQ74K4N.js} +6 -6
  15. package/dist/{Notepad-C6JHCCF2.js.map → Notepad-FUQ74K4N.js.map} +1 -1
  16. package/dist/{PomodoroTimer-EZMBYLQX.js → PomodoroTimer-QQOMBVP3.js} +6 -6
  17. package/dist/{PomodoroTimer-EZMBYLQX.js.map → PomodoroTimer-QQOMBVP3.js.map} +1 -1
  18. package/dist/{Preview-TFDEMTSH.js → Preview-OP4IUJFT.js} +6 -6
  19. package/dist/{Preview-TFDEMTSH.js.map → Preview-OP4IUJFT.js.map} +1 -1
  20. package/dist/{Sidebar-VF2IOOFX.js → Sidebar-E553SOXC.js} +4 -4
  21. package/dist/{Sidebar-VF2IOOFX.js.map → Sidebar-E553SOXC.js.map} +1 -1
  22. package/dist/{Spreadsheet-FRUPALW4.js → Spreadsheet-GADWOYDX.js} +6 -6
  23. package/dist/{Spreadsheet-FRUPALW4.js.map → Spreadsheet-GADWOYDX.js.map} +1 -1
  24. package/dist/{Stock-HL42NPTM.js → Stock-33C4U7CR.js} +5 -5
  25. package/dist/{Stock-HL42NPTM.js.map → Stock-33C4U7CR.js.map} +1 -1
  26. package/dist/{Weather-N74AKS6V.js → Weather-G3XHTB75.js} +5 -5
  27. package/dist/{Weather-N74AKS6V.js.map → Weather-G3XHTB75.js.map} +1 -1
  28. package/dist/{WorldClock-A2EDB57H.js → WorldClock-ZUVI3LBN.js} +5 -5
  29. package/dist/{WorldClock-A2EDB57H.js.map → WorldClock-ZUVI3LBN.js.map} +1 -1
  30. package/dist/apps/index.js +18 -18
  31. package/dist/chunk-3NZSR3ZG.js +20 -0
  32. package/dist/chunk-3NZSR3ZG.js.map +1 -0
  33. package/dist/{chunk-QJXXSMPG.js → chunk-5HCDJPX7.js} +3 -3
  34. package/dist/{chunk-QJXXSMPG.js.map → chunk-5HCDJPX7.js.map} +1 -1
  35. package/dist/{chunk-6Q4KYGMH.js → chunk-DKDD5KXG.js} +14 -3
  36. package/dist/chunk-DKDD5KXG.js.map +1 -0
  37. package/dist/{chunk-SI4XHEMM.js → chunk-EF5W3EXL.js} +285 -19
  38. package/dist/chunk-EF5W3EXL.js.map +1 -0
  39. package/dist/chunk-GDOCYHAG.js +7 -0
  40. package/dist/{chunk-D36OPVAT.js.map → chunk-GDOCYHAG.js.map} +1 -1
  41. package/dist/{chunk-CWFH34LM.js → chunk-LBY7KH2W.js} +3 -3
  42. package/dist/{chunk-CWFH34LM.js.map → chunk-LBY7KH2W.js.map} +1 -1
  43. package/dist/{chunk-5TU6DT3E.js → chunk-LSFZJZTQ.js} +3 -3
  44. package/dist/{chunk-5TU6DT3E.js.map → chunk-LSFZJZTQ.js.map} +1 -1
  45. package/dist/{chunk-RKNJSV2T.js → chunk-PZTYN2RX.js} +5 -5
  46. package/dist/{chunk-RKNJSV2T.js.map → chunk-PZTYN2RX.js.map} +1 -1
  47. package/dist/{chunk-52RFL3OQ.js → chunk-QAKURGOG.js} +3 -3
  48. package/dist/{chunk-52RFL3OQ.js.map → chunk-QAKURGOG.js.map} +1 -1
  49. package/dist/index.d.ts +493 -157
  50. package/dist/index.js +255 -85
  51. package/dist/index.js.map +1 -1
  52. package/package.json +3 -2
  53. package/dist/ConfirmDialog-QMBUHDXK.js +0 -4
  54. package/dist/chunk-6Q4KYGMH.js.map +0 -1
  55. package/dist/chunk-ADJ3CERD.js +0 -31
  56. package/dist/chunk-ADJ3CERD.js.map +0 -1
  57. package/dist/chunk-D36OPVAT.js +0 -7
  58. package/dist/chunk-SI4XHEMM.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -235,6 +235,30 @@ interface ModalProps {
235
235
  }
236
236
  /** Register an Escape interceptor; returns an unregister function. */
237
237
  declare function registerModalEscapeInterceptor(fn: (e: KeyboardEvent) => boolean): () => void;
238
+ /**
239
+ * Is the window identified by `windowKey` the frontmost one?
240
+ *
241
+ * For anything that binds a global shortcut from *outside* the `<Modal>` it
242
+ * belongs to — `UndoProvider` is mounted a level above `PageWindow`, so it has
243
+ * no `ModalActionsContext` to read and cannot use {@link useModalActive}, whose
244
+ * fallback path is made of module globals and therefore answers identically for
245
+ * every caller. That fallback is fine for "is any window active"; it is useless
246
+ * for "is *mine* active", and a per-window listener that asks the wrong
247
+ * question fires in every window at once.
248
+ *
249
+ * `windowKey` is the stable key a window passes to `<Modal windowKey=...>` —
250
+ * `WindowManager`'s `item.id` — not the private per-mount `modalId` that
251
+ * `activationOrder` actually holds. The two are mapped by `mountModal`, and
252
+ * resolving through that map is the whole point: `useIsActiveModal(item.id)`
253
+ * would compare a window key against a `modal-xxxxxx` id and be false for every
254
+ * window rather than true for every window.
255
+ *
256
+ * Omit `windowKey` — or pass one no mounted modal has claimed, which is the
257
+ * case for a `rendersOwnModal` window whose inner `<Modal>` sets no
258
+ * `windowKey` — and this degrades to {@link useModalActive}: the enclosing
259
+ * `<ModalActions>` context if there is one, the global test if there is not.
260
+ */
261
+ declare function useIsActiveWindow(windowKey?: string | null): boolean;
238
262
  declare function toggleExposeMode(): void;
239
263
  declare function exitExposeMode(): void;
240
264
  declare function subscribeExposeHighlight(fn: () => void): () => boolean;
@@ -857,6 +881,236 @@ declare function WindowManagerProvider({ children, windowAccentForRoute }: {
857
881
  windowAccentForRoute?: (route: string) => string | undefined;
858
882
  }): react_jsx_runtime.JSX.Element;
859
883
 
884
+ /**
885
+ * Frame-timing maths + bottleneck attribution for the desktop perf HUD.
886
+ *
887
+ * Split out from `PerfStats.tsx` because the interesting part is the
888
+ * *attribution*, and attribution is pure: given a frame rate and how much of
889
+ * the wall clock the main thread spent blocked, decide whether a janky UI is
890
+ * the GPU's fault or JavaScript's. That decision is what the HUD exists for —
891
+ * "the UI feels laggy" is not actionable, "you are GPU-bound" is — so it lives
892
+ * where a test can pin it.
893
+ *
894
+ * The discriminator: frames are landing late, but the main thread is idle.
895
+ * If JS were the problem the main thread would be busy, so late frames plus an
896
+ * idle thread means the cost is downstream of script — compositing, paint,
897
+ * backdrop-filter. The shell leans hard on frosted glass (`utils/glass.ts`
898
+ * blurs at a 40px radius), which is exactly the kind of work that shows up
899
+ * here and nowhere in a JS profile.
900
+ */
901
+ /** Frame rate at or above which we call the UI smooth. Below 60 because
902
+ * rAF sampling is noisy and a display may be capped at 60Hz anyway — a
903
+ * steady 55 is not a complaint anyone would file. */
904
+ declare const SMOOTH_FPS = 50;
905
+ /** Share of wall-clock time in long tasks that makes JS the prime suspect.
906
+ * `longtask` entries are >50ms by definition, so even 20% means the thread
907
+ * is stalling several times a second — visible as jank on its own. */
908
+ declare const BLOCKED_PCT_CPU = 20;
909
+ type BottleneckKind = 'smooth' | 'gpu' | 'cpu' | 'unknown';
910
+ interface PerfReading {
911
+ /** Frames per second across the sample window. */
912
+ fps: number;
913
+ /** Mean frame interval, ms. */
914
+ frameMs: number;
915
+ /** Slowest single frame in the window, ms — where the jank actually lives. */
916
+ worstMs: number;
917
+ /** Percentage of wall-clock time the main thread spent inside long tasks
918
+ * (0–100), or null when the browser exposes no `longtask` observer.
919
+ * Null is load-bearing: without it we cannot separate GPU from CPU, and
920
+ * guessing would defeat the point of the HUD. */
921
+ blockedPct: number | null;
922
+ }
923
+ interface Verdict {
924
+ kind: BottleneckKind;
925
+ /** Headline, for the HUD's verdict row. */
926
+ label: string;
927
+ /** One line of what to do about it. */
928
+ detail: string;
929
+ }
930
+ /** Turn a window of rAF timestamps into a frame-rate reading.
931
+ * Needs two timestamps to describe one interval; anything less is not yet a
932
+ * measurement and reports zeroes rather than a fabricated 0 fps. */
933
+ declare function summariseFrames(timestamps: number[]): Pick<PerfReading, 'fps' | 'frameMs' | 'worstMs'>;
934
+ /**
935
+ * Attribute a reading to a bottleneck.
936
+ *
937
+ * Order matters: smooth wins outright (nobody cares what a healthy frame rate
938
+ * is *not* bound by), and an unknown block share can only ever downgrade to
939
+ * `unknown` — never to `gpu`. Blaming the GPU because the browser withheld
940
+ * long-task timing would be a confident wrong answer, which is worse than no
941
+ * answer when someone is about to go change settings on the strength of it.
942
+ */
943
+ declare function classify(reading: PerfReading): Verdict;
944
+
945
+ /**
946
+ * Session log for the desktop perf HUD — and the analysis that turns it into
947
+ * a conclusion.
948
+ *
949
+ * A live frame rate tells you the UI is slow *now*. It does not tell you what
950
+ * made it slow, and the person watching it is usually the last person able to
951
+ * say. So while the HUD is on, every reading is stamped with what was
952
+ * happening around it: how many windows were open, which one was on top,
953
+ * whether the user was clicking, typing, scrolling or dragging. The log is
954
+ * exportable, so a laggy machine somewhere else can produce evidence rather
955
+ * than an adjective.
956
+ *
957
+ * The maths here is deliberately non-clever. Median rather than mean, because
958
+ * one 400ms stall would drag a mean somewhere no frame ever was. Buckets
959
+ * rather than a fitted curve, because "6 windows open halves the frame rate"
960
+ * is a sentence someone can act on and a correlation coefficient is not.
961
+ */
962
+
963
+ /** One flush interval's worth of measurement plus its context. Keys are short
964
+ * because thousands of these get JSON-serialised into localStorage and into
965
+ * whatever the user sends afterwards. */
966
+ interface PerfLogRecord {
967
+ /** Milliseconds since logging began. */
968
+ t: number;
969
+ fps: number;
970
+ frameMs: number;
971
+ worstMs: number;
972
+ blockedPct: number | null;
973
+ heapMB: number | null;
974
+ verdict: BottleneckKind;
975
+ /** Open shell windows at the moment of the reading. */
976
+ windows: number;
977
+ /** Identity of the topmost window, when there is one — so a summary can name
978
+ * the screen that was slow rather than just the count. */
979
+ active: string | null;
980
+ clicks: number;
981
+ keys: number;
982
+ scrolls: number;
983
+ /** Milliseconds spent with the pointer down and moving. Dragging is the
984
+ * single most compositing-heavy thing a user does in a window shell, so it
985
+ * gets its own axis rather than being lumped in with clicks. Covers any
986
+ * drag — a window gesture, a desktop icon, a text selection; `moveMs` and
987
+ * `resizeMs` below are the window subset of it. */
988
+ dragMs: number;
989
+ /** Start-menu opens (`perfEvents`). */
990
+ menus: number;
991
+ /** Flyout opens — 2nd- and 3rd-level menus. Hover-opened flyouts fire no
992
+ * click and no keypress, so before this axis existed the frame a submenu
993
+ * painted on was filed as *idle*, which is where the jank people actually
994
+ * report was going missing. */
995
+ submenus: number;
996
+ /** Last menu or flyout opened in the interval, so one can be named. */
997
+ menuKey: string | null;
998
+ /** Milliseconds spent dragging a window by its title bar. */
999
+ moveMs: number;
1000
+ /** Milliseconds spent dragging a window's resize handle. */
1001
+ resizeMs: number;
1002
+ }
1003
+ interface FpsGroup {
1004
+ samples: number;
1005
+ /** Median across the group's *measurable* samples — see `summariseLog`. Zero
1006
+ * when every sample in the group stalled. */
1007
+ medianFps: number;
1008
+ /** Slowest single frame anywhere in the group. For a group of brief
1009
+ * interactions this is the number that matters: a flyout that costs one
1010
+ * 300ms frame barely moves a median but is exactly what the user saw. */
1011
+ worstMs: number;
1012
+ /** Samples too blocked to report a frame rate at all. Kept beside the median
1013
+ * rather than folded into it, so a group that is entirely stalls reads as
1014
+ * the emergency it is instead of as a 0 fps reading. */
1015
+ stalls: number;
1016
+ }
1017
+ /**
1018
+ * What the user was doing during a sample, reduced to one label.
1019
+ *
1020
+ * A single interval routinely carries several axes at once — opening a flyout
1021
+ * involves a click, a pointer move and a menu mark — so the ranking below
1022
+ * decides which one the sample is filed under. It runs most-specific first:
1023
+ * the deliberate, expensive gesture beats the incidental click that came with
1024
+ * it, because filing a janky submenu open under "click" is how you end up
1025
+ * optimising the wrong thing.
1026
+ */
1027
+ type ActivityKind = 'submenu' | 'menu' | 'resize' | 'move' | 'scroll' | 'type' | 'click' | 'idle';
1028
+ /** File a sample under the one thing most likely to have cost it. */
1029
+ declare function classifyActivity(r: PerfLogRecord): ActivityKind;
1030
+ interface LogSummary {
1031
+ samples: number;
1032
+ durationMs: number;
1033
+ medianFps: number;
1034
+ worstFrameMs: number;
1035
+ /** Fraction of samples in each verdict, 0–1. */
1036
+ verdictShare: Record<BottleneckKind, number>;
1037
+ /** Split by whether the user was doing anything. The gap between these two
1038
+ * is the headline: a desktop that is smooth at rest and janky in use has a
1039
+ * rendering cost that only shows up under interaction. */
1040
+ interacting: FpsGroup | null;
1041
+ idle: FpsGroup | null;
1042
+ /** Frame rate per kind of interaction, worst-first — the answer to "which
1043
+ * gesture is slow", which is the question a report is usually filed to
1044
+ * ask. */
1045
+ byActivity: (FpsGroup & {
1046
+ kind: ActivityKind;
1047
+ })[];
1048
+ /** Frame rate against how many windows were open. */
1049
+ byWindowCount: (FpsGroup & {
1050
+ windows: number;
1051
+ })[];
1052
+ /** Windows ranked worst-first, so the slowest screen names itself. */
1053
+ worstWindows: (FpsGroup & {
1054
+ key: string;
1055
+ })[];
1056
+ /** Menus and flyouts ranked worst-first, same idea one layer up. */
1057
+ worstMenus: (FpsGroup & {
1058
+ key: string;
1059
+ })[];
1060
+ }
1061
+ /** Records kept in memory before the oldest are dropped. At one record per
1062
+ * 500ms this is about 20 minutes — long enough to catch an intermittent
1063
+ * stall, small enough to serialise without thinking about it. */
1064
+ declare const LOG_CAP = 2400;
1065
+ /** Minimum samples before a group is reported. One unlucky reading is not a
1066
+ * finding, and a summary that names a window off a single sample invites
1067
+ * someone to go optimise the wrong screen. */
1068
+ declare const MIN_GROUP_SAMPLES = 4;
1069
+ /** The floor for menu and gesture groups. Lower because these events are rare
1070
+ * by construction — a flyout opens inside a single 500ms interval, not across
1071
+ * twenty of them, so holding them to the window floor would suppress exactly
1072
+ * the findings the axes were added for. Two still rules out a one-off, and
1073
+ * every group carries its own `samples` for whoever reads it. */
1074
+ declare const MIN_EVENT_SAMPLES = 2;
1075
+ /** Append with a cap, oldest dropped first. Returns a new array — callers hold
1076
+ * this in React state, where mutation would not re-render. */
1077
+ declare function appendRecord(log: PerfLogRecord[], record: PerfLogRecord, cap?: number): PerfLogRecord[];
1078
+ /** True when the user was doing something during the interval. */
1079
+ declare function isInteracting(r: PerfLogRecord): boolean;
1080
+ /** Reduce a log to the handful of statements worth acting on. */
1081
+ declare function summariseLog(log: PerfLogRecord[]): LogSummary;
1082
+ /** Flat CSV, for opening in a spreadsheet without writing any code. */
1083
+ declare function toCsv(log: PerfLogRecord[]): string;
1084
+
1085
+ /** A finished report, handed to the host to file. The JSON is pre-serialised
1086
+ * because the host's job is to attach it, not to re-derive it; `summary` and
1087
+ * `verdict` come along so a host can title or route the report without
1088
+ * parsing the attachment back apart. */
1089
+ interface PerfReport {
1090
+ /** What the user typed about what they were doing. May be empty. */
1091
+ message: string;
1092
+ /** Suggested attachment filename, stamped with the local time. */
1093
+ filename: string;
1094
+ /** The whole report — environment, summary and every raw record. */
1095
+ json: string;
1096
+ summary: LogSummary;
1097
+ /** The HUD's current headline, e.g. "GPU-bound (compositing)". */
1098
+ verdict: string;
1099
+ }
1100
+ interface PerfStatsProps {
1101
+ /** Dismiss handler — the shell wires this to turn the pref back off, so the
1102
+ * HUD can be closed from itself rather than only from Preferences. */
1103
+ onClose?: () => void;
1104
+ /** File the report through the host's own feedback channel — the whole point
1105
+ * of the HUD, since a log that reaches nobody fixes nothing. Rejecting
1106
+ * surfaces the error and keeps the composer open with the text intact.
1107
+ * Without it the button downloads the same JSON instead, so the shell stays
1108
+ * usable standalone. */
1109
+ onSubmit?: (report: PerfReport) => void | Promise<void>;
1110
+ className?: string;
1111
+ }
1112
+ declare function PerfStats({ onClose, onSubmit, className }: PerfStatsProps): react_jsx_runtime.JSX.Element;
1113
+
860
1114
  /**
861
1115
  * INTERNAL stub — Desktop's About modal references the consumer-side
862
1116
  * changelog. The package ships no built-in changelog; consumer wires their
@@ -945,6 +1199,12 @@ interface DesktopHostConfig {
945
1199
  * calls this. Lets a consumer that files feedback natively (the shell itself
946
1200
  * dropped bug reporting in v3.0.0) surface the familiar right-click entry. */
947
1201
  onReportBug?: () => void;
1202
+ /** File a performance report from the desktop perf HUD through the same
1203
+ * feedback channel, with the session log attached. Unset, the HUD's button
1204
+ * downloads the report instead — which is a strictly worse outcome, because
1205
+ * a file on someone's Downloads folder is not a bug report. Rejecting shows
1206
+ * the error in the HUD and keeps what the user typed. */
1207
+ onSubmitPerfReport?: (report: PerfReport) => void | Promise<void>;
948
1208
  }
949
1209
  declare function DesktopHostProvider({ value, children }: {
950
1210
  value: DesktopHostConfig;
@@ -2154,168 +2414,47 @@ interface MetricBarProps {
2154
2414
  }
2155
2415
  declare function MetricBar({ label, value, max, warn, crit, severity, detail, formatValue, emptyLabel, size, ariaLabel, className, }: MetricBarProps): react_jsx_runtime.JSX.Element;
2156
2416
 
2157
- interface PerfStatsProps {
2158
- /** Dismiss handler — the shell wires this to turn the pref back off, so the
2159
- * HUD can be closed from itself rather than only from Preferences. */
2160
- onClose?: () => void;
2161
- className?: string;
2162
- }
2163
- declare function PerfStats({ onClose, className }: PerfStatsProps): react_jsx_runtime.JSX.Element;
2164
-
2165
- /**
2166
- * Frame-timing maths + bottleneck attribution for the desktop perf HUD.
2167
- *
2168
- * Split out from `PerfStats.tsx` because the interesting part is the
2169
- * *attribution*, and attribution is pure: given a frame rate and how much of
2170
- * the wall clock the main thread spent blocked, decide whether a janky UI is
2171
- * the GPU's fault or JavaScript's. That decision is what the HUD exists for —
2172
- * "the UI feels laggy" is not actionable, "you are GPU-bound" is — so it lives
2173
- * where a test can pin it.
2174
- *
2175
- * The discriminator: frames are landing late, but the main thread is idle.
2176
- * If JS were the problem the main thread would be busy, so late frames plus an
2177
- * idle thread means the cost is downstream of script — compositing, paint,
2178
- * backdrop-filter. The shell leans hard on frosted glass (`utils/glass.ts`
2179
- * blurs at a 40px radius), which is exactly the kind of work that shows up
2180
- * here and nowhere in a JS profile.
2181
- */
2182
- /** Frame rate at or above which we call the UI smooth. Below 60 because
2183
- * rAF sampling is noisy and a display may be capped at 60Hz anyway — a
2184
- * steady 55 is not a complaint anyone would file. */
2185
- declare const SMOOTH_FPS = 50;
2186
- /** Share of wall-clock time in long tasks that makes JS the prime suspect.
2187
- * `longtask` entries are >50ms by definition, so even 20% means the thread
2188
- * is stalling several times a second — visible as jank on its own. */
2189
- declare const BLOCKED_PCT_CPU = 20;
2190
- type BottleneckKind = 'smooth' | 'gpu' | 'cpu' | 'unknown';
2191
- interface PerfReading {
2192
- /** Frames per second across the sample window. */
2193
- fps: number;
2194
- /** Mean frame interval, ms. */
2195
- frameMs: number;
2196
- /** Slowest single frame in the window, ms — where the jank actually lives. */
2197
- worstMs: number;
2198
- /** Percentage of wall-clock time the main thread spent inside long tasks
2199
- * (0–100), or null when the browser exposes no `longtask` observer.
2200
- * Null is load-bearing: without it we cannot separate GPU from CPU, and
2201
- * guessing would defeat the point of the HUD. */
2202
- blockedPct: number | null;
2203
- }
2204
- interface Verdict {
2205
- kind: BottleneckKind;
2206
- /** Headline, for the HUD's verdict row. */
2207
- label: string;
2208
- /** One line of what to do about it. */
2209
- detail: string;
2210
- }
2211
- /** Turn a window of rAF timestamps into a frame-rate reading.
2212
- * Needs two timestamps to describe one interval; anything less is not yet a
2213
- * measurement and reports zeroes rather than a fabricated 0 fps. */
2214
- declare function summariseFrames(timestamps: number[]): Pick<PerfReading, 'fps' | 'frameMs' | 'worstMs'>;
2215
2417
  /**
2216
- * Attribute a reading to a bottleneck.
2418
+ * Shell interaction marks, folded into every perf-log record.
2217
2419
  *
2218
- * Order matters: smooth wins outright (nobody cares what a healthy frame rate
2219
- * is *not* bound by), and an unknown block share can only ever downgrade to
2220
- * `unknown` never to `gpu`. Blaming the GPU because the browser withheld
2221
- * long-task timing would be a confident wrong answer, which is worse than no
2222
- * answer when someone is about to go change settings on the strength of it.
2223
- */
2224
- declare function classify(reading: PerfReading): Verdict;
2225
-
2226
- /**
2227
- * Session log for the desktop perf HUD — and the analysis that turns it into
2228
- * a conclusion.
2420
+ * The HUD can see that frames were dropped and it can see that the pointer
2421
+ * moved, but "the pointer moved" covers wandering across the desktop and
2422
+ * opening a third-level flyout, and only one of those repaints a frosted
2423
+ * surface. The first version of the log conflated them, so the readings that
2424
+ * mattered most the frame the start menu opened on, the frame a window was
2425
+ * dragged across — arrived indistinguishable from an idle mouse. A report full
2426
+ * of anonymous samples points at nothing.
2229
2427
  *
2230
- * A live frame rate tells you the UI is slow *now*. It does not tell you what
2231
- * made it slow, and the person watching it is usually the last person able to
2232
- * say. So while the HUD is on, every reading is stamped with what was
2233
- * happening around it: how many windows were open, which one was on top,
2234
- * whether the user was clicking, typing, scrolling or dragging. The log is
2235
- * exportable, so a laggy machine somewhere else can produce evidence rather
2236
- * than an adjective.
2428
+ * So the places that do the expensive things say so. Menus mark themselves when
2429
+ * they open; window drags and resizes mark themselves for as long as they run.
2430
+ * Everything here is a plain counter drained once per flush interval no
2431
+ * subscriptions, no allocation per event, nothing that would make marking an
2432
+ * event cost more than the event.
2237
2433
  *
2238
- * The maths here is deliberately non-clever. Median rather than mean, because
2239
- * one 400ms stall would drag a mean somewhere no frame ever was. Buckets
2240
- * rather than a fitted curve, because "6 windows open halves the frame rate"
2241
- * is a sentence someone can act on and a correlation coefficient is not.
2242
- */
2243
-
2244
- /** One flush interval's worth of measurement plus its context. Keys are short
2245
- * because thousands of these get JSON-serialised into localStorage and into
2246
- * whatever the user emails afterwards. */
2247
- interface PerfLogRecord {
2248
- /** Milliseconds since logging began. */
2249
- t: number;
2250
- fps: number;
2251
- frameMs: number;
2252
- worstMs: number;
2253
- blockedPct: number | null;
2254
- heapMB: number | null;
2255
- verdict: BottleneckKind;
2256
- /** Open shell windows at the moment of the reading. */
2257
- windows: number;
2258
- /** Identity of the topmost window, when there is one — so a summary can name
2259
- * the screen that was slow rather than just the count. */
2260
- active: string | null;
2261
- clicks: number;
2262
- keys: number;
2263
- scrolls: number;
2264
- /** Milliseconds spent mid-drag during the interval. Dragging is the single
2265
- * most compositing-heavy thing a user does in a window shell, so it gets
2266
- * its own axis rather than being lumped in with clicks. */
2267
- dragMs: number;
2268
- }
2269
- interface FpsGroup {
2270
- samples: number;
2271
- medianFps: number;
2272
- }
2273
- interface LogSummary {
2274
- samples: number;
2275
- durationMs: number;
2276
- medianFps: number;
2277
- worstFrameMs: number;
2278
- /** Fraction of samples in each verdict, 0–1. */
2279
- verdictShare: Record<BottleneckKind, number>;
2280
- /** Split by whether the user was doing anything. The gap between these two
2281
- * is the headline: a desktop that is smooth at rest and janky in use has a
2282
- * rendering cost that only shows up under interaction. */
2283
- interacting: FpsGroup | null;
2284
- idle: FpsGroup | null;
2285
- /** Frame rate against how many windows were open. */
2286
- byWindowCount: (FpsGroup & {
2287
- windows: number;
2288
- })[];
2289
- /** Windows ranked worst-first, so the slowest screen names itself. */
2290
- worstWindows: (FpsGroup & {
2291
- key: string;
2292
- })[];
2293
- }
2294
- /** Records kept in memory before the oldest are dropped. At one record per
2295
- * 500ms this is about 20 minutes — long enough to catch an intermittent
2296
- * stall, small enough to serialise without thinking about it. */
2297
- declare const LOG_CAP = 2400;
2298
- /** Minimum samples before a group is reported. One unlucky reading is not a
2299
- * finding, and a summary that names a window off a single sample invites
2300
- * someone to go optimise the wrong screen. */
2301
- declare const MIN_GROUP_SAMPLES = 4;
2302
- /** Append with a cap, oldest dropped first. Returns a new array — callers hold
2303
- * this in React state, where mutation would not re-render. */
2304
- declare function appendRecord(log: PerfLogRecord[], record: PerfLogRecord, cap?: number): PerfLogRecord[];
2305
- /** True when the user was doing something during the interval. */
2306
- declare function isInteracting(r: PerfLogRecord): boolean;
2307
- /**
2308
- * Reduce a log to the handful of statements worth acting on.
2434
+ * Marks accumulate only while the HUD is mounted (`setPerfCollecting`). That is
2435
+ * not really about cost incrementing a number is free but about honesty: a
2436
+ * counter that had been climbing since page load would attribute a morning's
2437
+ * worth of menu opens to whichever 500ms interval happened to drain it first.
2438
+ */
2439
+ /** Which menu layer opened. The distinction is the point: the root menu is one
2440
+ * surface appearing, a flyout is a second one appearing *over* it, and the
2441
+ * cost of the second is what people report. */
2442
+ type MenuLayer = 'menu' | 'submenu';
2443
+ /** Record that a menu surface opened. `key` names it (a section label, a route)
2444
+ * so the summary can rank flyouts against each other. */
2445
+ declare function markMenuOpen(layer: MenuLayer, key: string): void;
2446
+ /**
2447
+ * Record a window drag or resize for as long as it runs. Returns the end
2448
+ * function; calling it twice adds the span once.
2309
2449
  *
2310
- * Only samples with a real frame rate are measured a reading taken while the
2311
- * main thread was too blocked to deliver frames carries fps 0, and letting
2312
- * those into a median would report a frame rate the display never showed.
2313
- * They still count toward `verdictShare`, which is where that condition
2314
- * belongs.
2450
+ * Duration rather than a count because these are the gestures whose *cost is
2451
+ * their length* a drag that stutters for four seconds and a drag that lasted
2452
+ * one frame are the same event and very different reports. The span is credited
2453
+ * to the interval it ends in, which can straddle a flush boundary; that is
2454
+ * accepted rather than apportioned, because a drag long enough to straddle two
2455
+ * intervals is already the thing being investigated.
2315
2456
  */
2316
- declare function summariseLog(log: PerfLogRecord[]): LogSummary;
2317
- /** Flat CSV, for opening in a spreadsheet without writing any code. */
2318
- declare function toCsv(log: PerfLogRecord[]): string;
2457
+ declare function beginWindowGesture(kind: 'move' | 'resize'): () => void;
2319
2458
 
2320
2459
  /**
2321
2460
  * Semantic role of a column, used to auto-map CSV columns to fields and to
@@ -2428,6 +2567,23 @@ interface MergeBulkOptions<T extends BaseItem> {
2428
2567
  }
2429
2568
  declare function mergeBulkItems<T extends BaseItem>(options: MergeBulkOptions<T>): MergeBulkResult<T>;
2430
2569
 
2570
+ interface UndoControlsProps {
2571
+ /** Extra classes for the wrapping row. */
2572
+ className?: string;
2573
+ }
2574
+ /**
2575
+ * Undo/Redo for the enclosing form, reading the stack from {@link UndoProvider}.
2576
+ *
2577
+ * Put it wherever the form's actions live — a window header, a section header,
2578
+ * beside the save button. The keys work without it; this is for discoverability
2579
+ * and for the mouse. Both buttons stay rendered and go disabled, so the row
2580
+ * does not reflow the moment there is something to undo.
2581
+ *
2582
+ * Renders nothing for a user who may not edit the record — dead buttons on a
2583
+ * read-only form read as something broken rather than something withheld.
2584
+ */
2585
+ declare function UndoControls({ className }: UndoControlsProps): react_jsx_runtime.JSX.Element | null;
2586
+
2431
2587
  /** Default item shape — overridable via the accessor props for any other shape. */
2432
2588
  interface ContainerFillItem {
2433
2589
  quantity?: number | null;
@@ -2895,4 +3051,184 @@ declare function useNewHotkey(callback: () => void): void;
2895
3051
  */
2896
3052
  declare function useEditHotkey(callback: (() => void) | null): void;
2897
3053
 
2898
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, type AccordionItem, type AccordionProps, AuthScreen, type AuthScreenProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarSize, type AvatarStatus, BLOCKED_PCT_CPU, Banner, type BannerProps, type BannerTone, BarChart, type BarChartProps, BehaviorPanel, type BottleneckKind, type BreadcrumbItem, Breadcrumbs, type BreadcrumbsProps, type BulkColumn, type BulkColumnKind, BulkImportGrid, type BulkImportGridProps, type BulkRow, Button, type ButtonProps, type ButtonSize, type ButtonVariant, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, Card, type CardProps, type CellStyle, ChangePasswordForm, type ChangePasswordFormProps, type ChangelogEntry, ChatTemplate, Checkbox, type CheckboxProps, CheckoutTemplate, type ClockCalendarConfig, ColoredBadge, type ColoredBadgeProps, type ColumnDef, ConfirmProvider, ContainerFillChart, type ContainerFillChartProps, type ContainerFillItem, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, type CustomizationSection, DEV_BANNER_TEXT, DashboardTemplate, DataTablePage, DateRangePicker, type DateRangePickerProps, Desktop, type DesktopContextMenuItem, type DesktopHostConfig, DesktopHostProvider, DevIndicator, DocFavStar, DonutChart, type DonutChartProps, type DonutSegment, type DuplicateGroup, ENTER, EditableGrid, type EditableGridProps, EmailTemplate, EmptyState, type EmptyStateProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListContextAction, type EntityListProps, ErrorPage, type ErrorPageProps, FilterBar, type FilterOption, FormField, type FormFieldProps, FormLayoutPage, type FpsGroup, GLASS_DIVIDER, GLASS_INPUT_BG, GalleryTemplate, GlobalSearch, type GridColumn, type HealthCheckResult, HelpCenter, type HelpCenterDoc, type HelpCenterProps, INPUT_BASE, ImageAnnotator, type ImageAnnotatorHandle, type ImageAnnotatorProps, Input, type InputProps, Kanban, type KanbanColumn, type KanbanProps, LOG_CAP, Label, type LabelProps, Layout, type LayoutProps, ListFooter, ListLoadError, type ListLoadErrorProps, LoadingSpinner, type LoadingSpinnerProps, type LogSummary, MIN_GROUP_SAMPLES, MOD, Markdown, type MarkdownProps, MediaUploadField, type MediaUploadFieldProps, MediaUploadGrid, type MediaUploadGridItem, type MediaUploadGridProps, type MergeBulkOptions, type MergeBulkResult, MetricBar, type MetricBarProps, type Milestone, type MilestoneKind, MilestoneTimeline, type MilestoneTimelineProps, type MobileAppConfig, Modal, ModalActions, NativeSelect, NotificationBell, type NotificationsConfig, PageHeader, type PageHeaderProps, type PaginatedResponse, Pagination, type PaginationProps, PdfActionButton, type PdfActionButtonProps, type PerfLogRecord, type PerfReading, PerfStats, type PerfStatsProps, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, Radio, type RadioProps, ResizableTable, SHIFT, SMOOTH_FPS, type SearchConfig, type SearchProvider, type SearchResult, type SearchableOption, SearchableSelect, type SearchableSelectProps, Select, type SelectOption, type SelectProps, type SemanticGroup, ServerStatusIndicator, type ServerStatusIndicatorProps, type ServerStatusUser, type SeverityTone, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, SidebarActionButton, type SidebarActionButtonProps, SidebarGroupLabel, SidebarLayout, type SidebarLayoutProps, SidebarNavItem, type SortState, SoundsPanel, Sparkline, type SparklineProps, StartMenu, StatCard, type StatCardProps, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, type TabItem, Tabs, type TabsProps, Textarea, type TextareaProps, type TodoProvider, type TodoTask, Tooltip, type TooltipProps, TopNav, type TopNavItem, type TopNavProps, VERSION, type Verdict, WidgetManager, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowRegistry, WindowTitle, appendRecord as appendPerfRecord, applyDevTitle, classify as classifyPerf, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, findDuplicateKeys, formatDate, getActiveWindowRoute, getExposeHighlight, getWindowPosition, glassStyle, inputClasses, isDevEnv, isInteracting, isMac, isSeverityTone, mediaFileName, mergeBulkItems, toCsv as perfLogToCsv, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellNavIcons, setShellTodoProvider, setWindowDefaultPosition, setWindowPosition, severityOf, subscribeExposeHighlight, summariseFrames, summariseLog as summarisePerfLog, toISODate, toast, toggleExposeMode, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useFilters, useInfiniteScroll, useLocalStoragePrefs, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
3054
+ interface UndoProviderProps {
3055
+ children: React.ReactNode;
3056
+ /**
3057
+ * Whether this user may edit the record. Undo is offered to everyone who
3058
+ * can — it is not gated on role or seniority — and withheld from a reader
3059
+ * only because they have nothing to take back. Defaults to true.
3060
+ */
3061
+ canEdit?: boolean;
3062
+ /**
3063
+ * Permission codes that count as "may edit", checked through
3064
+ * `ShellAuthProvider`. Combined with `canEdit`, so a form that already knows
3065
+ * it is read-only stays read-only whatever the codes say. Omit to rely on
3066
+ * `canEdit` alone.
3067
+ */
3068
+ perms?: string[];
3069
+ /**
3070
+ * The window this stack belongs to — the same stable key its `<Modal>` gets
3071
+ * as `windowKey`, which for a `WindowManager` window is `item.id`.
3072
+ *
3073
+ * This is what keeps ⌘Z inside the window the user is looking at. The
3074
+ * provider binds its hotkey on `window`, so every open window's provider sees
3075
+ * every keypress; the id is how one of them recognises the press as its own.
3076
+ * Without it there is no per-window identity to test and the best available
3077
+ * answer is "is any window active", which is true in all of them at once.
3078
+ *
3079
+ * Omit it for a provider nested inside a `<Modal>` — there the enclosing
3080
+ * modal's own context answers the question — or where there are no windows
3081
+ * at all.
3082
+ */
3083
+ windowId?: string;
3084
+ }
3085
+ /**
3086
+ * Undo/redo for everything in one open form.
3087
+ *
3088
+ * Wrap a form window in it, register each piece of its state with
3089
+ * {@link useUndoable}, and the whole form shares one stack: a field edit, a
3090
+ * line added, a bulk import are all steps in the same history, undone newest
3091
+ * first. Two open windows have two independent stacks, and passing
3092
+ * {@link UndoProviderProps.windowId} is what keeps them independent in
3093
+ * practice — see that prop.
3094
+ *
3095
+ * History is the unsaved edit only. It lives with the mounted provider and
3096
+ * dies with it. Both ends of the edit are the caller's to mark: `baseline()`
3097
+ * once the record has arrived, so the load is the starting point rather than
3098
+ * the first thing ⌘Z takes back, and `clear()` at a save, past which "earlier"
3099
+ * is on the server and not something a form can reach.
3100
+ *
3101
+ * Anyone who may edit the record gets it — it is not a privileged feature, and
3102
+ * the user most helped by an undo is the one least sure of what they just did.
3103
+ * A reader is the only one it is withheld from, and only because there is
3104
+ * nothing for them to take back. Note that `canEdit` is the caller's claim, and
3105
+ * the shell-level provider `WindowManager` mounts around every window has no
3106
+ * way to make it: it knows nothing about the record inside. That one defaults
3107
+ * to enabled, and a read-only form states the fact by nesting its own
3108
+ * `<UndoProvider canEdit={false}>`, which shadows it.
3109
+ */
3110
+ declare function UndoProvider({ children, canEdit, perms, windowId }: UndoProviderProps): react_jsx_runtime.JSX.Element;
3111
+ interface UndoControlsApi {
3112
+ undo: () => void;
3113
+ redo: () => void;
3114
+ canUndo: boolean;
3115
+ canRedo: boolean;
3116
+ /** What Undo/Redo would act on, for a button title. Null when unavailable. */
3117
+ undoLabel: string | null;
3118
+ redoLabel: string | null;
3119
+ /** End the history — call after a successful save. */
3120
+ clear: () => void;
3121
+ /**
3122
+ * Make the form as it stands the starting point, discarding the history.
3123
+ *
3124
+ * Call it once the record has arrived from the server. State filled from a
3125
+ * fetch is a change like any other as far as the slices are concerned, so
3126
+ * without this the load itself is the oldest step and the user's first ⌘Z
3127
+ * empties the form they were just given:
3128
+ *
3129
+ * const { data } = useQuery(...);
3130
+ * const { baseline } = useUndo();
3131
+ * useEffect(() => { if (data) baseline(); }, [data, baseline]);
3132
+ *
3133
+ * Worth calling on every arrival, not just the first: a window kept open
3134
+ * across a refetch, or one whose entity changes underneath it, wants the
3135
+ * same treatment, and the call is idempotent for a form nobody has touched.
3136
+ */
3137
+ baseline: () => void;
3138
+ /** False when the user may not edit this record, so custom UI can hide
3139
+ * itself the way `UndoControls` does. */
3140
+ enabled: boolean;
3141
+ }
3142
+ /**
3143
+ * The enclosing form's undo stack, for custom UI or to `clear()` on save.
3144
+ * Everything is inert outside an {@link UndoProvider}.
3145
+ */
3146
+ declare function useUndo(): UndoControlsApi;
3147
+ interface UndoableOptions {
3148
+ /** Names the step in a button title: `"qty"`, `"line items"`. */
3149
+ label: string;
3150
+ /**
3151
+ * Consecutive changes sharing a key fold into one step — pass the field name
3152
+ * so a run of typing is one Undo rather than one per keystroke. Omit for a
3153
+ * change that is already whole, like a bulk import or a deleted row.
3154
+ */
3155
+ coalesceKey?: string | null;
3156
+ }
3157
+ /**
3158
+ * Put one piece of the form's state under the window's undo stack.
3159
+ *
3160
+ * `value` is watched; when it changes, the form as it stood beforehand becomes
3161
+ * a step. `apply` puts a value back — the same setter the form already uses.
3162
+ *
3163
+ * const [items, setItems] = useState<Line[]>([]);
3164
+ * useUndoable(items, setItems, { label: 'line items' });
3165
+ *
3166
+ * Registering more than one slice is the point: a step snapshots all of them
3167
+ * together, so undoing restores a coherent form rather than one slice out of
3168
+ * step with the rest.
3169
+ *
3170
+ * `value` must be the state itself, not something derived from it on the way
3171
+ * in. A change is detected by identity, so `useUndoable(rows.filter(r => r.on),
3172
+ * ...)` hands over a new array on every render and reads as a change every
3173
+ * time — and since recording a step re-renders the provider, that closes a
3174
+ * loop at render speed. The provider trips a runaway guard and says so rather
3175
+ * than letting the tab hang, but the fix is at the call site: register the
3176
+ * state, and derive from it afterwards.
3177
+ */
3178
+ declare function useUndoable<T>(value: T, apply: (next: T) => void, opts: UndoableOptions): void;
3179
+ /**
3180
+ * `useState`, with the value in the window's undo stack.
3181
+ *
3182
+ * Written to be a rename rather than an extra line, because the forms this is
3183
+ * for hold their state in dozens of separate `useState` calls — one of them has
3184
+ * forty-three. Adopting a form is then a per-line edit:
3185
+ *
3186
+ * const [supplier, setSupplier] = useState('');
3187
+ * const [supplier, setSupplier] = useUndoableState('', { label: 'supplier' });
3188
+ *
3189
+ * Which also makes the choice legible: state left as plain `useState` is state
3190
+ * deliberately kept out of the history. Keep it that way for anything that is
3191
+ * not the user's input — a search box, fetched data, validation output, an
3192
+ * initialisation guard. Undoing those puts stale results back on screen, and a
3193
+ * reverted guard can re-fire the effect it exists to suppress.
3194
+ *
3195
+ * Pass `coalesceKey` for anything typed into, so a run of keystrokes is one
3196
+ * Undo; the field's own name is the obvious key.
3197
+ */
3198
+ declare function useUndoableState<T>(initial: T | (() => T), opts: UndoableOptions): [T, React.Dispatch<React.SetStateAction<T>>];
3199
+
3200
+ /**
3201
+ * Undo/redo for one open form — the pure half.
3202
+ *
3203
+ * A form window owns a single stack covering everything in it: its fields, its
3204
+ * line-items table, a bulk import. One ⌘Z steps back the last thing the user
3205
+ * did, whatever part of the form it happened in.
3206
+ *
3207
+ * The stack holds snapshots, not diffs. A step stores the value of every
3208
+ * registered slice **as it was before the change**, so undoing restores the
3209
+ * whole form to a coherent moment rather than replaying one slice out of step
3210
+ * with the others. Forms are small — a few dozen fields and some line items —
3211
+ * so whole-form snapshots stay cheap and the logic stays honest.
3212
+ *
3213
+ * Scope is the unsaved edit. History lives with the open window and dies with
3214
+ * it; nothing here reverses a saved record.
3215
+ */
3216
+ /** Registered slice id → that slice's value at the time of the snapshot. */
3217
+ type UndoSnapshot = Record<string, unknown>;
3218
+ interface UndoStep {
3219
+ /** The form as it stood before this change. Undo restores exactly this. */
3220
+ values: UndoSnapshot;
3221
+ /** What the step was, for a button title: `"qty"`, `"import of 5 lines"`. */
3222
+ label: string;
3223
+ /**
3224
+ * Consecutive changes sharing a non-null key fold into one step — typing in
3225
+ * a field is one Undo, not one per keystroke. Null never folds.
3226
+ */
3227
+ coalesceKey: string | null;
3228
+ }
3229
+ interface UndoState {
3230
+ past: UndoStep[];
3231
+ future: UndoStep[];
3232
+ }
3233
+
3234
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, type AccordionItem, type AccordionProps, type ActivityKind, AuthScreen, type AuthScreenProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarSize, type AvatarStatus, BLOCKED_PCT_CPU, Banner, type BannerProps, type BannerTone, BarChart, type BarChartProps, BehaviorPanel, type BottleneckKind, type BreadcrumbItem, Breadcrumbs, type BreadcrumbsProps, type BulkColumn, type BulkColumnKind, BulkImportGrid, type BulkImportGridProps, type BulkRow, Button, type ButtonProps, type ButtonSize, type ButtonVariant, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, Card, type CardProps, type CellStyle, ChangePasswordForm, type ChangePasswordFormProps, type ChangelogEntry, ChatTemplate, Checkbox, type CheckboxProps, CheckoutTemplate, type ClockCalendarConfig, ColoredBadge, type ColoredBadgeProps, type ColumnDef, ConfirmProvider, ContainerFillChart, type ContainerFillChartProps, type ContainerFillItem, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, type CustomizationSection, DEV_BANNER_TEXT, DashboardTemplate, DataTablePage, DateRangePicker, type DateRangePickerProps, Desktop, type DesktopContextMenuItem, type DesktopHostConfig, DesktopHostProvider, DevIndicator, DocFavStar, DonutChart, type DonutChartProps, type DonutSegment, type DuplicateGroup, ENTER, EditableGrid, type EditableGridProps, EmailTemplate, EmptyState, type EmptyStateProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListContextAction, type EntityListProps, ErrorPage, type ErrorPageProps, FilterBar, type FilterOption, FormField, type FormFieldProps, FormLayoutPage, type FpsGroup, GLASS_DIVIDER, GLASS_INPUT_BG, GalleryTemplate, GlobalSearch, type GridColumn, type HealthCheckResult, HelpCenter, type HelpCenterDoc, type HelpCenterProps, INPUT_BASE, ImageAnnotator, type ImageAnnotatorHandle, type ImageAnnotatorProps, Input, type InputProps, Kanban, type KanbanColumn, type KanbanProps, LOG_CAP, Label, type LabelProps, Layout, type LayoutProps, ListFooter, ListLoadError, type ListLoadErrorProps, LoadingSpinner, type LoadingSpinnerProps, type LogSummary, MIN_EVENT_SAMPLES, MIN_GROUP_SAMPLES, MOD, Markdown, type MarkdownProps, MediaUploadField, type MediaUploadFieldProps, MediaUploadGrid, type MediaUploadGridItem, type MediaUploadGridProps, type MenuLayer, type MergeBulkOptions, type MergeBulkResult, MetricBar, type MetricBarProps, type Milestone, type MilestoneKind, MilestoneTimeline, type MilestoneTimelineProps, type MobileAppConfig, Modal, ModalActions, NativeSelect, NotificationBell, type NotificationsConfig, PageHeader, type PageHeaderProps, type PaginatedResponse, Pagination, type PaginationProps, PdfActionButton, type PdfActionButtonProps, type PerfLogRecord, type PerfReading, type PerfReport, PerfStats, type PerfStatsProps, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, Radio, type RadioProps, ResizableTable, SHIFT, SMOOTH_FPS, type SearchConfig, type SearchProvider, type SearchResult, type SearchableOption, SearchableSelect, type SearchableSelectProps, Select, type SelectOption, type SelectProps, type SemanticGroup, ServerStatusIndicator, type ServerStatusIndicatorProps, type ServerStatusUser, type SeverityTone, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, SidebarActionButton, type SidebarActionButtonProps, SidebarGroupLabel, SidebarLayout, type SidebarLayoutProps, SidebarNavItem, type SortState, SoundsPanel, Sparkline, type SparklineProps, StartMenu, StatCard, type StatCardProps, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, type TabItem, Tabs, type TabsProps, Textarea, type TextareaProps, type TodoProvider, type TodoTask, Tooltip, type TooltipProps, TopNav, type TopNavItem, type TopNavProps, UndoControls, type UndoControlsApi, type UndoControlsProps, UndoProvider, type UndoProviderProps, type UndoSnapshot, type UndoState, type UndoStep, type UndoableOptions, VERSION, type Verdict, WidgetManager, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowRegistry, WindowTitle, appendRecord as appendPerfRecord, applyDevTitle, beginWindowGesture, classifyActivity, classify as classifyPerf, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, findDuplicateKeys, formatDate, getActiveWindowRoute, getExposeHighlight, getWindowPosition, glassStyle, inputClasses, isDevEnv, isInteracting, isMac, isSeverityTone, markMenuOpen, mediaFileName, mergeBulkItems, toCsv as perfLogToCsv, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellNavIcons, setShellTodoProvider, setWindowDefaultPosition, setWindowPosition, severityOf, subscribeExposeHighlight, summariseFrames, summariseLog as summarisePerfLog, toISODate, toast, toggleExposeMode, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useFilters, useInfiniteScroll, useIsActiveWindow, useLocalStoragePrefs, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useUndo, useUndoable, useUndoableState, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };