uidex 0.2.0 → 0.2.4

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.
@@ -5,27 +5,39 @@ interface UidexDefaults {
5
5
  color?: string;
6
6
  borderStyle?: BorderStyle;
7
7
  borderWidth?: number;
8
- showLabel?: boolean;
9
- labelPosition?: LabelPosition;
10
8
  }
11
9
  interface UidexConfig {
12
10
  defaults?: UidexDefaults;
13
11
  colors?: Record<string, string>;
14
12
  }
13
+ type UidexKind = 'block' | 'component' | 'primitive';
15
14
  interface UidexLocation {
16
15
  filePath: string;
17
16
  line: number;
17
+ kind: UidexKind;
18
18
  doc?: string;
19
+ scopes?: string[];
19
20
  }
20
21
  type UidexMap = Record<string, UidexLocation[]>;
22
+ interface PrimitiveEntry {
23
+ name: string;
24
+ filePath: string;
25
+ scope: string;
26
+ composes: string[];
27
+ usedBy: string[];
28
+ kind: 'primitive';
29
+ }
21
30
  interface UidexPage {
22
31
  dir: string;
23
32
  content: string;
33
+ description?: string;
24
34
  componentIds: string[];
35
+ rootId?: string;
25
36
  }
26
37
  interface UidexFeature {
27
38
  dir: string;
28
39
  content: string;
40
+ description?: string;
29
41
  componentIds: string[];
30
42
  }
