uidex 0.5.2 → 0.7.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 +3 -3
- package/dist/cli/cli.cjs +1542 -1227
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cloud/index.cjs +385 -175
- package/dist/cloud/index.cjs.map +1 -1
- package/dist/cloud/index.d.cts +192 -4
- package/dist/cloud/index.d.ts +192 -4
- package/dist/cloud/index.js +377 -177
- package/dist/cloud/index.js.map +1 -1
- package/dist/headless/index.cjs +116 -251
- package/dist/headless/index.cjs.map +1 -1
- package/dist/headless/index.d.cts +6 -11
- package/dist/headless/index.d.ts +6 -11
- package/dist/headless/index.js +116 -253
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +776 -1055
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +152 -160
- package/dist/index.d.ts +152 -160
- package/dist/index.js +792 -1066
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +801 -1019
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +102 -86
- package/dist/react/index.d.ts +102 -86
- package/dist/react/index.js +821 -1038
- package/dist/react/index.js.map +1 -1
- package/dist/scan/index.cjs +1550 -1220
- package/dist/scan/index.cjs.map +1 -1
- package/dist/scan/index.d.cts +210 -12
- package/dist/scan/index.d.ts +210 -12
- package/dist/scan/index.js +1547 -1219
- package/dist/scan/index.js.map +1 -1
- package/package.json +22 -21
- package/templates/claude/SKILL.md +71 -0
- package/templates/claude/references/audit.md +43 -0
- package/templates/claude/{rules.md → references/conventions.md} +25 -28
- package/templates/claude/audit.md +0 -43
- /package/templates/claude/{api.md → references/api.md} +0 -0
package/dist/react/index.d.cts
CHANGED
|
@@ -94,6 +94,7 @@ interface ReportRecord {
|
|
|
94
94
|
interface Registry {
|
|
95
95
|
add(entity: Entity): void;
|
|
96
96
|
get<K extends EntityKind>(kind: K, id: string): EntityByKind<K> | undefined;
|
|
97
|
+
matchPattern<K extends EntityKind>(kind: K, id: string): EntityByKind<K> | undefined;
|
|
97
98
|
list<K extends EntityKind>(kind: K): ReadonlyArray<EntityByKind<K>>;
|
|
98
99
|
query(predicate: (entity: Entity) => boolean): Entity[];
|
|
99
100
|
byScope(scope: Scope): Entity[];
|
|
@@ -101,88 +102,10 @@ interface Registry {
|
|
|
101
102
|
setReports(kind: EntityKind, id: string, reports: readonly ReportRecord[]): void;
|
|
102
103
|
getReports(kind: EntityKind, id: string): readonly ReportRecord[];
|
|
103
104
|
listReportKeys(): readonly string[];
|
|
104
|
-
|
|
105
|
+
closeReport?: (reportId: string, status?: string) => void | Promise<void>;
|
|
105
106
|
onReportsChange(cb: () => void): () => void;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
interface UserIdentity {
|
|
109
|
-
id: string;
|
|
110
|
-
name?: string;
|
|
111
|
-
avatar?: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
type ThemePreference = "light" | "dark" | "auto";
|
|
115
|
-
type ResolvedTheme = "light" | "dark";
|
|
116
|
-
interface ViewStackEntry {
|
|
117
|
-
id: string;
|
|
118
|
-
ref: EntityRef | null;
|
|
119
|
-
}
|
|
120
|
-
interface SessionSnapshot {
|
|
121
|
-
hover: EntityRef | null;
|
|
122
|
-
selection: EntityRef | null;
|
|
123
|
-
stack: ViewStackEntry[];
|
|
124
|
-
/** Sticky overlay highlight. Set by "Highlight Element" actions; cleared on Esc. */
|
|
125
|
-
pinnedHighlight: EntityRef | null;
|
|
126
|
-
inspectorActive: boolean;
|
|
127
|
-
theme: ThemePreference;
|
|
128
|
-
resolvedTheme: ResolvedTheme;
|
|
129
|
-
ingestActive: boolean;
|
|
130
|
-
/**
|
|
131
|
-
* Identity for the local user. Set once at session creation; gates realtime
|
|
132
|
-
* features (cursor labels, presence) and auto-populates report attribution.
|
|
133
|
-
*/
|
|
134
|
-
user: UserIdentity | null;
|
|
135
|
-
}
|
|
136
|
-
type SessionState = SessionSnapshot;
|
|
137
|
-
|
|
138
|
-
interface NavigationState {
|
|
139
|
-
stack: ViewStackEntry[];
|
|
140
|
-
}
|
|
141
|
-
interface NavigationActions {
|
|
142
|
-
push(entry: ViewStackEntry): void;
|
|
143
|
-
pop(): void;
|
|
144
|
-
replace(entry: ViewStackEntry): void;
|
|
145
|
-
clear(): void;
|
|
146
|
-
reset(stack: ViewStackEntry[]): void;
|
|
147
|
-
}
|
|
148
|
-
type NavigationStore = StoreApi<NavigationState> & {
|
|
149
|
-
nav: NavigationActions;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
type SurfaceMode = "idle" | "inspecting" | "palette" | "viewing";
|
|
153
|
-
interface ModeSnapshot {
|
|
154
|
-
mode: SurfaceMode;
|
|
155
|
-
inspectorActive: boolean;
|
|
156
|
-
}
|
|
157
|
-
interface ModeTransitions {
|
|
158
|
-
openPalette(): void;
|
|
159
|
-
openInspector(): void;
|
|
160
|
-
closeInspector(): void;
|
|
161
|
-
toggleInspector(): void;
|
|
162
|
-
enterViewing(initialStack: ViewStackEntry[]): void;
|
|
163
|
-
dismiss(): void;
|
|
164
|
-
popOrTransition(): void;
|
|
165
|
-
pushView(entry: ViewStackEntry): void;
|
|
166
|
-
}
|
|
167
|
-
type ModeStore = StoreApi<ModeSnapshot> & {
|
|
168
|
-
transition: ModeTransitions;
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
interface HighlightActions {
|
|
172
|
-
hover(ref: EntityRef, element?: HTMLElement | null, color?: string | null): void;
|
|
173
|
-
unhover(): void;
|
|
174
|
-
pin(ref?: EntityRef): void;
|
|
175
|
-
unpin(): void;
|
|
176
|
-
}
|
|
177
|
-
type SessionStore = StoreApi<SessionState> & {
|
|
178
|
-
readonly nav: NavigationStore;
|
|
179
|
-
readonly mode: ModeStore;
|
|
180
|
-
readonly highlight: HighlightActions;
|
|
181
|
-
select(ref: EntityRef | null): void;
|
|
182
|
-
setTheme(theme: ThemePreference, resolved?: ResolvedTheme): void;
|
|
183
|
-
setIngest(active: boolean): void;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
109
|
type ConsoleLevel = "warn" | "error";
|
|
187
110
|
interface ConsoleEntry {
|
|
188
111
|
level: ConsoleLevel;
|
|
@@ -224,6 +147,12 @@ interface NetworkCapture {
|
|
|
224
147
|
clear(): void;
|
|
225
148
|
}
|
|
226
149
|
|
|
150
|
+
interface UserIdentity {
|
|
151
|
+
id: string;
|
|
152
|
+
name?: string;
|
|
153
|
+
avatar?: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
227
156
|
type RealtimePresenceUser = {
|
|
228
157
|
userId: string;
|
|
229
158
|
name: string;
|
|
@@ -241,6 +170,8 @@ interface RealtimeChannel {
|
|
|
241
170
|
joinRoute(route: string): void;
|
|
242
171
|
onPresence(cb: (users: RealtimePresenceUser[]) => void): () => void;
|
|
243
172
|
onPin(cb: (pin: PinRecord) => void): () => void;
|
|
173
|
+
/** Optional so pre-existing channel stubs keep satisfying the interface. */
|
|
174
|
+
onPinArchived?(cb: (reportId: string) => void): () => void;
|
|
244
175
|
}
|
|
245
176
|
interface CloudAdapter<TPayload = ReportPayload, TResult = ReportResult, TIntegrations = {
|
|
246
177
|
getConfig(): Promise<IngestConfig>;
|
|
@@ -262,8 +193,17 @@ interface CloudAdapter<TPayload = ReportPayload, TResult = ReportResult, TIntegr
|
|
|
262
193
|
route?: string;
|
|
263
194
|
entities?: string;
|
|
264
195
|
}): Promise<PinRecord[]>;
|
|
265
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Pin records travel without their screenshot (kept out of `pins.list`
|
|
198
|
+
* so multi-MB frames don't stall the shared socket); the report detail
|
|
199
|
+
* view fetches it lazily through here. Optional for host-provided
|
|
200
|
+
* adapters that inline screenshots on the record instead.
|
|
201
|
+
*/
|
|
202
|
+
screenshot?(reportId: string): Promise<string | null>;
|
|
203
|
+
close(reportId: string, reason?: ArchiveReason): Promise<void>;
|
|
266
204
|
};
|
|
205
|
+
/** Closes the adapter's shared socket. Any later RPC call revives it. */
|
|
206
|
+
dispose?(): void;
|
|
267
207
|
}
|
|
268
208
|
|
|
269
209
|
interface IngestOptions {
|
|
@@ -283,6 +223,74 @@ interface Ingest {
|
|
|
283
223
|
readonly network: NetworkCapture | null;
|
|
284
224
|
}
|
|
285
225
|
|
|
226
|
+
type ThemePreference = "light" | "dark" | "auto";
|
|
227
|
+
type ResolvedTheme = "light" | "dark";
|
|
228
|
+
interface ViewStackEntry {
|
|
229
|
+
id: string;
|
|
230
|
+
ref: EntityRef | null;
|
|
231
|
+
}
|
|
232
|
+
interface SessionSnapshot {
|
|
233
|
+
stack: ViewStackEntry[];
|
|
234
|
+
/** Sticky overlay highlight. Set by "Highlight Element" actions; cleared on Esc. */
|
|
235
|
+
pinnedHighlight: EntityRef | null;
|
|
236
|
+
/** Mirrored from the mode store; the surface mode the session is currently in. */
|
|
237
|
+
mode: SurfaceMode;
|
|
238
|
+
theme: ThemePreference;
|
|
239
|
+
resolvedTheme: ResolvedTheme;
|
|
240
|
+
/**
|
|
241
|
+
* Identity for the local user. Set once at session creation; gates realtime
|
|
242
|
+
* features (cursor labels, presence) and auto-populates report attribution.
|
|
243
|
+
*/
|
|
244
|
+
user: UserIdentity | null;
|
|
245
|
+
}
|
|
246
|
+
type SessionState = SessionSnapshot;
|
|
247
|
+
|
|
248
|
+
interface NavigationState {
|
|
249
|
+
stack: ViewStackEntry[];
|
|
250
|
+
}
|
|
251
|
+
interface NavigationActions {
|
|
252
|
+
push(entry: ViewStackEntry): void;
|
|
253
|
+
pop(): void;
|
|
254
|
+
clear(): void;
|
|
255
|
+
reset(stack: ViewStackEntry[]): void;
|
|
256
|
+
}
|
|
257
|
+
type NavigationStore = StoreApi<NavigationState> & {
|
|
258
|
+
nav: NavigationActions;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
type SurfaceMode = "idle" | "inspecting" | "palette" | "viewing";
|
|
262
|
+
interface ModeSnapshot {
|
|
263
|
+
mode: SurfaceMode;
|
|
264
|
+
}
|
|
265
|
+
interface ModeTransitions {
|
|
266
|
+
openPalette(): void;
|
|
267
|
+
openInspector(): void;
|
|
268
|
+
closeInspector(): void;
|
|
269
|
+
toggleInspector(): void;
|
|
270
|
+
enterViewing(initialStack: ViewStackEntry[]): void;
|
|
271
|
+
dismiss(): void;
|
|
272
|
+
popOrTransition(): void;
|
|
273
|
+
pushView(entry: ViewStackEntry): void;
|
|
274
|
+
}
|
|
275
|
+
type ModeStore = StoreApi<ModeSnapshot> & {
|
|
276
|
+
transition: ModeTransitions;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
interface HighlightActions {
|
|
280
|
+
hover(ref: EntityRef, element?: HTMLElement | null, color?: string | null): void;
|
|
281
|
+
unhover(): void;
|
|
282
|
+
pin(ref?: EntityRef): void;
|
|
283
|
+
unpin(): void;
|
|
284
|
+
}
|
|
285
|
+
type SessionStore = StoreApi<SessionState> & {
|
|
286
|
+
readonly nav: NavigationStore;
|
|
287
|
+
readonly mode: ModeStore;
|
|
288
|
+
readonly highlight: HighlightActions;
|
|
289
|
+
setTheme(theme: ThemePreference, resolved?: ResolvedTheme): void;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
293
|
+
|
|
286
294
|
interface OverlayShowOptions {
|
|
287
295
|
label?: string;
|
|
288
296
|
color?: string;
|
|
@@ -293,8 +301,6 @@ interface OverlayShowOptions {
|
|
|
293
301
|
backdrop?: boolean;
|
|
294
302
|
}
|
|
295
303
|
|
|
296
|
-
type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
297
|
-
|
|
298
304
|
interface RouteMatch {
|
|
299
305
|
view: View;
|
|
300
306
|
priority: number;
|
|
@@ -362,6 +368,8 @@ interface DetailSurface {
|
|
|
362
368
|
entityKind: EntityKind;
|
|
363
369
|
/** Registry lookup failed — renders the "not found" placeholder. */
|
|
364
370
|
notFound?: EntityRef;
|
|
371
|
+
/** Entity exists in the DOM but not in the registry (gen file). */
|
|
372
|
+
unregistered?: boolean;
|
|
365
373
|
/** Entity display name, rendered as the heading. */
|
|
366
374
|
title?: string;
|
|
367
375
|
subtitle?: DetailSubtitle;
|
|
@@ -438,9 +446,16 @@ type DetailSection = {
|
|
|
438
446
|
id: "routes";
|
|
439
447
|
paths: readonly string[];
|
|
440
448
|
filterable?: boolean;
|
|
441
|
-
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* `url` renders immediately; `load` fetches lazily (cloud pins travel
|
|
452
|
+
* without their screenshot) and the section stays hidden until — and
|
|
453
|
+
* unless — the promise resolves with a data URL.
|
|
454
|
+
*/
|
|
455
|
+
| {
|
|
442
456
|
id: "screenshot";
|
|
443
|
-
url
|
|
457
|
+
url?: string;
|
|
458
|
+
load?: () => Promise<string | null>;
|
|
444
459
|
} | {
|
|
445
460
|
id: "metadata";
|
|
446
461
|
entries: readonly MetadataEntry[];
|
|
@@ -639,8 +654,9 @@ interface View {
|
|
|
639
654
|
* when the declared target has been removed from the host.
|
|
640
655
|
*/
|
|
641
656
|
focusTarget?: (root: HTMLElement, ctx: ViewContext) => HTMLElement | null;
|
|
642
|
-
|
|
643
|
-
|
|
657
|
+
/** Required unless `render` is provided. */
|
|
658
|
+
surface?: (ctx: ViewContext) => ViewSurface;
|
|
659
|
+
/** Direct render for integration adapters (React, etc.). Takes precedence over `surface` when both are present. */
|
|
644
660
|
render?: (ctx: ViewContext, root: HTMLElement) => Cleanup | void;
|
|
645
661
|
parent?: (ref: EntityRef | null) => ViewStackEntry | null;
|
|
646
662
|
}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ interface ReportRecord {
|
|
|
94
94
|
interface Registry {
|
|
95
95
|
add(entity: Entity): void;
|
|
96
96
|
get<K extends EntityKind>(kind: K, id: string): EntityByKind<K> | undefined;
|
|
97
|
+
matchPattern<K extends EntityKind>(kind: K, id: string): EntityByKind<K> | undefined;
|
|
97
98
|
list<K extends EntityKind>(kind: K): ReadonlyArray<EntityByKind<K>>;
|
|
98
99
|
query(predicate: (entity: Entity) => boolean): Entity[];
|
|
99
100
|
byScope(scope: Scope): Entity[];
|
|
@@ -101,88 +102,10 @@ interface Registry {
|
|
|
101
102
|
setReports(kind: EntityKind, id: string, reports: readonly ReportRecord[]): void;
|
|
102
103
|
getReports(kind: EntityKind, id: string): readonly ReportRecord[];
|
|
103
104
|
listReportKeys(): readonly string[];
|
|
104
|
-
|
|
105
|
+
closeReport?: (reportId: string, status?: string) => void | Promise<void>;
|
|
105
106
|
onReportsChange(cb: () => void): () => void;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
interface UserIdentity {
|
|
109
|
-
id: string;
|
|
110
|
-
name?: string;
|
|
111
|
-
avatar?: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
type ThemePreference = "light" | "dark" | "auto";
|
|
115
|
-
type ResolvedTheme = "light" | "dark";
|
|
116
|
-
interface ViewStackEntry {
|
|
117
|
-
id: string;
|
|
118
|
-
ref: EntityRef | null;
|
|
119
|
-
}
|
|
120
|
-
interface SessionSnapshot {
|
|
121
|
-
hover: EntityRef | null;
|
|
122
|
-
selection: EntityRef | null;
|
|
123
|
-
stack: ViewStackEntry[];
|
|
124
|
-
/** Sticky overlay highlight. Set by "Highlight Element" actions; cleared on Esc. */
|
|
125
|
-
pinnedHighlight: EntityRef | null;
|
|
126
|
-
inspectorActive: boolean;
|
|
127
|
-
theme: ThemePreference;
|
|
128
|
-
resolvedTheme: ResolvedTheme;
|
|
129
|
-
ingestActive: boolean;
|
|
130
|
-
/**
|
|
131
|
-
* Identity for the local user. Set once at session creation; gates realtime
|
|
132
|
-
* features (cursor labels, presence) and auto-populates report attribution.
|
|
133
|
-
*/
|
|
134
|
-
user: UserIdentity | null;
|
|
135
|
-
}
|
|
136
|
-
type SessionState = SessionSnapshot;
|
|
137
|
-
|
|
138
|
-
interface NavigationState {
|
|
139
|
-
stack: ViewStackEntry[];
|
|
140
|
-
}
|
|
141
|
-
interface NavigationActions {
|
|
142
|
-
push(entry: ViewStackEntry): void;
|
|
143
|
-
pop(): void;
|
|
144
|
-
replace(entry: ViewStackEntry): void;
|
|
145
|
-
clear(): void;
|
|
146
|
-
reset(stack: ViewStackEntry[]): void;
|
|
147
|
-
}
|
|
148
|
-
type NavigationStore = StoreApi<NavigationState> & {
|
|
149
|
-
nav: NavigationActions;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
type SurfaceMode = "idle" | "inspecting" | "palette" | "viewing";
|
|
153
|
-
interface ModeSnapshot {
|
|
154
|
-
mode: SurfaceMode;
|
|
155
|
-
inspectorActive: boolean;
|
|
156
|
-
}
|
|
157
|
-
interface ModeTransitions {
|
|
158
|
-
openPalette(): void;
|
|
159
|
-
openInspector(): void;
|
|
160
|
-
closeInspector(): void;
|
|
161
|
-
toggleInspector(): void;
|
|
162
|
-
enterViewing(initialStack: ViewStackEntry[]): void;
|
|
163
|
-
dismiss(): void;
|
|
164
|
-
popOrTransition(): void;
|
|
165
|
-
pushView(entry: ViewStackEntry): void;
|
|
166
|
-
}
|
|
167
|
-
type ModeStore = StoreApi<ModeSnapshot> & {
|
|
168
|
-
transition: ModeTransitions;
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
interface HighlightActions {
|
|
172
|
-
hover(ref: EntityRef, element?: HTMLElement | null, color?: string | null): void;
|
|
173
|
-
unhover(): void;
|
|
174
|
-
pin(ref?: EntityRef): void;
|
|
175
|
-
unpin(): void;
|
|
176
|
-
}
|
|
177
|
-
type SessionStore = StoreApi<SessionState> & {
|
|
178
|
-
readonly nav: NavigationStore;
|
|
179
|
-
readonly mode: ModeStore;
|
|
180
|
-
readonly highlight: HighlightActions;
|
|
181
|
-
select(ref: EntityRef | null): void;
|
|
182
|
-
setTheme(theme: ThemePreference, resolved?: ResolvedTheme): void;
|
|
183
|
-
setIngest(active: boolean): void;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
109
|
type ConsoleLevel = "warn" | "error";
|
|
187
110
|
interface ConsoleEntry {
|
|
188
111
|
level: ConsoleLevel;
|
|
@@ -224,6 +147,12 @@ interface NetworkCapture {
|
|
|
224
147
|
clear(): void;
|
|
225
148
|
}
|
|
226
149
|
|
|
150
|
+
interface UserIdentity {
|
|
151
|
+
id: string;
|
|
152
|
+
name?: string;
|
|
153
|
+
avatar?: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
227
156
|
type RealtimePresenceUser = {
|
|
228
157
|
userId: string;
|
|
229
158
|
name: string;
|
|
@@ -241,6 +170,8 @@ interface RealtimeChannel {
|
|
|
241
170
|
joinRoute(route: string): void;
|
|
242
171
|
onPresence(cb: (users: RealtimePresenceUser[]) => void): () => void;
|
|
243
172
|
onPin(cb: (pin: PinRecord) => void): () => void;
|
|
173
|
+
/** Optional so pre-existing channel stubs keep satisfying the interface. */
|
|
174
|
+
onPinArchived?(cb: (reportId: string) => void): () => void;
|
|
244
175
|
}
|
|
245
176
|
interface CloudAdapter<TPayload = ReportPayload, TResult = ReportResult, TIntegrations = {
|
|
246
177
|
getConfig(): Promise<IngestConfig>;
|
|
@@ -262,8 +193,17 @@ interface CloudAdapter<TPayload = ReportPayload, TResult = ReportResult, TIntegr
|
|
|
262
193
|
route?: string;
|
|
263
194
|
entities?: string;
|
|
264
195
|
}): Promise<PinRecord[]>;
|
|
265
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Pin records travel without their screenshot (kept out of `pins.list`
|
|
198
|
+
* so multi-MB frames don't stall the shared socket); the report detail
|
|
199
|
+
* view fetches it lazily through here. Optional for host-provided
|
|
200
|
+
* adapters that inline screenshots on the record instead.
|
|
201
|
+
*/
|
|
202
|
+
screenshot?(reportId: string): Promise<string | null>;
|
|
203
|
+
close(reportId: string, reason?: ArchiveReason): Promise<void>;
|
|
266
204
|
};
|
|
205
|
+
/** Closes the adapter's shared socket. Any later RPC call revives it. */
|
|
206
|
+
dispose?(): void;
|
|
267
207
|
}
|
|
268
208
|
|
|
269
209
|
interface IngestOptions {
|
|
@@ -283,6 +223,74 @@ interface Ingest {
|
|
|
283
223
|
readonly network: NetworkCapture | null;
|
|
284
224
|
}
|
|
285
225
|
|
|
226
|
+
type ThemePreference = "light" | "dark" | "auto";
|
|
227
|
+
type ResolvedTheme = "light" | "dark";
|
|
228
|
+
interface ViewStackEntry {
|
|
229
|
+
id: string;
|
|
230
|
+
ref: EntityRef | null;
|
|
231
|
+
}
|
|
232
|
+
interface SessionSnapshot {
|
|
233
|
+
stack: ViewStackEntry[];
|
|
234
|
+
/** Sticky overlay highlight. Set by "Highlight Element" actions; cleared on Esc. */
|
|
235
|
+
pinnedHighlight: EntityRef | null;
|
|
236
|
+
/** Mirrored from the mode store; the surface mode the session is currently in. */
|
|
237
|
+
mode: SurfaceMode;
|
|
238
|
+
theme: ThemePreference;
|
|
239
|
+
resolvedTheme: ResolvedTheme;
|
|
240
|
+
/**
|
|
241
|
+
* Identity for the local user. Set once at session creation; gates realtime
|
|
242
|
+
* features (cursor labels, presence) and auto-populates report attribution.
|
|
243
|
+
*/
|
|
244
|
+
user: UserIdentity | null;
|
|
245
|
+
}
|
|
246
|
+
type SessionState = SessionSnapshot;
|
|
247
|
+
|
|
248
|
+
interface NavigationState {
|
|
249
|
+
stack: ViewStackEntry[];
|
|
250
|
+
}
|
|
251
|
+
interface NavigationActions {
|
|
252
|
+
push(entry: ViewStackEntry): void;
|
|
253
|
+
pop(): void;
|
|
254
|
+
clear(): void;
|
|
255
|
+
reset(stack: ViewStackEntry[]): void;
|
|
256
|
+
}
|
|
257
|
+
type NavigationStore = StoreApi<NavigationState> & {
|
|
258
|
+
nav: NavigationActions;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
type SurfaceMode = "idle" | "inspecting" | "palette" | "viewing";
|
|
262
|
+
interface ModeSnapshot {
|
|
263
|
+
mode: SurfaceMode;
|
|
264
|
+
}
|
|
265
|
+
interface ModeTransitions {
|
|
266
|
+
openPalette(): void;
|
|
267
|
+
openInspector(): void;
|
|
268
|
+
closeInspector(): void;
|
|
269
|
+
toggleInspector(): void;
|
|
270
|
+
enterViewing(initialStack: ViewStackEntry[]): void;
|
|
271
|
+
dismiss(): void;
|
|
272
|
+
popOrTransition(): void;
|
|
273
|
+
pushView(entry: ViewStackEntry): void;
|
|
274
|
+
}
|
|
275
|
+
type ModeStore = StoreApi<ModeSnapshot> & {
|
|
276
|
+
transition: ModeTransitions;
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
interface HighlightActions {
|
|
280
|
+
hover(ref: EntityRef, element?: HTMLElement | null, color?: string | null): void;
|
|
281
|
+
unhover(): void;
|
|
282
|
+
pin(ref?: EntityRef): void;
|
|
283
|
+
unpin(): void;
|
|
284
|
+
}
|
|
285
|
+
type SessionStore = StoreApi<SessionState> & {
|
|
286
|
+
readonly nav: NavigationStore;
|
|
287
|
+
readonly mode: ModeStore;
|
|
288
|
+
readonly highlight: HighlightActions;
|
|
289
|
+
setTheme(theme: ThemePreference, resolved?: ResolvedTheme): void;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
293
|
+
|
|
286
294
|
interface OverlayShowOptions {
|
|
287
295
|
label?: string;
|
|
288
296
|
color?: string;
|
|
@@ -293,8 +301,6 @@ interface OverlayShowOptions {
|
|
|
293
301
|
backdrop?: boolean;
|
|
294
302
|
}
|
|
295
303
|
|
|
296
|
-
type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
297
|
-
|
|
298
304
|
interface RouteMatch {
|
|
299
305
|
view: View;
|
|
300
306
|
priority: number;
|
|
@@ -362,6 +368,8 @@ interface DetailSurface {
|
|
|
362
368
|
entityKind: EntityKind;
|
|
363
369
|
/** Registry lookup failed — renders the "not found" placeholder. */
|
|
364
370
|
notFound?: EntityRef;
|
|
371
|
+
/** Entity exists in the DOM but not in the registry (gen file). */
|
|
372
|
+
unregistered?: boolean;
|
|
365
373
|
/** Entity display name, rendered as the heading. */
|
|
366
374
|
title?: string;
|
|
367
375
|
subtitle?: DetailSubtitle;
|
|
@@ -438,9 +446,16 @@ type DetailSection = {
|
|
|
438
446
|
id: "routes";
|
|
439
447
|
paths: readonly string[];
|
|
440
448
|
filterable?: boolean;
|
|
441
|
-
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* `url` renders immediately; `load` fetches lazily (cloud pins travel
|
|
452
|
+
* without their screenshot) and the section stays hidden until — and
|
|
453
|
+
* unless — the promise resolves with a data URL.
|
|
454
|
+
*/
|
|
455
|
+
| {
|
|
442
456
|
id: "screenshot";
|
|
443
|
-
url
|
|
457
|
+
url?: string;
|
|
458
|
+
load?: () => Promise<string | null>;
|
|
444
459
|
} | {
|
|
445
460
|
id: "metadata";
|
|
446
461
|
entries: readonly MetadataEntry[];
|
|
@@ -639,8 +654,9 @@ interface View {
|
|
|
639
654
|
* when the declared target has been removed from the host.
|
|
640
655
|
*/
|
|
641
656
|
focusTarget?: (root: HTMLElement, ctx: ViewContext) => HTMLElement | null;
|
|
642
|
-
|
|
643
|
-
|
|
657
|
+
/** Required unless `render` is provided. */
|
|
658
|
+
surface?: (ctx: ViewContext) => ViewSurface;
|
|
659
|
+
/** Direct render for integration adapters (React, etc.). Takes precedence over `surface` when both are present. */
|
|
644
660
|
render?: (ctx: ViewContext, root: HTMLElement) => Cleanup | void;
|
|
645
661
|
parent?: (ref: EntityRef | null) => ViewStackEntry | null;
|
|
646
662
|
}
|