31
43
  interface KeyboardShortcut {
@@ -56,12 +68,16 @@ type FeedbackResult = {
56
68
  ok: false;
57
69
  error: string;
58
70
  };
71
+ type UidexTheme = 'dark' | 'light' | 'auto';
59
72
  interface UidexUIOptions {
60
73
  components?: UidexMap;
61
74
  pages?: UidexPage[];
62
75
  features?: UidexFeature[];
76
+ uiComponents?: PrimitiveEntry[];
63
77
  config?: UidexConfig;
64
78
  buttonPosition?: ButtonPosition;
79
+ /** Theme for the devtools widget. Default: 'auto'. */
80
+ theme?: UidexTheme;
65
81
  onSelect?: (id: string) => void;
66
82
  /** Keyboard shortcut to toggle inspect mode. Set to false to disable. */
67
83
  inspectShortcut?: KeyboardShortcut | false;
@@ -100,6 +116,7 @@ interface FeedbackReport {
100
116
  route: string | null;
101
117
  timestamp: string;
102
118
  pageTitle: string;
119
+ pageDescription?: string;
103
120
  locale: string;
104
121
  sessionId: string;
105
122
  viewport: {
@@ -119,149 +136,38 @@ interface FeedbackReport {
119
136
  metadata?: Record<string, string>;
120
137
  consoleLogs?: ConsoleLogEntry[];
121
138
  networkErrors?: NetworkErrorEntry[];
139
+ gitBranch?: string;
140
+ gitCommit?: string;
141
+ contextId?: string;
142
+ }
143
+ interface GitContext {
144
+ branch: string;
145
+ commit?: string;
122
146
  }
123
147
  interface OverlayOptions {
124
148
  color?: string;
125
149
  borderStyle?: BorderStyle;
126
150
  borderWidth?: number;
127
- label?: string;
128
- showLabel?: boolean;
129
- labelPosition?: LabelPosition;
130
151
  colors?: Record<string, string>;
131
- }
132
-
133
- type ModalView = {
134
- type: 'page';
135
- dir: string;
136
- } | {
137
- type: 'feature';
138
- dir: string;
139
- } | {
140
- type: 'component';
141
- id: string;
142
- } | {
143
- type: 'graph';
144
- };
145
- interface ModalPage {
146
- title: string;
147
- dir: string;
148
- content: string;
149
- componentIds: string[];
150
- }
151
- interface ModalFeature {
152
- title: string;
153
- dir: string;
154
- content: string;
155
- componentIds: string[];
156
- }
157
- interface ModalData {
158
- pages: ModalPage[];
159
- features: ModalFeature[];
160
- components: UidexMap;
161
- presentIds: Set<string>;
162
- }
163
- interface ModalOptions {
164
- onComponentNavigate?: (id: string) => void;
165
- elementGetter?: (id: string) => Element | null;
166
- ingest?: IngestConfig;
167
- onSubmit?: (report: FeedbackReport, result: FeedbackResult) => void;
168
- sessionId?: string;
169
- getConsoleLogs?: () => ConsoleLogEntry[];
170
- getNetworkErrors?: () => NetworkErrorEntry[];
171
- }
172
- declare class Modal {
173
- private backdrop;
174
- private sidebar;
175
- private mainContent;
176
- private renderTarget;
177
- private boundKeyDown;
178
- private data;
179
- private currentView;
180
- private modalType;
181
- private sidebarLevel;
182
- private expandedGroups;
183
- private searchQuery;
184
- private searchInput;
185
- private options;
186
- private static readonly VIEW_TYPE_TO_LEVEL;
187
- /** Strip the scanner root dir (e.g. "app") so pages display as routes: app → /, app/foo → /foo */
188
- private static formatPageDir;
189
- constructor(options?: ModalOptions);
190
- /** Set the shadow root to render modals into. */
191
- setShadowRoot(root: ShadowRoot): void;
192
- /** Update the data model. Refreshes sidebar and content if modal is open. */
193
- setData(data: ModalData): void;
194
- /** Open the modal. If already open, navigates to the given view. */
195
- open(view?: ModalView): void;
196
- /** Navigate to a view within the open modal. */
197
- navigateTo(view: ModalView): void;
198
- hide(): void;
199
- destroy(): void;
200
- isOpen(): boolean;
201
- private getDefaultView;
202
- /**
203
- * Create the shared modal frame: backdrop, dialog, header (title + close), and mount.
204
- * Returns the dialog and header elements so callers can append extra header/body content.
205
- */
206
- private createModalFrame;
207
- /** Finalize modal frame: append close button to header, header to dialog, mount to DOM. */
208
- private mountModalFrame;
209
- private createShell;
210
- private renderSidebar;
211
- private renderSidebarRoot;
212
- private renderSidebarSublevel;
213
- private currentViewMatchesLevel;
214
- private getFirstViewForLevel;
215
- private getComponentPrefix;
216
- private groupComponentsByPrefix;
217
- private createSidebarItem;
218
- private updateSidebarActive;
219
- private getSearchResults;
220
- private renderSearchResults;
221
- private renderMainContent;
222
- private renderPageView;
223
- private renderFeatureView;
224
- private renderComponentView;
225
- private renderGraphView;
226
- /** Open a dedicated feedback modal for a specific component. */
227
- openFeedback(id: string): void;
228
- private createFeedbackShell;
229
- /** Render component context (features, pages, doc) above the feedback form. */
230
- private renderFeedbackContext;
231
- private createChipContainer;
232
- private renderFeedbackFormContent;
233
- private createComponentChip;
234
- private createFeatureChipsSection;
235
- private createComponentChipsSection;
236
- private createFormGroup;
237
- private createSelect;
238
- private createChecklistItem;
239
- private renderMarkdown;
240
- /**
241
- * Capture an element by cloning it with inlined computed styles into an
242
- * SVG foreignObject, rendering to canvas via an <img> data-URI, and
243
- * returning a PNG data-URL.
244
- */
245
- private captureElementScreenshot;
246
- /** Visual CSS properties worth inlining for a screenshot clone. */
247
- private static readonly VISUAL_PROPS;
248
- /** Recursively copy visual computed styles from source onto a cloned target. */
249
- private inlineComputedStyles;
250
- private collectEnv;
251
- private getBrowserName;
252
- private describeElement;
253
- private handleKeyDown;
152
+ /** Outward padding in pixels — expands the overlay beyond the target rect. */
153
+ padding?: number;
154
+ /** Opacity of the overlay border (0–1). */
155
+ opacity?: number;
156
+ /** Opacity of the semi-transparent background fill (0–1). Default 0.08. */
157
+ fillOpacity?: number;
254
158
  }
255
159
 
256
160
  declare class UidexUI {
257
161
  private menu;
258
162
  private overlay;
163
+ private blockOverlay;
259
164
  private modal;
260
165
  private inspector;
261
166
  private options;
262
167
  private mounted;
263
168
  private shadowHost;
264
169
  private shadowRoot;
170
+ private themeWrapper;
265
171
  private observer;
266
172
  private refreshTimer;
267
173
  private copyTimer;
@@ -269,27 +175,56 @@ declare class UidexUI {
269
175
  private activeMode;
270
176
  private sessionId;
271
177
  private capture;
178
+ private theme;
179
+ private mediaQuery;
180
+ private boundMediaChange;
181
+ private classObserver;
182
+ private cursorTooltip;
183
+ private pinnedOverlays;
272
184
  constructor(options?: UidexUIOptions);
273
185
  mount(container?: HTMLElement): void;
186
+ /** Change the widget theme at runtime. */
187
+ setTheme(theme: UidexTheme): void;
188
+ private resolveAutoTheme;
189
+ private cleanupThemeListeners;
190
+ private applyTheme;
274
191
  destroy(): void;
275
192
  startInspect(): void;
276
193
  stopInspect(): void;
277
194
  isInspecting(): boolean;
278
- /** Open the modal panel, optionally to a specific view. */
279
- openPanel(view?: ModalView): void;
280
- private toggleMode;
281
- private updateMenuActiveStates;
195
+ /** Open the command palette. */
196
+ openCommand(): void;
197
+ /** Open the page dialog. */
198
+ openPage(dir?: string): void;
199
+ /** Cycle through inspect modes: inspect → copy → feedback → off. */
200
+ private cycleMode;
201
+ /** Set a specific inspect mode directly. */
202
+ private setMode;
282
203
  private getComponentsMap;
283
204
  private getPagesArray;
284
205
  private getFeaturesArray;
285
206
  private extractPageTitle;
286
- /** Hamburger button handler — open modal to default (current page) view. */
287
- private handleExpandClick;
207
+ /** Page button handler. */
208
+ private handlePageClick;
209
+ /** Match current URL pathname to a page dir. */
210
+ private matchCurrentRoute;
211
+ /** Format a page dir as a route by stripping prefix segments and route groups. */
212
+ private formatRoute;
213
+ /** Check if a route pattern matches a pathname, handling dynamic segments. */
214
+ private routeMatches;
215
+ /** Command button handler. */
216
+ private handleCommandClick;
288
217
  /** Selection handler — routes by active mode. */
289
218
  private handleSelect;
219
+ private clearPinnedOverlays;
290
220
  private handleCopySelect;
291
221
  private findElement;
222
+ private scrollAndHighlight;
223
+ private get overlayConfig();
224
+ private lastHighlightedElement;
292
225
  private handleHighlight;
226
+ /** Detect which components live inside which blocks via DOM ancestry. */
227
+ private scanBlockContainment;
293
228
  /** Push current pages/features/components/presentIds to the modal. */
294
229
  private updateModalData;
295
230
  /** Scan which registered component IDs are currently in the DOM. */
@@ -303,61 +238,93 @@ declare class UidexUI {
303
238
  }
304
239
  declare function createUidexUI(options?: UidexUIOptions): UidexUI;
305
240
 
241
+ type ActiveMode = 'inspect' | 'copy' | 'feedback' | null;
306
242
  interface MenuOptions {
307
- onInspectToggle?: () => void;
308
- onCopyToggle?: () => void;
309
- onFeedbackToggle?: () => void;
310
- onExpandClick?: () => void;
243
+ onInspectCycle?: () => void;
244
+ onModeSelect?: (mode: 'inspect' | 'copy' | 'feedback' | null) => void;
245
+ onPageClick?: () => void;
246
+ onCommandClick?: () => void;
311
247
  }
312
248
  declare class Menu {
313
- private container;
314
- private group;
315
- private expandBtn;
316
- private inspectBtn;
317
- private copyBtn;
318
- private feedbackBtn;
249
+ private host;
250
+ private root;
319
251
  private options;
320
- private isDragging;
321
- private dragStartX;
322
- private dragStartY;
323
- private dragStartLeft;
324
- private dragStartTop;
325
- private hasDragged;
326
- private boundPointerDown;
327
- private boundPointerMove;
328
- private boundPointerUp;
252
+ private activeMode;
253
+ private hasPages;
254
+ private positionClass;
255
+ private container;
329
256
  constructor(options?: MenuOptions);
257
+ setPosition(position: ButtonPosition): void;
330
258
  getContainer(): HTMLDivElement | null;
331
- /** Update a button's active state. */
332
- private setButtonActive;
333
- setInspectActive(active: boolean): void;
334
- setCopyActive(active: boolean): void;
335
- setFeedbackActive(active: boolean): void;
336
- private createButton;
259
+ setActiveMode(mode: ActiveMode): void;
260
+ setHasPages(has: boolean): void;
261
+ setContainer(el: HTMLElement | null): void;
337
262
  create(): HTMLDivElement;
338
263
  destroy(): void;
339
- private handlePointerDown;
340
- private handlePointerMove;
341
- private handlePointerUp;
342
- private snapToCorner;
264
+ private render;
265
+ }
266
+
267
+ type ModalPage = UidexPage & {
268
+ title: string;
269
+ description?: string;
270
+ };
271
+ type ModalFeature = UidexFeature & {
272
+ title: string;
273
+ };
274
+ interface ModalData {
275
+ pages: ModalPage[];
276
+ features: ModalFeature[];
277
+ components: UidexMap;
278
+ presentIds: Set<string>;
279
+ blockContainment: Map<string, string[]>;
280
+ uiComponents: Map<string, PrimitiveEntry>;
281
+ }
282
+ interface ModalOptions {
283
+ onComponentNavigate?: (id: string) => void;
284
+ onLocate?: (id: string) => void;
285
+ elementGetter?: (id: string) => Element | null;
286
+ ingest?: IngestConfig;
287
+ onSubmit?: (report: FeedbackReport, result: FeedbackResult) => void;
288
+ sessionId?: string;
289
+ getConsoleLogs?: () => ConsoleLogEntry[];
290
+ getNetworkErrors?: () => NetworkErrorEntry[];
291
+ }
292
+
293
+ declare class ModalManager {
294
+ private container;
295
+ private host;
296
+ private root;
297
+ private store;
298
+ private options;
299
+ constructor(options?: ModalOptions);
300
+ setContainer(el: HTMLElement): void;
301
+ setData(data: ModalData): void;
302
+ openCommand(): void;
303
+ openPage(dir?: string): void;
304
+ openComponent(id: string): void;
305
+ openUi(filePath: string): void;
306
+ openFeedback(id: string): void;
307
+ closeAll(): void;
308
+ isOpen(): boolean;
309
+ destroy(): void;
310
+ private ensureMounted;
311
+ private render;
343
312
  }
344
313
 
345
314
  declare class Overlay {
346
315
  private element;
347
- private labelElement;
348
316
  private target;
317
+ private baseOptions;
349
318
  private options;
350
319
  private boundUpdatePosition;
351
320
  private rafId;
352
321
  constructor(options?: OverlayOptions);
353
- show(target: HTMLElement, label?: string): void;
322
+ show(target: HTMLElement, overrides?: Partial<OverlayOptions>): void;
354
323
  hide(): void;
355
324
  destroy(): void;
356
325
  updateOptions(options: Partial<OverlayOptions>): void;
357
326
  private createElement;
358
327
  private updateStyles;
359
- private updateLabel;
360
- private applyLabelPosition;
361
328
  private updatePosition;
362
329
  private addListeners;
363
330
  private removeListeners;
@@ -365,8 +332,16 @@ declare class Overlay {
365
332
 
366
333
  interface InspectorOptions {
367
334
  shortcut?: KeyboardShortcut;
368
- onHighlight?: (element: HTMLElement | null, id: string | null) => void;
369
- onSelect?: (element: HTMLElement, id: string) => void;
335
+ onHighlight?: (element: HTMLElement | null, id: string | null, parentBlock?: {
336
+ element: HTMLElement;
337
+ id: string;
338
+ } | null, cursor?: {
339
+ x: number;
340
+ y: number;
341
+ } | null) => void;
342
+ onSelect?: (element: HTMLElement, id: string, opts?: {
343
+ persistent?: boolean;
344
+ }) => void;
370
345
  onActivate?: () => void;
371
346
  onDeactivate?: () => void;
372
347
  }
@@ -392,6 +367,14 @@ declare class Inspector {
392
367
  private handleClick;
393
368
  }
394
369
 
370
+ declare class CursorTooltip {
371
+ private element;
372
+ show(x: number, y: number, label: string, color: string): void;
373
+ hide(): void;
374
+ destroy(): void;
375
+ private createElement;
376
+ }
377
+
395
378
  /**
396
379
  * Injects the uidex styles into a shadow root as a <style> element.
397
380
  * This isolates all uidex CSS from the host page.
@@ -404,6 +387,8 @@ declare function registerPages(pages: UidexPage[]): void;
404
387
  declare function getPages(): UidexPage[] | null;
405
388
  declare function registerFeatures(features: UidexFeature[]): void;
406
389
  declare function getFeatures(): UidexFeature[] | null;
390
+ declare function registerGitContext(ctx: GitContext): void;
391
+ declare function getGitContext(): GitContext | null;
407
392
 
408
393
  declare function classNames(...classes: (string | undefined | null | false)[]): string;
409
394
  declare function getContrastColor(hexColor: string): string;
@@ -436,4 +421,4 @@ declare function submitFeedback(endpoint: string, apiKey: string, report: Feedba
436
421
  sequenceNumber: number;
437
422
  }>;
438
423
 
439
- export { type BorderStyle, type ButtonPosition, type ConsoleLogEntry, type FeedbackReport, type FeedbackResult, type FeedbackSeverity, type FeedbackType, IngestCapture, type IngestConfig, Inspector, type KeyboardShortcut, type LabelPosition, Menu, Modal, type ModalView, type NetworkErrorEntry, Overlay, type OverlayOptions, type UidexConfig, type UidexDefaults, type UidexFeature, type UidexLocation, type UidexMap, type UidexPage, UidexUI, type UidexUIOptions, classNames, createUidexUI, generateSessionId, getComponents, getContrastColor, getFeatures, getPages, hexToRgba, injectStyles, registerComponents, registerFeatures, registerPages, resolveColor, submitFeedback };
424
+ export { type BorderStyle, type ButtonPosition, type ConsoleLogEntry, CursorTooltip, type FeedbackReport, type FeedbackResult, type FeedbackSeverity, type FeedbackType, type GitContext, IngestCapture, type IngestConfig, Inspector, type KeyboardShortcut, type LabelPosition, Menu, ModalManager as Modal, type ModalData, type ModalFeature, ModalManager, type ModalOptions, type ModalPage, type NetworkErrorEntry, Overlay, type OverlayOptions, type PrimitiveEntry, type UidexConfig, type UidexDefaults, type UidexFeature, type UidexLocation, type UidexMap, type UidexPage, type UidexTheme, UidexUI, type UidexUIOptions, classNames, createUidexUI, generateSessionId, getComponents, getContrastColor, getFeatures, getGitContext, getPages, hexToRgba, injectStyles, registerComponents, registerFeatures, registerGitContext, registerPages, resolveColor, submitFeedback };